Commit 612a909eac58b8ebb6a2d9f68bbe2b8998411b89

Authored by Dmitriy Zaporozhets
2 parents 189f88de 41e98174

Merge branch 'git-refactoring' into 'master'

Git Refactoring
Procfile
1   -web: bundle exec unicorn_rails -p $PORT -E development
  1 +web: bundle exec unicorn_rails -p $PORT -E development -c config/unicorn_development.rb
2 2 worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default,gitlab_shell
... ...
config/unicorn_development.rb 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +worker_processes 2
  2 +timeout 30
... ...
lib/api/internal.rb
1 1 module API
2 2 # Internal access API
3 3 class Internal < Grape::API
4   -
5   - DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
6   - PUSH_COMMANDS = %w{ git-receive-pack }
7   -
8 4 namespace 'internal' do
9   - #
10   - # Check if ssh key has access to project code
  5 + # Check if git command is allowed to project
11 6 #
12 7 # Params:
13   - # key_id - SSH Key id
  8 + # key_id - ssh key id for Git over SSH
  9 + # user_id - user id for Git over HTTP
14 10 # project - project path with namespace
15 11 # action - git action (git-upload-pack or git-receive-pack)
16 12 # ref - branch name
... ... @@ -22,43 +18,25 @@ module API
22 18 # the wiki repository as well.
23 19 project_path = params[:project]
24 20 project_path.gsub!(/\.wiki/,'') if project_path =~ /\.wiki/
25   -
26   - key = Key.find(params[:key_id])
27 21 project = Project.find_with_namespace(project_path)
28   - git_cmd = params[:action]
29 22 return false unless project
30 23  
31   -
32   - if key.is_a? DeployKey
33   - key.projects.include?(project) && DOWNLOAD_COMMANDS.include?(git_cmd)
34   - else
35   - user = key.user
36   -
37   - return false if user.blocked?
38   -
39   - if Gitlab.config.ldap.enabled
40   - if user.ldap_user?
41   - # Check if LDAP user exists and match LDAP user_filter
42   - unless Gitlab::LDAP::Access.new.allowed?(user)
43   - return false
44   - end
45   - end
46   - end
47   -
48   - action = case git_cmd
49   - when *DOWNLOAD_COMMANDS
50   - then :download_code
51   - when *PUSH_COMMANDS
52   - then
53   - if project.protected_branch?(params[:ref])
54   - :push_code_to_protected_branches
55   - else
56   - :push_code
57   - end
58   - end
59   -
60   - user.can?(action, project)
61   - end
  24 + actor = if params[:key_id]
  25 + Key.find(params[:key_id])
  26 + elsif params[:user_id]
  27 + User.find(params[:user_id])
  28 + end
  29 +
  30 + return false unless actor
  31 +
  32 + Gitlab::GitAccess.new.allowed?(
  33 + actor,
  34 + params[:action],
  35 + project,
  36 + params[:ref],
  37 + params[:oldrev],
  38 + params[:newrev]
  39 + )
62 40 end
63 41  
64 42 #
... ...
lib/gitlab/backend/grack_auth.rb
... ... @@ -5,7 +5,7 @@ module Grack
5 5 class Auth < Rack::Auth::Basic
6 6 include Helpers
7 7  
8   - attr_accessor :user, :project, :ref, :env
  8 + attr_accessor :user, :project, :env
9 9  
10 10 def call(env)
11 11 @env = env
... ... @@ -80,24 +80,11 @@ module Grack
80 80 def authorize_request(service)
81 81 case service
82 82 when 'git-upload-pack'
83   - can?(user, :download_code, project)
84   - when'git-receive-pack'
85   - refs.each do |ref|
86   - action = if project.protected_branch?(ref)
87   - :push_code_to_protected_branches
88   - else
89   - :push_code
90   - end
91   -
92   - return false unless can?(user, action, project)
93   - end
94   -
95   - # Never let git-receive-pack trough unauthenticated; it's
96   - # harmless but git < 1.8 doesn't like it
97   - return false if user.nil?
98   - true
  83 + # Serve only upload request.
  84 + # Authorization on push will be serverd by update hook in repository
  85 + Gitlab::GitAccess.new.download_allowed?(user, project)
99 86 else
100   - false
  87 + true
101 88 end
102 89 end
103 90  
... ... @@ -114,29 +101,5 @@ module Grack
114 101 def project
115 102 @project ||= project_by_path(@request.path_info)
116 103 end
117   -
118   - def refs
119   - @refs ||= parse_refs
120   - end
121   -
122   - def parse_refs
123   - input = if @env["HTTP_CONTENT_ENCODING"] =~ /gzip/
124   - Zlib::GzipReader.new(@request.body).read
125   - else
126   - @request.body.read
127   - end
128   -
129   - # Need to reset seek point
130   - @request.body.rewind
131   -
132   - # Parse refs
133   - refs = input.force_encoding('ascii-8bit').scan(/refs\/heads\/([\/\w\.-]+)/n).flatten.compact
134   -
135   - # Cleanup grabare from refs
136   - # if push to multiple branches
137   - refs.map do |ref|
138   - ref.gsub(/00.*/, "")
139   - end
140   - end
141 104 end
142 105 end
... ...
lib/gitlab/git_access.rb 0 → 100644
... ... @@ -0,0 +1,74 @@
  1 +module Gitlab
  2 + class GitAccess
  3 + DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
  4 + PUSH_COMMANDS = %w{ git-receive-pack }
  5 +
  6 + attr_reader :params, :project, :git_cmd, :user
  7 +
  8 + def allowed?(actor, cmd, project, ref = nil, oldrev = nil, newrev = nil)
  9 + case cmd
  10 + when *DOWNLOAD_COMMANDS
  11 + if actor.is_a? User
  12 + download_allowed?(actor, project)
  13 + elsif actor.is_a? DeployKey
  14 + actor.projects.include?(project)
  15 + elsif actor.is_a? Key
  16 + download_allowed?(actor.user, project)
  17 + else
  18 + raise 'Wrong actor'
  19 + end
  20 + when *PUSH_COMMANDS
  21 + if actor.is_a? User
  22 + push_allowed?(actor, project, ref, oldrev, newrev)
  23 + elsif actor.is_a? DeployKey
  24 + # Deploy key not allowed to push
  25 + return false
  26 + elsif actor.is_a? Key
  27 + push_allowed?(actor.user, project, ref, oldrev, newrev)
  28 + else
  29 + raise 'Wrong actor'
  30 + end
  31 + else
  32 + false
  33 + end
  34 + end
  35 +
  36 + def download_allowed?(user, project)
  37 + if user_allowed?(user)
  38 + user.can?(:download_code, project)
  39 + else
  40 + false
  41 + end
  42 + end
  43 +
  44 + def push_allowed?(user, project, ref, oldrev, newrev)
  45 + if user_allowed?(user)
  46 + action = if project.protected_branch?(ref)
  47 + :push_code_to_protected_branches
  48 + else
  49 + :push_code
  50 + end
  51 + user.can?(action, project)
  52 + else
  53 + false
  54 + end
  55 + end
  56 +
  57 + private
  58 +
  59 + def user_allowed?(user)
  60 + return false if user.blocked?
  61 +
  62 + if Gitlab.config.ldap.enabled
  63 + if user.ldap_user?
  64 + # Check if LDAP user exists and match LDAP user_filter
  65 + unless Gitlab::LDAP::Access.new.allowed?(user)
  66 + return false
  67 + end
  68 + end
  69 + end
  70 +
  71 + true
  72 + end
  73 + end
  74 +end
... ...