@ -11,10 +11,12 @@ from flask import Flask
|
||||
from bot_api.abc.auth_service_abc import AuthServiceABC
|
||||
from bot_api.api import Api
|
||||
from bot_api.api_thread import ApiThread
|
||||
from bot_api.controller.discord.server_controller import ServerController
|
||||
from bot_api.controller.gui_controller import GuiController
|
||||
from bot_api.controller.auth_controller import AuthController
|
||||
from bot_api.event.bot_api_on_ready_event import BotApiOnReadyEvent
|
||||
from bot_api.service.auth_service import AuthService
|
||||
from bot_api.service.discord_service import DiscordService
|
||||
from bot_core.abc.module_abc import ModuleABC
|
||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||
|
||||
@ -41,6 +43,8 @@ class ApiModule(ModuleABC):
|
||||
services.add_transient(AuthServiceABC, AuthService)
|
||||
services.add_transient(AuthController)
|
||||
services.add_transient(GuiController)
|
||||
services.add_transient(DiscordService)
|
||||
services.add_transient(ServerController)
|
||||
|
||||
# cpl-discord
|
||||
self._dc.add_event(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent)
|
||||
|
@ -15,6 +15,7 @@ from bot_api.model.auth_user_dto import AuthUserDTO
|
||||
from bot_api.model.token_dto import TokenDTO
|
||||
from bot_api.model.update_auth_user_dto import UpdateAuthUserDTO
|
||||
from bot_api.route.route import Route
|
||||
from bot_data.model.auth_role_enum import AuthRoleEnum
|
||||
|
||||
|
||||
class AuthController:
|
||||
@ -41,13 +42,13 @@ class AuthController:
|
||||
self._auth_service = auth_service
|
||||
|
||||
@Route.get(f'{BasePath}/users')
|
||||
@Route.authorize
|
||||
@Route.authorize(role=AuthRoleEnum.admin)
|
||||
async def get_all_users(self) -> Response:
|
||||
result = await self._auth_service.get_all_auth_users_async()
|
||||
return jsonify(result.select(lambda x: x.to_dict()))
|
||||
|
||||
@Route.post(f'{BasePath}/users/get/filtered')
|
||||
@Route.authorize
|
||||
@Route.authorize(role=AuthRoleEnum.admin)
|
||||
async def get_filtered_users(self) -> Response:
|
||||
dto: AuthUserSelectCriteria = JSONProcessor.process(AuthUserSelectCriteria, request.get_json(force=True, silent=True))
|
||||
result = await self._auth_service.get_filtered_auth_users_async(dto)
|
||||
@ -55,13 +56,13 @@ class AuthController:
|
||||
return jsonify(result.to_dict())
|
||||
|
||||
@Route.get(f'{BasePath}/users/get/<email>')
|
||||
@Route.authorize
|
||||
@Route.authorize(role=AuthRoleEnum.admin)
|
||||
async def get_user_from_email(self, email: str) -> Response:
|
||||
result = await self._auth_service.get_auth_user_by_email_async(email)
|
||||
edraft marked this conversation as resolved
|
||||
return jsonify(result.to_dict())
|
||||
|
||||
@Route.get(f'{BasePath}/users/find/<email>')
|
||||
@Route.authorize
|
||||
@Route.authorize(role=AuthRoleEnum.admin)
|
||||
async def find_user_from_email(self, email: str) -> Response:
|
||||
result = await self._auth_service.find_auth_user_by_email_async(email)
|
||||
return jsonify(result.to_dict())
|
||||
@ -109,7 +110,7 @@ class AuthController:
|
||||
return '', 200
|
||||
|
||||
@Route.post(f'{BasePath}/update-user-as-admin')
|
||||
@Route.authorize
|
||||
@Route.authorize(role=AuthRoleEnum.admin)
|
||||
async def update_user_as_admin(self):
|
||||
dto: UpdateAuthUserDTO = JSONProcessor.process(UpdateAuthUserDTO, request.get_json(force=True, silent=True))
|
||||
await self._auth_service.update_user_as_admin_async(dto)
|
||||
@ -129,14 +130,14 @@ class AuthController:
|
||||
return '', 200
|
||||
|
||||
@Route.post(f'{BasePath}/delete-user')
|
||||
@Route.authorize
|
||||
@Route.authorize(role=AuthRoleEnum.admin)
|
||||
async def delete_user(self):
|
||||
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
|
||||
await self._auth_service.delete_auth_user_async(dto)
|
||||
return '', 200
|
||||
|
||||
@Route.post(f'{BasePath}/delete-user-by-mail/<email>')
|
||||
@Route.authorize
|
||||
@Route.authorize(role=AuthRoleEnum.admin)
|
||||
async def delete_user_by_mail(self, email: str):
|
||||
await self._auth_service.delete_auth_user_by_email_async(email)
|
||||
return '', 200
|
||||
|
@ -8,6 +8,7 @@ from bot_api.api import Api
|
||||
from bot_api.logging.api_logger import ApiLogger
|
||||
from bot_api.route.route import Route
|
||||
from bot_api.service.discord_service import DiscordService
|
||||
from bot_data.model.auth_role_enum import AuthRoleEnum
|
||||
|
||||
|
||||
class ServerController:
|
||||
@ -34,6 +35,6 @@ class ServerController:
|
||||
self._discord_service = discord_service
|
||||
|
||||
@Route.get(f'{BasePath}/servers')
|
||||
@Route.authorize
|
||||
@Route.authorize(role=AuthRoleEnum.admin)
|
||||
async def get_all_servers(self) -> Response:
|
||||
return jsonify(self._discord_service.get_all_servers().select(lambda x: x.to_dict()))
|
||||
|
@ -21,3 +21,4 @@ class ServiceErrorCode(Enum):
|
||||
MailError = 10
|
||||
|
||||
Unauthorized = 11
|
||||
Forbidden = 12
|
||||
|
@ -1,5 +1,6 @@
|
||||
import functools
|
||||
from functools import wraps
|
||||
from typing import Optional
|
||||
from typing import Optional, Callable
|
||||
|
||||
from flask import request, jsonify
|
||||
from flask_cors import cross_origin
|
||||
@ -9,6 +10,7 @@ from bot_api.exception.service_error_code_enum import ServiceErrorCode
|
||||
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
|
||||
|
||||
|
||||
class Route:
|
||||
@ -23,7 +25,10 @@ class Route:
|
||||
cls._auth = auth
|
||||
|
||||
@classmethod
|
||||
def authorize(cls, f):
|
||||
def authorize(cls, f: Callable = None, role: AuthRoleEnum = None):
|
||||
edraft marked this conversation as resolved
Ebola-Chan
commented
Vorschlag: Die HTTP-Response-Status-Codes in einem Enum packen, damit man schneller erkennen kann, um was die Response handelt. Vorschlag: Die HTTP-Response-Status-Codes in einem Enum packen, damit man schneller erkennen kann, um was die Response handelt.
edraft
commented
Kann man später mal nachbessern aber die API ist jetzt noch übersichtlich genug Kann man später mal nachbessern aber die API ist jetzt noch übersichtlich genug
|
||||
if f is None:
|
||||
return functools.partial(cls.authorize, role=role)
|
||||
|
||||
@wraps(f)
|
||||
async def decorator(*args, **kwargs):
|
||||
token = None
|
||||
@ -46,6 +51,23 @@ class Route:
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
token = cls._auth.decode_token(token)
|
||||
if token is None or 'email' not in token:
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f'Token invalid')
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
user = cls._auth_users.get_auth_user_by_email(token['email'])
|
||||
if user is None:
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f'Token invalid')
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
if role is not None and user.auth_role.value < role.value:
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f'Role {role} required')
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 403
|
||||
|
||||
return await f(*args, **kwargs)
|
||||
|
||||
return decorator
|
||||
|
@ -27,6 +27,8 @@ from bot_api.transformer.auth_user_transformer import AuthUserTransformer as AUT
|
||||
from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC
|
||||
from bot_data.model.auth_user import AuthUser
|
||||
|
||||
_email_regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
|
||||
|
||||
|
||||
class AuthService(AuthServiceABC):
|
||||
|
||||
@ -65,7 +67,7 @@ class AuthService(AuthServiceABC):
|
||||
|
||||
@staticmethod
|
||||
def _is_email_valid(email: str) -> bool:
|
||||
if re.match(re.compile(r'^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}$'), email) is not None:
|
||||
if re.fullmatch(_email_regex, email) is not None:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
@ -19,7 +19,7 @@ class AuthUserTransformer(TransformerABC):
|
||||
None,
|
||||
None,
|
||||
datetime.now(tz=timezone.utc),
|
||||
AuthRoleEnum.normal if dto.auth_role is None else dto.auth_role,
|
||||
AuthRoleEnum.normal if dto.auth_role is None else AuthRoleEnum(dto.auth_role),
|
||||
id=0 if dto.id is None else dto.id
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user
Was passiert, wenn eine andere E-Mail-Adresse angegeben wird?
Wenn eine positive Antwort gegeben wird: Ist es gewollt, dass ein User eine andere E-Mail-Adresse aufrufen kann?
Wenn ja: Soll ein User eine E-Mail-Adresse abfragen können, mit dem dieser nichts zu tun hat?
was spricht dagegen?
So kannst du Profile von anderen usern sehen, kannst damit ja nichts ans pw kommen.
Naja, so könnte sich jemand registrieren und dann somit eine Liste von gültigen E-Mails erstellen für Spammers.
Wenn der User nur Profile von anderen Usern aufrufen kann, mit dem er zu tun hat, dann wäre es besser.