comparison mercurial/hgweb/protocol.py @ 6779:d3147b4e3e8a

hgweb: centralize permission checks for protocol commands Consistently enforces authorization checks set up in hgrc up front, so that the actual commands don't have to worry about them and implementers of hgweb alternatives can easily implement their own permission checks.
author Dirkjan Ochtman <dirkjan@ochtman.nl>
date Sun, 29 Jun 2008 11:35:06 +0200
parents 8542fac26f63
children 4c1d67e0fa8c
comparison
equal deleted inserted replaced
6778:959efdac4a9c 6779:d3147b4e3e8a
60 req.write(resp) 60 req.write(resp)
61 61
62 def changegroup(web, req): 62 def changegroup(web, req):
63 req.respond(HTTP_OK, HGTYPE) 63 req.respond(HTTP_OK, HGTYPE)
64 nodes = [] 64 nodes = []
65 if not web.allowpull:
66 return
67 65
68 if 'roots' in req.form: 66 if 'roots' in req.form:
69 nodes = map(bin, req.form['roots'][0].split(" ")) 67 nodes = map(bin, req.form['roots'][0].split(" "))
70 68
71 z = zlib.compressobj() 69 z = zlib.compressobj()
80 78
81 def changegroupsubset(web, req): 79 def changegroupsubset(web, req):
82 req.respond(HTTP_OK, HGTYPE) 80 req.respond(HTTP_OK, HGTYPE)
83 bases = [] 81 bases = []
84 heads = [] 82 heads = []
85 if not web.allowpull:
86 return
87 83
88 if 'bases' in req.form: 84 if 'bases' in req.form:
89 bases = [bin(x) for x in req.form['bases'][0].split(' ')] 85 bases = [bin(x) for x in req.form['bases'][0].split(' ')]
90 if 'heads' in req.form: 86 if 'heads' in req.form:
91 heads = [bin(x) for x in req.form['heads'][0].split(' ')] 87 heads = [bin(x) for x in req.form['heads'][0].split(' ')]
118 req.header(headers.items()) 114 req.header(headers.items())
119 req.respond(status, HGTYPE) 115 req.respond(status, HGTYPE)
120 req.write('0\n') 116 req.write('0\n')
121 req.write(response) 117 req.write(response)
122 118
123 # enforce that you can only unbundle with POST requests 119 proto = req.env.get('wsgi.url_scheme') or 'http'
124 if req.env['REQUEST_METHOD'] != 'POST':
125 headers = {'status': '405 Method Not Allowed'}
126 bail('unbundle requires POST request\n', headers)
127 return
128
129 # require ssl by default, auth info cannot be sniffed and
130 # replayed
131 ssl_req = web.configbool('web', 'push_ssl', True)
132 if ssl_req:
133 if req.env.get('wsgi.url_scheme') != 'https':
134 bail('ssl required\n')
135 return
136 proto = 'https'
137 else:
138 proto = 'http'
139
140 # do not allow push unless explicitly allowed
141 if not web.check_perm(req, 'push', False):
142 bail('push not authorized\n', headers={'status': '401 Unauthorized'})
143 return
144
145 their_heads = req.form['heads'][0].split(' ') 120 their_heads = req.form['heads'][0].split(' ')
146 121
147 def check_heads(): 122 def check_heads():
148 heads = map(hex, web.repo.heads()) 123 heads = map(hex, web.repo.heads())
149 return their_heads == [hex('force')] or their_heads == heads 124 return their_heads == [hex('force')] or their_heads == heads
222 finally: 197 finally:
223 fp.close() 198 fp.close()
224 os.unlink(tempname) 199 os.unlink(tempname)
225 200
226 def stream_out(web, req): 201 def stream_out(web, req):
227 if not web.allowpull:
228 return
229 req.respond(HTTP_OK, HGTYPE) 202 req.respond(HTTP_OK, HGTYPE)
230 streamclone.stream_out(web.repo, req, untrusted=True) 203 streamclone.stream_out(web.repo, req, untrusted=True)