Source code for resdk.resources.permissions

"""Permissions manager class."""

import copy

from ..constants import ALL_PERMISSIONS
from .utils import is_group, is_user


[docs]class PermissionsManager: """Helper class to manage permissions of the :class:`BaseResource`.""" #: (lazy loaded) list of permissions on current object _permissions = None _viewers = None _editors = None _owners = None def __init__(self, all_permissions, api_root, resolwe): """Initialize attributes.""" self.all_permissions = all_permissions self.permissions_api = api_root.permissions self.resolwe = resolwe def _fetch_users(self, users): if not isinstance(users, list): users = [users] return [user.id if is_user(user) else user for user in users] def _fetch_group(self, groups): if not isinstance(groups, list): groups = [groups] return [group.id if is_group(group) else group for group in groups] def _normalize_perm(self, perm): """Check that given list of permissions is valid for current object type.""" if perm is None: perm = "none" perm = str(perm).lower() if perm not in self.all_permissions: valid_perms = ", ".join(["'{}'".format(p) for p in self.all_permissions]) raise ValueError( "Invalid permission '{}' for type '{}'. Valid permissions are: {}".format( perm, self.__class__.__name__, valid_perms ) ) return perm def _set_permissions_new(self, perm, who_type, who=None): """Generate permissions payload and post it to the API.""" perm = self._normalize_perm(perm) payload = {} if who_type in ["users", "groups"]: for single in who: payload.setdefault(who_type, {})[single] = perm elif who_type == "public": payload[who_type] = perm else: raise KeyError("`who_type` must be 'users', 'groups' or 'public'.") self._permissions = self.permissions_api.post(payload)
[docs] def clear_cache(self): """Clear cache.""" self._permissions = None self._viewers = None self._editors = None self._owners = None
[docs] def fetch(self): """Fetch permissions from server.""" if self._permissions is None: self._permissions = self.permissions_api.get()
[docs] def set_user(self, user, perm): """Set ``perm`` permission to ``user``. When assigning permissions, only the highest permission needs to be given. Permission hierarchy is: - none (no permissions) - view - edit - share - owner Some examples:: collection = res.collection.get(...) # Add share, edit and view permission to John: collection.permissions.set_user('john', 'share') # Remove share and edit permission from John: collection.permissions.set_user('john', 'view') # Remove all permissions from John: collection.permissions.set_user('john', 'none') """ self._set_permissions_new(perm, "users", self._fetch_users(user))
[docs] def set_group(self, group, perm): """Set ``perm`` permission to ``group``. When assigning permissions, only the highest permission needs to be given. Permission hierarchy is: - none (no permissions) - view - edit - share - owner Some examples:: collection = res.collection.get(...) # Add share, edit and view permission to BioLab: collection.permissions.set_group('biolab', 'share') # Remove share and edit permission from BioLab: collection.permissions.set_group('biolab', 'view') # Remove all permissions from BioLab: collection.permissions.set_group('biolab', 'none') """ self._set_permissions_new(perm, "groups", self._fetch_group(group))
[docs] def set_public(self, perm): """Set ``perm`` permission for public. Public can only get two sorts of permissions: - none (no permissions) - view Some examples:: collection = res.collection.get(...) # Add view permission to public: collection.permissions.set_public('view') # Remove view permission from public: collection.permissions.set_public('none') """ self._set_permissions_new(perm, "public")
def _get_perms_by_type(self, perm_type): """Return only permissions with ``perm_type`` type.""" return [perm for perm in self._permissions if perm["type"] == perm_type] def _perms_to_string(self, perms): """Return string representation of given permissions array.""" perms = copy.copy(perms) # Order known permissions by importance. for known_perm in ALL_PERMISSIONS: if known_perm in perms: perms.remove(known_perm) perms.insert(0, known_perm) return ", ".join(map(str, perms)) def __repr__(self): """Show permissions.""" self.fetch() res = [] public_perms = self._get_perms_by_type("public") if public_perms: res.append( "Public: {}".format( self._perms_to_string(public_perms[0]["permissions"]) ) ) user_perms = self._get_perms_by_type("user") if user_perms: res.append("Users:") for perm in user_perms: res.append( " - {} (id={}): {}".format( perm["name"], perm["id"], self._perms_to_string(perm["permissions"]), ) ) group_perms = self._get_perms_by_type("group") if group_perms: res.append("Groups:") for perm in group_perms: res.append( " - {} (id={}): {}".format( perm["name"], perm["id"], self._perms_to_string(perm["permissions"]), ) ) return "\n".join(res) def _get_holders_with_perm(self, perm): """Get Users/Group/public names that have ``perm`` perm.""" # Prevent circular imports from .user import Group, User self.fetch() holders = [] for item in self._permissions: if perm in item["permissions"]: if item["type"] == "user": holders.append( User( self.resolwe, id=item["id"], first_name=item["name"], username=item["username"], ), ) elif item["type"] == "group": holders.append( Group(self.resolwe, id=item["id"], name=item["name"]) ) elif item["type"] == "public": holders.append( User(self.resolwe, username="public", first_name="Public") ) return holders @property def owners(self): """Get users with ``owner`` permission.""" if not self._owners: self._owners = self._get_holders_with_perm(perm="owner") return self._owners @property def editors(self): """Get users with ``edit`` permission.""" if not self._editors: self._editors = self._get_holders_with_perm(perm="edit") return self._editors @property def viewers(self): """Get users with ``view`` permission.""" if not self._viewers: self._viewers = self._get_holders_with_perm(perm="view") return self._viewers
[docs] def copy_from(self, source): """Copy permissions from some other object to self.""" if not source.permissions._permissions: source.permissions.fetch() payload = {} for entry in source.permissions._permissions: who_type = entry["type"] # We only need the highest permission + they are sorted --> take last one perm = entry["permissions"][-1] perm = self._normalize_perm(perm) if who_type == "user": payload.setdefault("users", {})[entry["id"]] = perm if who_type == "group": payload["groups"][entry["id"]] = perm elif who_type == "public": payload[who_type] = perm self.clear_cache() self._permissions = self.permissions_api.post(payload)