Mercurial > hg
comparison hgext/acl.py @ 6766:e81d2bd66908
acl: refactoring
- undo class structure
- make buildmatch return None for no function
- use contexts properly
- simplify check loop
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Fri, 27 Jun 2008 21:45:16 -0500 |
parents | fb42030d79d6 |
children | 912bfef12ba6 |
comparison
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) |