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 ...@@ -4,15 +4,24 @@ class UsersController < ApplicationController
def show def show
@user = User.find_by_username!(params[:username]) @user = User.find_by_username!(params[:username])
@projects = Project.personal(@user).accessible_to(current_user)
unless current_user || @user.public_profile? unless current_user || @user.public_profile?
return authenticate_user! return authenticate_user!
end end
@groups = @user.groups.accessible_to(current_user) # Projects user can view
accessible_projects = @user.authorized_projects.accessible_to(current_user) authorized_projects_ids = ProjectsFinder.new.execute(current_user).pluck(:id)
@events = @user.recent_events.where(project_id: accessible_projects.pluck(:id)).limit(20)
@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 @title = @user.name
end end
......
...@@ -49,7 +49,7 @@ class BaseFinder ...@@ -49,7 +49,7 @@ class BaseFinder
elsif current_user && params[:authorized_only].presence elsif current_user && params[:authorized_only].presence
klass.of_projects(current_user.authorized_projects).references(:project) klass.of_projects(current_user.authorized_projects).references(:project)
else else
klass.of_projects(Project.accessible_to(current_user)).references(:project) klass.of_projects(ProjectsFinder.new.execute(current_user)).references(:project)
end end
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 class ProjectsFinder
def execute(current_user, options) def execute(current_user, options = {})
group = options[:group] group = options[:group]
if group if group
...@@ -56,8 +56,36 @@ class ProjectsFinder ...@@ -56,8 +56,36 @@ class ProjectsFinder
end end
end end
def all_projects def all_projects(current_user)
# TODO: implement if current_user
raise 'Not implemented yet' 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
end end
...@@ -81,7 +81,7 @@ module SearchHelper ...@@ -81,7 +81,7 @@ module SearchHelper
# Autocomplete results for the current user's projects # Autocomplete results for the current user's projects
def projects_autocomplete(term, limit = 5) 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)}", label: "project: #{search_result_sanitize(p.name_with_namespace)}",
url: project_path(p) url: project_path(p)
......
File mode changed from 100755 to 100644
...@@ -51,7 +51,7 @@ class Ability ...@@ -51,7 +51,7 @@ class Ability
nil nil
end end
if group && group.has_projects_accessible_to?(nil) if group && group.public_profile?
[:read_group] [:read_group]
else else
[] []
......
...@@ -27,12 +27,6 @@ class Group < Namespace ...@@ -27,12 +27,6 @@ class Group < Namespace
mount_uploader :avatar, AttachmentUploader 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 def human_name
name name
end end
...@@ -77,4 +71,8 @@ class Group < Namespace ...@@ -77,4 +71,8 @@ class Group < Namespace
self.errors.add :avatar, "only images allowed" self.errors.add :avatar, "only images allowed"
end end
end end
def public_profile?
projects.public_only.any?
end
end end
...@@ -48,14 +48,6 @@ class Namespace < ActiveRecord::Base ...@@ -48,14 +48,6 @@ class Namespace < ActiveRecord::Base
'GLN' 'GLN'
end 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 def to_param
path path
end end
......
...@@ -164,12 +164,6 @@ class Project < ActiveRecord::Base ...@@ -164,12 +164,6 @@ class Project < ActiveRecord::Base
where(visibility_level: visibility_levels) where(visibility_level: visibility_levels)
end 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 def with_push
includes(:events).where('events.action = ?', Event::PUSHED) includes(:events).where('events.action = ?', Event::PUSHED)
end end
......
...@@ -12,7 +12,7 @@ module Search ...@@ -12,7 +12,7 @@ module Search
return result unless query.present? return result unless query.present?
group = Group.find_by(id: params[:group_id]) if params[:group_id].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 projects = projects.where(namespace_id: group.id) if group
project_ids = projects.pluck(:id) 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