Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-01-26 15:10:19 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-01-26 15:10:19 +0300
commita1c0b634f78f51389fd3ec390a1803afa3de49a2 (patch)
treef57fc3000a6e7f2bd271a63018427c8fb9c06c08 /app
parentdb950c5706cdf47f7ccc2e02a4ffd691432ac5dc (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/api.js5
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue16
-rw-r--r--app/assets/javascripts/repository/index.js2
-rw-r--r--app/assets/javascripts/repository/utils/ref_switcher_utils.js7
-rw-r--r--app/graphql/resolvers/ci/variables_resolver.rb27
-rw-r--r--app/graphql/types/ci/variable_sort_enum.rb13
-rw-r--r--app/graphql/types/group_type.rb2
-rw-r--r--app/graphql/types/project_type.rb2
-rw-r--r--app/graphql/types/query_type.rb9
-rw-r--r--app/models/concerns/ci/has_variable.rb11
-rw-r--r--app/models/container_repository.rb2
-rw-r--r--app/models/lfs_object.rb5
-rw-r--r--app/services/projects/container_repository/destroy_service.rb21
-rw-r--r--app/services/projects/destroy_service.rb17
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)