Example #1
0
	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)
Example #2
0
    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)
Example #3
0
    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)
Example #4
0
    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)
Example #5
0
	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)
Example #6
0
    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)
Example #7
0
    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))
Example #8
0
    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)
Example #9
0
	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)
Example #10
0
    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)
Example #11
0
    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)