Commit d9bb4230 authored by Jason Hollingsworth's avatar Jason Hollingsworth
Browse files

Adding authenticated public mode (internal).

Added visibility_level icons to project view (rather than just text).
Added public projects to search results.
Added ability to restrict visibility levels standard users can set.
parent 8cc172aa8c0e
......@@ -58,10 +58,10 @@
%h4.project-title
= link_to project_path(project), class: dom_class(project) do
= project.name_with_namespace
- if project.public
- unless project.private?
%small.access-icon
= public_icon
Public
= visibility_level_icon(project.visibility_level)
= visibility_level_label(project.visibility_level)
- if current_user.can_leave_project?(project)
.pull-right
......
......@@ -51,10 +51,7 @@
%ul.well-list
- @group.projects.each do |project|
%li
- if project.public
= public_icon
- else
= private_icon
= visibility_level_icon(project.visibility_level)
= link_to project.name_with_namespace, project
.pull-right
= link_to 'Members', project_team_index_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
......
......@@ -143,7 +143,7 @@
%td.permission-x ✓
%td.permission-x ✓
%tr
%td Switch public mode
%td Switch visibility level
%td
%td
%td
......
......@@ -2,14 +2,20 @@
%h3.page-title Public Access
%p
GitLab allows you to open selected projects to be accessed publicly.
These projects will be cloneable
GitLab allows you to open selected projects to be accessed publicly or internally.
Projects with either of these visibility levels will be listed in the #{link_to "public access directory", public_root_path}. Internal projects will only be available to authenticated users.
%p
= public_icon
Public projects will be cloneable
%em without any
authentication.
Also they will be listed on the #{link_to "public access directory", public_root_path}.
%p
= internal_icon
Internal projects will be cloneable by
%em any authenticated user.
%ol
%li Go to your project dashboard
%li Click on the "Edit" tab
%li Select "Public clone access"
%li Change "Visibility Level"
- empty_repo = @project.empty_repo?
.project-home-panel{:class => ("empty-project" if empty_repo)}
.row
.span5
%h4.project-home-title
= @project.name_with_namespace
%span.visibility-level-label
= visibility_level_icon(@project.visibility_level)
= visibility_level_label(@project.visibility_level)
.span7
- unless empty_repo
.project-home-dropdown
= render "dropdown"
.form-horizontal
= render "shared/clone_panel"
.project-home-extra.clearfix
.project-home-desc
- if @project.description.present?
= @project.description
- if can?(current_user, :admin_project, @project)
–
%strong= link_to 'Edit', edit_project_path
- unless empty_repo
.project-home-links
= link_to pluralize(@repository.round_commit_count, 'commit'), project_commits_path(@project, @ref || @repository.root_ref)
= link_to pluralize(@repository.branch_names.count, 'branch'), project_branches_path(@project)
= link_to pluralize(@repository.tag_names.count, 'tag'), project_tags_path(@project)
%span.light.prepend-left-20= repository_size
\ No newline at end of file
.control-group.project-visibility-level-holder
= f.label :visibility_level, "Visibility Level"
- if can_change_visibility_level
- Gitlab::VisibilityLevel.values.each do |level|
- restricted = restricted_visibility_levels.include?(level)
.controls
= f.radio_button :visibility_level, level, checked: (visibility_level == level), disabled: restricted
%span.descr{:class => ("restricted" if restricted)}
= visibility_level_icon(level)
%strong
= visibility_level_label(level)
= visibility_level_description(level)
- unless restricted_visibility_levels.empty?
.controls
%span.info
Some visibility level settings have been restricted by the administrator.
- else
.controls
%span.info
= visibility_level_icon(visibility_level)
%strong
= visibility_level_label(visibility_level)
= visibility_level_description(visibility_level)
\ No newline at end of file
......@@ -29,22 +29,7 @@
.controls= f.select(:default_branch, @repository.branch_names, {}, {class: 'chosen'})
- if can?(current_user, :change_public_mode, @project)
%fieldset.public-mode
%legend
Public mode:
.control-group
= f.label :public, class: 'control-label' do
%span Public access
.controls
= f.check_box :public
%span.descr
If checked, this project can be cloned
%em without any
authentication.
It will also be listed on the #{link_to "public access directory", public_root_path}.
%em Any
user will have #{link_to "Guest", help_permissions_path} permissions on the repository.
= render "visibility_level", f: f, visibility_level: @project.visibility_level, can_change_visibility_level: can?(current_user, :change_visibility_level, @project)
%fieldset.features
%legend
......
%h3.page-title
= @project.name_with_namespace
.form-horizontal.pull-right
= render "shared/clone_panel"
= render "home_panel"
- if @project.import? && !@project.imported
.save-project-loader
......
......@@ -47,12 +47,7 @@
%span.light (optional)
.controls
= f.text_area :description, placeholder: "Awesome project", class: "input-xlarge", rows: 3, maxlength: 250, tabindex: 3
.control-group.project-public-holder
= f.label :public do
%span Public project
.controls
= f.check_box :public, { checked: gitlab_config.default_projects_features.public }, true, false
%span.help-inline Make project visible to everyone
= render "visibility_level", f: f, visibility_level: gitlab_config.default_projects_features.visibility_level, can_change_visibility_level: true
.form-actions
= f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4
......
.project-home-panel
.row
.span5
%h4.project-home-title
= @project.name_with_namespace
- if @project.public
%span.public-label Public
- else
%span.public-label Private
.span7
.project-home-dropdown
= render "dropdown"
.form-horizontal
= render "shared/clone_panel"
.project-home-extra.clearfix
.project-home-desc
- if @project.description.present?
= @project.description
- if can?(current_user, :admin_project, @project)
–
%strong= link_to 'Edit', edit_project_path
.project-home-links
= link_to pluralize(@repository.round_commit_count, 'commit'), project_commits_path(@project, @ref || @repository.root_ref)
= link_to pluralize(@repository.branch_names.count, 'branch'), project_branches_path(@project)
= link_to pluralize(@repository.tag_names.count, 'tag'), project_tags_path(@project)
%span.light.prepend-left-20= repository_size
= render "home_panel"
.row
.span9
......
......@@ -19,6 +19,10 @@
%h4
= link_to project_path(project) do
= project.name_with_namespace
- if project.internal?
%small.access-icon
= internal_icon
Internal
.pull-right
%pre.public-clone git clone #{project.http_url_to_repo}
......
......@@ -55,6 +55,10 @@ production: &base
# default: false - Account passwords are not sent via the email if signup is enabled.
# signup_enabled: true
# Restrict setting visibility levels for non-admin users.
# The default is to allow all levels.
#restricted_visibility_levels: [ "public" ]
## Automatic issue closing
# If a commit message matches this regular expression, all issues referenced from the matched text will be closed.
# This happens when the commit is pushed or merged into the default branch of a project.
......@@ -68,7 +72,7 @@ production: &base
wiki: true
wall: false
snippets: false
public: false
visibility_level: "private" # can be "private" | "internal" | "public"
## External issues trackers
issues_tracker:
......
......@@ -30,6 +30,29 @@ def build_gitlab_url
gitlab.relative_url_root
].join('')
end
# check that values in `current` (string or integer) is a contant in `modul`.
def verify_constant_array(modul, current, default)
values = default || []
if !current.nil?
values = []
current.each do |constant|
values.push(verify_constant(modul, constant, nil))
end
values.delete_if { |value| value.nil? }
end
values
end
# check that `current` (string or integer) is a contant in `modul`.
def verify_constant(modul, current, default)
constant = modul.constants.find{ |name| modul.const_get(name) == current }
value = constant.nil? ? default : modul.const_get(constant)
if current.is_a? String
value = modul.const_get(current.upcase) rescue default
end
value
end
end
end
......@@ -68,6 +91,7 @@ def build_gitlab_url
'/home/' + Settings.gitlab['user']
end
Settings.gitlab['signup_enabled'] ||= false
Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
Settings.gitlab['issue_closing_pattern'] = '([Cc]loses|[Ff]ixes) #(\d+)' if Settings.gitlab['issue_closing_pattern'].nil?
Settings.gitlab['default_projects_features'] ||= {}
......@@ -76,7 +100,7 @@ def build_gitlab_url
Settings.gitlab.default_projects_features['wiki'] = true if Settings.gitlab.default_projects_features['wiki'].nil?
Settings.gitlab.default_projects_features['wall'] = false if Settings.gitlab.default_projects_features['wall'].nil?
Settings.gitlab.default_projects_features['snippets'] = false if Settings.gitlab.default_projects_features['snippets'].nil?
Settings.gitlab.default_projects_features['public'] = false if Settings.gitlab.default_projects_features['public'].nil?
Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE)
#
# Gravatar
......
class AddVisibilityLevelToProjects < ActiveRecord::Migration
def self.up
add_column :projects, :visibility_level, :integer, :default => 0, :null => false
Project.where(public: true).update_all(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
remove_column :projects, :public
end
def self.down
add_column :projects, :public, :boolean, :default => false, :null => false
Project.where(visibility_level: Gitlab::VisibilityLevel::PUBLIC).update_all(public: true)
remove_column :projects, :visibility_level
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20131112114325) do
ActiveRecord::Schema.define(:version => 20131112220935) do
create_table "broadcast_messages", :force => true do |t|
t.text "message", :null => false
......@@ -185,13 +185,13 @@
t.boolean "merge_requests_enabled", :default => true, :null => false
t.boolean "wiki_enabled", :default => true, :null => false
t.integer "namespace_id"
t.boolean "public", :default => false, :null => false
t.string "issues_tracker", :default => "gitlab", :null => false
t.string "issues_tracker_id"
t.boolean "snippets_enabled", :default => true, :null => false
t.datetime "last_activity_at"
t.boolean "imported", :default => false, :null => false
t.string "import_url"
t.integer "visibility_level", :default => 0, :null => false
end
add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id"
......
......@@ -15,6 +15,7 @@ GET /projects
"description": null,
"default_branch": "master",
"public": false,
"visibility_level": 0,
"ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git",
"http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
"web_url": "http://example.com/diaspora/diaspora-client",
......@@ -49,6 +50,7 @@ GET /projects
"description": null,
"default_branch": "master",
"public": false,
"visibility_level": 0,
"ssh_url_to_repo": "git@example.com:brightbox/puppet.git",
"http_url_to_repo": "http://example.com/brightbox/puppet.git",
"web_url": "http://example.com/brightbox/puppet",
......@@ -117,6 +119,7 @@ Parameters:
"description": null,
"default_branch": "master",
"public": false,
"visibility_level": 0,
"ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git",
"http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
"web_url": "http://example.com/diaspora/diaspora-project-site",
......@@ -234,7 +237,8 @@ Parameters:
+ `merge_requests_enabled` (optional)
+ `wiki_enabled` (optional)
+ `snippets_enabled` (optional)
+ `public` (optional)
+ `public` (optional) - if `true` same as setting visibility_level = 20
+ `visibility_level` (optional)
### Create project for user
......@@ -256,7 +260,8 @@ Parameters:
+ `merge_requests_enabled` (optional)
+ `wiki_enabled` (optional)
+ `snippets_enabled` (optional)
+ `public` (optional)
+ `public` (optional) - if `true` same as setting visibility_level = 20
+ `visibility_level` (optional)
## Remove project
......
Feature: Public Projects Feature
Background:
Given public project "Community"
And internal project "Internal"
And private project "Enterprise"
Scenario: I visit public area
When I visit the public projects area
Then I should see project "Community"
And I should not see project "Internal"
And I should not see project "Enterprise"
Scenario: I visit public project page
When I visit project "Community" page
Then I should see project "Community" home page
Scenario: I visit internal project page
When I visit project "Internal" page
Then page status code should be 404
Scenario: I visit private project page
When I visit project "Enterprise" page
Then page status code should be 404
Scenario: I visit an empty public project page
Given public empty project "Empty Public Project"
When I visit empty project page
Then I should see empty public project details
Scenario: I visit public area as user
Given I sign in as a user
When I visit the public projects area
Then I should see project "Community"
And I should see project "Internal"
And I should not see project "Enterprise"
Scenario: I visit internal project page as user
Given I sign in as a user
When I visit project "Internal" page
Then I should see project "Internal" home page
class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedProject
step 'I should see project "Community"' do
page.should have_content "Community"
......@@ -23,11 +25,11 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
end
step 'public project "Community"' do
create :project_with_code, name: 'Community', public: true
create :project_with_code, name: 'Community', visibility_level: Gitlab::VisibilityLevel::PUBLIC
end
step 'public empty project "Empty Public Project"' do
create :project, name: 'Empty Public Project', public: true
create :project, name: 'Empty Public Project', visibility_level: Gitlab::VisibilityLevel::PUBLIC
end
step 'I visit empty project page' do
......@@ -48,16 +50,38 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
create :project, name: 'Enterprise'
end
step 'I visit project "Enterprise" page' do
project = Project.find_by_name('Enterprise')
visit project_path(project)
end
step 'I should see project "Community" home page' do
within '.project-home-title' do
page.should have_content 'Community'
end
end
private
step 'internal project "Internal"' do
create :project_with_code, name: 'Internal', visibility_level: Gitlab::VisibilityLevel::INTERNAL
end
def project
@project ||= Project.find_by_name("Community")
step 'I should see project "Internal"' do
page.should have_content "Internal"
end
step 'I should not see project "Internal"' do
page.should_not have_content "Internal"
end
step 'I visit project "Internal" page' do
project = Project.find_by_name('Internal')
visit project_path(project)
end
step 'I should see project "Internal" home page' do
within '.project-home-title' do
page.should have_content 'Internal'
end
end
end
......@@ -31,11 +31,13 @@ class ForkedFromProject < Grape::Entity
end
class Project < Grape::Entity
expose :id, :description, :default_branch, :public, :ssh_url_to_repo, :http_url_to_repo, :web_url
expose :id, :description, :default_branch
expose :public?, as: :public
expose :visibility_level, :ssh_url_to_repo, :http_url_to_repo, :web_url
expose :owner, using: Entities::UserBasic
expose :name, :name_with_namespace
expose :path, :path_with_namespace
expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at, :public
expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at
expose :namespace
expose :forked_from_project, using: Entities::ForkedFromProject, :if => lambda{ | project, options | project.forked? }
end
......
......@@ -11,6 +11,13 @@ def handle_project_member_errors(errors)
end
not_found!
end
def map_public_to_visibility_level(attrs)
publik = attrs.delete(:public)
publik = [ true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON' ].include?(publik)
attrs[:visibility_level] = Gitlab::VisibilityLevel::PUBLIC if !attrs[:visibility_level].present? && publik == true
attrs
end
end
# Get a projects list for authenticated user
......@@ -76,7 +83,8 @@ def handle_project_member_errors(errors)
# wiki_enabled (optional)
# snippets_enabled (optional)
# namespace_id (optional) - defaults to user namespace
# public (optional) - false by default
# public (optional) - if true same as setting visibility_level = 20
# visibility_level (optional) - 0 by default
# Example Request
# POST /projects
post do
......@@ -90,7 +98,9 @@ def handle_project_member_errors(errors)
:wiki_enabled,
:snippets_enabled,
:namespace_id,
:public]
:public,
:visibility_level]
attrs = map_public_to_visibility_level(attrs)
@project = ::Projects::CreateContext.new(current_user, attrs).execute
if @project.saved?
present @project, with: Entities::Project
......@@ -114,7 +124,8 @@ def handle_project_member_errors(errors)
# merge_requests_enabled (optional)
# wiki_enabled (optional)
# snippets_enabled (optional)
# public (optional)
# public (optional) - if true same as setting visibility_level = 20
# visibility_level (optional)
# Example Request
# POST /projects/user/:user_id
post "user/:user_id" do
......@@ -128,7 +139,9 @@ def handle_project_member_errors(errors)
:merge_requests_enabled,
:wiki_enabled,
:snippets_enabled,
:public]
:public,
:visibility_level]
attrs = map_public_to_visibility_level(attrs)
@project = ::Projects::CreateContext.new(user, attrs).execute
if @project.saved?
present @project, with: Entities::Project
......@@ -290,7 +303,8 @@ def handle_project_member_errors(errors)
# GET /projects/search/:query
get "/search/:query" do
ids = current_user.authorized_projects.map(&:id)
projects = Project.where("(id in (?) OR public = true) AND (name LIKE (?))", ids, "%#{params[:query]}%")
visibility_levels = [ Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC ]
projects = Project.where("(id in (?) OR visibility_level in (?)) AND (name LIKE (?))", ids, visibility_levels, "%#{params[:query]}%")
present paginate(projects), with: Entities::Project
end
end
......
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