annotate hgext/acl.py @ 11010:18e81d42ee5c stable

util: fix default termwidth() under Windows sys.stdout.write('-'*80 + '\n') or sys.stdout.write('-'*80 + '\r') do not work on Windows as they do on unix. On a 80 columns Windows console, the extra CR or LF are interpreted as if belonging to the next line, so the first command displays 2 lines (only one on unix) and the second one leave the line visible and move back to the following line. To avoid this, we sacrifice one column under Windows.
author Patrick Mezard <pmezard@gmail.com>
date Mon, 26 Apr 2010 22:30:40 +0200
parents fcfe2e50faab
children 470a6ace7574
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
1 # acl.py - changeset access control for mercurial
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
2 #
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
3 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
4 #
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8142
diff changeset
5 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10112
diff changeset
6 # GNU General Public License version 2 or any later version.
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
7
8935
f4f0e902b750 extensions: change descriptions for hook-providing extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8894
diff changeset
8 '''hooks for controlling repository access
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
9
9250
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
10 This hook makes it possible to allow or deny write access to portions
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
11 of a repository when receiving incoming changesets.
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
12
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
13 The authorization is matched based on the local user name on the
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
14 system where the hook runs, and not the committer of the original
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
15 changeset (since the latter is merely informative).
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
16
9250
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
17 The acl hook is best used along with a restricted shell like hgsh,
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
18 preventing authenticating users from doing anything other than
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
19 pushing or pulling. The hook is not safe to use if users have
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
20 interactive shell access, as they can then disable the hook.
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
21 Nor is it safe if remote users share an account, because then there
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
22 is no way to distinguish them.
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
23
9201
3d6c9659886b acl: use reST syntax for literal blocks
Martin Geisler <mg@lazybytes.net>
parents: 9052
diff changeset
24 To use this hook, configure the acl extension in your hgrc like this::
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
25
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
26 [extensions]
10112
703db37d186b hgext: enable extensions without "hgext." prefix in help texts
Martin Geisler <mg@lazybytes.net>
parents: 9467
diff changeset
27 acl =
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
28
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
29 [hooks]
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
30 pretxnchangegroup.acl = python:hgext.acl.hook
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
31
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
32 [acl]
8893
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
33 # Check whether the source of incoming changes is in this list
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
34 # ("serve" == ssh or http, "push", "pull", "bundle")
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
35 sources = serve
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
36
9250
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
37 The allow and deny sections take a subtree pattern as key (with a glob
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
38 syntax by default), and a comma separated list of users as the
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
39 corresponding value. The deny list is checked before the allow list
00986b9ed649 acl: wrap docstrings at 70 characters
Martin Geisler <mg@lazybytes.net>
parents: 9201
diff changeset
40 is. ::
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
41
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
42 [acl.allow]
8893
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
43 # If acl.allow is not present, all users are allowed by default.
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
44 # An empty acl.allow section means no users allowed.
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
45 docs/** = doc_writer
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
46 .hgtags = release_engineer
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
47
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
48 [acl.deny]
8893
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
49 # If acl.deny is not present, no users are refused by default.
cc0593af30d4 acl: help improvements
Cédric Duval <cedricduval@free.fr>
parents: 8873
diff changeset
50 # An empty acl.deny section means all users allowed.
8873
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
51 glob pattern = user4, user5
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
52 ** = user6
e872ef2e6758 help: add/fix docstrings for a bunch of extensions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8846
diff changeset
53 '''
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
54
3891
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3877
diff changeset
55 from mercurial.i18n import _
8566
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8225
diff changeset
56 from mercurial import util, match
8846
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
57 import getpass, urllib
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
58
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
59 def buildmatch(ui, repo, user, key):
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
60 '''return tuple of (match function, list enabled).'''
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
61 if not ui.has_section(key):
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9250
diff changeset
62 ui.debug('acl: %s not enabled\n' % key)
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
63 return None
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
64
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
65 pats = [pat for pat, users in ui.configitems(key)
10801
fcfe2e50faab Added support for 'everybody ' (using an asterisk) in user list.
Elifarley Callado Coelho Cruz <elifarley@gmail.com>
parents: 10263
diff changeset
66 if users == '*' or user in users.replace(',', ' ').split()]
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9250
diff changeset
67 ui.debug('acl: %s enabled, %d entries for user %s\n' %
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
68 (key, len(pats), user))
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
69 if pats:
8567
fea40a677d43 match: add some default args
Matt Mackall <mpm@selenic.com>
parents: 8566
diff changeset
70 return match.match(repo.root, '', pats)
8682
cc7da5aae4cd match: remove match.never
Matt Mackall <mpm@selenic.com>
parents: 8567
diff changeset
71 return match.exact(repo.root, '', [])
8566
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8225
diff changeset
72
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
73
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
74 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
75 if hooktype != 'pretxnchangegroup':
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
76 raise util.Abort(_('config error - hook type "%s" cannot stop '
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
77 'incoming changesets') % hooktype)
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
78 if source not in ui.config('acl', 'sources', 'serve').split():
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9250
diff changeset
79 ui.debug('acl: changes have source "%s" - skipping\n' % source)
2344
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
80 return
ae12e5a2c4a3 add acl extension, to limit who can push to subdirs of central repo.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
81
8846
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
82 user = None
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
83 if source == 'serve' and 'url' in kwargs:
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
84 url = kwargs['url'].split(':')
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
85 if url[0] == 'remote' and url[1].startswith('http'):
9018
5ed463d0ebdb acl: read correct index into url for username (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8935
diff changeset
86 user = urllib.unquote(url[3])
8846
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
87
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
88 if user is None:
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
89 user = getpass.getuser()
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8682
diff changeset
90
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
91 cfg = ui.config('acl', 'config')
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
92 if cfg:
8142
912bfef12ba6 ui: fold readsections into readconfig
Matt Mackall <mpm@selenic.com>
parents: 6766
diff changeset
93 ui.readconfig(cfg, sections = ['acl.allow', 'acl.deny'])
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
94 allow = buildmatch(ui, repo, user, 'acl.allow')
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
95 deny = buildmatch(ui, repo, user, 'acl.deny')
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
96
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
97 for rev in xrange(repo[node], len(repo)):
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
98 ctx = repo[rev]
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
99 for f in ctx.files():
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
100 if deny and deny(f):
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9250
diff changeset
101 ui.debug('acl: user %s denied on %s\n' % (user, f))
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
102 raise util.Abort(_('acl: access denied for changeset %s') % ctx)
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
103 if allow and not allow(f):
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9250
diff changeset
104 ui.debug('acl: user %s not allowed on %s\n' % (user, f))
6766
e81d2bd66908 acl: refactoring
Matt Mackall <mpm@selenic.com>
parents: 6750
diff changeset
105 raise util.Abort(_('acl: access denied for changeset %s') % ctx)
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9250
diff changeset
106 ui.debug('acl: allowing changeset %s\n' % ctx)