summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-08-26 14:36:54 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-08-26 14:36:54 +0000
commitdaf5ae5bd439f1f32363d410129d5b9e73fbb539 (patch)
tree6d670487dc3dccf1a0c3e6b8337e5b4ab9da4ee9 /app
parent6e8c2290dab8ae1612dff80e312911bc1147edaa (diff)
downloadgitlab-ce-daf5ae5bd439f1f32363d410129d5b9e73fbb539.tar.gz
Add latest changes from gitlab-org/security/gitlab@15-3-stable-ee
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/ide/components/preview/clientside.vue22
-rw-r--r--app/assets/javascripts/ide/components/preview/navigator.vue6
-rw-r--r--app/controllers/jwt_controller.rb45
-rw-r--r--app/controllers/repositories/git_http_client_controller.rb23
-rw-r--r--app/helpers/commits_helper.rb2
-rw-r--r--app/models/snippet.rb15
-rw-r--r--app/presenters/commit_presenter.rb10
-rw-r--r--app/validators/bytesize_validator.rb30
-rw-r--r--app/views/projects/commits/_commit.html.haml2
9 files changed, 100 insertions, 55 deletions
diff --git a/app/assets/javascripts/ide/components/preview/clientside.vue b/app/assets/javascripts/ide/components/preview/clientside.vue
index b1f6f2c87b9..70b881b6ff6 100644
--- a/app/assets/javascripts/ide/components/preview/clientside.vue
+++ b/app/assets/javascripts/ide/components/preview/clientside.vue
@@ -2,7 +2,7 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { listen } from 'codesandbox-api';
import { isEmpty, debounce } from 'lodash';
-import { Manager } from 'smooshpack';
+import { SandpackClient } from '@codesandbox/sandpack-client';
import { mapActions, mapGetters, mapState } from 'vuex';
import {
packageJsonPath,
@@ -21,7 +21,7 @@ export default {
},
data() {
return {
- manager: {},
+ client: {},
loading: false,
sandpackReady: false,
};
@@ -94,11 +94,11 @@ export default {
this.sandpackReady = false;
eventHub.$off('ide.files.change', this.onFilesChangeCallback);
- if (!isEmpty(this.manager)) {
- this.manager.listener();
+ if (!isEmpty(this.client)) {
+ this.client.cleanup();
}
- this.manager = {};
+ this.client = {};
if (this.listener) {
this.listener();
@@ -120,7 +120,7 @@ export default {
return this.loadFileContent(this.mainEntry)
.then(() => this.$nextTick())
.then(() => {
- this.initManager();
+ this.initClient();
this.listener = listen((e) => {
switch (e.type) {
@@ -136,15 +136,15 @@ export default {
update() {
if (!this.sandpackReady) return;
- if (isEmpty(this.manager)) {
+ if (isEmpty(this.client)) {
this.initPreview();
return;
}
- this.manager.updatePreview(this.sandboxOpts);
+ this.client.updatePreview(this.sandboxOpts);
},
- initManager() {
+ initClient() {
const { codesandboxBundlerUrl: bundlerURL } = this;
const settings = {
@@ -155,7 +155,7 @@ export default {
...(bundlerURL ? { bundlerURL } : {}),
};
- this.manager = new Manager('#ide-preview', this.sandboxOpts, settings);
+ this.client = new SandpackClient('#ide-preview', this.sandboxOpts, settings);
},
},
};
@@ -164,7 +164,7 @@ export default {
<template>
<div class="preview h-100 w-100 d-flex flex-column gl-bg-white">
<template v-if="showPreview">
- <navigator :manager="manager" />
+ <navigator :client="client" />
<div id="ide-preview"></div>
</template>
<div
diff --git a/app/assets/javascripts/ide/components/preview/navigator.vue b/app/assets/javascripts/ide/components/preview/navigator.vue
index 96f9a85c23f..852de16d508 100644
--- a/app/assets/javascripts/ide/components/preview/navigator.vue
+++ b/app/assets/javascripts/ide/components/preview/navigator.vue
@@ -8,7 +8,7 @@ export default {
GlLoadingIcon,
},
props: {
- manager: {
+ client: {
type: Object,
required: true,
},
@@ -51,7 +51,7 @@ export default {
onUrlChange(e) {
const lastPath = this.path;
- this.path = e.url.replace(this.manager.bundlerURL, '') || '/';
+ this.path = e.url.replace(this.client.bundlerURL, '') || '/';
if (lastPath !== this.path) {
this.currentBrowsingIndex =
@@ -79,7 +79,7 @@ export default {
},
visitPath(path) {
// eslint-disable-next-line vue/no-mutating-props
- this.manager.iframe.src = `${this.manager.bundlerURL}${path}`;
+ this.client.iframe.src = `${this.client.bundlerURL}${path}`;
},
},
};
diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb
index 8eebf9fbf6b..84f5632854b 100644
--- a/app/controllers/jwt_controller.rb
+++ b/app/controllers/jwt_controller.rb
@@ -36,31 +36,40 @@ class JwtController < ApplicationController
@authentication_result = Gitlab::Auth.find_for_git_client(login, password, project: nil, ip: request.ip)
if @authentication_result.failed?
- render_unauthorized
+ log_authentication_failed(login, @authentication_result)
+ render_access_denied
end
end
rescue Gitlab::Auth::MissingPersonalAccessTokenError
- render_missing_personal_access_token
+ render_access_denied
end
- def render_missing_personal_access_token
- render json: {
- errors: [
- { code: 'UNAUTHORIZED',
- message: _('HTTP Basic: Access denied\n' \
- 'You must use a personal access token with \'api\' scope for Git over HTTP.\n' \
- 'You can generate one at %{profile_personal_access_tokens_url}') % { profile_personal_access_tokens_url: profile_personal_access_tokens_url } }
- ]
- }, status: :unauthorized
+ def log_authentication_failed(login, result)
+ log_info = {
+ message: 'JWT authentication failed',
+ http_user: login,
+ remote_ip: request.ip,
+ auth_service: params[:service],
+ 'auth_result.type': result.type,
+ 'auth_result.actor_type': result.actor&.class
+ }.merge(::Gitlab::ApplicationContext.current)
+
+ Gitlab::AuthLogger.warn(log_info)
end
- def render_unauthorized
- render json: {
- errors: [
- { code: 'UNAUTHORIZED',
- message: 'HTTP Basic: Access denied' }
- ]
- }, status: :unauthorized
+ def render_access_denied
+ help_page = help_page_url(
+ 'user/profile/account/two_factor_authentication',
+ anchor: 'troubleshooting'
+ )
+
+ render(
+ json: { errors: [{
+ code: 'UNAUTHORIZED',
+ message: format(_("HTTP Basic: Access denied. The provided password or token is incorrect or your account has 2FA enabled and you must use a personal access token instead of a password. See %{help_page_url}"), help_page_url: help_page)
+ }] },
+ status: :unauthorized
+ )
end
def auth_params
diff --git a/app/controllers/repositories/git_http_client_controller.rb b/app/controllers/repositories/git_http_client_controller.rb
index 8d7ba3e38c0..fbf5d82a45b 100644
--- a/app/controllers/repositories/git_http_client_controller.rb
+++ b/app/controllers/repositories/git_http_client_controller.rb
@@ -67,9 +67,21 @@ module Repositories
end
send_challenges
- render plain: "HTTP Basic: Access denied\n", status: :unauthorized
+ render_access_denied
rescue Gitlab::Auth::MissingPersonalAccessTokenError
- render_missing_personal_access_token
+ render_access_denied
+ end
+
+ def render_access_denied
+ help_page = help_page_url(
+ 'topics/git/troubleshooting_git',
+ anchor: 'error-on-git-fetch-http-basic-access-denied'
+ )
+
+ render(
+ plain: format(_("HTTP Basic: Access denied. The provided password or token is incorrect or your account has 2FA enabled and you must use a personal access token instead of a password. See %{help_page_url}"), help_page_url: help_page),
+ status: :unauthorized
+ )
end
def basic_auth_provided?
@@ -103,13 +115,6 @@ module Repositories
@container, @project, @repo_type, @redirected_path = Gitlab::RepoPath.parse(repository_path)
end
- def render_missing_personal_access_token
- render plain: "HTTP Basic: Access denied\n" \
- "You must use a personal access token with 'read_repository' or 'write_repository' scope for Git over HTTP.\n" \
- "You can generate one at #{profile_personal_access_tokens_url}",
- status: :unauthorized
- end
-
def repository
strong_memoize(:repository) do
repo_type.repository_for(container)
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 1920650bc93..4493bc2bc6d 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -171,7 +171,7 @@ module CommitsHelper
ref,
{
merge_request: merge_request&.cache_key,
- pipeline_status: commit.status_for(ref)&.cache_key,
+ pipeline_status: commit.detailed_status_for(ref)&.cache_key,
xhr: request.xhr?,
controller: controller.controller_path,
path: @path # referred to in #link_to_browse_code
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index fd882633a44..943d09d983b 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -22,6 +22,8 @@ class Snippet < ApplicationRecord
MAX_FILE_COUNT = 10
+ DESCRIPTION_LENGTH_MAX = 1.megabyte
+
cache_markdown_field :title, pipeline: :single_line
cache_markdown_field :description
cache_markdown_field :content
@@ -57,19 +59,10 @@ class Snippet < ApplicationRecord
validates :title, presence: true, length: { maximum: 255 }
validates :file_name,
length: { maximum: 255 }
+ validates :description, bytesize: { maximum: -> { DESCRIPTION_LENGTH_MAX } }, if: :description_changed?
validates :content, presence: true
- validates :content,
- length: {
- maximum: ->(_) { Gitlab::CurrentSettings.snippet_size_limit },
- message: -> (_, data) do
- current_value = ActiveSupport::NumberHelper.number_to_human_size(data[:value].size)
- max_size = ActiveSupport::NumberHelper.number_to_human_size(Gitlab::CurrentSettings.snippet_size_limit)
-
- _("is too long (%{current_value}). The maximum size is %{max_size}.") % { current_value: current_value, max_size: max_size }
- end
- },
- if: :content_changed?
+ validates :content, bytesize: { maximum: -> { Gitlab::CurrentSettings.snippet_size_limit } }, if: :content_changed?
after_create :create_statistics
diff --git a/app/presenters/commit_presenter.rb b/app/presenters/commit_presenter.rb
index 7df45ca03bb..2cb88179845 100644
--- a/app/presenters/commit_presenter.rb
+++ b/app/presenters/commit_presenter.rb
@@ -5,12 +5,20 @@ class CommitPresenter < Gitlab::View::Presenter::Delegated
presents ::Commit, as: :commit
- def status_for(ref)
+ def detailed_status_for(ref)
+ return unless can?(current_user, :read_pipeline, commit.latest_pipeline(ref))
return unless can?(current_user, :read_commit_status, commit.project)
commit.latest_pipeline(ref)&.detailed_status(current_user)
end
+ def status_for(ref = nil)
+ return unless can?(current_user, :read_pipeline, commit.latest_pipeline(ref))
+ return unless can?(current_user, :read_commit_status, commit.project)
+
+ commit.status(ref)
+ end
+
def any_pipelines?
return false unless can?(current_user, :read_pipeline, commit.project)
diff --git a/app/validators/bytesize_validator.rb b/app/validators/bytesize_validator.rb
new file mode 100644
index 00000000000..adbdd81d5c4
--- /dev/null
+++ b/app/validators/bytesize_validator.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+# BytesizeValidator
+#
+# Custom validator for verifying that bytesize of a field doesn't exceed the specified limit.
+# It is different from Rails length validator because it takes .bytesize into account instead of .size/.length
+#
+# Example:
+#
+# class Snippet < ActiveRecord::Base
+# validates :content, bytesize: { maximum: -> { Gitlab::CurrentSettings.snippet_size_limit } }
+# end
+#
+# Configuration options:
+# * <tt>maximum</tt> - Proc that evaluates the bytesize limit that cannot be exceeded
+class BytesizeValidator < ActiveModel::EachValidator
+ def validate_each(record, attr, value)
+ size = value.to_s.bytesize
+ max_size = options[:maximum].call
+
+ return if size <= max_size
+
+ error_message = format(_('is too long (%{size}). The maximum size is %{max_size}.'), {
+ size: ActiveSupport::NumberHelper.number_to_human_size(size),
+ max_size: ActiveSupport::NumberHelper.number_to_human_size(max_size)
+ })
+
+ record.errors.add(attr, error_message)
+ end
+end
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 71485e203db..6f44c130603 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -14,7 +14,7 @@
- project = local_assigns.fetch(:project) { merge_request&.project }
- ref = local_assigns.fetch(:ref) { merge_request&.source_branch }
- commit = commit.present(current_user: current_user)
-- commit_status = commit.status_for(ref)
+- commit_status = commit.detailed_status_for(ref)
- collapsible = local_assigns.fetch(:collapsible, true)
- link_data_attrs = local_assigns.fetch(:link_data_attrs, {})
- link = commit_path(project, commit, merge_request: merge_request)