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-10-27 09:12:29 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-10-27 09:12:29 +0300
commit2af65f9153baf358bfc6acdd8de9652b39264497 (patch)
treed6af38edbdded9835907da8da5dc11bca09c7749 /app
parent39c9abe4fe410ac402d57a364bf89938a2067315 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/admin/users/components/actions/index.js4
-rw-r--r--app/assets/javascripts/admin/users/components/actions/trust_user.vue62
-rw-r--r--app/assets/javascripts/admin/users/components/actions/untrust_user.vue56
-rw-r--r--app/assets/javascripts/admin/users/constants.js2
-rw-r--r--app/assets/javascripts/ci/runner/components/runner_details.vue18
-rw-r--r--app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_base.vue10
-rw-r--r--app/assets/javascripts/issues/show/components/issue_header.vue8
-rw-r--r--app/assets/javascripts/organizations/users/components/app.vue51
-rw-r--r--app/assets/javascripts/organizations/users/graphql/organization_users.query.graphql14
-rw-r--r--app/assets/javascripts/organizations/users/index.js29
-rw-r--r--app/assets/javascripts/pages/organizations/organizations/users/index.js3
-rw-r--r--app/assets/stylesheets/utilities.scss2
-rw-r--r--app/controllers/admin/users_controller.rb2
-rw-r--r--app/helpers/admin/user_actions_helper.rb15
-rw-r--r--app/helpers/organizations/organization_helper.rb6
-rw-r--r--app/helpers/users_helper.rb4
-rw-r--r--app/models/user.rb8
-rw-r--r--app/views/admin/users/_users.html.haml3
-rw-r--r--app/views/events/_event.html.haml2
-rw-r--r--app/views/organizations/organizations/users.html.haml3
20 files changed, 277 insertions, 25 deletions
diff --git a/app/assets/javascripts/admin/users/components/actions/index.js b/app/assets/javascripts/admin/users/components/actions/index.js
index 4e63a85df89..633bc4d8b15 100644
--- a/app/assets/javascripts/admin/users/components/actions/index.js
+++ b/app/assets/javascripts/admin/users/components/actions/index.js
@@ -9,6 +9,8 @@ import Reject from './reject.vue';
import Unban from './unban.vue';
import Unblock from './unblock.vue';
import Unlock from './unlock.vue';
+import Trust from './trust_user.vue';
+import Untrust from './untrust_user.vue';
export default {
Activate,
@@ -22,4 +24,6 @@ export default {
Unblock,
Unlock,
Reject,
+ Trust,
+ Untrust,
};
diff --git a/app/assets/javascripts/admin/users/components/actions/trust_user.vue b/app/assets/javascripts/admin/users/components/actions/trust_user.vue
new file mode 100644
index 00000000000..41ff8d4120d
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/trust_user.vue
@@ -0,0 +1,62 @@
+<script>
+import { GlDisclosureDropdownItem } from '@gitlab/ui';
+import { sprintf, s__, __ } from '~/locale';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from '~/vue_shared/components/confirm_modal_eventhub';
+import { I18N_USER_ACTIONS } from '../../constants';
+
+// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
+const messageHtml = `
+ <p>${s__('AdminUsers|When not being monitored for spam:')}</p>
+ <ul>
+ <li>${s__(
+ 'AdminUsers|The user can create issues, notes, snippets, and merge requests that appear to be spam without being blocked.',
+ )}</li>
+ </ul>
+ <p>${s__('AdminUsers|You can untrust this user in the future.')}</p>
+`;
+
+export default {
+ components: {
+ GlDisclosureDropdownItem,
+ },
+ props: {
+ username: {
+ type: String,
+ required: true,
+ },
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+ methods: {
+ onClick() {
+ eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, {
+ path: this.path,
+ method: 'put',
+ modalAttributes: {
+ title: sprintf(s__('AdminUsers|Stop monitoring %{username} for possible spam?'), {
+ username: this.username,
+ }),
+ actionCancel: {
+ text: __('Cancel'),
+ },
+ actionPrimary: {
+ text: I18N_USER_ACTIONS.trust,
+ attributes: { variant: 'confirm' },
+ },
+ messageHtml,
+ },
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-disclosure-dropdown-item @action="onClick">
+ <template #list-item>
+ <slot></slot>
+ </template>
+ </gl-disclosure-dropdown-item>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/untrust_user.vue b/app/assets/javascripts/admin/users/components/actions/untrust_user.vue
new file mode 100644
index 00000000000..da59833af07
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/untrust_user.vue
@@ -0,0 +1,56 @@
+<script>
+import { GlDisclosureDropdownItem } from '@gitlab/ui';
+import { sprintf, s__, __ } from '~/locale';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from '~/vue_shared/components/confirm_modal_eventhub';
+import { I18N_USER_ACTIONS } from '../../constants';
+
+// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
+const messageHtml = `<p>${s__(
+ 'AdminUsers|You can trust this user in the future if necessary.',
+)}</p>`;
+
+export default {
+ components: {
+ GlDisclosureDropdownItem,
+ },
+ props: {
+ username: {
+ type: String,
+ required: true,
+ },
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+ methods: {
+ onClick() {
+ eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, {
+ path: this.path,
+ method: 'put',
+ modalAttributes: {
+ title: sprintf(s__('AdminUsers|Re-enable spam monitoring for %{username}?'), {
+ username: this.username,
+ }),
+ actionCancel: {
+ text: __('Cancel'),
+ },
+ actionPrimary: {
+ text: I18N_USER_ACTIONS.untrust,
+ attributes: { variant: 'confirm' },
+ },
+ messageHtml,
+ },
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-disclosure-dropdown-item @action="onClick">
+ <template #list-item>
+ <slot></slot>
+ </template>
+ </gl-disclosure-dropdown-item>
+</template>
diff --git a/app/assets/javascripts/admin/users/constants.js b/app/assets/javascripts/admin/users/constants.js
index 9cd61d6b1db..43c9a8749cd 100644
--- a/app/assets/javascripts/admin/users/constants.js
+++ b/app/assets/javascripts/admin/users/constants.js
@@ -19,4 +19,6 @@ export const I18N_USER_ACTIONS = {
deleteWithContributions: s__('AdminUsers|Delete user and contributions'),
ban: s__('AdminUsers|Ban user'),
unban: s__('AdminUsers|Unban user'),
+ trust: s__('AdminUsers|Trust user'),
+ untrust: s__('AdminUsers|Untrust user'),
};
diff --git a/app/assets/javascripts/ci/runner/components/runner_details.vue b/app/assets/javascripts/ci/runner/components/runner_details.vue
index 0ec2ef30c20..477d28c6c28 100644
--- a/app/assets/javascripts/ci/runner/components/runner_details.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_details.vue
@@ -120,12 +120,9 @@ export default {
}}
</p>
<p class="gl-mb-0">
- <gl-link
- :href="tokenExpirationHelpUrl"
- target="_blank"
- class="gl-reset-font-size"
- >{{ __('Learn more') }}</gl-link
- >
+ <gl-link :href="tokenExpirationHelpUrl" target="_blank">{{
+ __('Learn more')
+ }}</gl-link>
</p>
</help-popover>
</template>
@@ -156,12 +153,9 @@ export default {
"
>
<template #link="{ content }"
- ><gl-link
- :href="$options.RUNNER_MANAGERS_HELP_URL"
- target="_blank"
- class="gl-reset-font-size"
- >{{ content }}</gl-link
- ></template
+ ><gl-link :href="$options.RUNNER_MANAGERS_HELP_URL" target="_blank">{{
+ content
+ }}</gl-link></template
>
</gl-sprintf>
</help-popover>
diff --git a/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_base.vue b/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_base.vue
index e3d3360cd0c..3b9f14a218f 100644
--- a/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_base.vue
+++ b/app/assets/javascripts/contribution_events/components/contribution_event/contribution_event_base.vue
@@ -47,16 +47,20 @@ export default {
<template>
<li class="gl-mt-5 gl-pb-5 gl-border-b gl-relative">
- <time-ago-tooltip :time="event.created_at" class="gl-float-right gl-text-secondary" />
+ <time-ago-tooltip
+ :time="event.created_at"
+ class="gl-float-right gl-font-sm gl-text-secondary gl-mt-2"
+ />
<gl-avatar-link :href="author.web_url">
<gl-avatar-labeled
:label="author.name"
:sub-label="authorUsername"
+ inline-labels
:src="author.avatar_url"
- :size="32"
+ :size="24"
/>
</gl-avatar-link>
- <div class="gl-pl-8 gl-mt-2" data-testid="event-body">
+ <div class="gl-pl-7" data-testid="event-body">
<div class="gl-text-secondary">
<gl-icon :class="iconClass" :name="iconName" />
<gl-sprintf v-if="message" :message="message">
diff --git a/app/assets/javascripts/issues/show/components/issue_header.vue b/app/assets/javascripts/issues/show/components/issue_header.vue
index 211f3217ddc..c205a6361c7 100644
--- a/app/assets/javascripts/issues/show/components/issue_header.vue
+++ b/app/assets/javascripts/issues/show/components/issue_header.vue
@@ -115,11 +115,9 @@ export default {
<template #status-badge>
<gl-sprintf v-if="closedStatusLink" :message="statusText">
<template #link>
- <gl-link
- class="gl-reset-color! gl-reset-font-size gl-text-decoration-underline"
- :href="closedStatusLink"
- >{{ closedStatusText }}</gl-link
- >
+ <gl-link class="gl-reset-color! gl-text-decoration-underline" :href="closedStatusLink">{{
+ closedStatusText
+ }}</gl-link>
</template>
</gl-sprintf>
<template v-else>{{ statusText }}</template>
diff --git a/app/assets/javascripts/organizations/users/components/app.vue b/app/assets/javascripts/organizations/users/components/app.vue
new file mode 100644
index 00000000000..ae22bedd69a
--- /dev/null
+++ b/app/assets/javascripts/organizations/users/components/app.vue
@@ -0,0 +1,51 @@
+<script>
+import { __, s__ } from '~/locale';
+import { createAlert } from '~/alert';
+import organizationUsersQuery from '../graphql/organization_users.query.graphql';
+
+export default {
+ name: 'OrganizationsUsersApp',
+ i18n: {
+ users: __('Users'),
+ loadingPlaceholder: __('Loading'),
+ errorMessage: s__(
+ 'Organization|An error occurred loading the organization users. Please refresh the page to try again.',
+ ),
+ },
+ inject: ['organizationGid'],
+ data() {
+ return {
+ users: [],
+ };
+ },
+ apollo: {
+ users: {
+ query: organizationUsersQuery,
+ variables() {
+ return { id: this.organizationGid };
+ },
+ update(data) {
+ return data.organization.organizationUsers.nodes;
+ },
+ error(error) {
+ createAlert({ message: this.$options.i18n.errorMessage, error, captureError: true });
+ },
+ },
+ },
+ computed: {
+ loading() {
+ return this.$apollo.queries.users.loading;
+ },
+ },
+};
+</script>
+
+<template>
+ <section>
+ <h1 class="gl-my-4 gl-font-size-h-display">{{ $options.i18n.users }}</h1>
+ <template v-if="loading">
+ {{ $options.i18n.loadingPlaceholder }}
+ </template>
+ <div data-testid="organization-users">{{ users }}</div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/organizations/users/graphql/organization_users.query.graphql b/app/assets/javascripts/organizations/users/graphql/organization_users.query.graphql
new file mode 100644
index 00000000000..7b37186ba1a
--- /dev/null
+++ b/app/assets/javascripts/organizations/users/graphql/organization_users.query.graphql
@@ -0,0 +1,14 @@
+query getOrganizationUsers($id: OrganizationsOrganizationID!) {
+ organization(id: $id) {
+ id
+ organizationUsers {
+ nodes {
+ badges
+ id
+ user {
+ id
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/organizations/users/index.js b/app/assets/javascripts/organizations/users/index.js
new file mode 100644
index 00000000000..76656243075
--- /dev/null
+++ b/app/assets/javascripts/organizations/users/index.js
@@ -0,0 +1,29 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import OrganizationsUsersApp from './components/app.vue';
+
+export const initOrganizationsUsers = () => {
+ const el = document.getElementById('js-organizations-users');
+
+ if (!el) return false;
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ const { organizationGid } = convertObjectPropsToCamelCase(el.dataset);
+
+ return new Vue({
+ el,
+ name: 'OrganizationsUsersRoot',
+ apolloProvider,
+ provide: {
+ organizationGid,
+ },
+ render(createElement) {
+ return createElement(OrganizationsUsersApp);
+ },
+ });
+};
diff --git a/app/assets/javascripts/pages/organizations/organizations/users/index.js b/app/assets/javascripts/pages/organizations/organizations/users/index.js
new file mode 100644
index 00000000000..12d53207b22
--- /dev/null
+++ b/app/assets/javascripts/pages/organizations/organizations/users/index.js
@@ -0,0 +1,3 @@
+import { initOrganizationsUsers } from '~/organizations/users';
+
+initOrganizationsUsers();
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index 8fe45d4bb9d..d6500529170 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -65,8 +65,6 @@
min-width: 0;
}
-// .gl-font-size-inherit will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1466
-.gl-font-size-inherit,
.font-size-inherit { font-size: inherit; }
.gl-w-16 { width: px-to-rem($grid-size * 2); }
.gl-w-64 { width: px-to-rem($grid-size * 8); }
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 9634257209d..ee78d5a8c35 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -310,7 +310,7 @@ class Admin::UsersController < Admin::ApplicationController
end
def users_with_included_associations(users)
- users.includes(:authorized_projects) # rubocop: disable CodeReuse/ActiveRecord
+ users.includes(:authorized_projects, :trusted_with_spam_attribute) # rubocop: disable CodeReuse/ActiveRecord
end
def admin_making_changes_for_another_user?
diff --git a/app/helpers/admin/user_actions_helper.rb b/app/helpers/admin/user_actions_helper.rb
index 969c5d5a0b5..ba40b3c8a8d 100644
--- a/app/helpers/admin/user_actions_helper.rb
+++ b/app/helpers/admin/user_actions_helper.rb
@@ -16,6 +16,7 @@ module Admin
unlock_actions
delete_actions
ban_actions
+ trust_actions
@actions
end
@@ -66,5 +67,19 @@ module Admin
@actions << 'ban'
end
end
+
+ def trust_actions
+ return if @user.internal? ||
+ @user.blocked_pending_approval? ||
+ @user.banned? ||
+ @user.blocked? ||
+ @user.deactivated?
+
+ @actions << if @user.trusted?
+ 'untrust'
+ else
+ 'trust'
+ end
+ end
end
end
diff --git a/app/helpers/organizations/organization_helper.rb b/app/helpers/organizations/organization_helper.rb
index 48ba9d4ab84..312f55c11d2 100644
--- a/app/helpers/organizations/organization_helper.rb
+++ b/app/helpers/organizations/organization_helper.rb
@@ -42,6 +42,12 @@ module Organizations
}
end
+ def organization_user_app_data(organization)
+ {
+ organization_gid: organization.to_global_id
+ }
+ end
+
private
def shared_groups_and_projects_app_data
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 1bdc0cbb453..75ff2da2322 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -262,7 +262,9 @@ module UsersHelper
delete_with_contributions: admin_user_path(:id, hard_delete: true),
admin_user: admin_user_path(:id),
ban: ban_admin_user_path(:id),
- unban: unban_admin_user_path(:id)
+ unban: unban_admin_user_path(:id),
+ trust: trust_admin_user_path(:id),
+ untrust: untrust_admin_user_path(:id)
}
end
diff --git a/app/models/user.rb b/app/models/user.rb
index fdc0b531521..bc256ef0f31 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -601,6 +601,12 @@ class User < MainClusterwide::ApplicationRecord
scope :by_provider_and_extern_uid, ->(provider, extern_uid) { joins(:identities).merge(Identity.with_extern_uid(provider, extern_uid)) }
scope :by_ids_or_usernames, -> (ids, usernames) { where(username: usernames).or(where(id: ids)) }
scope :without_forbidden_states, -> { where.not(state: FORBIDDEN_SEARCH_STATES) }
+ scope :trusted, -> do
+ where('EXISTS (?)', ::UserCustomAttribute
+ .select(1)
+ .where('user_id = users.id')
+ .trusted_with_spam)
+ end
strip_attributes! :name
@@ -769,6 +775,8 @@ class User < MainClusterwide::ApplicationRecord
external
when 'deactivated'
deactivated
+ when "trusted"
+ trusted
else
active_without_ghosts
end
diff --git a/app/views/admin/users/_users.html.haml b/app/views/admin/users/_users.html.haml
index d4a9009a0cf..bbb068c3680 100644
--- a/app/views/admin/users/_users.html.haml
+++ b/app/views/admin/users/_users.html.haml
@@ -44,6 +44,9 @@
= gl_tab_link_to admin_users_path(filter: "wop"), { item_active: active_when(params[:filter] == 'wop'), class: 'gl-border-0!' } do
= s_('AdminUsers|Without projects')
= gl_tab_counter_badge(limited_counter_with_delimiter(User.without_projects))
+ = gl_tab_link_to admin_users_path(filter: "trusted"), { item_active: active_when(params[:filter] == 'trusted'), class: 'gl-border-0!' } do
+ = s_('AdminUsers|Trusted')
+ = gl_tab_counter_badge(limited_counter_with_delimiter(User.trusted))
.nav-controls
= render_if_exists 'admin/users/admin_email_users'
= render_if_exists 'admin/users/admin_export_user_permissions'
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index 83f7d743755..a3be188854d 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -2,7 +2,7 @@
- if event.visible_to_user?(current_user)
.event-item
- .event-item-timestamp
+ .event-item-timestamp.gl-font-sm
#{time_ago_with_tooltip(event.created_at)}
- if event.wiki_page?
diff --git a/app/views/organizations/organizations/users.html.haml b/app/views/organizations/organizations/users.html.haml
index a01c5f5045e..5fb9d786e0b 100644
--- a/app/views/organizations/organizations/users.html.haml
+++ b/app/views/organizations/organizations/users.html.haml
@@ -1 +1,4 @@
- page_title _('Users')
+
+#js-organizations-users{ data: organization_user_app_data(@organization) }
+