mirror of
https://github.com/wahyd4/gitlabhq.git
synced 2026-08-11 21:56:19 +10:00
Merge branch 'feature/public_groups' into 'master'
Public Groups This is the initial work (meaning no tests) for making groups public if they have a public project (or internal for logged in users). This allows issues and merge requests to be viewed, but _not_ group membership. As part of this I have also added back the link in the public project title section (it was removed as it didn't make sense before). This addesses the following suggestions/issues: http://feedback.gitlab.com/forums/176466-general/suggestions/5314461-groups-containing-one-or-more-public-projects-shou Issue #32 https://github.com/gitlabhq/gitlabhq/issues/5203 as well as a few closed issues. This also changes the public user page to only show groups that are accessible to the user in some manner.
This commit is contained in:
@@ -77,5 +77,6 @@ class DashboardController < ApplicationController
|
||||
def default_filter
|
||||
params[:scope] = 'assigned-to-me' if params[:scope].blank?
|
||||
params[:state] = 'opened' if params[:state].blank?
|
||||
params[:authorized_only] = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
class GroupsController < ApplicationController
|
||||
skip_before_filter :authenticate_user!, only: [:show, :issues, :members, :merge_requests]
|
||||
respond_to :html
|
||||
before_filter :group, except: [:new, :create]
|
||||
|
||||
@@ -36,7 +37,7 @@ class GroupsController < ApplicationController
|
||||
@events = Event.in_projects(project_ids)
|
||||
@events = event_filter.apply_filter(@events)
|
||||
@events = @events.limit(20).offset(params[:offset] || 0)
|
||||
@last_push = current_user.recent_push
|
||||
@last_push = current_user.recent_push if current_user
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
@@ -98,17 +99,21 @@ class GroupsController < ApplicationController
|
||||
end
|
||||
|
||||
def projects
|
||||
@projects ||= current_user.authorized_projects.where(namespace_id: group.id).sorted_by_activity
|
||||
@projects ||= group.projects_accessible_to(current_user).sorted_by_activity
|
||||
end
|
||||
|
||||
def project_ids
|
||||
projects.map(&:id)
|
||||
projects.pluck(:id)
|
||||
end
|
||||
|
||||
# Dont allow unauthorized access to group
|
||||
def authorize_read_group!
|
||||
unless @group and (projects.present? or can?(current_user, :read_group, @group))
|
||||
return render_404
|
||||
if current_user.nil?
|
||||
return authenticate_user!
|
||||
else
|
||||
return render_404
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -131,13 +136,21 @@ class GroupsController < ApplicationController
|
||||
def determine_layout
|
||||
if [:new, :create].include?(action_name.to_sym)
|
||||
'navless'
|
||||
else
|
||||
elsif current_user
|
||||
'group'
|
||||
else
|
||||
'public_group'
|
||||
end
|
||||
end
|
||||
|
||||
def default_filter
|
||||
params[:scope] = 'assigned-to-me' if params[:scope].blank?
|
||||
if params[:scope].blank?
|
||||
if current_user
|
||||
params[:scope] = 'assigned-to-me'
|
||||
else
|
||||
params[:scope] = 'all'
|
||||
end
|
||||
end
|
||||
params[:state] = 'opened' if params[:state].blank?
|
||||
params[:group_id] = @group.id
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ class Public::ProjectsController < ApplicationController
|
||||
layout 'public'
|
||||
|
||||
def index
|
||||
@projects = Project.public_or_internal_only(current_user)
|
||||
@projects = Project.publicish(current_user)
|
||||
@projects = @projects.search(params[:search]) if params[:search].present?
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@projects = @projects.includes(:namespace).page(params[:page]).per(20)
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
class UsersController < ApplicationController
|
||||
|
||||
skip_before_filter :authenticate_user!, only: [:show]
|
||||
layout :determine_layout
|
||||
|
||||
def show
|
||||
@user = User.find_by_username!(params[:username])
|
||||
@projects = @user.authorized_projects.includes(:namespace).select {|project| can?(current_user, :read_project, project)}
|
||||
@projects = @user.authorized_projects.accessible_to(current_user)
|
||||
if !current_user && @projects.empty?
|
||||
return authenticate_user!
|
||||
end
|
||||
@events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20)
|
||||
@groups = @user.groups.accessible_to(current_user)
|
||||
@events = @user.recent_events.where(project_id: @projects.pluck(:id)).limit(20)
|
||||
@title = @user.name
|
||||
end
|
||||
|
||||
|
||||
@@ -6,6 +6,14 @@ module GroupsHelper
|
||||
def leave_group_message(group)
|
||||
"Are you sure you want to leave \"#{group}\" group?"
|
||||
end
|
||||
|
||||
def should_user_see_group_roles?(user, group)
|
||||
if user
|
||||
user.is_admin? || group.members.exists?(user_id: user.id)
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def group_head_title
|
||||
title = @group.name
|
||||
|
||||
@@ -4,8 +4,7 @@ module SearchHelper
|
||||
|
||||
resources_results = [
|
||||
groups_autocomplete(term),
|
||||
projects_autocomplete(term),
|
||||
public_projects_autocomplete(term),
|
||||
projects_autocomplete(term)
|
||||
].flatten
|
||||
|
||||
generic_results = project_autocomplete + default_autocomplete + help_autocomplete
|
||||
@@ -82,17 +81,7 @@ module SearchHelper
|
||||
|
||||
# Autocomplete results for the current user's projects
|
||||
def projects_autocomplete(term, limit = 5)
|
||||
current_user.authorized_projects.search_by_title(term).non_archived.limit(limit).map do |p|
|
||||
{
|
||||
label: "project: #{search_result_sanitize(p.name_with_namespace)}",
|
||||
url: project_path(p)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# Autocomplete results for the current user's projects
|
||||
def public_projects_autocomplete(term, limit = 5)
|
||||
Project.public_or_internal_only(current_user).search_by_title(term).non_archived.limit(limit).map do |p|
|
||||
Project.accessible_to(current_user).search_by_title(term).non_archived.limit(limit).map do |p|
|
||||
{
|
||||
label: "project: #{search_result_sanitize(p.name_with_namespace)}",
|
||||
url: project_path(p)
|
||||
|
||||
+14
-2
@@ -43,7 +43,19 @@ class Ability
|
||||
:download_code
|
||||
]
|
||||
else
|
||||
[]
|
||||
group = if subject.kind_of?(Group)
|
||||
subject
|
||||
elsif subject.respond_to?(:group)
|
||||
subject.group
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
||||
if group && group.has_projects_accessible_to?(nil)
|
||||
[:read_group]
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -172,7 +184,7 @@ class Ability
|
||||
def group_abilities user, group
|
||||
rules = []
|
||||
|
||||
if group.users.include?(user) || user.admin?
|
||||
if user.admin? || group.users.include?(user) || group.has_projects_accessible_to?(user)
|
||||
rules << :read_group
|
||||
end
|
||||
|
||||
|
||||
@@ -25,6 +25,12 @@ class Group < Namespace
|
||||
validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
|
||||
|
||||
mount_uploader :avatar, AttachmentUploader
|
||||
|
||||
def self.accessible_to(user)
|
||||
accessible_ids = Project.accessible_to(user).pluck(:namespace_id)
|
||||
accessible_ids += user.groups.pluck(:id) if user
|
||||
where(id: accessible_ids)
|
||||
end
|
||||
|
||||
def human_name
|
||||
name
|
||||
|
||||
@@ -47,6 +47,14 @@ class Namespace < ActiveRecord::Base
|
||||
def self.global_id
|
||||
'GLN'
|
||||
end
|
||||
|
||||
def projects_accessible_to(user)
|
||||
projects.accessible_to(user)
|
||||
end
|
||||
|
||||
def has_projects_accessible_to?(user)
|
||||
projects_accessible_to(user).present?
|
||||
end
|
||||
|
||||
def to_param
|
||||
path
|
||||
|
||||
+12
-2
@@ -115,8 +115,6 @@ class Project < ActiveRecord::Base
|
||||
scope :sorted_by_activity, -> { reorder("projects.last_activity_at DESC") }
|
||||
scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
|
||||
scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) }
|
||||
scope :public_only, -> { where(visibility_level: PUBLIC) }
|
||||
scope :public_or_internal_only, ->(user) { where("visibility_level IN (:levels)", levels: user ? [ INTERNAL, PUBLIC ] : [ PUBLIC ]) }
|
||||
|
||||
scope :non_archived, -> { where(archived: false) }
|
||||
|
||||
@@ -126,6 +124,18 @@ class Project < ActiveRecord::Base
|
||||
def abandoned
|
||||
where('projects.last_activity_at < ?', 6.months.ago)
|
||||
end
|
||||
|
||||
def publicish(user)
|
||||
visibility_levels = [Project::PUBLIC]
|
||||
visibility_levels += [Project::INTERNAL] if user
|
||||
where(visibility_level: visibility_levels)
|
||||
end
|
||||
|
||||
def accessible_to(user)
|
||||
accessible_ids = publicish(user).pluck(:id)
|
||||
accessible_ids += user.authorized_projects.pluck(:id) if user
|
||||
where(id: accessible_ids)
|
||||
end
|
||||
|
||||
def with_push
|
||||
includes(:events).where('events.action = ?', Event::PUSHED)
|
||||
|
||||
@@ -41,16 +41,16 @@ class FilteringService
|
||||
def init_collection
|
||||
table_name = klass.table_name
|
||||
|
||||
return klass.of_projects(Project.public_only) unless current_user
|
||||
|
||||
if project
|
||||
if current_user.can?(:read_project, project)
|
||||
if project.public? || (current_user && current_user.can?(:read_project, project))
|
||||
project.send(table_name)
|
||||
else
|
||||
[]
|
||||
end
|
||||
else
|
||||
elsif current_user && params[:authorized_only].presence
|
||||
klass.of_projects(current_user.authorized_projects)
|
||||
else
|
||||
klass.of_projects(Project.accessible_to(current_user))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -11,12 +11,8 @@ module Search
|
||||
query = Shellwords.shellescape(query) if query.present?
|
||||
return result unless query.present?
|
||||
|
||||
authorized_projects_ids = []
|
||||
authorized_projects_ids += current_user.authorized_projects.pluck(:id) if current_user
|
||||
authorized_projects_ids += Project.public_or_internal_only(current_user).pluck(:id)
|
||||
|
||||
group = Group.find_by(id: params[:group_id]) if params[:group_id].present?
|
||||
projects = Project.where(id: authorized_projects_ids)
|
||||
projects = Project.accessible_to(current_user)
|
||||
projects = projects.where(namespace_id: group.id) if group
|
||||
projects = projects.search(query)
|
||||
project_ids = projects.pluck(:id)
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
%p.light
|
||||
Only issues from
|
||||
%strong #{@group.name}
|
||||
group are listed here. To see all issues you should visit #{link_to 'dashboard', issues_dashboard_path} page.
|
||||
group are listed here.
|
||||
- if current_user
|
||||
To see all issues you should visit #{link_to 'dashboard', issues_dashboard_path} page.
|
||||
%hr
|
||||
|
||||
.row
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
- show_roles = should_user_see_group_roles?(current_user, @group)
|
||||
%h3.page-title
|
||||
Group members
|
||||
%p.light
|
||||
Members of group have access to all group projects.
|
||||
Read more about permissions
|
||||
%strong= link_to "here", help_permissions_path, class: "vlink"
|
||||
- if show_roles
|
||||
%p.light
|
||||
Members of group have access to all group projects.
|
||||
Read more about permissions
|
||||
%strong= link_to "here", help_permissions_path, class: "vlink"
|
||||
|
||||
%hr
|
||||
|
||||
@@ -13,7 +15,7 @@
|
||||
= search_field_tag :search, params[:search], { placeholder: 'Find member by name', class: 'form-control search-text-input input-mn-300' }
|
||||
= submit_tag 'Search', class: 'btn'
|
||||
|
||||
- if current_user.can? :manage_group, @group
|
||||
- if current_user && current_user.can?(:manage_group, @group)
|
||||
.pull-right
|
||||
= link_to '#', class: 'btn btn-new js-toggle-visibility-link' do
|
||||
Add members
|
||||
@@ -30,7 +32,7 @@
|
||||
(#{@members.total_count})
|
||||
%ul.well-list
|
||||
- @members.each do |member|
|
||||
= render 'users_groups/users_group', member: member, show_controls: true
|
||||
= render 'users_groups/users_group', member: member, show_roles: show_roles, show_controls: true
|
||||
= paginate @members, theme: 'gitlab'
|
||||
|
||||
:coffeescript
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
%p.light
|
||||
Only merge requests from
|
||||
%strong #{@group.name}
|
||||
group are listed here. To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page.
|
||||
group are listed here.
|
||||
- if current_user
|
||||
To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page.
|
||||
%hr
|
||||
.row
|
||||
.col-md-3
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
.dashboard
|
||||
.activities.col-md-8.hidden-sm
|
||||
= render "events/event_last_push", event: @last_push
|
||||
= link_to dashboard_path, class: 'btn btn-tiny' do
|
||||
← To dashboard
|
||||
|
||||
- if current_user
|
||||
= render "events/event_last_push", event: @last_push
|
||||
= link_to dashboard_path, class: 'btn btn-tiny' do
|
||||
← To dashboard
|
||||
|
||||
%span.cgray You will only see events from projects in this group
|
||||
%hr
|
||||
= render 'shared/event_filter'
|
||||
@@ -21,11 +22,12 @@
|
||||
- if @group.description.present?
|
||||
%p= @group.description
|
||||
= render "projects", projects: @projects
|
||||
.prepend-top-20
|
||||
= link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed" do
|
||||
%strong
|
||||
%i.icon-rss
|
||||
News Feed
|
||||
- if current_user
|
||||
.prepend-top-20
|
||||
= link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed" do
|
||||
%strong
|
||||
%i.icon-rss
|
||||
News Feed
|
||||
|
||||
%hr
|
||||
= render 'shared/promo'
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
= nav_link(path: 'groups#issues') do
|
||||
= link_to issues_group_path(@group) do
|
||||
Issues
|
||||
%span.count= current_user.assigned_issues.opened.of_group(@group).count
|
||||
- if current_user
|
||||
%span.count= current_user.assigned_issues.opened.of_group(@group).count
|
||||
= nav_link(path: 'groups#merge_requests') do
|
||||
= link_to merge_requests_group_path(@group) do
|
||||
Merge Requests
|
||||
%span.count= current_user.cared_merge_requests.opened.of_group(@group).count
|
||||
- if current_user
|
||||
%span.count= current_user.cared_merge_requests.opened.of_group(@group).count
|
||||
= nav_link(path: 'groups#members') do
|
||||
= link_to "Members", members_group_path(@group)
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
!!! 5
|
||||
%html{ lang: "en"}
|
||||
= render "layouts/head", title: group_head_title
|
||||
%body{class: "#{app_theme} application", :'data-page' => body_data_page}
|
||||
= render "layouts/broadcast"
|
||||
= render "layouts/public_head_panel", title: "group: #{@group.name}"
|
||||
%nav.main-nav.navbar-collapse.collapse
|
||||
.container= render 'layouts/nav/group'
|
||||
.container
|
||||
.content= yield
|
||||
@@ -3,7 +3,7 @@
|
||||
= render "layouts/head", title: @project.name_with_namespace
|
||||
%body{class: "#{app_theme} application", :'data-page' => body_data_page}
|
||||
= render "layouts/broadcast"
|
||||
= render "layouts/public_head_panel", title: @project.name_with_namespace
|
||||
= render "layouts/public_head_panel", title: project_title(@project)
|
||||
%nav.main-nav
|
||||
.container= render 'layouts/nav/project'
|
||||
.container
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
.side-filters.hidden-xs.hidden-sm
|
||||
= form_tag filter_path(entity), method: 'get' do
|
||||
%fieldset.scope-filter
|
||||
%ul.nav.nav-pills.nav-stacked
|
||||
%li{class: ("active" if params[:scope] == 'assigned-to-me')}
|
||||
= link_to filter_path(entity, scope: 'assigned-to-me') do
|
||||
Assigned to me
|
||||
%li{class: ("active" if params[:scope] == 'authored')}
|
||||
= link_to filter_path(entity, scope: 'authored') do
|
||||
Created by me
|
||||
%li{class: ("active" if params[:scope] == 'all')}
|
||||
= link_to filter_path(entity, scope: 'all') do
|
||||
Everyone's
|
||||
- if current_user
|
||||
%fieldset.scope-filter
|
||||
%ul.nav.nav-pills.nav-stacked
|
||||
%li{class: ("active" if params[:scope] == 'assigned-to-me')}
|
||||
= link_to filter_path(entity, scope: 'assigned-to-me') do
|
||||
Assigned to me
|
||||
%li{class: ("active" if params[:scope] == 'authored')}
|
||||
= link_to filter_path(entity, scope: 'authored') do
|
||||
Created by me
|
||||
%li{class: ("active" if params[:scope] == 'all')}
|
||||
= link_to filter_path(entity, scope: 'all') do
|
||||
Everyone's
|
||||
|
||||
%fieldset.status-filter
|
||||
%legend State
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
%small member since #{@user.created_at.stamp("Nov 12, 2031")}
|
||||
.clearfix
|
||||
%h4 Groups:
|
||||
= render 'groups', groups: @user.groups
|
||||
= render 'groups', groups: @groups
|
||||
%hr
|
||||
%h4 User Activity:
|
||||
= render @events
|
||||
.col-md-4
|
||||
= render 'profile', user: @user
|
||||
= render 'projects', user: @user
|
||||
= render 'projects'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
- user = member.user
|
||||
- return unless user
|
||||
- show_roles = true if show_roles.nil?
|
||||
%li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)}
|
||||
= image_tag avatar_icon(user.email, 16), class: "avatar s16"
|
||||
%strong= user.name
|
||||
@@ -7,22 +8,23 @@
|
||||
- if user == current_user
|
||||
%span.label.label-success It's you
|
||||
|
||||
%span.pull-right
|
||||
%strong= member.human_access
|
||||
- if show_controls
|
||||
- if can?(current_user, :modify, member)
|
||||
= link_to '#', class: "btn-tiny btn js-toggle-button", title: 'Edit access level' do
|
||||
%i.icon-edit
|
||||
- if can?(current_user, :destroy, member)
|
||||
- if current_user == member.user
|
||||
= link_to leave_profile_group_path(@group), data: { confirm: leave_group_message(@group.name)}, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
|
||||
%i.icon-minus.icon-white
|
||||
- else
|
||||
= link_to group_users_group_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
|
||||
%i.icon-minus.icon-white
|
||||
|
||||
.edit-member.hide.js-toggle-content
|
||||
= form_for [@group, member], remote: true do |f|
|
||||
.alert.prepend-top-20
|
||||
= f.select :group_access, options_for_select(UsersGroup.group_access_roles, member.group_access)
|
||||
= f.submit 'Save', class: 'btn btn-save btn-small'
|
||||
- if show_roles
|
||||
%span.pull-right
|
||||
%strong= member.human_access
|
||||
- if show_controls
|
||||
- if can?(current_user, :modify, member)
|
||||
= link_to '#', class: "btn-tiny btn js-toggle-button", title: 'Edit access level' do
|
||||
%i.icon-edit
|
||||
- if can?(current_user, :destroy, member)
|
||||
- if current_user == member.user
|
||||
= link_to leave_profile_group_path(@group), data: { confirm: leave_group_message(@group.name)}, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
|
||||
%i.icon-minus.icon-white
|
||||
- else
|
||||
= link_to group_users_group_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
|
||||
%i.icon-minus.icon-white
|
||||
|
||||
.edit-member.hide.js-toggle-content
|
||||
= form_for [@group, member], remote: true do |f|
|
||||
.alert.prepend-top-20
|
||||
= f.select :group_access, options_for_select(UsersGroup.group_access_roles, member.group_access)
|
||||
= f.submit 'Save', class: 'btn btn-save btn-small'
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
Feature: Public Projects Feature
|
||||
Background:
|
||||
Given group "TestGroup" has private project "Enterprise"
|
||||
|
||||
Scenario: I should not see group with private projects as visitor
|
||||
When I visit group "TestGroup" page
|
||||
Then I should be redirected to sign in page
|
||||
|
||||
Scenario: I should not see group with private projects group as user
|
||||
When I sign in as a user
|
||||
And I visit group "TestGroup" page
|
||||
Then page status code should be 404
|
||||
|
||||
Scenario: I should not see group with private and internal projects as visitor
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
When I visit group "TestGroup" page
|
||||
Then I should be redirected to sign in page
|
||||
|
||||
Scenario: I should see group with private and internal projects as user
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
When I sign in as a user
|
||||
And I visit group "TestGroup" page
|
||||
Then I should see project "Internal" items
|
||||
And I should not see project "Enterprise" items
|
||||
|
||||
Scenario: I should see group issues for internal project as user
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
When I sign in as a user
|
||||
And I visit group "TestGroup" issues page
|
||||
And I change filter to Everyone's
|
||||
Then I should see project "Internal" items
|
||||
And I should not see project "Enterprise" items
|
||||
|
||||
Scenario: I should see group merge requests for internal project as user
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
When I sign in as a user
|
||||
And I visit group "TestGroup" merge requests page
|
||||
And I change filter to Everyone's
|
||||
Then I should see project "Internal" items
|
||||
And I should not see project "Enterprise" items
|
||||
|
||||
Scenario: I should see group's members as user
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
And "John Doe" is owner of group "TestGroup"
|
||||
When I sign in as a user
|
||||
And I visit group "TestGroup" members page
|
||||
Then I should see group member "John Doe"
|
||||
And I should not see member roles
|
||||
|
||||
Scenario: I should see group with private, internal and public projects as visitor
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
Given group "TestGroup" has public project "Community"
|
||||
When I visit group "TestGroup" page
|
||||
Then I should see project "Community" items
|
||||
And I should not see project "Internal" items
|
||||
And I should not see project "Enterprise" items
|
||||
|
||||
Scenario: I should see group issues for public project as visitor
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
Given group "TestGroup" has public project "Community"
|
||||
When I visit group "TestGroup" issues page
|
||||
Then I should see project "Community" items
|
||||
And I should not see project "Internal" items
|
||||
And I should not see project "Enterprise" items
|
||||
|
||||
Scenario: I should see group merge requests for public project as visitor
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
Given group "TestGroup" has public project "Community"
|
||||
When I visit group "TestGroup" merge requests page
|
||||
Then I should see project "Community" items
|
||||
And I should not see project "Internal" items
|
||||
And I should not see project "Enterprise" items
|
||||
|
||||
Scenario: I should see group's members as visitor
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
Given group "TestGroup" has public project "Community"
|
||||
And "John Doe" is owner of group "TestGroup"
|
||||
When I visit group "TestGroup" members page
|
||||
Then I should see group member "John Doe"
|
||||
And I should not see member roles
|
||||
|
||||
Scenario: I should see group with private, internal and public projects as user
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
Given group "TestGroup" has public project "Community"
|
||||
When I sign in as a user
|
||||
And I visit group "TestGroup" page
|
||||
Then I should see project "Community" items
|
||||
And I should see project "Internal" items
|
||||
And I should not see project "Enterprise" items
|
||||
|
||||
Scenario: I should see group issues for internal and public projects as user
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
Given group "TestGroup" has public project "Community"
|
||||
When I sign in as a user
|
||||
And I visit group "TestGroup" issues page
|
||||
And I change filter to Everyone's
|
||||
Then I should see project "Community" items
|
||||
And I should see project "Internal" items
|
||||
And I should not see project "Enterprise" items
|
||||
|
||||
Scenario: I should see group merge requests for internal and public projects as user
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
Given group "TestGroup" has public project "Community"
|
||||
When I sign in as a user
|
||||
And I visit group "TestGroup" merge requests page
|
||||
And I change filter to Everyone's
|
||||
Then I should see project "Community" items
|
||||
And I should see project "Internal" items
|
||||
And I should not see project "Enterprise" items
|
||||
|
||||
Scenario: I should see group's members as user
|
||||
Given group "TestGroup" has internal project "Internal"
|
||||
Given group "TestGroup" has public project "Community"
|
||||
And "John Doe" is owner of group "TestGroup"
|
||||
When I sign in as a user
|
||||
And I visit group "TestGroup" members page
|
||||
Then I should see group member "John Doe"
|
||||
And I should not see member roles
|
||||
@@ -0,0 +1,93 @@
|
||||
class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
|
||||
include SharedAuthentication
|
||||
include SharedPaths
|
||||
include SharedGroup
|
||||
include SharedProject
|
||||
|
||||
step 'group "TestGroup" has private project "Enterprise"' do
|
||||
group_has_project("TestGroup", "Enterprise", Gitlab::VisibilityLevel::PRIVATE)
|
||||
end
|
||||
|
||||
step 'group "TestGroup" has internal project "Internal"' do
|
||||
group_has_project("TestGroup", "Internal", Gitlab::VisibilityLevel::INTERNAL)
|
||||
end
|
||||
|
||||
step 'group "TestGroup" has public project "Community"' do
|
||||
group_has_project("TestGroup", "Community", Gitlab::VisibilityLevel::PUBLIC)
|
||||
end
|
||||
|
||||
step '"John Doe" is owner of group "TestGroup"' do
|
||||
group = Group.find_by(name: "TestGroup") || create(:group, name: "TestGroup")
|
||||
user = create(:user, name: "John Doe")
|
||||
group.add_user(user, Gitlab::Access::OWNER)
|
||||
end
|
||||
|
||||
step 'I visit group "TestGroup" page' do
|
||||
visit group_path(Group.find_by(name: "TestGroup"))
|
||||
end
|
||||
|
||||
step 'I visit group "TestGroup" issues page' do
|
||||
visit issues_group_path(Group.find_by(name: "TestGroup"))
|
||||
end
|
||||
|
||||
step 'I visit group "TestGroup" merge requests page' do
|
||||
visit merge_requests_group_path(Group.find_by(name: "TestGroup"))
|
||||
end
|
||||
|
||||
step 'I visit group "TestGroup" members page' do
|
||||
visit members_group_path(Group.find_by(name: "TestGroup"))
|
||||
end
|
||||
|
||||
step 'I should not see project "Enterprise" items' do
|
||||
page.should_not have_content "Enterprise"
|
||||
end
|
||||
|
||||
step 'I should see project "Internal" items' do
|
||||
page.should have_content "Internal"
|
||||
end
|
||||
|
||||
step 'I should not see project "Internal" items' do
|
||||
page.should_not have_content "Internal"
|
||||
end
|
||||
|
||||
step 'I should see project "Community" items' do
|
||||
page.should have_content "Community"
|
||||
end
|
||||
|
||||
step 'I change filter to Everyone\'s' do
|
||||
click_link "Everyone's"
|
||||
end
|
||||
|
||||
step 'I should see group member "John Doe"' do
|
||||
page.should have_content "John Doe"
|
||||
end
|
||||
|
||||
step 'I should not see member roles' do
|
||||
page.body.should_not match(%r{owner|developer|reporter|guest}i)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def group_has_project(groupname, projectname, visibility_level)
|
||||
group = Group.find_by(name: groupname) || create(:group, name: groupname)
|
||||
project = create(:project,
|
||||
namespace: group,
|
||||
name: projectname,
|
||||
path: "#{groupname}-#{projectname}",
|
||||
visibility_level: visibility_level
|
||||
)
|
||||
create(:issue,
|
||||
title: "#{projectname} feature",
|
||||
project: project
|
||||
)
|
||||
create(:merge_request,
|
||||
title: "#{projectname} feature implemented",
|
||||
source_project: project,
|
||||
target_project: project
|
||||
)
|
||||
create(:closed_issue_event,
|
||||
project: project
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
+6
@@ -14,6 +14,7 @@ describe "Group access" do
|
||||
let(:master) { create(:user) }
|
||||
let(:reporter) { create(:user) }
|
||||
let(:guest) { create(:user) }
|
||||
let(:nonmember) { create(:user) }
|
||||
|
||||
before do
|
||||
group.add_user(owner, Gitlab::Access::OWNER)
|
||||
@@ -21,6 +22,11 @@ describe "Group access" do
|
||||
group.add_user(reporter, Gitlab::Access::REPORTER)
|
||||
group.add_user(guest, Gitlab::Access::GUEST)
|
||||
end
|
||||
|
||||
describe "Group should not have accessible projects" do
|
||||
it { group.has_projects_accessible_to?(nil).should be_false }
|
||||
it { group.has_projects_accessible_to?(nonmember).should be_false }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path" do
|
||||
subject { group_path(group) }
|
||||
@@ -0,0 +1,87 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Group with internal project access" do
|
||||
describe "Group" do
|
||||
let(:group) { create(:group) }
|
||||
|
||||
let(:owner) { create(:owner) }
|
||||
let(:master) { create(:user) }
|
||||
let(:reporter) { create(:user) }
|
||||
let(:guest) { create(:user) }
|
||||
let(:nonmember) { create(:user) }
|
||||
|
||||
before do
|
||||
group.add_user(owner, Gitlab::Access::OWNER)
|
||||
group.add_user(master, Gitlab::Access::MASTER)
|
||||
group.add_user(reporter, Gitlab::Access::REPORTER)
|
||||
group.add_user(guest, Gitlab::Access::GUEST)
|
||||
|
||||
create(:project, group: group, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
|
||||
end
|
||||
|
||||
describe "Group should have accessible projects for users" do
|
||||
it { group.has_projects_accessible_to?(nil).should be_false }
|
||||
it { group.has_projects_accessible_to?(nonmember).should be_true }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path" do
|
||||
subject { group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_allowed_for master }
|
||||
it { should be_allowed_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_allowed_for guest }
|
||||
it { should be_allowed_for :user }
|
||||
it { should be_denied_for :visitor }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path/issues" do
|
||||
subject { issues_group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_allowed_for master }
|
||||
it { should be_allowed_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_allowed_for guest }
|
||||
it { should be_allowed_for :user }
|
||||
it { should be_denied_for :visitor }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path/merge_requests" do
|
||||
subject { merge_requests_group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_allowed_for master }
|
||||
it { should be_allowed_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_allowed_for guest }
|
||||
it { should be_allowed_for :user }
|
||||
it { should be_denied_for :visitor }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path/members" do
|
||||
subject { members_group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_allowed_for master }
|
||||
it { should be_allowed_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_allowed_for guest }
|
||||
it { should be_allowed_for :user }
|
||||
it { should be_denied_for :visitor }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path/edit" do
|
||||
subject { edit_group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_denied_for master }
|
||||
it { should be_denied_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_denied_for guest }
|
||||
it { should be_denied_for :user }
|
||||
it { should be_denied_for :visitor }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,88 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Group access" do
|
||||
describe "Group" do
|
||||
let(:group) { create(:group) }
|
||||
|
||||
let(:owner) { create(:owner) }
|
||||
let(:master) { create(:user) }
|
||||
let(:reporter) { create(:user) }
|
||||
let(:guest) { create(:user) }
|
||||
let(:nonmember) { create(:user) }
|
||||
|
||||
before do
|
||||
group.add_user(owner, Gitlab::Access::OWNER)
|
||||
group.add_user(master, Gitlab::Access::MASTER)
|
||||
group.add_user(reporter, Gitlab::Access::REPORTER)
|
||||
group.add_user(guest, Gitlab::Access::GUEST)
|
||||
|
||||
create(:project, path: "internal_project", group: group, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
|
||||
create(:project, path: "public_project", group: group, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
|
||||
end
|
||||
|
||||
describe "Group should have accessible projects" do
|
||||
it { group.has_projects_accessible_to?(nil).should be_true }
|
||||
it { group.has_projects_accessible_to?(nonmember).should be_true }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path" do
|
||||
subject { group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_allowed_for master }
|
||||
it { should be_allowed_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_allowed_for guest }
|
||||
it { should be_allowed_for :user }
|
||||
it { should be_allowed_for :visitor }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path/issues" do
|
||||
subject { issues_group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_allowed_for master }
|
||||
it { should be_allowed_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_allowed_for guest }
|
||||
it { should be_allowed_for :user }
|
||||
it { should be_allowed_for :visitor }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path/merge_requests" do
|
||||
subject { merge_requests_group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_allowed_for master }
|
||||
it { should be_allowed_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_allowed_for guest }
|
||||
it { should be_allowed_for :user }
|
||||
it { should be_allowed_for :visitor }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path/members" do
|
||||
subject { members_group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_allowed_for master }
|
||||
it { should be_allowed_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_allowed_for guest }
|
||||
it { should be_allowed_for :user }
|
||||
it { should be_allowed_for :visitor }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path/edit" do
|
||||
subject { edit_group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_denied_for master }
|
||||
it { should be_denied_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_denied_for guest }
|
||||
it { should be_denied_for :user }
|
||||
it { should be_denied_for :visitor }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,87 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Group with public project access" do
|
||||
describe "Group" do
|
||||
let(:group) { create(:group) }
|
||||
|
||||
let(:owner) { create(:owner) }
|
||||
let(:master) { create(:user) }
|
||||
let(:reporter) { create(:user) }
|
||||
let(:guest) { create(:user) }
|
||||
let(:nonmember) { create(:user) }
|
||||
|
||||
before do
|
||||
group.add_user(owner, Gitlab::Access::OWNER)
|
||||
group.add_user(master, Gitlab::Access::MASTER)
|
||||
group.add_user(reporter, Gitlab::Access::REPORTER)
|
||||
group.add_user(guest, Gitlab::Access::GUEST)
|
||||
|
||||
create(:project, group: group, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
|
||||
end
|
||||
|
||||
describe "Group should have accessible projects" do
|
||||
it { group.has_projects_accessible_to?(nil).should be_true }
|
||||
it { group.has_projects_accessible_to?(nonmember).should be_true }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path" do
|
||||
subject { group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_allowed_for master }
|
||||
it { should be_allowed_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_allowed_for guest }
|
||||
it { should be_allowed_for :user }
|
||||
it { should be_allowed_for :visitor }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path/issues" do
|
||||
subject { issues_group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_allowed_for master }
|
||||
it { should be_allowed_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_allowed_for guest }
|
||||
it { should be_allowed_for :user }
|
||||
it { should be_allowed_for :visitor }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path/merge_requests" do
|
||||
subject { merge_requests_group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_allowed_for master }
|
||||
it { should be_allowed_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_allowed_for guest }
|
||||
it { should be_allowed_for :user }
|
||||
it { should be_allowed_for :visitor }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path/members" do
|
||||
subject { members_group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_allowed_for master }
|
||||
it { should be_allowed_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_allowed_for guest }
|
||||
it { should be_allowed_for :user }
|
||||
it { should be_allowed_for :visitor }
|
||||
end
|
||||
|
||||
describe "GET /groups/:path/edit" do
|
||||
subject { edit_group_path(group) }
|
||||
|
||||
it { should be_allowed_for owner }
|
||||
it { should be_denied_for master }
|
||||
it { should be_denied_for reporter }
|
||||
it { should be_allowed_for :admin }
|
||||
it { should be_denied_for guest }
|
||||
it { should be_denied_for :user }
|
||||
it { should be_denied_for :visitor }
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user