Added logic to check if user is allowed to see requested data #89
This commit is contained in:
@@ -52,17 +52,13 @@ class AuthServiceABC(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def add_auth_user_async(self, user_dto: AuthUserDTO):
|
||||
def add_auth_user(self, user_dto: AuthUserDTO):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def add_auth_user_by_oauth_async(self, dto: OAuthDTO):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def add_auth_user_by_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> OAuthDTO:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def update_user_async(self, update_user_dto: UpdateAuthUserDTO):
|
||||
pass
|
||||
@@ -84,7 +80,7 @@ class AuthServiceABC(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def verify_api_key(self, api_key: str) -> bool:
|
||||
def verify_api_key(self, api_key: str) -> bool:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
@@ -92,7 +88,7 @@ class AuthServiceABC(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def login_discord_async(self, oauth_dto: AuthUserDTO) -> TokenDTO:
|
||||
async def login_discord_async(self, oauth_dto: AuthUserDTO, dc_id: int) -> TokenDTO:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
|
@@ -6,8 +6,6 @@ from flask import request, jsonify, Response
|
||||
|
||||
from bot_api.abc.auth_service_abc import AuthServiceABC
|
||||
from bot_api.api import Api
|
||||
from bot_api.exception.service_error_code_enum import ServiceErrorCode
|
||||
from bot_api.exception.service_exception import ServiceException
|
||||
from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria
|
||||
from bot_api.json_processor import JSONProcessor
|
||||
from bot_api.logging.api_logger import ApiLogger
|
||||
@@ -73,7 +71,7 @@ class AuthController:
|
||||
@Route.post(f"{BasePath}/register")
|
||||
async def register(self):
|
||||
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
|
||||
await self._auth_service.add_auth_user_async(dto)
|
||||
await self._auth_service.add_auth_user(dto)
|
||||
return "", 200
|
||||
|
||||
@Route.post(f"{BasePath}/register-by-id/<id>")
|
||||
|
@@ -77,23 +77,6 @@ class AuthDiscordController:
|
||||
login_url, state = oauth.authorization_url(self._auth_settings.auth_url)
|
||||
return jsonify({"loginUrl": login_url})
|
||||
|
||||
@Route.get(f"{BasePath}/create-user")
|
||||
async def discord_create_user(self) -> Response:
|
||||
response = self._get_user_from_discord_response()
|
||||
result = await self._auth_service.add_auth_user_by_discord_async(
|
||||
AuthUserDTO(
|
||||
0,
|
||||
response["username"],
|
||||
response["discriminator"],
|
||||
response["email"],
|
||||
str(uuid.uuid4()),
|
||||
None,
|
||||
AuthRoleEnum.normal,
|
||||
),
|
||||
response["id"],
|
||||
)
|
||||
return jsonify(result.to_dict())
|
||||
|
||||
@Route.get(f"{BasePath}/login")
|
||||
async def discord_login(self) -> Response:
|
||||
response = self._get_user_from_discord_response()
|
||||
@@ -107,5 +90,5 @@ class AuthDiscordController:
|
||||
AuthRoleEnum.normal,
|
||||
)
|
||||
|
||||
result = await self._auth_service.login_discord_async(dto)
|
||||
result = await self._auth_service.login_discord_async(dto, response["id"])
|
||||
return jsonify(result.to_dict())
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import functools
|
||||
from functools import wraps
|
||||
from typing import Optional, Callable
|
||||
from typing import Optional, Callable, Union
|
||||
|
||||
from cpl_core.dependency_injection import ServiceProviderABC
|
||||
from cpl_core.environment import ApplicationEnvironmentABC
|
||||
@@ -13,6 +13,7 @@ from bot_api.exception.service_exception import ServiceException
|
||||
from bot_api.model.error_dto import ErrorDTO
|
||||
from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC
|
||||
from bot_data.model.auth_role_enum import AuthRoleEnum
|
||||
from bot_data.model.auth_user import AuthUser
|
||||
|
||||
|
||||
class Route:
|
||||
@@ -29,6 +30,27 @@ class Route:
|
||||
cls._auth = auth
|
||||
cls._env = env.environment_name
|
||||
|
||||
@classmethod
|
||||
def get_user(cls) -> Optional[Union[str, AuthUser]]:
|
||||
token = None
|
||||
api_key = None
|
||||
authorization = request.headers.get("Authorization").split()
|
||||
match authorization[0]:
|
||||
case "Bearer":
|
||||
token = authorization[1]
|
||||
case "API-Key":
|
||||
api_key = authorization[1]
|
||||
|
||||
if api_key is not None:
|
||||
return "system"
|
||||
|
||||
if token is None:
|
||||
return None
|
||||
|
||||
jwt = cls._auth.decode_token(token)
|
||||
user = cls._auth_users.get_auth_user_by_email(jwt["email"])
|
||||
return user
|
||||
|
||||
@classmethod
|
||||
def authorize(cls, f: Callable = None, role: AuthRoleEnum = None, skip_in_dev=False, by_api_key=False):
|
||||
if f is None:
|
||||
@@ -39,10 +61,25 @@ class Route:
|
||||
if skip_in_dev and cls._env == "development":
|
||||
return await f(*args, **kwargs)
|
||||
|
||||
if "Authorization" not in request.headers and by_api_key and "API-Key" in request.headers:
|
||||
token = None
|
||||
api_key = None
|
||||
if "Authorization" in request.headers:
|
||||
if " " not in request.headers.get("Authorization"):
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token not set")
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
authorization = request.headers.get("Authorization").split()
|
||||
match authorization[0]:
|
||||
case "Bearer":
|
||||
token = authorization[1]
|
||||
case "API-Key":
|
||||
api_key = authorization[1]
|
||||
|
||||
if api_key is not None:
|
||||
valid = False
|
||||
try:
|
||||
valid = cls._auth.verify_api_key(request.headers["API-Key"])
|
||||
valid = cls._auth.verify_api_key(api_key)
|
||||
except ServiceException as e:
|
||||
error = ErrorDTO(e.error_code, e.message)
|
||||
return jsonify(error.to_dict()), 403
|
||||
@@ -56,11 +93,6 @@ class Route:
|
||||
|
||||
return await f(*args, **kwargs)
|
||||
|
||||
token = None
|
||||
if "Authorization" in request.headers:
|
||||
bearer = request.headers.get("Authorization")
|
||||
token = bearer.split()[1]
|
||||
|
||||
if token is None:
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token not set")
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
|
@@ -223,18 +223,13 @@ class AuthService(AuthServiceABC):
|
||||
user = self._auth_users.find_auth_user_by_email(email)
|
||||
return AUT.to_dto(user) if user is not None else None
|
||||
|
||||
async def add_auth_user_async(self, user_dto: AuthUserDTO):
|
||||
def add_auth_user(self, user_dto: AuthUserDTO):
|
||||
db_user = self._auth_users.find_auth_user_by_email(user_dto.email)
|
||||
if db_user is not None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidUser, "User already exists")
|
||||
|
||||
user = AUT.to_db(user_dto)
|
||||
if (
|
||||
self._auth_users.get_all_auth_users()
|
||||
.where(lambda x: x.name != "internal" and x.email != "internal@localhost")
|
||||
.count()
|
||||
== 0
|
||||
):
|
||||
if self._auth_users.get_all_auth_users().count() == 0:
|
||||
user.auth_role = AuthRoleEnum.admin
|
||||
|
||||
user.password_salt = uuid.uuid4()
|
||||
@@ -277,51 +272,6 @@ class AuthService(AuthServiceABC):
|
||||
|
||||
self._db.save_changes()
|
||||
|
||||
async def add_auth_user_by_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> OAuthDTO:
|
||||
db_auth_user = self._auth_users.find_auth_user_by_email(user_dto.email)
|
||||
|
||||
# user exists
|
||||
if db_auth_user is not None and db_auth_user.users.count() > 0:
|
||||
# raise ServiceException(ServiceErrorCode.InvalidUser, 'User already exists')
|
||||
self._logger.debug(__name__, f"Discord user already exists")
|
||||
return OAuthDTO(AUT.to_dto(db_auth_user), None)
|
||||
|
||||
# user exists but discord user id not set
|
||||
elif db_auth_user is not None and db_auth_user.users.count() == 0:
|
||||
self._logger.debug(__name__, f"Auth user exists but not linked with discord")
|
||||
# users = self._users.get_users_by_discord_id(user_dto.user_id)
|
||||
# add auth_user to user refs
|
||||
db_auth_user.oauth_id = None
|
||||
|
||||
else:
|
||||
# user does not exists
|
||||
self._logger.debug(__name__, f"Auth user does not exist")
|
||||
try:
|
||||
user_dto.user_id = self._users.get_users_by_discord_id(user_dto.user_id).single().user_id
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"User not found")
|
||||
user_dto.user_id = None
|
||||
|
||||
await self.add_auth_user_async(user_dto)
|
||||
db_auth_user = self._auth_users.get_auth_user_by_email(user_dto.email)
|
||||
db_auth_user.oauth_id = uuid.uuid4()
|
||||
|
||||
for g in self._bot.guilds:
|
||||
member = g.get_member(int(dc_id))
|
||||
if member is None:
|
||||
continue
|
||||
|
||||
server = self._servers.get_server_by_discord_id(g.id)
|
||||
users = self._users.get_users_by_discord_id(dc_id)
|
||||
for user in users:
|
||||
if user.server.server_id != server.server_id:
|
||||
continue
|
||||
self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_auth_user, user))
|
||||
|
||||
self._auth_users.update_auth_user(db_auth_user)
|
||||
self._db.save_changes()
|
||||
return OAuthDTO(AUT.to_dto(db_auth_user), db_auth_user.oauth_id)
|
||||
|
||||
async def update_user_async(self, update_user_dto: UpdateAuthUserDTO):
|
||||
if update_user_dto is None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
|
||||
@@ -498,7 +448,7 @@ class AuthService(AuthServiceABC):
|
||||
if not keys.contains(api_key):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, "API-Key invalid")
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Token invalid", e)
|
||||
self._logger.error(__name__, f"API-Key invalid", e)
|
||||
return False
|
||||
|
||||
return True
|
||||
@@ -523,16 +473,21 @@ class AuthService(AuthServiceABC):
|
||||
self._db.save_changes()
|
||||
return TokenDTO(token, refresh_token)
|
||||
|
||||
async def login_discord_async(self, user_dto: AuthUserDTO) -> TokenDTO:
|
||||
async def login_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> TokenDTO:
|
||||
if user_dto is None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, "User not set")
|
||||
|
||||
db_user = self._auth_users.find_auth_user_by_email(user_dto.email)
|
||||
if db_user is None:
|
||||
await self.add_auth_user_async(user_dto)
|
||||
self.add_auth_user(user_dto)
|
||||
# raise ServiceException(ServiceErrorCode.InvalidUser, f'User not found')
|
||||
|
||||
db_user = self._auth_users.get_auth_user_by_email(user_dto.email)
|
||||
if db_user.users.count() == 0:
|
||||
self._users.get_users_by_discord_id(dc_id).for_each(
|
||||
lambda x: self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_user, x))
|
||||
)
|
||||
|
||||
token = self.generate_token(db_user)
|
||||
refresh_token = self._create_and_save_refresh_token(db_user)
|
||||
if db_user.forgot_password_id is not None:
|
||||
|
Reference in New Issue
Block a user