Commit 6ede90f5 authored by 🤖 GitLab Bot 🤖's avatar 🤖 GitLab Bot 🤖

Add latest changes from gitlab-org/[email protected]

parent b8e30b44
......@@ -283,6 +283,7 @@ module ApplicationSettingsHelper
:unique_ips_limit_enabled,
:unique_ips_limit_per_user,
:unique_ips_limit_time_window,
:updating_name_disabled_for_users,
:usage_ping_enabled,
:instance_statistics_visibility_private,
:user_default_external,
......
......@@ -13,6 +13,11 @@ class UserPolicy < BasePolicy
desc "The user is blocked"
condition(:blocked_user, scope: :subject, score: 0) { @subject.blocked? }
condition(:updating_name_disabled_for_users) do
::Gitlab::CurrentSettings.current_application_settings
.updating_name_disabled_for_users
end
rule { ~restricted_public_level }.enable :read_user
rule { ~anonymous }.enable :read_user
......@@ -22,6 +27,8 @@ class UserPolicy < BasePolicy
enable :update_user_status
end
rule { can?(:update_user) & ( admin | ~updating_name_disabled_for_users ) }.enable :update_name
rule { default }.enable :read_user_profile
rule { (private_profile | blocked_user) & ~(user_is_self | admin) }.prevent :read_user_profile
end
......@@ -17,6 +17,8 @@ module Users
yield(@user) if block_given?
user_exists = @user.persisted?
discard_read_only_attributes
assign_attributes
assign_identity
......@@ -50,13 +52,28 @@ module Users
success
end
def assign_attributes
def discard_read_only_attributes
discard_synced_attributes
discard_name unless name_updatable?
end
def discard_synced_attributes
if (metadata = @user.user_synced_attributes_metadata)
read_only = metadata.read_only_attributes
params.reject! { |key, _| read_only.include?(key.to_sym) }
end
end
def discard_name
params.delete(:name)
end
def name_updatable?
can?(current_user, :update_name, @user)
end
def assign_attributes
@user.assign_attributes(params.except(*identity_attributes)) unless params.empty?
end
......
......@@ -51,6 +51,12 @@
= f.check_box :user_show_add_ssh_key_message, class: 'form-check-input'
= f.label :user_show_add_ssh_key_message, class: 'form-check-label' do
= _("Inform users without uploaded SSH keys that they can't push over SSH until one is added")
.form-group
= f.label :updating_name_disabled_for_users, _('User restrictions'), class: 'label-bold'
.form-check
= f.check_box :updating_name_disabled_for_users, class: 'form-check-input'
= f.label :updating_name_disabled_for_users, class: 'form-check-label' do
= _("Prevent users from changing their profile name")
= render_if_exists 'admin/application_settings/availability_on_namespace_setting', form: f
......
- if user.read_only_attribute?(:name)
= form.text_field :name, required: true, readonly: true, wrapper: { class: 'col-md-9 qa-full-name rspec-full-name' },
help: s_("Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you") % { provider_label: attribute_provider_label(:name) }
- elsif can?(current_user, :update_name, user)
= form.text_field :name, label: s_('Profiles|Full name'), required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name rspec-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you")
- else
= form.text_field :name, required: true, readonly: true, wrapper: { class: 'col-md-9 qa-full-name rspec-full-name' },
help: s_("Profiles|The ability to update your name has been disabled by your administrator.")
......@@ -88,11 +88,7 @@
= s_("Profiles|Some options are unavailable for LDAP accounts")
.col-lg-8
.row
- if @user.read_only_attribute?(:name)
= f.text_field :name, required: true, readonly: true, wrapper: { class: 'col-md-9 qa-full-name rspec-full-name' },
help: s_("Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you") % { provider_label: attribute_provider_label(:name) }
- else
= f.text_field :name, label: s_('Profiles|Full name'), required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name rspec-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you")
= render 'profiles/name', form: f, user: @user
= f.text_field :id, readonly: true, label: s_('Profiles|User ID'), wrapper: { class: 'col-md-3' }
= f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, { prompt: _('Select your role') }, required: true, class: 'input-md'
......
---
title: Allow admins to disable users ability to change profile name
merge_request: 21987
author:
type: added
---
title: Display location in the Security Project Dashboard
merge_request: 22376
author:
type: other
---
title: Update Mermaid to v8.4.5
merge_request: 22830
author:
type: fixed
# frozen_string_literal: true
class AddUpdatingNameDisabledForUsersToApplicationSettings < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default(:application_settings, :updating_name_disabled_for_users,
:boolean,
default: false,
allow_null: false)
end
def down
remove_column(:application_settings, :updating_name_disabled_for_users)
end
end
......@@ -364,6 +364,7 @@ ActiveRecord::Schema.define(version: 2020_01_08_233040) do
t.string "encrypted_slack_app_secret_iv", limit: 255
t.text "encrypted_slack_app_verification_token"
t.string "encrypted_slack_app_verification_token_iv", limit: 255
t.boolean "updating_name_disabled_for_users", default: false, null: false
t.index ["custom_project_templates_group_id"], name: "index_application_settings_on_custom_project_templates_group_id"
t.index ["file_template_project_id"], name: "index_application_settings_on_file_template_project_id"
t.index ["instance_administration_project_id"], name: "index_applicationsettings_on_instance_administration_project_id"
......
......@@ -116,3 +116,17 @@ Once a lifetime for personal access tokens is set, GitLab will:
- After three hours, revoke old tokens with no expiration date or with a lifetime longer than the
allowed lifetime. Three hours is given to allow administrators to change the allowed lifetime,
or remove it, before revocation takes place.
## Disabling user profile name changes **(CORE ONLY)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/24605) in GitLab 12.7.
To maintain integrity of user details in [Audit Events](../../../administration/audit_events.md), GitLab administrators can choose to disable a user's ability to change their profile name.
To do this:
1. Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**.
1. Check the **Prevent users from changing their profile name** checkbox.
NOTE: **Note:**
When this ability is disabled, GitLab administrators will still be able to update the name of any user in their instance via the [Admin UI](../index.md#administering-users) or the [API](../../../api/users.md#user-modification)
......@@ -142,6 +142,7 @@ module API
requires :sourcegraph_url, type: String, desc: 'The configured Sourcegraph instance URL'
end
optional :terminal_max_session_time, type: Integer, desc: 'Maximum time for web terminal websocket connection (in seconds). Set to 0 for unlimited time.'
optional :updating_name_disabled_for_users, type: Boolean, desc: 'Flag indicating if users are permitted to update their profile name'
optional :usage_ping_enabled, type: Boolean, desc: 'Every week GitLab will report license usage back to GitLab, Inc.'
optional :instance_statistics_visibility_private, type: Boolean, desc: 'When set to `true` Instance statistics will only be available to admins'
optional :local_markdown_version, type: Integer, desc: 'Local markdown version, increase this value when any cached markdown should be invalidated'
......
......@@ -13449,6 +13449,9 @@ msgstr ""
msgid "Prevent environment from auto-stopping"
msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
msgid "Preview"
msgstr ""
......@@ -13752,6 +13755,9 @@ msgstr ""
msgid "Profiles|Tell us about yourself in fewer than 250 characters"
msgstr ""
msgid "Profiles|The ability to update your name has been disabled by your administrator."
msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
......@@ -19932,6 +19938,9 @@ msgstr ""
msgid "User pipeline minutes were successfully reset."
msgstr ""
msgid "User restrictions"
msgstr ""
msgid "User settings"
msgstr ""
......
......@@ -102,6 +102,13 @@ describe Admin::ApplicationSettingsController do
expect(ApplicationSetting.current.minimum_password_length).to eq(10)
end
it 'updates updating_name_disabled_for_users setting' do
put :update, params: { application_setting: { updating_name_disabled_for_users: true } }
expect(response).to redirect_to(admin_application_settings_path)
expect(ApplicationSetting.current.updating_name_disabled_for_users).to eq(true)
end
context 'external policy classification settings' do
let(:settings) do
{
......
......@@ -257,6 +257,28 @@ describe Admin::UsersController do
end
describe 'POST update' do
context 'updating name' do
context 'when the ability to update their name is disabled for users' do
before do
stub_application_setting(updating_name_disabled_for_users: true)
end
it 'updates the name' do
params = {
id: user.to_param,
user: {
name: 'New Name'
}
}
put :update, params: params
expect(response).to redirect_to(admin_user_path(user))
expect(user.reload.name).to eq('New Name')
end
end
end
context 'when the password has changed' do
def update_password(user, password, password_confirmation = nil)
params = {
......
......@@ -81,6 +81,54 @@ describe ProfilesController, :request_store do
expect(ldap_user.location).to eq('City, Country')
end
context 'updating name' do
subject { put :update, params: { user: { name: 'New Name' } } }
context 'when the ability to update thier name is not disabled for users' do
before do
stub_application_setting(updating_name_disabled_for_users: false)
sign_in(user)
end
it 'updates the name' do
subject
expect(response.status).to eq(302)
expect(user.reload.name).to eq('New Name')
end
end
context 'when the ability to update their name is disabled for users' do
before do
stub_application_setting(updating_name_disabled_for_users: true)
end
context 'as a regular user' do
it 'does not update the name' do
sign_in(user)
subject
expect(response.status).to eq(302)
expect(user.reload.name).not_to eq('New Name')
end
end
context 'as an admin user' do
it 'updates the name' do
admin = create(:admin)
sign_in(admin)
subject
expect(response.status).to eq(302)
expect(admin.reload.name).to eq('New Name')
end
end
end
end
it 'allows setting a user status' do
sign_in(user)
......
......@@ -43,17 +43,17 @@ describe "User comments on issue", :js do
expect(page.find('pre code').text).to eq code_block_content
end
it "renders escaped HTML content in Mermaid" do
it "renders HTML content as text in Mermaid" do
html_content = "<img onerror=location=`javascript\\u003aalert\\u0028document.domain\\u0029` src=x>"
mermaid_content = "graph LR\n B-->D(#{html_content});"
escaped_content = CGI.escapeHTML(html_content).gsub('=', "&equals;")
comment = "```mermaid\n#{mermaid_content}\n```"
add_note(comment)
wait_for_requests
expect(page.find('svg.mermaid')).to have_content escaped_content
expect(page.find('svg.mermaid')).to have_content html_content
within('svg.mermaid') { expect(page).not_to have_selector('img') }
end
it 'opens autocomplete menu for quick actions and have `/label` first choice' do
......
......@@ -48,4 +48,36 @@ describe UserPolicy do
describe "updating a user" do
it_behaves_like 'changing a user', :update_user
end
describe "updating a user's name" do
context 'when the ability to update their name is not disabled for users' do
before do
stub_application_setting(updating_name_disabled_for_users: false)
end
it_behaves_like 'changing a user', :update_name
end
context 'when the ability to update their name is disabled for users' do
before do
stub_application_setting(updating_name_disabled_for_users: true)
end
context 'for a regular user' do
it { is_expected.not_to be_allowed(:update_name) }
end
context 'for a ghost user' do
let(:current_user) { create(:user, :ghost) }
it { is_expected.not_to be_allowed(:update_name) }
end
context 'for an admin user' do
let(:current_user) { create(:admin) }
it { is_expected.to be_allowed(:update_name) }
end
end
end
end
......@@ -136,6 +136,14 @@ describe API::Settings, 'Settings' do
expect(json_response['performance_bar_allowed_group_id']).to eq(group.id)
end
it "supports updating_name_disabled_for_users" do
put api("/application/settings", admin),
params: { updating_name_disabled_for_users: true }
expect(response).to have_gitlab_http_status(200)
expect(json_response['updating_name_disabled_for_users']).to eq(true)
end
it "supports legacy performance_bar_enabled" do
put api("/application/settings", admin),
params: {
......
......@@ -645,6 +645,21 @@ describe API::Users do
expect(response).to have_gitlab_http_status(200)
end
context 'updating name' do
context 'when the ability to update their name is disabled for users' do
before do
stub_application_setting(updating_name_disabled_for_users: true)
end
it 'updates the user with new name' do
put api("/users/#{user.id}", admin), params: { name: 'New Name' }
expect(response).to have_gitlab_http_status(200)
expect(json_response['name']).to eq('New Name')
end
end
end
it "updates user with new bio" do
put api("/users/#{user.id}", admin), params: { bio: 'new test bio' }
......
......@@ -6,11 +6,44 @@ describe Users::UpdateService do
let(:user) { create(:user) }
describe '#execute' do
it 'updates the name' do
result = update_user(user, name: 'New Name')
expect(result).to eq(status: :success)
expect(user.name).to eq('New Name')
context 'updating name' do
context 'when the ability to update their name is not disabled for users' do
before do
stub_application_setting(updating_name_disabled_for_users: false)
end
it 'updates the name' do
result = update_user(user, name: 'New Name')
expect(result).to eq(status: :success)
expect(user.name).to eq('New Name')
end
end
context 'when the ability to update their name is disabled for users' do
before do
stub_application_setting(updating_name_disabled_for_users: true)
end
context 'executing as a regular user' do
it 'does not update the name' do
result = update_user(user, name: 'New Name')
expect(result).to eq(status: :success)
expect(user.name).not_to eq('New Name')
end
end
context 'executing as an admin user' do
it 'updates the name' do
admin = create(:admin)
result = described_class.new(admin, { user: user, name: 'New Name' }).execute
expect(result).to eq(status: :success)
expect(user.name).to eq('New Name')
end
end
end
end
it 'updates time preferences' do
......
......@@ -3512,10 +3512,10 @@ [email protected]^4.13.0:
d3-voronoi "1.1.2"
d3-zoom "1.7.1"
[email protected]^5.12, [email protected]^5.7.0:
version "5.12.0"
resolved "https://registry.yarnpkg.com/d3/-/d3-5.12.0.tgz#0ddeac879c28c882317cd439b495290acd59ab61"
integrity sha512-flYVMoVuhPFHd9zVCe2BxIszUWqBcd5fvQGMNRmSiBrgdnh6Vlruh60RJQTouAK9xPbOB0plxMvBm4MoyODXNg==
[email protected]^5.14, [email protected]^5.7.0:
version "5.15.0"
resolved "https://registry.yarnpkg.com/d3/-/d3-5.15.0.tgz#ffd44958e6a3cb8a59a84429c45429b8bca5677a"
integrity sha512-C+E80SL2nLLtmykZ6klwYj5rPqB5nlfN5LdWEAVdWPppqTD8taoJi2PxLZjPeYT8FFRR2yucXq+kBlOnnvZeLg==
dependencies:
d3-array "1"
d3-axis "1"
......@@ -3549,22 +3549,23 @@ [email protected]^5.12, [email protected]^5.7.0:
d3-voronoi "1"
d3-zoom "1"
[email protected]/dagre-d3:
version "0.6.4-pre"
resolved "https://codeload.github.com/dagrejs/dagre-d3/tar.gz/e1a00e5cb518f5d2304a35647e024f31d178e55b"
[email protected]^0.6.4:
version "0.6.4"
resolved "https://registry.yarnpkg.com/dagre-d3/-/dagre-d3-0.6.4.tgz#0728d5ce7f177ca2337df141ceb60fbe6eeb7b29"
integrity sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==
dependencies:
d3 "^5.12"
dagre "^0.8.4"
graphlib "^2.1.7"
d3 "^5.14"
dagre "^0.8.5"
graphlib "^2.1.8"
lodash "^4.17.15"
[email protected]^0.8.4:
version "0.8.4"
resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.4.tgz#26b9fb8f7bdc60c6110a0458c375261836786061"
integrity sha512-Dj0csFDrWYKdavwROb9FccHfTC4fJbyF/oJdL9LNZJ8WUvl968P6PAKEriGqfbdArVJEmmfA+UyumgWEwcHU6A==
[email protected]^0.8.4, [email protected]^0.8.5:
version "0.8.5"
resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee"
integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==
dependencies:
graphlib "^2.1.7"
lodash "^4.17.4"
graphlib "^2.1.8"
lodash "^4.17.15"
[email protected]^1.12.0:
version "1.14.1"
......@@ -5321,12 +5322,12 @@ [email protected]^4.1.11, [email protected]^4.1.15, [email protected]^4.1.2, [email protected]^4.1.6
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
[email protected]^2.1.7:
version "2.1.7"
resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.7.tgz#b6a69f9f44bd9de3963ce6804a2fc9e73d86aecc"
integrity sha512-TyI9jIy2J4j0qgPmOOrHTCtpPqJGN/aurBwc6ZT+bRii+di1I+Wv3obRhVrmBEXet+qkMaEX67dXrwsd3QQM6w==
[email protected]^2.1.7, [email protected]^2.1.8:
version "2.1.8"
resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da"
integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==
dependencies:
lodash "^4.17.5"
lodash "^4.17.15"
[email protected]^2.10.0:
version "2.10.0"
......@@ -7628,22 +7629,21 @@ [email protected]^1.2.3:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5"
integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==
[email protected]^8.4.2:
version "8.4.2"
resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.4.2.tgz#91d3d8e9541e72eed7a78d0e882db11564fab3bb"
integrity sha512-vYSCP2u4XkOnjliWz/QIYwvzF/znQAq22vWJJ3YV40SnwV2JQyHblnwwNYXCprkXw7XfwBKDpSNaJ3HP4WfnZw==
[email protected]^8.4.5:
version "8.4.5"
resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.4.5.tgz#48d5722cbc72be2ad01002795835d7ca1b48e000"
integrity sha512-oJWgZBtT2rvAdmqHvKjDwb3tOut1+ksfgDdZrVhhNcdzNibzGPjCsmMPpVXjkFYzKZCVunIbAkfxltSuaGIhaw==
dependencies:
"@braintree/sanitize-url" "^3.1.0"
crypto-random-string "^3.0.1"
d3 "^5.7.0"
dagre "^0.8.4"
dagre-d3 dagrejs/dagre-d3
dagre-d3 "^0.6.4"
graphlib "^2.1.7"
he "^1.2.0"
lodash "^4.17.11"
minify "^4.1.1"
moment-mini "^2.22.1"
prettier "^1.18.2"
scope-css "^1.2.1"
[email protected]~1.1.2:
......@@ -8984,7 +8984,7 @@ [email protected]:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.3.tgz#8c62168453badef702f34b45b6ee899574a6a65d"
integrity sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw==
[email protected], [email protected]^1.18.2:
[email protected]:
version "1.18.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment