16 Commits

Author SHA1 Message Date
132d41f0a2 Fixed some stuff 2023-03-26 22:58:56 +02:00
707a835672 Updated docker & config 2023-03-26 20:08:04 +02:00
f56dbf8e2a Merge pull request 'Fixed permission handling for member data #256' (#258) from #256 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#258
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
#Closes #256
2023-03-25 18:01:57 +01:00
c311e534d7 Merge pull request 'Fixed profile navigation #255' (#257) from #255 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#257
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #255
2023-03-25 18:01:41 +01:00
87b277515c Fixed permission handling for member data #256 2023-03-24 14:23:13 +01:00
e6c614dfdc Fixed profile navigation #255 2023-03-24 14:15:21 +01:00
24d5bbf4d8 Made version in presence optional 2023-03-24 14:14:49 +01:00
52035af0cc Fixed jwt handling 2023-03-21 19:14:39 +01:00
fdc9a118c8 Fixed jwt handling 2023-03-20 16:30:07 +01:00
ba1f4ee955 Merge pull request '1.0.0-fix' (#254) from 1.0.0-fix into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#254
2023-03-20 14:41:33 +01:00
35d161c080 Removed obsolete fix 2023-03-20 14:40:56 +01:00
818163cbed Formatted tools 2023-03-20 14:39:23 +01:00
468ebb5f79 Merge branch 'master' into 1.0.0-fix
# Conflicts:
#	kdb-bot/src/bot/__init__.py
#	kdb-bot/src/bot/bot.json
#	kdb-bot/src/bot/config
#	kdb-bot/src/bot/extension/__init__.py
#	kdb-bot/src/bot_api/__init__.py
#	kdb-bot/src/bot_api/abc/__init__.py
#	kdb-bot/src/bot_api/bot-api.json
#	kdb-bot/src/bot_api/configuration/__init__.py
#	kdb-bot/src/bot_api/controller/__init__.py
#	kdb-bot/src/bot_api/event/__init__.py
#	kdb-bot/src/bot_api/exception/__init__.py
#	kdb-bot/src/bot_api/filter/__init__.py
#	kdb-bot/src/bot_api/filter/discord/__init__.py
#	kdb-bot/src/bot_api/logging/__init__.py
#	kdb-bot/src/bot_api/model/__init__.py
#	kdb-bot/src/bot_api/model/discord/__init__.py
#	kdb-bot/src/bot_api/route/__init__.py
#	kdb-bot/src/bot_api/service/__init__.py
#	kdb-bot/src/bot_api/transformer/__init__.py
#	kdb-bot/src/bot_core/__init__.py
#	kdb-bot/src/bot_core/abc/__init__.py
#	kdb-bot/src/bot_core/bot-core.json
#	kdb-bot/src/bot_core/configuration/__init__.py
#	kdb-bot/src/bot_core/core_extension/__init__.py
#	kdb-bot/src/bot_core/events/__init__.py
#	kdb-bot/src/bot_core/exception/__init__.py
#	kdb-bot/src/bot_core/helper/__init__.py
#	kdb-bot/src/bot_core/logging/__init__.py
#	kdb-bot/src/bot_core/pipes/__init__.py
#	kdb-bot/src/bot_core/service/__init__.py
#	kdb-bot/src/bot_data/__init__.py
#	kdb-bot/src/bot_data/abc/__init__.py
#	kdb-bot/src/bot_data/bot-data.json
#	kdb-bot/src/bot_data/migration/__init__.py
#	kdb-bot/src/bot_data/model/__init__.py
#	kdb-bot/src/bot_data/service/__init__.py
#	kdb-bot/src/bot_graphql/__init__.py
#	kdb-bot/src/bot_graphql/abc/__init__.py
#	kdb-bot/src/bot_graphql/filter/__init__.py
#	kdb-bot/src/bot_graphql/mutations/__init__.py
#	kdb-bot/src/modules/auto_role/__init__.py
#	kdb-bot/src/modules/auto_role/auto-role.json
#	kdb-bot/src/modules/auto_role/command/__init__.py
#	kdb-bot/src/modules/auto_role/events/__init__.py
#	kdb-bot/src/modules/auto_role/helper/__init__.py
#	kdb-bot/src/modules/base/__init__.py
#	kdb-bot/src/modules/base/abc/__init__.py
#	kdb-bot/src/modules/base/base.json
#	kdb-bot/src/modules/base/command/__init__.py
#	kdb-bot/src/modules/base/configuration/__init__.py
#	kdb-bot/src/modules/base/events/__init__.py
#	kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py
#	kdb-bot/src/modules/base/helper/__init__.py
#	kdb-bot/src/modules/base/model/__init__.py
#	kdb-bot/src/modules/base/service/__init__.py
#	kdb-bot/src/modules/base/thread/__init__.py
#	kdb-bot/src/modules/boot_log/__init__.py
#	kdb-bot/src/modules/boot_log/boot-log.json
#	kdb-bot/src/modules/boot_log/configuration/__init__.py
#	kdb-bot/src/modules/database/__init__.py
#	kdb-bot/src/modules/database/database.json
#	kdb-bot/src/modules/level/__init__.py
#	kdb-bot/src/modules/level/command/__init__.py
#	kdb-bot/src/modules/level/configuration/__init__.py
#	kdb-bot/src/modules/level/events/__init__.py
#	kdb-bot/src/modules/level/level.json
#	kdb-bot/src/modules/level/service/__init__.py
#	kdb-bot/src/modules/permission/__init__.py
#	kdb-bot/src/modules/permission/abc/__init__.py
#	kdb-bot/src/modules/permission/configuration/__init__.py
#	kdb-bot/src/modules/permission/events/__init__.py
#	kdb-bot/src/modules/permission/permission.json
#	kdb-bot/src/modules/permission/service/__init__.py
#	kdb-bot/src/modules/stats/service/__init__.py
#	kdb-bot/src/modules/stats/stats.json
#	kdb-bot/src/modules/technician/__init__.py
#	kdb-bot/src/modules/technician/command/__init__.py
#	kdb-bot/src/modules/technician/technician.json
#	kdb-bot/tools/get_version/get-version.json
#	kdb-bot/tools/post_build/post-build.json
#	kdb-bot/tools/set_version/set-version.json
2023-03-20 14:39:18 +01:00
e1c89814da Fixed voice state update (ontime) handling 2023-01-19 20:02:56 +01:00
53cdaf3fa0 Added get_ontime_overlaps script 2023-01-19 19:34:03 +01:00
b11ce18ac9 Fixed switch channel handling 2023-01-19 18:35:49 +01:00
24 changed files with 4416 additions and 187 deletions

View File

@@ -14,6 +14,7 @@
"level": "src/modules/level/level.json",
"permission": "src/modules/permission/permission.json",
"technician": "src/modules/technician/technician.json",
"checks": "tools/checks/checks.json",
"get-version": "tools/get_version/get-version.json",
"post-build": "tools/post_build/post-build.json",
"set-version": "tools/set_version/set-version.json"

View File

@@ -15,4 +15,7 @@ RUN apk add nano
RUN pip install -r requirements.txt --extra-index-url https://pip.sh-edraft.de
RUN pip install flask[async]
# RUN pip install dnspython==2.2.1 # https://stackoverflow.com/questions/75137717/eventlet-dns-python-attribute-error-module-dns-rdtypes-has-no-attribute-any
# ^ probably fixed py package updates
CMD [ "bash", "/app/bot/bot"]

View File

@@ -86,10 +86,10 @@
"no_permission_message": "Nein!\nIch höre nicht auf dich ¯\\_(ツ)_/¯",
"not_implemented_yet": "Ey Alter, das kann ich noch nicht...",
"presence": {
"booting": "{} Ich fahre gerade hoch...",
"restart": "{} Muss neue Kekse holen...",
"running": "{} Ich esse Kekse :D",
"shutdown": "{} Ich werde bestimmt wieder kommen..."
"booting": "Ich fahre gerade hoch...",
"restart": "Muss neue Kekse holen...",
"running": "Ich esse Kekse :D",
"shutdown": "Ich werde bestimmt wieder kommen..."
}
},
"modules": {

View File

@@ -129,7 +129,6 @@ class AuthController:
return "", 200
@Route.post(f"{BasePath}/refresh")
@Route.authorize
async def refresh(self) -> Response:
dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True))
result = await self._auth_service.refresh_async(dto)

View File

@@ -10,11 +10,12 @@ class FeatureFlagsEnum(Enum):
boot_log_module = "BootLogModule"
core_module = "CoreModule"
core_extension_module = "CoreExtensionModule"
data_module = ("DataModule",)
database_module = ("DatabaseModule",)
data_module = "DataModule"
database_module = "DatabaseModule"
level_module = "LevelModule"
moderator_module = "ModeratorModule"
permission_module = "PermissionModule"
# features
api_only = "ApiOnly"
presence = "Presence"
version_in_presence = "VersionInPresence"

View File

@@ -1,5 +1,4 @@
import traceback
from typing import Optional, Callable
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.console import Console
@@ -27,6 +26,7 @@ class FeatureFlagsSettings(ConfigurationModelABC):
# features
FeatureFlagsEnum.api_only.value: False, # 13.10.2022 #70
FeatureFlagsEnum.presence.value: True, # 03.10.2022 #56
FeatureFlagsEnum.version_in_presence.value: False, # 21.03.2023 #253
}
def get_flag(self, key: FeatureFlagsEnum) -> bool:

View File

@@ -111,7 +111,11 @@ class ClientUtilsService(ClientUtilsABC):
import bot
name = self._t.transform(t_key).format(bot.__version__)
if self._feature_flags.get_flag(FeatureFlagsEnum.version_in_presence):
name = f"{bot.__version__} {self._t.transform(t_key)}"
else:
name = self._t.transform(t_key)
await self._bot.change_presence(activity=discord.Game(name=name))
self._logger.info(__name__, f"Set presence {name}")

View File

@@ -82,7 +82,7 @@ class QueryABC(ObjectType):
break
elif type(element) == AutoRoleRule:
element: AutoRole = element.game_server
element: AutoRole = element
for u in user.users:
u: User = u
guild = bot.get_guild(u.server.discord_id)
@@ -124,28 +124,36 @@ class QueryABC(ObjectType):
elif type(element) == User:
for u in user.users:
u: User = u
if u.id == element.id:
guild = bot.get_guild(u.server.discord_id)
member = guild.get_member(u.discord_id)
if u.id == element.id or permissions.is_member_moderator(member):
access = True
break
elif type(element) == UserJoinedServer:
for u in user.users:
u: User = u
if u.id == element.user.id:
guild = bot.get_guild(u.server.discord_id)
member = guild.get_member(u.discord_id)
if u.id == element.id or permissions.is_member_moderator(member):
access = True
break
elif type(element) == UserJoinedVoiceChannel:
for u in user.users:
u: User = u
if u.id == element.user.id:
guild = bot.get_guild(u.server.discord_id)
member = guild.get_member(u.discord_id)
if u.id == element.id or permissions.is_member_moderator(member):
access = True
break
elif type(element) == UserJoinedGameServer:
for u in user.users:
u: User = u
if u.id == element.user.id:
guild = bot.get_guild(u.server.discord_id)
member = guild.get_member(u.discord_id)
if u.id == element.id or permissions.is_member_moderator(member):
access = True
break

View File

@@ -1,12 +1,12 @@
from datetime import datetime
from cpl_core.database.context import DatabaseContextABC
from cpl_core.logging import LoggerABC
from cpl_discord.service import DiscordBotServiceABC
from discord import RawReactionActionEvent
from bot_core.abc.client_utils_abc import ClientUtilsABC
from bot_core.helper.log_message_helper import LogMessageHelper
from bot_core.logging.message_logger import MessageLogger
from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.abc.user_repository_abc import UserRepositoryABC
from modules.base.abc.base_helper_abc import BaseHelperABC
@@ -16,7 +16,7 @@ from modules.base.configuration.base_server_settings import BaseServerSettings
class BaseReactionHandler:
def __init__(
self,
logger: LoggerABC,
logger: MessageLogger,
bot: DiscordBotServiceABC,
servers: ServerRepositoryABC,
users: UserRepositoryABC,

View File

@@ -274,6 +274,7 @@ class DatabaseOnReadyEvent(OnReadyABC):
self._logger.debug(__name__, f"Start checking UserJoinedVoiceChannel table")
for guild in self._bot.guilds:
guild: discord.Guild = guild
settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{guild.id}")
server = self._servers.find_server_by_discord_id(guild.id)
if server is None:
@@ -299,7 +300,6 @@ class DatabaseOnReadyEvent(OnReadyABC):
f"Active UserJoinedVoiceChannel found in database: {guild.id}:{member.id}@{join.joined_on}",
)
join.leaved_on = datetime.now()
settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{guild.id}")
if (
(join.leaved_on - join.joined_on).total_seconds() / 60 / 60
@@ -315,7 +315,7 @@ class DatabaseOnReadyEvent(OnReadyABC):
self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot")
continue
if member.voice is None:
if member.voice is None or member.voice.channel.id in settings.afk_channel_ids:
continue
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
# imports

View File

@@ -0,0 +1,44 @@
{
"ProjectSettings": {
"Name": "checks",
"Version": {
"Major": "1",
"Minor": "0",
"Micro": "0"
},
"Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de",
"Description": "CPL internal tool to set version from branch name",
"LongDescription": "CPL internal tool to set version from branch name",
"URL": "https://www.sh-edraft.de",
"CopyrightDate": "2022",
"CopyrightName": "sh-edraft.de",
"LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [
"cpl-core==2022.12.0"
],
"DevDependencies": [
"cpl-cli==2022.12.0"
],
"PythonVersion": ">=3.10.4",
"PythonPath": {},
"Classifiers": []
},
"BuildSettings": {
"ProjectType": "library",
"SourcePath": "",
"OutputPath": "../../dist",
"Main": "checks.main",
"EntryPoint": "checks",
"IncludePackageData": false,
"Included": [],
"Excluded": [
"*/__pycache__",
"*/logs",
"*/tests"
],
"PackageData": {},
"ProjectReferences": []
}
}

View File

@@ -0,0 +1,80 @@
import json
from datetime import datetime
from cpl_query.extension import List
class UserJoinedVoiceChannel:
def __init__(self):
self.JoinId = None
self.UserId = None
self.DiscordChannelId = None
self.JoinedOn = None
self.LeavedOn = None
self.CreatedAt = None
self.LastModifiedAt = None
@property
def ontime(self) -> int:
return round((self.LeavedOn - self.JoinedOn).total_seconds() / 3600, 2)
def from_dict(self, data: dict):
self.JoinId = data["JoinId"]
self.UserId = data["UserId"]
self.DiscordChannelId = data["DiscordChannelId"]
self.JoinedOn = datetime.strptime(data["JoinedOn"], "%Y-%m-%d %H:%M:%S.%f")
self.LeavedOn = datetime.strptime(data["LeavedOn"], "%Y-%m-%d %H:%M:%S.%f")
self.CreatedAt = data["CreatedAt"]
self.LastModifiedAt = data["LastModifiedAt"]
def __repr__(self):
return f"{self.JoinId}: {self.UserId} {self.JoinedOn} {self.LeavedOn}"
def main():
data = json.loads(open("UserJoinedVoiceChannel.json", "r").read())
ujvcs = List(UserJoinedVoiceChannel)
for x in data:
ujvc = UserJoinedVoiceChannel()
ujvc.from_dict(x)
ujvcs.append(ujvc)
users = ujvcs.order_by(lambda x: x.UserId).select(lambda x: x.UserId).distinct()
groups = {}
for user in users:
groups[user] = List(UserJoinedVoiceChannel)
groups[user].extend(ujvcs.where(lambda x: x.UserId == user))
for group in groups:
values: List[UserJoinedVoiceChannel] = groups[group]
def find_overlaps(x: UserJoinedVoiceChannel) -> bool:
for y in values:
if x == y:
continue
from collections import namedtuple
Range = namedtuple("Range", ["start", "end"])
r1 = Range(start=x.JoinedOn, end=x.LeavedOn)
r2 = Range(start=y.LeavedOn, end=y.LeavedOn)
latest_start = max(r1.start, r2.start)
earliest_end = min(r1.end, r2.end)
delta = (earliest_end - latest_start).days + 1
overlap = max(0, delta)
if overlap > 0:
return True
overlaps = values.where(find_overlaps)
if overlaps.count() == 0:
continue
print(overlaps.select(lambda x: x.JoinId))
print(f"{group} has {overlaps.count()} of {values.count()}")
ontime = overlaps.sum(lambda x: x.ontime)
print(f"ontime: {ontime}")
print(f"xp: {ontime * 8}")
if __name__ == "__main__":
main()

View File

@@ -1,18 +1,19 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { LangChangeEvent, TranslateService } from '@ngx-translate/core';
import { MenuItem, PrimeNGConfig } from 'primeng/api';
import { catchError } from 'rxjs/operators';
import { AuthService } from 'src/app/services/auth/auth.service';
import { SettingsService } from 'src/app/services/settings/settings.service';
import { SpinnerService } from 'src/app/services/spinner/spinner.service';
import { ThemeService } from 'src/app/services/theme/theme.service';
import { Component, OnInit } from "@angular/core";
import { Router } from "@angular/router";
import { LangChangeEvent, TranslateService } from "@ngx-translate/core";
import { MenuItem, PrimeNGConfig } from "primeng/api";
import { catchError } from "rxjs/operators";
import { AuthService } from "src/app/services/auth/auth.service";
import { SettingsService } from "src/app/services/settings/settings.service";
import { SpinnerService } from "src/app/services/spinner/spinner.service";
import { ThemeService } from "src/app/services/theme/theme.service";
import { throwError } from "rxjs";
import { SidebarService } from "../../services/sidebar/sidebar.service";
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
selector: "app-header",
templateUrl: "./header.component.html",
styleUrls: ["./header.component.scss"]
})
export class HeaderComponent implements OnInit {
langList: MenuItem[] = [];
@@ -26,8 +27,10 @@ export class HeaderComponent implements OnInit {
private spinnerService: SpinnerService,
private settings: SettingsService,
private translateService: TranslateService,
private config: PrimeNGConfig
) { }
private config: PrimeNGConfig,
private sidebarService: SidebarService,
) {
}
ngOnInit(): void {
this.initMenuLists();
@@ -38,9 +41,12 @@ export class HeaderComponent implements OnInit {
}
initUserMenuList(): void {
if (!this.authService.isLoggedIn$.value) {
return;
}
this.spinnerService.showSpinner();
const mail = this.authService.getEMailFromDecodedToken(this.authService.getDecodedToken());
this.authService.getUserByEMail(mail ?? '')
this.authService.getUserByEMail(mail ?? "")
.pipe(catchError(error => {
this.spinnerService.hideSpinner();
this.authService.logout();
@@ -48,7 +54,7 @@ export class HeaderComponent implements OnInit {
}))
.subscribe(user => {
this.spinnerService.hideSpinner();
this.sidebarService.setMenu(true);
this.userMenuList = [
{
@@ -59,22 +65,22 @@ export class HeaderComponent implements OnInit {
separator: true
},
{
label: this.translateService.instant('header.change_password'), command: () => {
label: this.translateService.instant("header.change_password"), command: () => {
this.changePassword();
},
icon: 'pi pi-key'
icon: "pi pi-key"
},
{
label: this.translateService.instant('header.settings'), command: () => {
label: this.translateService.instant("header.settings"), command: () => {
this.userSettings();
},
icon: 'pi pi-cog'
icon: "pi pi-cog"
},
{
label: this.translateService.instant('header.logout'), command: () => {
label: this.translateService.instant("header.logout"), command: () => {
this.logout();
},
icon: 'pi pi-sign-out'
icon: "pi pi-sign-out"
}
];
});
@@ -83,17 +89,17 @@ export class HeaderComponent implements OnInit {
initMenuLists(): void {
this.langList = [
{
label: 'English', command: () => {
this.translate('en');
this.setLang('en');
},
label: "English", command: () => {
this.translate("en");
this.setLang("en");
}
},
{
label: 'Deutsch', command: () => {
this.translate('de');
this.setLang('de');
},
},
label: "Deutsch", command: () => {
this.translate("de");
this.setLang("de");
}
}
];
this.initUserMenuList();
@@ -117,11 +123,11 @@ export class HeaderComponent implements OnInit {
}
changePassword(): void {
this.router.navigate(['/change-password']);
this.router.navigate(["/change-password"]);
}
userSettings(): void {
this.router.navigate(['/user-settings']);
this.router.navigate(["/user-settings"]);
}
logout(): void {
@@ -130,7 +136,7 @@ export class HeaderComponent implements OnInit {
translate(lang: string) {
this.translateService.use(lang);
this.translateService.get('primeng').subscribe(res => this.config.setTranslation(res));
this.translateService.get("primeng").subscribe(res => this.config.setTranslation(res));
}
loadLang(): void {
@@ -138,28 +144,26 @@ export class HeaderComponent implements OnInit {
const mail = this.authService.getEMailFromDecodedToken(token);
if (!mail) {
this.translate('en');
this.translate("en");
return;
}
let lang = localStorage.getItem(`${mail}_lang`);
if (!lang) {
lang = 'en';
lang = "en";
this.setLang(lang);
}
this.translate(lang);
}
setLang(lang: string): void {
this.authService.isUserLoggedInAsync().then(result => {
if (!result) {
return;
}
if (!this.authService.isLoggedIn$.value) {
return;
}
const token = this.authService.getDecodedToken();
const mail = this.authService.getEMailFromDecodedToken(token);
localStorage.setItem(`${mail}_lang`, lang);
});
const token = this.authService.getDecodedToken();
const mail = this.authService.getEMailFromDecodedToken(token);
localStorage.setItem(`${mail}_lang`, lang);
}
}

View File

@@ -1,18 +1,18 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { catchError } from 'rxjs/operators';
import { ResetPasswordDTO } from 'src/app/models/auth/reset-password.dto';
import { AuthService } from 'src/app/services/auth/auth.service';
import { SpinnerService } from 'src/app/services/spinner/spinner.service';
import { ToastService } from 'src/app/services/toast/toast.service';
import { Component, OnInit } from "@angular/core";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { ActivatedRoute, Router } from "@angular/router";
import { TranslateService } from "@ngx-translate/core";
import { catchError } from "rxjs/operators";
import { ResetPasswordDTO } from "src/app/models/auth/reset-password.dto";
import { AuthService } from "src/app/services/auth/auth.service";
import { SpinnerService } from "src/app/services/spinner/spinner.service";
import { ToastService } from "src/app/services/toast/toast.service";
import { throwError } from "rxjs";
@Component({
selector: 'app-forget-password',
templateUrl: './forget-password.component.html',
styleUrls: ['./forget-password.component.scss']
selector: "app-forget-password",
templateUrl: "./forget-password.component.html",
styleUrls: ["./forget-password.component.scss"]
})
export class ForgetPasswordComponent implements OnInit {
@@ -35,19 +35,18 @@ export class ForgetPasswordComponent implements OnInit {
private route: ActivatedRoute,
private toastService: ToastService,
private translate: TranslateService
) { }
) {
}
ngOnInit(): void {
this.spinnerService.showSpinner();
this.authService.isUserLoggedInAsync().then(result => {
if (result) {
this.router.navigate(['/dashboard']);
}
if (!this.authService.isLoggedIn$.value) {
this.router.navigate(["/dashboard"]);
}
this.initForms();
this.checkResetPasswordId();
this.spinnerService.hideSpinner();
});
this.initForms();
this.checkResetPasswordId();
this.spinnerService.hideSpinner();
}
initForms(): void {
@@ -62,11 +61,11 @@ export class ForgetPasswordComponent implements OnInit {
}
login(): void {
this.router.navigate(['/auth/login']);
this.router.navigate(["/auth/login"]);
}
register(): void {
this.router.navigate(['/auth/register']);
this.router.navigate(["/auth/register"]);
}
forgotPassword(): void {
@@ -82,35 +81,37 @@ export class ForgetPasswordComponent implements OnInit {
this.spinnerService.hideSpinner();
return throwError(() => error);
})).subscribe(res => {
this.spinnerService.hideSpinner();
this.ready = true;
setTimeout(() => { this.router.navigate(['/dashboard']); }, 5000);
});
this.spinnerService.hideSpinner();
this.ready = true;
setTimeout(() => {
this.router.navigate(["/dashboard"]);
}, 5000);
});
}
checkResetPasswordId(): void {
const id = this.route.snapshot.params['id'];
const id = this.route.snapshot.params["id"];
if (id) {
this.resetPasswordId = id;
this.spinnerService.showSpinner();
this.authService.getEMailFromforgotPasswordId(id)
.pipe(catchError(error => {
this.spinnerService.hideSpinner();
this.router.navigate(['/auth/forgot-password']);
return throwError(() => error);
this.router.navigate(["/auth/forgot-password"]);
return throwError(() => error);
})).subscribe(email => {
this.spinnerService.hideSpinner();
if (email) {
this.emailForm.value.email = email;
} else {
this.router.navigate(['/auth/forgot-password']);
}
});
this.spinnerService.hideSpinner();
if (email) {
this.emailForm.value.email = email;
} else {
this.router.navigate(["/auth/forgot-password"]);
}
});
}
}
resetPassword(): void {
const id = this.route.snapshot.params['id'];
const id = this.route.snapshot.params["id"];
if (this.emailForm.value.password !== this.emailForm.value.passwordRepeat) {
this.repeatErrors.password = true;
return;
@@ -124,14 +125,14 @@ export class ForgetPasswordComponent implements OnInit {
this.authService.resetPassword(resetPasswordDTO)
.pipe(catchError(error => {
this.router.navigate(['/auth/login']);
this.router.navigate(["/auth/login"]);
this.spinnerService.hideSpinner();
return throwError(() => error);
}))
.subscribe(resp => {
this.spinnerService.hideSpinner();
this.toastService.success(this.translate.instant('auth.forgot_password.message.reset_password'), this.translate.instant('auth.forgot_password.message.reset_password_d'));
this.router.navigate(['/auth/login']);
this.toastService.success(this.translate.instant("auth.forgot_password.message.reset_password"), this.translate.instant("auth.forgot_password.message.reset_password_d"));
this.router.navigate(["/auth/login"]);
});
}
}

View File

@@ -48,16 +48,14 @@ export class LoginComponent implements OnInit {
ngOnInit(): void {
this.initLoginForm();
this.spinnerService.showSpinner();
this.authService.isUserLoggedInAsync().then(result => {
if (result) {
this.router.navigate(["/dashboard"]);
return;
}
if (this.authService.isLoggedIn$.value) {
this.router.navigate(["/dashboard"]);
return;
}
this.checkDiscordLogin();
this.resetStateFlags();
this.spinnerService.hideSpinner();
});
this.checkDiscordLogin();
this.resetStateFlags();
this.spinnerService.hideSpinner();
}
checkDiscordLogin() {

View File

@@ -49,12 +49,10 @@ export class RegistrationComponent implements OnInit, OnDestroy {
private settings: SettingsService
) {
this.spinnerService.showSpinner();
this.authService.isUserLoggedInAsync().then(res => {
if (res) {
this.router.navigate(["/dashboard"]);
}
this.spinnerService.hideSpinner();
});
if (!this.authService.isLoggedIn$.value) {
this.router.navigate(["/dashboard"]);
}
this.spinnerService.hideSpinner();
}
ngOnInit(): void {

View File

@@ -1,4 +1,4 @@
import { Component, OnInit } from "@angular/core";
import { Component, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { Queries } from "../../../../models/graphql/queries.model";
import { UserListQuery } from "../../../../models/graphql/query.model";
@@ -10,17 +10,21 @@ import { AuthService } from "src/app/services/auth/auth.service";
import { ToastService } from "src/app/services/toast/toast.service";
import { TranslateService } from "@ngx-translate/core";
import { Server } from "../../../../models/data/server.model";
import { Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";
@Component({
selector: "app-profile",
templateUrl: "./profile.component.html",
styleUrls: ["./profile.component.scss"]
})
export class ProfileComponent implements OnInit {
export class ProfileComponent implements OnInit, OnDestroy {
user: User = { createdAt: "", modifiedAt: "" };
private server: Server = {};
private unsubscriber = new Subject<void>();
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -32,42 +36,47 @@ export class ProfileComponent implements OnInit {
) {
}
ngOnInit() {
this.data.getServerFromRoute(this.route).then(async (server) => {
if (!this.route.snapshot.params["memberId"] || this.route.snapshot.params["memberId"] == "undefined") {
this.router.navigate([`/server/${server.id}`]);
return;
}
this.server = server;
public ngOnInit(): void {
this.route.params.pipe(takeUntil(this.unsubscriber)).subscribe(params => {
this.data.getServerFromRoute(this.route).then(async (server) => {
if (!params["memberId"] || params["memberId"] == "undefined") {
await this.router.navigate([`/server/${server.id}`]);
return;
}
this.server = server;
let authUser = await this.auth.getLoggedInUser();
this.spinner.showSpinner();
let user: UserDTO | null = authUser?.users?.find(u => u.server == server.id) ?? null;
if (!user || user?.id != this.route.snapshot.params["memberId"] && !user?.isModerator) {
this.toast.error(this.translate.instant("view.server.profile.permission_denied"), this.translate.instant("view.server.profile.permission_denied_d"));
this.spinner.hideSpinner();
this.router.navigate(["/server", server.id]);
return;
}
let authUser = await this.auth.getLoggedInUser();
this.spinner.showSpinner();
let user: UserDTO | null = authUser?.users?.find(u => u.server == server.id) ?? null;
if (!user || user?.id != params["memberId"] && !user?.isModerator) {
this.toast.error(this.translate.instant("view.server.profile.permission_denied"), this.translate.instant("view.server.profile.permission_denied_d"));
this.spinner.hideSpinner();
await this.router.navigate(["/server", server.id]);
return;
}
this.data.query<UserListQuery>(Queries.usersQuery, {
serverId: this.server.id,
filter: {
id: this.route.snapshot.params["memberId"]
this.data.query<UserListQuery>(Queries.usersQuery, {
serverId: this.server.id,
filter: {
id: params["memberId"]
}
},
(x: { servers: Server[] }) => {
return x.servers[0];
}
},
(x: { servers: Server[] }) => {
return x.servers[0];
}
).subscribe(users => {
if (!users.users[0]) {
this.router.navigate([`/server/${server.id}`]);
}
this.user = users.users[0];
this.spinner.hideSpinner();
).subscribe(users => {
if (!users.users[0]) {
this.router.navigate([`/server/${server.id}`]);
}
this.user = users.users[0];
this.spinner.hideSpinner();
});
});
});
}
public ngOnDestroy(): void {
this.unsubscriber.next();
this.unsubscriber.complete();
}
}

View File

@@ -2,7 +2,7 @@ import { HttpClient, HttpHeaders } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Router } from "@angular/router";
import { JwtHelperService } from "@auth0/angular-jwt";
import { firstValueFrom, Observable, Subject, Subscription, throwError } from "rxjs";
import { BehaviorSubject, firstValueFrom, Observable, Subject, Subscription, throwError } from "rxjs";
import { catchError } from "rxjs/operators";
import { AdminUpdateUserDTO } from "src/app/models/auth/admin-update-user.dto";
import { AuthRoles } from "src/app/models/auth/auth-roles.enum";
@@ -23,8 +23,7 @@ import { OAuthDTO } from "../../models/auth/oauth.dto";
})
export class AuthService {
private isLoggedIn!: boolean;
isLoggedIn$ = new Subject<boolean>();
isLoggedIn$ = new BehaviorSubject<boolean>(false);
constructor(
private appsettings: SettingsService,
@@ -33,9 +32,6 @@ export class AuthService {
private jwtHelper: JwtHelperService,
private spinnerService: SpinnerService
) {
this.isLoggedIn$.subscribe(value => {
this.isLoggedIn = value;
});
}
/* data requests */
@@ -212,7 +208,7 @@ export class AuthService {
getDecodedToken(token: TokenDTO | undefined = undefined): { [key: string]: any } | null {
if (token) {
return this.jwtHelper.decodeToken(token.token);
return this.jwtHelper.decodeToken(token.token);
}
return this.jwtHelper.decodeToken(this.getToken().token);
@@ -279,16 +275,12 @@ export class AuthService {
return false;
}
if (this.isLoggedIn) {
this.spinnerService.showSpinner();
const resfreshedToken = await firstValueFrom(await this.refresh(token));
this.spinnerService.hideSpinner();
if (resfreshedToken) {
this.saveToken(resfreshedToken);
return true;
}
this.spinnerService.showSpinner();
const resfreshedToken = await firstValueFrom(await this.refresh(token));
this.spinnerService.hideSpinner();
if (resfreshedToken) {
this.saveToken(resfreshedToken);
return true;
}
return false;

View File

@@ -4,18 +4,18 @@ import { Themes } from "src/app/models/view/themes.enum";
import { AuthService } from "../auth/auth.service";
@Injectable({
providedIn: 'root'
providedIn: "root"
})
export class ThemeService {
themeName: string = Themes.Default;
sidebarWidth = '150px';
sidebarWidth = "150px";
isSidebarOpen = false;
themeName$ = new BehaviorSubject<string>(Themes.Default);
isSidebarOpen$ = new BehaviorSubject<boolean>(true);
sidebarWidth$ = new BehaviorSubject<string>('175px');
sidebarWidth$ = new BehaviorSubject<string>("175px");
constructor(
private authService: AuthService
@@ -25,7 +25,7 @@ export class ThemeService {
});
this.isSidebarOpen$.subscribe(isSidebarOpen => {
this.isSidebarOpen = isSidebarOpen;
this.sidebarWidth$.next(isSidebarOpen ? '175px' : '75px');
this.sidebarWidth$.next(isSidebarOpen ? "175px" : "75px");
});
this.sidebarWidth$.subscribe(sidebarWidth => {
this.sidebarWidth = sidebarWidth;
@@ -63,20 +63,18 @@ export class ThemeService {
return;
}
this.authService.isUserLoggedInAsync().then(result => {
if (!result) {
localStorage.setItem(`default_themeName`, Themes.Default);
this.themeName$.next(Themes.Default);
}
if (!this.authService.isLoggedIn$.value) {
localStorage.setItem(`default_themeName`, Themes.Default);
this.themeName$.next(Themes.Default);
}
const token = this.authService.getDecodedToken();
const mail = this.authService.getEMailFromDecodedToken(token);
if (mail) {
localStorage.setItem(`${mail}_themeName`, name);
}
localStorage.setItem(`default_themeName`, name);
this.themeName$.next(name);
});
const token = this.authService.getDecodedToken();
const mail = this.authService.getEMailFromDecodedToken(token);
if (mail) {
localStorage.setItem(`${mail}_themeName`, name);
}
localStorage.setItem(`default_themeName`, name);
this.themeName$.next(name);
}
loadMenu() {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 948 B

After

Width:  |  Height:  |  Size: 69 KiB