diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-01-26 15:10:19 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-01-26 15:10:19 +0300 |
commit | a1c0b634f78f51389fd3ec390a1803afa3de49a2 (patch) | |
tree | f57fc3000a6e7f2bd271a63018427c8fb9c06c08 /app | |
parent | db950c5706cdf47f7ccc2e02a4ffd691432ac5dc (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/jira_connect/subscriptions/api.js | 5 | ||||
-rw-r--r-- | app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue | 16 | ||||
-rw-r--r-- | app/assets/javascripts/repository/index.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/repository/utils/ref_switcher_utils.js | 7 | ||||
-rw-r--r-- | app/graphql/resolvers/ci/variables_resolver.rb | 27 | ||||
-rw-r--r-- | app/graphql/types/ci/variable_sort_enum.rb | 13 | ||||
-rw-r--r-- | app/graphql/types/group_type.rb | 2 | ||||
-rw-r--r-- | app/graphql/types/project_type.rb | 2 | ||||
-rw-r--r-- | app/graphql/types/query_type.rb | 9 | ||||
-rw-r--r-- | app/models/concerns/ci/has_variable.rb | 11 | ||||
-rw-r--r-- | app/models/container_repository.rb | 2 | ||||
-rw-r--r-- | app/models/lfs_object.rb | 5 | ||||
-rw-r--r-- | app/services/projects/container_repository/destroy_service.rb | 21 | ||||
-rw-r--r-- | app/services/projects/destroy_service.rb | 17 |
14 files changed, 108 insertions, 31 deletions
diff --git a/app/assets/javascripts/jira_connect/subscriptions/api.js b/app/assets/javascripts/jira_connect/subscriptions/api.js index c79d7002111..8c5dc88f183 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/api.js +++ b/app/assets/javascripts/jira_connect/subscriptions/api.js @@ -35,13 +35,16 @@ export const removeSubscription = async (removePath) => { }); }; -export const fetchGroups = async (groupsPath, { page, perPage, search }) => { +export const fetchGroups = async (groupsPath, { page, perPage, search }, accessToken = null) => { return axiosInstance.get(groupsPath, { params: { page, per_page: perPage, search, }, + headers: { + ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}), + }, }); }; diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue index a9ec7bd971e..a4b728335c5 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue +++ b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue @@ -1,4 +1,5 @@ <script> +import { mapState } from 'vuex'; import { GlLoadingIcon, GlPagination, GlAlert, GlSearchBoxByType } from '@gitlab/ui'; import { fetchGroups } from '~/jira_connect/subscriptions/api'; import { @@ -38,6 +39,7 @@ export default { showPagination() { return this.totalItems > this.$options.DEFAULT_GROUPS_PER_PAGE && this.groups.length > 0; }, + ...mapState(['accessToken']), }, mounted() { return this.loadGroups().finally(() => { @@ -47,11 +49,15 @@ export default { methods: { loadGroups() { this.isLoadingMore = true; - return fetchGroups(this.groupsPath, { - page: this.page, - perPage: this.$options.DEFAULT_GROUPS_PER_PAGE, - search: this.searchValue, - }) + return fetchGroups( + this.groupsPath, + { + page: this.page, + perPage: this.$options.DEFAULT_GROUPS_PER_PAGE, + search: this.searchValue, + }, + this.accessToken, + ) .then((response) => { const { page, total } = parseIntPagination(normalizeHeaders(response.headers)); this.page = page; diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js index 23d857de7a0..494e270a66c 100644 --- a/app/assets/javascripts/repository/index.js +++ b/app/assets/javascripts/repository/index.js @@ -133,7 +133,7 @@ export default function setupVueRepositoryList() { }, on: { input(selectedRef) { - visitUrl(generateRefDestinationPath(projectRootPath, selectedRef)); + visitUrl(generateRefDestinationPath(projectRootPath, ref, selectedRef)); }, }, }); diff --git a/app/assets/javascripts/repository/utils/ref_switcher_utils.js b/app/assets/javascripts/repository/utils/ref_switcher_utils.js index f296b5e9b4a..c62f7f709c4 100644 --- a/app/assets/javascripts/repository/utils/ref_switcher_utils.js +++ b/app/assets/javascripts/repository/utils/ref_switcher_utils.js @@ -5,9 +5,9 @@ import { joinPaths } from '~/lib/utils/url_utility'; * Example: /root/Flight/-/blob/fix/main/test/spec/utils_spec.js * Group 1: /-/blob * Group 2: blob - * Group 3: main/test/spec/utils_spec.js + * Group 3: /test/spec/utils_spec.js */ -const NAMESPACE_TARGET_REGEX = /(\/-\/(blob|tree))\/.*?\/(.*)/; +const getNamespaceTargetRegex = (ref) => new RegExp(`(/-/(blob|tree))/${ref}/(.*)`); /** * Generates a ref destination path based on the selected ref and current path. @@ -15,11 +15,12 @@ const NAMESPACE_TARGET_REGEX = /(\/-\/(blob|tree))\/.*?\/(.*)/; * @param {string} projectRootPath - The root path for a project. * @param {string} selectedRef - The selected ref from the ref dropdown. */ -export function generateRefDestinationPath(projectRootPath, selectedRef) { +export function generateRefDestinationPath(projectRootPath, ref, selectedRef) { const currentPath = window.location.pathname; const encodedHash = '%23'; let namespace = '/-/tree'; let target; + const NAMESPACE_TARGET_REGEX = getNamespaceTargetRegex(ref); const match = NAMESPACE_TARGET_REGEX.exec(currentPath); if (match) { [, namespace, , target] = match; diff --git a/app/graphql/resolvers/ci/variables_resolver.rb b/app/graphql/resolvers/ci/variables_resolver.rb new file mode 100644 index 00000000000..71d420120b3 --- /dev/null +++ b/app/graphql/resolvers/ci/variables_resolver.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Resolvers + module Ci + class VariablesResolver < BaseResolver + type Types::Ci::InstanceVariableType.connection_type, null: true + + argument :sort, ::Types::Ci::VariableSortEnum, + required: false, + description: 'Sort order of results.' + + def resolve(**args) + if parent.is_a?(Group) || parent.is_a?(Project) + parent.variables.order_by(args[:sort]) + elsif current_user&.can_admin_all_resources? + ::Ci::InstanceVariable.order_by(args[:sort]) + end + end + + private + + def parent + object.respond_to?(:sync) ? object.sync : object + end + end + end +end diff --git a/app/graphql/types/ci/variable_sort_enum.rb b/app/graphql/types/ci/variable_sort_enum.rb new file mode 100644 index 00000000000..3a60899ab5d --- /dev/null +++ b/app/graphql/types/ci/variable_sort_enum.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Types + module Ci + class VariableSortEnum < BaseEnum + graphql_name 'CiVariableSort' + description 'Values for sorting variables' + + value 'KEY_ASC', 'Sorted by key in ascending order.', value: :key_asc + value 'KEY_DESC', 'Sorted by key in descending order.', value: :key_desc + end + end +end diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb index 4e5ddbac8a2..dcf56f961ce 100644 --- a/app/graphql/types/group_type.rb +++ b/app/graphql/types/group_type.rb @@ -200,7 +200,7 @@ module Types null: true, description: "List of the group's CI/CD variables.", authorize: :admin_group, - method: :variables + resolver: Resolvers::Ci::VariablesResolver field :runners, Types::Ci::RunnerType.connection_type, null: true, diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb index 2f8a2d26120..d0c2c583f9f 100644 --- a/app/graphql/types/project_type.rb +++ b/app/graphql/types/project_type.rb @@ -345,7 +345,7 @@ module Types null: true, description: "List of the project's CI/CD variables.", authorize: :admin_build, - method: :variables + resolver: Resolvers::Ci::VariablesResolver field :ci_cd_settings, Types::Ci::CiCdSettingType, null: true, diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index f0430a47a7f..759819ba34b 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -17,7 +17,8 @@ module Types field :ci_variables, Types::Ci::InstanceVariableType.connection_type, null: true, - description: "List of the instance's CI/CD variables." + description: "List of the instance's CI/CD variables.", + resolver: Resolvers::Ci::VariablesResolver field :container_repository, Types::ContainerRepositoryDetailsType, null: true, description: 'Find a container repository.' do @@ -167,12 +168,6 @@ module Types application_settings end - def ci_variables - return unless current_user&.can_admin_all_resources? - - ::Ci::InstanceVariable.all - end - def application_settings Gitlab::CurrentSettings.current_application_settings end diff --git a/app/models/concerns/ci/has_variable.rb b/app/models/concerns/ci/has_variable.rb index 3b437fbba16..77e7e5035a0 100644 --- a/app/models/concerns/ci/has_variable.rb +++ b/app/models/concerns/ci/has_variable.rb @@ -18,6 +18,7 @@ module Ci scope :by_key, -> (key) { where(key: key) } scope :order_key_asc, -> { reorder(key: :asc) } + scope :order_key_desc, -> { reorder(key: :desc) } attr_encrypted :value, mode: :per_attribute_iv_and_salt, @@ -30,6 +31,16 @@ module Ci end end + class_methods do + def order_by(method) + case method.to_s + when 'key_asc' then order_key_asc + when 'key_desc' then order_key_desc + else all + end + end + end + def to_runner_variable var_cache_key = to_runner_variable_cache_key diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb index a1079abe5fd..98ce981ad8e 100644 --- a/app/models/container_repository.rb +++ b/app/models/container_repository.rb @@ -395,7 +395,7 @@ class ContainerRepository < ApplicationRecord end def migrated? - MIGRATION_PHASE_1_ENDED_AT < self.created_at || import_done? + (self.created_at && MIGRATION_PHASE_1_ENDED_AT < self.created_at) || import_done? end def last_import_step_done_at diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb index e1f28c0e117..2619a7cca99 100644 --- a/app/models/lfs_object.rb +++ b/app/models/lfs_object.rb @@ -12,7 +12,6 @@ class LfsObject < ApplicationRecord scope :with_files_stored_locally, -> { where(file_store: LfsObjectUploader::Store::LOCAL) } scope :with_files_stored_remotely, -> { where(file_store: LfsObjectUploader::Store::REMOTE) } scope :for_oids, -> (oids) { where(oid: oids) } - scope :for_oid_and_size, -> (oid, size) { find_by(oid: oid, size: size) } validates :oid, presence: true, uniqueness: true, format: { with: /\A\h{64}\z/ } @@ -20,6 +19,10 @@ class LfsObject < ApplicationRecord BATCH_SIZE = 3000 + def self.for_oid_and_size(oid, size) + find_by(oid: oid, size: size) + end + def self.not_linked_to_project(project) where('NOT EXISTS (?)', project.lfs_objects_projects.select(1).where('lfs_objects_projects.lfs_object_id = lfs_objects.id')) diff --git a/app/services/projects/container_repository/destroy_service.rb b/app/services/projects/container_repository/destroy_service.rb index 6db6b449671..6cb0d55aea4 100644 --- a/app/services/projects/container_repository/destroy_service.rb +++ b/app/services/projects/container_repository/destroy_service.rb @@ -10,12 +10,15 @@ module Projects }.freeze def execute(container_repository, disable_timeout: true) - return false unless can?(current_user, :update_container_image, project) + return error('Unauthorized access') unless can_destroy? # Delete tags outside of the transaction to avoid hitting an idle-in-transaction timeout - unless delete_tags(container_repository, disable_timeout) && + if delete_tags(container_repository, disable_timeout) && destroy_container_repository(container_repository) + success + else container_repository.delete_failed! + error('Deletion failed for container repository') end end @@ -40,9 +43,19 @@ module Projects false end + def can_destroy? + return true if skip_permission_check? + + can?(current_user, :destroy_container_image, project) + end + def error_message(container_repository, message) - "Container repository with ID: #{container_repository.id} and path: #{container_repository.path}" \ - " failed with message: #{message}" + "Container repository with ID: #{container_repository.id} and path: #{container_repository.path} " \ + "failed with message: #{message}" + end + + def skip_permission_check? + !!params[:skip_permission_check] end end end diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index 2e346ff6f12..2279ab301dc 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -257,12 +257,12 @@ module Projects return true unless Gitlab.config.registry.enabled return false unless remove_legacy_registry_tags + results = [] project.container_repositories.find_each do |container_repository| - service = Projects::ContainerRepository::DestroyService.new(project, current_user) - service.execute(container_repository) + results << destroy_repository(project, container_repository) end - true + results.all? end ## @@ -272,9 +272,14 @@ module Projects def remove_legacy_registry_tags return true unless Gitlab.config.registry.enabled - ::ContainerRepository.build_root_repository(project).tap do |repository| - break repository.has_tags? ? repository.delete_tags! : true - end + root_repository = ::ContainerRepository.build_root_repository(project) + root_repository.has_tags? ? destroy_repository(project, root_repository) : true + end + + def destroy_repository(project, repository) + service = ContainerRepository::DestroyService.new(project, current_user, { skip_permission_check: true }) + response = service.execute(repository) + response[:status] == :success end def raise_error(message) |