##// END OF EJS Templates
push over http: server side authorization support....
Vadim Gelfer -
r2466:e1066514 default
parent child Browse files
Show More
@@ -381,6 +381,14 b' web::'
381 Default is false.
381 Default is false.
382 allowpull;;
382 allowpull;;
383 Whether to allow pulling from the repository. Default is true.
383 Whether to allow pulling from the repository. Default is true.
384 allow_push;;
385 Whether to allow pushing to the repository. If empty or not set,
386 push is not allowed. If the special value "*", any remote user
387 can push, including unauthenticated users. Otherwise, the remote
388 user must have been authenticated, and the authenticated user name
389 must be present in this list (separated by whitespace or ",").
390 The contents of the allow_push list are examined after the
391 deny_push list.
384 allowzip;;
392 allowzip;;
385 (DEPRECATED) Whether to allow .zip downloading of repo revisions.
393 (DEPRECATED) Whether to allow .zip downloading of repo revisions.
386 Default is false. This feature creates temporary files.
394 Default is false. This feature creates temporary files.
@@ -391,6 +399,13 b' web::'
391 contact;;
399 contact;;
392 Name or email address of the person in charge of the repository.
400 Name or email address of the person in charge of the repository.
393 Default is "unknown".
401 Default is "unknown".
402 deny_push;;
403 Whether to deny pushing to the repository. If empty or not set,
404 push is not denied. If the special value "*", all remote users
405 are denied push. Otherwise, unauthenticated users are all denied,
406 and any authenticated user name present in this list (separated by
407 whitespace or ",") is also denied. The contents of the deny_push
408 list are examined before the allow_push list.
394 description;;
409 description;;
395 Textual description of the repository's purpose or contents.
410 Textual description of the repository's purpose or contents.
396 Default is "unknown".
411 Default is "unknown".
@@ -407,6 +422,9 b' web::'
407 Maximum number of files to list per changeset. Default is 10.
422 Maximum number of files to list per changeset. Default is 10.
408 port;;
423 port;;
409 Port to listen on. Default is 8000.
424 Port to listen on. Default is 8000.
425 push_ssl;;
426 Whether to require that inbound pushes be transported over SSL to
427 prevent password sniffing. Default is true.
410 style;;
428 style;;
411 Which template map style to use.
429 Which template map style to use.
412 templates;;
430 templates;;
@@ -839,19 +839,59 b' class hgweb(object):'
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
@@ -45,9 +45,9 b' class hgrequest(object):'
45 self.out.write("%s: %s\r\n" % header)
45 self.out.write("%s: %s\r\n" % header)
46 self.out.write("\r\n")
46 self.out.write("\r\n")
47
47
48 def httphdr(self, type, filename=None, length=0):
48 def httphdr(self, type, filename=None, length=0, headers={}):
49
49 headers = headers.items()
50 headers = [('Content-type', type)]
50 headers.append(('Content-type', type))
51 if filename:
51 if filename:
52 headers.append(('Content-disposition', 'attachment; filename=%s' %
52 headers.append(('Content-disposition', 'attachment; filename=%s' %
53 filename))
53 filename))
General Comments 0
You need to be logged in to leave comments. Login now