def get_all(self, request: 'th_Request') -> responses.Response: validator = validation.Dict({ "user_id": validation.Integer(allow_none=True), "banner_id": validation.Integer(allow_none=True), }, allow_none=True, allow_empty=True, allow_all_defined_keys_missing=True, allow_undefined_keys=not self._strict_requests) try: # Validation try: validator.validate(request.body) except validation.Error as ve: return responses.Unprocessable(ve.errors) # Filters user_id_filter = None if request.body is None else request.body.get("user_id") banner_id_filter = None if request.body is None else request.body.get("banner_id") # Authorization # TODO check whatever is going on here auth_response = self._s_auth.authorize(Action.USERS_ACCESS_BANNED, request.user) if isinstance(auth_response, responses.OKEmpty): # Can access all bans result = self._m_users_bans.get_all(user_id_filter, banner_id_filter) return responses.OK(result) else: # Can only access visible bans if isinstance(request.user, Registered): result = self._m_users_bans.get_all_visible(request.user.user_id, user_id_filter, banner_id_filter) return responses.OK(result) else: # An unregsitered user cannot get banned nor create bans return responses.OK([]) except SQLAlchemyError as sqlae: return responses.DatabaseException(sqlae)
def get_all(self, request: 'th_Request') -> responses.Response: validator = validation.Dict( { "user_id": validation.Integer(allow_none=True), "room_id": validation.Integer(allow_none=True) }, allow_none=True, allow_empty=True, allow_all_defined_keys_missing=True, allow_undefined_keys=not self._strict_requests) try: # Validation try: validator.validate(request.body) except validation.Error as ve: return responses.Unprocessable(ve.errors) # Filters user_id_filter = None if request.body is None else request.body.get( "user_id") room_id_filter = None if request.body is None else request.body.get( "room_id") # Get user's ID if registered user_id = None if isinstance(request.user, Registered): user_id = request.user.user_id # Authorization auth_response = self._s_auth.authorize(Action.ROOMS_POSTS_ACCESS, request.user) if isinstance(auth_response, responses.OKEmpty): result = self._m_posts.get_all(False, False, False, user_id, room_id_filter, user_id_filter) return responses.OK(result) else: # Filters by authorization auth_response = self._s_auth.authorize( Action.ROOMS_ACCESS_PUBLIC, request.user) exclude_public = not isinstance(auth_response, responses.OKEmpty) auth_response = self._s_auth.authorize( Action.ROOMS_ACCESS_PRIVATE, request.user) exclude_private = not isinstance(auth_response, responses.OKEmpty) auth_response = self._s_auth.authorize( Action.ROOMS_ACCESS_BANNED, request.user) exclude_banned = not isinstance(auth_response, responses.OKEmpty) result = self._m_posts.get_all(exclude_banned, exclude_public, exclude_private, user_id, room_id_filter, user_id_filter) return responses.OK(result) except SQLAlchemyError as sqlae: return responses.DatabaseException(sqlae)
def get(self, request: 'th_Request') -> responses.Response: validator = validation.Dict( {"room_id": validation.Integer()}, allow_undefined_keys=not self._strict_requests) try: # Validation try: validator.validate(request.body) except validation.Error as ve: return responses.Unprocessable(ve.errors) room_id = request.body["room_id"] # Queries for authorization try: orm_room_ban = self._m_rooms_bans.get(room_id) except NoResultFound: return responses.NotFoundByID("room_id") try: orm_room = self._m_rooms.get(room_id) except NoResultFound: return responses.NotFoundByID("room_id") # Authorization auth_response = self._s_auth.authorize( Action.ROOMS_BANS_ACCESS, request.user, [orm_room.user_id, orm_room_ban.banner_id]) if not isinstance(auth_response, responses.OKEmpty): return auth_response return responses.OK(orm_room_ban) except SQLAlchemyError as sqlae: return responses.DatabaseException(sqlae)
def get(self, request: 'th_Request') -> responses.Response: validator = validation.Dict( {"user_id": validation.Integer()}, allow_undefined_keys=not self._strict_requests) try: # Validation try: validator.validate(request.body) except validation.Error as ve: return responses.Unprocessable(ve.errors) user_id = request.body["user_id"] # Query to find the user try: orm_user = self._m_users.get(user_id) except NoResultFound: return responses.NotFoundByID("user_id") # Check if user is banned orm_user_ban = None try: orm_user_ban = self._m_users_bans.get(user_id) except NoResultFound: pass # User is not banned # Authorization (can see banned users or not?) auth_action = Action.USERS_ACCESS_NOTBANNED if orm_user_ban is None else Action.USERS_ACCESS_BANNED auth_response = self._s_auth.authorize(auth_action, request.user, user_id) if not isinstance(auth_response, responses.OKEmpty): return auth_response return responses.OK(orm_user) except SQLAlchemyError as sqlae: return responses.DatabaseException(sqlae)
def get_all(self, request: 'th_Request'): validator = validation.Dict({ "user_id": validation.Integer(allow_none=True), "room_id": validation.Integer(allow_none=True), }, allow_none=True, allow_empty=True, allow_all_defined_keys_missing=True, allow_undefined_keys=not self._strict_requests) try: # Validation try: validator.validate(request.body) except validation.Error as ve: return responses.Unprocessable(ve.errors) # Filters room_id_filter = None if request.body is None else request.body.get("room_id") user_id_filter = None if request.body is None else request.body.get("user_id") # Authorization # TODO check whatever is going on here # Can user access all rooms users? auth_response = self._s_auth.authorize(Action.ROOMS_USERS_ACCESS, request.user) if isinstance(auth_response, responses.OKEmpty): # yes result = self._m_rooms_users.get_all(False, False, False, room_id_filter, user_id_filter) return responses.OK(result) else: # Only return visible # Filters by authorization user_id = None if isinstance(request.user, Registered): user_id = request.user.user_id auth_response = self._s_auth.authorize(Action.ROOMS_ACCESS_PUBLIC, request.user) exclude_public = not isinstance(auth_response, responses.OKEmpty) auth_response = self._s_auth.authorize(Action.ROOMS_ACCESS_PRIVATE, request.user) exclude_private = not isinstance(auth_response, responses.OKEmpty) auth_response = self._s_auth.authorize(Action.ROOMS_ACCESS_BANNED, request.user) exclude_banned = not isinstance(auth_response, responses.OKEmpty) result = self._m_rooms_users.get_all( exclude_banned, exclude_public, exclude_private, user_id, room_id_filter, user_id_filter ) return responses.OK(result) except SQLAlchemyError as sqlae: return responses.DatabaseException(sqlae)
def get_all(self, request: 'th_Request') -> responses.Response: validator = validation.Dict( {}, allow_none=True, allow_empty=True, allow_all_defined_keys_missing=True, allow_undefined_keys=not self._strict_requests) # No keys since there's nothing to filter by (login is 'secret') try: # Validation try: validator.validate(request.body) except validation.Error as ve: return responses.Unprocessable(ve.errors) auth_response = self._s_auth.authorize( [Action.USERS_ACCESS_NOTBANNED, Action.USERS_ACCESS_BANNED], request.user) if isinstance(auth_response, responses.OKEmpty): # Can access all result = self._m_users.get_all() return responses.OK(result) auth_response = self._s_auth.authorize( Action.USERS_ACCESS_NOTBANNED, request.user) if isinstance(auth_response, responses.OKEmpty): # Can only access unbanned result = self._m_users.get_all_unbanned() return responses.OK(result) auth_response = self._s_auth.authorize(Action.USERS_ACCESS_BANNED, request.user) if isinstance(auth_response, responses.OKEmpty): # Can only access banned result = self._m_users.get_all_banned() return responses.OK(result) return auth_response except SQLAlchemyError as sqlae: return responses.DatabaseException(sqlae)
def from_token_string(self, token: str = None) -> responses.Response: if token is None: return responses.OK(user.Guest(role=roles.Roles.GUEST)) # Validate token try: token_valid = jwt.Token.from_string(token) except jwt.Error as jwte: return responses.Unauthorized({"token": jwte.errors}) # Query for token verification try: orm_user = self._m_users.get(token_valid.claims.user_id) except NoResultFound: return responses.Unauthorized( {"token": ["Token's user does not exist"]}) except MultipleResultsFound as mrf: return responses.InternalException(mrf, {"user_id": ["Not unique"]}) except SQLAlchemyError as sqlae: return responses.DatabaseException(sqlae) # Verify token try: token_valid.verify(self._public_key, orm_user.passhash, self._tokens_lifetime) except jwt.Error as jwte: return responses.Unauthorized({"token": jwte.errors}) # Validate user's role try: role = roles.Roles.id_to_role(orm_user.role) except KeyError as ke: return responses.InternalException(ke, {"role": ["Does not exist"]}) return responses.OK(user.Registered(role=role, user_id=orm_user.id))
def get(self, request: 'th_Request') -> responses.Response: validator = validation.Dict( { "post_id": validation.Integer(), }, allow_undefined_keys=not self._strict_requests) try: # Validation try: validator.validate(request.body) except validation.Error as ve: return responses.Unprocessable(ve.errors) post_id = request.body["post_id"] # Queries for authorization try: orm_post = self._m_posts.get(post_id) except NoResultFound: return responses.NotFoundByID("post_id") try: orm_room = self._m_rooms.get(orm_post.room_id) except NoResultFound: return responses.NotFoundByID("room_id") orm_room_users = self._m_rooms_users.get_all_by_room(orm_room.id) orm_room_ban = None try: orm_room_ban = self._m_rooms_bans.get(orm_post.room_id) except NoResultFound: pass # Room is not banned # Authorization if orm_room_ban is not None: # can the user access the banned room? auth_response = self._s_auth.authorize( Action.ROOMS_ACCESS_BANNED, request.user, orm_room.user_id) if not isinstance(auth_response, responses.OKEmpty): return auth_response # yes # TODO check this out auth_response = self._s_auth.authorize( Action.ROOMS_ACCESS_PUBLIC if orm_room.is_public else Action.ROOMS_ACCESS_PRIVATE, request.user, [orm_room.user_id] + [orm_room_user.user_id for orm_room_user in orm_room_users]) if not isinstance(auth_response, responses.OKEmpty): return auth_response return responses.OK(orm_post) except SQLAlchemyError as sqlae: return responses.DatabaseException(sqlae)
def get(self, request: 'th_Request') -> responses.Response: validator = validation.Dict({ "room_id": validation.Integer(), "user_id": validation.Integer() }, allow_undefined_keys=not self._strict_requests) try: # Validation try: validator.validate(request.body) except validation.Error as ve: return responses.Unprocessable(ve.errors) room_id = request.body["room_id"] user_id = request.body["user_id"] # Queries for authorization try: orm_room = self._m_rooms.get(room_id) except NoResultFound: return responses.NotFoundByID("room_id") orm_room_users = self._m_rooms_users.get_all_by_room(room_id) orm_room_ban = None try: orm_room_ban = self._m_rooms_bans.get(room_id) except NoResultFound: pass # Room isn't banned # Authorization if orm_room_ban is not None: # If room is banned auth_response = self._s_auth.authorize(Action.ROOMS_ACCESS_BANNED, request.user, orm_room.user_id) if not isinstance(auth_response, responses.OKEmpty): return auth_response # room is not banned auth_response = self._s_auth.authorize( Action.ROOMS_ACCESS_PUBLIC if orm_room.is_public else Action.ROOMS_ACCESS_PRIVATE, request.user, # Room's creator + users added to the room [orm_room.user_id] + [orm_room_user.user_id for orm_room_user in orm_room_users] ) if not isinstance(auth_response, responses.OKEmpty): return auth_response try: return responses.OK(self._m_rooms_users.get(room_id, user_id)) except NoResultFound: return responses.NotFoundByID("user_id") except SQLAlchemyError as sqlae: return responses.DatabaseException(sqlae)
def from_flask(self, flask_request: 'th_flask_request', additional_json: dict = None) -> responses.Response: token = flask_request.headers.get("token") users_response = self._s_users.from_token_string(token) if not isinstance(users_response, responses.OK): return users_response user = users_response.object if flask_request.method == "GET": body = flask_request.args.to_dict() # Convert str to int, if int for key in body: try: body[key] = int(body[key]) except ValueError: pass else: data = flask_request.get_data() if len(data) < 1: body = None else: try: body = json.loads(data.decode("utf-8")) except json.JSONDecodeError: if self._strict_requests: return responses.Unprocessable({"json": "Corrupt"}) else: body = None if additional_json is not None: if body is None: body = {} for key in additional_json: body[key] = additional_json[key] result = request.Request(user, body) return responses.OK(result)
def login(self, request: 'th_Request') -> responses.Response: validator = validation.Dict( { "login": validation.String(), "password": validation.String() }, allow_undefined_keys=not self._strict_requests) try: # Validation try: validator.validate(request.body) except validation.Error as ve: return responses.Unprocessable(ve.errors) # Authorization auth_response = self._s_auth.authorize(Action.LOGIN, request.user) if not isinstance(auth_response, responses.OKEmpty): return auth_response # Query # Find user by login try: user = self._m_users.get_by_login(request.body["login"]) except NoResultFound: return responses.NotFoundByID("login") # Check if user is banned try: self._m_users_bans.get(user.id) return responses.Forbidden() except NoResultFound: # Not banned, ok pass # Verify password try: self._password_hasher.verify(user.passhash, request.body["password"]) except VerifyMismatchError: return responses.Unauthorized( {"all": ["Invalid login or password"]}) except (VerificationError, InvalidHash) as argonerr: return responses.InternalException( argonerr, {"password": ["Hashing error"]}) # Check rehash if self._password_hasher.check_needs_rehash(user.passhash): try: passhash_new = self._password_hasher.hash( request.body["password"]) self._m_users.update(user.id, passhash=passhash_new) except (HashingError, SQLAlchemyError, NoResultFound, MultipleResultsFound) as err: # Not crucial logging.exception(err) # Generate and return token token = jwt.Token.generate(jwt.Claims(user.id), self._private_key, user.passhash) return responses.OK({"token": token.to_string()}) except SQLAlchemyError as sqlae: return responses.DatabaseException(sqlae)