Commit 80b8921a9a0adb60c7eb8edeaf195d9dc2530cb9
1 parent
eff6d3c1
Exists in
master
and in
4 other branches
Public HTTP clones and remove auth request for public projects
Showing
1 changed file
with
48 additions
and
20 deletions
Show diff stats
lib/gitlab/backend/grack_auth.rb
| @@ -2,30 +2,42 @@ module Grack | @@ -2,30 +2,42 @@ module Grack | ||
| 2 | class Auth < Rack::Auth::Basic | 2 | class Auth < Rack::Auth::Basic |
| 3 | attr_accessor :user, :project | 3 | attr_accessor :user, :project |
| 4 | 4 | ||
| 5 | - def valid? | ||
| 6 | - # Find project by PATH_INFO from env | ||
| 7 | - if m = /^\/([\w\.\/-]+)\.git/.match(@request.path_info).to_a | ||
| 8 | - self.project = Project.find_with_namespace(m.last) | ||
| 9 | - return false unless project | ||
| 10 | - end | 5 | + def call(env) |
| 6 | + @env = env | ||
| 7 | + @request = Rack::Request.new(env) | ||
| 8 | + @auth = Request.new(env) | ||
| 11 | 9 | ||
| 12 | - if @request.get? && project.public | ||
| 13 | - return true | ||
| 14 | - end | 10 | + # Pass Gitolite update hook |
| 11 | + ENV['GL_BYPASS_UPDATE_HOOK'] = "true" | ||
| 15 | 12 | ||
| 16 | - # Authentication with username and password | ||
| 17 | - login, password = @auth.credentials | 13 | + # Need this patch due to the rails mount |
| 14 | + @env['PATH_INFO'] = @request.path | ||
| 15 | + @env['SCRIPT_NAME'] = "" | ||
| 18 | 16 | ||
| 19 | - self.user = User.find_by_email(login) || User.find_by_username(login) | 17 | + return render_not_found unless project |
| 18 | + return unauthorized unless project.public || @auth.provided? | ||
| 19 | + return bad_request if @auth.provided? && !@auth.basic? | ||
| 20 | 20 | ||
| 21 | - return false unless user.try(:valid_password?, password) | 21 | + if valid? |
| 22 | + if @auth.provided? | ||
| 23 | + @env['REMOTE_USER'] = @auth.username | ||
| 24 | + end | ||
| 25 | + return @app.call(env) | ||
| 26 | + else | ||
| 27 | + unauthorized | ||
| 28 | + end | ||
| 29 | + end | ||
| 22 | 30 | ||
| 23 | - email = user.email | 31 | + def valid? |
| 32 | + if @auth.provided? | ||
| 33 | + # Authentication with username and password | ||
| 34 | + login, password = @auth.credentials | ||
| 35 | + self.user = User.find_by_email(login) || User.find_by_username(login) | ||
| 36 | + return false unless user.try(:valid_password?, password) | ||
| 24 | 37 | ||
| 25 | - # Set GL_USER env variable | ||
| 26 | - ENV['GL_USER'] = email | ||
| 27 | - # Pass Gitolite update hook | ||
| 28 | - ENV['GL_BYPASS_UPDATE_HOOK'] = "true" | 38 | + # Set GL_USER env variable |
| 39 | + ENV['GL_USER'] = user.email | ||
| 40 | + end | ||
| 29 | 41 | ||
| 30 | # Git upload and receive | 42 | # Git upload and receive |
| 31 | if @request.get? | 43 | if @request.get? |
| @@ -38,12 +50,12 @@ module Grack | @@ -38,12 +50,12 @@ module Grack | ||
| 38 | end | 50 | end |
| 39 | 51 | ||
| 40 | def validate_get_request | 52 | def validate_get_request |
| 41 | - can?(user, :download_code, project) | 53 | + project.public || can?(user, :download_code, project) |
| 42 | end | 54 | end |
| 43 | 55 | ||
| 44 | def validate_post_request | 56 | def validate_post_request |
| 45 | if @request.path_info.end_with?('git-upload-pack') | 57 | if @request.path_info.end_with?('git-upload-pack') |
| 46 | - can?(user, :download_code, project) | 58 | + project.public || can?(user, :download_code, project) |
| 47 | elsif @request.path_info.end_with?('git-receive-pack') | 59 | elsif @request.path_info.end_with?('git-receive-pack') |
| 48 | action = if project.protected_branch?(current_ref) | 60 | action = if project.protected_branch?(current_ref) |
| 49 | :push_code_to_protected_branches | 61 | :push_code_to_protected_branches |
| @@ -72,6 +84,22 @@ module Grack | @@ -72,6 +84,22 @@ module Grack | ||
| 72 | /refs\/heads\/([\w\.-]+)/.match(input).to_a.first | 84 | /refs\/heads\/([\w\.-]+)/.match(input).to_a.first |
| 73 | end | 85 | end |
| 74 | 86 | ||
| 87 | + def project | ||
| 88 | + unless instance_variable_defined? :@project | ||
| 89 | + # Find project by PATH_INFO from env | ||
| 90 | + if m = /^\/([\w\.\/-]+)\.git/.match(@request.path_info).to_a | ||
| 91 | + @project = Project.find_with_namespace(m.last) | ||
| 92 | + end | ||
| 93 | + end | ||
| 94 | + return @project | ||
| 95 | + end | ||
| 96 | + | ||
| 97 | + PLAIN_TYPE = {"Content-Type" => "text/plain"} | ||
| 98 | + | ||
| 99 | + def render_not_found | ||
| 100 | + [404, PLAIN_TYPE, ["Not Found"]] | ||
| 101 | + end | ||
| 102 | + | ||
| 75 | protected | 103 | protected |
| 76 | 104 | ||
| 77 | def abilities | 105 | def abilities |