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:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/ci/runner/components/runner_create_form.vue33
-rw-r--r--app/assets/javascripts/ci/runner/components/runner_details.vue4
-rw-r--r--app/assets/javascripts/ci/runner/components/runner_managers_detail.vue24
-rw-r--r--app/assets/javascripts/ci/runner/components/runner_managers_table.vue11
-rw-r--r--app/assets/javascripts/ci/runner/constants.js3
-rw-r--r--app/assets/javascripts/ci/runner/graphql/show/runner_managers.query.graphql6
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/details/components/package_files.vue31
-rw-r--r--app/graphql/mutations/achievements/delete_user_achievement.rb33
-rw-r--r--app/graphql/types/mutation_type.rb1
-rw-r--r--app/policies/group_policy.rb4
-rw-r--r--app/services/achievements/destroy_user_achievement_service.rb33
-rw-r--r--app/services/database/mark_migration_service.rb58
-rw-r--r--app/services/personal_access_tokens/last_used_service.rb9
13 files changed, 201 insertions, 49 deletions
diff --git a/app/assets/javascripts/ci/runner/components/runner_create_form.vue b/app/assets/javascripts/ci/runner/components/runner_create_form.vue
index 040e42fa938..1b363174d28 100644
--- a/app/assets/javascripts/ci/runner/components/runner_create_form.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_create_form.vue
@@ -4,7 +4,13 @@ import RunnerFormFields from '~/ci/runner/components/runner_form_fields.vue';
import runnerCreateMutation from '~/ci/runner/graphql/new/runner_create.mutation.graphql';
import { modelToUpdateMutationVariables } from 'ee_else_ce/ci/runner/runner_update_form_utils';
import { captureException } from '../sentry_utils';
-import { RUNNER_TYPES, DEFAULT_ACCESS_LEVEL, PROJECT_TYPE, GROUP_TYPE } from '../constants';
+import {
+ RUNNER_TYPES,
+ DEFAULT_ACCESS_LEVEL,
+ PROJECT_TYPE,
+ GROUP_TYPE,
+ I18N_CREATE_ERROR,
+} from '../constants';
export default {
name: 'RunnerCreateForm',
@@ -82,16 +88,29 @@ export default {
});
if (errors?.length) {
- this.$emit('error', new Error(errors.join(' ')));
- this.saving = false;
- } else {
- this.onSuccess(runner);
+ this.onError(new Error(errors.join(' ')), true);
+ return;
}
+
+ if (!runner?.ephemeralRegisterUrl) {
+ // runner is missing information, report issue and
+ // fail naviation to register page.
+ this.onError(new Error(I18N_CREATE_ERROR));
+ return;
+ }
+
+ this.onSuccess(runner);
} catch (error) {
+ this.onError(error);
+ }
+ },
+ onError(error, isValidationError = false) {
+ if (!isValidationError) {
captureException({ error, component: this.$options.name });
- this.$emit('error', error);
- this.saving = false;
}
+
+ this.$emit('error', error);
+ this.saving = false;
},
onSuccess(runner) {
this.$emit('saved', runner);
diff --git a/app/assets/javascripts/ci/runner/components/runner_details.vue b/app/assets/javascripts/ci/runner/components/runner_details.vue
index 51c752f0dee..8c1280cffb9 100644
--- a/app/assets/javascripts/ci/runner/components/runner_details.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_details.vue
@@ -10,6 +10,7 @@ import {
GROUP_TYPE,
PROJECT_TYPE,
RUNNER_MANAGERS_HELP_URL,
+ I18N_STATUS_NEVER_CONTACTED,
} from '../constants';
import RunnerDetail from './runner_detail.vue';
import RunnerGroups from './runner_groups.vue';
@@ -85,6 +86,7 @@ export default {
},
ACCESS_LEVEL_REF_PROTECTED,
RUNNER_MANAGERS_HELP_URL,
+ I18N_STATUS_NEVER_CONTACTED,
};
</script>
@@ -99,7 +101,7 @@ export default {
<runner-detail :label="s__('Runners|Description')" :value="runner.description" />
<runner-detail
:label="s__('Runners|Last contact')"
- :empty-value="s__('Runners|Never contacted')"
+ :empty-value="$options.I18N_STATUS_NEVER_CONTACTED"
>
<template v-if="runner.contactedAt" #value>
<time-ago :time="runner.contactedAt" />
diff --git a/app/assets/javascripts/ci/runner/components/runner_managers_detail.vue b/app/assets/javascripts/ci/runner/components/runner_managers_detail.vue
index a9df7f12955..5cc1bbef481 100644
--- a/app/assets/javascripts/ci/runner/components/runner_managers_detail.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_managers_detail.vue
@@ -1,13 +1,12 @@
<script>
-import { GlCollapse, GlButton, GlIcon, GlSkeletonLoader, GlTableLite } from '@gitlab/ui';
-import HelpPopover from '~/vue_shared/components/help_popover.vue';
+import { GlCollapse, GlButton, GlIcon, GlSkeletonLoader } from '@gitlab/ui';
import { __, s__, formatNumber } from '~/locale';
-import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { createAlert } from '~/alert';
import runnerManagersQuery from '../graphql/show/runner_managers.query.graphql';
import { I18N_FETCH_ERROR } from '../constants';
import { captureException } from '../sentry_utils';
import { tableField } from '../utils';
+import RunnerManagersTable from './runner_managers_table.vue';
export default {
name: 'RunnerManagersDetail',
@@ -16,9 +15,7 @@ export default {
GlButton,
GlIcon,
GlSkeletonLoader,
- GlTableLite,
- TimeAgo,
- HelpPopover,
+ RunnerManagersTable,
},
props: {
runner: {
@@ -108,20 +105,7 @@ export default {
<gl-collapse :visible="expanded" class="gl-mt-5">
<gl-skeleton-loader v-if="loading" />
- <gl-table-lite v-else-if="managers.length" :fields="$options.fields" :items="managers">
- <template #head(systemId)="{ label }">
- {{ label }}
- <help-popover>
- {{ s__('Runners|The unique ID for each runner that uses this configuration.') }}
- </help-popover>
- </template>
- <template #cell(contactedAt)="{ item = {} }">
- <template v-if="item.contactedAt">
- <time-ago :time="item.contactedAt" />
- </template>
- <template v-else>{{ s__('Runners|Never contacted') }}</template>
- </template>
- </gl-table-lite>
+ <runner-managers-table v-else-if="managers.length" :items="managers" />
</gl-collapse>
</div>
</template>
diff --git a/app/assets/javascripts/ci/runner/components/runner_managers_table.vue b/app/assets/javascripts/ci/runner/components/runner_managers_table.vue
index 71cf76aed46..2039d76f8f7 100644
--- a/app/assets/javascripts/ci/runner/components/runner_managers_table.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_managers_table.vue
@@ -4,6 +4,7 @@ import HelpPopover from '~/vue_shared/components/help_popover.vue';
import { s__ } from '~/locale';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { tableField } from '../utils';
+import { I18N_STATUS_NEVER_CONTACTED } from '../constants';
export default {
name: 'RunnerManagersTable',
@@ -20,13 +21,6 @@ export default {
default: () => [],
},
},
- data() {
- return {
- skip: true,
- expanded: false,
- managers: [],
- };
- },
fields: [
tableField({ key: 'systemId', label: s__('Runners|System ID') }),
tableField({ key: 'version', label: s__('Runners|Version') }),
@@ -40,6 +34,7 @@ export default {
thClasses: ['gl-text-right'],
}),
],
+ I18N_STATUS_NEVER_CONTACTED,
};
</script>
@@ -65,7 +60,7 @@ export default {
<template v-if="item.contactedAt">
<time-ago :time="item.contactedAt" />
</template>
- <template v-else>{{ s__('Runners|Never contacted') }}</template>
+ <template v-else>{{ $options.I18N_STATUS_NEVER_CONTACTED }}</template>
</template>
</gl-table-lite>
</template>
diff --git a/app/assets/javascripts/ci/runner/constants.js b/app/assets/javascripts/ci/runner/constants.js
index 395d9ac0d8e..40841696ead 100644
--- a/app/assets/javascripts/ci/runner/constants.js
+++ b/app/assets/javascripts/ci/runner/constants.js
@@ -9,6 +9,9 @@ export const RUNNER_DETAILS_PROJECTS_PAGE_SIZE = 5;
export const RUNNER_DETAILS_JOBS_PAGE_SIZE = 30;
export const I18N_FETCH_ERROR = s__('Runners|Something went wrong while fetching runner data.');
+export const I18N_CREATE_ERROR = s__(
+ 'Runners|An error occurred while creating the runner. Please try again.',
+);
export const FILTER_CSS_CLASSES =
'gl-bg-gray-10 gl-p-5 gl-border-solid gl-border-gray-100 gl-border-0 gl-border-t-1 gl-border-b-1';
diff --git a/app/assets/javascripts/ci/runner/graphql/show/runner_managers.query.graphql b/app/assets/javascripts/ci/runner/graphql/show/runner_managers.query.graphql
index 65fb5f91b60..c4fb63f2b0d 100644
--- a/app/assets/javascripts/ci/runner/graphql/show/runner_managers.query.graphql
+++ b/app/assets/javascripts/ci/runner/graphql/show/runner_managers.query.graphql
@@ -6,6 +6,12 @@ query getRunnerManagers($runnerId: CiRunnerID!) {
nodes {
id
systemId
+ version
+ revision
+ executorName
+ architectureName
+ platformName
+ ipAddress
contactedAt
}
}
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/details/components/package_files.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/details/components/package_files.vue
index e45b88bc6d5..ecd1bfb8ebe 100644
--- a/app/assets/javascripts/packages_and_registries/infrastructure_registry/details/components/package_files.vue
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/details/components/package_files.vue
@@ -1,5 +1,11 @@
<script>
-import { GlLink, GlTable, GlDropdownItem, GlDropdown, GlIcon, GlButton } from '@gitlab/ui';
+import {
+ GlLink,
+ GlTable,
+ GlDisclosureDropdownItem,
+ GlDisclosureDropdown,
+ GlButton,
+} from '@gitlab/ui';
import { last } from 'lodash';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { __ } from '~/locale';
@@ -13,9 +19,8 @@ export default {
components: {
GlLink,
GlTable,
- GlIcon,
- GlDropdown,
- GlDropdownItem,
+ GlDisclosureDropdown,
+ GlDisclosureDropdownItem,
GlButton,
FileIcon,
TimeAgoTooltip,
@@ -136,14 +141,16 @@ export default {
</template>
<template #cell(actions)="{ item }">
- <gl-dropdown category="tertiary" right>
- <template #button-content>
- <gl-icon name="ellipsis_v" />
- </template>
- <gl-dropdown-item data-testid="delete-file" @click="$emit('delete-file', item)">
- {{ $options.i18n.deleteFile }}
- </gl-dropdown-item>
- </gl-dropdown>
+ <gl-disclosure-dropdown category="tertiary" right no-caret icon="ellipsis_v">
+ <gl-disclosure-dropdown-item
+ data-testid="delete-file"
+ @action="$emit('delete-file', item)"
+ >
+ <template #list-item>
+ {{ $options.i18n.deleteFile }}
+ </template>
+ </gl-disclosure-dropdown-item>
+ </gl-disclosure-dropdown>
</template>
<template #row-details="{ item }">
diff --git a/app/graphql/mutations/achievements/delete_user_achievement.rb b/app/graphql/mutations/achievements/delete_user_achievement.rb
new file mode 100644
index 00000000000..f1527c2981a
--- /dev/null
+++ b/app/graphql/mutations/achievements/delete_user_achievement.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Achievements
+ class DeleteUserAchievement < BaseMutation
+ graphql_name 'UserAchievementsDelete'
+
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ field :user_achievement,
+ ::Types::Achievements::UserAchievementType,
+ null: true,
+ description: 'Deleted user achievement.'
+
+ argument :user_achievement_id, ::Types::GlobalIDType[::Achievements::UserAchievement],
+ required: true,
+ description: 'Global ID of the user achievement being deleted.'
+
+ authorize :destroy_user_achievement
+
+ def resolve(args)
+ user_achievement = authorized_find!(id: args[:user_achievement_id])
+
+ result = ::Achievements::DestroyUserAchievementService.new(current_user, user_achievement).execute
+ { user_achievement: result.payload, errors: result.errors }
+ end
+
+ def find_object(id:)
+ GitlabSchema.object_from_id(id, expected_type: ::Achievements::UserAchievement)
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index efc7bf89693..62ab1086ed3 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -9,6 +9,7 @@ module Types
mount_mutation Mutations::Achievements::Award, alpha: { milestone: '15.10' }
mount_mutation Mutations::Achievements::Create, alpha: { milestone: '15.8' }
mount_mutation Mutations::Achievements::Delete, alpha: { milestone: '15.11' }
+ mount_mutation Mutations::Achievements::DeleteUserAchievement, alpha: { milestone: '16.1' }
mount_mutation Mutations::Achievements::Revoke, alpha: { milestone: '15.10' }
mount_mutation Mutations::Achievements::Update, alpha: { milestone: '15.11' }
mount_mutation Mutations::Admin::SidekiqQueues::DeleteJobs
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 447251c6442..94a67f5b5c8 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -163,6 +163,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
enable :award_achievement
end
+ rule { can?(:owner_access) & achievements_enabled }.policy do
+ enable :destroy_user_achievement
+ end
+
rule { ~public_group & ~has_access }.prevent :read_counts
rule { ~can_read_group_member }.policy do
diff --git a/app/services/achievements/destroy_user_achievement_service.rb b/app/services/achievements/destroy_user_achievement_service.rb
new file mode 100644
index 00000000000..3beaed646e3
--- /dev/null
+++ b/app/services/achievements/destroy_user_achievement_service.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Achievements
+ class DestroyUserAchievementService
+ attr_reader :current_user, :user_achievement
+
+ def initialize(current_user, user_achievement)
+ @current_user = current_user
+ @user_achievement = user_achievement
+ end
+
+ def execute
+ return error_no_permissions unless allowed?
+
+ user_achievement.delete
+ ServiceResponse.success(payload: user_achievement)
+ end
+
+ private
+
+ def allowed?
+ current_user&.can?(:destroy_user_achievement, user_achievement)
+ end
+
+ def error_no_permissions
+ error('You have insufficient permissions to delete this user achievement')
+ end
+
+ def error(message)
+ ServiceResponse.error(message: Array(message))
+ end
+ end
+end
diff --git a/app/services/database/mark_migration_service.rb b/app/services/database/mark_migration_service.rb
new file mode 100644
index 00000000000..aff10fa5f76
--- /dev/null
+++ b/app/services/database/mark_migration_service.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Database
+ class MarkMigrationService
+ def initialize(connection:, version:)
+ @connection = connection
+ @version = version
+ end
+
+ def execute
+ return error(reason: :not_found) unless migration.present?
+ return error(reason: :invalid) if all_versions.include?(migration.version)
+
+ if create_version(version)
+ ServiceResponse.success
+ else
+ error(reason: :invalid)
+ end
+ end
+
+ private
+
+ attr_reader :connection, :version
+
+ def migration
+ @migration ||= connection
+ .migration_context
+ .migrations
+ .find { |migration| migration.version == version }
+ end
+
+ def all_versions
+ all_executed_migrations.map(&:to_i)
+ end
+
+ def all_executed_migrations
+ sm = Arel::SelectManager.new(arel_table)
+ sm.project(arel_table[:version])
+ sm.order(arel_table[:version].asc) # rubocop: disable CodeReuse/ActiveRecord
+ connection.select_values(sm, "#{self.class} Load")
+ end
+
+ def create_version(version)
+ im = Arel::InsertManager.new
+ im.into(arel_table)
+ im.insert(arel_table[:version] => version)
+ connection.insert(im, "#{self.class} Create", :version, version)
+ end
+
+ def arel_table
+ @arel_table ||= Arel::Table.new(:schema_migrations)
+ end
+
+ def error(reason:)
+ ServiceResponse.error(message: 'error', reason: reason)
+ end
+ end
+end
diff --git a/app/services/personal_access_tokens/last_used_service.rb b/app/services/personal_access_tokens/last_used_service.rb
index 9066fd1acdf..6fc3110a70b 100644
--- a/app/services/personal_access_tokens/last_used_service.rb
+++ b/app/services/personal_access_tokens/last_used_service.rb
@@ -22,7 +22,14 @@ module PersonalAccessTokens
last_used = @personal_access_token.last_used_at
- last_used.nil? || (last_used <= 1.day.ago)
+ return true if last_used.nil?
+
+ if Feature.enabled?(:update_personal_access_token_usage_information_every_10_minutes) &&
+ last_used <= 10.minutes.ago
+ return true
+ end
+
+ last_used <= 1.day.ago
end
end
end