Commit ea86eb57 authored by Serena Fang's avatar Serena Fang

Reset feature branch

Reset hard master and create banned user table

Add ban service spec

Add specs for banned user and ban service

Add unban service file

BannedUser object gets created and destroyed

Add unban service specs

Add specs for unban user

Run rake translate

Add aggregate failures

Update state machine transition

Update ban and unban specs

Remove enable admin mode

Remove unneeded method

Remove unneeded method

Add specs for ban and unban

DRY ban and unban service

Consolidate ban and unban user service
into one file

DRY spec shared example

Create Users BaseService

Need to fix specs

Fix Base Service

Update specs

Use error instead of service error

Change service error to permission error

Rename Users BaseService

DRY ban and unban service

Run rubocop linter

Run bin rake translate

Ban and unban user service

Move execute to base service

Run rubocop linter

Rename user ban spec

Run translation script

Use action method instead of override initialize

Move some conceptual material to main page and other minor improvements

Add hidden column to issues table

Does not allow non admin user
to read the issue

Rebase db structure with master

Add hidden only issues scope

Exclude hidden issues from issues finder

If user is non admin, do not show hidden issues

Add issues finder specs

Update issue scopes

Also fix specs

Add ampersand to issue policy

Revert unwanted rebase changes

Add migration files

Migration files got overwritten by rebase

Run rubocop linter

Run bin rake translate

Ban and unban user service

Move execute to base service

Run rubocop linter

Rename user ban spec

Run translation script

Use action method instead of override initialize

Move some conceptual material to main page and other minor improvements

Add hidden column to issues table

Does not allow non admin user
to read the issue

Rebase db structure with master

Add hidden only issues scope

Exclude hidden issues from issues finder

If user is non admin, do not show hidden issues

Add issues finder specs

Update issue scopes

Also fix specs

Add ampersand to issue policy

Revert unwanted rebase changes

Add migration files

Migration files got overwritten by rebase

Run rubocop linter

Run bin rake translate

Ban and unban user service

Move execute to base service

Run rubocop linter

Rename user ban spec

Run translation script

Use action method instead of override initialize

Move some conceptual material to main page and other minor improvements

Add hidden column to issues table

Does not allow non admin user
to read the issue

Rebase db structure with master

Add hidden only issues scope

Exclude hidden issues from issues finder

If user is non admin, do not show hidden issues

Add issues finder specs

Update issue scopes

Also fix specs

Add ampersand to issue policy

Revert unwanted rebase changes

Add migration files

Migration files got overwritten by rebase

Remove bad rebase changes

Some files got left over, remove them

Remove bad rebase changes

Some files got left over, remove them

Run rails migration

Remove issue hidden attribute

Also update ban copy

Add issue specs

Add specs for issue model

Use single quotes

Add hidden issue to user moderation doc

Run rubocop linter

Run bin rake translate

Ban and unban user service

Move execute to base service

Run rubocop linter

Rename user ban spec

Run translation script

Use action method instead of override initialize

Move some conceptual material to main page and other minor improvements

Add hidden column to issues table

Does not allow non admin user
to read the issue

Rebase db structure with master

Add hidden only issues scope

Exclude hidden issues from issues finder

If user is non admin, do not show hidden issues

Add issues finder specs

Update issue scopes

Also fix specs

Add ampersand to issue policy

Revert unwanted rebase changes

Add migration files

Migration files got overwritten by rebase

Remove bad rebase changes

Some files got left over, remove them

Remove bad rebase changes

Some files got left over, remove them

Run rails migration

Remove issue hidden attribute

Also update ban copy

Add issue specs

Add specs for issue model

Use single quotes

Add hidden issue to user moderation doc

Use safe operator

Alias author banned to hidden

Fix failing specs

Reset feature branch

Reset hard master and create banned user table

Add ban service spec

Add specs for banned user and ban service

Add unban service file

BannedUser object gets created and destroyed

Add unban service specs

Add specs for unban user

Run rake translate

Add aggregate failures

Update state machine transition

Update ban and unban specs

Remove enable admin mode

Remove unneeded method

Remove unneeded method

Add specs for ban and unban

DRY ban and unban service

Consolidate ban and unban user service
into one file

DRY spec shared example

Create Users BaseService

Need to fix specs

Fix Base Service

Update specs

Use error instead of service error

Change service error to permission error

Rename Users BaseService

DRY ban and unban service

Run rubocop linter

Run bin rake translate

Ban and unban user service

Move execute to base service

Run rubocop linter

Rename user ban spec

Run translation script

Use action method instead of override initialize

Move some conceptual material to main page and other minor improvements

Add hidden column to issues table

Does not allow non admin user
to read the issue

Rebase db structure with master

Add hidden only issues scope

Exclude hidden issues from issues finder

If user is non admin, do not show hidden issues

Add issues finder specs

Update issue scopes

Also fix specs

Add ampersand to issue policy

Revert unwanted rebase changes

Add migration files

Migration files got overwritten by rebase

Run rubocop linter

Run bin rake translate

Ban and unban user service

Move execute to base service

Run rubocop linter

Rename user ban spec

Run translation script

Use action method instead of override initialize

Move some conceptual material to main page and other minor improvements

Add hidden column to issues table

Does not allow non admin user
to read the issue

Rebase db structure with master

Add hidden only issues scope

Exclude hidden issues from issues finder

If user is non admin, do not show hidden issues

Add issues finder specs

Update issue scopes

Also fix specs

Add ampersand to issue policy

Revert unwanted rebase changes

Add migration files

Migration files got overwritten by rebase

Run rubocop linter

Run bin rake translate

Ban and unban user service

Move execute to base service

Run rubocop linter

Rename user ban spec

Run translation script

Use action method instead of override initialize

Move some conceptual material to main page and other minor improvements

Add hidden column to issues table

Does not allow non admin user
to read the issue

Rebase db structure with master

Add hidden only issues scope

Exclude hidden issues from issues finder

If user is non admin, do not show hidden issues

Add issues finder specs

Update issue scopes

Also fix specs

Add ampersand to issue policy

Revert unwanted rebase changes

Add migration files

Migration files got overwritten by rebase

Remove bad rebase changes

Some files got left over, remove them

Remove bad rebase changes

Some files got left over, remove them

Run rails migration

Remove issue hidden attribute

Also update ban copy

Add issue specs

Add specs for issue model

Use single quotes

Add hidden issue to user moderation doc

Run rubocop linter

Run bin rake translate

Ban and unban user service

Move execute to base service

Run rubocop linter

Rename user ban spec

Run translation script

Use action method instead of override initialize

Move some conceptual material to main page and other minor improvements

Add hidden column to issues table

Does not allow non admin user
to read the issue

Rebase db structure with master

Add hidden only issues scope

Exclude hidden issues from issues finder

If user is non admin, do not show hidden issues

Add issues finder specs

Update issue scopes

Also fix specs

Add ampersand to issue policy

Revert unwanted rebase changes

Add migration files

Migration files got overwritten by rebase

Remove bad rebase changes

Some files got left over, remove them

Remove bad rebase changes

Some files got left over, remove them

Run rails migration

Remove issue hidden attribute

Also update ban copy

Add issue specs

Add specs for issue model

Use single quotes

Add hidden issue to user moderation doc

Fix failing specs

New way of fixing pipeline failures

Change query limit

Update issue spec

Address MR review comments

Apply MR review suggestions

Add specs, fix docs

FF check for banned users

Run rake translate

Add spec to issues spec

Apply maintainer suggestions
parent d8f1a157
......@@ -6,10 +6,11 @@ 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 banned, users:')}</p>
<p>${s__('AdminUsers|When banned:')}</p>
<ul>
<li>${s__("AdminUsers|Can't log in.")}</li>
<li>${s__("AdminUsers|Can't access Git repositories.")}</li>
<li>${s__("AdminUsers|The user can't log in.")}</li>
<li>${s__("AdminUsers|The user can't access git repositories.")}</li>
<li>${s__('AdminUsers|Issues authored by this user are hidden from other users.')}</li>
</ul>
<p>${s__('AdminUsers|You can unban their account in the future. Their data remains intact.')}</p>
<p>${sprintf(
......
......@@ -47,17 +47,22 @@ class IssuesFinder < IssuableFinder
# rubocop: disable CodeReuse/ActiveRecord
def with_confidentiality_access_check
return Issue.all if params.user_can_see_all_confidential_issues?
return Issue.all if params.user_can_see_all_issues?
# Only admins can see hidden issues, so for non-admins, we filter out any hidden issues
issues = Issue.without_hidden
return issues.all if params.user_can_see_all_confidential_issues?
# If already filtering by assignee we can skip confidentiality since a user
# can always see confidential issues assigned to them. This is just an
# optimization since a very common usecase of this Finder is to load the
# count of issues assigned to the user for the header bar.
return Issue.all if current_user && assignee_filter.includes_user?(current_user)
return issues.all if current_user && assignee_filter.includes_user?(current_user)
return Issue.where('issues.confidential IS NOT TRUE') if params.user_cannot_see_confidential_issues?
return issues.where('issues.confidential IS NOT TRUE') if params.user_cannot_see_confidential_issues?
Issue.where('
issues.where('
issues.confidential IS NOT TRUE
OR (issues.confidential = TRUE
AND (issues.author_id = :user_id
......
......@@ -32,7 +32,7 @@ class IssuesFinder
if parent
Ability.allowed?(current_user, :read_confidential_issues, parent)
else
Ability.allowed?(current_user, :read_all_resources)
user_can_see_all_issues?
end
end
end
......@@ -42,6 +42,12 @@ class IssuesFinder
current_user.blank?
end
def user_can_see_all_issues?
strong_memoize(:user_can_see_all_issues) do
Ability.allowed?(current_user, :read_all_resources)
end
end
end
end
......
......@@ -37,7 +37,8 @@ module Resolvers
[
{
project: [:project_feature]
}
},
:author
]
end
......
......@@ -52,6 +52,10 @@ module IssuesHelper
sprite_icon('eye-slash', css_class: 'gl-vertical-align-text-bottom') if issue.confidential?
end
def hidden_issue_icon(issue)
sprite_icon('spam', css_class: 'gl-vertical-align-text-bottom') if issue.hidden?
end
def award_user_list(awards, current_user, limit: 10)
names = awards.map do |award|
award.user == current_user ? 'You' : award.user.name
......
......@@ -135,6 +135,15 @@ class Issue < ApplicationRecord
scope :public_only, -> { where(confidential: false) }
scope :confidential_only, -> { where(confidential: true) }
scope :without_hidden, -> {
if Feature.enabled?(:ban_user_feature_flag)
where(id: joins('LEFT JOIN banned_users ON banned_users.user_id = issues.author_id WHERE banned_users.user_id IS NULL')
.select('issues.id'))
else
all
end
}
scope :counts_by_state, -> { reorder(nil).group(:state_id).count }
scope :service_desk, -> { where(author: ::User.support_bot) }
......@@ -556,6 +565,8 @@ class Issue < ApplicationRecord
true
elsif confidential? && !assignee_or_author?(user)
project.team.member?(user, Gitlab::Access::REPORTER)
elsif hidden?
false
else
project.public? ||
project.internal? && !user.external? ||
......@@ -563,6 +574,10 @@ class Issue < ApplicationRecord
end
end
def hidden?
author&.banned?
end
private
def spammable_attribute_changed?
......@@ -590,7 +605,7 @@ class Issue < ApplicationRecord
# Returns `true` if this Issue is visible to everybody.
def publicly_visible?
project.public? && !confidential? && !::Gitlab::ExternalAuthorization.enabled?
project.public? && !confidential? && !hidden? && !::Gitlab::ExternalAuthorization.enabled?
end
def expire_etag_cache
......
......@@ -15,6 +15,9 @@ class IssuePolicy < IssuablePolicy
desc "Issue is confidential"
condition(:confidential, scope: :subject) { @subject.confidential? }
desc "Issue is hidden"
condition(:hidden, scope: :subject) { @subject.hidden? }
desc "Issue is persisted"
condition(:persisted, scope: :subject) { @subject.persisted? }
......@@ -23,6 +26,10 @@ class IssuePolicy < IssuablePolicy
prevent :read_issue_iid
end
rule { hidden & ~admin }.policy do
prevent :read_issue
end
rule { ~can?(:read_issue) }.prevent :create_note
rule { locked }.policy do
......
......@@ -12,6 +12,9 @@
- if issue.confidential?
%span.has-tooltip{ title: _('Confidential') }
= confidential_icon(issue)
- if Feature.enabled?(:ban_user_feature_flag) && issue.hidden?
%span.has-tooltip{ title: _('This issue is hidden because its author has been banned') }
= hidden_issue_icon(issue)
= link_to issue.title, issue_path(issue)
= render_if_exists 'projects/issues/subepic_flag', issue: issue
- if issue.tasks?
......
......@@ -195,12 +195,12 @@ Users can also be activated using the [GitLab API](../../api/users.md#activate-u
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327353) in GitLab 14.2.
GitLab administrators can ban and unban users. The banned user's issues are still displayed. Hiding
a banned user's issues is a [work in progress](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66687).
GitLab administrators can ban and unban users. Banned users are blocked, and their issues are hidden.
The banned user's comments are still displayed. Hiding a banned user's comments is [tracked in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/327356).
### Ban a user
To completely block a user, administrators can choose to ban the user.
To block a user and hide their contributions, administrators can ban the user.
Users can be banned using the Admin Area. To do this:
......
......@@ -237,9 +237,11 @@ RSpec.describe IssuesFinder do
let_it_be(:guest) { create(:user) }
let_it_be(:authorized_user) { create(:user) }
let_it_be(:banned_user) { create(:user, :banned) }
let_it_be(:project) { create(:project, namespace: authorized_user.namespace) }
let_it_be(:public_issue) { create(:issue, project: project) }
let_it_be(:confidential_issue) { create(:issue, project: project, confidential: true) }
let_it_be(:hidden_issue) { create(:issue, project: project, author: banned_user) }
context 'when no project filter is given' do
let(:params) { {} }
......@@ -250,7 +252,7 @@ RSpec.describe IssuesFinder do
subject { described_class.new(auditor_user, params).with_confidentiality_access_check }
it 'returns all issues' do
expect(subject).to include(public_issue, confidential_issue)
expect(subject).to include(public_issue, confidential_issue, hidden_issue)
end
end
end
......@@ -264,7 +266,7 @@ RSpec.describe IssuesFinder do
subject { described_class.new(auditor_user, params).with_confidentiality_access_check }
it 'returns all issues' do
expect(subject).to include(public_issue, confidential_issue)
expect(subject).to include(public_issue, confidential_issue, hidden_issue)
end
end
end
......
......@@ -2563,12 +2563,6 @@ msgstr ""
msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
msgid "AdminUsers|Can't access Git repositories."
msgstr ""
msgid "AdminUsers|Can't log in."
msgstr ""
msgid "AdminUsers|Cannot sign in or access instance information"
msgstr ""
......@@ -2635,6 +2629,9 @@ msgstr ""
msgid "AdminUsers|Is using seat"
msgstr ""
msgid "AdminUsers|Issues authored by this user are hidden from other users."
msgstr ""
msgid "AdminUsers|It's you!"
msgstr ""
......@@ -2698,6 +2695,12 @@ msgstr ""
msgid "AdminUsers|Sort by"
msgstr ""
msgid "AdminUsers|The user can't access git repositories."
msgstr ""
msgid "AdminUsers|The user can't log in."
msgstr ""
msgid "AdminUsers|The user will be logged out"
msgstr ""
......@@ -2764,7 +2767,7 @@ msgstr ""
msgid "AdminUsers|What does this mean?"
msgstr ""
msgid "AdminUsers|When banned, users:"
msgid "AdminUsers|When banned:"
msgstr ""
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
......@@ -33913,6 +33916,9 @@ msgstr ""
msgid "This issue is currently blocked by the following issues:"
msgstr ""
msgid "This issue is hidden because its author has been banned"
msgstr ""
msgid "This issue is in a child epic of the filtered epic"
msgstr ""
......
This diff is collapsed.
......@@ -86,9 +86,9 @@ RSpec.describe Mutations::DesignManagement::Delete do
end
end
it 'runs no more than 28 queries' do
it 'runs no more than 29 queries' do
filenames.each(&:present?) # ignore setup
# Queries: as of 2019-08-28
# Queries: as of 2021-07-22
# -------------
# 01. routing query
# 02. find project by id
......@@ -100,25 +100,26 @@ RSpec.describe Mutations::DesignManagement::Delete do
# 09. find namespace by id
# 10. find group namespace by id
# 11. project.authorizations for user (same query as 5)
# 12. project.project_features (same query as 3)
# 13. project.authorizations for user (same query as 5)
# 14. current designs by filename and issue
# 15, 16 project.authorizations for user (same query as 5)
# 17. find route by id and source_type
# 12. find user by id
# 13. project.project_features (same query as 3)
# 14. project.authorizations for user (same query as 5)
# 15. current designs by filename and issue
# 16, 17 project.authorizations for user (same query as 5)
# 18. find route by id and source_type
# ------------- our queries are below:
# 18. start transaction 1
# 19. start transaction 2
# 20. find version by sha and issue
# 21. exists version with sha and issue?
# 22. leave transaction 2
# 23. create version with sha and issue
# 24. create design-version links
# 25. validate version.actions.present?
# 26. validate version.issue.present?
# 27. validate version.sha is unique
# 28. leave transaction 1
# 19. start transaction 1
# 20. start transaction 2
# 21. find version by sha and issue
# 22. exists version with sha and issue?
# 23. leave transaction 2
# 24. create version with sha and issue
# 25. create design-version links
# 26. validate version.actions.present?
# 27. validate version.issue.present?
# 28. validate version.sha is unique
# 29. leave transaction 1
#
expect { run_mutation }.not_to exceed_query_limit(28)
expect { run_mutation }.not_to exceed_query_limit(29)
end
end
......
......@@ -393,13 +393,13 @@ RSpec.describe Resolvers::IssuesResolver do
end
it 'finds a specific issue with iid', :request_store do
result = batch_sync(max_queries: 4) { resolve_issues(iid: issue1.iid).to_a }
result = batch_sync(max_queries: 5) { resolve_issues(iid: issue1.iid).to_a }
expect(result).to contain_exactly(issue1)
end
it 'batches queries that only include IIDs', :request_store do
result = batch_sync(max_queries: 4) do
result = batch_sync(max_queries: 5) do
[issue1, issue2]
.map { |issue| resolve_issues(iid: issue.iid.to_s) }
.flat_map(&:to_a)
......@@ -409,7 +409,7 @@ RSpec.describe Resolvers::IssuesResolver do
end
it 'finds a specific issue with iids', :request_store do
result = batch_sync(max_queries: 4) do
result = batch_sync(max_queries: 5) do
resolve_issues(iids: [issue1.iid]).to_a
end
......
......@@ -796,17 +796,47 @@ RSpec.describe Issue do
end
end
shared_examples 'hidden issue readable by user' do
before do
issue.author.ban!
end
specify do
is_expected.to eq(true)
end
after do
issue.author.activate!
end
end
shared_examples 'hidden issue not readable by user' do
before do
issue.author.ban!
end
specify do
is_expected.to eq(false)
end
after do
issue.author.activate!
end
end
context 'with an admin user' do
let(:user) { build(:admin) }
context 'when admin mode is enabled', :enable_admin_mode do
it_behaves_like 'issue readable by user'
it_behaves_like 'confidential issue readable by user'
it_behaves_like 'hidden issue readable by user'
end
context 'when admin mode is disabled' do
it_behaves_like 'issue not readable by user'
it_behaves_like 'confidential issue not readable by user'
it_behaves_like 'hidden issue not readable by user'
end
end
......@@ -817,6 +847,7 @@ RSpec.describe Issue do
it_behaves_like 'issue readable by user'
it_behaves_like 'confidential issue readable by user'
it_behaves_like 'hidden issue not readable by user'
end
context 'with a reporter user' do
......@@ -826,6 +857,7 @@ RSpec.describe Issue do
it_behaves_like 'issue readable by user'
it_behaves_like 'confidential issue readable by user'
it_behaves_like 'hidden issue not readable by user'
end
context 'with a guest user' do
......@@ -835,6 +867,7 @@ RSpec.describe Issue do
it_behaves_like 'issue readable by user'
it_behaves_like 'confidential issue not readable by user'
it_behaves_like 'hidden issue not readable by user'
context 'when user is an assignee' do
before do
......@@ -843,6 +876,7 @@ RSpec.describe Issue do
it_behaves_like 'issue readable by user'
it_behaves_like 'confidential issue readable by user'
it_behaves_like 'hidden issue not readable by user'
end
context 'when user is the author' do
......@@ -852,6 +886,7 @@ RSpec.describe Issue do
it_behaves_like 'issue readable by user'
it_behaves_like 'confidential issue readable by user'
it_behaves_like 'hidden issue not readable by user'
end
end
......@@ -861,6 +896,7 @@ RSpec.describe Issue do
it_behaves_like 'issue readable by user'
it_behaves_like 'confidential issue not readable by user'
it_behaves_like 'hidden issue not readable by user'
end
context 'using an internal project' do
......@@ -873,6 +909,7 @@ RSpec.describe Issue do
it_behaves_like 'issue readable by user'
it_behaves_like 'confidential issue not readable by user'
it_behaves_like 'hidden issue not readable by user'
end
context 'using an external user' do
......@@ -882,6 +919,7 @@ RSpec.describe Issue do
it_behaves_like 'issue not readable by user'
it_behaves_like 'confidential issue not readable by user'
it_behaves_like 'hidden issue not readable by user'
end
end
......@@ -892,6 +930,7 @@ RSpec.describe Issue do
it_behaves_like 'issue not readable by user'
it_behaves_like 'confidential issue not readable by user'
it_behaves_like 'hidden issue not readable by user'
end
end
......@@ -1160,6 +1199,26 @@ RSpec.describe Issue do
end
end
describe '.without_hidden' do
let_it_be(:banned_user) { create(:user, :banned) }
let_it_be(:public_issue) { create(:issue, project: reusable_project) }
let_it_be(:hidden_issue) { create(:issue, project: reusable_project, author: banned_user) }
it 'only returns without_hidden issues' do
expect(described_class.without_hidden).to eq([public_issue])
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(ban_user_feature_flag: false)
end
it 'returns public and hidden issues' do
expect(described_class.without_hidden).to eq([public_issue, hidden_issue])
end
end
end
describe '.by_project_id_and_iid' do
let_it_be(:issue_a) { create(:issue, project: reusable_project) }
let_it_be(:issue_b) { create(:issue, iid: issue_a.iid) }
......
......@@ -360,6 +360,21 @@ RSpec.describe IssuePolicy do
expect(permissions(assignee, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata)
end
end
context 'with a hidden issue' do
let(:user) { create(:user) }
let(:banned_user) { create(:user, :banned) }
let(:admin) { create(:user, :admin)}
let(:hidden_issue) { create(:issue, project: project, author: banned_user) }
it 'does not allow non-admin user to read the issue' do
expect(permissions(user, hidden_issue)).not_to be_allowed(:read_issue)
end
it 'allows admin to read the issue', :enable_admin_mode do
expect(permissions(admin, hidden_issue)).to be_allowed(:read_issue)
end
end
end
context 'with external authorization enabled' do
......
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