mercurial/hgweb/hgweb_mod.py
changeset 6926 57b954d8d003
parent 6914 95f35b553ae6
child 6945 2cfdabe235fb
equal deleted inserted replaced
6925:87abfefafe02 6926:57b954d8d003
    11 from mercurial.repo import RepoError
    11 from mercurial.repo import RepoError
    12 from mercurial import mdiff, ui, hg, util, patch, hook
    12 from mercurial import mdiff, ui, hg, util, patch, hook
    13 from mercurial import revlog, templater, templatefilters
    13 from mercurial import revlog, templater, templatefilters
    14 from common import get_mtime, style_map, paritygen, countgen, ErrorResponse
    14 from common import get_mtime, style_map, paritygen, countgen, ErrorResponse
    15 from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
    15 from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
       
    16 from common import HTTP_UNAUTHORIZED, HTTP_METHOD_NOT_ALLOWED
    16 from request import wsgirequest
    17 from request import wsgirequest
    17 import webcommands, protocol, webutil
    18 import webcommands, protocol, webutil
    18 
    19 
    19 perms = {
    20 perms = {
    20     'changegroup': 'pull',
    21     'changegroup': 'pull',
    86         # protocol bits don't need to create any URLs
    87         # protocol bits don't need to create any URLs
    87         # and the clients always use the old URL structure
    88         # and the clients always use the old URL structure
    88 
    89 
    89         cmd = req.form.get('cmd', [''])[0]
    90         cmd = req.form.get('cmd', [''])[0]
    90         if cmd and cmd in protocol.__all__:
    91         if cmd and cmd in protocol.__all__:
    91             if cmd in perms and not self.check_perm(req, perms[cmd]):
    92             try:
    92                 return []
    93                 if cmd in perms:
    93             method = getattr(protocol, cmd)
    94                     self.check_perm(req, perms[cmd])
    94             return method(self.repo, req)
    95                 method = getattr(protocol, cmd)
       
    96                 return method(self.repo, req)
       
    97             except ErrorResponse, inst:
       
    98                 req.respond(inst.code, protocol.HGTYPE)
       
    99                 if not inst.message:
       
   100                     return []
       
   101                 return '0\n%s\n' % inst.message,
    95 
   102 
    96         # work with CGI variables to create coherent structure
   103         # work with CGI variables to create coherent structure
    97         # use SCRIPT_NAME, PATH_INFO and QUERY_STRING as well as our REPO_NAME
   104         # use SCRIPT_NAME, PATH_INFO and QUERY_STRING as well as our REPO_NAME
    98 
   105 
    99         req.url = req.env['SCRIPT_NAME']
   106         req.url = req.env['SCRIPT_NAME']
   342 
   349 
   343     def check_perm(self, req, op):
   350     def check_perm(self, req, op):
   344         '''Check permission for operation based on request data (including
   351         '''Check permission for operation based on request data (including
   345         authentication info. Return true if op allowed, else false.'''
   352         authentication info. Return true if op allowed, else false.'''
   346 
   353 
   347         def error(status, message):
   354         if op == 'pull' and not self.allowpull:
   348             req.respond(status, protocol.HGTYPE)
   355             raise ErrorResponse(HTTP_OK, '')
   349             req.write('0\n%s\n' % message)
   356         elif op == 'pull':
   350 
   357             return
   351         if op == 'pull':
       
   352             return self.allowpull
       
   353 
   358 
   354         # enforce that you can only push using POST requests
   359         # enforce that you can only push using POST requests
   355         if req.env['REQUEST_METHOD'] != 'POST':
   360         if req.env['REQUEST_METHOD'] != 'POST':
   356             error('405 Method Not Allowed', 'push requires POST request')
   361             msg = 'push requires POST request'
   357             return False
   362             raise ErrorResponse(HTTP_METHOD_NOT_ALLOWED, msg)
   358 
   363 
   359         # require ssl by default for pushing, auth info cannot be sniffed
   364         # require ssl by default for pushing, auth info cannot be sniffed
   360         # and replayed
   365         # and replayed
   361         scheme = req.env.get('wsgi.url_scheme')
   366         scheme = req.env.get('wsgi.url_scheme')
   362         if self.configbool('web', 'push_ssl', True) and scheme != 'https':
   367         if self.configbool('web', 'push_ssl', True) and scheme != 'https':
   363             error(HTTP_OK, 'ssl required')
   368             raise ErrorResponse(HTTP_OK, 'ssl required')
   364             return False
       
   365 
   369 
   366         user = req.env.get('REMOTE_USER')
   370         user = req.env.get('REMOTE_USER')
   367 
   371 
   368         deny = self.configlist('web', 'deny_push')
   372         deny = self.configlist('web', 'deny_push')
   369         if deny and (not user or deny == ['*'] or user in deny):
   373         if deny and (not user or deny == ['*'] or user in deny):
   370             error('401 Unauthorized', 'push not authorized')
   374             raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized')
   371             return False
       
   372 
   375 
   373         allow = self.configlist('web', 'allow_push')
   376         allow = self.configlist('web', 'allow_push')
   374         result = allow and (allow == ['*'] or user in allow)
   377         result = allow and (allow == ['*'] or user in allow)
   375         if not result:
   378         if not result:
   376             error('401 Unauthorized', 'push not authorized')
   379             raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized')
   377 
       
   378         return result