hgext/acl.py
changeset 6766 e81d2bd66908
parent 6750 fb42030d79d6
child 8142 912bfef12ba6
equal deleted inserted replaced
6765:be142cb994ff 6766:e81d2bd66908
    44 #   # empty acl.deny = all users allowed
    44 #   # empty acl.deny = all users allowed
    45 #   glob pattern = user4, user5
    45 #   glob pattern = user4, user5
    46 #   ** = user6
    46 #   ** = user6
    47 
    47 
    48 from mercurial.i18n import _
    48 from mercurial.i18n import _
    49 from mercurial.node import bin, short
       
    50 from mercurial import util
    49 from mercurial import util
    51 import getpass
    50 import getpass
    52 
    51 
    53 class checker(object):
    52 def buildmatch(ui, repo, user, key):
    54     '''acl checker.'''
    53     '''return tuple of (match function, list enabled).'''
       
    54     if not ui.has_section(key):
       
    55         ui.debug(_('acl: %s not enabled\n') % key)
       
    56         return None
    55 
    57 
    56     def buildmatch(self, key):
    58     pats = [pat for pat, users in ui.configitems(key)
    57         '''return tuple of (match function, list enabled).'''
    59             if user in users.replace(',', ' ').split()]
    58         if not self.ui.has_section(key):
    60     ui.debug(_('acl: %s enabled, %d entries for user %s\n') %
    59             self.ui.debug(_('acl: %s not enabled\n') % key)
    61              (key, len(pats), user))
    60             return None, False
    62     if pats:
    61 
    63         return util.matcher(repo.root, names=pats)[1]
    62         thisuser = self.getuser()
    64     return util.never
    63         pats = [pat for pat, users in self.ui.configitems(key)
       
    64                 if thisuser in users.replace(',', ' ').split()]
       
    65         self.ui.debug(_('acl: %s enabled, %d entries for user %s\n') %
       
    66                       (key, len(pats), thisuser))
       
    67         if pats:
       
    68             match = util.matcher(self.repo.root, names=pats)[1]
       
    69         else:
       
    70             match = util.never
       
    71         return match, True
       
    72 
       
    73     def getuser(self):
       
    74         '''return name of authenticated user.'''
       
    75         return self.user
       
    76 
       
    77     def __init__(self, ui, repo):
       
    78         self.ui = ui
       
    79         self.repo = repo
       
    80         self.user = getpass.getuser()
       
    81         cfg = self.ui.config('acl', 'config')
       
    82         if cfg:
       
    83             self.ui.readsections(cfg, 'acl.allow', 'acl.deny')
       
    84         self.allow, self.allowable = self.buildmatch('acl.allow')
       
    85         self.deny, self.deniable = self.buildmatch('acl.deny')
       
    86 
       
    87     def skipsource(self, source):
       
    88         '''true if incoming changes from this source should be skipped.'''
       
    89         ok_sources = self.ui.config('acl', 'sources', 'serve').split()
       
    90         return source not in ok_sources
       
    91 
       
    92     def check(self, node):
       
    93         '''return if access allowed, raise exception if not.'''
       
    94         files = self.repo[node].files()
       
    95         if self.deniable:
       
    96             for f in files:
       
    97                 if self.deny(f):
       
    98                     self.ui.debug(_('acl: user %s denied on %s\n') %
       
    99                                   (self.getuser(), f))
       
   100                     raise util.Abort(_('acl: access denied for changeset %s') %
       
   101                                      short(node))
       
   102         if self.allowable:
       
   103             for f in files:
       
   104                 if not self.allow(f):
       
   105                     self.ui.debug(_('acl: user %s not allowed on %s\n') %
       
   106                                   (self.getuser(), f))
       
   107                     raise util.Abort(_('acl: access denied for changeset %s') %
       
   108                                      short(node))
       
   109         self.ui.debug(_('acl: allowing changeset %s\n') % short(node))
       
   110 
    65 
   111 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
    66 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
   112     if hooktype != 'pretxnchangegroup':
    67     if hooktype != 'pretxnchangegroup':
   113         raise util.Abort(_('config error - hook type "%s" cannot stop '
    68         raise util.Abort(_('config error - hook type "%s" cannot stop '
   114                            'incoming changesets') % hooktype)
    69                            'incoming changesets') % hooktype)
   115 
    70     if source not in ui.config('acl', 'sources', 'serve').split():
   116     c = checker(ui, repo)
       
   117     if c.skipsource(source):
       
   118         ui.debug(_('acl: changes have source "%s" - skipping\n') % source)
    71         ui.debug(_('acl: changes have source "%s" - skipping\n') % source)
   119         return
    72         return
   120 
    73 
   121     for rev in xrange(repo[node].rev(), len(repo)):
    74     user = getpass.getuser()
   122         c.check(repo.changelog.node(rev))
    75     cfg = ui.config('acl', 'config')
       
    76     if cfg:
       
    77         ui.readsections(cfg, 'acl.allow', 'acl.deny')
       
    78     allow = buildmatch(ui, repo, user, 'acl.allow')
       
    79     deny = buildmatch(ui, repo, user, 'acl.deny')
       
    80 
       
    81     for rev in xrange(repo[node], len(repo)):
       
    82         ctx = repo[rev]
       
    83         for f in ctx.files():
       
    84             if deny and deny(f):
       
    85                 ui.debug(_('acl: user %s denied on %s\n') % (user, f))
       
    86                 raise util.Abort(_('acl: access denied for changeset %s') % ctx)
       
    87             if allow and not allow(f):
       
    88                 ui.debug(_('acl: user %s not allowed on %s\n') % (user, f))
       
    89                 raise util.Abort(_('acl: access denied for changeset %s') % ctx)
       
    90         ui.debug(_('acl: allowing changeset %s\n') % ctx)