diff options
76 files changed, 544 insertions, 92 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f02cc1f102..508b9905d02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -441,6 +441,7 @@ Please view this file on the master branch, on stable branches it's out of date. - Avoid conflict with admin labels when importing GitHub labels. !6158 - Restores `fieldName` to allow only string values in `gl_dropdown.js`. !6234 - Allow the Rails cookie to be used for API authentication. + - Add the audit user for read only admin access. !6355 (brianp) - Login/Register UX upgrade !6328 ## 8.11.6 diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb index cf795d977ce..a4648b33cfa 100644 --- a/app/controllers/admin/application_controller.rb +++ b/app/controllers/admin/application_controller.rb @@ -6,6 +6,6 @@ class Admin::ApplicationController < ApplicationController layout 'admin' def authenticate_admin! - render_404 unless current_user.is_admin? + render_404 unless current_user.admin? end end diff --git a/app/controllers/admin/impersonations_controller.rb b/app/controllers/admin/impersonations_controller.rb index 9433da02f64..8e7adc06584 100644 --- a/app/controllers/admin/impersonations_controller.rb +++ b/app/controllers/admin/impersonations_controller.rb @@ -21,6 +21,6 @@ class Admin::ImpersonationsController < Admin::ApplicationController end def authenticate_impersonator! - render_404 unless impersonator && impersonator.is_admin? && !impersonator.blocked? + render_404 unless impersonator && impersonator.admin? && !impersonator.blocked? end end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index f35f4a8c811..f91dbef8039 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -169,7 +169,7 @@ class Admin::UsersController < Admin::ApplicationController :email, :remember_me, :bio, :name, :username, :skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id, :force_random_password, :extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key, :hide_no_password, - :projects_limit, :can_create_group, :admin, :key_id, :external + :projects_limit, :can_create_group, :role_type, :key_id, :external ) end diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb index 36d246d185b..f22ac70bc23 100644 --- a/app/controllers/import/gitlab_projects_controller.rb +++ b/app/controllers/import/gitlab_projects_controller.rb @@ -47,4 +47,8 @@ class Import::GitlabProjectsController < Import::BaseController :path, :namespace_id, :file ) end + + def authenticate_admin! + render_404 unless current_user.admin? + end end diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb index 4e43f42e9e1..932ea7782d4 100644 --- a/app/finders/groups_finder.rb +++ b/app/finders/groups_finder.rb @@ -8,8 +8,9 @@ class GroupsFinder < UnionFinder private def all_groups(current_user) - groups = [] + return [Group.all] if current_user && current_user.auditor? + groups = [] groups << current_user.authorized_groups if current_user groups << Group.unscoped.public_to_user(current_user) diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb index c7911736812..83cdc5a3de7 100644 --- a/app/finders/projects_finder.rb +++ b/app/finders/projects_finder.rb @@ -9,8 +9,9 @@ class ProjectsFinder < UnionFinder private def all_projects(current_user) - projects = [] + return [Project.all] if current_user && current_user.auditor? + projects = [] projects << current_user.authorized_projects if current_user projects << Project.unscoped.public_to_user(current_user) diff --git a/app/helpers/admin/user_helper.rb b/app/helpers/admin/user_helper.rb new file mode 100644 index 00000000000..12aa6c1e144 --- /dev/null +++ b/app/helpers/admin/user_helper.rb @@ -0,0 +1,8 @@ +# Helper methods for Admin interface User settings +module Admin + module UserHelper + def role_type_choices + User.role_types.keys.collect{|k| [k.titleize, k]} + end + end +end diff --git a/app/helpers/runners_helper.rb b/app/helpers/runners_helper.rb index 9fb42487a75..5e0c6c9e256 100644 --- a/app/helpers/runners_helper.rb +++ b/app/helpers/runners_helper.rb @@ -18,7 +18,7 @@ module RunnersHelper display_name = truncate(runner.display_name, length: 15) id = "\##{runner.id}" - if current_user && current_user.admin + if current_user && current_user.admin? link_to admin_runner_path(runner) do display_name + id end diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb index 3a83ae15dd8..9c4ac4a262e 100644 --- a/app/helpers/visibility_level_helper.rb +++ b/app/helpers/visibility_level_helper.rb @@ -85,7 +85,7 @@ module VisibilityLevelHelper end def restricted_visibility_levels(show_all = false) - return [] if current_user.is_admin? && !show_all + return [] if current_user.admin? && !show_all current_application_settings.restricted_visibility_levels || [] end diff --git a/app/models/issue.rb b/app/models/issue.rb index 89158a50353..9f29ecb0a86 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -91,6 +91,7 @@ class Issue < ActiveRecord::Base def self.visible_to_user(user) return where('issues.confidential IS NULL OR issues.confidential IS FALSE') if user.blank? return all if user.admin? + return all if user.auditor? # Check if we are scoped to a specific project's issues if owner_project @@ -258,6 +259,8 @@ class Issue < ActiveRecord::Base def readable_by?(user) if user.admin? true + elsif user.auditor? + true elsif project.owner == user true elsif confidential? diff --git a/app/models/protected_branch/merge_access_level.rb b/app/models/protected_branch/merge_access_level.rb index 806b3ccd275..c54f44edeb2 100644 --- a/app/models/protected_branch/merge_access_level.rb +++ b/app/models/protected_branch/merge_access_level.rb @@ -15,7 +15,7 @@ class ProtectedBranch::MergeAccessLevel < ActiveRecord::Base end def check_access(user) - return true if user.is_admin? + return true if user.admin? project.team.max_member_access(user.id) >= access_level end diff --git a/app/models/protected_branch/push_access_level.rb b/app/models/protected_branch/push_access_level.rb index 92e9c51d883..efe17e75ee2 100644 --- a/app/models/protected_branch/push_access_level.rb +++ b/app/models/protected_branch/push_access_level.rb @@ -18,7 +18,7 @@ class ProtectedBranch::PushAccessLevel < ActiveRecord::Base def check_access(user) return false if access_level == Gitlab::Access::NO_ACCESS - return true if user.is_admin? + return true if user.admin? project.team.max_member_access(user.id) >= access_level end diff --git a/app/models/user.rb b/app/models/user.rb index f367f4616fb..26823907024 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -14,7 +14,7 @@ class User < ActiveRecord::Base add_authentication_token_field :authentication_token - default_value_for :admin, false + default_value_for :role_type, :regular default_value_for(:external) { current_application_settings.user_default_external } default_value_for :can_create_group, gitlab_config.default_can_create_group default_value_for :can_create_team, false @@ -136,6 +136,10 @@ class User < ActiveRecord::Base # Note: When adding an option, it MUST go on the end of the array. enum project_view: [:readme, :activity, :files] + # User's role + # Note: When adding an option, it MUST go on the end of the array. + enum role_type: [:regular, :admin, :auditor] + alias_attribute :private_token, :authentication_token delegate :path, to: :namespace, allow_nil: true, prefix: true @@ -165,7 +169,8 @@ class User < ActiveRecord::Base mount_uploader :avatar, AvatarUploader # Scopes - scope :admins, -> { where(admin: true) } + scope :admins, -> { admin } # `admin` comes from the enum attribute on `role_type` + scope :auditors, -> { auditor } # `auditor` comes from the enum attribute on `role_type` scope :blocked, -> { with_states(:blocked, :ldap_blocked) } scope :external, -> { where(external: true) } scope :active, -> { with_state(:active) } @@ -223,6 +228,8 @@ class User < ActiveRecord::Base case filter_name when 'admins' self.admins + when 'auditors' + self.auditors when 'blocked' self.blocked when 'two_factor_disabled' @@ -441,10 +448,6 @@ class User < ActiveRecord::Base authorized_projects(Gitlab::Access::REPORTER).non_archived.with_issues_enabled end - def is_admin? - admin - end - def require_ssh_key? keys.count == 0 end @@ -466,7 +469,7 @@ class User < ActiveRecord::Base end def can_select_namespace? - several_namespaces? || admin + several_namespaces? || admin? end def can?(action, subject) diff --git a/app/policies/ci/runner_policy.rb b/app/policies/ci/runner_policy.rb index 7edd383530d..416d93ffe63 100644 --- a/app/policies/ci/runner_policy.rb +++ b/app/policies/ci/runner_policy.rb @@ -3,7 +3,7 @@ module Ci def rules return unless @user - can! :assign_runner if @user.is_admin? + can! :assign_runner if @user.admin? return if @subject.is_shared? || @subject.locked? diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb index b65fb68cd88..2c68ad00d65 100644 --- a/app/policies/group_policy.rb +++ b/app/policies/group_policy.rb @@ -12,6 +12,7 @@ class GroupPolicy < BasePolicy can_read ||= globally_viewable can_read ||= member can_read ||= @user.admin? + can_read ||= @user.auditor? can_read ||= GroupProjectsFinder.new(@subject).execute(@user).any? can! :read_group if can_read @@ -38,6 +39,7 @@ class GroupPolicy < BasePolicy def can_read_group? return true if @subject.public? return true if @user.admin? + return true if @user.auditor? return true if @subject.internal? && !@user.external? return true if @subject.users.include?(@user) diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb index bd1811a3c54..83e73ceae7d 100644 --- a/app/policies/issue_policy.rb +++ b/app/policies/issue_policy.rb @@ -19,6 +19,7 @@ class IssuePolicy < IssuablePolicy def can_read_confidential? return false unless @user return true if @user.admin? + return true if @user.auditor? return true if @subject.author == @user return true if @subject.assignee == @user return true if @subject.project.team.member?(@user, Gitlab::Access::REPORTER) diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index fbb3d4507d6..27e2f55721b 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -8,6 +8,8 @@ class ProjectPolicy < BasePolicy owner_access! if owner + read_only_access! if user.auditor? + if project.public? || (project.internal? && !user.external?) guest_access! public_access! @@ -233,6 +235,36 @@ class ProjectPolicy < BasePolicy disabled_features! end + # This is similar to anonymous but doesn't check to see if the repo or builds + # are public. + def read_only_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! :read_cycle_analytics + can! :read_build + + # Abilities anonymous_rules lack + can! :read_environment + can! :read_deployment + + # NOTE: may be overridden by IssuePolicy + can! :read_issue + + disabled_features! + end + def project_group_member?(user) project.group && ( diff --git a/app/policies/project_snippet_policy.rb b/app/policies/project_snippet_policy.rb index 57acccfafd9..875089f64df 100644 --- a/app/policies/project_snippet_policy.rb +++ b/app/policies/project_snippet_policy.rb @@ -16,5 +16,9 @@ class ProjectSnippetPolicy < BasePolicy if @subject.private? && @subject.project.team.member?(@user) can! :read_project_snippet end + + if @user.auditor? + can! :read_project_snippet + end end end diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index 3145212728f..c17753c2494 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -51,12 +51,16 @@ .col-sm-10= f.check_box :can_create_group .form-group - = f.label :admin, class: 'control-label' + = f.label :role_type, 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. + .col-sm-10= f.select :role_type, role_type_choices, {}, class: 'form-control', disabled: true + .col-sm-10.col-sm-push-2 You cannot remove your own admin rights. - else - .col-sm-10= f.check_box :admin + .col-sm-10= f.select :role_type, role_type_choices, {}, class: 'form-control' + .col-sm-10.col-sm-offset-2 + Role types offer users different types of permissions. Check out the + = link_to 'Permissions documentation', 'https://docs.gitlab.com/ce/user/permissions.html' + for more info. .form-group = f.label :external, class: 'control-label' diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml index ce5e21e54cc..ffdc55dd497 100644 --- a/app/views/admin/users/_head.html.haml +++ b/app/views/admin/users/_head.html.haml @@ -2,8 +2,10 @@ = @user.name - if @user.blocked? %span.cred (Blocked) - - if @user.admin + - if @user.admin? %span.cred (Admin) + - if @user.auditor? + %span.cred (Auditor) .pull-right - unless @user == current_user || @user.blocked? diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml index 4bf1c9cde3c..9e5e5314d4e 100644 --- a/app/views/admin/users/_user.html.haml +++ b/app/views/admin/users/_user.html.haml @@ -8,6 +8,8 @@ %span.label.label-danger blocked - if user.admin? %span.label.label-success Admin + - if user.auditor? + %span.label.label-default Auditor - if user.external? %span.label.label-default External - if user == current_user diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index 357123c2c13..3b530191620 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -46,6 +46,10 @@ = link_to admin_users_path(filter: "admins") do Admins %small.badge= number_with_delimiter(User.admins.count) + = nav_link(html_options: { class: ('active' if params[:filter] == 'auditors') }) do + = link_to admin_users_path(filter: "auditors") do + Auditors + %small.badge= number_with_delimiter(User.auditors.count) = nav_link(html_options: { class: "#{'active' if params[:filter] == 'two_factor_enabled'} filter-two-factor-enabled" }) do = link_to admin_users_path(filter: 'two_factor_enabled') do 2FA Enabled diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 7faa8bded86..dde27fd270d 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -20,7 +20,7 @@ %li.impersonation = link_to admin_impersonation_path, method: :delete, title: "Stop Impersonation", aria: { label: 'Stop Impersonation' }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do = icon('user-secret fw') - - if current_user.is_admin? + - if current_user.admin? %li = link_to admin_root_path, title: 'Admin Area', aria: { label: "Admin Area" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = icon('wrench fw') diff --git a/app/views/projects/builds/_sidebar.html.haml b/app/views/projects/builds/_sidebar.html.haml index b1053028279..fd3e3ca8d83 100644 --- a/app/views/projects/builds/_sidebar.html.haml +++ b/app/views/projects/builds/_sidebar.html.haml @@ -63,7 +63,7 @@ #{time_ago_with_tooltip(@build.erased_at)} %p.build-detail-row %span.build-light-text Runner: - - if @build.runner && current_user && current_user.admin + - if @build.runner && current_user && current_user.admin? = link_to "##{@build.runner.id}", admin_runner_path(@build.runner.id) - elsif @build.runner \##{@build.runner.id} diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 1e0752bd3c3..6b60787fd32 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -28,6 +28,7 @@ = link_to user_path(@user, :atom, { private_token: current_user.private_token }), class: 'btn btn-gray' do = icon('rss') - if current_user.admin? + = link_to [:admin, @user], class: 'btn btn-gray', title: 'View user in admin area', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = icon('users') diff --git a/db/fixtures/development/01_admin.rb b/db/fixtures/development/01_admin.rb index bba2fc4b186..ee5aa43877e 100644 --- a/db/fixtures/development/01_admin.rb +++ b/db/fixtures/development/01_admin.rb @@ -6,7 +6,7 @@ Gitlab::Seeder.quiet do s.notification_email = 'admin@example.com' s.username = 'root' s.password = '5iveL!fe' - s.admin = true + s.role_type = 'admin' s.projects_limit = 100 s.confirmed_at = DateTime.now end diff --git a/db/migrate/20160908095522_add_role_type_to_users.rb b/db/migrate/20160908095522_add_role_type_to_users.rb new file mode 100644 index 00000000000..ff67e62c0f8 --- /dev/null +++ b/db/migrate/20160908095522_add_role_type_to_users.rb @@ -0,0 +1,18 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class AddRoleTypeToUsers < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_column_with_default(:users, :role_type, :integer, default: 0) + end + + def down + remove_column :users, :role_type + end +end diff --git a/db/migrate/20160908100449_migrate_admins_to_role_types.rb b/db/migrate/20160908100449_migrate_admins_to_role_types.rb new file mode 100644 index 00000000000..0c800ee1cf6 --- /dev/null +++ b/db/migrate/20160908100449_migrate_admins_to_role_types.rb @@ -0,0 +1,32 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class MigrateAdminsToRoleTypes < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + sql = + %Q{ + UPDATE users + SET + role_type = 1 + WHERE admin = TRUE + } + + execute(sql) + end + + def down + sql = + %Q{ + UPDATE users + SET + admin = TRUE + WHERE role_type = 1 + } + + execute(sql) + end +end diff --git a/db/migrate/20160908105417_drop_admin_from_users.rb b/db/migrate/20160908105417_drop_admin_from_users.rb new file mode 100644 index 00000000000..fb06f3c37c0 --- /dev/null +++ b/db/migrate/20160908105417_drop_admin_from_users.rb @@ -0,0 +1,19 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class DropAdminFromUsers < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + remove_column :users, :admin + end + + def down + add_column_with_default(:users, :admin, :boolean, default: false) + add_concurrent_index :users, [:admin], { name: "index_users_on_admin", using: :btree } + end +end diff --git a/db/schema.rb b/db/schema.rb index 02282b0f666..63a61ebcf7d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1128,7 +1128,6 @@ ActiveRecord::Schema.define(version: 20161024042317) do t.datetime "created_at" t.datetime "updated_at" t.string "name" - t.boolean "admin", default: false, null: false t.integer "projects_limit", default: 10 t.string "skype", default: "", null: false t.string "linkedin", default: "", null: false @@ -1173,9 +1172,9 @@ ActiveRecord::Schema.define(version: 20161024042317) do t.boolean "ldap_email", default: false, null: false t.boolean "external", default: false t.string "organization" + t.integer "role_type", default: 0, null: false end - add_index "users", ["admin"], name: "index_users_on_admin", using: :btree add_index "users", ["authentication_token"], name: "index_users_on_authentication_token", unique: true, using: :btree add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree add_index "users", ["created_at"], name: "index_users_on_created_at", using: :btree diff --git a/doc/api/users.md b/doc/api/users.md index a50ba5432fe..1f923d57e98 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -51,6 +51,9 @@ GET /users "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "is_admin": false, + "admin": false, + "auditor": false, + "role_type": "regular", "bio": null, "location": null, "skype": "", @@ -84,6 +87,9 @@ GET /users "web_url": "http://localhost:3000/jack_smith", "created_at": "2012-05-23T08:01:01Z", "is_admin": false, + "admin": false, + "auditor": false, + "role_type": "regular", "bio": null, "location": null, "skype": "", @@ -144,6 +150,9 @@ Parameters: "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "is_admin": false, + "admin": false, + "auditor": false, + "role_type": "regular", "bio": null, "location": null, "skype": "", @@ -175,6 +184,9 @@ Parameters: "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "is_admin": false, + "admin": false, + "auditor": false, + "role_type": "regular", "bio": null, "location": null, "skype": "", @@ -224,7 +236,8 @@ Parameters: - `provider` (optional) - External provider name - `bio` (optional) - User's biography - `location` (optional) - User's location -- `admin` (optional) - User is admin - true or false (default) +- `admin` - User is admin - true or false (default) +- `role_type` (optional) - The users role - (regular, admin, or auditor) - `can_create_group` (optional) - User can create groups - true or false - `confirm` (optional) - Require confirmation - true (default) or false - `external` (optional) - Flags the user as external - true or false(default) @@ -253,7 +266,8 @@ Parameters: - `provider` - External provider name - `bio` - User's biography - `location` (optional) - User's location -- `admin` (optional) - User is admin - true or false (default) +- `admin` - User is admin - true or false (default) +- `role_type` (optional) - The users role - (regular, admin, or auditor) - `can_create_group` (optional) - User can create groups - true or false - `external` (optional) - Flags the user as external - true or false(default) @@ -296,6 +310,9 @@ GET /user "web_url": "http://localhost:3000/john_smith", "created_at": "2012-05-23T08:00:58Z", "is_admin": false, + "admin": false, + "auditor": false, + "role_type": "regular", "bio": null, "location": null, "skype": "", diff --git a/doc/user/permissions.md b/doc/user/permissions.md index d6216a8dd50..51a7fc9eaf7 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -9,6 +9,9 @@ be able to create issues, leave comments, and pull or download the project code. GitLab administrators receive all permissions. +GitLab auditors receive read-only admin permissions. Access to view all +projects and groups without the ability to modify them. + To add or import a user, you can follow the [project users and members documentation](../workflow/add-user/add-user.md). diff --git a/features/steps/shared/user.rb b/features/steps/shared/user.rb index 9856c510aa0..ae4fd88ccb3 100644 --- a/features/steps/shared/user.rb +++ b/features/steps/shared/user.rb @@ -16,7 +16,7 @@ module SharedUser protected def user_exists(name, options = {}) - User.find_by(name: name) || create(:user, { name: name, admin: false }.merge(options)) + User.find_by(name: name) || create(:user, { name: name }.merge(options)) end step 'I have an ssh key' do diff --git a/lib/api/entities.rb b/lib/api/entities.rb index feaa0c213bf..e1995aa6f4b 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -14,8 +14,9 @@ module API class User < UserBasic expose :created_at - expose :is_admin?, as: :is_admin - expose :bio, :location, :skype, :linkedin, :twitter, :website_url, :organization + expose :admin?, as: :is_admin + expose :auditor?, as: :is_auditor + expose :bio, :location, :skype, :linkedin, :twitter, :website_url, :role_type, :organization end class Identity < Grape::Entity @@ -549,9 +550,9 @@ module API expose :locked expose :version, :revision, :platform, :architecture expose :contacted_at - expose :token, if: lambda { |runner, options| options[:current_user].is_admin? || !runner.is_shared? } + expose :token, if: lambda { |runner, options| options[:current_user].admin? || !runner.is_shared? } expose :projects, with: Entities::BasicProjectDetails do |runner, options| - if options[:current_user].is_admin? + if options[:current_user].admin? runner.projects else options[:current_user].authorized_projects.where(id: runner.projects) diff --git a/lib/api/groups.rb b/lib/api/groups.rb index bfb89475025..8ca4cfa68cd 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -11,7 +11,7 @@ module API # Example Request: # GET /groups get do - @groups = if current_user.admin + @groups = if current_user.admin? || current_user.auditor? Group.all else current_user.groups diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 45120898b76..d05841def89 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -48,7 +48,7 @@ module API # If the sudo is the current user do nothing if identifier && !(@current_user.id == identifier || @current_user.username == identifier) - forbidden!('Must be admin to use sudo') unless @current_user.is_admin? + forbidden!('Must be admin to use sudo') unless @current_user.admin? @current_user = User.by_username_or_id(identifier) not_found!("No user id or username for: #{identifier}") if @current_user.nil? end @@ -150,7 +150,7 @@ module API end def authenticated_as_admin! - forbidden! unless current_user.is_admin? + forbidden! unless current_user.admin? end def authorize!(action, subject = nil) diff --git a/lib/api/namespaces.rb b/lib/api/namespaces.rb index fe981d7b9fa..cd398274507 100644 --- a/lib/api/namespaces.rb +++ b/lib/api/namespaces.rb @@ -11,7 +11,7 @@ module API optional :search, type: String, desc: "Search query for namespaces" end get do - namespaces = current_user.admin ? Namespace.all : current_user.namespaces + namespaces = current_user.admin? ? Namespace.all : current_user.namespaces namespaces = namespaces.search(params[:search]) if params[:search].present? diff --git a/lib/api/notes.rb b/lib/api/notes.rb index c5c214d4d13..1245343a7c3 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -79,7 +79,7 @@ module API noteable_id: params[noteable_id_str] } - if params[:created_at] && (current_user.is_admin? || user_project.owner == current_user) + if params[:created_at] && (current_user.admin? || user_project.owner == current_user) opts[:created_at] = params[:created_at] end diff --git a/lib/api/runners.rb b/lib/api/runners.rb index ecc8f2fc5a2..e47b2ea4890 100644 --- a/lib/api/runners.rb +++ b/lib/api/runners.rb @@ -149,18 +149,18 @@ module API end def authenticate_show_runner!(runner) - return if runner.is_shared || current_user.is_admin? + return if runner.is_shared || current_user.admin? || current_user.auditor? forbidden!("No access granted") unless user_can_access_runner?(runner) end def authenticate_update_runner!(runner) - return if current_user.is_admin? + return if current_user.admin? forbidden!("Runner is shared") if runner.is_shared? forbidden!("No access granted") unless user_can_access_runner?(runner) end def authenticate_delete_runner!(runner) - return if current_user.is_admin? + return if current_user.admin? forbidden!("Runner is shared") if runner.is_shared? forbidden!("Runner associated with more than one project") if runner.projects.count > 1 forbidden!("No access granted") unless user_can_access_runner?(runner) @@ -169,7 +169,7 @@ module API def authenticate_enable_runner!(runner) forbidden!("Runner is shared") if runner.is_shared? forbidden!("Runner is locked") if runner.locked? - return if current_user.is_admin? + return if current_user.admin? forbidden!("No access granted") unless user_can_access_runner?(runner) end diff --git a/lib/api/services.rb b/lib/api/services.rb index fc8598daa32..a9888b31e9b 100644 --- a/lib/api/services.rb +++ b/lib/api/services.rb @@ -56,7 +56,7 @@ module API # GET /project/:id/services/gitlab-ci # get ':id/services/:service_slug' do - present project_service, with: Entities::ProjectService, include_passwords: current_user.is_admin? + present project_service, with: Entities::ProjectService, include_passwords: current_user.admin? end end end diff --git a/lib/api/users.rb b/lib/api/users.rb index e868f628404..6ab9786a97a 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -24,7 +24,7 @@ module API @users = paginate @users end - if current_user.is_admin? + if current_user.admin? present @users, with: Entities::UserFull else present @users, with: Entities::UserBasic @@ -40,7 +40,7 @@ module API get ":id" do @user = User.find(params[:id]) - if current_user && current_user.is_admin? + if current_user && current_user.admin? present @user, with: Entities::UserFull elsif can?(current_user, :read_user, @user) present @user, with: Entities::User @@ -67,6 +67,7 @@ module API # bio - Bio # location - Location of the user # admin - User is admin - true or false (default) + # role_type - Possible role type to apply - regular (default), admin, auditor # can_create_group - User can create groups - true or false # confirm - Require user confirmation - true (default) or false # external - Flags the user as external - true or false(default) @@ -75,11 +76,18 @@ module API post do authenticated_as_admin! required_attributes! [:email, :password, :name, :username] - attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :bio, :location, :can_create_group, :admin, :confirm, :external, :organization] + attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :bio, :location, :can_create_group, :admin, :role_type, :confirm, :external, :organization] admin = attrs.delete(:admin) + role_type = attrs.delete(:role_type) confirm = !(attrs.delete(:confirm) =~ /(false|f|no|0)$/i) user = User.build_user(attrs) - user.admin = admin unless admin.nil? + + if admin == 'true' + user.role_type = User.role_types[:admin] + elsif User.role_types.keys.include?(role_type) + user.role_type = role_type + end + user.skip_confirmation! unless confirm identity_attrs = attributes_for_keys [:provider, :extern_uid] @@ -117,6 +125,7 @@ module API # bio - Bio # location - Location of the user # admin - User is admin - true or false (default) + # role_type - Possible role type to apply - regular (default), admin, auditor # can_create_group - User can create groups - true or false # external - Flags the user as external - true or false(default) # Example Request: @@ -124,12 +133,20 @@ module API put ":id" do authenticated_as_admin! - attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :bio, :location, :can_create_group, :admin, :external, :organization] + attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :bio, :location, :can_create_group, :admin, :role_type, :external, :organization] user = User.find(params[:id]) not_found!('User') unless user + role_type = attrs.delete(:role_type) admin = attrs.delete(:admin) - user.admin = admin unless admin.nil? + + if admin == 'true' + user.role_type = User.role_types[:admin] + elsif admin == 'false' + user.role_type = User.role_types[:regular] + elsif User.role_types.keys.include?(role_type) + user.role_type = role_type + end conflict!('Email has already been taken') if attrs[:email] && User.where(email: attrs[:email]). diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index dc630e76411..ce31c923feb 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -168,7 +168,7 @@ module Gitlab end def admin_user? - @user.is_admin? + @user.admin? end def parsed_relation_hash diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb index 9462f3368e6..f5803c201fe 100644 --- a/lib/gitlab/visibility_level.rb +++ b/lib/gitlab/visibility_level.rb @@ -40,7 +40,7 @@ module Gitlab end def allowed_for?(user, level) - user.is_admin? || allowed_level?(level.to_i) + user.admin? || allowed_level?(level.to_i) end # Return true if the specified level is allowed for the current user. diff --git a/lib/tasks/gitlab/bulk_add_permission.rake b/lib/tasks/gitlab/bulk_add_permission.rake index 83dd870fa31..fc46218db98 100644 --- a/lib/tasks/gitlab/bulk_add_permission.rake +++ b/lib/tasks/gitlab/bulk_add_permission.rake @@ -2,8 +2,8 @@ namespace :gitlab do namespace :import do desc "GitLab | Add all users to all projects (admin users are added as masters)" task all_users_to_all_projects: :environment do |t, args| - user_ids = User.where(admin: false).pluck(:id) - admin_ids = User.where(admin: true).pluck(:id) + user_ids = User.where(role_type: User.role_types[:regular]).pluck(:id) + admin_ids = User.where(role_type: User.role_types[:regular]).pluck(:id) project_ids = Project.pluck(:id) puts "Importing #{user_ids.size} users into #{project_ids.size} projects" @@ -23,8 +23,8 @@ namespace :gitlab do desc "GitLab | Add all users to all groups (admin users are added as owners)" task all_users_to_all_groups: :environment do |t, args| - user_ids = User.where(admin: false).pluck(:id) - admin_ids = User.where(admin: true).pluck(:id) + user_ids = User.where(role_type: User.role_types[:regular]).pluck(:id) + admin_ids = User.where(role_type: User.role_types[:admin]).pluck(:id) groups = Group.all puts "Importing #{user_ids.size} users into #{groups.size} groups" diff --git a/spec/controllers/admin/impersonations_controller_spec.rb b/spec/controllers/admin/impersonations_controller_spec.rb index 8be662974a0..b7fb712f368 100644 --- a/spec/controllers/admin/impersonations_controller_spec.rb +++ b/spec/controllers/admin/impersonations_controller_spec.rb @@ -39,7 +39,7 @@ describe Admin::ImpersonationsController do context "when the impersonator is not admin (anymore)" do before do - impersonator.admin = false + impersonator.role_type = User.role_types[:regular] impersonator.save end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index c6f7869516e..3efe2de9cd4 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -11,7 +11,11 @@ FactoryGirl.define do can_create_group true trait :admin do - admin true + role_type User.role_types[:admin] + end + + trait :auditor do + role_type User.role_types[:auditor] end trait :two_factor do @@ -51,5 +55,6 @@ FactoryGirl.define do end factory :admin, traits: [:admin] + factory :auditor, traits: [:auditor] end end diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb index cb3191dfdde..255816f09ea 100644 --- a/spec/features/admin/admin_users_spec.rb +++ b/spec/features/admin/admin_users_spec.rb @@ -208,7 +208,7 @@ describe "Admin::Users", feature: true do fill_in "user_email", with: "bigbang@mail.com" fill_in "user_password", with: "AValidPassword1" fill_in "user_password_confirmation", with: "AValidPassword1" - check "user_admin" + select "Admin", from: "user_role_type" click_button "Save changes" end @@ -220,9 +220,25 @@ describe "Admin::Users", feature: true do it "changes user entry" do @simple_user.reload expect(@simple_user.name).to eq('Big Bang') - expect(@simple_user.is_admin?).to be_truthy + expect(@simple_user.admin?).to be_truthy expect(@simple_user.password_expires_at).to be <= Time.now end end + + describe "Update user as auditor" do + before do + fill_in "user_name", with: "Big Bang" + fill_in "user_email", with: "bigbang@mail.com" + fill_in "user_password", with: "AValidPassword1" + fill_in "user_password_confirmation", with: "AValidPassword1" + select "Auditor", from: "user_role_type" + click_button "Save changes" + end + + it "changes user entry" do + @simple_user.reload + expect(@simple_user.auditor?).to be_truthy + end + end end end diff --git a/spec/features/explore/groups_spec.rb b/spec/features/explore/groups_spec.rb new file mode 100644 index 00000000000..5d6b1f3f444 --- /dev/null +++ b/spec/features/explore/groups_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +feature 'Explore Projects Tab', feature: true, js: true do + include WaitForAjax + + before do + create(:group, name: 'TestGroup', visibility_level: Gitlab::VisibilityLevel::PRIVATE) + + login_as user + visit explore_groups_path + wait_for_ajax + end + + context 'as an auditor' do + let(:user) { create(:auditor) } + + it 'shows private groups' do + expect(page).to have_content "TestGroup" + end + end + + context 'as a regular user' do + let(:user) { create(:user) } + + it 'does not show private groups' do + expect(page).not_to have_content "TestGroup" + end + end +end diff --git a/spec/features/explore/projects_spec.rb b/spec/features/explore/projects_spec.rb new file mode 100644 index 00000000000..ec98c5ba9e5 --- /dev/null +++ b/spec/features/explore/projects_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +feature 'Explore Projects Tab', feature: true, js: true do + include WaitForAjax + + before do + create :project, :public, name: 'Community Project' + create :project, :internal, name: 'Internal Project' + create :project, name: 'Enterprise Project' + create :project, :public, archived: true, name: 'Archived Project' + + login_as user + visit explore_projects_path + wait_for_ajax + end + + context 'as an auditor' do + let(:user) { create(:auditor) } + + it 'shows all projects' do + expect(page).to have_content 'Enterprise Project' + expect(page).to have_content 'Internal Project' + expect(page).to have_content 'Community Project' + expect(page).not_to have_content 'Archive Project' + end + end + + context 'as a regular user' do + let(:user) { create(:user) } + + it 'shows public projects' do + expect(page).to have_content 'Community Project' + expect(page).to have_content 'Internal Project' + expect(page).not_to have_content 'Enterprise Project' + expect(page).not_to have_content 'Archive Project' + end + end +end diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb index 1d4484a9edd..45d333184bb 100644 --- a/spec/features/projects/features_visibility_spec.rb +++ b/spec/features/projects/features_visibility_spec.rb @@ -99,7 +99,7 @@ describe 'Edit Project Settings', feature: true do context 'admin user' do before do - non_member.update_attribute(:admin, true) + non_member.update_attribute(:role_type, 'admin') login_as(non_member) end diff --git a/spec/features/security/admin_access_spec.rb b/spec/features/security/admin_access_spec.rb index fe8cd7b7602..81b08c42a19 100644 --- a/spec/features/security/admin_access_spec.rb +++ b/spec/features/security/admin_access_spec.rb @@ -9,6 +9,7 @@ describe "Admin::Projects", feature: true do it { is_expected.to be_allowed_for :admin } it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /admin/users" do @@ -17,6 +18,7 @@ describe "Admin::Projects", feature: true do it { is_expected.to be_allowed_for :admin } it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /admin/hooks" do @@ -25,5 +27,6 @@ describe "Admin::Projects", feature: true do it { is_expected.to be_allowed_for :admin } it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end end diff --git a/spec/features/security/dashboard_access_spec.rb b/spec/features/security/dashboard_access_spec.rb index 40f773956d1..390cc18ef12 100644 --- a/spec/features/security/dashboard_access_spec.rb +++ b/spec/features/security/dashboard_access_spec.rb @@ -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 :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :visitor } end @@ -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 :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :visitor } end @@ -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 :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :visitor } end @@ -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 :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :visitor } end @@ -41,6 +45,7 @@ describe "Dashboard access", feature: true do it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /koding" 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 :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :visitor } end end @@ -60,12 +66,14 @@ describe "Dashboard access", feature: true 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 :user } + it { expect(new_project_path).to be_allowed_for :auditor } it { expect(new_project_path).to be_denied_for :visitor } end describe "GET /groups/new" do 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 :auditor } it { expect(new_group_path).to be_denied_for :visitor } end @@ -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 :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :visitor } end end diff --git a/spec/features/security/group/internal_access_spec.rb b/spec/features/security/group/internal_access_spec.rb index 35fcef7a712..d21589a5f53 100644 --- a/spec/features/security/group/internal_access_spec.rb +++ b/spec/features/security/group/internal_access_spec.rb @@ -42,6 +42,7 @@ describe 'Internal Group access', feature: true do it { is_expected.to be_allowed_for guest } it { is_expected.to be_allowed_for project_guest } it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } end @@ -57,6 +58,7 @@ describe 'Internal Group access', feature: true do it { is_expected.to be_allowed_for guest } it { is_expected.to be_allowed_for project_guest } it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } end @@ -72,6 +74,7 @@ describe 'Internal Group access', feature: true do it { is_expected.to be_allowed_for guest } it { is_expected.to be_allowed_for project_guest } it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } end @@ -87,6 +90,7 @@ describe 'Internal Group access', feature: true do it { is_expected.to be_allowed_for guest } it { is_expected.to be_allowed_for project_guest } it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } end @@ -104,5 +108,6 @@ describe 'Internal Group access', feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :auditor } end end diff --git a/spec/features/security/group/private_access_spec.rb b/spec/features/security/group/private_access_spec.rb index 75a93342628..4fdb87c7cbd 100644 --- a/spec/features/security/group/private_access_spec.rb +++ b/spec/features/security/group/private_access_spec.rb @@ -35,6 +35,7 @@ describe 'Private Group access', feature: true do subject { group_path(group) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -50,6 +51,7 @@ describe 'Private Group access', feature: true do subject { issues_group_path(group) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -65,6 +67,7 @@ describe 'Private Group access', feature: true do subject { merge_requests_group_path(group) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -80,6 +83,7 @@ describe 'Private Group access', feature: true do subject { group_group_members_path(group) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -104,5 +108,6 @@ describe 'Private Group access', feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :auditor } end end diff --git a/spec/features/security/group/public_access_spec.rb b/spec/features/security/group/public_access_spec.rb index 6c5ee93970b..f2df37f78e9 100644 --- a/spec/features/security/group/public_access_spec.rb +++ b/spec/features/security/group/public_access_spec.rb @@ -20,7 +20,7 @@ describe 'Public Group access', feature: true do group.add_developer(developer) group.add_reporter(reporter) group.add_guest(guest) - + project.team << [project_guest, :guest] end @@ -35,6 +35,7 @@ describe 'Public Group access', feature: true do subject { group_path(group) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -50,6 +51,7 @@ describe 'Public Group access', feature: true do subject { issues_group_path(group) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -65,6 +67,7 @@ describe 'Public Group access', feature: true do subject { merge_requests_group_path(group) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -80,6 +83,7 @@ describe 'Public Group access', feature: true do subject { group_group_members_path(group) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -104,5 +108,6 @@ describe 'Public Group access', feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :auditor } end end diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb index c19678ab381..86fc58d9306 100644 --- a/spec/features/security/profile_access_spec.rb +++ b/spec/features/security/profile_access_spec.rb @@ -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 :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :visitor } end @@ -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 :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :visitor } end @@ -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 :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :visitor } end @@ -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 :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :visitor } end @@ -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 :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :visitor } end @@ -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 :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :visitor } end end diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb index b6acc509342..ec6831b1257 100644 --- a/spec/features/security/project/internal_access_spec.rb +++ b/spec/features/security/project/internal_access_spec.rb @@ -29,6 +29,7 @@ describe "Internal Project Access", feature: true do subject { namespace_project_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -43,6 +44,7 @@ describe "Internal Project Access", feature: true do subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -57,6 +59,7 @@ describe "Internal Project Access", feature: true do subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -71,6 +74,7 @@ describe "Internal Project Access", feature: true do subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -85,6 +89,7 @@ describe "Internal Project Access", feature: true do subject { namespace_project_compare_index_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -99,6 +104,7 @@ describe "Internal Project Access", feature: true do subject { namespace_project_project_members_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -114,6 +120,7 @@ describe "Internal Project Access", feature: true do subject { namespace_project_blob_path(project.namespace, project, File.join(commit.id, '.gitignore')) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -136,6 +143,7 @@ describe "Internal Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/deploy_keys" do @@ -150,12 +158,14 @@ describe "Internal Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/issues" do subject { namespace_project_issues_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -179,12 +189,14 @@ describe "Internal Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/snippets" do subject { namespace_project_snippets_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -207,12 +219,14 @@ describe "Internal Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/merge_requests" do subject { namespace_project_merge_requests_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -235,6 +249,7 @@ describe "Internal Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/branches" do @@ -246,6 +261,7 @@ describe "Internal Project Access", feature: true do end it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -265,6 +281,7 @@ describe "Internal Project Access", feature: true do end it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -287,12 +304,14 @@ describe "Internal Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/pipelines" do subject { namespace_project_pipelines_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -308,6 +327,7 @@ describe "Internal Project Access", feature: true do subject { namespace_project_pipeline_path(project.namespace, project, pipeline) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -325,6 +345,7 @@ describe "Internal Project Access", feature: true do before { project.update(public_builds: true) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -339,6 +360,7 @@ describe "Internal Project Access", feature: true do before { project.update(public_builds: false) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -359,6 +381,7 @@ describe "Internal Project Access", feature: true do before { project.update(public_builds: true) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -373,6 +396,7 @@ describe "Internal Project Access", feature: true do before { project.update(public_builds: false) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -388,6 +412,7 @@ describe "Internal Project Access", feature: true do subject { namespace_project_environments_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -403,6 +428,7 @@ describe "Internal Project Access", feature: true do subject { namespace_project_environment_path(project.namespace, project, environment) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -425,6 +451,7 @@ describe "Internal Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/container_registry" do @@ -436,6 +463,7 @@ describe "Internal Project Access", feature: true do subject { namespace_project_container_registry_index_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb index 79417c769a8..799f54cbc31 100644 --- a/spec/features/security/project/private_access_spec.rb +++ b/spec/features/security/project/private_access_spec.rb @@ -29,6 +29,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -43,6 +44,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -57,6 +59,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -71,6 +74,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -85,6 +89,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_compare_index_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -99,6 +104,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_project_members_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -114,6 +120,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_blob_path(project.namespace, project, File.join(commit.id, '.gitignore'))} it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -136,6 +143,7 @@ describe "Private Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/deploy_keys" do @@ -150,12 +158,14 @@ describe "Private Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/issues" do subject { namespace_project_issues_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -179,12 +189,14 @@ describe "Private Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/snippets" do subject { namespace_project_snippets_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -199,6 +211,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_merge_requests_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -218,6 +231,7 @@ describe "Private Project Access", feature: true do end it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -237,6 +251,7 @@ describe "Private Project Access", feature: true do end it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -259,12 +274,14 @@ describe "Private Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/pipelines" do subject { namespace_project_pipelines_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -280,6 +297,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_pipeline_path(project.namespace, project, pipeline) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -294,6 +312,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_builds_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -310,6 +329,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_build_path(project.namespace, project, build.id) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -324,6 +344,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_environments_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -339,6 +360,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_environment_path(project.namespace, project, environment) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -361,6 +383,7 @@ describe "Private Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/container_registry" do @@ -372,6 +395,7 @@ describe "Private Project Access", feature: true do subject { namespace_project_container_registry_index_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb index 985663e7c98..e88e4f38128 100644 --- a/spec/features/security/project/public_access_spec.rb +++ b/spec/features/security/project/public_access_spec.rb @@ -37,6 +37,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/tree/master" do @@ -51,6 +52,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/commits/master" do @@ -65,6 +67,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/commit/:sha" do @@ -79,6 +82,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/compare" do @@ -93,6 +97,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/project_members" do @@ -107,6 +112,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :visitor } it { is_expected.to be_allowed_for :external } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/pipelines" do @@ -121,6 +127,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/pipelines/:id" do @@ -136,6 +143,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/builds" do @@ -153,6 +161,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end context "when disallowed for public" do @@ -163,6 +172,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for guest } it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } @@ -187,6 +197,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end context "when disallowed for public" do @@ -197,6 +208,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for guest } it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } @@ -208,6 +220,7 @@ describe "Public Project Access", feature: true do subject { namespace_project_environments_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -223,6 +236,7 @@ describe "Public Project Access", feature: true do subject { namespace_project_environment_path(project.namespace, project, environment) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -245,6 +259,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/blob" do @@ -260,6 +275,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for guest } it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/edit" do @@ -274,6 +290,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/deploy_keys" do @@ -288,6 +305,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/issues" do @@ -302,6 +320,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/issues/:id/edit" do @@ -317,6 +336,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/snippets" do @@ -345,12 +365,14 @@ describe "Public Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/merge_requests" do subject { namespace_project_merge_requests_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -373,6 +395,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/branches" do @@ -392,6 +415,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/tags" do @@ -411,6 +435,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/hooks" do @@ -425,6 +450,7 @@ describe "Public Project Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/container_registry" do @@ -436,6 +462,7 @@ describe "Public Project Access", feature: true do subject { namespace_project_container_registry_index_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } diff --git a/spec/features/security/project/snippet/internal_access_spec.rb b/spec/features/security/project/snippet/internal_access_spec.rb index db53a9cec97..20a2abf8c0d 100644 --- a/spec/features/security/project/snippet/internal_access_spec.rb +++ b/spec/features/security/project/snippet/internal_access_spec.rb @@ -30,6 +30,7 @@ describe "Internal Project Snippets Access", feature: true do it { is_expected.to be_allowed_for reporter } it { is_expected.to be_allowed_for guest } it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } end @@ -46,6 +47,7 @@ describe "Internal Project Snippets Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/snippets/:id for an internal snippet" do @@ -58,6 +60,7 @@ describe "Internal Project Snippets Access", feature: true do it { is_expected.to be_allowed_for reporter } it { is_expected.to be_allowed_for guest } it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } end @@ -66,6 +69,7 @@ describe "Internal Project Snippets Access", feature: true do 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 :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } diff --git a/spec/features/security/project/snippet/private_access_spec.rb b/spec/features/security/project/snippet/private_access_spec.rb index d23d645c8e5..14967cd3c71 100644 --- a/spec/features/security/project/snippet/private_access_spec.rb +++ b/spec/features/security/project/snippet/private_access_spec.rb @@ -23,6 +23,7 @@ describe "Private Project Snippets Access", feature: true do subject { namespace_project_snippets_path(project.namespace, project) } it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } @@ -45,12 +46,14 @@ describe "Private Project Snippets Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/snippets/:id for a private snippet" do 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 :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } diff --git a/spec/features/security/project/snippet/public_access_spec.rb b/spec/features/security/project/snippet/public_access_spec.rb index e3665b6116a..42d8711cf09 100644 --- a/spec/features/security/project/snippet/public_access_spec.rb +++ b/spec/features/security/project/snippet/public_access_spec.rb @@ -33,6 +33,7 @@ describe "Public Project Snippets Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/snippets/new" do @@ -47,6 +48,7 @@ describe "Public Project Snippets Access", feature: true do it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_denied_for :auditor } end describe "GET /:project_path/snippets/:id for a public snippet" do @@ -61,6 +63,7 @@ describe "Public Project Snippets Access", feature: true do it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for :auditor } end describe "GET /:project_path/snippets/:id for an internal snippet" do @@ -73,6 +76,7 @@ describe "Public Project Snippets Access", feature: true do it { is_expected.to be_allowed_for reporter } it { is_expected.to be_allowed_for guest } it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :auditor } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } end @@ -81,6 +85,7 @@ describe "Public Project Snippets Access", feature: true do 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 :auditor } it { is_expected.to be_allowed_for owner } it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } diff --git a/spec/finders/groups_finder_spec.rb b/spec/finders/groups_finder_spec.rb index d5d111e8d15..4bfb161c51d 100644 --- a/spec/finders/groups_finder_spec.rb +++ b/spec/finders/groups_finder_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' describe GroupsFinder do describe '#execute' do let(:user) { create(:user) } + let(:auditor) { create(:auditor) } let!(:private_group) { create(:group, :private) } let!(:internal_group) { create(:group, :internal) } let!(:public_group) { create(:group, :public) } @@ -27,6 +28,11 @@ describe GroupsFinder do it { is_expected.to eq([public_group]) } end + + describe 'with an audit user' do + subject { finder.execute(auditor) } + it { is_expected.to eq([public_group, internal_group, private_group]) } + end end end end diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb index 13bda5f7c5a..a3a078ce521 100644 --- a/spec/finders/projects_finder_spec.rb +++ b/spec/finders/projects_finder_spec.rb @@ -2,7 +2,9 @@ require 'spec_helper' describe ProjectsFinder do describe '#execute' do - let(:user) { create(:user) } + let(:user) { create(:user) } + let(:auditor) { create(:auditor) } + let(:group) { create(:group, :public) } let!(:private_project) do @@ -47,6 +49,11 @@ describe ProjectsFinder do end end + describe 'with an audit user' do + subject { finder.execute(auditor) } + it { is_expected.to eq([shared_project, public_project, internal_project, private_project]) } + end + describe 'with project_ids_relation' do let(:project_ids_relation) { Project.where(id: internal_project.id) } diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index a5aa387f4f7..09e1b5488f6 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -191,7 +191,7 @@ describe Gitlab::GitAccess, lib: true do describe "#{role} access" do before do if role == :admin - user.update_attribute(:admin, true) + user.update_attribute(:role_type, 'admin') else project.team << [user, role] end diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index 1bdf005c823..dcacb5fc813 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -72,7 +72,7 @@ describe Ability, lib: true do let(:project) { create(:project, :internal) } it 'returns users that are administrators' do - user = build(:user, admin: true) + user = build(:user, role_type: 'admin') expect(described_class.users_that_can_read_project([user], project)). to eq([user]) @@ -123,7 +123,7 @@ describe Ability, lib: true do let(:project) { create(:project, :private) } it 'returns users that are administrators' do - user = build(:user, admin: true) + user = build(:user, role_type: 'admin') expect(described_class.users_that_can_read_project([user], project)). to eq([user]) @@ -174,7 +174,7 @@ describe Ability, lib: true do describe '.issues_readable_by_user' do context 'with an admin user' do it 'returns all given issues' do - user = build(:user, admin: true) + user = build(:user, role_type: 'admin') issue = build(:issue) expect(described_class.issues_readable_by_user([issue], user)). diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 60d30eb7418..ac73c2975eb 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -500,18 +500,18 @@ describe Issue, models: true do context 'with an admin user' do let(:project) { create(:empty_project) } - let(:user) { create(:admin) } + let(:admin) { create(:admin) } it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue).to be_readable_by(admin) end it 'returns true for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).to be_readable_by(user) + expect(issue).to be_readable_by(admin) end end end diff --git a/spec/models/project_feature_spec.rb b/spec/models/project_feature_spec.rb index a55d43ab2f9..93317c6db7a 100644 --- a/spec/models/project_feature_spec.rb +++ b/spec/models/project_feature_spec.rb @@ -45,7 +45,7 @@ describe ProjectFeature do end it "returns true if user is an admin" do - user.update_attribute(:admin, true) + user.update_attribute(:role_type, 'admin') features.each do |feature| project.project_feature.update_attribute("#{feature}_access_level".to_sym, ProjectFeature::PRIVATE) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 65b2896930a..ccfbffafb10 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -259,7 +259,7 @@ describe User, models: true do end describe "Respond to" do - it { is_expected.to respond_to(:is_admin?) } + it { is_expected.to respond_to(:admin?) } it { is_expected.to respond_to(:name) } it { is_expected.to respond_to(:private_token) } it { is_expected.to respond_to(:external?) } @@ -490,7 +490,7 @@ describe User, models: true do describe 'normal user' do let(:user) { create(:user, name: 'John Smith') } - it { expect(user.is_admin?).to be_falsey } + it { expect(user.admin?).to be_falsey } it { expect(user.require_ssh_key?).to be_truthy } it { expect(user.can_create_group?).to be_truthy } it { expect(user.can_create_project?).to be_truthy } diff --git a/spec/requests/api/session_spec.rb b/spec/requests/api/session_spec.rb index acad1365ace..423cffae058 100644 --- a/spec/requests/api/session_spec.rb +++ b/spec/requests/api/session_spec.rb @@ -13,7 +13,7 @@ describe API::API, api: true do expect(json_response['email']).to eq(user.email) expect(json_response['private_token']).to eq(user.private_token) - expect(json_response['is_admin']).to eq(user.is_admin?) + expect(json_response['is_admin']).to eq(user.admin?) expect(json_response['can_create_project']).to eq(user.can_create_project?) expect(json_response['can_create_group']).to eq(user.can_create_group?) end @@ -37,7 +37,7 @@ describe API::API, api: true do expect(json_response['email']).to eq user.email expect(json_response['private_token']).to eq user.private_token - expect(json_response['is_admin']).to eq user.is_admin? + expect(json_response['is_admin']).to eq user.admin? expect(json_response['can_create_project']).to eq user.can_create_project? expect(json_response['can_create_group']).to eq user.can_create_group? end @@ -50,7 +50,7 @@ describe API::API, api: true do expect(json_response['email']).to eq user.email expect(json_response['private_token']).to eq user.private_token - expect(json_response['is_admin']).to eq user.is_admin? + expect(json_response['is_admin']).to eq user.admin? expect(json_response['can_create_project']).to eq user.can_create_project? expect(json_response['can_create_group']).to eq user.can_create_group? end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index d48752473f3..e44521fa682 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -6,9 +6,9 @@ describe API::API, api: true do let(:user) { create(:user) } let(:admin) { create(:admin) } let(:key) { create(:key, user: user) } - let(:email) { create(:email, user: user) } - let(:omniauth_user) { create(:omniauth_user) } - let(:ldap_user) { create(:omniauth_user, provider: 'ldapmain') } + let(:email) { create(:email, user: user) } + let(:omniauth_user) { create(:omniauth_user) } + let(:ldap_user) { create(:omniauth_user, provider: 'ldapmain') } let(:ldap_blocked_user) { create(:omniauth_user, provider: 'ldapmain', state: 'ldap_blocked') } describe "GET /users" do @@ -106,23 +106,43 @@ describe API::API, api: true do end.to change { User.count }.by(1) end - it "creates user with correct attributes" do + it "creates user with correct attributes with admin bool" do post api('/users', admin), attributes_for(:user, admin: true, can_create_group: true) expect(response).to have_http_status(201) user_id = json_response['id'] new_user = User.find(user_id) expect(new_user).not_to eq(nil) - expect(new_user.admin).to eq(true) + expect(new_user.admin?).to eq(true) + expect(new_user.can_create_group).to eq(true) + end + + it "creates user with correct attributes" do + post api('/users', admin), attributes_for(:user, role_type: 'admin', can_create_group: true) + expect(response).to have_http_status(201) + user_id = json_response['id'] + new_user = User.find(user_id) + expect(new_user).not_to eq(nil) + expect(new_user.admin?).to eq(true) expect(new_user.can_create_group).to eq(true) end it "creates non-admin user" do - post api('/users', admin), attributes_for(:user, admin: false, can_create_group: false) + post api('/users', admin), attributes_for(:user, can_create_group: false) + expect(response).to have_http_status(201) + user_id = json_response['id'] + new_user = User.find(user_id) + expect(new_user).not_to eq(nil) + expect(new_user.admin?).to eq(false) + expect(new_user.can_create_group).to eq(false) + end + + it "creates auditor user" do + post api('/users', admin), attributes_for(:user, role_type: 'auditor', can_create_group: false) expect(response).to have_http_status(201) user_id = json_response['id'] new_user = User.find(user_id) expect(new_user).not_to eq(nil) - expect(new_user.admin).to eq(false) + expect(new_user.auditor?).to eq(true) expect(new_user.can_create_group).to eq(false) end @@ -132,7 +152,7 @@ describe API::API, api: true do user_id = json_response['id'] new_user = User.find(user_id) expect(new_user).not_to eq(nil) - expect(new_user.admin).to eq(false) + expect(new_user.admin?).to eq(false) end it "returns 201 Created on success" do @@ -302,11 +322,36 @@ describe API::API, api: true do expect(user.reload.identities.first.provider).to eq('github') end - it "updates admin status" do + it "updates admin status with admin bool" do put api("/users/#{user.id}", admin), { admin: true } expect(response).to have_http_status(200) expect(json_response['is_admin']).to eq(true) - expect(user.reload.admin).to eq(true) + expect(json_response['role_type']).to eq('admin') + expect(user.reload.admin?).to eq(true) + end + + it "updates admin status with admin bool to regular user" do + put api("/users/#{user.id}", admin), { admin: false } + expect(response).to have_http_status(200) + expect(json_response['is_admin']).to eq(false) + expect(json_response['role_type']).to eq('regular') + expect(user.reload.admin?).to eq(false) + end + + it "updates admin status" do + put api("/users/#{user.id}", admin), { role_type: 'admin' } + expect(response).to have_http_status(200) + expect(json_response['is_admin']).to eq(true) + expect(json_response['role_type']).to eq('admin') + expect(user.reload.admin?).to eq(true) + end + + it "updates auditor status" do + put api("/users/#{user.id}", admin), { role_type: 'auditor' } + expect(response).to have_http_status(200) + expect(json_response['is_auditor']).to eq(true) + expect(json_response['role_type']).to eq('auditor') + expect(user.reload.auditor?).to eq(true) end it "updates external status" do @@ -320,7 +365,8 @@ describe API::API, api: true do put api("/users/#{admin_user.id}", admin), { can_create_group: false } expect(response).to have_http_status(200) expect(json_response['is_admin']).to eq(true) - expect(admin_user.reload.admin).to eq(true) + expect(json_response['role_type']).to eq('admin') + expect(admin_user.reload.admin?).to eq(true) expect(admin_user.can_create_group).to eq(false) end @@ -619,7 +665,7 @@ describe API::API, api: true do get api("/user", user) expect(response).to have_http_status(200) expect(json_response['email']).to eq(user.email) - expect(json_response['is_admin']).to eq(user.is_admin?) + expect(json_response['is_admin']).to eq(user.admin?) expect(json_response['can_create_project']).to eq(user.can_create_project?) expect(json_response['can_create_group']).to eq(user.can_create_group?) expect(json_response['projects_limit']).to eq(user.projects_limit) diff --git a/spec/services/create_snippet_service_spec.rb b/spec/services/create_snippet_service_spec.rb index d81d0fd76c9..c620d66c900 100644 --- a/spec/services/create_snippet_service_spec.rb +++ b/spec/services/create_snippet_service_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe CreateSnippetService, services: true do before do @user = create :user - @admin = create :user, admin: true + @admin = create :admin @opts = { title: 'Test snippet', file_name: 'snippet.rb', diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb index e139be19140..609aa4ce6e3 100644 --- a/spec/services/projects/update_service_spec.rb +++ b/spec/services/projects/update_service_spec.rb @@ -4,7 +4,7 @@ describe Projects::UpdateService, services: true do describe :update_by_user do before do @user = create :user - @admin = create :user, admin: true + @admin = create :admin @project = create :project, creator_id: @user.id, namespace: @user.namespace @opts = {} end @@ -101,7 +101,7 @@ describe Projects::UpdateService, services: true do end describe :visibility_level do - let(:user) { create :user, admin: true } + let(:user) { create :admin } let(:project) { create(:project, :internal) } let(:forked_project) { create(:forked_project_with_submodules, :internal) } let(:opts) { {} } diff --git a/spec/services/update_snippet_service_spec.rb b/spec/services/update_snippet_service_spec.rb index 37c2e861362..3ef8c360a89 100644 --- a/spec/services/update_snippet_service_spec.rb +++ b/spec/services/update_snippet_service_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe UpdateSnippetService, services: true do before do @user = create :user - @admin = create :user, admin: true + @admin = create :admin @opts = { title: 'Test snippet', file_name: 'snippet.rb', diff --git a/spec/support/matchers/access_matchers.rb b/spec/support/matchers/access_matchers.rb index 0497e391860..c2ef24079aa 100644 --- a/spec/support/matchers/access_matchers.rb +++ b/spec/support/matchers/access_matchers.rb @@ -17,6 +17,8 @@ module AccessMatchers login_as(create(:admin)) when :external login_as(create(:user, external: true)) + when :auditor + login_as(create(:auditor)) when User login_as(user) else |