1.0.0 #253
| @@ -1,7 +1,10 @@ | ||||
| from datetime import datetime | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from bot_api.abc.dto_abc import DtoABC | ||||
| from bot_api.model.user_dto import UserDTO | ||||
| from bot_data.model.auth_role_enum import AuthRoleEnum | ||||
|  | ||||
|  | ||||
| @@ -15,6 +18,7 @@ class AuthUserDTO(DtoABC): | ||||
|         password: str = None, | ||||
|         confirmation_id: Optional[str] = None, | ||||
|         auth_role: AuthRoleEnum = None, | ||||
|         users: List[UserDTO] = None, | ||||
|         created_at: datetime = None, | ||||
|         modified_at: datetime = None, | ||||
|     ): | ||||
| @@ -30,6 +34,11 @@ class AuthUserDTO(DtoABC): | ||||
|         self._created_at = created_at | ||||
|         self._modified_at = modified_at | ||||
|  | ||||
|         if users is None: | ||||
|             self._users = List(UserDTO) | ||||
|         else: | ||||
|             self._users = users | ||||
|  | ||||
|     @property | ||||
|     def id(self) -> int: | ||||
|         return self._id | ||||
| @@ -82,6 +91,10 @@ class AuthUserDTO(DtoABC): | ||||
|     def auth_role(self, value: AuthRoleEnum): | ||||
|         self._auth_role = value | ||||
|  | ||||
|     @property | ||||
|     def users(self) -> List[UserDTO]: | ||||
|         return self._users | ||||
|  | ||||
|     @property | ||||
|     def created_at(self) -> datetime: | ||||
|         return self._created_at | ||||
| @@ -98,6 +111,12 @@ class AuthUserDTO(DtoABC): | ||||
|         self._password = values["password"] | ||||
|         self._is_confirmed = values["isConfirmed"] | ||||
|         self._auth_role = AuthRoleEnum(values["authRole"]) | ||||
|         if "users" in values: | ||||
|             self._users = List(UserDTO) | ||||
|             for u in values["users"]: | ||||
|                 user = UserDTO() | ||||
|                 user.from_dict(u) | ||||
|                 self._users.add(user) | ||||
|  | ||||
|         self._created_at = values["createdAt"] | ||||
|         self._modified_at = values["modifiedAt"] | ||||
| @@ -111,6 +130,7 @@ class AuthUserDTO(DtoABC): | ||||
|             "password": self._password, | ||||
|             "isConfirmed": self._is_confirmed, | ||||
|             "authRole": self._auth_role.value, | ||||
|             "users": self._users.select(lambda u: u.to_dict()).to_list(), | ||||
|             "createdAt": self._created_at, | ||||
|             "modifiedAt": self._modified_at, | ||||
|         } | ||||
|   | ||||
							
								
								
									
										88
									
								
								kdb-bot/src/bot_api/model/user_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								kdb-bot/src/bot_api/model/user_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| from typing import Optional | ||||
|  | ||||
| from bot_api.abc.dto_abc import DtoABC | ||||
| from bot_data.model.server import Server | ||||
|  | ||||
|  | ||||
| class UserDTO(DtoABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         id: int = None, | ||||
|         dc_id: int = None, | ||||
|         xp: int = None, | ||||
|         minecraft_id: Optional[str] = None, | ||||
|         server: Optional[Server] = None, | ||||
|         is_technician: Optional[bool] = None, | ||||
|         is_admin: Optional[bool] = None, | ||||
|         is_moderator: Optional[bool] = None, | ||||
|     ): | ||||
|         DtoABC.__init__(self) | ||||
|  | ||||
|         self._user_id = id | ||||
|         self._discord_id = dc_id | ||||
|         self._xp = xp | ||||
|         self._minecraft_id = minecraft_id | ||||
|         self._server = server | ||||
|  | ||||
|         self._is_technician = is_technician | ||||
|         self._is_admin = is_admin | ||||
|         self._is_moderator = is_moderator | ||||
|  | ||||
|     @property | ||||
|     def user_id(self) -> int: | ||||
|         return self._user_id | ||||
|  | ||||
|     @property | ||||
|     def discord_id(self) -> int: | ||||
|         return self._discord_id | ||||
|  | ||||
|     @property | ||||
|     def xp(self) -> int: | ||||
|         return self._xp | ||||
|  | ||||
|     @xp.setter | ||||
|     def xp(self, value: int): | ||||
|         self._xp = value | ||||
|  | ||||
|     @property | ||||
|     def minecraft_id(self) -> Optional[str]: | ||||
|         return self._minecraft_id | ||||
|  | ||||
|     @minecraft_id.setter | ||||
|     def minecraft_id(self, value: str): | ||||
|         self._minecraft_id = value | ||||
|  | ||||
|     @property | ||||
|     def server(self) -> Optional[Server]: | ||||
|         return self._server | ||||
|  | ||||
|     @property | ||||
|     def is_technician(self) -> bool: | ||||
|         return self._is_technician if self._is_technician is not None else False | ||||
|  | ||||
|     @property | ||||
|     def is_admin(self) -> bool: | ||||
|         return self._is_admin if self._is_admin is not None else False | ||||
|  | ||||
|     @property | ||||
|     def is_moderator(self) -> bool: | ||||
|         return self._is_moderator if self._is_moderator is not None else False | ||||
|  | ||||
|     def from_dict(self, values: dict): | ||||
|         self._user_id = values["id"] | ||||
|         self._discord_id = values["dcId"] | ||||
|         self._xp = values["xp"] | ||||
|         self._minecraft_id = values["minecraftId"] | ||||
|         self._server = values["server"] | ||||
|  | ||||
|     def to_dict(self) -> dict: | ||||
|         return { | ||||
|             "id": self._user_id, | ||||
|             "dcId": self._discord_id, | ||||
|             "xp": self._xp, | ||||
|             "minecraftId": self._minecraft_id, | ||||
|             "server": self._server.server_id, | ||||
|             "isTechnician": self.is_technician, | ||||
|             "isAdmin": self.is_admin, | ||||
|             "isModerator": self.is_moderator, | ||||
|         } | ||||
| @@ -1,9 +1,16 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| from cpl_core.dependency_injection import ServiceProviderABC | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from bot_api.abc.transformer_abc import TransformerABC | ||||
| from bot_api.model.auth_user_dto import AuthUserDTO | ||||
| from bot_api.model.user_dto import UserDTO | ||||
| from bot_data.model.auth_role_enum import AuthRoleEnum | ||||
| from bot_data.model.auth_user import AuthUser | ||||
| from bot_data.model.user import User | ||||
| from modules.permission.abc.permission_service_abc import PermissionServiceABC | ||||
|  | ||||
|  | ||||
| class AuthUserTransformer(TransformerABC): | ||||
| @@ -25,7 +32,28 @@ class AuthUserTransformer(TransformerABC): | ||||
|         ) | ||||
|  | ||||
|     @staticmethod | ||||
|     def to_dto(db: AuthUser, password: str = None) -> AuthUserDTO: | ||||
|     @ServiceProviderABC.inject | ||||
|     def _is_technician(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC): | ||||
|         guild = bot.get_guild(user.server.discord_server_id) | ||||
|         member = guild.get_member(user.discord_id) | ||||
|         return permissions.is_member_technician(member) | ||||
|  | ||||
|     @staticmethod | ||||
|     @ServiceProviderABC.inject | ||||
|     def _is_admin(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC): | ||||
|         guild = bot.get_guild(user.server.discord_server_id) | ||||
|         member = guild.get_member(user.discord_id) | ||||
|         return permissions.is_member_technician(member) | ||||
|  | ||||
|     @staticmethod | ||||
|     @ServiceProviderABC.inject | ||||
|     def _is_moderator(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC): | ||||
|         guild = bot.get_guild(user.server.discord_server_id) | ||||
|         member = guild.get_member(user.discord_id) | ||||
|         return permissions.is_member_technician(member) | ||||
|  | ||||
|     @classmethod | ||||
|     def to_dto(cls, db: AuthUser, password: str = None) -> AuthUserDTO: | ||||
|         return AuthUserDTO( | ||||
|             db.id, | ||||
|             db.first_name, | ||||
| @@ -34,6 +62,21 @@ class AuthUserTransformer(TransformerABC): | ||||
|             "" if password is None else password, | ||||
|             db.confirmation_id, | ||||
|             db.auth_role, | ||||
|             List( | ||||
|                 UserDTO, | ||||
|                 db.users.select( | ||||
|                     lambda u: UserDTO( | ||||
|                         u.user_id, | ||||
|                         u.discord_id, | ||||
|                         u.xp, | ||||
|                         u.minecraft_id, | ||||
|                         u.server, | ||||
|                         cls._is_technician(u), | ||||
|                         cls._is_admin(u), | ||||
|                         cls._is_moderator(u), | ||||
|                     ) | ||||
|                 ), | ||||
|             ), | ||||
|             db.created_at, | ||||
|             db.modified_at, | ||||
|         ) | ||||
|   | ||||
| @@ -42,6 +42,8 @@ class AuthUser(TableABC): | ||||
|  | ||||
|         if users is None: | ||||
|             self._users = List(User) | ||||
|         else: | ||||
|             self._users = users | ||||
|  | ||||
|         self._auth_role_id = auth_role | ||||
|  | ||||
|   | ||||
| @@ -10,6 +10,7 @@ from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServ | ||||
| from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter | ||||
| from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter | ||||
| from modules.level.service.level_service import LevelService | ||||
| from modules.permission.abc.permission_service_abc import PermissionServiceABC | ||||
|  | ||||
|  | ||||
| class UserQuery(DataQueryABC): | ||||
| @@ -21,6 +22,7 @@ class UserQuery(DataQueryABC): | ||||
|         ujs: UserJoinedServerRepositoryABC, | ||||
|         ujvs: UserJoinedVoiceChannelRepositoryABC, | ||||
|         user_joined_game_server: UserJoinedGameServerRepositoryABC, | ||||
|         permissions: PermissionServiceABC, | ||||
|     ): | ||||
|         DataQueryABC.__init__(self, "User") | ||||
|  | ||||
| @@ -30,6 +32,7 @@ class UserQuery(DataQueryABC): | ||||
|         self._user_joined_game_server = user_joined_game_server | ||||
|         self._ujs = ujs | ||||
|         self._ujvs = ujvs | ||||
|         self._permissions = permissions | ||||
|  | ||||
|         self.set_field("id", self.resolve_id) | ||||
|         self.set_field("discordId", self.resolve_discord_id) | ||||
|   | ||||
| @@ -1,13 +1,28 @@ | ||||
| import { AuthRoles } from "./auth-roles.enum"; | ||||
| import {AuthRoles} from "./auth-roles.enum"; | ||||
|  | ||||
| export interface AuthUserDTO { | ||||
|     id?: number; | ||||
|     firstName: string | null; | ||||
|     lastName: string | null; | ||||
|     email: string | null; | ||||
|     password: string | null; | ||||
|     isConfirmed?: boolean | ||||
|     authRole?: AuthRoles; | ||||
|     createdAt?: string; | ||||
|     modifiedAt?: string; | ||||
|   id?: number; | ||||
|   firstName: string | null; | ||||
|   lastName: string | null; | ||||
|   email: string | null; | ||||
|   password: string | null; | ||||
|   isConfirmed?: boolean; | ||||
|   authRole?: AuthRoles; | ||||
|   users?: UserDTO[]; | ||||
|   createdAt?: string; | ||||
|   modifiedAt?: string; | ||||
| } | ||||
|  | ||||
|  | ||||
| export interface UserDTO { | ||||
|   id: number; | ||||
|   discordId: number; | ||||
|   xp: number; | ||||
|   minecraftId: number | null; | ||||
|   server: number; | ||||
|   createdAt: string; | ||||
|   modifiedAt: string; | ||||
|   isTechnician: boolean; | ||||
|   isAdmin: boolean; | ||||
|   IsModerator: boolean; | ||||
| } | ||||
|   | ||||
| @@ -122,7 +122,7 @@ export class DashboardComponent implements OnInit { | ||||
|   } | ||||
|  | ||||
|   selectServer(server: Server) { | ||||
|     this.sidebar.serverName$.next(server.name ?? ""); | ||||
|     this.sidebar.server$.next(server); | ||||
|     this.router.navigate(["/server", server.id]); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1 @@ | ||||
| <p>profile works!</p> | ||||
| @@ -0,0 +1,23 @@ | ||||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||||
|  | ||||
| import { ProfileComponent } from './profile.component'; | ||||
|  | ||||
| describe('ProfileComponent', () => { | ||||
|   let component: ProfileComponent; | ||||
|   let fixture: ComponentFixture<ProfileComponent>; | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     await TestBed.configureTestingModule({ | ||||
|       declarations: [ ProfileComponent ] | ||||
|     }) | ||||
|     .compileComponents(); | ||||
|  | ||||
|     fixture = TestBed.createComponent(ProfileComponent); | ||||
|     component = fixture.componentInstance; | ||||
|     fixture.detectChanges(); | ||||
|   }); | ||||
|  | ||||
|   it('should create', () => { | ||||
|     expect(component).toBeTruthy(); | ||||
|   }); | ||||
| }); | ||||
| @@ -0,0 +1,10 @@ | ||||
| import { Component } from '@angular/core'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-profile', | ||||
|   templateUrl: './profile.component.html', | ||||
|   styleUrls: ['./profile.component.scss'] | ||||
| }) | ||||
| export class ProfileComponent { | ||||
|  | ||||
| } | ||||
| @@ -42,7 +42,7 @@ export class ServerDashboardComponent implements OnInit { | ||||
|       } | ||||
|     ).subscribe(server => { | ||||
|       this.server = server; | ||||
|       this.sidebar.serverName$.next(server.name ?? ""); | ||||
|       this.sidebar.server$.next(server); | ||||
|       this.spinner.hideSpinner(); | ||||
|     }); | ||||
|   } | ||||
|   | ||||
| @@ -1,9 +1,11 @@ | ||||
| import { NgModule } from "@angular/core"; | ||||
| import { RouterModule, Routes } from "@angular/router"; | ||||
| import { ServerDashboardComponent } from "./server-dashboard/server-dashboard.component"; | ||||
| import { ProfileComponent } from "./profile/profile.component"; | ||||
|  | ||||
| const routes: Routes = [ | ||||
|   { path: '', component: ServerDashboardComponent }, | ||||
|   { path: 'profile', component: ProfileComponent }, | ||||
| ]; | ||||
|  | ||||
| @NgModule({ | ||||
|   | ||||
| @@ -3,12 +3,14 @@ import { CommonModule } from '@angular/common'; | ||||
| import { ServerDashboardComponent } from './server-dashboard/server-dashboard.component'; | ||||
| import { ServerRoutingModule } from './server-routing.module'; | ||||
| import { SharedModule } from '../../shared/shared.module'; | ||||
| import { ProfileComponent } from './profile/profile.component'; | ||||
|  | ||||
|  | ||||
|  | ||||
| @NgModule({ | ||||
|   declarations: [ | ||||
|     ServerDashboardComponent | ||||
|     ServerDashboardComponent, | ||||
|     ProfileComponent | ||||
|   ], | ||||
|   imports: [ | ||||
|     CommonModule, | ||||
|   | ||||
| @@ -241,6 +241,20 @@ export class AuthService { | ||||
|     return null | ||||
|   } | ||||
|  | ||||
|   async getLoggedInUser(): Promise<AuthUserDTO | null> { | ||||
|     if (!await this.isUserLoggedInAsync()) { | ||||
|       return null; | ||||
|     } | ||||
|     const token = this.getDecodedToken(); | ||||
|     if (!token) return null; | ||||
|  | ||||
|     try { | ||||
|       return await firstValueFrom(this.findUserByEMail(token["email"])); | ||||
|     } catch (error: unknown) { | ||||
|       return null; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   async isUserLoggedInAsync(): Promise<boolean> { | ||||
|     const token = this.getToken(); | ||||
|  | ||||
|   | ||||
| @@ -4,8 +4,10 @@ import { BehaviorSubject } from "rxjs"; | ||||
| import { AuthRoles } from "../../models/auth/auth-roles.enum"; | ||||
| import { AuthService } from "../auth/auth.service"; | ||||
| import { TranslateService } from "@ngx-translate/core"; | ||||
| import { ActivatedRoute, NavigationEnd, Router } from "@angular/router"; | ||||
| import { NavigationEnd, Router } from "@angular/router"; | ||||
| import { ThemeService } from "../theme/theme.service"; | ||||
| import { Server } from "../../models/data/server.model"; | ||||
| import { UserDTO } from "../../models/auth/auth-user.dto"; | ||||
|  | ||||
| @Injectable({ | ||||
|   providedIn: "root" | ||||
| @@ -13,14 +15,14 @@ import { ThemeService } from "../theme/theme.service"; | ||||
| export class SidebarService { | ||||
|  | ||||
|   isSidebarOpen: boolean = true; | ||||
|   menuItems$: BehaviorSubject<MenuItem[]> = new BehaviorSubject(new Array<MenuItem>()); | ||||
|   serverName$: BehaviorSubject<string> = new BehaviorSubject(""); | ||||
|   menuItems$ = new BehaviorSubject<MenuItem[]>(new Array<MenuItem>()); | ||||
|   server$ = new BehaviorSubject<Server | null>(null); | ||||
|  | ||||
|   constructor( | ||||
|     private themeService: ThemeService, | ||||
|     private authService: AuthService, | ||||
|     private translateService: TranslateService, | ||||
|     private router: Router, | ||||
|     private router: Router | ||||
|   ) { | ||||
|     this.themeService.isSidebarOpen$.subscribe(value => { | ||||
|       this.isSidebarOpen = value; | ||||
| @@ -28,7 +30,7 @@ export class SidebarService { | ||||
|     }); | ||||
|  | ||||
|  | ||||
|     this.serverName$.subscribe(value => { | ||||
|     this.server$.subscribe(value => { | ||||
|       this.setMenu(); | ||||
|     }); | ||||
|  | ||||
| @@ -40,18 +42,27 @@ export class SidebarService { | ||||
|   } | ||||
|  | ||||
|   setMenu() { | ||||
|     this.authService.hasUserPermission(AuthRoles.Admin).then(hasPermission => { | ||||
|     this.authService.hasUserPermission(AuthRoles.Admin).then(async hasPermission => { | ||||
|       let menuItems: MenuItem[] = [ | ||||
|         { label: this.isSidebarOpen ? this.translateService.instant("sidebar.dashboard") : "", icon: "pi pi-th-large", routerLink: "dashboard" } | ||||
|       ]; | ||||
|  | ||||
|       const serverMenu = { | ||||
|         label: this.isSidebarOpen ? this.serverName$.value : "", icon: "pi pi-server", items: [ | ||||
|           { label: this.isSidebarOpen ? this.translateService.instant("sidebar.settings") : "", icon: "pi pi-cog", routerLink: "server/settings" }, | ||||
|           { label: this.isSidebarOpen ? this.translateService.instant("sidebar.members") : "", icon: "pi pi-users", routerLink: "server/members" } | ||||
|         label: this.isSidebarOpen ? this.server$.value?.name : "", icon: "pi pi-server", items: [ | ||||
|           { label: this.isSidebarOpen ? this.translateService.instant("sidebar.profile") : "", icon: "pi pi-user", routerLink: `server/${this.server$.value?.id}/profile` }, | ||||
|           // { label: this.isSidebarOpen ? this.translateService.instant("sidebar.members") : "", icon: "pi pi-users", routerLink: "server/members" } | ||||
|         ] | ||||
|       }; | ||||
|       if (this.serverName$.value != "") { | ||||
|       if (this.server$.value) { | ||||
|         let authUser = await this.authService.getLoggedInUser(); | ||||
|         let user: UserDTO | null = authUser?.users?.find(u => u.server == this.server$.value?.id) ?? null; | ||||
|  | ||||
|         if (user?.isAdmin) { | ||||
|           serverMenu.items.push( | ||||
|             { label: this.isSidebarOpen ? this.translateService.instant("sidebar.members") : "", icon: "pi pi-users", routerLink: `server/${this.server$.value?.id}/members` } | ||||
|           ); | ||||
|         } | ||||
|  | ||||
|         menuItems.push(serverMenu); | ||||
|       } else if (menuItems.find(x => x.icon == "pi pi-server")) { | ||||
|         menuItems.splice(menuItems.indexOf(serverMenu), 1); | ||||
|   | ||||
| @@ -9,8 +9,8 @@ | ||||
|     "dashboard": "Dashboard", | ||||
|     "server": "Server", | ||||
|     "server_empty": "Kein Server ausgewählt", | ||||
|     "settings": "Einstellungen", | ||||
|     "members": "Mitglieder", | ||||
|     "settings": "Einstellungen", | ||||
|     "administration": "Administration", | ||||
|     "config": "Konfiguration", | ||||
|     "auth_user_list": "Benutzer" | ||||
| @@ -146,7 +146,7 @@ | ||||
|       "servers": "Server", | ||||
|       "server": { | ||||
|         "header": "Server", | ||||
|         "member_count": "Mitglid(er)" | ||||
|         "member_count": "Mitglied(er)" | ||||
|       }, | ||||
|       "filter": { | ||||
|         "name": "Name" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user