Make GitLab pages support access control
This commit is contained in:
parent
c972f2e459
commit
c84b60b164
|
|
@ -1 +1 @@
|
|||
1.1.0
|
||||
1.2.0
|
||||
|
|
|
|||
|
|
@ -52,6 +52,21 @@
|
|||
required: false,
|
||||
default: '',
|
||||
},
|
||||
pagesAvailable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
pagesAccessControlEnabled: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
pagesHelpPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
@ -64,6 +79,7 @@
|
|||
buildsAccessLevel: 20,
|
||||
wikiAccessLevel: 20,
|
||||
snippetsAccessLevel: 20,
|
||||
pagesAccessLevel: 20,
|
||||
containerRegistryEnabled: true,
|
||||
lfsEnabled: true,
|
||||
requestAccessEnabled: true,
|
||||
|
|
@ -90,6 +106,13 @@
|
|||
);
|
||||
},
|
||||
|
||||
pagesFeatureAccessLevelOptions() {
|
||||
if (this.visibilityLevel !== visibilityOptions.PUBLIC) {
|
||||
return this.featureAccessLevelOptions.concat([[30, 'Everyone']]);
|
||||
}
|
||||
return this.featureAccessLevelOptions;
|
||||
},
|
||||
|
||||
repositoryEnabled() {
|
||||
return this.repositoryAccessLevel > 0;
|
||||
},
|
||||
|
|
@ -109,6 +132,10 @@
|
|||
this.buildsAccessLevel = Math.min(10, this.buildsAccessLevel);
|
||||
this.wikiAccessLevel = Math.min(10, this.wikiAccessLevel);
|
||||
this.snippetsAccessLevel = Math.min(10, this.snippetsAccessLevel);
|
||||
if (this.pagesAccessLevel === 20) {
|
||||
// When from Internal->Private narrow access for only members
|
||||
this.pagesAccessLevel = 10;
|
||||
}
|
||||
this.highlightChanges();
|
||||
} else if (oldValue === visibilityOptions.PRIVATE) {
|
||||
// if changing away from private, make enabled features more permissive
|
||||
|
|
@ -118,6 +145,7 @@
|
|||
if (this.buildsAccessLevel > 0) this.buildsAccessLevel = 20;
|
||||
if (this.wikiAccessLevel > 0) this.wikiAccessLevel = 20;
|
||||
if (this.snippetsAccessLevel > 0) this.snippetsAccessLevel = 20;
|
||||
if (this.pagesAccessLevel === 10) this.pagesAccessLevel = 20;
|
||||
this.highlightChanges();
|
||||
}
|
||||
},
|
||||
|
|
@ -323,6 +351,18 @@
|
|||
name="project[project_feature_attributes][snippets_access_level]"
|
||||
/>
|
||||
</project-setting-row>
|
||||
<project-setting-row
|
||||
v-if="pagesAvailable && pagesAccessControlEnabled"
|
||||
:help-path="pagesHelpPath"
|
||||
label="Pages"
|
||||
help-text="Static website for the project."
|
||||
>
|
||||
<project-feature-setting
|
||||
v-model="pagesAccessLevel"
|
||||
:options="pagesFeatureAccessLevelOptions"
|
||||
name="project[project_feature_attributes][pages_access_level]"
|
||||
/>
|
||||
</project-setting-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -366,6 +366,7 @@ class ProjectsController < Projects::ApplicationController
|
|||
repository_access_level
|
||||
snippets_access_level
|
||||
wiki_access_level
|
||||
pages_access_level
|
||||
]
|
||||
]
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ module Types
|
|||
:create_deployment, :push_to_delete_protected_branch,
|
||||
:admin_wiki, :admin_project, :update_pages,
|
||||
:admin_remote_mirror, :create_label, :update_wiki, :destroy_wiki,
|
||||
:create_pages, :destroy_pages
|
||||
:create_pages, :destroy_pages, :read_pages_content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -454,6 +454,7 @@ module ProjectsHelper
|
|||
buildsAccessLevel: feature.builds_access_level,
|
||||
wikiAccessLevel: feature.wiki_access_level,
|
||||
snippetsAccessLevel: feature.snippets_access_level,
|
||||
pagesAccessLevel: feature.pages_access_level,
|
||||
containerRegistryEnabled: !!project.container_registry_enabled,
|
||||
lfsEnabled: !!project.lfs_enabled
|
||||
}
|
||||
|
|
@ -468,7 +469,10 @@ module ProjectsHelper
|
|||
registryAvailable: Gitlab.config.registry.enabled,
|
||||
registryHelpPath: help_page_path('user/project/container_registry'),
|
||||
lfsAvailable: Gitlab.config.lfs.enabled,
|
||||
lfsHelpPath: help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
|
||||
lfsHelpPath: help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs'),
|
||||
pagesAvailable: Gitlab.config.pages.enabled,
|
||||
pagesAccessControlEnabled: Gitlab.config.pages.access_control,
|
||||
pagesHelpPath: help_page_path('user/project/pages/index.md')
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ class Project < ActiveRecord::Base
|
|||
cache_markdown_field :description, pipeline: :description
|
||||
|
||||
delegate :feature_available?, :builds_enabled?, :wiki_enabled?,
|
||||
:merge_requests_enabled?, :issues_enabled?, to: :project_feature,
|
||||
allow_nil: true
|
||||
:merge_requests_enabled?, :issues_enabled?, :pages_enabled?, :public_pages?,
|
||||
to: :project_feature, allow_nil: true
|
||||
|
||||
delegate :base_dir, :disk_path, :ensure_storage_path_exists, to: :storage
|
||||
|
||||
|
|
@ -356,7 +356,7 @@ class Project < ActiveRecord::Base
|
|||
# "enabled" here means "not disabled". It includes private features!
|
||||
scope :with_feature_enabled, ->(feature) {
|
||||
access_level_attribute = ProjectFeature.access_level_attribute(feature)
|
||||
with_project_feature.where(project_features: { access_level_attribute => [nil, ProjectFeature::PRIVATE, ProjectFeature::ENABLED] })
|
||||
with_project_feature.where(project_features: { access_level_attribute => [nil, ProjectFeature::PRIVATE, ProjectFeature::ENABLED, ProjectFeature::PUBLIC] })
|
||||
}
|
||||
|
||||
# Picks a feature where the level is exactly that given.
|
||||
|
|
@ -418,15 +418,15 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
# project features may be "disabled", "internal" or "enabled". If "internal",
|
||||
# project features may be "disabled", "internal", "enabled" or "public". If "internal",
|
||||
# they are only available to team members. This scope returns projects where
|
||||
# the feature is either enabled, or internal with permission for the user.
|
||||
# the feature is either public, enabled, or internal with permission for the user.
|
||||
#
|
||||
# This method uses an optimised version of `with_feature_access_level` for
|
||||
# logged in users to more efficiently get private projects with the given
|
||||
# feature.
|
||||
def self.with_feature_available_for_user(feature, user)
|
||||
visible = [nil, ProjectFeature::ENABLED]
|
||||
visible = [nil, ProjectFeature::ENABLED, ProjectFeature::PUBLIC]
|
||||
|
||||
if user&.admin?
|
||||
with_feature_enabled(feature)
|
||||
|
|
|
|||
|
|
@ -13,14 +13,16 @@ class ProjectFeature < ActiveRecord::Base
|
|||
# Disabled: not enabled for anyone
|
||||
# Private: enabled only for team members
|
||||
# Enabled: enabled for everyone able to access the project
|
||||
# Public: enabled for everyone (only allowed for pages)
|
||||
#
|
||||
|
||||
# Permission levels
|
||||
DISABLED = 0
|
||||
PRIVATE = 10
|
||||
ENABLED = 20
|
||||
PUBLIC = 30
|
||||
|
||||
FEATURES = %i(issues merge_requests wiki snippets builds repository).freeze
|
||||
FEATURES = %i(issues merge_requests wiki snippets builds repository pages).freeze
|
||||
|
||||
class << self
|
||||
def access_level_attribute(feature)
|
||||
|
|
@ -46,6 +48,7 @@ class ProjectFeature < ActiveRecord::Base
|
|||
validates :project, presence: true
|
||||
|
||||
validate :repository_children_level
|
||||
validate :allowed_access_levels
|
||||
|
||||
default_value_for :builds_access_level, value: ENABLED, allows_nil: false
|
||||
default_value_for :issues_access_level, value: ENABLED, allows_nil: false
|
||||
|
|
@ -81,6 +84,16 @@ class ProjectFeature < ActiveRecord::Base
|
|||
issues_access_level > DISABLED
|
||||
end
|
||||
|
||||
def pages_enabled?
|
||||
pages_access_level > DISABLED
|
||||
end
|
||||
|
||||
def public_pages?
|
||||
return true unless Gitlab.config.pages.access_control
|
||||
|
||||
pages_access_level == PUBLIC || pages_access_level == ENABLED && project.public?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Validates builds and merge requests access level
|
||||
|
|
@ -95,6 +108,17 @@ class ProjectFeature < ActiveRecord::Base
|
|||
%i(merge_requests_access_level builds_access_level).each(&validator)
|
||||
end
|
||||
|
||||
# Validates access level for other than pages cannot be PUBLIC
|
||||
def allowed_access_levels
|
||||
validator = lambda do |field|
|
||||
level = public_send(field) || ProjectFeature::ENABLED # rubocop:disable GitlabSecurity/PublicSend
|
||||
not_allowed = level > ProjectFeature::ENABLED
|
||||
self.errors.add(field, "cannot have public visibility level") if not_allowed
|
||||
end
|
||||
|
||||
(FEATURES - %i(pages)).each {|f| validator.call("#{f}_access_level")}
|
||||
end
|
||||
|
||||
def get_permission(user, level)
|
||||
case level
|
||||
when DISABLED
|
||||
|
|
@ -103,6 +127,8 @@ class ProjectFeature < ActiveRecord::Base
|
|||
user && (project.team.member?(user) || user.full_private_access?)
|
||||
when ENABLED
|
||||
true
|
||||
when PUBLIC
|
||||
true
|
||||
else
|
||||
true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ class ProjectPolicy < BasePolicy
|
|||
snippets
|
||||
wiki
|
||||
builds
|
||||
pages
|
||||
]
|
||||
|
||||
features.each do |f|
|
||||
|
|
@ -167,6 +168,7 @@ class ProjectPolicy < BasePolicy
|
|||
enable :upload_file
|
||||
enable :read_cycle_analytics
|
||||
enable :award_emoji
|
||||
enable :read_pages_content
|
||||
end
|
||||
|
||||
# These abilities are not allowed to admins that are not members of the project,
|
||||
|
|
@ -286,6 +288,8 @@ class ProjectPolicy < BasePolicy
|
|||
prevent(*create_read_update_admin_destroy(:merge_request))
|
||||
end
|
||||
|
||||
rule { pages_disabled }.prevent :read_pages_content
|
||||
|
||||
rule { issues_disabled & merge_requests_disabled }.policy do
|
||||
prevent(*create_read_update_admin_destroy(:label))
|
||||
prevent(*create_read_update_admin_destroy(:milestone))
|
||||
|
|
@ -345,6 +349,7 @@ class ProjectPolicy < BasePolicy
|
|||
enable :download_code
|
||||
enable :download_wiki_code
|
||||
enable :read_cycle_analytics
|
||||
enable :read_pages_content
|
||||
|
||||
# NOTE: may be overridden by IssuePolicy
|
||||
enable :read_issue
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@ module Projects
|
|||
def pages_config
|
||||
{
|
||||
domains: pages_domains_config,
|
||||
https_only: project.pages_https_only?
|
||||
https_only: project.pages_https_only?,
|
||||
id: project.project_id,
|
||||
access_control: !project.public_pages?
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -31,7 +33,9 @@ module Projects
|
|||
domain: domain.domain,
|
||||
certificate: domain.certificate,
|
||||
key: domain.key,
|
||||
https_only: project.pages_https_only? && domain.https?
|
||||
https_only: project.pages_https_only? && domain.https?,
|
||||
id: project.project_id,
|
||||
access_control: !project.public_pages?
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -72,7 +72,11 @@ module Projects
|
|||
system_hook_service.execute_hooks_for(project, :update)
|
||||
end
|
||||
|
||||
update_pages_config if changing_pages_https_only?
|
||||
update_pages_config if changing_pages_related_config?
|
||||
end
|
||||
|
||||
def changing_pages_related_config?
|
||||
changing_pages_https_only? || changing_pages_access_level?
|
||||
end
|
||||
|
||||
def update_failed!
|
||||
|
|
@ -102,6 +106,10 @@ module Projects
|
|||
params.dig(:project_feature_attributes, :wiki_access_level).to_i > ProjectFeature::DISABLED
|
||||
end
|
||||
|
||||
def changing_pages_access_level?
|
||||
params.dig(:project_feature_attributes, :pages_access_level)
|
||||
end
|
||||
|
||||
def ensure_wiki_exists
|
||||
ProjectWiki.new(project, project.owner).wiki
|
||||
rescue ProjectWiki::CouldNotCreateWikiError
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add access control to GitLab pages and make it possible to enable/disable it in project settings
|
||||
merge_request: 18589
|
||||
author: Tuomo Ala-Vannesluoma
|
||||
type: added
|
||||
|
|
@ -210,6 +210,7 @@ production: &base
|
|||
## GitLab Pages
|
||||
pages:
|
||||
enabled: false
|
||||
access_control: false
|
||||
# The location where pages are stored (default: shared/pages).
|
||||
# path: shared/pages
|
||||
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ Settings.registry['path'] = Settings.absolute(Settings.registry['path
|
|||
#
|
||||
Settings['pages'] ||= Settingslogic.new({})
|
||||
Settings.pages['enabled'] = false if Settings.pages['enabled'].nil?
|
||||
Settings.pages['access_control'] = false if Settings.pages['access_control'].nil?
|
||||
Settings.pages['path'] = Settings.absolute(Settings.pages['path'] || File.join(Settings.shared['path'], "pages"))
|
||||
Settings.pages['https'] = false if Settings.pages['https'].nil?
|
||||
Settings.pages['host'] ||= "example.com"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
class AddPagesAccessLevelToProjectFeature < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
disable_ddl_transaction!
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
def up
|
||||
add_column_with_default(:project_features, :pages_access_level, :integer, default: ProjectFeature::PUBLIC, allow_null: false)
|
||||
|
||||
change_column_default(:project_features, :pages_access_level, ProjectFeature::ENABLED)
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :project_features, :pages_access_level
|
||||
end
|
||||
end
|
||||
|
|
@ -1578,6 +1578,7 @@ ActiveRecord::Schema.define(version: 20180924141949) do
|
|||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "repository_access_level", default: 20, null: false
|
||||
t.integer "pages_access_level", default: 20, null: false
|
||||
end
|
||||
|
||||
add_index "project_features", ["project_id"], name: "index_project_features_on_project_id", unique: true, using: :btree
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ which visibility level you select on project settings.
|
|||
- Disabled: disabled for everyone
|
||||
- Only team members: only team members will see even if your project is public or internal
|
||||
- Everyone with access: everyone can see depending on your project visibility level
|
||||
- Everyone: enabled for everyone (only available for GitLab Pages)
|
||||
|
||||
### Protected branches
|
||||
|
||||
|
|
@ -242,6 +243,7 @@ which visibility level you select on project settings.
|
|||
- Disabled: disabled for everyone
|
||||
- Only team members: only team members will see even if your project is public or internal
|
||||
- Everyone with access: everyone can see depending on your project visibility level
|
||||
- Everyone: enabled for everyone (only available for GitLab Pages)
|
||||
|
||||
## GitLab CI/CD permissions
|
||||
|
||||
|
|
|
|||
|
|
@ -287,6 +287,12 @@ module API
|
|||
present_projects forks
|
||||
end
|
||||
|
||||
desc 'Check pages access of this project'
|
||||
get ':id/pages_access' do
|
||||
authorize! :read_pages_content, user_project unless user_project.public_pages?
|
||||
status 200
|
||||
end
|
||||
|
||||
desc 'Update an existing project' do
|
||||
success Entities::Project
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
require_relative '../support/helpers/test_env'
|
||||
|
||||
FactoryBot.define do
|
||||
PAGES_ACCESS_LEVEL_SCHEMA_VERSION = 20180423204600
|
||||
|
||||
# Project without repository
|
||||
#
|
||||
# Project does not have bare repository.
|
||||
|
|
@ -23,6 +25,7 @@ FactoryBot.define do
|
|||
issues_access_level ProjectFeature::ENABLED
|
||||
merge_requests_access_level ProjectFeature::ENABLED
|
||||
repository_access_level ProjectFeature::ENABLED
|
||||
pages_access_level ProjectFeature::ENABLED
|
||||
|
||||
# we can't assign the delegated `#ci_cd_settings` attributes directly, as the
|
||||
# `#ci_cd_settings` relation needs to be created first
|
||||
|
|
@ -34,13 +37,20 @@ FactoryBot.define do
|
|||
builds_access_level = [evaluator.builds_access_level, evaluator.repository_access_level].min
|
||||
merge_requests_access_level = [evaluator.merge_requests_access_level, evaluator.repository_access_level].min
|
||||
|
||||
project.project_feature.update(
|
||||
hash = {
|
||||
wiki_access_level: evaluator.wiki_access_level,
|
||||
builds_access_level: builds_access_level,
|
||||
snippets_access_level: evaluator.snippets_access_level,
|
||||
issues_access_level: evaluator.issues_access_level,
|
||||
merge_requests_access_level: merge_requests_access_level,
|
||||
repository_access_level: evaluator.repository_access_level)
|
||||
repository_access_level: evaluator.repository_access_level
|
||||
}
|
||||
|
||||
if ActiveRecord::Migrator.current_version >= PAGES_ACCESS_LEVEL_SCHEMA_VERSION
|
||||
hash.store("pages_access_level", evaluator.pages_access_level)
|
||||
end
|
||||
|
||||
project.project_feature.update(hash)
|
||||
|
||||
# Normally the class Projects::CreateService is used for creating
|
||||
# projects, and this class takes care of making sure the owner and current
|
||||
|
|
@ -244,6 +254,10 @@ FactoryBot.define do
|
|||
trait(:repository_enabled) { repository_access_level ProjectFeature::ENABLED }
|
||||
trait(:repository_disabled) { repository_access_level ProjectFeature::DISABLED }
|
||||
trait(:repository_private) { repository_access_level ProjectFeature::PRIVATE }
|
||||
trait(:pages_public) { pages_access_level ProjectFeature::PUBLIC }
|
||||
trait(:pages_enabled) { pages_access_level ProjectFeature::ENABLED }
|
||||
trait(:pages_disabled) { pages_access_level ProjectFeature::DISABLED }
|
||||
trait(:pages_private) { pages_access_level ProjectFeature::PRIVATE }
|
||||
|
||||
trait :auto_devops do
|
||||
association :auto_devops, factory: :project_auto_devops
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ describe Types::PermissionTypes::Project do
|
|||
:read_commit_status, :request_access, :create_pipeline, :create_pipeline_schedule,
|
||||
:create_merge_request_from, :create_wiki, :push_code, :create_deployment, :push_to_delete_protected_branch,
|
||||
:admin_wiki, :admin_project, :update_pages, :admin_remote_mirror, :create_label,
|
||||
:update_wiki, :destroy_wiki, :create_pages, :destroy_pages
|
||||
:update_wiki, :destroy_wiki, :create_pages, :destroy_pages, :read_pages_content
|
||||
]
|
||||
|
||||
expect(described_class).to have_graphql_fields(expected_permissions)
|
||||
|
|
|
|||
|
|
@ -492,6 +492,7 @@ ProjectFeature:
|
|||
- snippets_access_level
|
||||
- builds_access_level
|
||||
- repository_access_level
|
||||
- pages_access_level
|
||||
- created_at
|
||||
- updated_at
|
||||
ProtectedBranch::MergeAccessLevel:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
require 'spec_helper'
|
||||
require Rails.root.join('db', 'migrate', '20180423204600_add_pages_access_level_to_project_feature.rb')
|
||||
|
||||
describe AddPagesAccessLevelToProjectFeature, :migration do
|
||||
let(:namespaces) { table(:namespaces) }
|
||||
let(:projects) { table(:projects) }
|
||||
let(:features) { table(:project_features) }
|
||||
let!(:namespace) { namespaces.create(name: 'gitlab', path: 'gitlab') }
|
||||
let!(:first_project) { projects.create(name: 'gitlab1', path: 'gitlab1', namespace_id: namespace.id) }
|
||||
let!(:first_project_features) { features.create(project_id: first_project.id) }
|
||||
let!(:second_project) { projects.create(name: 'gitlab2', path: 'gitlab2', namespace_id: namespace.id) }
|
||||
let!(:second_project_features) { features.create(project_id: second_project.id) }
|
||||
|
||||
it 'correctly migrate pages for old projects to be public' do
|
||||
migrate!
|
||||
|
||||
# For old projects pages should be public
|
||||
expect(first_project_features.reload.pages_access_level).to eq ProjectFeature::PUBLIC
|
||||
expect(second_project_features.reload.pages_access_level).to eq ProjectFeature::PUBLIC
|
||||
end
|
||||
|
||||
it 'after migration pages are enabled as default' do
|
||||
migrate!
|
||||
|
||||
# For new project default is enabled
|
||||
third_project = projects.create(name: 'gitlab3', path: 'gitlab3', namespace_id: namespace.id)
|
||||
third_project_features = features.create(project_id: third_project.id)
|
||||
expect(third_project_features.reload.pages_access_level).to eq ProjectFeature::ENABLED
|
||||
end
|
||||
end
|
||||
|
|
@ -65,7 +65,8 @@ describe InternalId do
|
|||
context 'with an insufficient schema version' do
|
||||
before do
|
||||
described_class.reset_column_information
|
||||
expect(ActiveRecord::Migrator).to receive(:current_version).and_return(InternalId::REQUIRED_SCHEMA_VERSION - 1)
|
||||
# Project factory will also call the current_version
|
||||
expect(ActiveRecord::Migrator).to receive(:current_version).twice.and_return(InternalId::REQUIRED_SCHEMA_VERSION - 1)
|
||||
end
|
||||
|
||||
let(:init) { double('block') }
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ describe ProjectFeature do
|
|||
end
|
||||
|
||||
describe '#feature_available?' do
|
||||
let(:features) { %w(issues wiki builds merge_requests snippets repository) }
|
||||
let(:features) { %w(issues wiki builds merge_requests snippets repository pages) }
|
||||
|
||||
context 'when features are disabled' do
|
||||
it "returns false" do
|
||||
|
|
@ -112,6 +112,19 @@ describe ProjectFeature do
|
|||
end
|
||||
end
|
||||
|
||||
context 'public features' do
|
||||
it "does not allow public for other than pages" do
|
||||
features = %w(issues wiki builds merge_requests snippets repository)
|
||||
project_feature = project.project_feature
|
||||
|
||||
features.each do |feature|
|
||||
field = "#{feature}_access_level".to_sym
|
||||
project_feature.update_attribute(field, ProjectFeature::PUBLIC)
|
||||
expect(project_feature.valid?).to be_falsy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#*_enabled?' do
|
||||
let(:features) { %w(wiki builds merge_requests) }
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe "Internal Project Pages Access" do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
include AccessMatchers
|
||||
|
||||
set(:group) { create(:group) }
|
||||
set(:project) { create(:project, :internal, pages_access_level: ProjectFeature::ENABLED, namespace: group) }
|
||||
|
||||
set(:admin) { create(:admin) }
|
||||
set(:owner) { create(:user) }
|
||||
set(:master) { create(:user) }
|
||||
set(:developer) { create(:user) }
|
||||
set(:reporter) { create(:user) }
|
||||
set(:guest) { create(:user) }
|
||||
set(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
allow(Gitlab.config.pages).to receive(:access_control).and_return(true)
|
||||
group.add_owner(owner)
|
||||
project.add_master(master)
|
||||
project.add_developer(developer)
|
||||
project.add_reporter(reporter)
|
||||
project.add_guest(guest)
|
||||
end
|
||||
|
||||
describe "Project should be internal" do
|
||||
describe '#internal?' do
|
||||
subject { project.internal? }
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /projects/:id/pages_access" do
|
||||
context 'access depends on the level' do
|
||||
where(:pages_access_level, :with_user, :expected_result) do
|
||||
ProjectFeature::DISABLED | "admin" | 403
|
||||
ProjectFeature::DISABLED | "owner" | 403
|
||||
ProjectFeature::DISABLED | "master" | 403
|
||||
ProjectFeature::DISABLED | "developer" | 403
|
||||
ProjectFeature::DISABLED | "reporter" | 403
|
||||
ProjectFeature::DISABLED | "guest" | 403
|
||||
ProjectFeature::DISABLED | "user" | 403
|
||||
ProjectFeature::DISABLED | nil | 404
|
||||
ProjectFeature::PUBLIC | "admin" | 200
|
||||
ProjectFeature::PUBLIC | "owner" | 200
|
||||
ProjectFeature::PUBLIC | "master" | 200
|
||||
ProjectFeature::PUBLIC | "developer" | 200
|
||||
ProjectFeature::PUBLIC | "reporter" | 200
|
||||
ProjectFeature::PUBLIC | "guest" | 200
|
||||
ProjectFeature::PUBLIC | "user" | 200
|
||||
ProjectFeature::PUBLIC | nil | 404
|
||||
ProjectFeature::ENABLED | "admin" | 200
|
||||
ProjectFeature::ENABLED | "owner" | 200
|
||||
ProjectFeature::ENABLED | "master" | 200
|
||||
ProjectFeature::ENABLED | "developer" | 200
|
||||
ProjectFeature::ENABLED | "reporter" | 200
|
||||
ProjectFeature::ENABLED | "guest" | 200
|
||||
ProjectFeature::ENABLED | "user" | 200
|
||||
ProjectFeature::ENABLED | nil | 404
|
||||
ProjectFeature::PRIVATE | "admin" | 200
|
||||
ProjectFeature::PRIVATE | "owner" | 200
|
||||
ProjectFeature::PRIVATE | "master" | 200
|
||||
ProjectFeature::PRIVATE | "developer" | 200
|
||||
ProjectFeature::PRIVATE | "reporter" | 200
|
||||
ProjectFeature::PRIVATE | "guest" | 200
|
||||
ProjectFeature::PRIVATE | "user" | 403
|
||||
ProjectFeature::PRIVATE | nil | 404
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
project.project_feature.update(pages_access_level: pages_access_level)
|
||||
end
|
||||
it "correct return value" do
|
||||
if !with_user.nil?
|
||||
user = public_send(with_user)
|
||||
get api("/projects/#{project.id}/pages_access", user)
|
||||
else
|
||||
get api("/projects/#{project.id}/pages_access")
|
||||
end
|
||||
|
||||
expect(response).to have_gitlab_http_status(expected_result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe "Private Project Pages Access" do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
include AccessMatchers
|
||||
|
||||
set(:group) { create(:group) }
|
||||
set(:project) { create(:project, :private, pages_access_level: ProjectFeature::ENABLED, namespace: group) }
|
||||
|
||||
set(:admin) { create(:admin) }
|
||||
set(:owner) { create(:user) }
|
||||
set(:master) { create(:user) }
|
||||
set(:developer) { create(:user) }
|
||||
set(:reporter) { create(:user) }
|
||||
set(:guest) { create(:user) }
|
||||
set(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
allow(Gitlab.config.pages).to receive(:access_control).and_return(true)
|
||||
group.add_owner(owner)
|
||||
project.add_master(master)
|
||||
project.add_developer(developer)
|
||||
project.add_reporter(reporter)
|
||||
project.add_guest(guest)
|
||||
end
|
||||
|
||||
describe "Project should be private" do
|
||||
describe '#private?' do
|
||||
subject { project.private? }
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /projects/:id/pages_access" do
|
||||
context 'access depends on the level' do
|
||||
where(:pages_access_level, :with_user, :expected_result) do
|
||||
ProjectFeature::DISABLED | "admin" | 403
|
||||
ProjectFeature::DISABLED | "owner" | 403
|
||||
ProjectFeature::DISABLED | "master" | 403
|
||||
ProjectFeature::DISABLED | "developer" | 403
|
||||
ProjectFeature::DISABLED | "reporter" | 403
|
||||
ProjectFeature::DISABLED | "guest" | 403
|
||||
ProjectFeature::DISABLED | "user" | 404
|
||||
ProjectFeature::DISABLED | nil | 404
|
||||
ProjectFeature::PUBLIC | "admin" | 200
|
||||
ProjectFeature::PUBLIC | "owner" | 200
|
||||
ProjectFeature::PUBLIC | "master" | 200
|
||||
ProjectFeature::PUBLIC | "developer" | 200
|
||||
ProjectFeature::PUBLIC | "reporter" | 200
|
||||
ProjectFeature::PUBLIC | "guest" | 200
|
||||
ProjectFeature::PUBLIC | "user" | 404
|
||||
ProjectFeature::PUBLIC | nil | 404
|
||||
ProjectFeature::ENABLED | "admin" | 200
|
||||
ProjectFeature::ENABLED | "owner" | 200
|
||||
ProjectFeature::ENABLED | "master" | 200
|
||||
ProjectFeature::ENABLED | "developer" | 200
|
||||
ProjectFeature::ENABLED | "reporter" | 200
|
||||
ProjectFeature::ENABLED | "guest" | 200
|
||||
ProjectFeature::ENABLED | "user" | 404
|
||||
ProjectFeature::ENABLED | nil | 404
|
||||
ProjectFeature::PRIVATE | "admin" | 200
|
||||
ProjectFeature::PRIVATE | "owner" | 200
|
||||
ProjectFeature::PRIVATE | "master" | 200
|
||||
ProjectFeature::PRIVATE | "developer" | 200
|
||||
ProjectFeature::PRIVATE | "reporter" | 200
|
||||
ProjectFeature::PRIVATE | "guest" | 200
|
||||
ProjectFeature::PRIVATE | "user" | 404
|
||||
ProjectFeature::PRIVATE | nil | 404
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
project.project_feature.update(pages_access_level: pages_access_level)
|
||||
end
|
||||
it "correct return value" do
|
||||
if !with_user.nil?
|
||||
user = public_send(with_user)
|
||||
get api("/projects/#{project.id}/pages_access", user)
|
||||
else
|
||||
get api("/projects/#{project.id}/pages_access")
|
||||
end
|
||||
|
||||
expect(response).to have_gitlab_http_status(expected_result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe "Public Project Pages Access" do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
include AccessMatchers
|
||||
|
||||
set(:group) { create(:group) }
|
||||
set(:project) { create(:project, :public, pages_access_level: ProjectFeature::ENABLED, namespace: group) }
|
||||
|
||||
set(:admin) { create(:admin) }
|
||||
set(:owner) { create(:user) }
|
||||
set(:master) { create(:user) }
|
||||
set(:developer) { create(:user) }
|
||||
set(:reporter) { create(:user) }
|
||||
set(:guest) { create(:user) }
|
||||
set(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
allow(Gitlab.config.pages).to receive(:access_control).and_return(true)
|
||||
group.add_owner(owner)
|
||||
project.add_master(master)
|
||||
project.add_developer(developer)
|
||||
project.add_reporter(reporter)
|
||||
project.add_guest(guest)
|
||||
end
|
||||
|
||||
describe "Project should be public" do
|
||||
describe '#public?' do
|
||||
subject { project.public? }
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /projects/:id/pages_access" do
|
||||
context 'access depends on the level' do
|
||||
where(:pages_access_level, :with_user, :expected_result) do
|
||||
ProjectFeature::DISABLED | "admin" | 403
|
||||
ProjectFeature::DISABLED | "owner" | 403
|
||||
ProjectFeature::DISABLED | "master" | 403
|
||||
ProjectFeature::DISABLED | "developer" | 403
|
||||
ProjectFeature::DISABLED | "reporter" | 403
|
||||
ProjectFeature::DISABLED | "guest" | 403
|
||||
ProjectFeature::DISABLED | "user" | 403
|
||||
ProjectFeature::DISABLED | nil | 403
|
||||
ProjectFeature::PUBLIC | "admin" | 200
|
||||
ProjectFeature::PUBLIC | "owner" | 200
|
||||
ProjectFeature::PUBLIC | "master" | 200
|
||||
ProjectFeature::PUBLIC | "developer" | 200
|
||||
ProjectFeature::PUBLIC | "reporter" | 200
|
||||
ProjectFeature::PUBLIC | "guest" | 200
|
||||
ProjectFeature::PUBLIC | "user" | 200
|
||||
ProjectFeature::PUBLIC | nil | 200
|
||||
ProjectFeature::ENABLED | "admin" | 200
|
||||
ProjectFeature::ENABLED | "owner" | 200
|
||||
ProjectFeature::ENABLED | "master" | 200
|
||||
ProjectFeature::ENABLED | "developer" | 200
|
||||
ProjectFeature::ENABLED | "reporter" | 200
|
||||
ProjectFeature::ENABLED | "guest" | 200
|
||||
ProjectFeature::ENABLED | "user" | 200
|
||||
ProjectFeature::ENABLED | nil | 200
|
||||
ProjectFeature::PRIVATE | "admin" | 200
|
||||
ProjectFeature::PRIVATE | "owner" | 200
|
||||
ProjectFeature::PRIVATE | "master" | 200
|
||||
ProjectFeature::PRIVATE | "developer" | 200
|
||||
ProjectFeature::PRIVATE | "reporter" | 200
|
||||
ProjectFeature::PRIVATE | "guest" | 200
|
||||
ProjectFeature::PRIVATE | "user" | 403
|
||||
ProjectFeature::PRIVATE | nil | 403
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
project.project_feature.update(pages_access_level: pages_access_level)
|
||||
end
|
||||
it "correct return value" do
|
||||
if !with_user.nil?
|
||||
user = public_send(with_user)
|
||||
get api("/projects/#{project.id}/pages_access", user)
|
||||
else
|
||||
get api("/projects/#{project.id}/pages_access")
|
||||
end
|
||||
|
||||
expect(response).to have_gitlab_http_status(expected_result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -340,6 +340,27 @@ describe Projects::UpdateService do
|
|||
call_service
|
||||
end
|
||||
end
|
||||
|
||||
context 'when updating #pages_access_level' do
|
||||
subject(:call_service) do
|
||||
update_project(project, admin, project_feature_attributes: { pages_access_level: ProjectFeature::PRIVATE })
|
||||
end
|
||||
|
||||
it 'updates the attribute' do
|
||||
expect { call_service }
|
||||
.to change { project.project_feature.pages_access_level }
|
||||
.to(ProjectFeature::PRIVATE)
|
||||
end
|
||||
|
||||
it 'calls Projects::UpdatePagesConfigurationService' do
|
||||
expect(Projects::UpdatePagesConfigurationService)
|
||||
.to receive(:new)
|
||||
.with(project)
|
||||
.and_call_original
|
||||
|
||||
call_service
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#run_auto_devops_pipeline?' do
|
||||
|
|
|
|||
Loading…
Reference in New Issue