Mercurial > public > mercurial-scm > hg
comparison mercurial/hgweb/hgweb_mod.py @ 2466:e10665147d26
push over http: server side authorization support.
new hgrc entries allow_push, deny_push, push_ssl control push over http.
allow_push list controls push. if empty or not set, no user can push.
if "*", any user (incl. unauthenticated user) can push. if list of user
names, only authenticated users in list can push.
deny_push list examined before allow_push. if "*", no user can push.
if list of user names, no unauthenticated user can push, and no users
in list can push.
push_ssl requires https connection for push. default is true, so password
sniffing can not be done.
author | Vadim Gelfer <vadim.gelfer@gmail.com> |
---|---|
date | Tue, 20 Jun 2006 15:23:01 -0700 |
parents | 09b1c9ef317c |
children | 76ff5efe8181 d0db3462d568 |
comparison
equal
deleted
inserted
replaced
2465:c91118f425d0 | 2466:e10665147d26 |
---|---|
837 def do_capabilities(self, req): | 837 def do_capabilities(self, req): |
838 resp = 'unbundle' | 838 resp = 'unbundle' |
839 req.httphdr("application/mercurial-0.1", length=len(resp)) | 839 req.httphdr("application/mercurial-0.1", length=len(resp)) |
840 req.write(resp) | 840 req.write(resp) |
841 | 841 |
842 def check_perm(self, req, op, default): | |
843 '''check permission for operation based on user auth. | |
844 return true if op allowed, else false. | |
845 default is policy to use if no config given.''' | |
846 | |
847 user = req.env.get('REMOTE_USER') | |
848 | |
849 deny = self.repo.ui.config('web', 'deny_' + op, '') | |
850 deny = deny.replace(',', ' ').split() | |
851 | |
852 if deny and (not user or deny == ['*'] or user in deny): | |
853 return False | |
854 | |
855 allow = self.repo.ui.config('web', 'allow_' + op, '') | |
856 allow = allow.replace(',', ' ').split() | |
857 | |
858 return (allow and (allow == ['*'] or user in allow)) or default | |
859 | |
842 def do_unbundle(self, req): | 860 def do_unbundle(self, req): |
861 def bail(response, headers={}): | |
862 length = int(req.env['CONTENT_LENGTH']) | |
863 for s in util.filechunkiter(req, limit=length): | |
864 # drain incoming bundle, else client will not see | |
865 # response when run outside cgi script | |
866 pass | |
867 req.httphdr("application/mercurial-0.1", headers=headers) | |
868 req.write('0\n') | |
869 req.write(response) | |
870 | |
871 # require ssl by default, auth info cannot be sniffed and | |
872 # replayed | |
873 ssl_req = self.repo.ui.configbool('web', 'push_ssl', True) | |
874 if ssl_req and not req.env.get('HTTPS'): | |
875 bail(_('ssl required\n')) | |
876 return | |
877 | |
878 # do not allow push unless explicitly allowed | |
879 if not self.check_perm(req, 'push', False): | |
880 bail(_('push not authorized\n'), | |
881 headers={'status': '401 Unauthorized'}) | |
882 return | |
883 | |
884 req.httphdr("application/mercurial-0.1") | |
885 | |
843 their_heads = req.form['heads'][0].split(' ') | 886 their_heads = req.form['heads'][0].split(' ') |
844 | 887 |
845 def check_heads(): | 888 def check_heads(): |
846 heads = map(hex, self.repo.heads()) | 889 heads = map(hex, self.repo.heads()) |
847 return their_heads == [hex('force')] or their_heads == heads | 890 return their_heads == [hex('force')] or their_heads == heads |
848 | 891 |
849 req.httphdr("application/mercurial-0.1") | |
850 | |
851 # fail early if possible | 892 # fail early if possible |
852 if not check_heads(): | 893 if not check_heads(): |
853 req.write('0\n') | 894 bail(_('unsynced changes\n')) |
854 req.write(_('unsynced changes\n')) | |
855 return | 895 return |
856 | 896 |
857 # do not lock repo until all changegroup data is | 897 # do not lock repo until all changegroup data is |
858 # streamed. save to temporary file. | 898 # streamed. save to temporary file. |
859 | 899 |