Orgs: show "My Organizations" in the user's menu

This is shown only when the user is member of or administrator for one or
more organizations, otherwise it's hidden.
This commit is contained in:
Sybren A. Stüvel 2017-08-24 12:35:31 +02:00
parent 95dc799692
commit b9ae4396e5
5 changed files with 50 additions and 3 deletions

View File

@ -361,6 +361,21 @@ class OrgManager:
projection={'_id': 1, 'full_name': 1, 'email': 1})
return list(users)
def user_has_organizations(self, user_id: bson.ObjectId) -> bool:
"""Returns True iff the user has anything to do with organizations.
That is, if the user is admin for and/or member of any organization.
"""
org_coll = current_app.db('organizations')
org_count = org_coll.count({'$or': [
{'admin_uid': user_id},
{'members': user_id}
]})
return bool(org_count)
def setup_app(app):
from . import patch, hooks

View File

@ -42,11 +42,14 @@ class UserClass(flask_login.UserMixin):
self.group_ids: typing.List[bson.ObjectId] = []
self.capabilities: typing.Set[str] = set()
# Lazily evaluated
self._has_organizations: typing.Optional[bool] = None
@classmethod
def construct(cls, token: str, db_user: dict) -> 'UserClass':
"""Constructs a new UserClass instance from a Mongo user document."""
user = UserClass(token)
user = cls(token)
user.user_id = db_user['_id']
user.roles = db_user.get('roles') or []
@ -63,7 +66,7 @@ class UserClass(flask_login.UserMixin):
return user
def __str__(self):
def __repr__(self):
return f'UserClass(user_id={self.user_id})'
def __getitem__(self, item):
@ -138,6 +141,15 @@ class UserClass(flask_login.UserMixin):
return not bool(require_roles) or bool(intersection)
def has_organizations(self) -> bool:
"""Returns True iff this user administers or is member of any organization."""
if self._has_organizations is None:
assert self.user_id
self._has_organizations = current_app.org_manager.user_has_organizations(self.user_id)
return bool(self._has_organizations)
class AnonymousUser(flask_login.AnonymousUserMixin, UserClass):
def __init__(self):
@ -149,6 +161,9 @@ class AnonymousUser(flask_login.AnonymousUserMixin, UserClass):
def has_cap(self, *capabilities):
return False
def has_organizations(self) -> bool:
return False
def _load_user(token) -> typing.Union[UserClass, AnonymousUser]:
"""Loads a user by their token.

View File

@ -4,6 +4,7 @@ import logging
import typing
import flask
import flask_login
import jinja2.filters
import jinja2.utils
import werkzeug.exceptions as wz_exceptions
@ -157,3 +158,4 @@ def setup_jinja_env(jinja_env):
jinja_env.filters['repr'] = repr
jinja_env.globals['url_for_node'] = do_url_for_node
jinja_env.globals['session'] = flask.session
jinja_env.globals['current_user'] = flask_login.current_user

View File

@ -62,7 +62,14 @@ li(class="dropdown")
title="My Projects")
i.pi-star
| My Projects
| {% if current_user.has_organizations() %}
li
a.navbar-item(
href="{{ url_for('pillar.web.organizations.index') }}"
title="My Organizations")
i.pi-users
| My Organizations
| {% endif %}
li
a.navbar-item(
href="{{ url_for('users.settings_profile') }}"

View File

@ -203,6 +203,8 @@ class OrganizationPatchTest(AbstractPillarTest):
org_doc = om.create_new_org('Хакеры', admin_uid, 25)
org_id = org_doc['_id']
self.assertFalse(om.user_has_organizations(member1_uid))
# Try the PATCH
resp = self.patch(f'/api/organizations/{org_id}',
json={
@ -218,6 +220,9 @@ class OrganizationPatchTest(AbstractPillarTest):
self.assertEqual([member1_uid], db_org['members'])
self.assertEqual([str(member1_uid)], new_org_doc['members'])
# The user should now have an organization
self.assertTrue(om.user_has_organizations(member1_uid))
def test_assign_users_access_denied(self):
self.enter_app_context()
@ -299,6 +304,7 @@ class OrganizationPatchTest(AbstractPillarTest):
org_id = org_doc['_id']
om.assign_users(org_id, ['member1@example.com', 'member2@example.com'])
self.assertTrue(om.user_has_organizations(member_uid))
# Try the PATCH to remove a known user
resp = self.patch(f'/api/organizations/{org_id}',
@ -318,6 +324,8 @@ class OrganizationPatchTest(AbstractPillarTest):
self.assertEqual([], new_org_doc['members'])
self.assertEqual(['member2@example.com'], new_org_doc['unknown_members'])
self.assertFalse(om.user_has_organizations(member_uid))
# Try the PATCH to remove an unknown user
resp = self.patch(f'/api/organizations/{org_id}',
json={