gitlab-org--gitlab-foss/spec/models/ability_spec.rb

304 lines
9.8 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
describe Ability do
context 'using a nil subject' do
it 'has no permissions' do
expect(described_class.policy_for(nil, nil)).to be_banned
end
end
describe '.users_that_can_read_project' do
context 'using a public project' do
it 'returns all the users' do
project = create(:project, :public)
user = build(:user)
expect(described_class.users_that_can_read_project([user], project))
.to eq([user])
end
end
context 'using an internal project' do
let(:project) { create(:project, :internal) }
it 'returns users that are administrators' do
user = build(:user, admin: true)
expect(described_class.users_that_can_read_project([user], project))
.to eq([user])
end
it 'returns internal users while skipping external users' do
user1 = build(:user)
user2 = build(:user, external: true)
users = [user1, user2]
expect(described_class.users_that_can_read_project(users, project))
.to eq([user1])
end
it 'returns external users if they are the project owner' do
user1 = build(:user, external: true)
user2 = build(:user, external: true)
users = [user1, user2]
expect(project).to receive(:owner).at_least(:once).and_return(user1)
expect(described_class.users_that_can_read_project(users, project))
.to eq([user1])
end
it 'returns external users if they are project members' do
user1 = build(:user, external: true)
user2 = build(:user, external: true)
users = [user1, user2]
expect(project.team).to receive(:members).at_least(:once).and_return([user1])
expect(described_class.users_that_can_read_project(users, project))
.to eq([user1])
end
it 'returns an empty Array if all users are external users without access' do
user1 = build(:user, external: true)
user2 = build(:user, external: true)
users = [user1, user2]
expect(described_class.users_that_can_read_project(users, project))
.to eq([])
end
end
context 'using a private project' do
let(:project) { create(:project, :private) }
it 'returns users that are administrators' do
user = build(:user, admin: true)
expect(described_class.users_that_can_read_project([user], project))
.to eq([user])
end
it 'returns external users if they are the project owner' do
user1 = build(:user, external: true)
user2 = build(:user, external: true)
users = [user1, user2]
expect(project).to receive(:owner).at_least(:once).and_return(user1)
expect(described_class.users_that_can_read_project(users, project))
.to eq([user1])
end
it 'returns external users if they are project members' do
user1 = build(:user, external: true)
user2 = build(:user, external: true)
users = [user1, user2]
expect(project.team).to receive(:members).at_least(:once).and_return([user1])
expect(described_class.users_that_can_read_project(users, project))
.to eq([user1])
end
it 'returns an empty Array if all users are internal users without access' do
user1 = build(:user)
user2 = build(:user)
users = [user1, user2]
expect(described_class.users_that_can_read_project(users, project))
.to eq([])
end
it 'returns an empty Array if all users are external users without access' do
user1 = build(:user, external: true)
user2 = build(:user, external: true)
users = [user1, user2]
expect(described_class.users_that_can_read_project(users, project))
.to eq([])
end
end
end
describe '.users_that_can_read_personal_snippet' do
def users_for_snippet(snippet)
described_class.users_that_can_read_personal_snippet(users, snippet)
end
let(:users) { create_list(:user, 3) }
let(:author) { users[0] }
it 'private snippet is readable only by its author' do
snippet = create(:personal_snippet, :private, author: author)
expect(users_for_snippet(snippet)).to match_array([author])
end
it 'public snippet is readable by all users' do
snippet = create(:personal_snippet, :public, author: author)
expect(users_for_snippet(snippet)).to match_array(users)
end
end
describe '.merge_requests_readable_by_user' do
context 'with an admin' do
it 'returns all merge requests' do
user = build(:user, admin: true)
merge_request = build(:merge_request)
expect(described_class.merge_requests_readable_by_user([merge_request], user))
.to eq([merge_request])
end
end
context 'without a user' do
it 'returns merge_requests that are publicly visible' do
hidden_merge_request = build(:merge_request)
visible_merge_request = build(:merge_request, source_project: build(:project, :public))
merge_requests = described_class
.merge_requests_readable_by_user([hidden_merge_request, visible_merge_request])
expect(merge_requests).to eq([visible_merge_request])
end
end
context 'with a user' do
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:merge_request) { create(:merge_request, source_project: project) }
let(:cross_project_merge_request) do
create(:merge_request, source_project: create(:project, :public))
end
let(:other_merge_request) { create(:merge_request) }
let(:all_merge_requests) do
[merge_request, cross_project_merge_request, other_merge_request]
end
subject(:readable_merge_requests) do
described_class.merge_requests_readable_by_user(all_merge_requests, user)
end
before do
project.add_developer(user)
end
it 'returns projects visible to the user' do
expect(readable_merge_requests).to contain_exactly(merge_request, cross_project_merge_request)
end
context 'when a user cannot read cross project and a filter is passed' do
before do
allow(described_class).to receive(:allowed?).and_call_original
expect(described_class).to receive(:allowed?).with(user, :read_cross_project) { false }
end
subject(:readable_merge_requests) do
read_cross_project_filter = -> (merge_requests) do
merge_requests.select { |mr| mr.source_project == project }
end
described_class.merge_requests_readable_by_user(
all_merge_requests, user,
filters: { read_cross_project: read_cross_project_filter }
)
end
it 'returns only MRs of the specified project without checking access on others' do
expect(described_class).not_to receive(:allowed?).with(user, :read_merge_request, cross_project_merge_request)
expect(readable_merge_requests).to contain_exactly(merge_request)
end
end
end
end
describe '.issues_readable_by_user' do
context 'with an admin user' do
it 'returns all given issues' do
user = build(:user, admin: true)
issue = build(:issue)
expect(described_class.issues_readable_by_user([issue], user))
.to eq([issue])
end
end
context 'with a regular user' do
it 'returns the issues readable by the user' do
user = build(:user)
issue = build(:issue)
expect(issue).to receive(:readable_by?).with(user).and_return(true)
expect(described_class.issues_readable_by_user([issue], user))
.to eq([issue])
end
it 'returns an empty Array when no issues are readable' do
user = build(:user)
issue = build(:issue)
expect(issue).to receive(:readable_by?).with(user).and_return(false)
expect(described_class.issues_readable_by_user([issue], user)).to eq([])
end
end
context 'without a regular user' do
it 'returns issues that are publicly visible' do
hidden_issue = build(:issue)
visible_issue = build(:issue)
expect(hidden_issue).to receive(:publicly_visible?).and_return(false)
expect(visible_issue).to receive(:publicly_visible?).and_return(true)
issues = described_class
.issues_readable_by_user([hidden_issue, visible_issue])
expect(issues).to eq([visible_issue])
end
end
context 'when the user cannot read cross project' do
let(:user) { create(:user) }
let(:issue) { create(:issue) }
let(:other_project_issue) { create(:issue) }
let(:project) { issue.project }
before do
project.add_developer(user)
allow(described_class).to receive(:allowed?).and_call_original
allow(described_class).to receive(:allowed?).with(user, :read_cross_project, any_args) { false }
end
it 'excludes issues from other projects whithout checking separatly when passing a scope' do
expect(described_class).not_to receive(:allowed?).with(user, :read_issue, other_project_issue)
filters = { read_cross_project: -> (issues) { issues.where(project: project) } }
result = described_class.issues_readable_by_user(Issue.all, user, filters: filters)
expect(result).to contain_exactly(issue)
end
end
end
describe '.project_disabled_features_rules' do
let(:project) { create(:project, :wiki_disabled) }
subject { described_class.policy_for(project.owner, project) }
context 'wiki named abilities' do
it 'disables wiki abilities if the project has no wiki' do
expect(subject).not_to be_allowed(:read_wiki)
expect(subject).not_to be_allowed(:create_wiki)
expect(subject).not_to be_allowed(:update_wiki)
expect(subject).not_to be_allowed(:admin_wiki)
end
end
end
end