From 66998f6d46ee778e6bde749e41f1d712b184a771 Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Tue, 24 Sep 2013 15:58:39 +0300
Subject: [PATCH] Allow non authenticated user access to public projects

---
 app/assets/stylesheets/common.scss            |  5 +++
 .../projects/application_controller.rb        | 23 +++++++++++++-
 app/controllers/projects_controller.rb        |  9 ++++--
 app/helpers/application_helper.rb             |  2 ++
 app/models/ability.rb                         | 31 ++++++++++++-------
 app/views/layouts/public.html.haml            | 23 ++++++++++----
 app/views/projects/_clone_panel.html.haml     |  2 +-
 app/views/projects/commits/_head.html.haml    |  2 +-
 app/views/projects/issues/_head.html.haml     |  7 +++--
 9 files changed, 79 insertions(+), 25 deletions(-)

diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index 6d80b22b3aa..1572227ec3a 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -382,3 +382,8 @@ table {
   width: 50px;
   min-height: 100px;
 }
+
+.navbar-gitlab .navbar-inner .nav > li .btn-sign-in {
+  @extend .btn-new;
+  padding: 5px 15px;
+}
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index 1f2a75175cf..d525bd4a700 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -1,5 +1,26 @@
 class Projects::ApplicationController < ApplicationController
   before_filter :project
   before_filter :repository
-  layout 'projects'
+  layout :determine_layout
+
+  def authenticate_user!
+    # Restrict access to Projects area only
+    # for non-signed users
+    if !current_user
+      id = params[:project_id] || params[:id]
+      @project = Project.find_with_namespace(id)
+
+      return if @project && @project.public
+    end
+
+    super
+  end
+
+  def determine_layout
+    if current_user
+      'projects'
+    else
+      'public'
+    end
+  end
 end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 23b54ec44a8..9ba2a758b8a 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -1,4 +1,5 @@
 class ProjectsController < Projects::ApplicationController
+  skip_before_filter :authenticate_user!, only: [:show]
   skip_before_filter :project, only: [:new, :create]
   skip_before_filter :repository, only: [:new, :create]
 
@@ -54,6 +55,8 @@ class ProjectsController < Projects::ApplicationController
   end
 
   def show
+    return authenticate_user! unless @project.public
+
     limit = (params[:limit] || 20).to_i
 
     @events = @project.events.recent
@@ -69,8 +72,10 @@ class ProjectsController < Projects::ApplicationController
         if @project.empty_repo?
           render "projects/empty"
         else
-          @last_push = current_user.recent_push(@project.id)
-          render :show
+          if current_user
+            @last_push = current_user.recent_push(@project.id)
+          end
+          render :show, layout: current_user ? "project" : "public"
         end
       end
       format.js
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 4209b081bfa..7e5c10fee05 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -90,6 +90,8 @@ module ApplicationHelper
   end
 
   def search_autocomplete_source
+    return unless current_user
+
     projects = current_user.authorized_projects.map { |p| { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } }
     groups = current_user.authorized_groups.map { |group| { label: "group: #{simple_sanitize(group.name)}", url: group_path(group) } }
 
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 8335829f919..7f044b220a5 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -1,6 +1,7 @@
 class Ability
   class << self
     def allowed(user, subject)
+      return not_auth_abilities(user, subject) if user.nil?
       return [] unless user.kind_of?(User)
       return [] if user.blocked?
 
@@ -17,6 +18,24 @@ class Ability
       end.concat(global_abilities(user))
     end
 
+    # List of possible abilities
+    # for non-authenticated user
+    def not_auth_abilities(user, subject)
+      project = if subject.kind_of?(Project)
+                  subject
+                elsif subject.respond_to?(:project)
+                  subject.project
+                else
+                  nil
+                end
+
+      if project && project.public
+        public_project_rules
+      else
+        []
+      end
+    end
+
     def global_abilities(user)
       rules = []
       rules << :create_group if user.can_create_group
@@ -58,19 +77,9 @@ class Ability
     end
 
     def public_project_rules
-      [
+      project_guest_rules + [
         :download_code,
         :fork_project,
-        :read_project,
-        :read_wiki,
-        :read_issue,
-        :read_milestone,
-        :read_project_snippet,
-        :read_team_member,
-        :read_merge_request,
-        :read_note,
-        :write_issue,
-        :write_note
       ]
     end
 
diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml
index 7dce0cbeae2..c1fe5fcae7e 100644
--- a/app/views/layouts/public.html.haml
+++ b/app/views/layouts/public.html.haml
@@ -1,7 +1,7 @@
 !!! 5
 %html{ lang: "en"}
   = render "layouts/head", title: "Public Projects"
-  %body{class: "#{app_theme} application", :'data-page' => body_data_page}
+  %body{class: "ui_mars application", :'data-page' => body_data_page}
     - if current_user
       = render "layouts/head_panel", title: "Public Projects"
     - else
@@ -13,7 +13,12 @@
               = link_to public_root_path, class: "home" do
                 %h1 GITLAB
               %span.separator
-            %h1.project_name Public Projects
+            %h1.project_name
+              - if @project
+                = project_title(@project)
+              - else
+                Public Projects
+
             %ul.nav
               %li
                 %a
@@ -21,8 +26,14 @@
                     %i.icon-refresh.icon-spin
                     Loading...
               %li
-                = link_to "Sign in", new_session_path(:user)
+                = link_to "Sign in", new_session_path(:user), class: 'btn btn-sign-in'
+
+    - if @project
+      %nav.main-nav
+        .container= render 'layouts/nav/project'
 
-    .container.navless-container
-      .content
-        = yield
+      .container
+        .content= yield
+    - else
+      .container.navless-container
+        .content= yield
diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml
index 7228c760d27..c5ab64505c6 100644
--- a/app/views/projects/_clone_panel.html.haml
+++ b/app/views/projects/_clone_panel.html.haml
@@ -5,7 +5,7 @@
     .span3.pull-right
       .pull-right
         - unless @project.empty_repo?
-          - if can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace
+          - if current_user && can?(current_user, :fork_project, @project) && @project.namespace != current_user.namespace
             - if current_user.already_forked?(@project)
               = link_to project_path(current_user.fork_of(@project)), class: 'btn grouped disabled' do
                 %i.icon-code-fork
diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml
index 624604142b1..c2da9f273b3 100644
--- a/app/views/projects/commits/_head.html.haml
+++ b/app/views/projects/commits/_head.html.haml
@@ -21,7 +21,7 @@
       Stats
 
 
-  - if current_controller?(:commits) && current_user.private_token
+  - if current_user && current_controller?(:commits) && current_user.private_token
     %li.pull-right
       = link_to project_commits_path(@project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Feed" do
         %i.icon-rss
diff --git a/app/views/projects/issues/_head.html.haml b/app/views/projects/issues/_head.html.haml
index 44d14d5cdf9..438cc02b477 100644
--- a/app/views/projects/issues/_head.html.haml
+++ b/app/views/projects/issues/_head.html.haml
@@ -5,6 +5,7 @@
     = link_to 'Milestones', project_milestones_path(@project), class: "tab"
   = nav_link(controller: :labels) do
     = link_to 'Labels', project_labels_path(@project), class: "tab"
-  %li.pull-right
-    = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
-      %i.icon-rss
+  - if current_user
+    %li.pull-right
+      = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
+        %i.icon-rss
-- 
GitLab