Mitglieder auf einem Server anzeigen #130 #206
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user