diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index c17c6f9694ae13a9357924919cd2036c946b87c2..0b442f5383a2ed8f9f0b4d48841d08cee15be404 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -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
 
diff --git a/app/finders/base_finder.rb b/app/finders/base_finder.rb
index 7fc5840561cb7748e71bfbef1dee83ba202fed83..7150bb2e31b1ee24640bcfdbc84d238c8c6c0da1 100644
--- a/app/finders/base_finder.rb
+++ b/app/finders/base_finder.rb
@@ -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
 
diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d3597ef090192ee01f5380c84344df1303ed7b79
--- /dev/null
+++ b/app/finders/groups_finder.rb
@@ -0,0 +1,38 @@
+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
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index bfaba7587884bb6aea7b979fa1641edd4e8e9f2e..26898bad493283c69308770ac095a60534cb41fa 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -1,5 +1,5 @@
 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
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 01c31205695ed5f2dcbb25c5dd26068ec52797dc..a4471507da888fadfc1f4a144941914789279699 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -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)
diff --git a/app/helpers/submodule_helper.rb b/app/helpers/submodule_helper.rb
old mode 100755
new mode 100644
diff --git a/app/models/ability.rb b/app/models/ability.rb
index df9b210dfca1e9eb2d7665de7176571e2ab2a5fd..c60aa2d622e841e912a1544f117fb49e5b61fad0 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -51,7 +51,7 @@ class Ability
                   nil
                 end
 
-        if group && group.has_projects_accessible_to?(nil)
+        if group && group.public_profile?
           [:read_group]
         else
           []
diff --git a/app/models/group.rb b/app/models/group.rb
index 2e68779d3674e95f6b11e144061d71fd5ea498a1..e51e19ab60ca3a24b0b1c515fd1101466a54e409 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -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
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 7973eef7e1cdcb35656ef199d077a68e720ea687..446e5f04c63188db00d55bbca1ab04eb3048f7c4 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -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
diff --git a/app/models/project.rb b/app/models/project.rb
index 758ef14703c1631842cfce3e626dcc472e504f6b..f92cc40642ae73c3c2f79c1d158895ab87f5bad8 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -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
diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb
index 8a1fce17ce7b4cc175100f63dd595721ed0ccf37..21214511182c7ca159834aed01d47c0ba71b8f2c 100644
--- a/app/services/search/global_service.rb
+++ b/app/services/search/global_service.rb
@@ -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)