Commit 63a91faf authored by Douwe Maan's avatar Douwe Maan

Merge branch '1439-read-only-user' into 'master'

Implement backend for a read-only "Auditor" user

Closes #1439

See merge request !998
parents df6eb9c4 7e3ec6e8
...@@ -3,3 +3,4 @@ lib/gitlab/sanitizers/svg/whitelist.rb ...@@ -3,3 +3,4 @@ lib/gitlab/sanitizers/svg/whitelist.rb
lib/gitlab/diff/position_tracer.rb lib/gitlab/diff/position_tracer.rb
app/controllers/projects/approver_groups_controller.rb app/controllers/projects/approver_groups_controller.rb
app/controllers/projects/approvers_controller.rb app/controllers/projects/approvers_controller.rb
app/policies/project_policy.rb
\ No newline at end of file
...@@ -175,7 +175,7 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -175,7 +175,7 @@ class Admin::UsersController < Admin::ApplicationController
def user_params_ce def user_params_ce
[ [
:admin, :access_level,
:avatar, :avatar,
:bio, :bio,
:can_create_group, :can_create_group,
......
...@@ -18,7 +18,7 @@ class GroupProjectsFinder < UnionFinder ...@@ -18,7 +18,7 @@ class GroupProjectsFinder < UnionFinder
projects = [] projects = []
if current_user if current_user
if @group.users.include?(current_user) || current_user.admin? if @group.users.include?(current_user)
projects << @group.projects unless only_shared projects << @group.projects unless only_shared
projects << @group.shared_projects unless only_owned projects << @group.shared_projects unless only_owned
else else
......
...@@ -33,7 +33,7 @@ class IssuesFinder < IssuableFinder ...@@ -33,7 +33,7 @@ class IssuesFinder < IssuableFinder
def self.not_restricted_by_confidentiality(user) def self.not_restricted_by_confidentiality(user)
return Issue.where('issues.confidential IS NULL OR issues.confidential IS FALSE') if user.blank? return Issue.where('issues.confidential IS NULL OR issues.confidential IS FALSE') if user.blank?
return Issue.all if user.admin? return Issue.all if user.admin_or_auditor?
Issue.where(' Issue.where('
issues.confidential IS NULL issues.confidential IS NULL
......
...@@ -44,7 +44,7 @@ class SnippetsFinder ...@@ -44,7 +44,7 @@ class SnippetsFinder
snippets = project.snippets.fresh snippets = project.snippets.fresh
if current_user if current_user
include_private = project.team.member?(current_user) || current_user.admin? include_private = project.team.member?(current_user) || current_user.admin_or_auditor?
by_scope(snippets, scope, include_private) by_scope(snippets, scope, include_private)
else else
snippets.are_public snippets.are_public
......
module AuditorUserHelper
def license_allows_auditor_user?
@license_allows_auditor_user ||= (::License.current && ::License.current.add_on?('GitLab_Auditor_User'))
end
end
module EE
# User EE mixin
#
# This module is intended to encapsulate EE-specific model logic
# and be prepended in the `User` model
module User
extend ActiveSupport::Concern
include AuditorUserHelper
included do
# We aren't using the `auditor?` method for the `if` condition here
# because `auditor?` returns `false` when the `auditor` column is `true`
# and the auditor add-on absent. We want to run this validation
# regardless of the add-on's presence, so we need to check the `auditor`
# column directly.
validate :auditor_requires_license_add_on, if: :auditor
validate :cannot_be_admin_and_auditor
end
def cannot_be_admin_and_auditor
if admin? && auditor?
errors.add(:admin, "user cannot also be an Auditor.")
end
end
def auditor_requires_license_add_on
unless license_allows_auditor_user?
errors.add(:auditor, 'user cannot be created without the "GitLab_Auditor_User" addon')
end
end
def auditor?
license_allows_auditor_user? && self.auditor
end
def admin_or_auditor?
admin? || auditor?
end
end
end
...@@ -83,7 +83,7 @@ class ProjectFeature < ActiveRecord::Base ...@@ -83,7 +83,7 @@ class ProjectFeature < ActiveRecord::Base
when DISABLED when DISABLED
false false
when PRIVATE when PRIVATE
user && (project.team.member?(user) || user.admin?) user && (project.team.member?(user) || user.admin_or_auditor?)
when ENABLED when ENABLED
true true
else else
......
...@@ -10,6 +10,7 @@ class User < ActiveRecord::Base ...@@ -10,6 +10,7 @@ class User < ActiveRecord::Base
include CaseSensitivity include CaseSensitivity
include TokenAuthenticatable include TokenAuthenticatable
prepend EE::GeoAwareAvatar prepend EE::GeoAwareAvatar
prepend EE::User
DEFAULT_NOTIFICATION_LEVEL = :participating DEFAULT_NOTIFICATION_LEVEL = :participating
...@@ -933,6 +934,24 @@ class User < ActiveRecord::Base ...@@ -933,6 +934,24 @@ class User < ActiveRecord::Base
Gitlab::UserActivities::ActivitySet.record(self) Gitlab::UserActivities::ActivitySet.record(self)
end end
def access_level
if admin?
:admin
elsif auditor?
:auditor
else
:regular
end
end
def access_level=(new_level)
new_level = new_level.to_s
return unless %w(admin auditor regular).include?(new_level)
self.admin = (new_level == 'admin')
self.auditor = (new_level == 'auditor')
end
private private
def ci_projects_union def ci_projects_union
......
...@@ -12,6 +12,7 @@ class GroupPolicy < BasePolicy ...@@ -12,6 +12,7 @@ class GroupPolicy < BasePolicy
can_read ||= globally_viewable can_read ||= globally_viewable
can_read ||= member can_read ||= member
can_read ||= @user.admin? can_read ||= @user.admin?
can_read ||= @user.auditor?
can_read ||= GroupProjectsFinder.new(@subject).execute(@user).any? can_read ||= GroupProjectsFinder.new(@subject).execute(@user).any?
can! :read_group if can_read can! :read_group if can_read
...@@ -40,6 +41,7 @@ class GroupPolicy < BasePolicy ...@@ -40,6 +41,7 @@ class GroupPolicy < BasePolicy
def can_read_group? def can_read_group?
return true if @subject.public? return true if @subject.public?
return true if @user.admin? return true if @user.admin?
return true if @user.auditor?
return true if @subject.internal? && !@user.external? return true if @subject.internal? && !@user.external?
return true if @subject.users.include?(@user) return true if @subject.users.include?(@user)
......
...@@ -8,6 +8,7 @@ class ProjectPolicy < BasePolicy ...@@ -8,6 +8,7 @@ class ProjectPolicy < BasePolicy
(project.group && project.group.has_owner?(user)) (project.group && project.group.has_owner?(user))
owner_access! if user.admin? || owner owner_access! if user.admin? || owner
auditor_access! if user.auditor?
team_member_owner_access! if owner team_member_owner_access! if owner
if project.public? || (project.internal? && !user.external?) if project.public? || (project.internal? && !user.external?)
...@@ -182,6 +183,16 @@ class ProjectPolicy < BasePolicy ...@@ -182,6 +183,16 @@ class ProjectPolicy < BasePolicy
cannot! :admin_merge_request cannot! :admin_merge_request
end end
# An auditor user has read-only access to all projects
def auditor_access!
base_readonly_access!
can! :read_build
can! :read_environment
can! :read_deployment
can! :read_pages
end
def disabled_features! def disabled_features!
repository_enabled = project.feature_available?(:repository, user) repository_enabled = project.feature_available?(:repository, user)
...@@ -228,25 +239,7 @@ class ProjectPolicy < BasePolicy ...@@ -228,25 +239,7 @@ class ProjectPolicy < BasePolicy
def anonymous_rules def anonymous_rules
return unless project.public? return unless project.public?
can! :read_project base_readonly_access!
can! :read_board
can! :read_list
can! :read_wiki
can! :read_label
can! :read_milestone
can! :read_project_snippet
can! :read_project_member
can! :read_merge_request
can! :read_note
can! :read_pipeline
can! :read_commit_status
can! :read_container_image
can! :download_code
can! :download_wiki_code
can! :read_cycle_analytics
# NOTE: may be overridden by IssuePolicy
can! :read_issue
# Allow to read builds by anonymous user if guests are allowed # Allow to read builds by anonymous user if guests are allowed
can! :read_build if project.public_builds? can! :read_build if project.public_builds?
...@@ -279,4 +272,31 @@ class ProjectPolicy < BasePolicy ...@@ -279,4 +272,31 @@ class ProjectPolicy < BasePolicy
:"admin_#{name}" :"admin_#{name}"
] ]
end end
private
# A base set of abilities for read-only users, which
# is then augmented as necessary for anonymous and other
# read-only users.
def base_readonly_access!
can! :read_project
can! :read_board
can! :read_list
can! :read_wiki
can! :read_label
can! :read_milestone
can! :read_project_snippet
can! :read_project_member
can! :read_merge_request
can! :read_note
can! :read_pipeline
can! :read_commit_status
can! :read_container_image
can! :download_code
can! :download_wiki_code
can! :read_cycle_analytics
# NOTE: may be overridden by IssuePolicy
can! :read_issue
end
end end
...@@ -3,12 +3,16 @@ class ProjectSnippetPolicy < BasePolicy ...@@ -3,12 +3,16 @@ class ProjectSnippetPolicy < BasePolicy
can! :read_project_snippet if @subject.public? can! :read_project_snippet if @subject.public?
return unless @user return unless @user
if @user && @subject.author == @user || @user.admin? if @user && (@subject.author == @user || @user.admin?)
can! :read_project_snippet can! :read_project_snippet
can! :update_project_snippet can! :update_project_snippet
can! :admin_project_snippet can! :admin_project_snippet
end end
if @user.auditor?
can! :read_project_snippet
end
if @subject.internal? && !@user.external? if @subject.internal? && !@user.external?
can! :read_project_snippet can! :read_project_snippet
end end
......
%fieldset
%legend Access
.form-group
= f.label :projects_limit, class: 'control-label'
.col-sm-10= f.number_field :projects_limit, min: 0, class: 'form-control'
.form-group
= f.label :can_create_group, class: 'control-label'
.col-sm-10= f.check_box :can_create_group
.form-group
= f.label :access_level, class: 'control-label'
.col-sm-10
- editing_current_user = (current_user == @user)
= f.radio_button :access_level, :regular, disabled: editing_current_user
= label_tag :regular do
Regular
%p.light
Regular users have access to their groups and projects
- if license_allows_auditor_user?
= f.radio_button :access_level, :auditor, disabled: editing_current_user
= label_tag :auditor do
Auditor
%p.light
Auditors have read-only access to all groups, projects and users
= f.radio_button :access_level, :admin, disabled: editing_current_user
= label_tag :admin do
Admin
%p.light
Administrators have access to all groups, projects and users and can manage all features in this installation
- if editing_current_user
%p.light
You cannot remove your own admin rights.
.form-group
= f.label :external, class: 'control-label'
.col-sm-10
= f.check_box :external do
External
%p.light
External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects or groups.
...@@ -40,28 +40,7 @@ ...@@ -40,28 +40,7 @@
= f.label :password_confirmation, class: 'control-label' = f.label :password_confirmation, class: 'control-label'
.col-sm-10= f.password_field :password_confirmation, disabled: f.object.force_random_password, class: 'form-control' .col-sm-10= f.password_field :password_confirmation, disabled: f.object.force_random_password, class: 'form-control'
%fieldset = render partial: 'access_levels', locals: { f: f }
%legend Access
.form-group
= f.label :projects_limit, class: 'control-label'
.col-sm-10= f.number_field :projects_limit, min: 0, class: 'form-control'
.form-group
= f.label :can_create_group, class: 'control-label'
.col-sm-10= f.check_box :can_create_group
.form-group
= f.label :admin, class: 'control-label'
- if current_user == @user
.col-sm-10= f.check_box :admin, disabled: true
.col-sm-10 You cannot remove your own admin rights.
- else
.col-sm-10= f.check_box :admin
.form-group
= f.label :external, class: 'control-label'
.col-sm-10= f.check_box :external
.col-sm-10 External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects or groups.
%fieldset %fieldset
%legend Profile %legend Profile
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
%span.cred (Blocked) %span.cred (Blocked)
- if @user.admin - if @user.admin
%span.cred (Admin) %span.cred (Admin)
- if @user.auditor
%span.cred (Auditor)
.pull-right .pull-right
- unless @user == current_user || @user.blocked? - unless @user == current_user || @user.blocked?
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
= image_tag avatar_icon(current_user), alt: current_user.to_reference, class: 'avatar s40' = image_tag avatar_icon(current_user), alt: current_user.to_reference, class: 'avatar s40'
.timeline-content.timeline-content-form .timeline-content.timeline-content-form
= render "projects/notes/form", view: diff_view = render "projects/notes/form", view: diff_view
- else - elsif !current_user
.disabled-comment.text-center .disabled-comment.text-center
.disabled-comment-text.inline .disabled-comment-text.inline
Please Please
......
---
title: Read-only "auditor" user role
merge_request: 998
author:
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddColumnAuditorToUsers < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default :users, :auditor, :boolean, default: false, allow_null: false
end
def down
remove_column :users, :auditor
end
end
...@@ -1454,6 +1454,7 @@ ActiveRecord::Schema.define(version: 20170204181513) do ...@@ -1454,6 +1454,7 @@ ActiveRecord::Schema.define(version: 20170204181513) do
t.string "incoming_email_token" t.string "incoming_email_token"
t.string "organization" t.string "organization"
t.boolean "authorized_projects_populated" t.boolean "authorized_projects_populated"
t.boolean "auditor", default: false, null: false
end end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
......
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
- [High Availability](administration/high_availability/README.md) Configure multiple servers for scaling or high availability. - [High Availability](administration/high_availability/README.md) Configure multiple servers for scaling or high availability.
- [Container Registry](administration/container_registry.md) Configure Docker Registry with GitLab. - [Container Registry](administration/container_registry.md) Configure Docker Registry with GitLab.
- [Repository restrictions](user/admin_area/settings/account_and_limit_settings.md#repository-size-limit) Define size restrictions for your repositories to limit the space they occupy in your storage device. Includes LFS objects. - [Repository restrictions](user/admin_area/settings/account_and_limit_settings.md#repository-size-limit) Define size restrictions for your repositories to limit the space they occupy in your storage device. Includes LFS objects.
- [Auditor users](administration/auditor_users.md) Create auditor users, with read-only access to the entire system.
## Contributor documentation ## Contributor documentation
......
# Auditor Users
>**Note:** [Introduced][998] in GitLab 8.17.
With Gitlab Enterprise Edition Premium, you can create *auditor* users, who
are given read-only access to all projects, groups, and other resources on the
GitLab instance.
First and foremost, an auditor user can perform all the actions that a regular user can.
In projects that the auditor user owns, or has been added to, they can be added to
groups, mentioned in comments, or have issues assigned to them. The one exception is
that auditor users cannot _create_ projects or groups.
In addition, the auditor will be granted read-only access to all other projects/groups/etc.
on the GitLab instance.
The `auditor` role is _not_ a read-only version of the `admin` role. The auditor will not be
able to access the project settings pages, or the Admin Area.
A user's access level can be set to ‘Auditor’ in the Admin Area
![Admin Area Form](auditor_access_form.png)
[998]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/998
...@@ -13,7 +13,19 @@ module Gitlab ...@@ -13,7 +13,19 @@ module Gitlab
scope :public_and_internal_only, -> { where(visibility_level: [PUBLIC, INTERNAL] ) } scope :public_and_internal_only, -> { where(visibility_level: [PUBLIC, INTERNAL] ) }
scope :non_public_only, -> { where.not(visibility_level: PUBLIC) } scope :non_public_only, -> { where.not(visibility_level: PUBLIC) }
scope :public_to_user, -> (user) { user && !user.external ? public_and_internal_only : public_only } scope :public_to_user, -> (user) do
if user
if user.admin_or_auditor?
all
elsif !user.external?
public_and_internal_only
else
public_only
end
else
public_only
end
end
end end
PRIVATE = 0 unless const_defined?(:PRIVATE) PRIVATE = 0 unless const_defined?(:PRIVATE)
......
require 'spec_helper'
describe Admin::DashboardController do
describe '#index' do
it "allows an admin user to access the page" do
sign_in(create(:user, :admin))
get :index
expect(response).to have_http_status(200)
end
it "does not allow an auditor user to access the page" do
sign_in(create(:user, :auditor))
get :index
expect(response).to have_http_status(404)
end
it "does not allow a regular user to access the page" do
sign_in(create(:user))
get :index
expect(response).to have_http_status(404)
end
end
end
...@@ -126,4 +126,48 @@ describe GroupsController do ...@@ -126,4 +126,48 @@ describe GroupsController do
expect(assigns(:group).path).not_to eq('new_path') expect(assigns(:group).path).not_to eq('new_path')
end end
end end
describe 'POST create' do
it 'allows creating a group' do
sign_in(user)
expect do
post :create, group: { name: 'new_group', path: "new_group" }
end.to change { Group.count }.by(1)
expect(response).to have_http_status(302)
end
context 'authorization' do
it 'allows an admin to create a group' do
sign_in(create(:admin))
expect do
post :create, group: { name: 'new_group', path: "new_group" }
end.to change { Group.count }.by(1)
expect(response).to have_http_status(302)
end
it 'does not allow a user with "can_create_group" set to false to create a group' do
sign_in(create(:user, can_create_group: false))
expect do
post :create, group: { name: 'new_group', path: "new_group" }
end.not_to change { Group.count }
expect(response).to have_http_status(404)
end
it 'allows an auditor with "can_create_group" set to true to create a group' do
sign_in(create(:user, :auditor, can_create_group: true))
expect do
post :create, group: { name: 'new_group', path: "new_group" }
end.to change { Group.count }.by(1)
expect(response).to have_http_status(302)
end
end
end
end end
...@@ -425,4 +425,26 @@ describe ProjectsController do ...@@ -425,4 +425,26 @@ describe ProjectsController do
expect(parsed_body["Commits"]).to include("123456") expect(parsed_body["Commits"]).to include("123456")
end end
end end
describe 'GET edit' do
it 'does not allow an auditor user to access the page' do
sign_in(create(:user, :auditor))
get :edit,
namespace_id: project.namespace.path,
id: project.path
expect(response).to have_http_status(404)
end
it 'allows an admin user to access the page' do
sign_in(create(:user, :admin))
get :edit,
namespace_id: project.namespace.path,
id: project.path
expect(response).to have_http_status(200)
end
end
end end
...@@ -6,7 +6,12 @@ FactoryGirl.define do ...@@ -6,7 +6,12 @@ FactoryGirl.define do
{ "Name" => FFaker::Name.name } { "Name" => FFaker::Name.name }
end end
restrictions do restrictions do
{ add_ons: { 'GitLab_FileLocks' => 1 } } {
add_ons: {
'GitLab_FileLocks' => 1,
'GitLab_Auditor_User' => 1
}
}
end end
notify_users_at { |l| l.expires_at } notify_users_at { |l| l.expires_at }
notify_admins_at { |l| l.expires_at } notify_admins_at { |l| l.expires_at }
......
...@@ -14,6 +14,10 @@ FactoryGirl.define do ...@@ -14,6 +14,10 @@ FactoryGirl.define do
admin true admin true
end end
trait :auditor do
auditor true
end
trait :external do trait :external do
external true external true
end end
......
...@@ -211,7 +211,7 @@ describe "Admin::Users", feature: true do ...@@ -211,7 +211,7 @@ describe "Admin::Users", feature: true do
fill_in "user_email", with: "bigbang@mail.com" fill_in "user_email", with: "bigbang@mail.com"
fill_in "user_password", with: "AValidPassword1" fill_in "user_password", with: "AValidPassword1"
fill_in "user_password_confirmation", with: "AValidPassword1" fill_in "user_password_confirmation", with: "AValidPassword1"
check "user_admin" choose "user_access_level_admin"
click_button "Save changes" click_button "Save changes"
end end
...@@ -228,6 +228,21 @@ describe "Admin::Users", feature: true do ...@@ -228,6 +228,21 @@ describe "Admin::Users", feature: true do
end end
end end
describe "Update user account type" do
before do
allow_any_instance_of(AuditorUserHelper).to receive(:license_allows_auditor_user?).and_return(true)
choose "user_access_level_auditor"
click_button "Save changes"
end
it "changes account type to be auditor" do
user.reload
expect(user).not_to be_admin
expect(user).to be_auditor
end
end
describe 'update username to non ascii char' do describe 'update username to non ascii char' do
it do it do
fill_in 'user_username', with: '\u3042\u3044' fill_in 'user_username', with: '\u3042\u3044'
......
...@@ -9,6 +9,7 @@ describe "Admin::Projects", feature: true do ...@@ -9,6 +9,7 @@ describe "Admin::Projects", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :auditor }
end end
describe "GET /admin/users" do describe "GET /admin/users" do
...@@ -17,6 +18,7 @@ describe "Admin::Projects", feature: true do ...@@ -17,6 +18,7 @@ describe "Admin::Projects", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :auditor }
end end
describe "GET /admin/hooks" do describe "GET /admin/hooks" do
...@@ -25,5 +27,6 @@ describe "Admin::Projects", feature: true do ...@@ -25,5 +27,6 @@ describe "Admin::Projects", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :auditor }
end end
end end
...@@ -8,6 +8,7 @@ describe "Dashboard access", feature: true do ...@@ -8,6 +8,7 @@ describe "Dashboard access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
end end
...@@ -16,6 +17,7 @@ describe "Dashboard access", feature: true do ...@@ -16,6 +17,7 @@ describe "Dashboard access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
end end
...@@ -24,6 +26,7 @@ describe "Dashboard access", feature: true do ...@@ -24,6 +26,7 @@ describe "Dashboard access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
end end
...@@ -32,6 +35,7 @@ describe "Dashboard access", feature: true do ...@@ -32,6 +35,7 @@ describe "Dashboard access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
end end
...@@ -40,6 +44,7 @@ describe "Dashboard access", feature: true do ...@@ -40,6 +44,7 @@ describe "Dashboard access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_allowed_for :visitor } it { is_expected.to be_allowed_for :visitor }
end end
...@@ -53,6 +58,7 @@ describe "Dashboard access", feature: true do ...@@ -53,6 +58,7 @@ describe "Dashboard access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
end end
end end
...@@ -60,12 +66,14 @@ describe "Dashboard access", feature: true do ...@@ -60,12 +66,14 @@ describe "Dashboard access", feature: true do
describe "GET /projects/new" do describe "GET /projects/new" do
it { expect(new_project_path).to be_allowed_for :admin } it { expect(new_project_path).to be_allowed_for :admin }
it { expect(new_project_path).to be_allowed_for :user } it { expect(new_project_path).to be_allowed_for :user }
it { expect(new_project_path).to be_allowed_for :auditor }
it { expect(new_project_path).to be_denied_for :visitor } it { expect(new_project_path).to be_denied_for :visitor }
end end
describe "GET /groups/new" do describe "GET /groups/new" do
it { expect(new_group_path).to be_allowed_for :admin } it { expect(new_group_path).to be_allowed_for :admin }
it { expect(new_group_path).to be_allowed_for :user } it { expect(new_group_path).to be_allowed_for :user }
it { expect(new_group_path).to be_allowed_for :auditor }
it { expect(new_group_path).to be_denied_for :visitor } it { expect(new_group_path).to be_denied_for :visitor }
end end
...@@ -74,6 +82,7 @@ describe "Dashboard access", feature: true do ...@@ -74,6 +82,7 @@ describe "Dashboard access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
end end
end end
...@@ -22,6 +22,7 @@ describe 'Internal Group access', feature: true do ...@@ -22,6 +22,7 @@ describe 'Internal Group access', feature: true do
subject { group_path(group) } subject { group_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_allowed_for(:master).of(group) } it { is_expected.to be_allowed_for(:master).of(group) }
it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:developer).of(group) }
...@@ -37,6 +38,7 @@ describe 'Internal Group access', feature: true do ...@@ -37,6 +38,7 @@ describe 'Internal Group access', feature: true do
subject { issues_group_path(group) } subject { issues_group_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_allowed_for(:master).of(group) } it { is_expected.to be_allowed_for(:master).of(group) }
it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:developer).of(group) }
...@@ -52,6 +54,7 @@ describe 'Internal Group access', feature: true do ...@@ -52,6 +54,7 @@ describe 'Internal Group access', feature: true do
subject { merge_requests_group_path(group) } subject { merge_requests_group_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_allowed_for(:master).of(group) } it { is_expected.to be_allowed_for(:master).of(group) }
it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:developer).of(group) }
...@@ -67,6 +70,7 @@ describe 'Internal Group access', feature: true do ...@@ -67,6 +70,7 @@ describe 'Internal Group access', feature: true do
subject { group_group_members_path(group) } subject { group_group_members_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_allowed_for(:master).of(group) } it { is_expected.to be_allowed_for(:master).of(group) }
it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:developer).of(group) }
...@@ -82,6 +86,7 @@ describe 'Internal Group access', feature: true do ...@@ -82,6 +86,7 @@ describe 'Internal Group access', feature: true do
subject { edit_group_path(group) } subject { edit_group_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_denied_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_denied_for(:master).of(group) } it { is_expected.to be_denied_for(:master).of(group) }
it { is_expected.to be_denied_for(:developer).of(group) } it { is_expected.to be_denied_for(:developer).of(group) }
......
...@@ -22,6 +22,7 @@ describe 'Private Group access', feature: true do ...@@ -22,6 +22,7 @@ describe 'Private Group access', feature: true do
subject { group_path(group) } subject { group_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_allowed_for(:master).of(group) } it { is_expected.to be_allowed_for(:master).of(group) }
it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:developer).of(group) }
...@@ -37,6 +38,7 @@ describe 'Private Group access', feature: true do ...@@ -37,6 +38,7 @@ describe 'Private Group access', feature: true do
subject { issues_group_path(group) } subject { issues_group_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_allowed_for(:master).of(group) } it { is_expected.to be_allowed_for(:master).of(group) }
it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:developer).of(group) }
...@@ -52,6 +54,7 @@ describe 'Private Group access', feature: true do ...@@ -52,6 +54,7 @@ describe 'Private Group access', feature: true do
subject { merge_requests_group_path(group) } subject { merge_requests_group_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_allowed_for(:master).of(group) } it { is_expected.to be_allowed_for(:master).of(group) }
it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:developer).of(group) }
...@@ -67,6 +70,7 @@ describe 'Private Group access', feature: true do ...@@ -67,6 +70,7 @@ describe 'Private Group access', feature: true do
subject { group_group_members_path(group) } subject { group_group_members_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_allowed_for(:master).of(group) } it { is_expected.to be_allowed_for(:master).of(group) }
it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:developer).of(group) }
...@@ -82,6 +86,7 @@ describe 'Private Group access', feature: true do ...@@ -82,6 +86,7 @@ describe 'Private Group access', feature: true do
subject { edit_group_path(group) } subject { edit_group_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_denied_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_denied_for(:master).of(group) } it { is_expected.to be_denied_for(:master).of(group) }
it { is_expected.to be_denied_for(:developer).of(group) } it { is_expected.to be_denied_for(:developer).of(group) }
......
...@@ -22,6 +22,7 @@ describe 'Public Group access', feature: true do ...@@ -22,6 +22,7 @@ describe 'Public Group access', feature: true do
subject { group_path(group) } subject { group_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_allowed_for(:master).of(group) } it { is_expected.to be_allowed_for(:master).of(group) }
it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:developer).of(group) }
...@@ -37,6 +38,7 @@ describe 'Public Group access', feature: true do ...@@ -37,6 +38,7 @@ describe 'Public Group access', feature: true do
subject { issues_group_path(group) } subject { issues_group_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_allowed_for(:master).of(group) } it { is_expected.to be_allowed_for(:master).of(group) }
it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:developer).of(group) }
...@@ -52,6 +54,7 @@ describe 'Public Group access', feature: true do ...@@ -52,6 +54,7 @@ describe 'Public Group access', feature: true do
subject { merge_requests_group_path(group) } subject { merge_requests_group_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_allowed_for(:master).of(group) } it { is_expected.to be_allowed_for(:master).of(group) }
it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:developer).of(group) }
...@@ -67,6 +70,7 @@ describe 'Public Group access', feature: true do ...@@ -67,6 +70,7 @@ describe 'Public Group access', feature: true do
subject { group_group_members_path(group) } subject { group_group_members_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_allowed_for(:master).of(group) } it { is_expected.to be_allowed_for(:master).of(group) }
it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:developer).of(group) }
...@@ -82,6 +86,7 @@ describe 'Public Group access', feature: true do ...@@ -82,6 +86,7 @@ describe 'Public Group access', feature: true do
subject { edit_group_path(group) } subject { edit_group_path(group) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_denied_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(group) } it { is_expected.to be_allowed_for(:owner).of(group) }
it { is_expected.to be_denied_for(:master).of(group) } it { is_expected.to be_denied_for(:master).of(group) }
it { is_expected.to be_denied_for(:developer).of(group) } it { is_expected.to be_denied_for(:developer).of(group) }
......
...@@ -8,6 +8,7 @@ describe "Profile access", feature: true do ...@@ -8,6 +8,7 @@ describe "Profile access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
end end
...@@ -16,6 +17,7 @@ describe "Profile access", feature: true do ...@@ -16,6 +17,7 @@ describe "Profile access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
end end
...@@ -24,6 +26,7 @@ describe "Profile access", feature: true do ...@@ -24,6 +26,7 @@ describe "Profile access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
end end
...@@ -32,6 +35,7 @@ describe "Profile access", feature: true do ...@@ -32,6 +35,7 @@ describe "Profile access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
end end
...@@ -40,6 +44,7 @@ describe "Profile access", feature: true do ...@@ -40,6 +44,7 @@ describe "Profile access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
end end
...@@ -48,6 +53,7 @@ describe "Profile access", feature: true do ...@@ -48,6 +53,7 @@ describe "Profile access", feature: true do
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :auditor }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
end end
end end
...@@ -12,6 +12,7 @@ describe "Internal Project Snippets Access", feature: true do ...@@ -12,6 +12,7 @@ describe "Internal Project Snippets Access", feature: true do
subject { namespace_project_snippets_path(project.namespace, project) } subject { namespace_project_snippets_path(project.namespace, project) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -26,6 +27,7 @@ describe "Internal Project Snippets Access", feature: true do ...@@ -26,6 +27,7 @@ describe "Internal Project Snippets Access", feature: true do
subject { new_namespace_project_snippet_path(project.namespace, project) } subject { new_namespace_project_snippet_path(project.namespace, project) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_denied_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -41,6 +43,7 @@ describe "Internal Project Snippets Access", feature: true do ...@@ -41,6 +43,7 @@ describe "Internal Project Snippets Access", feature: true do
subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -55,6 +58,7 @@ describe "Internal Project Snippets Access", feature: true do ...@@ -55,6 +58,7 @@ describe "Internal Project Snippets Access", feature: true do
subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } subject { namespace_project_snippet_path(project.namespace, project, private_snippet) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -71,6 +75,7 @@ describe "Internal Project Snippets Access", feature: true do ...@@ -71,6 +75,7 @@ describe "Internal Project Snippets Access", feature: true do
subject { raw_namespace_project_snippet_path(project.namespace, project, internal_snippet) } subject { raw_namespace_project_snippet_path(project.namespace, project, internal_snippet) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -85,6 +90,7 @@ describe "Internal Project Snippets Access", feature: true do ...@@ -85,6 +90,7 @@ describe "Internal Project Snippets Access", feature: true do
subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) } subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
......
...@@ -11,6 +11,7 @@ describe "Private Project Snippets Access", feature: true do ...@@ -11,6 +11,7 @@ describe "Private Project Snippets Access", feature: true do
subject { namespace_project_snippets_path(project.namespace, project) } subject { namespace_project_snippets_path(project.namespace, project) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -25,6 +26,7 @@ describe "Private Project Snippets Access", feature: true do ...@@ -25,6 +26,7 @@ describe "Private Project Snippets Access", feature: true do
subject { new_namespace_project_snippet_path(project.namespace, project) } subject { new_namespace_project_snippet_path(project.namespace, project) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_denied_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -39,6 +41,7 @@ describe "Private Project Snippets Access", feature: true do ...@@ -39,6 +41,7 @@ describe "Private Project Snippets Access", feature: true do
subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } subject { namespace_project_snippet_path(project.namespace, project, private_snippet) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -53,6 +56,7 @@ describe "Private Project Snippets Access", feature: true do ...@@ -53,6 +56,7 @@ describe "Private Project Snippets Access", feature: true do
subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) } subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
......
...@@ -13,6 +13,7 @@ describe "Public Project Snippets Access", feature: true do ...@@ -13,6 +13,7 @@ describe "Public Project Snippets Access", feature: true do
subject { namespace_project_snippets_path(project.namespace, project) } subject { namespace_project_snippets_path(project.namespace, project) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -27,6 +28,7 @@ describe "Public Project Snippets Access", feature: true do ...@@ -27,6 +28,7 @@ describe "Public Project Snippets Access", feature: true do
subject { new_namespace_project_snippet_path(project.namespace, project) } subject { new_namespace_project_snippet_path(project.namespace, project) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_denied_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -42,6 +44,7 @@ describe "Public Project Snippets Access", feature: true do ...@@ -42,6 +44,7 @@ describe "Public Project Snippets Access", feature: true do
subject { namespace_project_snippet_path(project.namespace, project, public_snippet) } subject { namespace_project_snippet_path(project.namespace, project, public_snippet) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -56,6 +59,7 @@ describe "Public Project Snippets Access", feature: true do ...@@ -56,6 +59,7 @@ describe "Public Project Snippets Access", feature: true do
subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -70,6 +74,7 @@ describe "Public Project Snippets Access", feature: true do ...@@ -70,6 +74,7 @@ describe "Public Project Snippets Access", feature: true do
subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } subject { namespace_project_snippet_path(project.namespace, project, private_snippet) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -86,6 +91,7 @@ describe "Public Project Snippets Access", feature: true do ...@@ -86,6 +91,7 @@ describe "Public Project Snippets Access", feature: true do
subject { raw_namespace_project_snippet_path(project.namespace, project, public_snippet) } subject { raw_namespace_project_snippet_path(project.namespace, project, public_snippet) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -100,6 +106,7 @@ describe "Public Project Snippets Access", feature: true do ...@@ -100,6 +106,7 @@ describe "Public Project Snippets Access", feature: true do
subject { raw_namespace_project_snippet_path(project.namespace, project, internal_snippet) } subject { raw_namespace_project_snippet_path(project.namespace, project, internal_snippet) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
...@@ -114,6 +121,7 @@ describe "Public Project Snippets Access", feature: true do ...@@ -114,6 +121,7 @@ describe "Public Project Snippets Access", feature: true do
subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) } subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) }
it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:admin) }
it { is_expected.to be_allowed_for(:auditor) }
it { is_expected.to be_allowed_for(:owner).of(project) } it { is_expected.to be_allowed_for(:owner).of(project) }
it { is_expected.to be_allowed_for(:master).of(project) } it { is_expected.to be_allowed_for(:master).of(project) }
it { is_expected.to be_allowed_for(:developer).of(project) } it { is_expected.to be_allowed_for(:developer).of(project) }
......
...@@ -76,6 +76,44 @@ describe GroupProjectsFinder do ...@@ -76,6 +76,44 @@ describe GroupProjectsFinder do
end end
end end
describe 'with an admin current user' do
let(:current_user) { create(:admin) }
context "only shared" do
subject { described_class.new(group, only_shared: true).execute(current_user) }
it { is_expected.to eq([shared_project_3, shared_project_2, shared_project_1]) }
end
context "only owned" do
subject { described_class.new(group, only_owned: true).execute(current_user) }
it { is_expected.to eq([private_project, public_project]) }
end
context "all" do
subject { described_class.new(group).execute(current_user) }
it { is_expected.to eq([shared_project_3, shared_project_2, shared_project_1, private_project, public_project]) }
end
end
describe 'with an auditor current user' do
let(:current_user) { create(:user, :auditor) }
context "only shared" do
subject { described_class.new(group, only_shared: true).execute(current_user) }
it { is_expected.to eq([shared_project_3, shared_project_2, shared_project_1]) }
end
context "only owned" do
subject { described_class.new(group, only_owned: true).execute(current_user) }
it { is_expected.to eq([private_project, public_project]) }
end
context "all" do
subject { described_class.new(group).execute(current_user) }
it { is_expected.to eq([shared_project_3, shared_project_2, shared_project_1, private_project, public_project]) }
end
end
describe "no user" do describe "no user" do
context "only shared" do context "only shared" do
subject { described_class.new(group, only_shared: true).execute(current_user) } subject { described_class.new(group, only_shared: true).execute(current_user) }
......
...@@ -258,6 +258,8 @@ describe IssuesFinder do ...@@ -258,6 +258,8 @@ describe IssuesFinder do
describe '.not_restricted_by_confidentiality' do describe '.not_restricted_by_confidentiality' do
let(:authorized_user) { create(:user) } let(:authorized_user) { create(:user) }
let(:admin_user) { create(:admin) }
let(:auditor_user) { create(:user, :auditor) }
let(:project) { create(:empty_project, namespace: authorized_user.namespace) } let(:project) { create(:empty_project, namespace: authorized_user.namespace) }
let!(:public_issue) { create(:issue, project: project) } let!(:public_issue) { create(:issue, project: project) }
let!(:confidential_issue) { create(:issue, project: project, confidential: true) } let!(:confidential_issue) { create(:issue, project: project, confidential: true) }
...@@ -273,5 +275,13 @@ describe IssuesFinder do ...@@ -273,5 +275,13 @@ describe IssuesFinder do
it 'returns all issues for user authorized for the issues projects' do it 'returns all issues for user authorized for the issues projects' do
expect(IssuesFinder.send(:not_restricted_by_confidentiality, authorized_user)).to include(public_issue, confidential_issue) expect(IssuesFinder.send(:not_restricted_by_confidentiality, authorized_user)).to include(public_issue, confidential_issue)
end end
it 'returns all issues for an admin user' do
expect(IssuesFinder.send(:not_restricted_by_confidentiality, admin_user)).to include(public_issue, confidential_issue)
end
it 'returns all issues for an auditor user' do
expect(IssuesFinder.send(:not_restricted_by_confidentiality, auditor_user)).to include(public_issue, confidential_issue)
end
end end
end end
...@@ -15,12 +15,14 @@ describe SnippetsFinder do ...@@ -15,12 +15,14 @@ describe SnippetsFinder do
it "returns all private and internal snippets" do it "returns all private and internal snippets" do
snippets = SnippetsFinder.new.execute(user, filter: :all) snippets = SnippetsFinder.new.execute(user, filter: :all)
expect(snippets).to include(snippet2, snippet3) expect(snippets).to include(snippet2, snippet3)
expect(snippets).not_to include(snippet1) expect(snippets).not_to include(snippet1)
end end
it "returns all public snippets" do it "returns all public snippets" do
snippets = SnippetsFinder.new.execute(nil, filter: :all) snippets = SnippetsFinder.new.execute(nil, filter: :all)
expect(snippets).to include(snippet3) expect(snippets).to include(snippet3)
expect(snippets).not_to include(snippet1, snippet2) expect(snippets).not_to include(snippet1, snippet2)
end end
...@@ -46,6 +48,7 @@ describe SnippetsFinder do ...@@ -46,6 +48,7 @@ describe SnippetsFinder do
it "returns all public and internal snippets" do it "returns all public and internal snippets" do
snippets = SnippetsFinder.new.execute(user1, filter: :by_user, user: user) snippets = SnippetsFinder.new.execute(user1, filter: :by_user, user: user)
expect(snippets).to include(snippet2, snippet3) expect(snippets).to include(snippet2, snippet3)
expect(snippets).not_to include(snippet1) expect(snippets).not_to include(snippet1)
end end
...@@ -58,23 +61,27 @@ describe SnippetsFinder do ...@@ -58,23 +61,27 @@ describe SnippetsFinder do
it "returns private snippets" do it "returns private snippets" do
snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_private") snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_private")
expect(snippets).to include(snippet1) expect(snippets).to include(snippet1)
expect(snippets).not_to include(snippet2, snippet3) expect(snippets).not_to include(snippet2, snippet3)
end end
it "returns public snippets" do it "returns public snippets" do
snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_public") snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_public")
expect(snippets).to include(snippet3) expect(snippets).to include(snippet3)
expect(snippets).not_to include(snippet1, snippet2) expect(snippets).not_to include(snippet1, snippet2)
end end
it "returns all snippets" do it "returns all snippets" do
snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user) snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user)
expect(snippets).to include(snippet1, snippet2, snippet3) expect(snippets).to include(snippet1, snippet2, snippet3)
end end
it "returns only public snippets if unauthenticated user" do it "returns only public snippets if unauthenticated user" do
snippets = SnippetsFinder.new.execute(nil, filter: :by_user, user: user) snippets = SnippetsFinder.new.execute(nil, filter: :by_user, user: user)
expect(snippets).to include(snippet3) expect(snippets).to include(snippet3)
expect(snippets).not_to include(snippet2, snippet1) expect(snippets).not_to include(snippet2, snippet1)
end end
...@@ -89,43 +96,68 @@ describe SnippetsFinder do ...@@ -89,43 +96,68 @@ describe SnippetsFinder do
it "returns public snippets for unauthorized user" do it "returns public snippets for unauthorized user" do
snippets = SnippetsFinder.new.execute(nil, filter: :by_project, project: project1) snippets = SnippetsFinder.new.execute(nil, filter: :by_project, project: project1)
expect(snippets).to include(@snippet3) expect(snippets).to include(@snippet3)
expect(snippets).not_to include(@snippet1, @snippet2) expect(snippets).not_to include(@snippet1, @snippet2)
end end
it "returns public and internal snippets for non project members" do it "returns public and internal snippets for non project members" do
snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1) snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1)
expect(snippets).to include(@snippet2, @snippet3) expect(snippets).to include(@snippet2, @snippet3)
expect(snippets).not_to include(@snippet1) expect(snippets).not_to include(@snippet1)
end end
it "returns public snippets for non project members" do it "returns public snippets for non project members" do
snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1, scope: "are_public") snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1, scope: "are_public")
expect(snippets).to include(@snippet3) expect(snippets).to include(@snippet3)
expect(snippets).not_to include(@snippet1, @snippet2) expect(snippets).not_to include(@snippet1, @snippet2)
end end
it "returns internal snippets for non project members" do it "returns internal snippets for non project members" do
snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1, scope: "are_internal") snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1, scope: "are_internal")
expect(snippets).to include(@snippet2) expect(snippets).to include(@snippet2)
expect(snippets).not_to include(@snippet1, @snippet3) expect(snippets).not_to include(@snippet1, @snippet3)
end end
it "does not return private snippets for non project members" do it "does not return private snippets for non project members" do
snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1, scope: "are_private") snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1, scope: "are_private")
expect(snippets).not_to include(@snippet1, @snippet2, @snippet3) expect(snippets).not_to include(@snippet1, @snippet2, @snippet3)
end end
it "returns all snippets for project members" do it "returns all snippets for project members" do
project1.team << [user, :developer] project1.team << [user, :developer]
snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1) snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1)
expect(snippets).to include(@snippet1, @snippet2, @snippet3) expect(snippets).to include(@snippet1, @snippet2, @snippet3)
end end
it "returns private snippets for project members" do it "returns private snippets for project members" do
project1.team << [user, :developer] project1.team << [user, :developer]
snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1, scope: "are_private") snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1, scope: "are_private")
expect(snippets).to include(@snippet1) expect(snippets).to include(@snippet1)
end end
it "returns all snippets for admin users" do
user = create(:user, :admin)
snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1)
expect(snippets).to include(@snippet1, @snippet2, @snippet3)
end
it "returns all snippets for auditor users" do
user = create(:user, :auditor)
snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1)
expect(snippets).to include(@snippet1, @snippet2, @snippet3)
end
end end
end end
...@@ -52,6 +52,15 @@ describe ProjectFeature do ...@@ -52,6 +52,15 @@ describe ProjectFeature do
expect(project.feature_available?(:issues, user)).to eq(true) expect(project.feature_available?(:issues, user)).to eq(true)
end end
end end
it "returns true if user is an auditor" do
user.update_attribute(:auditor, true)
features.each do |feature|
project.project_feature.update_attribute("#{feature}_access_level".to_sym, ProjectFeature::PRIVATE)
expect(project.feature_available?(:issues, user)).to eq(true)
end
end
end end
context 'when feature is enabled for everyone' do context 'when feature is enabled for everyone' do
......
...@@ -198,6 +198,12 @@ describe User, models: true do ...@@ -198,6 +198,12 @@ describe User, models: true do
end end
end end
end end
it 'does not allow a user to be both an auditor and an admin' do
user = build(:user, :admin, :auditor)
expect(user).to be_invalid
end
end end
describe "non_ldap" do describe "non_ldap" do
...@@ -1486,4 +1492,141 @@ describe User, models: true do ...@@ -1486,4 +1492,141 @@ describe User, models: true do
expect(user.project_authorizations.where(access_level: Gitlab::Access::REPORTER).exists?).to eq(true) expect(user.project_authorizations.where(access_level: Gitlab::Access::REPORTER).exists?).to eq(true)
end end
end end
describe '#access_level=' do
let(:user) { build(:user) }
before do
# `auditor?` returns true only when the user is an auditor _and_ the auditor license
# add-on is present. We aren't testing this here, so we can assume that the add-on exists.
allow_any_instance_of(License).to receive(:add_on?).with('GitLab_Auditor_User') { true }
end
it 'does nothing for an invalid access level' do
user.access_level = :invalid_access_level
expect(user.access_level).to eq(:regular)
expect(user.admin).to be false
expect(user.auditor).to be false
end
it "assigns the 'admin' access level" do
user.access_level = :admin
expect(user.access_level).to eq(:admin)
expect(user.admin).to be true
expect(user.auditor).to be false
end
it "assigns the 'auditor' access level" do
user.access_level = :auditor
expect(user.access_level).to eq(:auditor)
expect(user.admin).to be false
expect(user.auditor).to be true
end
it "assigns the 'auditor' access level" do
user.access_level = :regular
expect(user.access_level).to eq(:regular)
expect(user.admin).to be false
expect(user.auditor).to be false
end
it "clears the 'admin' access level when a user is made an auditor" do
user.access_level = :admin
user.access_level = :auditor
expect(user.access_level).to eq(:auditor)
expect(user.admin).to be false
expect(user.auditor).to be true
end
it "clears the 'auditor' access level when a user is made an admin" do
user.access_level = :auditor
user.access_level = :admin
expect(user.access_level).to eq(:admin)
expect(user.admin).to be true
expect(user.auditor).to be false
end
it "doesn't clear existing access levels when an invalid access level is passed in" do
user.access_level = :admin
user.access_level = :invalid_access_level
expect(user.access_level).to eq(:admin)
expect(user.admin).to be true
expect(user.auditor).to be false
end
it "accepts string values in addition to symbols" do
user.access_level = 'admin'
expect(user.access_level).to eq(:admin)
expect(user.admin).to be true
expect(user.auditor).to be false
end
end
describe 'the GitLab_Auditor_User add-on' do
let(:license) { build(:license) }
before do
allow(::License).to receive(:current).and_return(license)
end
context 'creating an auditor user' do
it "does not allow creating an auditor user if the addon isn't enabled" do
allow_any_instance_of(License).to receive(:add_on?).with('GitLab_Auditor_User') { false }
expect(build(:user, :auditor)).to be_invalid
end
it "does not allow creating an auditor user if no license is present" do
allow(License).to receive(:current).and_return nil
expect(build(:user, :auditor)).to be_invalid
end
it "allows creating an auditor user if the addon is enabled" do
allow_any_instance_of(License).to receive(:add_on?).with('GitLab_Auditor_User') { true }
expect(build(:user, :auditor)).to be_valid
end
it "allows creating a regular user if the addon isn't enabled" do
allow_any_instance_of(License).to receive(:add_on?).with('GitLab_Auditor_User') { false }
expect(build(:user)).to be_valid
end
end
context '#auditor?' do
it "returns true for an auditor user if the addon is enabled" do
allow_any_instance_of(License).to receive(:add_on?).with('GitLab_Auditor_User') { true }
expect(build(:user, :auditor)).to be_auditor
end
it "returns false for an auditor user if the addon is not enabled" do
allow_any_instance_of(License).to receive(:add_on?).with('GitLab_Auditor_User') { false }
expect(build(:user, :auditor)).not_to be_auditor
end
it "returns false for an auditor user if a license is not present" do
allow_any_instance_of(License).to receive(:add_on?).with('GitLab_Auditor_User') { false }
expect(build(:user, :auditor)).not_to be_auditor
end
it "returns false for a non-auditor user even if the addon is present" do
allow_any_instance_of(License).to receive(:add_on?).with('GitLab_Auditor_User') { true }
expect(build(:user)).not_to be_auditor
end
end
end
end end
...@@ -6,6 +6,7 @@ describe GroupPolicy, models: true do ...@@ -6,6 +6,7 @@ describe GroupPolicy, models: true do
let(:developer) { create(:user) } let(:developer) { create(:user) }
let(:master) { create(:user) } let(:master) { create(:user) }
let(:owner) { create(:user) } let(:owner) { create(:user) }
let(:auditor) { create(:user, :auditor) }
let(:admin) { create(:admin) } let(:admin) { create(:admin) }
let(:group) { create(:group) } let(:group) { create(:group) }
...@@ -170,5 +171,16 @@ describe GroupPolicy, models: true do ...@@ -170,5 +171,16 @@ describe GroupPolicy, models: true do
is_expected.to include(*owner_permissions) is_expected.to include(*owner_permissions)
end end
end end
context 'auditor' do
let(:current_user) { auditor }
it do
is_expected.to include(:read_group)
is_expected.to all(start_with("read"))
is_expected.not_to include(*master_permissions)
is_expected.not_to include(*owner_permissions)
end
end
end end
end end
require 'spec_helper'
describe NamespacePolicy, models: true do
let(:user) { create(:user) }
let(:owner) { create(:user) }
let(:auditor) { create(:user, :auditor) }
let(:admin) { create(:admin) }
let(:namespace) { create(:namespace, owner: owner) }
let(:owner_permissions) { [:create_projects, :admin_namespace] }
let(:admin_permissions) { owner_permissions }
subject { described_class.abilities(current_user, namespace).to_set }
context 'with no user' do
let(:current_user) { nil }
it { is_expected.to be_empty }
end
context 'regular user' do
let(:current_user) { user }
it { is_expected.to be_empty }
end
context 'owner' do
let(:current_user) { owner }
it { is_expected.to include(*owner_permissions) }
end
context 'auditor' do
let(:current_user) { auditor }
context 'owner' do
let(:namespace) { create(:namespace, owner: auditor) }
it { is_expected.to include(*owner_permissions) }
end
context 'non-owner' do
it { is_expected.to be_empty }
end
end
context 'admin' do
let(:current_user) { admin }
it { is_expected.to include(*owner_permissions) }
end
end
...@@ -6,65 +6,74 @@ describe ProjectPolicy, models: true do ...@@ -6,65 +6,74 @@ describe ProjectPolicy, models: true do
let(:dev) { create(:user) } let(:dev) { create(:user) }
let(:master) { create(:user) } let(:master) { create(:user) }
let(:owner) { create(:user) } let(:owner) { create(:user) }
let(:auditor) { create(:user, :auditor) }
let(:admin) { create(:admin) } let(:admin) { create(:admin) }
let(:project) { create(:empty_project, :public, namespace: owner.namespace) } let(:project) { create(:empty_project, :public, namespace: owner.namespace) }
let(:guest_permissions) do let(:guest_permissions) do
[ %i[
:read_project, :read_board, :read_list, :read_wiki, :read_issue, :read_label, read_project read_board read_list read_wiki read_issue read_label
:read_milestone, :read_project_snippet, :read_project_member, read_milestone read_project_snippet read_project_member
:read_note, :create_project, :create_issue, :create_note, read_note create_project create_issue create_note
:upload_file upload_file
] ]
end end
let(:reporter_permissions) do let(:reporter_permissions) do
[ %i[
:download_code, :fork_project, :create_project_snippet, :update_issue, download_code fork_project create_project_snippet update_issue
:admin_issue, :admin_label, :admin_list, :read_commit_status, :read_build, admin_issue admin_label admin_list read_commit_status read_build
:read_container_image, :read_pipeline, :read_environment, :read_deployment, read_container_image read_pipeline read_environment read_deployment
:read_merge_request, :download_wiki_code read_merge_request download_wiki_code
] ]
end end
let(:team_member_reporter_permissions) do let(:team_member_reporter_permissions) do
[ %i[build_download_code build_read_container_image]
:build_download_code, :build_read_container_image
]
end end
let(:developer_permissions) do let(:developer_permissions) do
[ %i[
:admin_merge_request, :update_merge_request, :create_commit_status, admin_merge_request update_merge_request create_commit_status
:update_commit_status, :create_build, :update_build, :create_pipeline, update_commit_status create_build update_build create_pipeline
:update_pipeline, :create_merge_request, :create_wiki, :push_code, update_pipeline create_merge_request create_wiki push_code
:resolve_note, :create_container_image, :update_container_image, resolve_note create_container_image update_container_image
:create_environment, :create_deployment create_environment create_deployment
] ]
end end
let(:master_permissions) do let(:master_permissions) do
[ %i[
:push_code_to_protected_branches, :update_project_snippet, :update_environment, push_code_to_protected_branches update_project_snippet update_environment
:update_deployment, :admin_milestone, :admin_project_snippet, update_deployment admin_milestone admin_project_snippet
:admin_project_member, :admin_note, :admin_wiki, :admin_project, admin_project_member admin_note admin_wiki admin_project
:admin_commit_status, :admin_build, :admin_container_image, admin_commit_status admin_build admin_container_image
:admin_pipeline, :admin_environment, :admin_deployment admin_pipeline admin_environment admin_deployment
] ]
end end
let(:public_permissions) do let(:public_permissions) do
[ %i[
:download_code, :fork_project, :read_commit_status, :read_pipeline, download_code fork_project read_commit_status read_pipeline
:read_container_image, :build_download_code, :build_read_container_image, read_container_image build_download_code build_read_container_image
:download_wiki_code download_wiki_code
] ]
end end
let(:owner_permissions) do let(:owner_permissions) do
[ %i[
:change_namespace, :change_visibility_level, :rename_project, :remove_project, change_namespace change_visibility_level rename_project remove_project
:archive_project, :remove_fork_project, :destroy_merge_request, :destroy_issue archive_project remove_fork_project destroy_merge_request destroy_issue
]
end
let(:auditor_permissions) do
%i[
download_code download_wiki_code read_project read_board read_list
read_wiki read_issue read_label read_milestone read_project_snippet
read_project_member read_note read_cycle_analytics read_pipeline
read_build read_commit_status read_container_image read_environment
read_deployment read_merge_request read_pages
] ]
end end
...@@ -207,5 +216,16 @@ describe ProjectPolicy, models: true do ...@@ -207,5 +216,16 @@ describe ProjectPolicy, models: true do
is_expected.to include(*owner_permissions) is_expected.to include(*owner_permissions)
end end
end end
context 'auditor' do
let(:current_user) { auditor }
it do
is_expected.not_to include(*developer_permissions)
is_expected.not_to include(*master_permissions)
is_expected.not_to include(*owner_permissions)
is_expected.to include(*auditor_permissions)
end
end
end end
end end
require 'spec_helper'
describe ProjectSnippetPolicy, models: true do
let(:current_user) { create(:user) }
let(:author_permissions) do
[
:update_project_snippet,
:admin_project_snippet
]
end
subject { described_class.abilities(current_user, project_snippet).to_set }
context 'public snippet' do
let(:project_snippet) { create(:project_snippet, :public) }
context 'no user' do
let(:current_user) { nil }
it do
is_expected.to include(:read_project_snippet)
is_expected.not_to include(*author_permissions)
end
end
context 'regular user' do
it do
is_expected.to include(:read_project_snippet)
is_expected.not_to include(*author_permissions)
end
end
end
context 'internal snippet' do
let(:project_snippet) { create(:project_snippet, :internal) }
context 'no user' do
let(:current_user) { nil }
it do
is_expected.not_to include(:read_project_snippet)
is_expected.not_to include(*author_permissions)
end
end
context 'regular user' do
it do
is_expected.to include(:read_project_snippet)
is_expected.not_to include(*author_permissions)
end
end
context 'external user' do
let(:current_user) { create(:user, :external) }
it do
is_expected.not_to include(:read_project_snippet)
is_expected.not_to include(*author_permissions)
end
end
end
context 'private snippet' do
let(:project_snippet) { create(:project_snippet, :private) }
context 'no user' do
let(:current_user) { nil }
it do
is_expected.not_to include(:read_project_snippet)
is_expected.not_to include(*author_permissions)
end
end
context 'regular user' do
it do
is_expected.not_to include(:read_project_snippet)
is_expected.not_to include(*author_permissions)
end
end
context 'snippet author' do
let(:project_snippet) { create(:project_snippet, :private, author: current_user) }
it do
is_expected.to include(:read_project_snippet)
is_expected.to include(*author_permissions)
end
end
context 'project team member' do
before { project_snippet.project.team << [current_user, :developer] }
it do
is_expected.to include(:read_project_snippet)
is_expected.not_to include(*author_permissions)
end
end
context 'auditor user' do
let(:current_user) { create(:user, :auditor) }
it do
is_expected.to include(:read_project_snippet)
is_expected.not_to include(*author_permissions)
end
end
context 'admin user' do
let(:current_user) { create(:admin) }
it do
is_expected.to include(:read_project_snippet)
is_expected.to include(*author_permissions)
end
end
end
end
...@@ -17,7 +17,7 @@ describe API::License, api: true do ...@@ -17,7 +17,7 @@ describe API::License, api: true do
expect(Date.parse(json_response['expires_at'])).to eq Date.today + 11.months expect(Date.parse(json_response['expires_at'])).to eq Date.today + 11.months
expect(json_response['active_users']).to eq 1 expect(json_response['active_users']).to eq 1
expect(json_response['licensee']).not_to be_empty expect(json_response['licensee']).not_to be_empty
expect(json_response['add_ons']).to eq({ 'GitLab_FileLocks' => 1 }) expect(json_response['add_ons']).to eq({ 'GitLab_FileLocks' => 1, 'GitLab_Auditor_User' => 1 })
end end
it 'denies access if not admin' do it 'denies access if not admin' do
......
...@@ -76,7 +76,7 @@ describe Groups::UpdateService, services: true do ...@@ -76,7 +76,7 @@ describe Groups::UpdateService, services: true do
end end
context 'rename group' do context 'rename group' do
let!(:service) { described_class.new(internal_group, user, path: 'new_path') } let!(:service) { described_class.new(internal_group, user, path: SecureRandom.hex) }
before do before do
internal_group.add_user(user, Gitlab::Access::MASTER) internal_group.add_user(user, Gitlab::Access::MASTER)
......
...@@ -12,7 +12,7 @@ RSpec.configure do |config| ...@@ -12,7 +12,7 @@ RSpec.configure do |config|
end end
config.before(:each, truncate: true) do config.before(:each, truncate: true) do
DatabaseCleaner.strategy = :truncation DatabaseCleaner.strategy = :truncation, { except: ['licenses'] }
end end
config.before(:each) do config.before(:each) do
......
...@@ -15,6 +15,8 @@ module AccessMatchers ...@@ -15,6 +15,8 @@ module AccessMatchers
logout logout
when :admin when :admin
login_as(create(:admin)) login_as(create(:admin))
when :auditor
login_as(create(:user, :auditor))
when :external when :external
login_as(create(:user, external: true)) login_as(create(:user, external: true))
when User when User
......
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