This instance was upgraded to Heptapod 0.27.2 on 2021-12-08 at 22:00 UTC+1

Commit 892dea67 authored by Felipe Artur's avatar Felipe Artur
Browse files

Project tools visibility level

parent d24571d75b56
......@@ -7,7 +7,6 @@ def initialize(user, params)
def execute
forked_from_project_id = params.delete(:forked_from_project_id)
import_data = params.delete(:import_data)
@project = Project.new(params)
# Make sure that the user is allowed to use the specified visibility level
......@@ -81,8 +80,7 @@ def after_create_actions
log_info("#{@project.owner.name} created a new project \"#{@project.name_with_namespace}\"")
unless @project.gitlab_project_import?
@project.create_wiki if @project.wiki_enabled?
@project.create_wiki if @project.feature_available?(:wiki, current_user)
@project.build_missing_services
@project.create_labels
......
......@@ -8,7 +8,6 @@ def execute
name: @project.name,
path: @project.path,
shared_runners_enabled: @project.shared_runners_enabled,
builds_enabled: @project.builds_enabled,
namespace_id: @params[:namespace].try(:id) || current_user.namespace.id
}
......@@ -17,6 +16,9 @@ def execute
end
new_project = CreateService.new(current_user, new_params).execute
builds_access_level = @project.project_feature.builds_access_level
new_project.project_feature.update_attributes(builds_access_level: builds_access_level)
new_project
end
......
......@@ -26,7 +26,7 @@
%span
Protected Branches
- if @project.builds_enabled?
- if @project.feature_available?(:builds, current_user)
= nav_link(controller: :runners) do
= link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do
%span
......
......@@ -44,52 +44,56 @@
%hr
%fieldset.features.append-bottom-0
%h5.prepend-top-0
Features
.form-group
.checkbox
= f.label :issues_enabled do
= f.check_box :issues_enabled
%strong Issues
%br
%span.descr Lightweight issue tracking system for this project
.form-group
.checkbox
= f.label :merge_requests_enabled do
= f.check_box :merge_requests_enabled
%strong Merge Requests
%br
%span.descr Submit changes to be merged upstream
.form-group
.checkbox
= f.label :builds_enabled do
= f.check_box :builds_enabled
%strong Builds
%br
%span.descr Test and deploy your changes before merge
.form-group
.checkbox
= f.label :wiki_enabled do
= f.check_box :wiki_enabled
%strong Wiki
%br
%span.descr Pages for project documentation
.form-group
.checkbox
= f.label :snippets_enabled do
= f.check_box :snippets_enabled
%strong Snippets
%br
%span.descr Share code pastes with others out of git repository
- if Gitlab.config.lfs.enabled && current_user.admin?
.form-group
.checkbox
= f.label :lfs_enabled do
= f.check_box :lfs_enabled, checked: @project.lfs_enabled?
%strong LFS
%br
%span.descr
Git Large File Storage
= link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
Feature Visibility
= f.fields_for :project_feature do |feature_fields|
.form_group.prepend-top-20
.row
.col-md-9
= feature_fields.label :issues_access_level, "Issues", class: 'label-light'
%span.help-block Lightweight issue tracking system for this project
.col-md-3
= project_feature_access_select(:issues_access_level)
.row
.col-md-9
= feature_fields.label :merge_requests_access_level, "Merge requests", class: 'label-light'
%span.help-block Submit changes to be merged upstream
.col-md-3
= project_feature_access_select(:merge_requests_access_level)
.row
.col-md-9
= feature_fields.label :builds_access_level, "Builds", class: 'label-light'
%span.help-block Submit Test and deploy your changes before merge
.col-md-3
= project_feature_access_select(:builds_access_level)
.row
.col-md-9
= feature_fields.label :wiki_access_level, "Wiki", class: 'label-light'
%span.help-block Pages for project documentation
.col-md-3
= project_feature_access_select(:wiki_access_level)
.row
.col-md-9
= feature_fields.label :snippets_access_level, "Snippets", class: 'label-light'
%span.help-block Share code pastes with others out of Git repository
.col-md-3
= project_feature_access_select(:snippets_access_level)
- if Gitlab.config.lfs.enabled && current_user.admin?
.form-group
.checkbox
= f.label :lfs_enabled do
= f.check_box :lfs_enabled, checked: @project.lfs_enabled?
%strong LFS
%br
%span.descr
Git Large File Storage
= link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
- if Gitlab.config.registry.enabled
.form-group
.checkbox
......@@ -98,7 +102,7 @@
%strong Container Registry
%br
%span.descr Enable Container Registry for this repository
%hr
= render 'merge_request_settings', f: f
%hr
%fieldset.features.append-bottom-default
......
......@@ -12,7 +12,7 @@
= link_to 'Commits', commits_namespace_project_graph_path
= nav_link(action: :languages) do
= link_to 'Languages', languages_namespace_project_graph_path
- if @project.builds_enabled?
- if @project.feature_available?(:builds, current_user)
= nav_link(action: :ci) do
= link_to ci_namespace_project_graph_path do
Continuous Integration
class CreateProjectFeatures < ActiveRecord::Migration
DOWNTIME = false
def change
create_table :project_features do |t|
t.belongs_to :project, index: true
t.integer :merge_requests_access_level
t.integer :issues_access_level
t.integer :wiki_access_level
t.integer :snippets_access_level
t.integer :builds_access_level
t.timestamps
end
end
end
class MigrateProjectFeatures < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
DOWNTIME_REASON =
<<-EOT
Migrating issues_enabled, merge_requests_enabled, wiki_enabled, builds_enabled, snippets_enabled fields from projects to
a new table called project_features.
EOT
def up
sql =
%Q{
INSERT INTO project_features(project_id, issues_access_level, merge_requests_access_level, wiki_access_level,
builds_access_level, snippets_access_level, created_at, updated_at)
SELECT
id AS project_id,
CASE WHEN issues_enabled IS true THEN 20 ELSE 0 END AS issues_access_level,
CASE WHEN merge_requests_enabled IS true THEN 20 ELSE 0 END AS merge_requests_access_level,
CASE WHEN wiki_enabled IS true THEN 20 ELSE 0 END AS wiki_access_level,
CASE WHEN builds_enabled IS true THEN 20 ELSE 0 END AS builds_access_level,
CASE WHEN snippets_enabled IS true THEN 20 ELSE 0 END AS snippets_access_level,
created_at,
updated_at
FROM projects
}
execute(sql)
end
def down
sql = %Q{
UPDATE projects
SET
issues_enabled = COALESCE((SELECT CASE WHEN issues_access_level = 20 THEN true ELSE false END AS issues_enabled FROM project_features WHERE project_features.project_id = projects.id), true),
merge_requests_enabled = COALESCE((SELECT CASE WHEN merge_requests_access_level = 20 THEN true ELSE false END AS merge_requests_enabled FROM project_features WHERE project_features.project_id = projects.id),true),
wiki_enabled = COALESCE((SELECT CASE WHEN wiki_access_level = 20 THEN true ELSE false END AS wiki_enabled FROM project_features WHERE project_features.project_id = projects.id), true),
builds_enabled = COALESCE((SELECT CASE WHEN builds_access_level = 20 THEN true ELSE false END AS builds_enabled FROM project_features WHERE project_features.project_id = projects.id), true),
snippets_enabled = COALESCE((SELECT CASE WHEN snippets_access_level = 20 THEN true ELSE false END AS snippets_enabled FROM project_features WHERE project_features.project_id = projects.id),true)
}
execute(sql)
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class RemoveFeaturesEnabledFromProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
# Set this constant to true if this migration requires downtime.
DOWNTIME = true
DOWNTIME_REASON = "Removing fields from database requires downtine."
def up
remove_column :projects, :issues_enabled
remove_column :projects, :merge_requests_enabled
remove_column :projects, :builds_enabled
remove_column :projects, :wiki_enabled
remove_column :projects, :snippets_enabled
end
# Ugly SQL but the only way i found to make it work on both Postgres and Mysql
# It will be slow but it is ok since it is a revert method
def down
add_column_with_default(:projects, :issues_enabled, :boolean, default: true, allow_null: false)
add_column_with_default(:projects, :merge_requests_enabled, :boolean, default: true, allow_null: false)
add_column_with_default(:projects, :builds_enabled, :boolean, default: true, allow_null: false)
add_column_with_default(:projects, :wiki_enabled, :boolean, default: true, allow_null: false)
add_column_with_default(:projects, :snippets_enabled, :boolean, default: true, allow_null: false)
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160830232601) do
ActiveRecord::Schema.define(version: 20160831223750) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -766,6 +766,19 @@
add_index "personal_access_tokens", ["token"], name: "index_personal_access_tokens_on_token", unique: true, using: :btree
add_index "personal_access_tokens", ["user_id"], name: "index_personal_access_tokens_on_user_id", using: :btree
create_table "project_features", force: :cascade do |t|
t.integer "project_id"
t.integer "merge_requests_access_level"
t.integer "issues_access_level"
t.integer "wiki_access_level"
t.integer "snippets_access_level"
t.integer "builds_access_level"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "project_features", ["project_id"], name: "index_project_features_on_project_id", using: :btree
create_table "project_group_links", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "group_id", null: false
......@@ -790,11 +803,7 @@
t.datetime "created_at"
t.datetime "updated_at"
t.integer "creator_id"
t.boolean "issues_enabled", default: true, null: false
t.boolean "merge_requests_enabled", default: true, null: false
t.boolean "wiki_enabled", default: true, null: false
t.integer "namespace_id"
t.boolean "snippets_enabled", default: true, null: false
t.datetime "last_activity_at"
t.string "import_url"
t.integer "visibility_level", default: 0, null: false
......@@ -808,7 +817,6 @@
t.integer "commit_count", default: 0
t.text "import_error"
t.integer "ci_id"
t.boolean "builds_enabled", default: true, null: false
t.boolean "shared_runners_enabled", default: true, null: false
t.string "runners_token"
t.string "build_coverage_regex"
......
......@@ -104,6 +104,15 @@ will find the option to flag the user as external.
By default new users are not set as external users. This behavior can be changed
by an administrator under **Admin > Application Settings**.
## Project features
Project features like wiki and issues can be hidden from users depending on
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
## GitLab CI
GitLab CI permissions rely on the role the user has in GitLab. There are four
......
......@@ -5,7 +5,7 @@ class Spinach::Features::Project < Spinach::FeatureSteps
step 'change project settings' do
fill_in 'project_name_edit', with: 'NewName'
uncheck 'project_issues_enabled'
select 'Disabled', from: 'project_project_feature_attributes_issues_access_level'
end
step 'I save project' do
......
......@@ -15,7 +15,7 @@ module SharedProject
# Create a specific project called "Shop"
step 'I own project "Shop"' do
@project = Project.find_by(name: "Shop")
@project ||= create(:project, name: "Shop", namespace: @user.namespace, snippets_enabled: true)
@project ||= create(:project, name: "Shop", namespace: @user.namespace)
@project.team << [@user, :master]
end
......@@ -41,6 +41,8 @@ module SharedProject
step 'I own project "Forum"' do
@project = Project.find_by(name: "Forum")
@project ||= create(:project, name: "Forum", namespace: @user.namespace, path: 'forum_project')
@project.build_project_feature
@project.project_feature.save
@project.team << [@user, :master]
end
......@@ -95,7 +97,7 @@ module SharedProject
step 'I should see project settings' do
expect(current_path).to eq edit_namespace_project_path(@project.namespace, @project)
expect(page).to have_content("Project name")
expect(page).to have_content("Features")
expect(page).to have_content("Feature Visibility")
end
def current_project
......
......@@ -76,7 +76,15 @@ class Project < Grape::Entity
expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
expose :name, :name_with_namespace
expose :path, :path_with_namespace
expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :builds_enabled, :snippets_enabled, :container_registry_enabled
expose :container_registry_enabled
# Expose old field names with the new permissions methods to keep API compatible
expose(:issues_enabled) { |project, options| project.feature_available?(:issues, options[:user]) }
expose(:merge_requests_enabled) { |project, options| project.feature_available?(:merge_requests, options[:user]) }
expose(:wiki_enabled) { |project, options| project.feature_available?(:wiki, options[:user]) }
expose(:builds_enabled) { |project, options| project.feature_available?(:builds, options[:user]) }
expose(:snippets_enabled) { |project, options| project.feature_available?(:snippets, options[:user]) }
expose :created_at, :last_activity_at
expose :shared_runners_enabled, :lfs_enabled
expose :creator_id
......@@ -84,7 +92,7 @@ class Project < Grape::Entity
expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda{ |project, options| project.forked? }
expose :avatar_url
expose :star_count, :forks_count
expose :open_issues_count, if: lambda { |project, options| project.issues_enabled? && project.default_issues_tracker? }
expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:user]) && project.default_issues_tracker? }
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
expose :public_builds
expose :shared_with_groups do |project, options|
......
......@@ -97,7 +97,7 @@ class Groups < Grape::API
group = find_group(params[:id])
projects = GroupProjectsFinder.new(group).execute(current_user)
projects = paginate projects
present projects, with: Entities::Project
present projects, with: Entities::Project, user: current_user
end
# Transfer a project to the Group namespace
......
......@@ -51,7 +51,7 @@ def map_public_to_visibility_level(attrs)
@projects = current_user.viewable_starred_projects
@projects = filter_projects(@projects)
@projects = paginate @projects
present @projects, with: Entities::Project
present @projects, with: Entities::Project, user: current_user
end
# Get all projects for admin user
......
......@@ -168,7 +168,7 @@ def import_wiki
unless project.wiki_enabled?
wiki = WikiFormatter.new(project)
gitlab_shell.import_repository(project.repository_storage_path, wiki.path_with_namespace, wiki.import_url)
project.update_attribute(:wiki_enabled, true)
project.project.update_attribute(:wiki_access_level, ProjectFeature::ENABLED)
end
rescue Gitlab::Shell::Error => e
# GitHub error message when the wiki repo has not been created,
......
......@@ -11,7 +11,7 @@ def initialize(repo, namespace, current_user, session_data)
end
def execute
::Projects::CreateService.new(
project = ::Projects::CreateService.new(
current_user,
name: repo.name,
path: repo.name,
......@@ -20,9 +20,15 @@ def execute
visibility_level: repo.private ? Gitlab::VisibilityLevel::PRIVATE : Gitlab::VisibilityLevel::PUBLIC,
import_type: "github",
import_source: repo.full_name,
import_url: repo.clone_url.sub("https://", "https://#{@session_data[:github_access_token]}@"),
wiki_enabled: !repo.has_wiki? # If repo has wiki we'll import it later
import_url: repo.clone_url.sub("https://", "https://#{@session_data[:github_access_token]}@")
).execute
# If repo has wiki we'll import it later
if repo.has_wiki? && project
project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED)
end
project
end
end
end
......
......@@ -39,15 +39,12 @@ project_tree:
- :labels
- milestones:
- :events
- :project_feature
# Only include the following attributes for the models specified.
included_attributes:
project:
- :description
- :issues_enabled
- :merge_requests_enabled
- :wiki_enabled
- :snippets_enabled
- :visibility_level
- :archived
user:
......@@ -72,4 +69,4 @@ methods:
statuses:
- :type
merge_request_diff:
- :utf8_st_diffs
\ No newline at end of file
- :utf8_st_diffs
require 'spec_helper'
describe Projects::SnippetsController do
let(:project) { create(:project_empty_repo, :public, snippets_enabled: true) }
let(:project) { create(:project_empty_repo, :public) }
let(:user) { create(:user) }
let(:user2) { create(:user) }
......
......@@ -8,7 +8,6 @@
path { name.downcase.gsub(/\s/, '_') }
namespace
creator
snippets_enabled true
trait :public do
visibility_level Gitlab::VisibilityLevel::PUBLIC
......@@ -27,6 +26,26 @@
project.create_repository
end
end
# Nest Project Feature attributes
transient do
wiki_access_level ProjectFeature::ENABLED
builds_access_level ProjectFeature::ENABLED
snippets_access_level ProjectFeature::ENABLED
issues_access_level ProjectFeature::ENABLED
merge_requests_access_level ProjectFeature::ENABLED
end
after(:create) do |project, evaluator|
project.project_feature.
update_attributes(
wiki_access_level: evaluator.wiki_access_level,
builds_access_level: evaluator.builds_access_level,
snippets_access_level: evaluator.snippets_access_level,
issues_access_level: evaluator.issues_access_level,
merge_requests_access_level: evaluator.merge_requests_access_level,
)
end
end
# Project with empty repository
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment