2015-07-04 22:29:25 +08:00
|
|
|
#coding=utf-8
|
|
|
|
#
|
2015-07-01 22:54:07 +08:00
|
|
|
require 'rack/auth/basic'
|
|
|
|
require 'rack/auth/abstract/handler'
|
|
|
|
require 'rack/auth/abstract/request'
|
|
|
|
|
|
|
|
module Grack
|
2015-07-04 22:29:25 +08:00
|
|
|
|
2015-07-01 22:54:07 +08:00
|
|
|
class Auth < Rack::Auth::Basic
|
2015-07-04 22:29:25 +08:00
|
|
|
DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
|
|
|
|
PUSH_COMMANDS = %w{ git-receive-pack }
|
|
|
|
|
|
|
|
attr_accessor :user, :repository
|
2015-07-01 22:54:07 +08:00
|
|
|
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
|
2015-07-04 22:29:25 +08:00
|
|
|
env['REP_PATH'] = repository.root_url
|
2015-07-01 22:54:07 +08:00
|
|
|
@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)
|
2015-07-04 22:29:25 +08:00
|
|
|
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
|
2015-07-01 22:54:07 +08:00
|
|
|
match = @request.path_info.match(/(\/.+\.git)\//)
|
2015-07-04 22:29:25 +08:00
|
|
|
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
|
2015-07-01 22:54:07 +08:00
|
|
|
end
|
2015-07-04 22:29:25 +08:00
|
|
|
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
|
2015-07-01 22:54:07 +08:00
|
|
|
end
|
|
|
|
end
|
2015-07-04 22:29:25 +08:00
|
|
|
|
2015-07-01 22:54:07 +08:00
|
|
|
end# class Auth
|
|
|
|
end# module Grack
|
|
|
|
|