gitlab-org--gitlab-foss/spec/models/ability_spec.rb
Francisco Javier López 740f07b1ec
Fixed bug when external wiki is enabled
When the external wiki is enabled, the internal wiki link is replaced
by the external wiki url. But the internal wiki is still accessible.
In this change the external wiki will have its own tab in the sidebar
and only if the services are disabled the tab (and access rights)
will not be displayed.
2019-01-31 16:51:53 +01:00

308 lines
10 KiB
Ruby

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 'internal snippet is readable by all registered users' do
snippet = create(:personal_snippet, :public, author: author)
expect(users_for_snippet(snippet)).to match_array(users)
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