Ejemplo n.º 1
0
    def replace_sample_acls(self,
                            id_: UUID,
                            user: UserID,
                            new_acls: SampleACLOwnerless,
                            as_admin: bool = False) -> None:
        '''
        Completely replace a sample's ACLs. The owner cannot be changed.

        :param id_: the sample's ID.
        :param user: the user changing the ACLs.
        :param new_acls: the new ACLs.
        :param as_admin: Skip ACL checks.
        :raises NoSuchUserError: if any of the users in the ACLs do not exist.
        :raises NoSuchSampleError: if the sample does not exist.
        :raises UnauthorizedError: if the user does not have admin permission for the sample or
            the request attempts to change the owner.
        :raises SampleStorageError: if the sample could not be retrieved.
        '''
        _not_falsy(id_, 'id_')
        _not_falsy(user, 'user')
        _not_falsy(new_acls, 'new_acls')
        try:
            bad_users = self._user_lookup.invalid_users(
                _cast(List[UserID], []) + list(new_acls.admin) +
                list(new_acls.write) + list(new_acls.read))
            # let authentication errors propagate, not much to do
            # could add retries to the client
        except _user_lookup_mod.InvalidUserError as e:
            raise _NoSuchUserError(e.args[0]) from e
        except _user_lookup_mod.InvalidTokenError:
            raise ValueError(
                'user lookup token for KBase auth server is invalid, cannot continue'
            )
        if bad_users:
            raise _NoSuchUserError(', '.join([u.id for u in bad_users[:5]]))

        count = 0
        while count >= 0:
            if count >= 5:
                raise ValueError(
                    f'Failed setting ACLs after 5 attempts for sample {id_}')
            acls = self._storage.get_sample_acls(id_)
            self._check_perms(id_,
                              user,
                              _SampleAccessType.ADMIN,
                              acls,
                              as_admin=as_admin)
            new_acls = SampleACL(acls.owner, new_acls.admin, new_acls.write,
                                 new_acls.read)
            try:
                self._storage.replace_sample_acls(id_, new_acls)
                count = -1
            except _OwnerChangedError:
                count += 1
Ejemplo n.º 2
0
 def _check_for_bad_users(self, users: List[UserID]):
     try:
         bad_users = self._user_lookup.invalid_users(users)
         # let authentication errors propagate, not much to do
         # could add retries to the client
     except _user_lookup_mod.InvalidUserError as e:
         raise _NoSuchUserError(e.args[0]) from e
     except _user_lookup_mod.InvalidTokenError:
         raise ValueError('user lookup token for KBase auth server is invalid, cannot continue')
     if bad_users:
         raise _NoSuchUserError(', '.join([u.id for u in bad_users[:5]]))
Ejemplo n.º 3
0
    def get_user_workspaces(self, user: UserID) -> List[int]:
        '''
        Get a list of IDs of workspaces a user can read, including public workspaces.

        :param user: The username of the user whose workspaces will be returned.
        :returns: A list of workspace IDs.
        :raises NoSuchUserError: if the user does not exist.
        '''
        # May also want write / admin / no public ws
        try:
            ids = self._ws.administer({
                'command': 'listWorkspaceIDs',
                'user': _not_falsy(user, 'user').id,
                'params': {
                    'perm': 'r',
                    'excludeGlobal': 0
                }
            })
        except _ServerError as se:
            # this is pretty ugly, need error codes
            if 'not a valid user' in se.args[0]:
                raise _NoSuchUserError(se.args[0]) from se
            else:
                raise
        return sorted(ids['workspaces'] + ids['pub'])
Ejemplo n.º 4
0
def check_admin(user_lookup: KBaseUserLookup,
                token: Optional[str],
                perm: AdminPermission,
                method: str,
                log_fn: Callable[[str], None],
                as_user: UserID = None,
                skip_check: bool = False) -> bool:
    '''
    Check whether a user has admin privileges.
    The request is logged.

    :param user_lookup: the service to use to look up user information.
    :param token: the user's token, or None if the user is anonymous. In this case, if skip_check
        is false, an UnauthorizedError will be thrown.
    :param perm: the required administration permission.
    :param method: the method the user is trying to run. This is used in logging and error
      messages.
    :param logger: a function that logs information when called with a string.
    :param as_user: if the admin is impersonating another user, the username of that user.
    :param skip_check: Skip the administration permission check and return false.
    :returns: true if the user has the required administration permission, false if skip_check
        is true.
    :raises UnauthorizedError: if the user does not have the permission required.
    :raises InvalidUserError: if any of the user names are invalid.
    :raises UnauthorizedError: if any of the users names are valid but do not exist in the system.
    '''
    if skip_check:
        return False
    if not token:
        raise _UnauthorizedError(
            'Anonymous users may not act as service administrators.')
    _not_falsy(method, 'method')
    _not_falsy(log_fn, 'log_fn')
    if _not_falsy(perm, 'perm') == AdminPermission.NONE:
        raise ValueError(
            'what are you doing calling this method with no permission ' +
            'requirement? That totally makes no sense. Get a brain moran')
    if as_user and perm != AdminPermission.FULL:
        raise ValueError('as_user is supplied, but permission is not FULL')
    p, user = _not_falsy(user_lookup, 'user_lookup').is_admin(token)
    if p < perm:
        err = (f'User {user} does not have the necessary administration ' +
               f'privileges to run method {method}')
        log_fn(err)
        raise _UnauthorizedError(err)
    if as_user and user_lookup.invalid_users([as_user
                                              ]):  # returns list of bad users
        raise _NoSuchUserError(as_user.id)
    log_fn(
        f'User {user} is running method {method} with administration permission {p.name}'
        + (f' as user {as_user}' if as_user else ''))
    return True