def update(self, token, user: UserModelUpsert) -> UserModel: """ Update an existing user. If successfull, a new user model is returned with the latest version of the user data. """ response = self.requests.put( self.url_for(f"/user/{user.id}"), data=user.json(), headers=self.create_default_header(token), ) if response.status_code == 404: raise DoesNotExist(response.text) if response.status_code == 500: raise ServerError(response.text) if response.status_code != 200: raise ServerError(f"Wrong status. Expected 200. Got {response.status_code}") user = UserModel.parse_obj(response.json()) # Add or update the cached user # self.cache.set_user(user) return user # TODO Check other status_codes
def create(self, token: str, user: UserModelUpsert, fields: XFieldList = None) -> UserModel: """ Creates a new user """ headers = self.create_default_header(token, fields=fields) data = user.json() url = self.url_for("/users/") result = self.requests.post(url, data=data, headers=headers) if result.status_code == 201: # User created successfully. We cannot create the user directly # with the password, so we have to set the password in a second step. # # TODO: Why not able to set the password directly in the # REST call? Check is and change it, if possible. user_model = UserModel.parse_obj(result.json()) if not user.password: logger.debug("Created user without password.") else: self.set_password(token=token, user_id=user_model.id, new_password=user.password) return user_model if result.status_code == 409: raise ConstraintViolation(result.text) if result.status_code == 500: raise ServerError(result.text) raise ServerError(f"Unknown error. [{result.status_code}] {result.text}")
def all( self, token, fields: XFieldList = None, offset: Optional[int] = None, count: Optional[int] = None, **kwargs, ) -> UserList: """ Get all users in the database. Returns a list of :class:`UserModel` instances. If ``X-Filter-Fields`` is provided, only attributes are send back that are in the list. If an attribute has no value it will be omitted. :Route: ``GET /users/`` :param str token: The authentification token :param XFieldList fields: A list of fieldnames that should be send back. If omitted all attributes will be send back. *[Optional]* :offset: Starting with the n-th element in the database. If omitted, the list will start with the first element in the database. :count: Limits the number of returned items. If omitted, it will fallback to the configured maximum number of items. The number of returned items may of course be smaller than count. :kwargs: These named parameters will be added as query parameters :return: The requested Users :rtype: A list of :class:`UserModel` objects. :raises InsufficientRights: If the requesting user has not the permission. :raises TokenExpired: is the token has expired. :raises ServerError: if an unpredicted exception occurred. """ headers = self.create_default_header(token, fields=fields) url = self.url_for("/users/") params = {} if offset: params["offset"] = offset if count: params["count"] = count result = self.requests.get(url, headers=headers, params=params) if result.status_code == 404: return [] if result.status_code == 401: raise ValueError("Not authenticated") if result.status_code != 200: raise ServerError("Got an server error.") data = result.json() user_data = data.get("result", None) if user_data is None: raise ServerError("No content provided.") return parse_obj_as(List[UserModel], user_data)
def generate_token_for(self, login: str, password: str) -> BearerTokenData: """ Log into the server with the given credentials. If successfull, the it returns the access token. :param str login: The user login :param str password: The user password :returns: The access token :rtype: BearerTokenData :raises: DoesNotExist, ServerError """ logger.info("Login with account %s to get bearer token.", login) data = {"login": login, "password": password} headers = {"accept": "application/json"} response = self.requests.post(self.url_for("/login/"), data=data, headers=headers) if response.status_code == 404: raise DoesNotExist(f"User with login {login} does not exist.") if response.status_code != 200: raise ServerError(response.text) return BearerTokenData.parse_obj(response.json())
def delete_all(self, token) -> None: """ Delete all users from the database """ headers = self.create_default_header(token) url = self.url_for("/users/") result = self.requests.delete(url, headers=headers) if result.status_code != 200: raise ServerError(f"Wrong status. Expected 200. Got {result.status_code}")
def create(self, token, right: RightModel) -> RightModel: """ Creates a new right """ headers = self.create_default_header(token) data = right.json() url = self.url_for("/rights/") result = self.requests.post(url, data=data, headers=headers) if result.status_code == 201: return RightModel.parse_obj(result.json()) if result.status_code == 409: raise ConstraintViolation(result.text) if result.status_code == 500: raise ServerError(result.text) raise ServerError( f"Unknown error. [{result.status_code}] {result.text}")
def delete_all(self, token): """ Delete all digicube rights. This operation is atomic. A successful operation is indicated by a 200 status. If the operation fails, a ``ServerError`` is thrown. .. warning:: This operation cannot be undone. So be shure you know, what you are doing. """ headers = self.create_default_header(token) url = self.url_for("/rights/") result = self.requests.delete(url, headers=headers) if result.status_code != 200: raise ServerError(result.text)
def refresh_token(self, token) -> BearerTokenData: """ Requesting a new bearer token. """ logger.info("Refreshing bearer token. Old token is %s", token) url = self.url_for("/token/") headers = self.create_default_header(token) response = self.requests.post(url, headers=headers) if response.status_code == 200: data = BearerTokenData.parse_obj(response.json()) return data if response.status_code == 401: raise TokenExpired("Your auth token has expired.") raise ServerError("A server error occurred.")
def delete(self, token, user_id: int) -> Optional[UserModel]: """ Deletes a user from the database """ # TODO: Clear from cache (or wait for expiration of the key) headers = self.create_default_header(token) url = self.url_for(f"/user/{user_id}") result = self.requests.delete(url, headers=headers) if result.status_code == 404: raise DoesNotExist(f"User with user id {user_id} not found.") if result.status_code != 200: raise ServerError(f"Wrong status. Expected 200. Got {result.status_code}") return UserModel.parse_obj(result.json())
def get_roles(self, token, right: RightModel) -> List[RoleModel]: # TODO: Use Filter fields """ Get all roles associated with this right """ headers = self.create_default_header(token) url = self.url_for(f"/right/{right.id}/roles/") result = self.requests.get(url, headers=headers) if result.status_code == 404: raise DoesNotExist(result.text) if result.status_code == 200: return [RoleModel.parse_obj(role) for role in result.json()] raise ServerError(result.text)
def get_rights(self, token: str, user_id: int) -> List[str]: """ Get all rights. The rest method returns an array of right names and not json objects. """ headers = self.create_default_header(token) url = self.url_for(f"/user/{user_id}/rights/") result = self.requests.get(url, headers=headers) if result.status_code == 401: raise TokenExpired() if result.status_code == 404: raise DoesNotExist(result.text) if result.status_code != 200: raise ServerError(f"Wrong status. Expected 200. Got {result.status_code}") user_rights = result.json() return user_rights
def get_roles(self, token, user: UserModel) -> List[RoleModel]: """ Get all roles for user. """ if user is None: raise ValueError("No user provided") if user.id is None: raise ValueError("Invalid user provided. No id.") # TODO Filter fields as parameter headers = self.create_default_header(token) url = self.url_for(f"/user/{user.id}/roles/") result = self.requests.get(url, headers=headers) if result.status_code == 404: raise DoesNotExist(result.text) if result.status_code != 200: raise ServerError(f"Wrong status. Expected 200. Got {result.status_code}") return parse_obj_as(List[RoleModel], result.json())