Beispiel #1
0
	def create(self, request: 'th_Request') -> responses.Response:
		validator = validation.Dict({
			"user_id": validation.Integer(),
			"reason": validation.String(length_min=orm.UsersBans.REASON_LEN_MIN, length_max=orm.UsersBans.REASON_LEN_MAX)
		}, 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.USERS_BANS_CREATE, request.user)
			if not isinstance(auth_response, responses.OKEmpty): return auth_response

			# Get the user's ID from request (Which gets it's user info from a token)
			if not isinstance(request.user, Registered): return responses.UnauthorizedNotLoggedIn()
			user: Registered = request.user

			# Query
			try:
				self._m_users_bans.create(request.body["user_id"], user.user_id, request.body["reason"])
				return responses.Created()
			except IntegrityError: return responses.NotFoundByID("user_id")
		except SQLAlchemyError as sqlae:
			return responses.DatabaseException(sqlae)
Beispiel #2
0
	def update(self, request: 'th_Request') -> responses.Response:
		validator = validation.Dict({
			"user_id": validation.Integer(),
			"reason": validation.String(length_min=orm.UsersBans.REASON_LEN_MIN, length_max=orm.UsersBans.REASON_LEN_MAX)
		}, 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 for authorization
			try: orm_user_ban = self._m_users_bans.get(user_id)
			except NoResultFound: return responses.NotFoundByID("user_id")

			# Authorization
			auth_response = self._s_auth.authorize(Action.USERS_BANS_UPDATE, request.user, orm_user_ban.banner_id)
			if not isinstance(auth_response, responses.OKEmpty): return auth_response

			# Query
			try:
				self._m_users_bans.update(user_id, request.body["reason"])
				return responses.OKEmpty()
			except NoResultFound: return responses.NotFoundByID("user_id")
		except SQLAlchemyError as sqlae:
			return responses.DatabaseException(sqlae)
Beispiel #3
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)
Beispiel #4
0
	def get_all(self, request: 'th_Request') -> responses.Response:
		validator = validation.Dict({
			"user_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")

			# 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.get_all(
				exclude_banned, exclude_public, exclude_private,
				user_id, user_id_filter
			)
			return responses.OK(result)
		except SQLAlchemyError as sqlae:
			return responses.DatabaseException(sqlae)
Beispiel #5
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)
Beispiel #6
0
	def update(self, request: 'th_Request') -> responses.Response:
		validator = validation.Dict({
			"room_id": validation.Integer(),
			"title": validation.String(length_min=orm.Rooms.TITLE_LEN_MIN, length_max=orm.Rooms.TITLE_LEN_MAX),
		})
		try:
			# Validation
			try: validator.validate(request.body)
			except validation.Error as ve: return responses.Unprocessable(ve.errors)

			room_id = request.body["room_id"]

			# Query for authorization
			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_UPDATE_TITLE, request.user, orm_room.user_id)
			if not isinstance(auth_response, responses.OKEmpty): return auth_response

			try:
				self._m_rooms.update(room_id, request.body["title"])
				return responses.OKEmpty()
			except NoResultFound: return responses.NotFoundByID("room_id")
		except SQLAlchemyError as sqlae:
			return responses.DatabaseException(sqlae)
Beispiel #7
0
	def create(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"]

			# Query for authorization
			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_USERS_CREATE, request.user, orm_room.user_id)
			if not isinstance(auth_response, responses.OKEmpty): return auth_response

			# Query
			try:
				self._m_rooms_users.create(room_id, user_id)
				return responses.Created()
			except IntegrityError: return responses.NotFoundByID("user_id")
		except SQLAlchemyError as sqlae:
			return responses.DatabaseException(sqlae)
Beispiel #8
0
	def create(self, request: 'th_Request') -> responses.Response:
		validator = validation.Dict({
			"title": validation.String(length_min=orm.Rooms.TITLE_LEN_MIN, length_max=orm.Rooms.TITLE_LEN_MAX),
			"is_public": validation.Boolean()
		})
		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.ROOMS_CREATE, request.user)
			if not isinstance(auth_response, responses.OKEmpty): return auth_response

			# Get the user's ID from request (Which gets it's user info from a token)
			if not isinstance(request.user, Registered): return responses.UnauthorizedNotLoggedIn()
			user: Registered = request.user

			# Query
			try:
				self._m_rooms.create(user.user_id, request.body["is_public"], request.body["title"])
				return responses.Created()
			except IntegrityError: return responses.NotFoundByID("user_id")
		except SQLAlchemyError as sqlae:
			return responses.DatabaseException(sqlae)
Beispiel #9
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)
Beispiel #10
0
    def delete_self(self, request: 'th_Request'):
        validator = validation.Dict(
            {},
            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)

            # Authorization
            auth_response = self._s_auth.authorize(Action.USERS_DELETE_SELF,
                                                   request.user)
            if not isinstance(auth_response, responses.OKEmpty):
                return auth_response

            # Get the user's ID from request (Which gets it's user info from a token)
            if not isinstance(request.user, Registered):
                return responses.UnauthorizedNotLoggedIn()
            user: Registered = request.user

            # Query
            try:
                self._m_users.delete(user.user_id)
                return responses.OKEmpty()
            except NoResultFound:
                return responses.NotFoundByID("user_id")
        except SQLAlchemyError as sqlae:
            return responses.DatabaseException(sqlae)
Beispiel #11
0
    def delete(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"]

            # Authorization
            auth_response = self._s_auth.authorize(Action.USERS_DELETE,
                                                   request.user, user_id)
            if not isinstance(auth_response, responses.OKEmpty):
                return auth_response

            # Query
            try:
                self._m_users.delete(user_id)
                return responses.OKEmpty()
            except NoResultFound:
                return responses.NotFoundByID("user_id")
        except SQLAlchemyError as sqlae:
            return responses.DatabaseException(sqlae)
Beispiel #12
0
    def create(self, request: 'th_Request') -> responses.Response:
        validator = validation.Dict(
            {
                "room_id":
                validation.Integer(),
                "content":
                validation.String(length_min=orm.Posts.CONTENT_LEN_MIN,
                                  length_max=orm.Posts.CONTENT_LEN_MAX)
            },
            allow_undefined_keys=not self._strict_requests)
        try:
            print(request.body)
            # 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 = self._m_rooms.get(room_id)
            except NoResultFound:
                return responses.NotFoundByID("room_id")
            orm_room_users = self._m_rooms_users.get_all_by_room(orm_room.id)

            # Get the user's ID from request (Which gets it's user info from a token)
            if not isinstance(request.user, Registered):
                return responses.UnauthorizedNotLoggedIn()
            user: Registered = request.user

            # Authorize
            if orm_room.is_public:
                auth_response = self._s_auth.authorize(
                    Action.POSTS_CREATE_PUBLIC, request.user)
            else:
                allowed_ids = [orm_room.user_id] + [
                    orm_ru.user_id for orm_ru in orm_room_users
                ]
                auth_response = self._s_auth.authorize(Action.POSTS_CREATE,
                                                       request.user,
                                                       allowed_ids)
            if not isinstance(auth_response, responses.OKEmpty):
                return auth_response

            # Query
            try:
                self._m_posts.create(room_id, user.user_id,
                                     request.body["content"])
                return responses.Created()
            except IntegrityError:
                return responses.NotFoundByID("user_id")
        except SQLAlchemyError as sqlae:
            return responses.DatabaseException(sqlae)
Beispiel #13
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)
Beispiel #14
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)
Beispiel #15
0
    def update(self, request: 'th_Request') -> responses.Response:
        validator = validation.Dict(
            {
                "post_id":
                validation.Integer(),
                "content":
                validation.String(length_min=orm.Posts.CONTENT_LEN_MIN,
                                  length_max=orm.Posts.CONTENT_LEN_MAX)
            },
            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"]

            # Query for authorization
            try:
                orm_post = self._m_posts.get(post_id)
            except NoResultFound:
                return responses.NotFoundByID("post_id")

            # Authorization
            auth_response = self._s_auth.authorize(Action.POSTS_UPDATE,
                                                   request.user,
                                                   orm_post.user_id)
            if not isinstance(auth_response, responses.OKEmpty):
                return auth_response

            # TODO
            # Also possible to revoke update access to the user on lost access to the room
            # What about banned room checks

            try:
                self._m_posts.update(post_id, request.body["content"])
                return responses.OKEmpty()
            except NoResultFound:
                return responses.NotFoundByID("post_id")
        except SQLAlchemyError as sqlae:
            return responses.DatabaseException(sqlae)
Beispiel #16
0
    def create(self, request: 'th_Request') -> responses.Response:
        validator = validation.Dict(
            {
                "name":
                validation.String(length_min=orm.Users.NAME_LEN_MIN,
                                  length_max=orm.Users.NAME_LEN_MAX),
                "login":
                validation.String(length_min=orm.Users.LOGIN_LEN_MIN,
                                  length_max=orm.Users.LOGIN_LEN_MAX),
                "password":
                validation.String(length_min=orm.Users.PASSWORD_LEN_MIN,
                                  length_max=orm.Users.PASSWORD_LEN_MAX)
            },
            allow_undefined_keys=not self._strict_requests)
        try:
            # Authorization
            auth_response = self._s_auth.authorize(Action.USERS_CREATE,
                                                   request.user)
            if not isinstance(auth_response, responses.OKEmpty):
                return auth_response

            # Validation
            try:
                validator.validate(request.body)
            except validation.Error as ve:
                return responses.Unprocessable(ve.errors)

            # Hash password
            try:
                passhash = self._password_hasher.hash(request.body["password"])
            except HashingError as he:
                return responses.InternalException(
                    he, {"password": ["Could not be hashed"]})

            # Query
            try:
                self._m_users.create(Roles.USER.id_, request.body["login"],
                                     request.body["name"], passhash)
                return responses.Created()
            except IntegrityError:
                return responses.ConflictID("login")
        except SQLAlchemyError as sqlae:
            return responses.DatabaseException(sqlae)
Beispiel #17
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)
Beispiel #18
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)
Beispiel #19
0
    def delete(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"]

            # Query for authorization
            try:
                orm_post = self._m_posts.get(post_id)
            except NoResultFound:
                return responses.NotFoundByID("post_id")

            # Authorization
            auth_response = self._s_auth.authorize(Action.POSTS_DELETE,
                                                   request.user,
                                                   orm_post.user_id)
            if not isinstance(auth_response, responses.OKEmpty):
                return auth_response

            # Also possible to revoke delete access to the user on lost access to the room
            # what about bans

            try:
                self._m_posts.delete(post_id)
                return responses.OKEmpty()
            except NoResultFound:
                return responses.NotFoundByID("post_id")
        except SQLAlchemyError as sqlae:
            return responses.DatabaseException(sqlae)
Beispiel #20
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))
Beispiel #21
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)
Beispiel #22
0
    def update(self, request: 'th_Request') -> responses.Response:
        validator = validation.Dict(
            {
                "user_id":
                validation.Integer(),
                "role":
                validation.Integer(allow_none=True),
                "login":
                validation.String(allow_none=True,
                                  length_min=orm.Users.LOGIN_LEN_MIN,
                                  length_max=orm.Users.LOGIN_LEN_MAX),
                "name":
                validation.String(allow_none=True,
                                  length_min=orm.Users.NAME_LEN_MIN,
                                  length_max=orm.Users.NAME_LEN_MAX),
                "password":
                validation.String(allow_none=True,
                                  length_min=orm.Users.PASSWORD_LEN_MIN,
                                  length_max=orm.Users.PASSWORD_LEN_MAX)
            },
            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"]

            # Authorization (certain attributes)
            if "name" in request.body:
                # Authorize name change
                auth_response = self._s_auth.authorize(
                    Action.USERS_UPDATE_NAME, request.user, user_id)
                if not isinstance(auth_response, responses.OKEmpty):
                    return auth_response
            if "role" in request.body:
                # Authorize role change
                auth_response = self._s_auth.authorize(
                    Action.USERS_UPDATE_ROLE, request.user, None)
                if not isinstance(auth_response, responses.OKEmpty):
                    return auth_response
            if "login" in request.body or "password" in request.body:
                # Authorize credential change
                auth_response = self._s_auth.authorize(
                    Action.USERS_UPDATE_CRED, request.user, user_id)
                if not isinstance(auth_response, responses.OKEmpty):
                    return auth_response

            # Hash password
            try:
                passhash = None if "password" not in request.body else self._password_hasher.hash(
                    request.body["password"])
            except HashingError as he:
                return responses.InternalException(
                    he, {"password": ["Could not be hashed"]})

            # Query
            try:
                self._m_users.update(user_id, request.body.get("role"),
                                     request.body.get("login"),
                                     request.body.get("name"), passhash)
                return responses.OKEmpty()
            except IntegrityError:
                return responses.ConflictID("login")
            except NoResultFound:
                return responses.NotFoundByID("user_id")
        except SQLAlchemyError as sqlae:
            return responses.DatabaseException(sqlae)