comparison hgext/acl.py @ 43077:687b865b95ad

formatting: byteify all mercurial/ and hgext/ string literals Done with python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py') black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**') # skip-blame mass-reformatting only Differential Revision: https://phab.mercurial-scm.org/D6972
author Augie Fackler <augie@google.com>
date Sun, 06 Oct 2019 09:48:39 -0400
parents 2372284d9457
children 8ff1ecfadcd1
comparison
equal deleted inserted replaced
43076:2372284d9457 43077:687b865b95ad
230 230
231 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for 231 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
232 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should 232 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
233 # be specifying the version(s) of Mercurial they are tested with, or 233 # be specifying the version(s) of Mercurial they are tested with, or
234 # leave the attribute unspecified. 234 # leave the attribute unspecified.
235 testedwith = 'ships-with-hg-core' 235 testedwith = b'ships-with-hg-core'
236 236
237 configtable = {} 237 configtable = {}
238 configitem = registrar.configitem(configtable) 238 configitem = registrar.configitem(configtable)
239 239
240 # deprecated config: acl.config 240 # deprecated config: acl.config
241 configitem( 241 configitem(
242 'acl', 'config', default=None, 242 b'acl', b'config', default=None,
243 ) 243 )
244 configitem( 244 configitem(
245 'acl.groups', '.*', default=None, generic=True, 245 b'acl.groups', b'.*', default=None, generic=True,
246 ) 246 )
247 configitem( 247 configitem(
248 'acl.deny.branches', '.*', default=None, generic=True, 248 b'acl.deny.branches', b'.*', default=None, generic=True,
249 ) 249 )
250 configitem( 250 configitem(
251 'acl.allow.branches', '.*', default=None, generic=True, 251 b'acl.allow.branches', b'.*', default=None, generic=True,
252 ) 252 )
253 configitem( 253 configitem(
254 'acl.deny', '.*', default=None, generic=True, 254 b'acl.deny', b'.*', default=None, generic=True,
255 ) 255 )
256 configitem( 256 configitem(
257 'acl.allow', '.*', default=None, generic=True, 257 b'acl.allow', b'.*', default=None, generic=True,
258 ) 258 )
259 configitem( 259 configitem(
260 'acl', 'sources', default=lambda: ['serve'], 260 b'acl', b'sources', default=lambda: [b'serve'],
261 ) 261 )
262 262
263 263
264 def _getusers(ui, group): 264 def _getusers(ui, group):
265 265
266 # First, try to use group definition from section [acl.groups] 266 # First, try to use group definition from section [acl.groups]
267 hgrcusers = ui.configlist('acl.groups', group) 267 hgrcusers = ui.configlist(b'acl.groups', group)
268 if hgrcusers: 268 if hgrcusers:
269 return hgrcusers 269 return hgrcusers
270 270
271 ui.debug('acl: "%s" not defined in [acl.groups]\n' % group) 271 ui.debug(b'acl: "%s" not defined in [acl.groups]\n' % group)
272 # If no users found in group definition, get users from OS-level group 272 # If no users found in group definition, get users from OS-level group
273 try: 273 try:
274 return util.groupmembers(group) 274 return util.groupmembers(group)
275 except KeyError: 275 except KeyError:
276 raise error.Abort(_("group '%s' is undefined") % group) 276 raise error.Abort(_(b"group '%s' is undefined") % group)
277 277
278 278
279 def _usermatch(ui, user, usersorgroups): 279 def _usermatch(ui, user, usersorgroups):
280 280
281 if usersorgroups == '*': 281 if usersorgroups == b'*':
282 return True 282 return True
283 283
284 for ug in usersorgroups.replace(',', ' ').split(): 284 for ug in usersorgroups.replace(b',', b' ').split():
285 285
286 if ug.startswith('!'): 286 if ug.startswith(b'!'):
287 # Test for excluded user or group. Format: 287 # Test for excluded user or group. Format:
288 # if ug is a user name: !username 288 # if ug is a user name: !username
289 # if ug is a group name: !@groupname 289 # if ug is a group name: !@groupname
290 ug = ug[1:] 290 ug = ug[1:]
291 if ( 291 if (
292 not ug.startswith('@') 292 not ug.startswith(b'@')
293 and user != ug 293 and user != ug
294 or ug.startswith('@') 294 or ug.startswith(b'@')
295 and user not in _getusers(ui, ug[1:]) 295 and user not in _getusers(ui, ug[1:])
296 ): 296 ):
297 return True 297 return True
298 298
299 # Test for user or group. Format: 299 # Test for user or group. Format:
300 # if ug is a user name: username 300 # if ug is a user name: username
301 # if ug is a group name: @groupname 301 # if ug is a group name: @groupname
302 elif user == ug or ug.startswith('@') and user in _getusers(ui, ug[1:]): 302 elif (
303 user == ug or ug.startswith(b'@') and user in _getusers(ui, ug[1:])
304 ):
303 return True 305 return True
304 306
305 return False 307 return False
306 308
307 309
308 def buildmatch(ui, repo, user, key): 310 def buildmatch(ui, repo, user, key):
309 '''return tuple of (match function, list enabled).''' 311 '''return tuple of (match function, list enabled).'''
310 if not ui.has_section(key): 312 if not ui.has_section(key):
311 ui.debug('acl: %s not enabled\n' % key) 313 ui.debug(b'acl: %s not enabled\n' % key)
312 return None 314 return None
313 315
314 pats = [ 316 pats = [
315 pat for pat, users in ui.configitems(key) if _usermatch(ui, user, users) 317 pat for pat, users in ui.configitems(key) if _usermatch(ui, user, users)
316 ] 318 ]
317 ui.debug( 319 ui.debug(
318 'acl: %s enabled, %d entries for user %s\n' % (key, len(pats), user) 320 b'acl: %s enabled, %d entries for user %s\n' % (key, len(pats), user)
319 ) 321 )
320 322
321 # Branch-based ACL 323 # Branch-based ACL
322 if not repo: 324 if not repo:
323 if pats: 325 if pats:
324 # If there's an asterisk (meaning "any branch"), always return True; 326 # If there's an asterisk (meaning "any branch"), always return True;
325 # Otherwise, test if b is in pats 327 # Otherwise, test if b is in pats
326 if '*' in pats: 328 if b'*' in pats:
327 return util.always 329 return util.always
328 return lambda b: b in pats 330 return lambda b: b in pats
329 return util.never 331 return util.never
330 332
331 # Path-based ACL 333 # Path-based ACL
332 if pats: 334 if pats:
333 return match.match(repo.root, '', pats) 335 return match.match(repo.root, b'', pats)
334 return util.never 336 return util.never
335 337
336 338
337 def ensureenabled(ui): 339 def ensureenabled(ui):
338 """make sure the extension is enabled when used as hook 340 """make sure the extension is enabled when used as hook
340 When acl is used through hooks, the extension is never formally loaded and 342 When acl is used through hooks, the extension is never formally loaded and
341 enabled. This has some side effect, for example the config declaration is 343 enabled. This has some side effect, for example the config declaration is
342 never loaded. This function ensure the extension is enabled when running 344 never loaded. This function ensure the extension is enabled when running
343 hooks. 345 hooks.
344 """ 346 """
345 if 'acl' in ui._knownconfig: 347 if b'acl' in ui._knownconfig:
346 return 348 return
347 ui.setconfig('extensions', 'acl', '', source='internal') 349 ui.setconfig(b'extensions', b'acl', b'', source=b'internal')
348 extensions.loadall(ui, ['acl']) 350 extensions.loadall(ui, [b'acl'])
349 351
350 352
351 def hook(ui, repo, hooktype, node=None, source=None, **kwargs): 353 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
352 354
353 ensureenabled(ui) 355 ensureenabled(ui)
354 356
355 if hooktype not in ['pretxnchangegroup', 'pretxncommit', 'prepushkey']: 357 if hooktype not in [b'pretxnchangegroup', b'pretxncommit', b'prepushkey']:
356 raise error.Abort( 358 raise error.Abort(
357 _( 359 _(
358 'config error - hook type "%s" cannot stop ' 360 b'config error - hook type "%s" cannot stop '
359 'incoming changesets, commits, nor bookmarks' 361 b'incoming changesets, commits, nor bookmarks'
360 ) 362 )
361 % hooktype 363 % hooktype
362 ) 364 )
363 if hooktype == 'pretxnchangegroup' and source not in ui.configlist( 365 if hooktype == b'pretxnchangegroup' and source not in ui.configlist(
364 'acl', 'sources' 366 b'acl', b'sources'
365 ): 367 ):
366 ui.debug('acl: changes have source "%s" - skipping\n' % source) 368 ui.debug(b'acl: changes have source "%s" - skipping\n' % source)
367 return 369 return
368 370
369 user = None 371 user = None
370 if source == 'serve' and r'url' in kwargs: 372 if source == b'serve' and r'url' in kwargs:
371 url = kwargs[r'url'].split(':') 373 url = kwargs[r'url'].split(b':')
372 if url[0] == 'remote' and url[1].startswith('http'): 374 if url[0] == b'remote' and url[1].startswith(b'http'):
373 user = urlreq.unquote(url[3]) 375 user = urlreq.unquote(url[3])
374 376
375 if user is None: 377 if user is None:
376 user = procutil.getuser() 378 user = procutil.getuser()
377 379
378 ui.debug('acl: checking access for user "%s"\n' % user) 380 ui.debug(b'acl: checking access for user "%s"\n' % user)
379 381
380 if hooktype == 'prepushkey': 382 if hooktype == b'prepushkey':
381 _pkhook(ui, repo, hooktype, node, source, user, **kwargs) 383 _pkhook(ui, repo, hooktype, node, source, user, **kwargs)
382 else: 384 else:
383 _txnhook(ui, repo, hooktype, node, source, user, **kwargs) 385 _txnhook(ui, repo, hooktype, node, source, user, **kwargs)
384 386
385 387
386 def _pkhook(ui, repo, hooktype, node, source, user, **kwargs): 388 def _pkhook(ui, repo, hooktype, node, source, user, **kwargs):
387 if kwargs[r'namespace'] == 'bookmarks': 389 if kwargs[r'namespace'] == b'bookmarks':
388 bookmark = kwargs[r'key'] 390 bookmark = kwargs[r'key']
389 ctx = kwargs[r'new'] 391 ctx = kwargs[r'new']
390 allowbookmarks = buildmatch(ui, None, user, 'acl.allow.bookmarks') 392 allowbookmarks = buildmatch(ui, None, user, b'acl.allow.bookmarks')
391 denybookmarks = buildmatch(ui, None, user, 'acl.deny.bookmarks') 393 denybookmarks = buildmatch(ui, None, user, b'acl.deny.bookmarks')
392 394
393 if denybookmarks and denybookmarks(bookmark): 395 if denybookmarks and denybookmarks(bookmark):
394 raise error.Abort( 396 raise error.Abort(
395 _('acl: user "%s" denied on bookmark "%s"' ' (changeset "%s")') 397 _(
398 b'acl: user "%s" denied on bookmark "%s"'
399 b' (changeset "%s")'
400 )
396 % (user, bookmark, ctx) 401 % (user, bookmark, ctx)
397 ) 402 )
398 if allowbookmarks and not allowbookmarks(bookmark): 403 if allowbookmarks and not allowbookmarks(bookmark):
399 raise error.Abort( 404 raise error.Abort(
400 _( 405 _(
401 'acl: user "%s" not allowed on bookmark "%s"' 406 b'acl: user "%s" not allowed on bookmark "%s"'
402 ' (changeset "%s")' 407 b' (changeset "%s")'
403 ) 408 )
404 % (user, bookmark, ctx) 409 % (user, bookmark, ctx)
405 ) 410 )
406 ui.debug( 411 ui.debug(
407 'acl: bookmark access granted: "%s" on bookmark "%s"\n' 412 b'acl: bookmark access granted: "%s" on bookmark "%s"\n'
408 % (ctx, bookmark) 413 % (ctx, bookmark)
409 ) 414 )
410 415
411 416
412 def _txnhook(ui, repo, hooktype, node, source, user, **kwargs): 417 def _txnhook(ui, repo, hooktype, node, source, user, **kwargs):
413 # deprecated config: acl.config 418 # deprecated config: acl.config
414 cfg = ui.config('acl', 'config') 419 cfg = ui.config(b'acl', b'config')
415 if cfg: 420 if cfg:
416 ui.readconfig( 421 ui.readconfig(
417 cfg, 422 cfg,
418 sections=[ 423 sections=[
419 'acl.groups', 424 b'acl.groups',
420 'acl.allow.branches', 425 b'acl.allow.branches',
421 'acl.deny.branches', 426 b'acl.deny.branches',
422 'acl.allow', 427 b'acl.allow',
423 'acl.deny', 428 b'acl.deny',
424 ], 429 ],
425 ) 430 )
426 431
427 allowbranches = buildmatch(ui, None, user, 'acl.allow.branches') 432 allowbranches = buildmatch(ui, None, user, b'acl.allow.branches')
428 denybranches = buildmatch(ui, None, user, 'acl.deny.branches') 433 denybranches = buildmatch(ui, None, user, b'acl.deny.branches')
429 allow = buildmatch(ui, repo, user, 'acl.allow') 434 allow = buildmatch(ui, repo, user, b'acl.allow')
430 deny = buildmatch(ui, repo, user, 'acl.deny') 435 deny = buildmatch(ui, repo, user, b'acl.deny')
431 436
432 for rev in pycompat.xrange(repo[node].rev(), len(repo)): 437 for rev in pycompat.xrange(repo[node].rev(), len(repo)):
433 ctx = repo[rev] 438 ctx = repo[rev]
434 branch = ctx.branch() 439 branch = ctx.branch()
435 if denybranches and denybranches(branch): 440 if denybranches and denybranches(branch):
436 raise error.Abort( 441 raise error.Abort(
437 _('acl: user "%s" denied on branch "%s"' ' (changeset "%s")') 442 _(b'acl: user "%s" denied on branch "%s"' b' (changeset "%s")')
438 % (user, branch, ctx) 443 % (user, branch, ctx)
439 ) 444 )
440 if allowbranches and not allowbranches(branch): 445 if allowbranches and not allowbranches(branch):
441 raise error.Abort( 446 raise error.Abort(
442 _( 447 _(
443 'acl: user "%s" not allowed on branch "%s"' 448 b'acl: user "%s" not allowed on branch "%s"'
444 ' (changeset "%s")' 449 b' (changeset "%s")'
445 ) 450 )
446 % (user, branch, ctx) 451 % (user, branch, ctx)
447 ) 452 )
448 ui.debug( 453 ui.debug(
449 'acl: branch access granted: "%s" on branch "%s"\n' % (ctx, branch) 454 b'acl: branch access granted: "%s" on branch "%s"\n' % (ctx, branch)
450 ) 455 )
451 456
452 for f in ctx.files(): 457 for f in ctx.files():
453 if deny and deny(f): 458 if deny and deny(f):
454 raise error.Abort( 459 raise error.Abort(
455 _('acl: user "%s" denied on "%s"' ' (changeset "%s")') 460 _(b'acl: user "%s" denied on "%s"' b' (changeset "%s")')
456 % (user, f, ctx) 461 % (user, f, ctx)
457 ) 462 )
458 if allow and not allow(f): 463 if allow and not allow(f):
459 raise error.Abort( 464 raise error.Abort(
460 _('acl: user "%s" not allowed on "%s"' ' (changeset "%s")') 465 _(
466 b'acl: user "%s" not allowed on "%s"'
467 b' (changeset "%s")'
468 )
461 % (user, f, ctx) 469 % (user, f, ctx)
462 ) 470 )
463 ui.debug('acl: path access granted: "%s"\n' % ctx) 471 ui.debug(b'acl: path access granted: "%s"\n' % ctx)