|
a/Allura/allura/lib/security.py |
|
b/Allura/allura/lib/security.py |
|
... |
|
... |
295 |
result = False
|
295 |
result = False
|
296 |
# log.info('%s: %s', txt, result)
|
296 |
# log.info('%s: %s', txt, result)
|
297 |
return result
|
297 |
return result
|
298 |
return TruthyCallable(predicate)
|
298 |
return TruthyCallable(predicate)
|
299 |
|
299 |
|
|
|
300 |
def all_allowed(obj, user_or_role=None, project=None):
|
|
|
301 |
'''
|
|
|
302 |
List all the permission names that a given user or named role
|
|
|
303 |
is allowed for a given object. This list reflects the permissions
|
|
|
304 |
for which has_access() would return True for the user (or a user
|
|
|
305 |
in the given named role, e.g. Developer).
|
|
|
306 |
|
|
|
307 |
Example:
|
|
|
308 |
|
|
|
309 |
Given a tracker with the following ACL (pseudo-code):
|
|
|
310 |
[
|
|
|
311 |
ACE.allow(ProjectRole.by_name('Developer'), 'create'),
|
|
|
312 |
ACE.allow(ProjectRole.by_name('Member'), 'post'),
|
|
|
313 |
ACE.allow(ProjectRole.by_name('*anonymous'), 'read'),
|
|
|
314 |
]
|
|
|
315 |
|
|
|
316 |
And user1 is in the Member group, then all_allowed(tracker, user1)
|
|
|
317 |
will return:
|
|
|
318 |
|
|
|
319 |
set(['post', 'read'])
|
|
|
320 |
|
|
|
321 |
And all_allowed(tracker, ProjectRole.by_name('Developer')) will return:
|
|
|
322 |
|
|
|
323 |
set(['create', 'post', 'read'])
|
|
|
324 |
'''
|
|
|
325 |
from allura import model as M
|
|
|
326 |
anon = M.ProjectRole.anonymous(project)
|
|
|
327 |
auth = M.ProjectRole.authenticated(project)
|
|
|
328 |
if user_or_role is None:
|
|
|
329 |
user_or_role = c.user
|
|
|
330 |
if user_or_role is None:
|
|
|
331 |
user_or_role = anon
|
|
|
332 |
if isinstance(user_or_role, M.User):
|
|
|
333 |
user_or_role = M.ProjectRole.by_user(user_or_role, project)
|
|
|
334 |
if user_or_role is None:
|
|
|
335 |
user_or_role = auth # user is not member of project, treat as auth
|
|
|
336 |
roles = [user_or_role]
|
|
|
337 |
if user_or_role == anon:
|
|
|
338 |
pass # anon inherits nothing
|
|
|
339 |
elif user_or_role == auth:
|
|
|
340 |
roles += [anon] # auth inherits from anon
|
|
|
341 |
else:
|
|
|
342 |
roles += [auth, anon] # named group or user inherits from auth + anon
|
|
|
343 |
role_ids = RoleCache(Credentials.get(), roles).reaching_ids # match rules applicable to us
|
|
|
344 |
perms = set()
|
|
|
345 |
denied = defaultdict(set)
|
|
|
346 |
while obj: # traverse parent contexts
|
|
|
347 |
for role_id in role_ids:
|
|
|
348 |
for ace in obj.acl:
|
|
|
349 |
if ace.permission in denied[role_id]:
|
|
|
350 |
# don't consider permissions that were denied for this role
|
|
|
351 |
continue
|
|
|
352 |
if M.ACE.match(ace, role_id, ace.permission):
|
|
|
353 |
if ace.access == M.ACE.ALLOW:
|
|
|
354 |
perms.add(ace.permission)
|
|
|
355 |
else:
|
|
|
356 |
# explicit DENY overrides any ALLOW for this permission
|
|
|
357 |
# for this role_id in this ACL or parent(s) (but an ALLOW
|
|
|
358 |
# for a different role could still grant this permission)
|
|
|
359 |
denied[role_id].add(ace.permission)
|
|
|
360 |
obj = obj.parent_security_context()
|
|
|
361 |
if M.ALL_PERMISSIONS in perms:
|
|
|
362 |
return set([M.ALL_PERMISSIONS])
|
|
|
363 |
return perms
|
|
|
364 |
|
300 |
def require(predicate, message=None):
|
365 |
def require(predicate, message=None):
|
301 |
'''
|
366 |
'''
|
302 |
Example: require(has_access(c.app, 'read'))
|
367 |
Example: require(has_access(c.app, 'read'))
|
303 |
|
368 |
|
304 |
:param callable predicate: truth function to call
|
369 |
:param callable predicate: truth function to call
|