OSDN Git Service

Public HTTP clones and remove auth request for public projects
authorJeremy Slater <jeremy.slater@nuance.com>
Mon, 14 Jan 2013 14:46:55 +0000 (09:46 -0500)
committerJeremy Slater <jeremy.slater@nuance.com>
Mon, 14 Jan 2013 14:46:55 +0000 (09:46 -0500)
lib/gitlab/backend/grack_auth.rb

index 0defee2..c921ec0 100644 (file)
@@ -2,30 +2,42 @@ module Grack
   class Auth < Rack::Auth::Basic
     attr_accessor :user, :project
 
-    def valid?
-      # Find project by PATH_INFO from env
-      if m = /^\/([\w\.\/-]+)\.git/.match(@request.path_info).to_a
-        self.project = Project.find_with_namespace(m.last)
-        return false unless project
-      end
+    def call(env)
+      @env = env
+      @request = Rack::Request.new(env)
+      @auth = Request.new(env)
 
-      if @request.get? && project.public
-        return true
-      end
+      # Pass Gitolite update hook
+      ENV['GL_BYPASS_UPDATE_HOOK'] = "true"
 
-      # Authentication with username and password
-      login, password = @auth.credentials
+      # Need this patch due to the rails mount
+      @env['PATH_INFO'] = @request.path
+      @env['SCRIPT_NAME'] = ""
 
-      self.user = User.find_by_email(login) || User.find_by_username(login)
+      return render_not_found unless project
+      return unauthorized unless project.public || @auth.provided?
+      return bad_request if @auth.provided? && !@auth.basic?
 
-      return false unless user.try(:valid_password?, password)
+      if valid?
+        if @auth.provided?
+          @env['REMOTE_USER'] = @auth.username
+        end
+        return @app.call(env)
+      else
+        unauthorized
+      end
+    end
 
-      email = user.email
+    def valid?
+      if @auth.provided?
+        # Authentication with username and password
+        login, password = @auth.credentials
+        self.user = User.find_by_email(login) || User.find_by_username(login)
+        return false unless user.try(:valid_password?, password)
 
-      # Set GL_USER env variable
-      ENV['GL_USER'] = email
-      # Pass Gitolite update hook
-      ENV['GL_BYPASS_UPDATE_HOOK'] = "true"
+        # Set GL_USER env variable
+        ENV['GL_USER'] = user.email
+      end
 
       # Git upload and receive
       if @request.get?
@@ -38,12 +50,12 @@ module Grack
     end
 
     def validate_get_request
-      can?(user, :download_code, project)
+      project.public || can?(user, :download_code, project)
     end
 
     def validate_post_request
       if @request.path_info.end_with?('git-upload-pack')
-        can?(user, :download_code, project)
+        project.public || can?(user, :download_code, project)
       elsif @request.path_info.end_with?('git-receive-pack')
         action = if project.protected_branch?(current_ref)
                    :push_code_to_protected_branches
@@ -72,6 +84,22 @@ module Grack
       /refs\/heads\/([\w\.-]+)/.match(input).to_a.first
     end
 
+    def project
+      unless instance_variable_defined? :@project
+        # Find project by PATH_INFO from env
+        if m = /^\/([\w\.\/-]+)\.git/.match(@request.path_info).to_a
+          @project = Project.find_with_namespace(m.last)
+        end
+      end
+      return @project
+    end
+
+    PLAIN_TYPE = {"Content-Type" => "text/plain"}
+
+    def render_not_found
+      [404, PLAIN_TYPE, ["Not Found"]]
+    end
+
     protected
 
     def abilities