You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							104 lines
						
					
					
						
							2.4 KiB
						
					
					
				
			
		
		
	
	
							104 lines
						
					
					
						
							2.4 KiB
						
					
					
				| #coding=utf-8
 | |
| #
 | |
| require 'rack/auth/basic'
 | |
| require 'rack/auth/abstract/handler'
 | |
| require 'rack/auth/abstract/request'
 | |
| 
 | |
| module Grack
 | |
| 
 | |
|   class Auth < Rack::Auth::Basic
 | |
|     DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
 | |
|     PUSH_COMMANDS = %w{ git-receive-pack }
 | |
| 
 | |
|     attr_accessor :user, :repository
 | |
|     def call(env)
 | |
|       @env = env
 | |
|       @request = Rack::Request.new(env)
 | |
|       @auth = Request.new(env)
 | |
| 
 | |
|       if not @auth.provided?
 | |
|         unauthorized
 | |
|       elsif not @auth.basic?
 | |
|         bad_request
 | |
|       else
 | |
|         result = if (access = valid?(@auth) and access == true)
 | |
|           @env['REMOTE_USER'] = @auth.username
 | |
|           env['REP_PATH'] = repository.root_url 
 | |
|           @app.call(env)
 | |
|         else
 | |
|           if access == '404'
 | |
|             render_not_found
 | |
|           elsif access == '403'
 | |
|             #render_no_access
 | |
|             unauthorized
 | |
|           else
 | |
|             unauthorized
 | |
|           end
 | |
|         end
 | |
|         result
 | |
|       end
 | |
|     end# method call
 | |
| 
 | |
| 
 | |
|     def render_not_found
 | |
|       [404, {"Content-Type" => "text/plain"}, ["Not Found"]]
 | |
|     end
 | |
| 
 | |
|     def valid?(auth)
 | |
|       self.repository = auth_rep
 | |
|       return "404" unless repository
 | |
|       username, password = auth.credentials
 | |
|       self.user = auth_user(username, password)
 | |
|       return '403' unless user
 | |
|       access = auth_request
 | |
|       puts "access #{access}"
 | |
|       access
 | |
|     end
 | |
| 
 | |
|     def auth_rep
 | |
|       rep = nil
 | |
|       match = @request.path_info.match(/(\/.+\.git)\//)
 | |
|       if match
 | |
|         rep = Repository.where("root_url like ?", "%#{match[1]}").first
 | |
|       end
 | |
|       rep
 | |
|     end
 | |
| 
 | |
|     def auth_user(username, password)
 | |
|         u, last_login_on = User.try_to_login(username, password)
 | |
|         unless u && (u.member_of?(repository.project) || u.admin?)
 | |
|           u = nil
 | |
|         end
 | |
|         u
 | |
|     end
 | |
| 
 | |
|     def auth_request
 | |
|       case git_cmd
 | |
|       when *DOWNLOAD_COMMANDS
 | |
|         user != nil
 | |
|       when *PUSH_COMMANDS
 | |
|         unless user
 | |
|           false
 | |
|         else
 | |
|           ### 只有Manager和Development才有push权限
 | |
|           repository.project.members.where(user_id: user.id).first.roles.any?{|r| r.name == 'Manager' || r.name == 'Developer'}
 | |
|         end
 | |
|       else
 | |
|         false
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     def git_cmd
 | |
|       if @request.get?
 | |
|         @request.params['service']
 | |
|       elsif @request.post?
 | |
|         File.basename(@request.path)
 | |
|       else
 | |
|         nil
 | |
|       end
 | |
|     end
 | |
| 
 | |
|   end# class Auth
 | |
| end# module Grack
 | |
| 
 |