access.py
author Paul Crowley <paul@ciphergoth.org>
Mon, 21 Apr 2008 12:37:56 +0100
changeset 17 4c98440de851
child 18 538d6b198f4a
permissions -rw-r--r--
Started work on acl.py replacement - currently broken.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
17
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
     1
# Copyright 2008 Paul Crowley <paul@lshift.net>
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
     2
# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
     3
#
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
     4
# This software may be used and distributed according to the terms
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
     5
# of the GNU General Public License, incorporated herein by reference.
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
     6
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
     7
from mercurial.i18n import _
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
     8
from mercurial.node import *
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
     9
from mercurial import util
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    10
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    11
import os
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    12
import re
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    13
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    14
allowedchars = "A-Za-z0-9_-"
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    15
goodglobre = re.compile("[*/%s]+$" % allowedchars)
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    16
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    17
# Don't put anything except *A-Za-z0-9_- in rule globs or   
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    18
# it will match nothing.  No regexp metachars, not even .
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    19
# We may fix this later.
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    20
def globmatcher(pattern):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    21
    if not goodglobre.match(pattern):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    22
        #fail("Bad glob pattern in auth config: %s" % pattern)
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    23
        # FIXME: report it somehow
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    24
        return lambda x: False
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    25
    pattern = pattern.replace("*", "[]")
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    26
    pattern = pattern.replace("[][]", "[/%s]*" % allowedchars)
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    27
    pattern = pattern.replace("[]", "[%s]*" % allowedchars)
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    28
    rex = re.compile(pattern + "$")
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    29
    return lambda x: rex.match(x) is not None
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    30
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    31
def rule(pairs):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    32
    matchers = [(k, globmatcher(v)) for k, v in pairs]
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    33
    def c(**kw):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    34
        for k, m in matchers:
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    35
            if k not in kw or not m(kw[k]):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    36
                return False
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    37
        return True
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    38
    return c
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    39
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    40
class Rulefile(object):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    41
    '''Class representing the rules in a rule file'''
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    42
    
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    43
    self.levels = ["init", "write", "read", "deny"]
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    44
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    45
    def __init__(self):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    46
        self.rules = []
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    47
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    48
    def add(self, action, conditions):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    49
        self.rules.append((action, conditions))
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    50
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    51
    def matchrule(self, **kw):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    52
        for a, c in self.rules:
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    53
            if c(**kw):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    54
                return a
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    55
        return None
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    56
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    57
    def allow(self, level, **kw):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    58
        a = matchrule(self, **kw)
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    59
        return a in self.levels and self.levels.index(a) <= self.levels.index(level)
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    60
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    61
def read_rules(fn):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    62
    res = Rulefile()
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    63
    f = open(fn)
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    64
    try:
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    65
        for l in f:
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    66
            l = l.strip()
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    67
            if len(l) == 0 or l.startswith["#"]:
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    68
                continue
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    69
            res.add(l[0], rule([c.split("=", 1) for c in l[1:]]))
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    70
    finally:
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    71
        f.close()
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    72
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    73
class Checker(object):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    74
    '''acl checker.'''
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    75
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    76
    def getuser(self):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    77
        '''return name of hg-ssh user'''
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    78
        return os.environ['REMOTE_USER']
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    79
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    80
    def __init__(self, ui, repo):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    81
        self.ui = ui
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    82
        self.repo = repo
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    83
        self.rules = read_rules(os.environ['HG_ACCESS_RULES_FILE'])
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    84
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    85
    def check(self, node):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    86
        '''return if access allowed, raise exception if not.'''
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    87
        files = self.repo.changectx(node).files()
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    88
        for f in files:
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    89
            if not self.rules.allow("write", user=self.user, ):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    90
                self.ui.debug(_('%s: user %s not allowed on %s\n') %
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    91
                              (__name__, self.getuser(), f))
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    92
                raise util.Abort(_('%s: access denied for changeset %s') %
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    93
                                 (__name__, short(node)))
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    94
        self.ui.debug(_('%s: allowing changeset %s\n') % (__name__, short(node)))
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    95
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    96
def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    97
    if hooktype != 'pretxnchangegroup':
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    98
        raise util.Abort(_('config error - hook type "%s" cannot stop '
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
    99
                           'incoming changesets') % hooktype)
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
   100
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
   101
    c = checker(ui, repo)
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
   102
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
   103
    start = repo.changelog.rev(bin(node))
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
   104
    end = repo.changelog.count()
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
   105
    for rev in xrange(start, end):
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
   106
        c.check(repo.changelog.node(rev))
4c98440de851 Started work on acl.py replacement - currently broken.
Paul Crowley <paul@ciphergoth.org>
parents:
diff changeset
   107