diff -r 4c98440de851 -r 538d6b198f4a access.py --- a/access.py Mon Apr 21 12:37:56 2008 +0100 +++ b/access.py Tue Apr 22 09:46:29 2008 +0100 @@ -1,6 +1,10 @@ -# Copyright 2008 Paul Crowley +# Copyright 2008 LShift Ltd # Copyright 2006 Vadim Gelfer # +# Authors: +# Paul Crowley +# Vadim Gelfer +# # This software may be used and distributed according to the terms # of the GNU General Public License, incorporated herein by reference. @@ -9,84 +13,23 @@ from mercurial import util import os -import re - -allowedchars = "A-Za-z0-9_-" -goodglobre = re.compile("[*/%s]+$" % allowedchars) - -# Don't put anything except *A-Za-z0-9_- in rule globs or -# it will match nothing. No regexp metachars, not even . -# We may fix this later. -def globmatcher(pattern): - if not goodglobre.match(pattern): - #fail("Bad glob pattern in auth config: %s" % pattern) - # FIXME: report it somehow - return lambda x: False - pattern = pattern.replace("*", "[]") - pattern = pattern.replace("[][]", "[/%s]*" % allowedchars) - pattern = pattern.replace("[]", "[%s]*" % allowedchars) - rex = re.compile(pattern + "$") - return lambda x: rex.match(x) is not None - -def rule(pairs): - matchers = [(k, globmatcher(v)) for k, v in pairs] - def c(**kw): - for k, m in matchers: - if k not in kw or not m(kw[k]): - return False - return True - return c - -class Rulefile(object): - '''Class representing the rules in a rule file''' - - self.levels = ["init", "write", "read", "deny"] - - def __init__(self): - self.rules = [] - - def add(self, action, conditions): - self.rules.append((action, conditions)) - - def matchrule(self, **kw): - for a, c in self.rules: - if c(**kw): - return a - return None - - def allow(self, level, **kw): - a = matchrule(self, **kw) - return a in self.levels and self.levels.index(a) <= self.levels.index(level) - -def read_rules(fn): - res = Rulefile() - f = open(fn) - try: - for l in f: - l = l.strip() - if len(l) == 0 or l.startswith["#"]: - continue - res.add(l[0], rule([c.split("=", 1) for c in l[1:]])) - finally: - f.close() +import rules class Checker(object): '''acl checker.''' - def getuser(self): - '''return name of hg-ssh user''' - return os.environ['REMOTE_USER'] - def __init__(self, ui, repo): self.ui = ui self.repo = repo - self.rules = read_rules(os.environ['HG_ACCESS_RULES_FILE']) + self.repo_path = os.environ['HG_REPO_PATH'] + self.user = os.environ['REMOTE_USER'] + self.rules = rules.Ruleset.readfile(os.environ['HG_ACCESS_RULES_FILE']) def check(self, node): '''return if access allowed, raise exception if not.''' files = self.repo.changectx(node).files() for f in files: - if not self.rules.allow("write", user=self.user, ): + if not self.rules.allow("write", user=self.user, repo=self.repo_path, file=f): self.ui.debug(_('%s: user %s not allowed on %s\n') % (__name__, self.getuser(), f)) raise util.Abort(_('%s: access denied for changeset %s') % @@ -97,9 +40,7 @@ if hooktype != 'pretxnchangegroup': raise util.Abort(_('config error - hook type "%s" cannot stop ' 'incoming changesets') % hooktype) - - c = checker(ui, repo) - + c = Checker(ui, repo) start = repo.changelog.rev(bin(node)) end = repo.changelog.count() for rev in xrange(start, end):