Commit 71cf4e51 authored by Jason Hollingsworth's avatar Jason Hollingsworth
Browse files

Allow access to groups with public projects.

Fixed Group avatars to only display when user has read
permissions to at least one project in the group.
parent 569a7cec5d43
......@@ -77,5 +77,6 @@
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
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 @@
@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,7 +99,7 @@
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
......@@ -102,9 +103,9 @@
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))
......@@ -106,9 +107,13 @@
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,4 +136,6 @@
def determine_layout
if [:new, :create].include?(action_name.to_sym)
'navless'
elsif current_user
'group'
else
......@@ -134,6 +141,6 @@
else
'group'
'public_group'
end
end
def default_filter
......@@ -136,8 +143,14 @@
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 @@
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)
......
class UsersController < ApplicationController
skip_before_filter :authenticate_user!, only: [:show]
layout :determine_layout
def show
@user = User.find_by_username!(params[:username])
......@@ -3,9 +2,9 @@
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
......@@ -9,7 +8,8 @@
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 @@
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 @@
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 @@
# 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)
......
......@@ -43,7 +43,19 @@
: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 @@
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 @@
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 @@
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
......
......@@ -114,8 +114,6 @@
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) }
......@@ -125,6 +123,18 @@
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,6 +41,4 @@
def init_collection
table_name = klass.table_name
return klass.of_projects(Project.public_only) unless current_user
if project
......@@ -46,6 +44,6 @@
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
......@@ -48,5 +46,7 @@
project.send(table_name)
else
[]
end
elsif current_user && params[:authorized_only].presence
klass.of_projects(current_user.authorized_projects)
else
......@@ -52,5 +52,5 @@
else
klass.of_projects(current_user.authorized_projects)
klass.of_projects(Project.accessible_to(current_user))
end
end
......
......@@ -11,8 +11,4 @@
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?
......@@ -18,5 +14,5 @@
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
......
- show_roles = should_user_see_group_roles?(current_user, @group)
%h3.page-title
Group members
......@@ -1,9 +2,10 @@
%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
......
.dashboard
.activities.col-md-8.hidden-sm
= render "events/event_last_push", event: @last_push
= link_to dashboard_path, class: 'btn btn-tiny' do
&larr; To dashboard
&nbsp;
- if current_user
= render "events/event_last_push", event: @last_push
= link_to dashboard_path, class: 'btn btn-tiny' do
&larr; To dashboard
&nbsp;
%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,7 +5,8 @@
= 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
......@@ -9,7 +10,8 @@
= 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)
......
!!! 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
......
.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
......
Supports Markdown
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