Commit 8db12921 authored by Douwe Maan's avatar Douwe Maan

Tweaks, refactoring, and specs

parent 2eb19ea3
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
display: block; display: block;
} }
#project-home-desc { .project-home-desc {
font-size: 21px; font-size: 21px;
} }
......
...@@ -25,7 +25,6 @@ class ApplicationController < ActionController::Base ...@@ -25,7 +25,6 @@ class ApplicationController < ActionController::Base
helper_method :abilities, :can?, :current_application_settings helper_method :abilities, :can?, :current_application_settings
helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled? helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?
helper_method :repository, :can_collaborate_with_project?
rescue_from Encoding::CompatibilityError do |exception| rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception) log_exception(exception)
...@@ -118,47 +117,6 @@ class ApplicationController < ActionController::Base ...@@ -118,47 +117,6 @@ class ApplicationController < ActionController::Base
abilities.allowed?(object, action, subject) abilities.allowed?(object, action, subject)
end end
def project
unless @project
namespace = params[:namespace_id]
id = params[:project_id] || params[:id]
# Redirect from
# localhost/group/project.git
# to
# localhost/group/project
#
if id =~ /\.git\Z/
redirect_to request.original_url.gsub(/\.git\/?\Z/, '') and return
end
project_path = "#{namespace}/#{id}"
@project = Project.find_with_namespace(project_path)
if @project and can?(current_user, :read_project, @project)
if @project.path_with_namespace != project_path
redirect_to request.original_url.gsub(project_path, @project.path_with_namespace) and return
end
@project
elsif current_user.nil?
@project = nil
authenticate_user!
else
@project = nil
render_404 and return
end
end
@project
end
def repository
@repository ||= project.repository
end
def authorize_project!(action)
return access_denied! unless can?(current_user, action, project)
end
def access_denied! def access_denied!
render "errors/access_denied", layout: "errors", status: 404 render "errors/access_denied", layout: "errors", status: 404
end end
...@@ -167,14 +125,6 @@ class ApplicationController < ActionController::Base ...@@ -167,14 +125,6 @@ class ApplicationController < ActionController::Base
render "errors/git_not_found.html", layout: "errors", status: 404 render "errors/git_not_found.html", layout: "errors", status: 404
end end
def method_missing(method_sym, *arguments, &block)
if method_sym.to_s =~ /\Aauthorize_(.*)!\z/
authorize_project!($1.to_sym)
else
super
end
end
def render_403 def render_403
head :forbidden head :forbidden
end end
...@@ -183,10 +133,6 @@ class ApplicationController < ActionController::Base ...@@ -183,10 +133,6 @@ class ApplicationController < ActionController::Base
render file: Rails.root.join("public", "404"), layout: false, status: "404" render file: Rails.root.join("public", "404"), layout: false, status: "404"
end end
def require_non_empty_project
redirect_to @project if @project.empty_repo?
end
def no_cache_headers def no_cache_headers
response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate" response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
response.headers["Pragma"] = "no-cache" response.headers["Pragma"] = "no-cache"
...@@ -412,13 +358,6 @@ class ApplicationController < ActionController::Base ...@@ -412,13 +358,6 @@ class ApplicationController < ActionController::Base
current_user.nil? && root_path == request.path current_user.nil? && root_path == request.path
end end
def can_collaborate_with_project?(project = nil)
project ||= @project
can?(current_user, :push_code, project) ||
(current_user && current_user.already_forked?(project))
end
private private
def set_default_sort def set_default_sort
......
class Groups::ApplicationController < ApplicationController class Groups::ApplicationController < ApplicationController
layout 'group' layout 'group'
skip_before_action :authenticate_user!
before_action :group before_action :group
private private
def group def group
@group ||= Group.find_by(path: params[:group_id]) unless @group
end id = params[:group_id] || params[:id]
@group = Group.find_by(path: id)
def authorize_read_group!
unless @group && can?(current_user, :read_group, @group) unless @group && can?(current_user, :read_group, @group)
@group = nil
if current_user.nil? if current_user.nil?
return authenticate_user! authenticate_user!
else else
return render_404 render_404
end end
end end
end end
@group
end
def group_projects
@projects ||= GroupProjectsFinder.new(group).execute(current_user)
end
def authorize_admin_group! def authorize_admin_group!
unless can?(current_user, :admin_group, group) unless can?(current_user, :admin_group, group)
return render_404 return render_404
......
class Groups::AvatarsController < Groups::ApplicationController class Groups::AvatarsController < Groups::ApplicationController
before_action :authorize_admin_group!
def destroy def destroy
@group.remove_avatar! @group.remove_avatar!
@group.save @group.save
......
class Groups::GroupMembersController < Groups::ApplicationController class Groups::GroupMembersController < Groups::ApplicationController
skip_before_action :authenticate_user!, only: [:index]
# Authorize # Authorize
before_action :authorize_read_group!
before_action :authorize_admin_group_member!, except: [:index, :leave] before_action :authorize_admin_group_member!, except: [:index, :leave]
def index def index
......
class Groups::MilestonesController < Groups::ApplicationController class Groups::MilestonesController < Groups::ApplicationController
include GlobalMilestones include GlobalMilestones
before_action :projects before_action :group_projects
before_action :milestones, only: [:index] before_action :milestones, only: [:index]
before_action :milestone, only: [:show, :update] before_action :milestone, only: [:show, :update]
before_action :authorize_group_milestone!, only: [:create, :update] before_action :authorize_admin_milestones!, only: [:new, :create, :update]
def index def index
end end
...@@ -17,7 +17,7 @@ class Groups::MilestonesController < Groups::ApplicationController ...@@ -17,7 +17,7 @@ class Groups::MilestonesController < Groups::ApplicationController
project_ids = params[:milestone][:project_ids] project_ids = params[:milestone][:project_ids]
title = milestone_params[:title] title = milestone_params[:title]
@group.projects.where(id: project_ids).each do |project| @projects.where(id: project_ids).each do |project|
Milestones::CreateService.new(project, current_user, milestone_params).execute Milestones::CreateService.new(project, current_user, milestone_params).execute
end end
...@@ -37,7 +37,7 @@ class Groups::MilestonesController < Groups::ApplicationController ...@@ -37,7 +37,7 @@ class Groups::MilestonesController < Groups::ApplicationController
private private
def authorize_group_milestone! def authorize_admin_milestones!
return render_404 unless can?(current_user, :admin_milestones, group) return render_404 unless can?(current_user, :admin_milestones, group)
end end
...@@ -48,8 +48,4 @@ class Groups::MilestonesController < Groups::ApplicationController ...@@ -48,8 +48,4 @@ class Groups::MilestonesController < Groups::ApplicationController
def milestone_path(title) def milestone_path(title)
group_milestone_path(@group, title.to_slug.to_s, title: title) group_milestone_path(@group, title.to_slug.to_s, title: title)
end end
def projects
@projects ||= @group.projects
end
end end
...@@ -5,16 +5,15 @@ class GroupsController < Groups::ApplicationController ...@@ -5,16 +5,15 @@ class GroupsController < Groups::ApplicationController
respond_to :html respond_to :html
skip_before_action :authenticate_user!, only: [:index, :show, :issues, :merge_requests] before_action :authenticate_user!, only: [:new, :create]
before_action :group, except: [:index, :new, :create] before_action :group, except: [:index, :new, :create]
# Authorize # Authorize
before_action :authorize_read_group!, except: [:index, :new, :create]
before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects] before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects]
before_action :authorize_create_group!, only: [:new, :create] before_action :authorize_create_group!, only: [:new, :create]
# Load group projects # Load group projects
before_action :load_projects, except: [:index, :new, :create, :projects, :edit, :update, :autocomplete] before_action :group_projects, only: [:show, :projects, :activity, :issues, :merge_requests]
before_action :event_filter, only: [:activity] before_action :event_filter, only: [:activity]
layout :determine_layout layout :determine_layout
...@@ -39,12 +38,13 @@ class GroupsController < Groups::ApplicationController ...@@ -39,12 +38,13 @@ class GroupsController < Groups::ApplicationController
def show def show
@last_push = current_user.recent_push if current_user @last_push = current_user.recent_push if current_user
@projects = @projects.includes(:namespace) @projects = @projects.includes(:namespace)
@projects = filter_projects(@projects) @projects = filter_projects(@projects)
@projects = @projects.sort(@sort = params[:sort]) @projects = @projects.sort(@sort = params[:sort])
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank? @projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
@shared_projects = @group.shared_projects @shared_projects = GroupProjectsFinder.new(group, shared: true).execute(current_user)
respond_to do |format| respond_to do |format|
format.html format.html
...@@ -77,7 +77,7 @@ class GroupsController < Groups::ApplicationController ...@@ -77,7 +77,7 @@ class GroupsController < Groups::ApplicationController
end end
def projects def projects
@projects = @group.projects.page(params[:page]) @projects = @projects.sorted_by_activity.page(params[:page])
end end
def update def update
...@@ -96,15 +96,6 @@ class GroupsController < Groups::ApplicationController ...@@ -96,15 +96,6 @@ class GroupsController < Groups::ApplicationController
protected protected
def group
@group ||= Group.find_by(path: params[:id])
@group || render_404
end
def load_projects
@projects ||= ProjectsFinder.new.execute(current_user, group: group).sorted_by_activity
end
def authorize_create_group! def authorize_create_group!
unless can?(current_user, :create_group, nil) unless can?(current_user, :create_group, nil)
return render_404 return render_404
......
class Projects::ApplicationController < ApplicationController class Projects::ApplicationController < ApplicationController
before_action :project skip_before_action :authenticate_user!
before_action :repository before_action :project, :repository
layout 'project' layout 'project'
def authenticate_user! helper_method :repository, :can_collaborate_with_project?
# Restrict access to Projects area only
# for non-signed users private
if !current_user
def project
unless @project
namespace = params[:namespace_id]
id = params[:project_id] || params[:id] id = params[:project_id] || params[:id]
project_with_namespace = "#{params[:namespace_id]}/#{id}"
@project = Project.find_with_namespace(project_with_namespace)
return if @project && @project.public? # Redirect from
# localhost/group/project.git
# to
# localhost/group/project
#
if id =~ /\.git\Z/
redirect_to request.original_url.gsub(/\.git\/?\Z/, '')
return
end
project_path = "#{namespace}/#{id}"
@project = Project.find_with_namespace(project_path)
if @project && can?(current_user, :read_project, @project)
if @project.path_with_namespace != project_path
redirect_to request.original_url.gsub(project_path, @project.path_with_namespace)
end
else
@project = nil
if current_user.nil?
authenticate_user!
else
render_404
end
end
end
@project
end end
def repository
@repository ||= project.repository
end
def can_collaborate_with_project?(project = nil)
project ||= @project
can?(current_user, :push_code, project) ||
(current_user && current_user.already_forked?(project))
end
def authorize_project!(action)
return access_denied! unless can?(current_user, action, project)
end
def method_missing(method_sym, *arguments, &block)
if method_sym.to_s =~ /\Aauthorize_(.*)!\z/
authorize_project!($1.to_sym)
else
super super
end end
end
def require_non_empty_project
redirect_to @project if @project.empty_repo?
end
def require_branch_head def require_branch_head
unless @repository.branch_names.include?(@ref) unless @repository.branch_names.include?(@ref)
...@@ -26,8 +79,6 @@ class Projects::ApplicationController < ApplicationController ...@@ -26,8 +79,6 @@ class Projects::ApplicationController < ApplicationController
end end
end end
private
def apply_diff_view_cookie! def apply_diff_view_cookie!
view = params[:view] || cookies[:diff_view] view = params[:view] || cookies[:diff_view]
cookies.permanent[:diff_view] = params[:view] = view if view cookies.permanent[:diff_view] = params[:view] = view if view
......
class Projects::AvatarsController < Projects::ApplicationController class Projects::AvatarsController < Projects::ApplicationController
include BlobHelper include BlobHelper
before_action :project before_action :authorize_admin_project!, only: [:destroy]
def show def show
@blob = @repository.blob_at_branch('master', @project.avatar_in_git) @blob = @repository.blob_at_branch('master', @project.avatar_in_git)
......
class Projects::UploadsController < Projects::ApplicationController class Projects::UploadsController < Projects::ApplicationController
skip_before_action :authenticate_user!, :reject_blocked!, :project, skip_before_action :reject_blocked!, :project,
:repository, if: -> { action_name == 'show' && image? } :repository, if: -> { action_name == 'show' && image? }
before_action :authenticate_user!, only: [:create]
def create def create
link_to_file = ::Projects::UploadService.new(project, params[:file]). link_to_file = ::Projects::UploadService.new(project, params[:file]).
execute execute
...@@ -26,6 +28,8 @@ class Projects::UploadsController < Projects::ApplicationController ...@@ -26,6 +28,8 @@ class Projects::UploadsController < Projects::ApplicationController
send_file uploader.file.path, disposition: disposition send_file uploader.file.path, disposition: disposition
end end
private
def uploader def uploader
return @uploader if defined?(@uploader) return @uploader if defined?(@uploader)
......
class ProjectsController < ApplicationController class ProjectsController < Projects::ApplicationController
include ExtractsPath include ExtractsPath
skip_before_action :authenticate_user!, only: [:show, :activity] before_action :authenticate_user!, except: [:show, :activity]
before_action :project, except: [:new, :create] before_action :project, except: [:new, :create]
before_action :repository, except: [:new, :create] before_action :repository, except: [:new, :create]
before_action :assign_ref_vars, :tree, only: [:show], if: :repo_exists? before_action :assign_ref_vars, :tree, only: [:show], if: :repo_exists?
......
class ContributedProjectsFinder class ContributedProjectsFinder < UnionFinder
def initialize(user) def initialize(user)
@user = user @user = user
end end
...@@ -10,27 +10,20 @@ class ContributedProjectsFinder ...@@ -10,27 +10,20 @@ class ContributedProjectsFinder
# visible by this user. # visible by this user.
# #
# Returns an ActiveRecord::Relation. # Returns an ActiveRecord::Relation.
def execute(current_user = nil) def execute(current_user = nil)
if current_user segments = all_projects(current_user)
relation = projects_visible_to_user(current_user)
else
relation = public_projects
end
relation.includes(:namespace).order_id_desc find_union(segments, Project).includes(:namespace).order_id_desc
end end
private private
def projects_visible_to_user(current_user) def all_projects(current_user)
authorized = @user.contributed_projects.visible_to_user(current_user) projects = []
union = Gitlab::SQL::Union.new([authorized.select(:id), public_projects.select(:id)])
Project.where("projects.id IN (#{union.to_sql})") projects << @user.contributed_projects.visible_to_user(current_user) if current_user
end projects << @user.contributed_projects.public_to_user(current_user)
def public_projects projects
@user.contributed_projects.public_only
end end
end end
class GroupProjectsFinder < UnionFinder
def initialize(group, options = {})
@group = group
@options = options
end
def execute(current_user = nil)
segments = group_projects(current_user)
find_union(segments, Project)
end
private
def group_projects(current_user)
include_owned = @options.fetch(:owned, true)
include_shared = @options.fetch(:shared, true)
projects = []
if current_user
if @group.users.include?(current_user)
projects << @group.projects if include_owned
projects << @group.shared_projects if include_shared
else
if include_owned
projects << @group.projects.visible_to_user(current_user)
projects << @group.projects.public_to_user(current_user)
end
if include_shared
projects << @group.shared_projects.visible_to_user(current_user)
projects << @group.shared_projects.public_to_user(current_user)
end
end
else
projects << @group.projects.public_only if include_owned
projects << @group.shared_projects.public_only if include_shared
end
projects
end
end
class GroupsFinder class GroupsFinder < UnionFinder
def execute(current_user = nil) def execute(current_user = nil)
segments = all_groups(current_user) segments = all_groups(current_user)
if segments.length > 1 find_union(segments, Group).order_id_desc
union = Gitlab::SQL::Union.new(segments.map { |s| s.select(:id) })
Group.where("namespaces.id IN (#{union.to_sql})").order_id_desc
else
segments.first
end
end end
private private
def all_groups(current_user) def all_groups(current_user)
if current_user groups = []
user_groups(current_user)
else
[Group.unscoped.public_only]
end
end
def user_groups(current_user) groups << current_user.authorized_groups if current_user
if current_user.external? groups << Group.unscoped.public_to_user(current_user)
[current_user.authorized_groups, Group.unscoped.public_only]
else groups
[current_user.authorized_groups, Group.unscoped.public_and_internal_only]
end
end end
end end
...@@ -81,7 +81,7 @@ class IssuableFinder ...@@ -81,7 +81,7 @@ class IssuableFinder
elsif current_user && params[:authorized_only].presence && !current_user_related? elsif current_user && params[:authorized_only].presence && !current_user_related?
@projects = current_user.authorized_projects.reorder(nil) @projects = current_user.authorized_projects.reorder(nil)
else else
@projects = ProjectsFinder.new.execute(current_user, group: group). @projects = GroupProjectsFinder.new(group).execute(current_user).
reorder(nil) reorder(nil)
end end
end end
...@@ -170,7 +170,7 @@ class IssuableFinder ...@@ -170,7 +170,7 @@ class IssuableFinder
end end
def by_scope(items) def by_scope(items)
case params[:scope] case params[:scope] || 'all'
when 'created-by-me', 'authored' then when 'created-by-me', 'authored' then
items.where(author_id: current_user.id) items.where(author_id: current_user.id)
when 'all' then when 'all' then
......
#Shows only authorized groups of a user class JoinedGroupsFinder < UnionFinder
class JoinedGroupsFinder
def initialize(user) def initialize(user)
@user = user @user = user
end end
...@@ -12,34 +11,19 @@ class JoinedGroupsFinder ...@@ -12,34 +11,19 @@ class JoinedGroupsFinder
# #
# Returns an ActiveRecord::Relation. # Returns an ActiveRecord::Relation.
def execute(current_user = nil) def execute(current_user = nil)
if current_user segments = all_groups(current_user)
relation = groups_visible_to_user(current_user)
else
relation = public_groups
end
relation.order_id_desc find_union(segments, Group).order_id_desc
end end
private private
# Returns the groups the user in "current_user" can see. def all_groups(current_user)
# groups = []
# This list includes all public/internal projects as well as the projects of
# "@user" that "current_user" also has access to.
def groups_visible_to_user(current_user)
base = @user.authorized_groups.visible_to_user(current_user)
extra = current_user.external? ? public_groups : public_and_internal_groups
union = Gitlab::SQL::Union.new([base.select(:id), extra.select(:id)])
Group.where("namespaces.id IN (#{union.to_sql})") groups << @user.authorized_groups.visible_to_user(current_user) if current_user
end groups << @user.authorized_groups.public_to_user(current_user)
def public_groups
@user.authorized_groups.public_only
end
def public_and_internal_groups groups
@user.authorized_groups.public_and_internal_only
end end
end end
class PersonalProjectsFinder class PersonalProjectsFinder < UnionFinder
def initialize(user) def initialize(user)
@user = user @user = user
end end
...@@ -11,38 +11,19 @@ class PersonalProjectsFinder ...@@ -11,38 +11,19 @@ class PersonalProjectsFinder
# #
# Returns an ActiveRecord::Relation. # Returns an ActiveRecord::Relation.
def execute(current_user = nil) def execute(current_user = nil)
if current_user segments = all_projects(current_user)
relation = projects_visible_to_user(current_user)
else
relation = public_projects
end
relation.includes(:namespace).order_id_desc find_union(segments, Project).includes(:namespace).order_id_desc
end end
private private
def projects_visible_to_user(current_user) def all_projects(current_user)
union = Gitlab::SQL::Union.new(projects_for_user_ids(current_user)) projects = []
Project.where("projects.id IN (#{union.to_sql})")
end
def public_projects
@user.personal_projects.public_only
end
def public_and_internal_projects
@user.personal_projects.public_and_internal_only
end
def projects_for_user_ids(current_user) projects << @user.personal_projects.visible_to_user(current_user) if current_user
authorized = @user.personal_projects.visible_to_user(current_user) projects << @user.personal_projects.public_to_user(current_user)
if current_user.external? projects
[authorized.select(:id), public_projects.select(:id)]
else
[authorized.select(:id), public_and_internal_projects.select(:id)]
end
end end
end end
class ProjectsFinder class ProjectsFinder < UnionFinder
# Returns all projects, optionally including group projects a user has access
# to.
#
# ## Examples
#
# Retrieving all public projects:
#
# ProjectsFinder.new.execute
#
# Retrieving all public/internal projects and those the given user has access
# to:
#
# ProjectsFinder.new.execute(some_user)
#
# Retrieving all public/internal projects as well as the group's projects the
# user has access to:
#
# ProjectsFinder.new.execute(some_user, group: some_group)
#
# Returns an ActiveRecord::Relation.
def execute(current_user = nil, options = {}) def execute(current_user = nil, options = {})
group = options[:group]
if group
segments = group_projects(current_user, group)
else
segments = all_projects(current_user) segments = all_projects(current_user)
end
if segments.length > 1 find_union(segments, Project)
union = Gitlab::SQL::Union.new(segments.map { |s| s.select(:id) })
Project.where("projects.id IN (#{union.to_sql})")
else
segments.first
end
end end
private private
def group_projects(current_user, group)
return [group.projects.public_only] unless current_user
user_group_projects = [
group_projects_for_user(current_user, group),
group.shared_projects.visible_to_user(current_user)
]
if current_user.external?
user_group_projects << group.projects.public_only
else
user_group_projects << group.projects.public_and_internal_only
end
end
def all_projects(current_user) def all_projects(current_user)
return [public_projects] unless current_user projects = []
if current_user.external? projects << current_user.authorized_projects if current_user
[current_user.authorized_projects, public_projects] projects << Project.unscoped.public_to_user(current_user)
else
[current_user.authorized_projects, public_and_internal_projects]
end
end
def group_projects_for_user(current_user, group)
if group.users.include?(current_user)
group.projects
else
group.projects.visible_to_user(current_user)
end
end
def public_projects
Project.unscoped.public_only
end
def public_and_internal_projects projects
Project.unscoped.public_and_internal_only
end end
end end
class UnionFinder
def find_union(segments, klass)
if segments.length > 1
union = Gitlab::SQL::Union.new(segments.map { |s| s.select(:id) })
klass.where("#{klass.table_name}.id IN (#{union.to_sql})")
else
segments.first
end
end
end
...@@ -43,8 +43,4 @@ module GroupsHelper ...@@ -43,8 +43,4 @@ module GroupsHelper
full_title full_title
end end
end end
def group_visibility_description(group)
"#{visibility_level_label(group.visibility_level)} - #{group_visibility_level_description(group.visibility_level)}"
end
end end
...@@ -63,6 +63,14 @@ module VisibilityLevelHelper ...@@ -63,6 +63,14 @@ module VisibilityLevelHelper
end end
end end
def group_visibility_icon_description(group)
"#{visibility_level_label(group.visibility_level)} - #{group_visibility_level_description(group.visibility_level)}"
end
def project_visibility_icon_description(project)
"#{visibility_level_label(project.visibility_level)} - #{project_visibility_level_description(project.visibility_level)}"
end
def visibility_level_label(level) def visibility_level_label(level)
Project.visibility_levels.key(level) Project.visibility_levels.key(level)
end end
......
...@@ -114,6 +114,13 @@ class Ability ...@@ -114,6 +114,13 @@ class Ability
# Push abilities on the users team role # Push abilities on the users team role
rules.push(*project_team_rules(project.team, user)) rules.push(*project_team_rules(project.team, user))
if project.owner == user ||
(project.group && project.group.has_owner?(user)) ||
user.admin?
rules.push(*project_owner_rules)
end
if project.public? || (project.internal? && !user.external?) if project.public? || (project.internal? && !user.external?)
rules.push(*public_project_rules) rules.push(*public_project_rules)
...@@ -121,14 +128,6 @@ class Ability ...@@ -121,14 +128,6 @@ class Ability
rules << :read_build if project.public_builds? rules << :read_build if project.public_builds?
end end
if project.owner == user || user.admin?
rules.push(*project_admin_rules)
end
if project.group && project.group.has_owner?(user)
rules.push(*project_admin_rules)
end
if project.archived? if project.archived?
rules -= project_archived_rules rules -= project_archived_rules
end end
...@@ -228,8 +227,8 @@ class Ability ...@@ -228,8 +227,8 @@ class Ability
] ]
end end
def project_admin_rules def project_owner_rules
@project_admin_rules ||= project_master_rules + [ @project_owner_rules ||= project_master_rules + [
:change_namespace, :change_namespace,
:change_visibility_level, :change_visibility_level,
:rename_project, :rename_project,
...@@ -275,7 +274,7 @@ class Ability ...@@ -275,7 +274,7 @@ class Ability
rules << :read_group if can_read_group?(user, group) rules << :read_group if can_read_group?(user, group)
# Only group masters and group owners can create new projects and change permission level # Only group masters and group owners can create new projects
if group.has_master?(user) || group.has_owner?(user) || user.admin? if group.has_master?(user) || group.has_owner?(user) || user.admin?
rules += [ rules += [
:create_projects, :create_projects,
...@@ -298,7 +297,7 @@ class Ability ...@@ -298,7 +297,7 @@ class Ability
def can_read_group?(user, group) def can_read_group?(user, group)
user.admin? || group.public? || (group.internal? && !user.external?) || group.users.include?(user) || user.admin? || group.public? || (group.internal? && !user.external?) || group.users.include?(user) ||
ProjectsFinder.new.execute(user, group: group).any? GroupProjectsFinder.new(group).execute(user).any?
end end
def namespace_abilities(user, namespace) def namespace_abilities(user, namespace)
......
...@@ -83,16 +83,9 @@ class Group < Namespace ...@@ -83,16 +83,9 @@ class Group < Namespace
end end
def visibility_level_allowed_by_projects def visibility_level_allowed_by_projects
unless visibility_level_allowed?
level_name = Gitlab::VisibilityLevel.level_name(visibility_level).downcase
self.errors.add(:visibility_level, "#{level_name} is not allowed since there are projects with higher visibility.")
end
end
def visibility_level_allowed?
projects_visibility = self.projects.pluck(:visibility_level) projects_visibility = self.projects.pluck(:visibility_level)
allowed_by_projects = projects_visibility.none? { |project_visibility| self.visibility_level < project_visibility } allowed_by_projects = projects_visibility.all? { |project_visibility| self.visibility_level >= project_visibility }
unless allowed_by_projects unless allowed_by_projects
level_name = Gitlab::VisibilityLevel.level_name(visibility_level).downcase level_name = Gitlab::VisibilityLevel.level_name(visibility_level).downcase
......
...@@ -197,7 +197,8 @@ class Project < ActiveRecord::Base ...@@ -197,7 +197,8 @@ class Project < ActiveRecord::Base
validate :avatar_type, validate :avatar_type,
if: ->(project) { project.avatar.present? && project.avatar_changed? } if: ->(project) { project.avatar.present? && project.avatar_changed? }
validates :avatar, file_size: { maximum: 200.kilobytes.to_i } validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
validate :visibility_level_allowed_in_group validate :visibility_level_allowed_by_group
validate :visibility_level_allowed_as_fork
add_authentication_token_field :runners_token add_authentication_token_field :runners_token
before_save :ensure_runners_token before_save :ensure_runners_token
...@@ -441,16 +442,25 @@ class Project < ActiveRecord::Base ...@@ -441,16 +442,25 @@ class Project < ActiveRecord::Base
def check_limit def check_limit
unless creator.can_create_project? or namespace.kind == 'group' unless creator.can_create_project? or namespace.kind == 'group'
errors[:limit_reached] << ("Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it") self.errors.add(:limit_reached, "Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it")
end end
rescue rescue
errors[:base] << ("Can't check your ability to create project") self.errors.add(:base, "Can't check your ability to create project")
end end
def visibility_level_allowed_in_group def visibility_level_allowed_by_group
unless visibility_level_allowed? return if visibility_level_allowed_by_group?
self.errors.add(:visibility_level, "#{self.visibility_level} is not allowed in a #{self.group.visibility_level} group.")
level_name = Gitlab::VisibilityLevel.level_name(self.visibility_level).downcase
group_level_name = Gitlab::VisibilityLevel.level_name(self.group.visibility_level).downcase
self.errors.add(:visibility_level, "#{level_name} is not allowed in a #{group_level_name} group.")
end end
def visibility_level_allowed_as_fork
return if visibility_level_allowed_as_fork?
level_name = Gitlab::VisibilityLevel.level_name(self.visibility_level).downcase
self.errors.add(:visibility_level, "#{level_name} is not allowed since the fork source project has lower visibility.")
end end
def to_param def to_param
...@@ -965,22 +975,22 @@ class Project < ActiveRecord::Base ...@@ -965,22 +975,22 @@ class Project < ActiveRecord::Base
issues.opened.count issues.opened.count
end end
def visibility_level_allowed?(level = self.visibility_level) def visibility_level_allowed_as_fork?(level = self.visibility_level)
allowed_by_forks = if forked? && forked_project_link.forked_from_project_id.present? return true unless forked? && forked_project_link.forked_from_project_id.present?
from_project = eager_load_forked_from_project
from_project = self.forked_from_project
from_project ||= Project.find(forked_project_link.forked_from_project_id)
Gitlab::VisibilityLevel.allowed_fork_levels(from_project.visibility_level).include?(level) Gitlab::VisibilityLevel.allowed_fork_levels(from_project.visibility_level).include?(level)
else
true
end end
allowed_by_groups = group.present? ? level <= group.visibility_level : true def visibility_level_allowed_by_group?(level = self.visibility_level)
return true unless group
allowed_by_forks && allowed_by_groups level <= group.visibility_level
end end
#Necessary to retrieve many-to-many associations on new forks before validating visibility level def visibility_level_allowed?(level = self.visibility_level)
def eager_load_forked_from_project visibility_level_allowed_as_fork?(level) && visibility_level_allowed_by_group?(level)
Project.find(forked_project_link.forked_from_project_id)
end end
def runners_token def runners_token
......
...@@ -43,12 +43,9 @@ class BaseService ...@@ -43,12 +43,9 @@ class BaseService
def deny_visibility_level(model, denied_visibility_level = nil) def deny_visibility_level(model, denied_visibility_level = nil)
denied_visibility_level ||= model.visibility_level denied_visibility_level ||= model.visibility_level
level_name = Gitlab::VisibilityLevel.level_name(denied_visibility_level) level_name = Gitlab::VisibilityLevel.level_name(denied_visibility_level).downcase
model.errors.add( model.errors.add(:visibility_level, "#{level_name} has been restricted by your GitLab administrator")
:visibility_level,
"#{level_name} visibility has been restricted by your GitLab administrator"
)
end end
private private
......
...@@ -6,8 +6,7 @@ class CreateSnippetService < BaseService ...@@ -6,8 +6,7 @@ class CreateSnippetService < BaseService
snippet = project.snippets.build(params) snippet = project.snippets.build(params)
end end
unless Gitlab::VisibilityLevel.allowed_for?(current_user, unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
params[:visibility_level])
deny_visibility_level(snippet) deny_visibility_level(snippet)
return snippet return snippet
end end
......
module Groups module Groups
class BaseService class BaseService < BaseService
attr_accessor :group, :current_user, :params attr_accessor :group, :current_user, :params
def initialize(group, user, params = {}) def initialize(group, user, params = {})
@group, @current_user, @params = group, user, params.dup @group, @current_user, @params = group, user, params.dup
end end
private
def visibility_allowed_for_user?
level = group.visibility_level
allowed_by_user = Gitlab::VisibilityLevel.allowed_for?(current_user, level)
group.errors.add(:visibility_level, "#{level} has been restricted by your GitLab administrator.") unless allowed_by_user
allowed_by_user
end
end end
end end
...@@ -7,7 +7,10 @@ module Groups ...@@ -7,7 +7,10 @@ module Groups
def execute def execute
@group = Group.new(params) @group = Group.new(params)
return @group unless visibility_allowed_for_user? unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
deny_visibility_level(@group)
return @group
end
@group.name = @group.path.dup unless @group.name @group.name = @group.path.dup unless @group.name
@group.save @group.save
......
...@@ -5,9 +5,18 @@ ...@@ -5,9 +5,18 @@
module Groups module Groups
class UpdateService < Groups::BaseService class UpdateService < Groups::BaseService
def execute def execute
group.assign_attributes(params) # check that user is allowed to set specified visibility_level
new_visibility = params[:visibility_level]
if new_visibility && new_visibility.to_i != group.visibility_level
unless can?(current_user, :change_visibility_level, group) &&
Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
return false unless visibility_allowed_for_user? deny_visibility_level(group, new_visibility)
return group
end
end
group.assign_attributes(params)
group.save group.save
end end
......
...@@ -10,7 +10,7 @@ module Projects ...@@ -10,7 +10,7 @@ module Projects
@project = Project.new(params) @project = Project.new(params)
# Make sure that the user is allowed to use the specified visibility level # Make sure that the user is allowed to use the specified visibility level
unless visibility_level_allowed? unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
deny_visibility_level(@project) deny_visibility_level(@project)
return @project return @project
end end
...@@ -96,9 +96,5 @@ module Projects ...@@ -96,9 +96,5 @@ module Projects
@project.import_start if @project.import? @project.import_start if @project.import?
end end
def visibility_level_allowed?
Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) && @project.visibility_level_allowed?(@project.visibility_level)
end
end end
end end
...@@ -3,18 +3,15 @@ module Projects ...@@ -3,18 +3,15 @@ module Projects
def execute def execute
# check that user is allowed to set specified visibility_level # check that user is allowed to set specified visibility_level
new_visibility = params[:visibility_level] new_visibility = params[:visibility_level]
if new_visibility if new_visibility && new_visibility.to_i != project.visibility_level
if new_visibility.to_i != project.visibility_level
unless can?(current_user, :change_visibility_level, project) && unless can?(current_user, :change_visibility_level, project) &&
Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility) Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
deny_visibility_level(project, new_visibility) deny_visibility_level(project, new_visibility)
return project return project
end end
end end
return false unless visibility_level_allowed?(new_visibility)
end
new_branch = params[:default_branch] new_branch = params[:default_branch]
if project.repository.exists? && new_branch && new_branch != project.default_branch if project.repository.exists? && new_branch && new_branch != project.default_branch
...@@ -27,19 +24,5 @@ module Projects ...@@ -27,19 +24,5 @@ module Projects
end end
end end
end end
private
def visibility_level_allowed?(level)
return true if project.visibility_level_allowed?(level)
level_name = Gitlab::VisibilityLevel.level_name(level)
project.errors.add(
:visibility_level,
"#{level_name} could not be set as visibility level of this project - parent project settings are more restrictive"
)
false
end
end end
end end
...@@ -9,7 +9,6 @@ class UpdateSnippetService < BaseService ...@@ -9,7 +9,6 @@ class UpdateSnippetService < BaseService
def execute def execute
# check that user is allowed to set specified visibility_level # check that user is allowed to set specified visibility_level
new_visibility = params[:visibility_level] new_visibility = params[:visibility_level]
if new_visibility && new_visibility.to_i != snippet.visibility_level if new_visibility && new_visibility.to_i != snippet.visibility_level
unless Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility) unless Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
deny_visibility_level(snippet, new_visibility) deny_visibility_level(snippet, new_visibility)
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
.cover-title .cover-title
%h1 %h1
= @group.name = @group.name
%span.visibility-icon.has_tooltip{ data: { container: 'body', placement: 'left' }, title: group_visibility_description(@group) } %span.visibility-icon.has_tooltip{ data: { container: 'body' }, title: group_visibility_icon_description(@group) }
= visibility_level_icon(@group.visibility_level, fw: false) = visibility_level_icon(@group.visibility_level, fw: false)
.cover-desc.username .cover-desc.username
...@@ -27,8 +27,7 @@ ...@@ -27,8 +27,7 @@
.cover-desc.description .cover-desc.description
= markdown(@group.description, pipeline: :description) = markdown(@group.description, pipeline: :description)
- if can?(current_user, :read_group, @group) %div{ class: container_class }
%div{ class: container_class }
.top-area .top-area
%ul.nav-links %ul.nav-links
%li.active %li.active
...@@ -54,7 +53,3 @@ ...@@ -54,7 +53,3 @@
- if @shared_projects.present? - if @shared_projects.present?
.tab-pane#shared .tab-pane#shared
= render "shared_projects", projects: @shared_projects = render "shared_projects", projects: @shared_projects
- else
%p.nav-links.no-top
No projects to show
...@@ -12,13 +12,11 @@ ...@@ -12,13 +12,11 @@
= icon('group fw') = icon('group fw')
%span %span
Group Group
- if can?(current_user, :read_group, @group)
= nav_link(path: 'groups#activity') do = nav_link(path: 'groups#activity') do
= link_to activity_group_path(@group), title: 'Activity' do = link_to activity_group_path(@group), title: 'Activity' do
= icon('dashboard fw') = icon('dashboard fw')
%span %span
Activity Activity
- if current_user
= nav_link(controller: [:group, :milestones]) do = nav_link(controller: [:group, :milestones]) do
= link_to group_milestones_path(@group), title: 'Milestones' do = link_to group_milestones_path(@group), title: 'Milestones' do
= icon('clock-o fw') = icon('clock-o fw')
...@@ -29,15 +27,15 @@ ...@@ -29,15 +27,15 @@
= icon('exclamation-circle fw') = icon('exclamation-circle fw')
%span %span
Issues Issues
- if current_user - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
%span.count= number_with_delimiter(Issue.opened.of_group(@group).count) %span.count= number_with_delimiter(issues.count)
= nav_link(path: 'groups#merge_requests') do = nav_link(path: 'groups#merge_requests') do
= link_to merge_requests_group_path(@group), title: 'Merge Requests' do = link_to merge_requests_group_path(@group), title: 'Merge Requests' do
= icon('tasks fw') = icon('tasks fw')
%span %span
Merge Requests Merge Requests
- if current_user - merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened').execute
%span.count= number_with_delimiter(MergeRequest.opened.of_group(@group).count) %span.count= number_with_delimiter(merge_requests.count)
= nav_link(controller: [:group_members]) do = nav_link(controller: [:group_members]) do
= link_to group_group_members_path(@group), title: 'Members' do = link_to group_group_members_path(@group), title: 'Members' do
= icon('users fw') = icon('users fw')
......
...@@ -2,18 +2,18 @@ ...@@ -2,18 +2,18 @@
.project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)} .project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)}
.project-identicon-holder .project-identicon-holder
= project_icon(@project, alt: '', class: 'project-avatar avatar s90') = project_icon(@project, alt: '', class: 'project-avatar avatar s90')
.cover-title#project-home-desc .cover-title.project-home-desc
%h1 %h1
= @project.name = @project.name
%span.visibility-icon.has_tooltip{data: { container: 'body' }, %span.visibility-icon.has_tooltip{data: { container: 'body' }, title: project_visibility_icon_description(@project)}
title: "#{visibility_level_label(@project.visibility_level)} - #{project_visibility_level_description(@project.visibility_level)}"}
= visibility_level_icon(@project.visibility_level, fw: false) = visibility_level_icon(@project.visibility_level, fw: false)
- if @project.description.present? - if @project.description.present?
.cover-desc.project-home-desc
= markdown(@project.description, pipeline: :description) = markdown(@project.description, pipeline: :description)
- if forked_from_project = @project.forked_from_project - if forked_from_project = @project.forked_from_project
%p .cover-desc
Forked from Forked from
= link_to project_path(forked_from_project) do = link_to project_path(forked_from_project) do
= forked_from_project.namespace.try(:name) = forked_from_project.namespace.try(:name)
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
= icon('users') = icon('users')
= number_with_delimiter(group.users.count) = number_with_delimiter(group.users.count)
%span{title: group_visibility_description(group)} %span.visibility-icon.has_tooltip{data: { container: 'body', placement: 'left' }, title: group_visibility_icon_description(group)}
= visibility_level_icon(group.visibility_level, fw: false) = visibility_level_icon(group.visibility_level, fw: false)
= image_tag group_icon(group), class: "avatar s40 hidden-xs" = image_tag group_icon(group), class: "avatar s40 hidden-xs"
......
...@@ -27,8 +27,7 @@ ...@@ -27,8 +27,7 @@
%span %span
= icon('star') = icon('star')
= project.star_count = project.star_count
%span.visibility-icon.has_tooltip{data: { container: 'body', placement: 'left' }, %span.visibility-icon.has_tooltip{data: { container: 'body', placement: 'left' }, title: project_visibility_icon_description(project)}
title: "#{visibility_level_label(project.visibility_level)} - #{project_visibility_level_description(project.visibility_level)}"}
= visibility_level_icon(project.visibility_level, fw: false) = visibility_level_icon(project.visibility_level, fw: false)
.title .title
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
class AddDefaultGroupVisibilityToApplicationSettings < ActiveRecord::Migration class AddDefaultGroupVisibilityToApplicationSettings < ActiveRecord::Migration
def up def up
add_column :application_settings, :default_group_visibility, :integer add_column :application_settings, :default_group_visibility, :integer
execute("update application_settings set default_group_visibility = #{allowed_visibility_level}") execute("UPDATE application_settings SET default_group_visibility = #{allowed_visibility_level}")
end end
def down def down
...@@ -15,6 +15,7 @@ class AddDefaultGroupVisibilityToApplicationSettings < ActiveRecord::Migration ...@@ -15,6 +15,7 @@ class AddDefaultGroupVisibilityToApplicationSettings < ActiveRecord::Migration
private private
def allowed_visibility_level def allowed_visibility_level
# TODO: Don't use `current_application_settings`
allowed_levels = Gitlab::VisibilityLevel.values - current_application_settings.restricted_visibility_levels allowed_levels = Gitlab::VisibilityLevel.values - current_application_settings.restricted_visibility_levels
allowed_levels.max allowed_levels.max
end end
......
...@@ -590,8 +590,8 @@ ActiveRecord::Schema.define(version: 20160316204731) do ...@@ -590,8 +590,8 @@ ActiveRecord::Schema.define(version: 20160316204731) do
t.string "type" t.string "type"
t.string "description", default: "", null: false t.string "description", default: "", null: false
t.string "avatar" t.string "avatar"
t.integer "visibility_level", default: 0, null: false
t.boolean "share_with_group_lock", default: false t.boolean "share_with_group_lock", default: false
t.integer "visibility_level", default: 20, null: false
end end
add_index "namespaces", ["created_at", "id"], name: "index_namespaces_on_created_at_and_id", using: :btree add_index "namespaces", ["created_at", "id"], name: "index_namespaces_on_created_at_and_id", using: :btree
......
...@@ -111,6 +111,7 @@ Parameters: ...@@ -111,6 +111,7 @@ Parameters:
- `name` (required) - The name of the group - `name` (required) - The name of the group
- `path` (required) - The path of the group - `path` (required) - The path of the group
- `description` (optional) - The group's description - `description` (optional) - The group's description
- `visibility_level` (optional) - The group's visibility. 0 for private, 10 for internal, 20 for public.
## Transfer project to group ## Transfer project to group
......
...@@ -31,7 +31,7 @@ module API ...@@ -31,7 +31,7 @@ module API
authorize! :create_group, current_user authorize! :create_group, current_user
required_attributes! [:name, :path] required_attributes! [:name, :path]
attrs = attributes_for_keys [:name, :path, :description] attrs = attributes_for_keys [:name, :path, :description, :visibility_level]
@group = Group.new(attrs) @group = Group.new(attrs)
if @group.save if @group.save
......
...@@ -11,6 +11,8 @@ module Gitlab ...@@ -11,6 +11,8 @@ module Gitlab
included do included do
scope :public_only, -> { where(visibility_level: PUBLIC) } scope :public_only, -> { where(visibility_level: PUBLIC) }
scope :public_and_internal_only, -> { where(visibility_level: [PUBLIC, INTERNAL] ) } scope :public_and_internal_only, -> { where(visibility_level: [PUBLIC, INTERNAL] ) }
scope :public_to_user, -> (user) { user && !user.external ? public_and_internal_only : public_only }
end end
PRIVATE = 0 unless const_defined?(:PRIVATE) PRIVATE = 0 unless const_defined?(:PRIVATE)
......
...@@ -20,43 +20,4 @@ describe GroupsController do ...@@ -20,43 +20,4 @@ describe GroupsController do
end end
end end
end end
describe 'GET show' do
let(:group) { create(:group, visibility_level: 20) }
it 'checks if group can be read' do
expect(controller).to receive(:authorize_read_group!)
get :show, id: group.path
end
end
describe 'POST create' do
before { sign_in(create(:user)) }
it 'checks if group can be created' do
expect(controller).to receive(:authorize_create_group!)
post :create, { group: { name: "any params" } }
end
end
describe 'DELETE destroy' do
before { sign_in(create(:user)) }
let(:group) { create(:group, visibility_level: 20) }
it 'checks if group can be deleted' do
expect(controller).to receive(:authorize_admin_group!)
delete :destroy, id: group.path
end
end
describe 'PUT update' do
before { sign_in(create(:user)) }
let(:group) { create(:group, visibility_level: 20) }
it 'checks if group can be updated' do
expect_any_instance_of(Groups::UpdateService).to receive(:execute)
expect(controller).to receive(:authorize_admin_group!)
put :update, id: group.path, group: { name: 'test' }
end
end
end end
...@@ -15,12 +15,11 @@ describe NamespacesController do ...@@ -15,12 +15,11 @@ describe NamespacesController do
end end
context "when the namespace belongs to a group" do context "when the namespace belongs to a group" do
let!(:group) { create(:group, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } let!(:group) { create(:group) }
let!(:project) { create(:project, namespace: group) }
context "when the group has public projects" do context "when the group is public" do
before do before do
project.update_attribute(:visibility_level, Project::PUBLIC) group.update_attribute(:visibility_level, Group::PUBLIC)
end end
context "when not signed in" do context "when not signed in" do
...@@ -44,27 +43,27 @@ describe NamespacesController do ...@@ -44,27 +43,27 @@ describe NamespacesController do
end end
end end
context "when the project doesn't have public projects" do context "when the group is private" do
context "when not signed in" do context "when not signed in" do
it "does not redirect to the sign in page" do it "does not redirect to the sign in page" do
get :show, id: group.path get :show, id: group.path
expect(response).not_to redirect_to(new_user_session_path) expect(response).not_to redirect_to(new_user_session_path)
end end
end end
context "when signed in" do context "when signed in" do
before do before do
sign_in(user) sign_in(user)
end end
context "when the user has access to the project" do context "when the user has access to the group" do
before do before do
project.team << [user, :master] group.add_developer(user)
end end
context "when the user is blocked" do context "when the user is blocked" do
before do before do
user.block user.block
project.team << [user, :master]
end end
it "redirects to the sign in page" do it "redirects to the sign in page" do
...@@ -83,11 +82,11 @@ describe NamespacesController do ...@@ -83,11 +82,11 @@ describe NamespacesController do
end end
end end
context "when the user doesn't have access to the project" do context "when the user doesn't have access to the group" do
it "redirects to the group's page" do it "responds with status 404" do
get :show, id: group.path get :show, id: group.path
expect(response).to redirect_to(group_path(group)) expect(response.status).to eq(404)
end end
end end
end end
......
...@@ -127,12 +127,10 @@ describe UploadsController do ...@@ -127,12 +127,10 @@ describe UploadsController do
context "when viewing a group avatar" do context "when viewing a group avatar" do
let!(:group) { create(:group, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } let!(:group) { create(:group, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) }
let!(:project) { create(:project, namespace: group) }
context "when the group has public projects" do context "when the group is public" do
before do before do
group.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PUBLIC) group.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PUBLIC)
project.update_attribute(:visibility_level, Project::PUBLIC)
end end
context "when not signed in" do context "when not signed in" do
...@@ -156,7 +154,7 @@ describe UploadsController do ...@@ -156,7 +154,7 @@ describe UploadsController do
end end
end end
context "when the project doesn't have public projects" do context "when the group is private" do
context "when signed in" do context "when signed in" do
before do before do
sign_in(user) sign_in(user)
...@@ -164,13 +162,12 @@ describe UploadsController do ...@@ -164,13 +162,12 @@ describe UploadsController do
context "when the user has access to the project" do context "when the user has access to the project" do
before do before do
project.team << [user, :master] project.add_developer(user)
end end
context "when the user is blocked" do context "when the user is blocked" do
before do before do
user.block user.block
project.team << [user, :master]
end end
it "redirects to the sign in page" do it "redirects to the sign in page" do
......
...@@ -12,25 +12,25 @@ feature 'Project', feature: true do ...@@ -12,25 +12,25 @@ feature 'Project', feature: true do
it 'parses Markdown' do it 'parses Markdown' do
project.update_attribute(:description, 'This is **my** project') project.update_attribute(:description, 'This is **my** project')
visit path visit path
expect(page).to have_css('.cover-title > p > strong') expect(page).to have_css('.project-home-desc > p > strong')
end end
it 'passes through html-pipeline' do it 'passes through html-pipeline' do
project.update_attribute(:description, 'This project is the :poop:') project.update_attribute(:description, 'This project is the :poop:')
visit path visit path
expect(page).to have_css('.cover-title > p > img') expect(page).to have_css('.project-home-desc > p > img')
end end
it 'sanitizes unwanted tags' do it 'sanitizes unwanted tags' do
project.update_attribute(:description, "```\ncode\n```") project.update_attribute(:description, "```\ncode\n```")
visit path visit path
expect(page).not_to have_css('.cover-title code') expect(page).not_to have_css('.project-home-desc code')
end end
it 'permits `rel` attribute on links' do it 'permits `rel` attribute on links' do
project.update_attribute(:description, 'https://google.com/') project.update_attribute(:description, 'https://google.com/')
visit path visit path
expect(page).to have_css('.cover-title a[rel]') expect(page).to have_css('.project-home-desc a[rel]')
end end
end end
......
require 'rails_helper' require 'rails_helper'
describe 'Internal group access', feature: true do describe 'Internal Group access', feature: true do
include AccessMatchers include AccessMatchers
include GroupAccessHelper
describe 'GET /groups/:path' do let(:group) { create(:group, :internal) }
subject { group_path(group(Gitlab::VisibilityLevel::INTERNAL)) } let(:project) { create(:project, :internal, group: group) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :external }
let(:owner) { create(:user) }
let(:master) { create(:user) }
let(:developer) { create(:user) }
let(:reporter) { create(:user) }
let(:guest) { create(:user) }
let(:project_guest) { create(:user) }
before do
group.add_user(owner, Gitlab::Access::OWNER)
group.add_user(master, Gitlab::Access::MASTER)
group.add_user(developer, Gitlab::Access::DEVELOPER)
group.add_user(reporter, Gitlab::Access::REPORTER)
group.add_user(guest, Gitlab::Access::GUEST)
project.team << [project_guest, :guest]
end end
context "when user in group project" do describe "Group should be internal" do
it { is_expected.to be_allowed_for project_group_member(:user) } describe '#internal?' do
it { is_expected.to_not be_allowed_for :visitor } subject { group.internal? }
it { is_expected.to be_truthy }
end end
end end
describe 'GET /groups/:path/issues' do describe 'GET /groups/:path' do
subject { issues_group_path(group(Gitlab::VisibilityLevel::INTERNAL)) } subject { group_path(group) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for developer }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for project_guest }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end end
context "when user in group project" do describe 'GET /groups/:path/issues' do
it { is_expected.to be_allowed_for project_group_member(:user) } subject { issues_group_path(group) }
it { is_expected.to_not be_allowed_for :visitor }
end
end
describe 'GET /groups/:path/merge_requests' do
subject { issues_group_path(group(Gitlab::VisibilityLevel::INTERNAL)) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for developer }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for project_guest }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end end
context "when user in group project" do describe 'GET /groups/:path/merge_requests' do
it { is_expected.to be_allowed_for project_group_member(:user) } subject { merge_requests_group_path(group) }
it { is_expected.to_not be_allowed_for :visitor }
end it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for developer }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for project_guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end end
describe 'GET /groups/:path/group_members' do describe 'GET /groups/:path/group_members' do
subject { issues_group_path(group(Gitlab::VisibilityLevel::INTERNAL)) } subject { group_group_members_path(group) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for developer }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for project_guest }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :external }
end it { is_expected.to be_denied_for :visitor }
context "when user in group project" do
it { is_expected.to be_allowed_for project_group_member(:user) }
it { is_expected.to_not be_allowed_for :visitor }
end
end end
describe 'GET /groups/:path/edit' do describe 'GET /groups/:path/edit' do
subject { issues_group_path(group(Gitlab::VisibilityLevel::INTERNAL)) } subject { edit_group_path(group) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for owner }
it { is_expected.to be_denied_for master }
it { is_expected.to be_denied_for developer }
it { is_expected.to be_denied_for reporter }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for project_guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :external }
end end
context "when user in group project" do
it { is_expected.to be_allowed_for project_group_member(:user) }
it { is_expected.to_not be_allowed_for :visitor }
end
end
end end
require 'rails_helper' require 'rails_helper'
describe 'Private group access', feature: true do describe 'Private Group access', feature: true do
include AccessMatchers include AccessMatchers
include GroupAccessHelper
let(:group) { create(:group, :private) }
let(:project) { create(:project, :private, group: group) }
let(:owner) { create(:user) }
let(:master) { create(:user) }
let(:developer) { create(:user) }
let(:reporter) { create(:user) }
let(:guest) { create(:user) }
describe 'GET /groups/:path' do let(:project_guest) { create(:user) }
subject { group_path(group(Gitlab::VisibilityLevel::PRIVATE)) }
before do
context "when user not in group project" do group.add_user(owner, Gitlab::Access::OWNER)
it { is_expected.to be_allowed_for group_member(:owner) } group.add_user(master, Gitlab::Access::MASTER)
it { is_expected.to be_allowed_for group_member(:master) } group.add_user(developer, Gitlab::Access::DEVELOPER)
it { is_expected.to be_allowed_for group_member(:reporter) } group.add_user(reporter, Gitlab::Access::REPORTER)
it { is_expected.to be_allowed_for group_member(:guest) } group.add_user(guest, Gitlab::Access::GUEST)
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } project.team << [project_guest, :guest]
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :external }
end end
context "when user in group project" do describe "Group should be private" do
it { is_expected.to be_allowed_for project_group_member(:user) } describe '#private?' do
it { is_expected.to_not be_allowed_for :visitor } subject { group.private? }
it { is_expected.to be_truthy }
end end
end end
describe 'GET /groups/:path/issues' do describe 'GET /groups/:path' do
subject { issues_group_path(group(Gitlab::VisibilityLevel::PRIVATE)) } subject { group_path(group) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for developer }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for project_guest }
it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end end
context "when user in group project" do describe 'GET /groups/:path/issues' do
it { is_expected.to be_allowed_for project_group_member(:user) } subject { issues_group_path(group) }
it { is_expected.to_not be_allowed_for :visitor }
end
end
describe 'GET /groups/:path/merge_requests' do
subject { issues_group_path(group(Gitlab::VisibilityLevel::PRIVATE)) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for developer }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for project_guest }
it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end end
context "when user in group project" do describe 'GET /groups/:path/merge_requests' do
it { is_expected.to be_allowed_for project_group_member(:user) } subject { merge_requests_group_path(group) }
it { is_expected.to_not be_allowed_for :visitor }
end it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for developer }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for project_guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end end
describe 'GET /groups/:path/group_members' do describe 'GET /groups/:path/group_members' do
subject { issues_group_path(group(Gitlab::VisibilityLevel::PRIVATE)) } subject { group_group_members_path(group) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for developer }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for project_guest }
it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :external }
end it { is_expected.to be_denied_for :visitor }
context "when user in group project" do
it { is_expected.to be_allowed_for project_group_member(:user) }
it { is_expected.to_not be_allowed_for :visitor }
end
end end
describe 'GET /groups/:path/edit' do describe 'GET /groups/:path/edit' do
subject { issues_group_path(group(Gitlab::VisibilityLevel::PRIVATE)) } subject { edit_group_path(group) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_denied_for master }
it { is_expected.to be_denied_for developer }
it { is_expected.to be_denied_for reporter }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for project_guest }
it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :visitor } it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :external }
end end
context "when user in group project" do
it { is_expected.to be_allowed_for project_group_member(:user) }
it { is_expected.to_not be_allowed_for :visitor }
end
end
end end
require 'rails_helper' require 'rails_helper'
describe 'Public group access', feature: true do describe 'Public Group access', feature: true do
include AccessMatchers include AccessMatchers
include GroupAccessHelper
let(:group) { create(:group, :public) }
let(:project) { create(:project, :public, group: group) }
let(:owner) { create(:user) }
let(:master) { create(:user) }
let(:developer) { create(:user) }
let(:reporter) { create(:user) }
let(:guest) { create(:user) }
let(:project_guest) { create(:user) }
before do
group.add_user(owner, Gitlab::Access::OWNER)
group.add_user(master, Gitlab::Access::MASTER)
group.add_user(developer, Gitlab::Access::DEVELOPER)
group.add_user(reporter, Gitlab::Access::REPORTER)
group.add_user(guest, Gitlab::Access::GUEST)
project.team << [project_guest, :guest]
end
describe "Group should be public" do
describe '#public?' do
subject { group.public? }
it { is_expected.to be_truthy }
end
end
describe 'GET /groups/:path' do describe 'GET /groups/:path' do
subject { group_path(group(Gitlab::VisibilityLevel::PUBLIC)) } subject { group_path(group) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for developer }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for project_guest }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :visitor }
it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :external }
end
context "when user in group project" do
it { is_expected.to be_allowed_for project_group_member(:user) }
it { is_expected.to be_allowed_for :visitor } it { is_expected.to be_allowed_for :visitor }
end end
end
describe 'GET /groups/:path/issues' do describe 'GET /groups/:path/issues' do
subject { issues_group_path(group(Gitlab::VisibilityLevel::PUBLIC)) } subject { issues_group_path(group) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for developer }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for project_guest }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :visitor }
it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :external }
end
context "when user in group project" do
it { is_expected.to be_allowed_for project_group_member(:user) }
it { is_expected.to be_allowed_for :visitor } it { is_expected.to be_allowed_for :visitor }
end end
end
describe 'GET /groups/:path/merge_requests' do describe 'GET /groups/:path/merge_requests' do
subject { issues_group_path(group(Gitlab::VisibilityLevel::PUBLIC)) } subject { merge_requests_group_path(group) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for developer }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for project_guest }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :visitor }
it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :external }
end
context "when user in group project" do
it { is_expected.to be_allowed_for project_group_member(:user) }
it { is_expected.to be_allowed_for :visitor } it { is_expected.to be_allowed_for :visitor }
end end
end
describe 'GET /groups/:path/group_members' do describe 'GET /groups/:path/group_members' do
subject { issues_group_path(group(Gitlab::VisibilityLevel::PUBLIC)) } subject { group_group_members_path(group) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin } it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for developer }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for project_guest }
it { is_expected.to be_allowed_for :user } it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :visitor }
it { is_expected.to be_allowed_for :external } it { is_expected.to be_allowed_for :external }
end
context "when user in group project" do
it { is_expected.to be_allowed_for project_group_member(:user) }
it { is_expected.to be_allowed_for :visitor } it { is_expected.to be_allowed_for :visitor }
end end
end
describe 'GET /groups/:path/edit' do describe 'GET /groups/:path/edit' do
subject { issues_group_path(group(Gitlab::VisibilityLevel::PUBLIC)) } subject { edit_group_path(group) }
context "when user not in group project" do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for external_guest }
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :visitor }
it { is_expected.to be_allowed_for :external }
end
context "when user in group project" do it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for project_group_member(:user) } it { is_expected.to be_allowed_for owner }
it { is_expected.to be_allowed_for :visitor } it { is_expected.to be_denied_for master }
end it { is_expected.to be_denied_for developer }
it { is_expected.to be_denied_for reporter }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for project_guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :visitor }
it { is_expected.to be_denied_for :external }
end end
end end
require 'rails_helper'
describe 'Group access', feature: true do
include AccessMatchers
def group
@group ||= create(:group, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
end
def create_project(access_level)
if access_level == :mixed
create(:empty_project, :public, group: group)
create(:empty_project, :internal, group: group)
else
create(:empty_project, access_level, group: group)
end
end
def group_member(access_level, grp = group())
level = Object.const_get("Gitlab::Access::#{access_level.upcase}")
create(:user).tap do |user|
grp.add_user(user, level)
end
end
describe 'GET /groups/new' do
subject { new_group_path }
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :visitor }
end
describe 'GET /groups/:path' do
subject { group_path(group) }
context 'with public projects' do
let!(:project) { create_project(:public) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with mixed projects' do
let!(:project) { create_project(:mixed) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with internal projects' do
let!(:project) { create_project(:internal) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with no projects' do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
end
describe 'GET /groups/:path/issues' do
subject { issues_group_path(group) }
context 'with public projects' do
let!(:project) { create_project(:public) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with mixed projects' do
let!(:project) { create_project(:mixed) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with internal projects' do
let!(:project) { create_project(:internal) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with no projects' do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
end
describe 'GET /groups/:path/merge_requests' do
subject { merge_requests_group_path(group) }
context 'with public projects' do
let!(:project) { create_project(:public) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with mixed projects' do
let!(:project) { create_project(:mixed) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with internal projects' do
let!(:project) { create_project(:internal) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with no projects' do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
end
describe 'GET /groups/:path/group_members' do
subject { group_group_members_path(group) }
context 'with public projects' do
let!(:project) { create_project(:public) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with mixed projects' do
let!(:project) { create_project(:mixed) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with internal projects' do
let!(:project) { create_project(:internal) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with no projects' do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_allowed_for group_member(:master) }
it { is_expected.to be_allowed_for group_member(:reporter) }
it { is_expected.to be_allowed_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
end
describe 'GET /groups/:path/edit' do
subject { edit_group_path(group) }
context 'with public projects' do
let!(:project) { create_project(:public) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_denied_for group_member(:master) }
it { is_expected.to be_denied_for group_member(:reporter) }
it { is_expected.to be_denied_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with mixed projects' do
let!(:project) { create_project(:mixed) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_denied_for group_member(:master) }
it { is_expected.to be_denied_for group_member(:reporter) }
it { is_expected.to be_denied_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with internal projects' do
let!(:project) { create_project(:internal) }
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_denied_for group_member(:master) }
it { is_expected.to be_denied_for group_member(:reporter) }
it { is_expected.to be_denied_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
context 'with no projects' do
it { is_expected.to be_allowed_for group_member(:owner) }
it { is_expected.to be_denied_for group_member(:master) }
it { is_expected.to be_denied_for group_member(:reporter) }
it { is_expected.to be_denied_for group_member(:guest) }
it { is_expected.to be_allowed_for :admin }
end
end
end
...@@ -18,19 +18,4 @@ describe GroupsHelper do ...@@ -18,19 +18,4 @@ describe GroupsHelper do
expect(group_icon(group.path)).to match('group_avatar.png') expect(group_icon(group.path)).to match('group_avatar.png')
end end
end end
describe 'permissions' do
let(:group) { create(:group) }
let!(:user) { create(:user) }
before do
allow(self).to receive(:current_user).and_return(user)
allow(self).to receive(:can?) { true }
end
it 'checks user ability to change permissions' do
expect(self).to receive(:can?).with(user, :change_visibility_level, group)
can_change_group_visibility_level?(group)
end
end
end end
module GroupAccessHelper
def group(visibility_level=0)
@group ||= create(:group, visibility_level: visibility_level)
end
def project_group_member(access_level)
project = create(:project, visibility_level: group.visibility_level, group: group, name: 'B', path: 'B')
create(:user).tap { |user| project.team.add_user(user, Gitlab::Access::DEVELOPER) }
end
def group_member(access_level, grp=group())
level = Object.const_get("Gitlab::Access::#{access_level.upcase}")
create(:user).tap { |user| grp.add_user(user, level) }
end
def external_guest(grp=group())
create(:user, external: true).tap { |user| grp.add_user(user, Gitlab::Access::GUEST) }
end
end
...@@ -28,7 +28,7 @@ module AccessMatchers ...@@ -28,7 +28,7 @@ module AccessMatchers
if user.kind_of?(User) if user.kind_of?(User)
# User#inspect displays too much information for RSpec's description # User#inspect displays too much information for RSpec's description
# messages # messages
"be #{type} for supplied User" "be #{type} for the specified user"
else else
"be #{type} for #{user}" "be #{type} for #{user}"
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