summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Artur <felipefac@gmail.com>2016-09-16 16:15:39 -0300
committerFelipe Artur <felipefac@gmail.com>2016-10-17 18:12:18 -0200
commitda07c2e4d3d382c05ec287ee60f639b870074fe7 (patch)
treef6ffa7fd29fe177d4d78c0e043a1fdcff5b6eba4
parentc49e152605ad1fe77bea6414c383cf70669ca110 (diff)
downloadgitlab-ce-issue_19734_2.tar.gz
Add visibility level to project repositoryissue_19734_2
-rw-r--r--CHANGELOG.md1
-rw-r--r--app/assets/javascripts/project_new.js38
-rw-r--r--app/assets/stylesheets/pages/projects.scss83
-rw-r--r--app/controllers/projects_controller.rb35
-rw-r--r--app/helpers/preferences_helper.rb16
-rw-r--r--app/helpers/projects_helper.rb33
-rw-r--r--app/models/project_feature.rb19
-rw-r--r--app/policies/project_policy.rb14
-rw-r--r--app/views/projects/_customize_workflow.html.haml8
-rw-r--r--app/views/projects/_home_panel.html.haml5
-rw-r--r--app/views/projects/_wiki.html.haml19
-rw-r--r--app/views/projects/edit.html.haml56
-rw-r--r--app/views/projects/issues/_issues.html.haml2
-rw-r--r--app/views/projects/show.html.haml130
-rw-r--r--db/migrate/20161012180455_add_repository_access_level_to_project_feature.rb14
-rw-r--r--db/schema.rb3
-rw-r--r--spec/controllers/projects_controller_spec.rb40
-rw-r--r--spec/factories/projects.rb2
-rw-r--r--spec/features/projects/features_visibility_spec.rb30
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml1
-rw-r--r--spec/models/project_feature_spec.rb23
21 files changed, 398 insertions, 174 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 37383ea1b72..44ddc1e03a2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -61,6 +61,7 @@ Please view this file on the master branch, on stable branches it's out of date.
- Fix inconsistent highlighting of already selected activity nav-links (ClemMakesApps)
- Remove redundant mixins (ClemMakesApps)
- Added 'Download' button to the Snippets page (Justin DiPierro)
+ - Add visibility level to project repository
- Fix robots.txt disallowing access to groups starting with "s" (Matt Harrison)
- Close open merge request without source project (Katarzyna Kobierska Ula Budziszewska)
- Fix that manual jobs would no longer block jobs in the next stage. !6604
diff --git a/app/assets/javascripts/project_new.js b/app/assets/javascripts/project_new.js
index 3cf41505814..478e82aa14d 100644
--- a/app/assets/javascripts/project_new.js
+++ b/app/assets/javascripts/project_new.js
@@ -4,9 +4,8 @@
this.ProjectNew = (function() {
function ProjectNew() {
this.toggleSettings = bind(this.toggleSettings, this);
- this.$selects = $('.features select').filter(function () {
- return $(this).data('field');
- });
+ this.$selects = $('.features select');
+ this.$repoSelects = this.$selects.filter('.js-repo-select');
$('.project-edit-container').on('ajax:before', (function(_this) {
return function() {
@@ -16,6 +15,7 @@
})(this));
this.toggleSettings();
this.toggleSettingsOnclick();
+ this.toggleRepoVisibility();
}
ProjectNew.prototype.toggleSettings = function() {
@@ -43,6 +43,38 @@
}
};
+ ProjectNew.prototype.toggleRepoVisibility = function () {
+ var $repoAccessLevel = $('.js-repo-access-level select');
+
+ this.$repoSelects.find("option[value='" + $repoAccessLevel.val() + "']")
+ .nextAll()
+ .hide();
+
+ $repoAccessLevel.off('change')
+ .on('change', function () {
+ var selectedVal = parseInt($repoAccessLevel.val());
+
+ this.$repoSelects.each(function () {
+ var $this = $(this),
+ repoSelectVal = parseInt($this.val());
+
+ $this.find('option').show();
+
+ if (selectedVal < repoSelectVal) {
+ $this.val(selectedVal);
+ }
+
+ $this.find("option[value='" + selectedVal + "']").nextAll().hide();
+ });
+
+ if (selectedVal) {
+ this.$repoSelects.removeClass('disabled');
+ } else {
+ this.$repoSelects.addClass('disabled');
+ }
+ }.bind(this));
+ };
+
return ProjectNew;
})();
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index d30f02340b9..1062d7effb0 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -761,62 +761,6 @@ pre.light-well {
.dropdown-menu {
width: 300px;
}
-
- &.from .compare-dropdown-toggle {
- width: 237px;
- }
-
- &.to .compare-dropdown-toggle {
- width: 254px;
- }
-
- .dropdown-toggle-text {
- display: block;
- height: 100%;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- width: 100%;
- }
-}
-
-.compare-ellipsis {
- display: inline;
-}
-
-@media (max-width: $screen-xs-max) {
- .compare-form-group {
- .input-group {
- width: 100%;
-
- & > .compare-dropdown-toggle {
- width: 100%;
- }
- }
-
- .dropdown-menu {
- width: 100%;
- }
- }
-
- .compare-switch-container {
- text-align: center;
- padding: 0 0 $gl-padding;
-
- .commits-compare-switch {
- float: none;
- }
- }
-
- .compare-ellipsis {
- display: block;
- text-align: center;
- padding: 0 0 $gl-padding;
- }
-
- .commits-compare-btn {
- width: 100%;
- }
}
.clearable-input {
@@ -855,3 +799,30 @@ pre.light-well {
border-bottom-right-radius: 0;
}
}
+
+.project-home-empty {
+ border-top: 0;
+
+ .container-fluid {
+ background: none;
+ }
+
+ p {
+ margin-left: auto;
+ margin-right: auto;
+ max-width: 650px;
+ }
+}
+
+.project-feature-nested {
+ @media (min-width: $screen-sm-min) {
+ padding-left: 45px;
+ }
+}
+
+.project-repo-select {
+ &.disabled {
+ opacity: 0.5;
+ pointer-events: none;
+ }
+}
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 62916270172..76b730198d4 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -1,4 +1,5 @@
class ProjectsController < Projects::ApplicationController
+ include IssuableCollections
include ExtractsPath
before_action :authenticate_user!, except: [:show, :activity, :refs]
@@ -103,16 +104,7 @@ class ProjectsController < Projects::ApplicationController
respond_to do |format|
format.html do
@notification_setting = current_user.notification_settings_for(@project) if current_user
-
- if @project.repository_exists?
- if @project.empty_repo?
- render 'projects/empty'
- else
- render :show
- end
- else
- render 'projects/no_repo'
- end
+ render_landing_page
end
format.atom do
@@ -285,6 +277,26 @@ class ProjectsController < Projects::ApplicationController
private
+ # Render project landing depending of which features are available
+ # So if page is not availble in the list it renders the next page
+ #
+ # pages list order: repository readme, wiki home, issues list, customize workflow
+ def render_landing_page
+ if @project.feature_available?(:repository, current_user)
+ return render 'projects/no_repo' unless @project.repository_exists?
+ render 'projects/empty' if @project.empty_repo?
+ else
+ if @project.wiki_enabled?
+ @wiki_home = @project.wiki.find_page('home', params[:version_id])
+ elsif @project.feature_available?(:issues, current_user)
+ @issues = issues_collection
+ @issues = @issues.page(params[:page])
+ end
+
+ render :show
+ end
+ end
+
def determine_layout
if [:new, :create].include?(action_name.to_sym)
'application'
@@ -308,7 +320,8 @@ class ProjectsController < Projects::ApplicationController
project_feature_attributes:
[
:issues_access_level, :builds_access_level,
- :wiki_access_level, :merge_requests_access_level, :snippets_access_level
+ :wiki_access_level, :merge_requests_access_level,
+ :snippets_access_level, :repository_access_level
]
}
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index c3832cf5d65..a46f2c6e17d 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -50,6 +50,20 @@ module PreferencesHelper
end
def default_project_view
- current_user ? current_user.project_view : 'readme'
+ return 'readme' unless current_user
+
+ user_view = current_user.project_view
+
+ if @project.feature_available?(:repository, current_user)
+ user_view
+ elsif user_view == "activity"
+ "activity"
+ elsif @project.wiki_enabled?
+ "wiki"
+ elsif @project.feature_available?(:issues, current_user)
+ "projects/issues/issues"
+ else
+ "customize_workflow"
+ end
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index e667c9e4e2e..d26b4018be6 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -134,16 +134,35 @@ module ProjectsHelper
options = project_feature_options
if @project.private?
+ level = @project.project_feature.send(field)
options.delete('Everyone with access')
- highest_available_option = options.values.max if @project.project_feature.send(field) == ProjectFeature::ENABLED
+ highest_available_option = options.values.max if level == ProjectFeature::ENABLED
end
options = options_for_select(options, selected: highest_available_option || @project.project_feature.public_send(field))
- content_tag(:select, options, name: "project[project_feature_attributes][#{field}]", id: "project_project_feature_attributes_#{field}", class: "pull-right form-control", data: { field: field }).html_safe
+
+ content_tag(
+ :select,
+ options,
+ name: "project[project_feature_attributes][#{field}]",
+ id: "project_project_feature_attributes_#{field}",
+ class: "pull-right form-control #{repo_children_classes(field)}",
+ data: { field: field }
+ ).html_safe
end
private
+ def repo_children_classes(field)
+ needs_repo_check = [:merge_requests_access_level, :builds_access_level]
+ return unless needs_repo_check.include?(field)
+
+ classes = "project-repo-select js-repo-select"
+ classes << " disabled" unless @project.feature_available?(:repository, current_user)
+
+ classes
+ end
+
def get_project_nav_tabs(project, current_user)
nav_tabs = [:home]
@@ -155,12 +174,8 @@ module ProjectsHelper
nav_tabs << :merge_requests
end
- if can?(current_user, :read_pipeline, project)
- nav_tabs << :pipelines
- end
-
if can?(current_user, :read_build, project)
- nav_tabs << :builds
+ nav_tabs << :pipelines
end
if Gitlab.config.registry.enabled && can?(current_user, :read_container_image, project)
@@ -435,4 +450,8 @@ module ProjectsHelper
'Everyone with access' => ProjectFeature::ENABLED
}
end
+
+ def project_child_container_class(view_path)
+ view_path == "projects/issues/issues" ? "prepend-top-default" : "project-show-#{view_path}"
+ end
end
diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb
index 530f7d5a30e..b37ce1d3cf6 100644
--- a/app/models/project_feature.rb
+++ b/app/models/project_feature.rb
@@ -13,23 +13,26 @@ class ProjectFeature < ActiveRecord::Base
# Enabled: enabled for everyone able to access the project
#
- # Permision levels
+ # Permission levels
DISABLED = 0
PRIVATE = 10
ENABLED = 20
- FEATURES = %i(issues merge_requests wiki snippets builds)
+ FEATURES = %i(issues merge_requests wiki snippets builds repository)
# Default scopes force us to unscope here since a service may need to check
# permissions for a project in pending_delete
# http://stackoverflow.com/questions/1540645/how-to-disable-default-scope-for-a-belongs-to
belongs_to :project, -> { unscope(where: :pending_delete) }
+ validate :repository_children_level
+
default_value_for :builds_access_level, value: ENABLED, allows_nil: false
default_value_for :issues_access_level, value: ENABLED, allows_nil: false
default_value_for :merge_requests_access_level, value: ENABLED, allows_nil: false
default_value_for :snippets_access_level, value: ENABLED, allows_nil: false
default_value_for :wiki_access_level, value: ENABLED, allows_nil: false
+ default_value_for :repository_access_level, value: ENABLED, allows_nil: false
def feature_available?(feature, user)
raise ArgumentError, 'invalid project feature' unless FEATURES.include?(feature)
@@ -57,6 +60,18 @@ class ProjectFeature < ActiveRecord::Base
private
+ # Validates builds and merge requests access level
+ # which cannot be higher than repository access level
+ def repository_children_level
+ validator = lambda do |field|
+ level = public_send(field) || ProjectFeature::ENABLED
+ not_allowed = level > repository_access_level
+ self.errors.add(field, "cannot have higher visibility level than repository access level") if not_allowed
+ end
+
+ %i(merge_requests_access_level builds_access_level).each(&validator)
+ end
+
def get_permission(user, level)
case level
when DISABLED
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index be4721d7a51..fbb3d4507d6 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -162,11 +162,13 @@ class ProjectPolicy < BasePolicy
end
def disabled_features!
+ repository_enabled = project.feature_available?(:repository, user)
+
unless project.feature_available?(:issues, user)
cannot!(*named_abilities(:issue))
end
- unless project.feature_available?(:merge_requests, user)
+ unless project.feature_available?(:merge_requests, user) && repository_enabled
cannot!(*named_abilities(:merge_request))
end
@@ -183,13 +185,21 @@ class ProjectPolicy < BasePolicy
cannot!(*named_abilities(:wiki))
end
- unless project.feature_available?(:builds, user)
+ unless project.feature_available?(:builds, user) && repository_enabled
cannot!(*named_abilities(:build))
cannot!(*named_abilities(:pipeline))
cannot!(*named_abilities(:environment))
cannot!(*named_abilities(:deployment))
end
+ unless repository_enabled
+ cannot! :push_code
+ cannot! :push_code_to_protected_branches
+ cannot! :download_code
+ cannot! :fork_project
+ cannot! :read_commit_status
+ end
+
unless project.container_registry_enabled
cannot!(*named_abilities(:container_image))
end
diff --git a/app/views/projects/_customize_workflow.html.haml b/app/views/projects/_customize_workflow.html.haml
new file mode 100644
index 00000000000..d2c1e943db1
--- /dev/null
+++ b/app/views/projects/_customize_workflow.html.haml
@@ -0,0 +1,8 @@
+.row-content-block.project-home-empty
+ %div.text-center{ class: container_class }
+ %h4
+ Customize your workflow!
+ %p
+ Get started with GitLab by enabling features that work best for your project. From issues and wikis, to merge requests and builds, GitLab can help manage your workflow from idea to production!
+ - if can?(current_user, :admin_project, @project)
+ = link_to "Get started", edit_project_path(@project), class: "btn btn-success"
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 5590198a20e..d3987fc9c4f 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -22,5 +22,6 @@
= render 'projects/buttons/star'
= render 'projects/buttons/fork'
- .project-clone-holder
- = render "shared/clone_panel"
+ - if @project.feature_available?(:repository, current_user)
+ .project-clone-holder
+ = render "shared/clone_panel"
diff --git a/app/views/projects/_wiki.html.haml b/app/views/projects/_wiki.html.haml
new file mode 100644
index 00000000000..f00422dd7c0
--- /dev/null
+++ b/app/views/projects/_wiki.html.haml
@@ -0,0 +1,19 @@
+- if @wiki_home.present?
+ %div{ class: container_class }
+ .wiki-holder.prepend-top-default.append-bottom-default
+ .wiki
+ = preserve do
+ = render_wiki_content(@wiki_home)
+- else
+ - can_create_wiki = can?(current_user, :create_wiki, @project)
+ .project-home-empty{ class: [('row-content-block' if can_create_wiki), ('content-block' unless can_create_wiki)] }
+ %div.text-center{ class: container_class }
+ %h4
+ This project does not have a wiki homepage yet
+ - if can_create_wiki
+ %p
+ Add a homepage to your wiki that contains information about your project
+ %p
+ We recommend you
+ = link_to "add a homepage", namespace_project_wiki_path(@project.namespace, @project, :home)
+ to your project's wiki and GitLab will show it here instead of this message.
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index c8f84b96cb7..fb776e3a3e7 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -50,24 +50,39 @@
.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)
+ = feature_fields.label :repository_access_level, "Repository", class: 'label-light'
+ %span.help-block Push files to be stored in this project
+ .col-md-3.js-repo-access-level
+ = project_feature_access_select(:repository_access_level)
+
+ .col-sm-12
+ .row
+ .col-md-9.project-feature-nested
+ = 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.project-feature-nested
+ = 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 :merge_requests_access_level, "Merge requests", class: 'label-light'
- %span.help-block Submit changes to be merged upstream
+ = 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(:merge_requests_access_level)
+ = project_feature_access_select(:snippets_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
+ = 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(:builds_access_level)
+ = project_feature_access_select(:issues_access_level)
.row
.col-md-9
@@ -76,24 +91,17 @@
.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?
- .row
- .col-md-9
- = f.label :lfs_enabled, 'LFS', class: 'label-light'
- %span.help-block
+ .checkbox
+ = f.label :lfs_enabled do
+ = f.check_box :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')
- .col-md-3
- = f.select :lfs_enabled, [%w(Enabled true), %w(Disabled false)], {}, selected: @project.lfs_enabled?, class: 'pull-right form-control', data: { field: 'lfs_enabled' }
- - if Gitlab.config.registry.enabled
+ - if Gitlab.config.lfs.enabled && current_user.admin?
.form-group
.checkbox
= f.label :container_registry_enabled do
diff --git a/app/views/projects/issues/_issues.html.haml b/app/views/projects/issues/_issues.html.haml
index a2c31c0b4c5..a4b752ad86d 100644
--- a/app/views/projects/issues/_issues.html.haml
+++ b/app/views/projects/issues/_issues.html.haml
@@ -1,5 +1,5 @@
%ul.content-list.issues-list.issuable-list
- = render @issues
+ = render partial: "projects/issues/issue", collection: @issues
- if @issues.blank?
%li
.nothing-here-block No issues to show
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index ea4deb6cb28..ba16c641462 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -12,72 +12,74 @@
= render 'projects/last_push'
= render "home_panel"
-%nav.project-stats{ class: (container_class) }
- %ul.nav
- %li
- = link_to project_files_path(@project) do
- Files (#{repository_size})
- %li
- = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
- #{'Commit'.pluralize(@project.commit_count)} (#{number_with_delimiter(@project.commit_count)})
- %li
- = link_to namespace_project_branches_path(@project.namespace, @project) do
- #{'Branch'.pluralize(@repository.branch_count)} (#{number_with_delimiter(@repository.branch_count)})
- %li
- = link_to namespace_project_tags_path(@project.namespace, @project) do
- #{'Tag'.pluralize(@repository.tag_count)} (#{number_with_delimiter(@repository.tag_count)})
-
- - if default_project_view != 'readme' && @repository.readme
+- if @project.feature_available?(:repository, current_user)
+ %nav.project-stats{ class: container_class }
+ %ul.nav
%li
- = link_to 'Readme', readme_path(@project)
-
- - if @repository.changelog
+ = link_to project_files_path(@project) do
+ Files (#{repository_size})
%li
- = link_to 'Changelog', changelog_path(@project)
-
- - if @repository.license_blob
+ = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
+ #{'Commit'.pluralize(@project.commit_count)} (#{number_with_delimiter(@project.commit_count)})
%li
- = link_to license_short_name(@project), license_path(@project)
-
- - if @repository.contribution_guide
+ = link_to namespace_project_branches_path(@project.namespace, @project) do
+ #{'Branch'.pluralize(@repository.branch_count)} (#{number_with_delimiter(@repository.branch_count)})
%li
- = link_to 'Contribution guide', contribution_guide_path(@project)
+ = link_to namespace_project_tags_path(@project.namespace, @project) do
+ #{'Tag'.pluralize(@repository.tag_count)} (#{number_with_delimiter(@repository.tag_count)})
- - if @repository.gitlab_ci_yml
- %li
- = link_to 'CI configuration', ci_configuration_path(@project)
-
- - if current_user && can_push_branch?(@project, @project.default_branch)
- - unless @repository.changelog
- %li.missing
- = link_to add_special_file_path(@project, file_name: 'CHANGELOG') do
- Add Changelog
- - unless @repository.license_blob
- %li.missing
- = link_to add_special_file_path(@project, file_name: 'LICENSE') do
- Add License
- - unless @repository.contribution_guide
- %li.missing
- = link_to add_special_file_path(@project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide') do
- Add Contribution guide
- - unless @repository.gitlab_ci_yml
- %li.missing
- = link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml') do
- Set Up CI
-
- %li.project-repo-buttons-right
- .project-repo-buttons.project-right-buttons
- - if current_user
- = render 'shared/members/access_request_buttons', source: @project
- = render "projects/buttons/koding"
-
- = render 'projects/buttons/download', project: @project, ref: @ref
- = render 'projects/buttons/dropdown'
-
- = render 'shared/notifications/button', notification_setting: @notification_setting
-- if @repository.commit
- .project-last-commit{ class: container_class }
- = render 'projects/last_commit', commit: @repository.commit, project: @project
+ - if default_project_view != 'readme' && @repository.readme
+ %li
+ = link_to 'Readme', readme_path(@project)
+
+ - if @repository.changelog
+ %li
+ = link_to 'Changelog', changelog_path(@project)
+
+ - if @repository.license_blob
+ %li
+ = link_to license_short_name(@project), license_path(@project)
+
+ - if @repository.contribution_guide
+ %li
+ = link_to 'Contribution guide', contribution_guide_path(@project)
+
+ - if @repository.gitlab_ci_yml
+ %li
+ = link_to 'CI configuration', ci_configuration_path(@project)
+
+ - if current_user && can_push_branch?(@project, @project.default_branch)
+ - unless @repository.changelog
+ %li.missing
+ = link_to add_special_file_path(@project, file_name: 'CHANGELOG') do
+ Add Changelog
+ - unless @repository.license_blob
+ %li.missing
+ = link_to add_special_file_path(@project, file_name: 'LICENSE') do
+ Add License
+ - unless @repository.contribution_guide
+ %li.missing
+ = link_to add_special_file_path(@project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide') do
+ Add Contribution guide
+ - unless @repository.gitlab_ci_yml
+ %li.missing
+ = link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml') do
+ Set Up CI
+
+ %li.project-repo-buttons-right
+ .project-repo-buttons.project-right-buttons
+ - if current_user
+ = render 'shared/members/access_request_buttons', source: @project
+ = render "projects/buttons/koding"
+
+ .btn-group.project-repo-btn-group
+ = render 'projects/buttons/download', project: @project, ref: @ref
+ = render 'projects/buttons/dropdown'
+
+ = render 'shared/notifications/button', notification_setting: @notification_setting
+ - if @repository.commit
+ .project-last-commit{ class: container_class }
+ = render 'projects/last_commit', commit: @repository.commit, project: @project
%div{ class: container_class }
- if @project.archived?
@@ -86,5 +88,7 @@
= icon("exclamation-triangle fw")
Archived project! Repository is read-only
- %div{class: "project-show-#{default_project_view}"}
- = render default_project_view
+ - view_path = default_project_view
+
+ %div{ class: project_child_container_class(view_path) }
+ = render view_path
diff --git a/db/migrate/20161012180455_add_repository_access_level_to_project_feature.rb b/db/migrate/20161012180455_add_repository_access_level_to_project_feature.rb
new file mode 100644
index 00000000000..7b33da3ea11
--- /dev/null
+++ b/db/migrate/20161012180455_add_repository_access_level_to_project_feature.rb
@@ -0,0 +1,14 @@
+class AddRepositoryAccessLevelToProjectFeature < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+
+ def up
+ add_column_with_default(:project_features, :repository_access_level, :integer, default: ProjectFeature::ENABLED)
+ end
+
+ def down
+ remove_column :project_features, :repository_access_level
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index a362fd8f228..51ac0fbaeb5 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20161007133303) do
+ActiveRecord::Schema.define(version: 20161012180455) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -830,6 +830,7 @@ ActiveRecord::Schema.define(version: 20161007133303) do
t.integer "builds_access_level"
t.datetime "created_at"
t.datetime "updated_at"
+ t.integer "repository_access_level", default: 20, null: false
end
add_index "project_features", ["project_id"], name: "index_project_features_on_project_id", using: :btree
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index da0fdce39db..8eefa284ba0 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -41,6 +41,46 @@ describe ProjectsController do
end
end
end
+
+ describe "when project repository is disabled" do
+ render_views
+
+ before do
+ project.team << [user, :developer]
+ project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED)
+ end
+
+ it 'shows wiki homepage' do
+ get :show, namespace_id: project.namespace.path, id: project.path
+
+ expect(response).to render_template('projects/_wiki')
+ end
+
+ it 'shows issues list page if wiki is disabled' do
+ project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED)
+
+ get :show, namespace_id: project.namespace.path, id: project.path
+
+ expect(response).to render_template('projects/issues/_issues')
+ end
+
+ it 'shows customize workflow page if wiki and issues are disabled' do
+ project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED)
+ project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED)
+
+ get :show, namespace_id: project.namespace.path, id: project.path
+
+ expect(response).to render_template("projects/_customize_workflow")
+ end
+
+ it 'shows activity if enabled by user' do
+ user.update_attribute(:project_view, 'activity')
+
+ get :show, namespace_id: project.namespace.path, id: project.path
+
+ expect(response).to render_template("projects/_activity")
+ end
+ end
end
context "project with empty repo" do
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 719ef17f57e..4065e2defbc 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -45,6 +45,7 @@ FactoryGirl.define do
snippets_access_level ProjectFeature::ENABLED
issues_access_level ProjectFeature::ENABLED
merge_requests_access_level ProjectFeature::ENABLED
+ repository_access_level ProjectFeature::ENABLED
end
after(:create) do |project, evaluator|
@@ -55,6 +56,7 @@ FactoryGirl.define do
snippets_access_level: evaluator.snippets_access_level,
issues_access_level: evaluator.issues_access_level,
merge_requests_access_level: evaluator.merge_requests_access_level,
+ repository_access_level: evaluator.repository_access_level
)
end
end
diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb
index 9b487e350f2..1d4484a9edd 100644
--- a/spec/features/projects/features_visibility_spec.rb
+++ b/spec/features/projects/features_visibility_spec.rb
@@ -2,8 +2,11 @@ require 'spec_helper'
include WaitForAjax
describe 'Edit Project Settings', feature: true do
+ include WaitForAjax
+
let(:member) { create(:user) }
let!(:project) { create(:project, :public, path: 'gitlab', name: 'sample') }
+ let!(:issue) { create(:issue, project: project) }
let(:non_member) { create(:user) }
describe 'project features visibility selectors', js: true do
@@ -119,4 +122,31 @@ describe 'Edit Project Settings', feature: true do
end
end
end
+
+ describe 'repository visibility', js: true do
+ before do
+ project.team << [member, :master]
+ login_as(member)
+ visit edit_namespace_project_path(project.namespace, project)
+ end
+
+ it "disables repository related features" do
+ select "Disabled", from: "project_project_feature_attributes_repository_access_level"
+
+ expect(find(".edit-project")).to have_selector("select.disabled", count: 2)
+ end
+
+ it "shows empty features project homepage" do
+ select "Disabled", from: "project_project_feature_attributes_repository_access_level"
+ select "Disabled", from: "project_project_feature_attributes_issues_access_level"
+ select "Disabled", from: "project_project_feature_attributes_wiki_access_level"
+
+ click_button "Save changes"
+ wait_for_ajax
+
+ visit namespace_project_path(project.namespace, project)
+
+ expect(page).to have_content "Customize your workflow!"
+ end
+ end
end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 8bccd313d6c..8c8be66df9f 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -307,6 +307,7 @@ ProjectFeature:
- wiki_access_level
- snippets_access_level
- builds_access_level
+- repository_access_level
- created_at
- updated_at
ProtectedBranch::MergeAccessLevel:
diff --git a/spec/models/project_feature_spec.rb b/spec/models/project_feature_spec.rb
index 8d554a01be5..a55d43ab2f9 100644
--- a/spec/models/project_feature_spec.rb
+++ b/spec/models/project_feature_spec.rb
@@ -5,7 +5,7 @@ describe ProjectFeature do
let(:user) { create(:user) }
describe '#feature_available?' do
- let(:features) { %w(issues wiki builds merge_requests snippets) }
+ let(:features) { %w(issues wiki builds merge_requests snippets repository) }
context 'when features are disabled' do
it "returns false" do
@@ -64,6 +64,27 @@ describe ProjectFeature do
end
end
+ context 'repository related features' do
+ before do
+ project.project_feature.update_attributes(
+ merge_requests_access_level: ProjectFeature::DISABLED,
+ builds_access_level: ProjectFeature::DISABLED,
+ repository_access_level: ProjectFeature::PRIVATE
+ )
+ end
+
+ it "does not allow repository related features have higher level" do
+ features = %w(builds merge_requests)
+ project_feature = project.project_feature
+
+ features.each do |feature|
+ field = "#{feature}_access_level".to_sym
+ project_feature.update_attribute(field, ProjectFeature::ENABLED)
+ expect(project_feature.valid?).to be_falsy
+ end
+ end
+ end
+
describe '#*_enabled?' do
let(:features) { %w(wiki builds merge_requests) }