Commit a105101c authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'improve-projects-collecting' into 'master'

Improve projects collecting

Refactor code that cause unexpected AR behaviour.

For example this works fine:

    @projects = Project.personal(@user).accessible_to(current_user)
    @groups = @user.groups.accessible_to(current_user) # OK

But

    @projects = Project.all
    @groups = @user.groups.accessible_to(current_user) # PG:Error
parents 70a6af93 0fdce4a5
......@@ -4,15 +4,24 @@ class UsersController < ApplicationController
def show
@user = User.find_by_username!(params[:username])
@projects = Project.personal(@user).accessible_to(current_user)
unless current_user || @user.public_profile?
return authenticate_user!
end
@groups = @user.groups.accessible_to(current_user)
accessible_projects = @user.authorized_projects.accessible_to(current_user)
@events = @user.recent_events.where(project_id: accessible_projects.pluck(:id)).limit(20)
# Projects user can view
authorized_projects_ids = ProjectsFinder.new.execute(current_user).pluck(:id)
@projects = @user.personal_projects.
where(id: authorized_projects_ids)
# Collect only groups common for both users
@groups = @user.groups & GroupsFinder.new.execute(current_user)
# Get user activity feed for projects common for both users
@events = @user.recent_events.
where(project_id: authorized_projects_ids).limit(20)
@title = @user.name
end
......
......@@ -49,7 +49,7 @@ class BaseFinder
elsif current_user && params[:authorized_only].presence
klass.of_projects(current_user.authorized_projects).references(:project)
else
klass.of_projects(Project.accessible_to(current_user)).references(:project)
klass.of_projects(ProjectsFinder.new.execute(current_user)).references(:project)
end
end
......
class GroupsFinder
def execute(current_user, options = {})
all_groups(current_user)
end
private
def all_groups(current_user)
if current_user
if current_user.authorized_groups.any?
# User has access to groups
#
# Return only:
# groups with public projects
# groups with internal projects
# groups with joined projects
#
group_ids = Project.public_and_internal_only.pluck(:namespace_id) +
current_user.authorized_groups.pluck(:id)
Group.where(id: group_ids)
else
# User has no group membership
#
# Return only:
# groups with public projects
# groups with internal projects
#
Group.where(id: Project.public_and_internal_only.pluck(:namespace_id))
end
else
# Not authenticated
#
# Return only:
# groups with public projects
Group.where(id: Project.public_only.pluck(:namespace_id))
end
end
end
class ProjectsFinder
def execute(current_user, options)
def execute(current_user, options = {})
group = options[:group]
if group
......@@ -56,8 +56,36 @@ class ProjectsFinder
end
end
def all_projects
# TODO: implement
raise 'Not implemented yet'
def all_projects(current_user)
if current_user
if current_user.authorized_projects.any?
# User has access to private projects
#
# Return only:
# public projects
# internal projects
# joined projects
#
Project.where(
"projects.id IN (?) OR projects.visibility_level IN (?)",
current_user.authorized_projects.pluck(:id),
Project.public_and_internal_levels
)
else
# User has no access to private projects
#
# Return only:
# public projects
# internal projects
#
Project.public_and_internal_only
end
else
# Not authenticated
#
# Return only:
# public projects
Project.public_only
end
end
end
......@@ -81,7 +81,7 @@ module SearchHelper
# Autocomplete results for the current user's projects
def projects_autocomplete(term, limit = 5)
Project.accessible_to(current_user).search_by_title(term).non_archived.limit(limit).map do |p|
ProjectsFinder.new.execute(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)
......
File mode changed from 100755 to 100644
......@@ -51,7 +51,7 @@ class Ability
nil
end
if group && group.has_projects_accessible_to?(nil)
if group && group.public_profile?
[:read_group]
else
[]
......
......@@ -27,12 +27,6 @@ class Group < Namespace
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
end
......@@ -77,4 +71,8 @@ class Group < Namespace
self.errors.add :avatar, "only images allowed"
end
end
def public_profile?
projects.public_only.any?
end
end
......@@ -47,14 +47,6 @@ 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
......
......@@ -164,12 +164,6 @@ class Project < ActiveRecord::Base
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)
end
......
......@@ -12,7 +12,7 @@ module Search
return result unless query.present?
group = Group.find_by(id: params[:group_id]) if params[:group_id].present?
projects = Project.accessible_to(current_user)
projects = ProjectsFinder.new.execute(current_user)
projects = projects.where(namespace_id: group.id) if group
project_ids = projects.pluck(:id)
......
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