|
a/Allura/allura/model/auth.py |
|
b/Allura/allura/model/auth.py |
|
... |
|
... |
292 |
project = Project.query.get(_id=p, deleted=False)
|
292 |
project = Project.query.get(_id=p, deleted=False)
|
293 |
if project and self._id in [role.user_id for role in project.roles] and not project.shortname.startswith('u/'):
|
293 |
if project and self._id in [role.user_id for role in project.roles] and not project.shortname.startswith('u/'):
|
294 |
yield project
|
294 |
yield project
|
295 |
|
295 |
|
296 |
def role_iter(self):
|
296 |
def role_iter(self):
|
297 |
anon_role = ProjectRole.query.get(name='*anonymous')
|
297 |
anon_role = ProjectRole.anonymous()
|
298 |
auth_role = ProjectRole.query.get(name='*authenticated')
|
298 |
auth_role = ProjectRole.authenticated()
|
299 |
if anon_role:
|
299 |
if anon_role:
|
300 |
yield anon_role
|
300 |
yield anon_role
|
301 |
if self._id and auth_role:
|
301 |
if self._id and auth_role:
|
302 |
yield auth_role
|
302 |
yield auth_role
|
303 |
if self._id:
|
303 |
if self._id:
|
304 |
pr = self.project_role()
|
304 |
pr = self.project_role()
|
305 |
for role in pr.role_iter():
|
305 |
for role in pr.role_iter():
|
306 |
yield role
|
306 |
yield role
|
307 |
|
307 |
|
308 |
def project_role(self, project=None):
|
308 |
def project_role(self, project=None):
|
309 |
if project is None: project = c.project
|
309 |
if project is None: project = c.project.root_project
|
310 |
with h.push_config(c, project=project, user=self):
|
310 |
with h.push_config(c, project=project, user=self):
|
311 |
if self._id is None:
|
311 |
if self._id is None:
|
312 |
return ProjectRole.query.get(name='*anonymous')
|
312 |
return ProjectRole.anonymous(project)
|
313 |
pr = ProjectRole.query.get(user_id=self._id)
|
|
|
314 |
if pr: return pr
|
|
|
315 |
try:
|
|
|
316 |
obj = ProjectRole(user_id=self._id)
|
|
|
317 |
session(obj).insert_now(obj, state(obj))
|
|
|
318 |
self.projects.append(c.project._id)
|
|
|
319 |
return obj
|
|
|
320 |
except pymongo.errors.DuplicateKeyError:
|
|
|
321 |
session(obj).expunge(obj)
|
|
|
322 |
return ProjectRole.query.get(user_id=self._id)
|
313 |
return ProjectRole.upsert(user_id=self._id, project_id=project._id)
|
323 |
|
314 |
|
324 |
def set_password(self, new_password):
|
315 |
def set_password(self, new_password):
|
325 |
return plugin.AuthenticationProvider.get(request).set_password(
|
316 |
return plugin.AuthenticationProvider.get(request).set_password(
|
326 |
self, self.password, new_password)
|
317 |
self, self.password, new_password)
|
327 |
|
318 |
|
|
... |
|
... |
331 |
|
322 |
|
332 |
class ProjectRole(MappedClass):
|
323 |
class ProjectRole(MappedClass):
|
333 |
class __mongometa__:
|
324 |
class __mongometa__:
|
334 |
session = project_orm_session
|
325 |
session = project_orm_session
|
335 |
name='user'
|
326 |
name='user'
|
336 |
unique_indexes = [ ('name', 'user_id') ]
|
327 |
unique_indexes = [ ('user_id', 'project_id', 'name') ]
|
337 |
|
328 |
|
338 |
_id = FieldProperty(S.ObjectId)
|
329 |
_id = FieldProperty(S.ObjectId)
|
|
|
330 |
user_id = FieldProperty(S.ObjectId, if_missing=None) # if role is a user
|
|
|
331 |
project_id = FieldProperty(S.ObjectId, if_missing=lambda:c.project._id)
|
339 |
name = FieldProperty(str)
|
332 |
name = FieldProperty(str)
|
340 |
user_id = FieldProperty(S.ObjectId, if_missing=None) # if role is a user
|
|
|
341 |
roles = FieldProperty([S.ObjectId])
|
333 |
roles = FieldProperty([S.ObjectId])
|
|
|
334 |
|
|
|
335 |
def __init__(self, **kw):
|
|
|
336 |
assert 'project_id' in kw, 'Project roles must specify a project id'
|
|
|
337 |
super(ProjectRole, self).__init__(**kw)
|
342 |
|
338 |
|
343 |
def display(self):
|
339 |
def display(self):
|
344 |
if self.name: return self.name
|
340 |
if self.name: return self.name
|
345 |
if self.user_id:
|
341 |
if self.user_id:
|
346 |
u = self.user
|
342 |
u = self.user
|
|
... |
|
... |
349 |
else: uname = u._id
|
345 |
else: uname = u._id
|
350 |
return '*user-%s' % uname
|
346 |
return '*user-%s' % uname
|
351 |
return '**unknown name role: %s' % self._id # pragma no cover
|
347 |
return '**unknown name role: %s' % self._id # pragma no cover
|
352 |
|
348 |
|
353 |
@classmethod
|
349 |
@classmethod
|
|
|
350 |
def by_user(cls, user=None, project=None):
|
|
|
351 |
if user is None: user = c.user
|
|
|
352 |
if project is None: project = c.project.root_project
|
|
|
353 |
return cls.query.get(user_id=user._id, project_id=project._id)
|
|
|
354 |
|
|
|
355 |
@classmethod
|
|
|
356 |
def by_name(cls, name, project=None):
|
|
|
357 |
if project is None: project = c.project.root_project
|
|
|
358 |
return cls.query.get(name=name, project_id=project._id)
|
|
|
359 |
|
|
|
360 |
@classmethod
|
|
|
361 |
def anonymous(cls, project=None):
|
|
|
362 |
if project is None: project = c.project.root_project
|
|
|
363 |
return cls.by_name('*anonymous', project)
|
|
|
364 |
|
|
|
365 |
@classmethod
|
|
|
366 |
def authenticated(cls, project=None):
|
|
|
367 |
if project is None: project = c.project.root_project
|
|
|
368 |
return cls.by_name('*authenticated', project)
|
|
|
369 |
|
|
|
370 |
@classmethod
|
354 |
def upsert(cls, **kw):
|
371 |
def upsert(cls, **kw):
|
|
|
372 |
obj = cls.query.get(**kw)
|
|
|
373 |
if obj is not None: return obj
|
355 |
try:
|
374 |
try:
|
356 |
obj = cls(**kw)
|
375 |
obj = cls(**kw)
|
357 |
session(obj).insert_now(obj, state(obj))
|
376 |
session(obj).insert_now(obj, state(obj))
|
358 |
except pymongo.errors.DuplicateKeyError:
|
377 |
except pymongo.errors.DuplicateKeyError:
|
359 |
session(obj).expunge(obj)
|
378 |
session(obj).expunge(obj)
|
|
... |
|
... |
368 |
return True
|
387 |
return True
|
369 |
return False # pragma no cover
|
388 |
return False # pragma no cover
|
370 |
|
389 |
|
371 |
@property
|
390 |
@property
|
372 |
def user(self):
|
391 |
def user(self):
|
|
|
392 |
if self.user_id is None: return None
|
373 |
return User.query.get(_id=self.user_id)
|
393 |
return User.query.get(_id=self.user_id)
|
374 |
|
394 |
|
|
|
395 |
@classmethod
|
|
|
396 |
def roles_reachable_from(cls, *roots):
|
|
|
397 |
to_visit = list(roots)
|
|
|
398 |
visited = set()
|
|
|
399 |
while to_visit:
|
|
|
400 |
pr = to_visit.pop(0)
|
|
|
401 |
if pr in visited: continue
|
|
|
402 |
visited.add(pr)
|
|
|
403 |
yield pr
|
|
|
404 |
to_visit += cls.query.find(dict(_id={'$in':pr.roles})).all()
|
|
|
405 |
|
|
|
406 |
@classmethod
|
|
|
407 |
def roles_that_reach(cls, *roots):
|
|
|
408 |
to_visit = list(roots)
|
|
|
409 |
visited = set()
|
|
|
410 |
while to_visit:
|
|
|
411 |
pr = to_visit.pop(0)
|
|
|
412 |
if pr in visited: continue
|
|
|
413 |
visited.add(pr)
|
|
|
414 |
yield pr
|
|
|
415 |
to_visit += cls.query.find(dict(roles=pr._id)).all()
|
|
|
416 |
|
375 |
def users_with_role(self):
|
417 |
def users_with_role(self):
|
376 |
return [pr.user for pr in ProjectRole.query.find({'roles':self._id}).all() if pr.user_id]
|
418 |
return [
|
|
|
419 |
role.user for role in self.roles_that_reach(self) if role.user_id ]
|
377 |
|
420 |
|
378 |
def role_iter(self, visited=None):
|
421 |
def role_iter(self):
|
379 |
if visited is None: visited = set()
|
422 |
return self.roles_reachable_from(self)
|
380 |
if self._id not in visited:
|
|
|
381 |
yield self
|
|
|
382 |
visited.add(self._id)
|
|
|
383 |
for rid in self.roles:
|
|
|
384 |
pr = ProjectRole.query.get(_id=rid)
|
|
|
385 |
if pr is None: continue
|
|
|
386 |
for rr in pr.role_iter(visited):
|
|
|
387 |
yield rr
|
|
|
388 |
|
423 |
|