Commit 75eed4eb authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Implement project collection service

Main purpose is move big amount of methods from user, group, project
models and place filtering logic in one place.
It also fixes 500 error on group page for PostgreSQL
Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
parent 9f20580e
......@@ -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
......
......@@ -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
......
......@@ -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
......
# 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
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
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