diff --git a/bot/src/bot_api/controller/auth_controller.py b/bot/src/bot_api/controller/auth_controller.py index 983b5fb9..12ec2b9b 100644 --- a/bot/src/bot_api/controller/auth_controller.py +++ b/bot/src/bot_api/controller/auth_controller.py @@ -14,7 +14,10 @@ from bot_api.model.reset_password_dto import ResetPasswordDTO 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_core.configuration.feature_flags_enum import FeatureFlagsEnum +from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings from bot_data.model.auth_role_enum import AuthRoleEnum +from bot_data.model.technician_config import TechnicianConfig class AuthController: @@ -30,6 +33,7 @@ class AuthController: mail_settings: EMailClientSettings, mailer: EMailClientABC, auth_service: AuthServiceABC, + technician_config: TechnicianConfig, ): self._config = config self._env = env @@ -39,6 +43,7 @@ class AuthController: self._mail_settings = mail_settings self._mailer = mailer self._auth_service = auth_service + self._technician_config = technician_config @Route.get(f"{BasePath}/users") @Route.authorize(role=AuthRoleEnum.admin) @@ -70,17 +75,32 @@ class AuthController: @Route.post(f"{BasePath}/register") async def register(self): + if not FeatureFlagsSettings.get_flag_from_dict( + self._technician_config.feature_flags, FeatureFlagsEnum.basic_registration + ): + return + dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True)) self._auth_service.add_auth_user(dto) return "", 200 @Route.post(f"{BasePath}/register-by-id/") async def register_id(self, id: str): + if not FeatureFlagsSettings.get_flag_from_dict( + self._technician_config.feature_flags, FeatureFlagsEnum.basic_registration + ): + return + result = await self._auth_service.confirm_email_async(id) return jsonify(result) @Route.post(f"{BasePath}/login") async def login(self) -> Response: + if not FeatureFlagsSettings.get_flag_from_dict( + self._technician_config.feature_flags, FeatureFlagsEnum.basic_login + ): + return jsonify({}) + dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True)) result = await self._auth_service.login_async(dto) return jsonify(result.to_dict()) @@ -100,6 +120,11 @@ class AuthController: @Route.post(f"{BasePath}/forgot-password/") async def forgot_password(self, email: str): + if not FeatureFlagsSettings.get_flag_from_dict( + self._technician_config.feature_flags, FeatureFlagsEnum.basic_login + ): + return "", 409 + await self._auth_service.forgot_password_async(email) return "", 200 @@ -110,6 +135,11 @@ class AuthController: @Route.post(f"{BasePath}/reset-password") async def reset_password(self): + if not FeatureFlagsSettings.get_flag_from_dict( + self._technician_config.feature_flags, FeatureFlagsEnum.basic_login + ): + return "", 409 + dto: ResetPasswordDTO = JSONProcessor.process(ResetPasswordDTO, request.get_json(force=True, silent=True)) await self._auth_service.reset_password_async(dto) return "", 200 diff --git a/bot/src/bot_api/controller/gui_controller.py b/bot/src/bot_api/controller/gui_controller.py index c047b0e3..1f97d852 100644 --- a/bot/src/bot_api/controller/gui_controller.py +++ b/bot/src/bot_api/controller/gui_controller.py @@ -12,6 +12,9 @@ from bot_api.logging.api_logger import ApiLogger from bot_api.model.settings_dto import SettingsDTO from bot_api.model.version_dto import VersionDTO from bot_api.route.route import Route +from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum +from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings +from bot_data.model.technician_config import TechnicianConfig class GuiController: @@ -82,3 +85,11 @@ class GuiController: ) self._mailer.send_mail(mail) return "", 200 + + @Route.get(f"{BasePath}/has-feature-flag/") + async def has_feature_flag(self, flag: str): + settings: TechnicianConfig = self._config.get_configuration(TechnicianConfig) + return { + "key": flag, + "value": FeatureFlagsSettings.get_flag_from_dict(settings.feature_flags, FeatureFlagsEnum(flag)), + } diff --git a/bot/src/bot_core/configuration/feature_flags_enum.py b/bot/src/bot_core/configuration/feature_flags_enum.py index 8506af95..61a4652e 100644 --- a/bot/src/bot_core/configuration/feature_flags_enum.py +++ b/bot/src/bot_core/configuration/feature_flags_enum.py @@ -28,3 +28,5 @@ class FeatureFlagsEnum(Enum): technician_full_access = "TechnicianFullAccess" steam_special_offers = "SteamSpecialOffers" scheduled_events = "ScheduledEvents" + basic_registration = "BasicRegistration" + basic_login = "BasicLogin" diff --git a/bot/src/bot_core/configuration/feature_flags_settings.py b/bot/src/bot_core/configuration/feature_flags_settings.py index 3b994b17..cbea9a97 100644 --- a/bot/src/bot_core/configuration/feature_flags_settings.py +++ b/bot/src/bot_core/configuration/feature_flags_settings.py @@ -30,6 +30,8 @@ class FeatureFlagsSettings(ConfigurationModelABC): FeatureFlagsEnum.technician_full_access.value: False, # 03.10.2023 #393 FeatureFlagsEnum.steam_special_offers.value: False, # 11.10.2023 #188 FeatureFlagsEnum.scheduled_events.value: False, # 14.11.2023 #410 + FeatureFlagsEnum.basic_registration.value: False, # 19.11.2023 #440 + FeatureFlagsEnum.basic_login.value: False, # 19.11.2023 #440 } def __init__(self, **kwargs: dict): diff --git a/bot/src/bot_graphql/graphql/query.gql b/bot/src/bot_graphql/graphql/query.gql index 6892510d..cf1f4223 100644 --- a/bot/src/bot_graphql/graphql/query.gql +++ b/bot/src/bot_graphql/graphql/query.gql @@ -50,4 +50,6 @@ type Query { technicianConfig: TechnicianConfig possibleFeatureFlags: [String] discord: Discord + + hasFeatureFlag(flag: String): FeatureFlag } \ No newline at end of file diff --git a/bot/src/bot_graphql/query.py b/bot/src/bot_graphql/query.py index 154079d9..aa3f56b6 100644 --- a/bot/src/bot_graphql/query.py +++ b/bot/src/bot_graphql/query.py @@ -1,7 +1,9 @@ +from cpl_core.configuration import ConfigurationABC from cpl_discord.service import DiscordBotServiceABC from cpl_query.extension import List from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum +from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC from bot_data.abc.client_repository_abc import ClientRepositoryABC @@ -22,6 +24,7 @@ from bot_data.abc.user_joined_voice_channel_repository_abc import ( from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC from bot_data.model.short_role_name_position_enum import ShortRoleNamePositionEnum +from bot_data.model.technician_config import TechnicianConfig from bot_graphql.abc.query_abc import QueryABC from bot_graphql.filter.achievement_filter import AchievementFilter from bot_graphql.filter.auto_role_filter import AutoRoleFilter @@ -45,6 +48,7 @@ from modules.achievements.achievement_service import AchievementService class Query(QueryABC): def __init__( self, + config: ConfigurationABC, bot: DiscordBotServiceABC, auto_roles: AutoRoleRepositoryABC, clients: ClientRepositoryABC, @@ -65,6 +69,8 @@ class Query(QueryABC): ): QueryABC.__init__(self, "Query") + self._config = config + self.add_collection("autoRole", lambda *_: auto_roles.get_auto_roles(), AutoRoleFilter) self.add_collection( "autoRoleRule", @@ -120,3 +126,17 @@ class Query(QueryABC): self.set_field("possibleFeatureFlags", lambda *_: [e.value for e in FeatureFlagsEnum]) self.set_field("discord", lambda *_: Discord(bot.guilds, List(any).extend(bot.users))) + + self.set_field( + "hasFeatureFlag", + lambda *_, **kwargs: self._resolve_has_feature_flag(*_, **kwargs), + ) + + def _resolve_has_feature_flag(self, *_, **kwargs): + settings: TechnicianConfig = self._config.get_configuration(TechnicianConfig) + if "flag" not in kwargs: + return False + return { + "key": kwargs["flag"], + "value": FeatureFlagsSettings.get_flag_from_dict(settings.feature_flags, FeatureFlagsEnum(kwargs["flag"])), + } diff --git a/web/package.json b/web/package.json index 281eca54..3255abc5 100644 --- a/web/package.json +++ b/web/package.json @@ -1,56 +1,56 @@ { - "name": "web", - "version": "1.2.dev410", - "scripts": { - "ng": "ng", - "update-version": "ts-node update-version.ts", - "prestart": "npm run update-version", - "start": "ng serve", - "prebuild": "npm run update-version", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test", - "gv": "echo $npm_package_version", - "predocker-build": "npm run update-version", - "docker-build": "export VERSION=$npm_package_version; ng build; docker build -t sh-edraft.de/sdb-web:$VERSION .", - "docker-build-dev": "export VERSION=$npm_package_version; ng build --configuration development; docker build -t sh-edraft.de/sdb-web:$VERSION .", - "docker-build-stage": "export VERSION=$npm_package_version; ng build --configuration staging; docker build -t sh-edraft.de/sdb-web:$VERSION ." - }, - "private": true, - "dependencies": { - "@angular/animations": "^15.1.4", - "@angular/common": "^15.1.4", - "@angular/compiler": "^15.1.4", - "@angular/core": "^15.1.4", - "@angular/forms": "^15.1.4", - "@angular/platform-browser": "^15.1.4", - "@angular/platform-browser-dynamic": "^15.1.4", - "@angular/router": "^15.1.4", - "@auth0/angular-jwt": "^5.1.0", - "@microsoft/signalr": "^6.0.9", - "@ngx-translate/core": "^14.0.0", - "@ngx-translate/http-loader": "^7.0.0", - "@types/socket.io-client": "^3.0.0", - "moment": "^2.29.4", - "primeicons": "^6.0.1", - "primeng": "^15.2.0", - "rxjs": "~7.5.0", - "socket.io-client": "^4.5.3", - "zone.js": "~0.11.4" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^15.1.5", - "@angular/cli": "~15.1.5", - "@angular/compiler-cli": "^15.1.4", - "@types/jasmine": "~4.0.0", - "@types/node": "^18.11.9", - "jasmine-core": "~4.1.0", - "karma": "~6.3.0", - "karma-chrome-launcher": "~3.1.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.0.0", - "karma-jasmine-html-reporter": "~1.7.0", - "tslib": "^2.4.1", - "typescript": "~4.9.5" - } -} \ No newline at end of file + "name": "web", + "version": "1.2.2", + "scripts": { + "ng": "ng", + "update-version": "ts-node update-version.ts", + "prestart": "npm run update-version", + "start": "ng serve", + "prebuild": "npm run update-version", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "test": "ng test", + "gv": "echo $npm_package_version", + "predocker-build": "npm run update-version", + "docker-build": "export VERSION=$npm_package_version; ng build; docker build -t sh-edraft.de/sdb-web:$VERSION .", + "docker-build-dev": "export VERSION=$npm_package_version; ng build --configuration development; docker build -t sh-edraft.de/sdb-web:$VERSION .", + "docker-build-stage": "export VERSION=$npm_package_version; ng build --configuration staging; docker build -t sh-edraft.de/sdb-web:$VERSION ." + }, + "private": true, + "dependencies": { + "@angular/animations": "^15.1.4", + "@angular/common": "^15.1.4", + "@angular/compiler": "^15.1.4", + "@angular/core": "^15.1.4", + "@angular/forms": "^15.1.4", + "@angular/platform-browser": "^15.1.4", + "@angular/platform-browser-dynamic": "^15.1.4", + "@angular/router": "^15.1.4", + "@auth0/angular-jwt": "^5.1.0", + "@microsoft/signalr": "^6.0.9", + "@ngx-translate/core": "^14.0.0", + "@ngx-translate/http-loader": "^7.0.0", + "@types/socket.io-client": "^3.0.0", + "moment": "^2.29.4", + "primeicons": "^6.0.1", + "primeng": "^15.2.0", + "rxjs": "~7.5.0", + "socket.io-client": "^4.5.3", + "zone.js": "~0.11.4" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^15.1.5", + "@angular/cli": "~15.1.5", + "@angular/compiler-cli": "^15.1.4", + "@types/jasmine": "~4.0.0", + "@types/node": "^18.11.9", + "jasmine-core": "~4.1.0", + "karma": "~6.3.0", + "karma-chrome-launcher": "~3.1.0", + "karma-coverage": "~2.2.0", + "karma-jasmine": "~5.0.0", + "karma-jasmine-html-reporter": "~1.7.0", + "tslib": "^2.4.1", + "typescript": "~4.9.5" + } +} diff --git a/web/src/app/models/graphql/queries.model.ts b/web/src/app/models/graphql/queries.model.ts index 1365d76e..402d9f09 100644 --- a/web/src/app/models/graphql/queries.model.ts +++ b/web/src/app/models/graphql/queries.model.ts @@ -108,6 +108,15 @@ export class Queries { } `; + static hasFeatureFlag = ` + query HasFeatureFlag($flag: String) { + hasFeatureFlag(flag: $flag) { + key + value + } + } + `; + static hasServerFeatureFlag = ` query HasServerFeatureFlag($filter: ServerFilter, $flag: String) { servers(filter: $filter) { diff --git a/web/src/app/modules/auth/components/login/login.component.html b/web/src/app/modules/auth/components/login/login.component.html index f9809db0..2447b714 100644 --- a/web/src/app/modules/auth/components/login/login.component.html +++ b/web/src/app/modules/auth/components/login/login.component.html @@ -4,7 +4,9 @@

{{'auth.header' | translate}}

- -