diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index f6f7e3b..014ef77 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -99,7 +99,7 @@ class GroupsController < ApplicationController end def projects - @projects ||= group.projects_accessible_to(current_user).sorted_by_activity + @projects ||= Projects::CollectService.new.execute(current_user, group: group) end def project_ids diff --git a/app/models/ability.rb b/app/models/ability.rb index 89f8f32..e5b5771 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -50,7 +50,7 @@ class Ability else nil end - + if group && group.has_projects_accessible_to?(nil) [:read_group] else @@ -184,7 +184,7 @@ class Ability def group_abilities user, group rules = [] - if user.admin? || group.users.include?(user) || group.has_projects_accessible_to?(user) + if user.admin? || Projects::CollectService.new.execute(user, group: group).any? rules << :read_group end diff --git a/app/models/project.rb b/app/models/project.rb index 60f0e40..c3bf7a5 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -116,21 +116,28 @@ class Project < ActiveRecord::Base scope :personal, ->(user) { where(namespace_id: user.namespace_id) } scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) } + scope :public_only, -> { where(visibility_level: Project::PUBLIC) } + scope :public_and_internal_only, -> { where(visibility_level: Project.public_and_internal_levels) } + scope :non_archived, -> { where(archived: false) } enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab class << self + def public_and_internal_levels + [Project::PUBLIC, Project::INTERNAL] + end + 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 diff --git a/app/services/projects/collect_service.rb b/app/services/projects/collect_service.rb new file mode 100644 index 0000000..0c26231 --- /dev/null +++ b/app/services/projects/collect_service.rb @@ -0,0 +1,69 @@ +# Projects::CollectService class +# +# Used to collect projects user has access to +# +module Projects + class CollectService + def execute(current_user, options) + group = options[:group] + + if group + group_projects(current_user, group) + else + all_projects(current_user) + end + end + + private + + def group_projects(current_user, group) + if current_user + if group.users.include?(current_user) + # User is group member + # + # Return ALL group projects + group.projects + else + projects_members = UsersProject.where( + project_id: group.projects, + user_id: current_user + ) + + if projects_members.any? + # User is a project member + # + # Return only: + # public projects + # internal projects + # joined projects + # + group.projects.where( + "projects.id IN (?) OR projects.visibility_level IN (?)", + projects_members.pluck(:project_id), + Project.public_and_internal_levels + ) + else + # User has no access to group or group projects + # + # Return only: + # public projects + # internal projects + # + group.projects.public_and_internal_only + end + end + else + # Not authenticated + # + # Return only: + # public projects + group.projects.public_only + end + end + end + + def all_projects + # TODO: implement + raise 'Not implemented yet' + end +end diff --git a/spec/services/projects_collect_service_spec.rb b/spec/services/projects_collect_service_spec.rb new file mode 100644 index 0000000..107c6dc --- /dev/null +++ b/spec/services/projects_collect_service_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +describe Projects::CollectService do + let(:user) { create :user } + let(:group) { create :group } + + let(:project1) { create(:empty_project, group: group, visibility_level: Project::PUBLIC) } + let(:project2) { create(:empty_project, group: group, visibility_level: Project::INTERNAL) } + let(:project3) { create(:empty_project, group: group, visibility_level: Project::PRIVATE) } + let(:project4) { create(:empty_project, group: group, visibility_level: Project::PRIVATE) } + + context 'non authenticated' do + subject { Projects::CollectService.new.execute(nil, group: group) } + + it { should include(project1) } + it { should_not include(project2) } + it { should_not include(project3) } + it { should_not include(project4) } + end + + context 'authenticated' do + subject { Projects::CollectService.new.execute(user, group: group) } + + it { should include(project1) } + it { should include(project2) } + it { should_not include(project3) } + it { should_not include(project4) } + end + + context 'authenticated, project member' do + before { project3.team << [user, :developer] } + + subject { Projects::CollectService.new.execute(user, group: group) } + + it { should include(project1) } + it { should include(project2) } + it { should include(project3) } + it { should_not include(project4) } + end + + context 'authenticated, group member' do + before { group.add_user(user, Gitlab::Access::DEVELOPER) } + + subject { Projects::CollectService.new.execute(user, group: group) } + + it { should include(project1) } + it { should include(project2) } + it { should include(project3) } + it { should include(project4) } + end +end -- libgit2 0.21.2