Show More
@@ -46,77 +46,45 b'' | |||||
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).''' | |
55 |
|
54 | if not ui.has_section(key): | ||
56 | def buildmatch(self, key): |
|
55 | ui.debug(_('acl: %s not enabled\n') % key) | |
57 | '''return tuple of (match function, list enabled).''' |
|
56 | return None | |
58 | if not self.ui.has_section(key): |
|
|||
59 | self.ui.debug(_('acl: %s not enabled\n') % key) |
|
|||
60 | return None, False |
|
|||
61 |
|
||||
62 | thisuser = self.getuser() |
|
|||
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 |
|
57 | |||
77 | def __init__(self, ui, repo): |
|
58 | pats = [pat for pat, users in ui.configitems(key) | |
78 | self.ui = ui |
|
59 | if user in users.replace(',', ' ').split()] | |
79 | self.repo = repo |
|
60 | ui.debug(_('acl: %s enabled, %d entries for user %s\n') % | |
80 | self.user = getpass.getuser() |
|
61 | (key, len(pats), user)) | |
81 | cfg = self.ui.config('acl', 'config') |
|
62 | if pats: | |
82 | if cfg: |
|
63 | return util.matcher(repo.root, names=pats)[1] | |
83 | self.ui.readsections(cfg, 'acl.allow', 'acl.deny') |
|
64 | return util.never | |
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) |
@@ -58,8 +58,6 b' adding foo/file.txt revisions' | |||||
58 | adding quux/file.py revisions |
|
58 | adding quux/file.py revisions | |
59 | added 3 changesets with 3 changes to 3 files |
|
59 | added 3 changesets with 3 changes to 3 files | |
60 | calling hook pretxnchangegroup.acl: hgext.acl.hook |
|
60 | calling hook pretxnchangegroup.acl: hgext.acl.hook | |
61 | acl: acl.allow not enabled |
|
|||
62 | acl: acl.deny not enabled |
|
|||
63 | acl: changes have source "push" - skipping |
|
61 | acl: changes have source "push" - skipping | |
64 | updating the branch cache |
|
62 | updating the branch cache | |
65 | rolling back last transaction |
|
63 | rolling back last transaction |
General Comments 0
You need to be logged in to leave comments.
Login now