[PATCH 1 of 3] Moved hgweb.check_perm outside the class and added multiple permission checking
Martin Vejnar
avakar at ratatanek.cz
Mon Sep 28 04:18:31 CDT 2009
# HG changeset patch
# User Martin Vejnar <avakar at ratatanek.cz>
# Date 1254128490 -7200
# Node ID 81f5d7d7ed578d8029f3b1761b1c9716e9a97b2d
# Parent f3f400b13984d175f44943de2cc348c435c4119e
Moved hgweb.check_perm outside the class and added multiple permission checking.
hgweb_mod.check_perms accepts multiple operations to check permissions for.
The permissions are deduced from web.allow_<op> and web.deny_<op> config items,
the syntax is compatible with original web.allow_push and web.deny_push
(deny access if both lists are empty).
This is to be used by hgwebdir_mod to check permissions to create a new repository.
diff -r f3f400b13984 -r 81f5d7d7ed57 mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py Wed Sep 23 00:23:50 2009 -0500
+++ b/mercurial/hgweb/hgweb_mod.py Mon Sep 28 11:01:30 2009 +0200
@@ -21,6 +21,61 @@
'stream_out': 'pull',
}
+def check_perms(ui, req, ops):
+ '''Check for permission to perform operation based on request data (including
+ authentication info). Return if all of the ops are allowed, else raise an ErrorResponse
+ exception.'''
+
+ user = req.env.get('REMOTE_USER')
+
+ ui.debug('checking for permission to perform %s as %s\n' % (ops, user))
+
+ deny_read = ui.configlist('web', 'deny_read')
+ if deny_read and (not user or deny_read == ['*'] or user in deny_read):
+ raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized')
+
+ allow_read = ui.configlist('web', 'allow_read')
+ result = (not allow_read) or (allow_read == ['*'])
+ if not (result or user in allow_read):
+ raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized')
+
+ if 'pull' in ops and not ui.configbool("web", "allowpull", True):
+ raise ErrorResponse(HTTP_UNAUTHORIZED, 'pull not authorized')
+ elif 'pull' in ops:
+ ops.remove('pull')
+
+ if not ops:
+ return
+
+ # handle mutating operations,
+ # enforce that they are performed using POST requests
+ if req.env['REQUEST_METHOD'] != 'POST':
+ msg = '%s requires POST request' % ops[0]
+ raise ErrorResponse(HTTP_METHOD_NOT_ALLOWED, msg)
+
+ if 'push' in ops:
+ # require ssl by default for pushing, auth info cannot be sniffed
+ # and replayed
+ scheme = req.env.get('wsgi.url_scheme')
+ if ui.configbool('web', 'push_ssl', True) and scheme != 'https':
+ raise ErrorResponse(HTTP_OK, 'ssl required')
+
+ for op in ops:
+ deny = ui.configlist('web', 'deny_%s' % op)
+ if deny and (not user or deny == ['*'] or user in deny):
+ raise ErrorResponse(HTTP_UNAUTHORIZED, '%s not authorized' % op)
+
+ allow = ui.configlist('web', 'allow_%s' % op)
+ result = allow and (allow == ['*'] or user in allow)
+ if not result:
+ raise ErrorResponse(HTTP_UNAUTHORIZED, '%s not authorized' % op)
+
+def check_perm(ui, req, op):
+ if op is None:
+ check_perms(ui, req, [])
+ else:
+ check_perms(ui, req, [op])
+
class hgweb(object):
def __init__(self, repo, name=None):
if isinstance(repo, str):
@@ -112,7 +167,7 @@
try:
if cmd in perms:
try:
- self.check_perm(req, perms[cmd])
+ check_perm(self.repo.ui, req, perms[cmd])
except ErrorResponse, inst:
if cmd == 'unbundle':
req.drain()
@@ -168,7 +223,7 @@
# check read permissions non-static content
if cmd != 'static':
- self.check_perm(req, None)
+ check_perm(self.repo.ui, req, None)
if cmd == '':
req.form['cmd'] = [tmpl.cache['default']]
@@ -272,44 +327,3 @@
'gz': ('application/x-tar', 'tgz', '.tar.gz', None),
'zip': ('application/zip', 'zip', '.zip', None),
}
-
- def check_perm(self, req, op):
- '''Check permission for operation based on request data (including
- authentication info). Return if op allowed, else raise an ErrorResponse
- exception.'''
-
- user = req.env.get('REMOTE_USER')
-
- deny_read = self.configlist('web', 'deny_read')
- if deny_read and (not user or deny_read == ['*'] or user in deny_read):
- raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized')
-
- allow_read = self.configlist('web', 'allow_read')
- result = (not allow_read) or (allow_read == ['*'])
- if not (result or user in allow_read):
- raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized')
-
- if op == 'pull' and not self.allowpull:
- raise ErrorResponse(HTTP_UNAUTHORIZED, 'pull not authorized')
- elif op == 'pull' or op is None: # op is None for interface requests
- return
-
- # enforce that you can only push using POST requests
- if req.env['REQUEST_METHOD'] != 'POST':
- msg = 'push requires POST request'
- raise ErrorResponse(HTTP_METHOD_NOT_ALLOWED, msg)
-
- # require ssl by default for pushing, auth info cannot be sniffed
- # and replayed
- scheme = req.env.get('wsgi.url_scheme')
- if self.configbool('web', 'push_ssl', True) and scheme != 'https':
- raise ErrorResponse(HTTP_OK, 'ssl required')
-
- deny = self.configlist('web', 'deny_push')
- if deny and (not user or deny == ['*'] or user in deny):
- raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized')
-
- allow = self.configlist('web', 'allow_push')
- result = allow and (allow == ['*'] or user in allow)
- if not result:
- raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized')
More information about the Mercurial-devel
mailing list