1.0.0 #253

Merged
edraft merged 262 commits from 1.0.0 into master 2023-03-27 09:30:50 +02:00
17 changed files with 112 additions and 91 deletions
Showing only changes of commit 54b0086a14 - Show all commits

View File

@ -71,7 +71,7 @@ class AuthController:
@Route.post(f"{BasePath}/register")
async def register(self):
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
await self._auth_service.add_auth_user(dto)
self._auth_service.add_auth_user(dto)
return "", 200
@Route.post(f"{BasePath}/register-by-id/<id>")

View File

@ -80,6 +80,9 @@ class AuthService(AuthServiceABC):
@staticmethod
def _is_email_valid(email: str) -> bool:
if email is None:
raise False
if re.fullmatch(_email_regex, email) is not None:
return True

View File

@ -63,7 +63,7 @@ class QueryABC(ObjectType):
return self._resolve_collection(collection, *args, **kwargs)
self.set_field(f"{name}s", wrapper)
self.set_field(f"{name}Count", lambda *args: get_collection(*args).count())
self.set_field(f"{name}Count", lambda *args: wrapper(*args).count())
@ServiceProviderABC.inject
def _can_user_see_element(self, user: AuthUser, element, services: ServiceProviderABC) -> bool:

View File

@ -1,6 +1,6 @@
{
"name": "kdb-web",
"version": "1.0.0.rc1",
"version": "1.0.dev247",
"scripts": {
"ng": "ng",
"update-version": "ts-node-esm update-version.ts",

View File

@ -4,6 +4,7 @@ import { SoftwareVersion } from "src/app/models/config/software-version";
import { GuiService } from "src/app/services/gui/gui.service";
import { SettingsService } from "src/app/services/settings/settings.service";
import { SpinnerService } from "src/app/services/spinner/spinner.service";
import { throwError } from "rxjs";
@Component({
selector: 'app-footer',
@ -27,9 +28,9 @@ export class FooterComponent implements OnInit {
this.spinnerService.showSpinner();
this.guiService.getApiVersion()
.pipe(catchError(err => {
.pipe(catchError(error => {
this.spinnerService.hideSpinner();
throw err;
return throwError(() => error);
}))
.subscribe(version => {
this.spinnerService.hideSpinner();

View File

@ -7,6 +7,7 @@ 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";
@Component({
selector: 'app-header',
@ -40,10 +41,10 @@ export class HeaderComponent implements OnInit {
this.spinnerService.showSpinner();
const mail = this.authService.getEMailFromDecodedToken(this.authService.getDecodedToken());
this.authService.getUserByEMail(mail ?? '')
.pipe(catchError(err => {
.pipe(catchError(error => {
this.spinnerService.hideSpinner();
this.authService.logout();
throw err;
return throwError(() => error);
}))
.subscribe(user => {
this.spinnerService.hideSpinner();

View File

@ -18,9 +18,9 @@ import { TranslateService } from "@ngx-translate/core";
@Component({
selector: 'app-auth-user',
templateUrl: './auth-user.component.html',
styleUrls: ['./auth-user.component.scss']
selector: "app-auth-user",
templateUrl: "./auth-user.component.html",
styleUrls: ["./auth-user.component.scss"]
})
export class AuthUserComponent implements OnInit {
@ -35,7 +35,7 @@ export class AuthUserComponent implements OnInit {
authRoles = [
{ label: AuthRoles[AuthRoles.Normal].toString(), value: AuthRoles.Normal },
{ label: AuthRoles[AuthRoles.Admin].toString(), value: AuthRoles.Admin }
]
];
newUserTemplate: AuthUserDTO = {
id: 0,
@ -71,10 +71,11 @@ export class AuthUserComponent implements OnInit {
private confirmDialog: ConfirmationDialogService,
private fb: FormBuilder,
private translate: TranslateService
) { }
) {
}
ngOnInit(): void {
this.loggedInUserEMail = this.authService.getEMailFromDecodedToken(this.authService.getDecodedToken()) ?? '';
this.loggedInUserEMail = this.authService.getEMailFromDecodedToken(this.authService.getDecodedToken()) ?? "";
this.searchCriterions = {
firstName: null,
lastName: null,
@ -92,10 +93,10 @@ export class AuthUserComponent implements OnInit {
setFilterForm() {
this.filterForm = this.fb.group({
firstName: [''],
lastName: [''],
email: [''],
authRole: ['']
firstName: [""],
lastName: [""],
email: [""],
authRole: [""]
});
this.filterForm.valueChanges.pipe(
@ -152,14 +153,14 @@ export class AuthUserComponent implements OnInit {
if (event.first != null && event.rows != null)
this.searchCriterions.pageIndex = event.first / event.rows;
this.searchCriterions.sortColumn = event.sortField ?? null;
this.searchCriterions.sortDirection = event.sortOrder === 1 ? 'asc' : event.sortOrder === -1 ? 'desc' : 'asc';
this.searchCriterions.sortDirection = event.sortOrder === 1 ? "asc" : event.sortOrder === -1 ? "desc" : "asc";
if (event.filters) {
// + "" => convert to string
this.searchCriterions.firstName = event.filters['firstName'] ? event.filters['firstName'] + "" : null;
this.searchCriterions.lastName = event.filters['lastName'] ? event.filters['lastName'] + "" : null;
this.searchCriterions.email = event.filters['email'] ? event.filters['email'] + "" : null;
this.searchCriterions.authRole = event.filters['authRole'] ? +event.filters['authRole'] : null;
this.searchCriterions.firstName = event.filters["firstName"] ? event.filters["firstName"] + "" : null;
this.searchCriterions.lastName = event.filters["lastName"] ? event.filters["lastName"] + "" : null;
this.searchCriterions.email = event.filters["email"] ? event.filters["email"] + "" : null;
this.searchCriterions.authRole = event.filters["authRole"] ? +event.filters["authRole"] : null;
}
this.loadNextPage();
@ -172,9 +173,9 @@ export class AuthUserComponent implements OnInit {
initUserList(): void {
this.spinnerService.showSpinner();
this.authService.getAllUsers()
.pipe(catchError(err => {
.pipe(catchError(error => {
this.spinnerService.hideSpinner();
throw err;
return throwError(() => error);
}))
.subscribe(users => {
this.users = users;
@ -226,22 +227,22 @@ export class AuthUserComponent implements OnInit {
if (err.errorCode === ServiceErrorCode.InvalidData && err.message === RegisterErrorMessages.InvalidEMail) {
this.isEMailInvalid = true;
this.toastService.error(this.translate.instant('admin.auth_users.message.invalid_email'), this.translate.instant('admin.auth_users.message.invalid_email_d', { email: newUser.email }));
this.toastService.error(this.translate.instant("admin.auth_users.message.invalid_email"), this.translate.instant("admin.auth_users.message.invalid_email_d", { email: newUser.email }));
} else if (err.errorCode === ServiceErrorCode.InvalidUser && err.message === RegisterErrorMessages.UserAlreadyExists) {
this.isEMailInvalid = true;
this.toastService.error(this.translate.instant('admin.auth_users.message.user_already_exists'), this.translate.instant('admin.auth_users.message.user_already_exists_d', { email: newUser.email }));
this.toastService.error(this.translate.instant("admin.auth_users.message.user_already_exists"), this.translate.instant("admin.auth_users.message.user_already_exists_d", { email: newUser.email }));
}
error.error = null;
table.initRowEdit(newUser);
}
this.spinnerService.hideSpinner();
throw error;
return throwError(() => error);
}))
.subscribe(_ => {
this.initUserList();
this.spinnerService.hideSpinner();
this.toastService.success(this.translate.instant('admin.auth_users.message.user_added'), this.translate.instant('admin.auth_users.message.user_added_d', { email: newUser.email }));
this.toastService.success(this.translate.instant("admin.auth_users.message.user_added"), this.translate.instant("admin.auth_users.message.user_added_d", { email: newUser.email }));
this.isEditingNew = false;
});
this.triggerUserChangeDetection();
@ -253,16 +254,16 @@ export class AuthUserComponent implements OnInit {
authUserDTO: oldUser,
newAuthUserDTO: newUser,
changePassword: newUser.password != ""
}).pipe(catchError(err => {
}).pipe(catchError(error => {
this.spinnerService.hideSpinner();
this.toastService.error(this.translate.instant('admin.auth_users.message.user_change_failed'), this.translate.instant('admin.auth_users.message.user_change_failed_d', { email: newUser.email }));
this.toastService.error(this.translate.instant("admin.auth_users.message.user_change_failed"), this.translate.instant("admin.auth_users.message.user_change_failed_d", { email: newUser.email }));
this.initUserList();
throw err;
return throwError(() => error);
}))
.subscribe(_ => {
this.initUserList();
this.spinnerService.hideSpinner();
this.toastService.success(this.translate.instant('admin.auth_users.message.user_changed'), this.translate.instant('admin.auth_users.message.user_changed_d', { email: newUser.email }));
this.toastService.success(this.translate.instant("admin.auth_users.message.user_changed"), this.translate.instant("admin.auth_users.message.user_changed_d", { email: newUser.email }));
});
this.triggerUserChangeDetection();
}
@ -288,30 +289,32 @@ export class AuthUserComponent implements OnInit {
deleteUser(user: AuthUserDTO) {
if (user.email == this.loggedInUserEMail) {
this.toastService.error(this.translate.instant('admin.auth_users.message.cannot_delete_user'), this.translate.instant('admin.auth_users.message.logon_with_another_user'));
this.toastService.error(this.translate.instant("admin.auth_users.message.cannot_delete_user"), this.translate.instant("admin.auth_users.message.logon_with_another_user"));
return;
}
this.confirmDialog.confirmDialog(
this.translate.instant('admin.auth_users.message.user_delete'), this.translate.instant('admin.auth_users.message.user_delete_q', { email: user.email }),
this.translate.instant("admin.auth_users.message.user_delete"), this.translate.instant("admin.auth_users.message.user_delete_q", { email: user.email }),
() => {
this.spinnerService.showSpinner();
this.authService.deleteUserByMail(user.email ?? '')
.pipe(catchError(err => {
this.authService.deleteUserByMail(user.email ?? "")
.pipe(catchError(error => {
this.spinnerService.hideSpinner();
throw err;
return throwError(() => error);
}))
.subscribe(_ => {
this.initUserList();
this.spinnerService.hideSpinner();
this.toastService.success(this.translate.instant('admin.auth_users.message.user_deleted'), this.translate.instant('admin.auth_users.message.user_deleted_d', { email: user.email }));
this.toastService.success(this.translate.instant("admin.auth_users.message.user_deleted"), this.translate.instant("admin.auth_users.message.user_deleted_d", { email: user.email }));
});
});
}
addUser(table: Table) {
const newUser = JSON.parse(JSON.stringify(this.newUserTemplate));
newUser.id = Math.max.apply(Math, this.users.map(u => { return u.id ?? 0; })) + 1;
newUser.id = Math.max.apply(Math, this.users.map(u => {
return u.id ?? 0;
})) + 1;
this.users.push(newUser);
this.triggerUserChangeDetection();

View File

@ -10,6 +10,7 @@ import { GuiService } from 'src/app/services/gui/gui.service';
import { SettingsService } from 'src/app/services/settings/settings.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-settings',
@ -50,9 +51,9 @@ export class SettingsComponent implements OnInit {
this.initForms();
this.guiService.getSettings()
.pipe(catchError(err => {
.pipe(catchError(error => {
this.spinnerService.hideSpinner();
throw err;
return throwError(() => error);
}))
.subscribe(settings => {
this.spinnerService.hideSpinner();
@ -109,7 +110,7 @@ export class SettingsComponent implements OnInit {
this.spinnerService.hideSpinner();
this.toastService.error(header, message);
throw error;
return throwError(() => error);
}))
.subscribe(res => {
this.spinnerService.hideSpinner();

View File

@ -7,6 +7,7 @@ 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',
@ -77,9 +78,9 @@ export class ForgetPasswordComponent implements OnInit {
this.spinnerService.showSpinner();
this.authService.forgotPassword(this.emailForm.value.email)
.pipe(catchError(err => {
.pipe(catchError(error => {
this.spinnerService.hideSpinner();
throw err;
return throwError(() => error);
})).subscribe(res => {
this.spinnerService.hideSpinner();
this.ready = true;
@ -93,10 +94,10 @@ export class ForgetPasswordComponent implements OnInit {
this.resetPasswordId = id;
this.spinnerService.showSpinner();
this.authService.getEMailFromforgotPasswordId(id)
.pipe(catchError(err => {
.pipe(catchError(error => {
this.spinnerService.hideSpinner();
this.router.navigate(['/auth/forgot-password']);
throw err;
return throwError(() => error);
})).subscribe(email => {
this.spinnerService.hideSpinner();
if (email) {
@ -125,7 +126,7 @@ export class ForgetPasswordComponent implements OnInit {
.pipe(catchError(error => {
this.router.navigate(['/auth/login']);
this.spinnerService.hideSpinner();
throw error;
return throwError(() => error);
}))
.subscribe(resp => {
this.spinnerService.hideSpinner();

View File

@ -146,17 +146,20 @@ export class LoginComponent implements OnInit {
if (err.errorCode === ServiceErrorCode.InvalidData && err.message === AuthErrorMessages.UserIsEmpty) {
this.authUserAtrErrors.email.required = true;
this.authUserAtrErrors.password.required = true;
error.error = null;
} else if (err.errorCode === ServiceErrorCode.InvalidUser && err.message === AuthErrorMessages.UserNotFound) {
this.authUserAtrErrors.email.wrongData = true;
error.error = null;
} else if (err.errorCode === ServiceErrorCode.InvalidUser && err.message === AuthErrorMessages.WrongPassword) {
this.authUserAtrErrors.password.wrongData = true;
error.error = null;
} else if (err.errorCode === ServiceErrorCode.InvalidUser && err.message === AuthErrorMessages.EMailNotConfirmed) {
this.authUserAtrErrors.email.notConfirmed = true;
error.error = null;
}
error.error = null;
}
this.spinnerService.hideSpinner();
throw error;
return throwError(() => error);
}))
.subscribe(token => {
this.authService.saveToken(token);

View File

@ -127,7 +127,7 @@ export class RegistrationComponent implements OnInit {
}
}
this.spinnerService.hideSpinner();
throw error;
return throwError(() => error);
}))
.subscribe(resp => {
this.spinnerService.hideSpinner();
@ -143,7 +143,7 @@ export class RegistrationComponent implements OnInit {
.pipe(catchError(error => {
this.router.navigate(["/auth/login"]);
this.spinnerService.hideSpinner();
throw error;
return throwError(() => error);
}))
.subscribe(resp => {
this.spinnerService.hideSpinner();

View File

@ -10,6 +10,7 @@ import { ServiceErrorCode } from 'src/app/models/error/service-error-code.enum';
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-change-password',
@ -95,7 +96,8 @@ export class ChangePasswordComponent implements OnInit {
}
this.spinnerService.hideSpinner();
this.toastService.error(this.translate.instant('view.change_password.message.error'), this.translate.instant('view.change_password.message.password_cannot_be_changed'));
throw error;
return throwError(() => error);
}))
.subscribe(resp => {
this.spinnerService.hideSpinner();

View File

@ -1,22 +1,23 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { catchError } from 'rxjs/operators';
import { AuthErrorMessages } from 'src/app/models/auth/auth-error-messages.enum';
import { AuthUserDTO } from 'src/app/models/auth/auth-user.dto';
import { UpdateUserDTO } from 'src/app/models/auth/update-user.dto';
import { ErrorDTO } from 'src/app/models/error/error-dto';
import { ServiceErrorCode } from 'src/app/models/error/service-error-code.enum';
import { AuthService } from 'src/app/services/auth/auth.service';
import { SpinnerService } from 'src/app/services/spinner/spinner.service';
import { ThemeService } from 'src/app/services/theme/theme.service';
import { ToastService } from 'src/app/services/toast/toast.service';
import { Component, OnInit } from "@angular/core";
import { FormBuilder, FormControl, FormGroup, Validators } from "@angular/forms";
import { Router } from "@angular/router";
import { TranslateService } from "@ngx-translate/core";
import { catchError } from "rxjs/operators";
import { AuthErrorMessages } from "src/app/models/auth/auth-error-messages.enum";
import { AuthUserDTO } from "src/app/models/auth/auth-user.dto";
import { UpdateUserDTO } from "src/app/models/auth/update-user.dto";
import { ErrorDTO } from "src/app/models/error/error-dto";
import { ServiceErrorCode } from "src/app/models/error/service-error-code.enum";
import { AuthService } from "src/app/services/auth/auth.service";
import { SpinnerService } from "src/app/services/spinner/spinner.service";
import { ThemeService } from "src/app/services/theme/theme.service";
import { ToastService } from "src/app/services/toast/toast.service";
import { throwError } from "rxjs";
@Component({
selector: 'app-user-settings',
templateUrl: './user-settings.component.html',
styleUrls: ['./user-settings.component.scss']
selector: "app-user-settings",
templateUrl: "./user-settings.component.html",
styleUrls: ["./user-settings.component.scss"]
})
export class UserSettingsComponent implements OnInit {
settingsForm!: FormGroup<{
@ -42,7 +43,8 @@ export class UserSettingsComponent implements OnInit {
private toastService: ToastService,
private themeService: ThemeService,
private translaste: TranslateService
) { }
) {
}
ngOnInit(): void {
this.initForms();
@ -51,10 +53,10 @@ export class UserSettingsComponent implements OnInit {
initForms(): void {
this.settingsForm = this.formBuilder.group({
firstName: ['', [Validators.required]],
lastName: ['', [Validators.required]],
email: ['', [Validators.required, Validators.email]],
password: ['', [Validators.required, Validators.minLength(8)]]
firstName: ["", [Validators.required]],
lastName: ["", [Validators.required]],
email: ["", [Validators.required, Validators.email]],
password: ["", [Validators.required, Validators.minLength(8)]]
});
}
@ -73,14 +75,14 @@ export class UserSettingsComponent implements OnInit {
}
this.authService.findUserByEMail(mail)
.pipe(catchError(err => {
this.toastService.error(this.translaste.instant('view.user_settings.message.user_not_found'), this.translaste.instant('view.user_settings.message.user_not_found_d'));
.pipe(catchError(error => {
this.toastService.error(this.translaste.instant("view.user_settings.message.user_not_found"), this.translaste.instant("view.user_settings.message.user_not_found_d"));
this.authService.logout();
throw err;
return throwError(() => error);
}))
.subscribe(user => {
if (!user) {
this.toastService.error(this.translaste.instant('view.user_settings.message.user_not_found'), this.translaste.instant('view.user_settings.message.user_not_found_d'));
this.toastService.error(this.translaste.instant("view.user_settings.message.user_not_found"), this.translaste.instant("view.user_settings.message.user_not_found_d"));
this.authService.logout();
}
this.authUser = user;
@ -122,27 +124,27 @@ export class UserSettingsComponent implements OnInit {
}
}
this.spinnerService.hideSpinner();
this.toastService.error(this.translaste.instant('view.user_settings.message.error'), this.translaste.instant('view.user_settings.message.could_not_change_settings'));
throw error;
this.toastService.error(this.translaste.instant("view.user_settings.message.error"), this.translaste.instant("view.user_settings.message.could_not_change_settings"));
return throwError(() => error);
}))
.subscribe(resp => {
updateUserDTO.newAuthUserDTO.password = updateUserDTO.authUserDTO.password;
this.authService.login(updateUserDTO.newAuthUserDTO)
.pipe(catchError(err => {
this.router.navigate(['/auth/login']);
throw err;
.pipe(catchError(error => {
this.router.navigate(["/auth/login"]);
return throwError(() => error);
}))
.subscribe(token => {
this.spinnerService.hideSpinner();
if (token) {
this.toastService.success(this.translaste.instant('view.user_settings.message.success'), this.translaste.instant('view.user_settings.message.changed_settings'));
this.toastService.success(this.translaste.instant("view.user_settings.message.success"), this.translaste.instant("view.user_settings.message.changed_settings"));
this.authService.saveToken(token);
this.themeService.loadTheme();
this.themeService.loadMenu();
this.load();
return true;
}
this.router.navigate(['/auth/login']);
this.router.navigate(["/auth/login"]);
return false;
});
});

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 } from "rxjs";
import { 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";
@ -231,7 +231,7 @@ export class AuthService {
this.isLoggedIn$.next(false);
localStorage.removeItem("rjwt");
this.router.navigate(["/auth/login"]);
throw error;
return throwError(() => error);
})).subscribe(() => {
this.isLoggedIn$.next(false);
localStorage.removeItem("jwt");

View File

@ -3,7 +3,7 @@
"WebVersion": {
"Major": "1",
"Minor": "0",
"Micro": "0.rc1"
"Micro": "dev247"
},
"Themes": [
{

View File

@ -518,6 +518,10 @@
}
.icon-btn {
.p-button-label {
transition-duration: unset !important;
}
&:hover {
background-color: transparent !important;
color: $primaryHeaderColor !important;

View File

@ -9,7 +9,7 @@ function Main(): void {
setVersion(version);
})
.catch(err => {
throw err;
throwError(() => err);
});
}
@ -50,7 +50,7 @@ async function setVersion(version: SoftwareVersion) {
const fs = require("fs");
fs.readFile(jsonFilePath, "utf8", (err: Error, data: string) => {
if (err) {
throw err;
throwError(() => err);
}
const settings: Appsettings = JSON.parse(data);
settings.WebVersion = version;
@ -59,7 +59,7 @@ async function setVersion(version: SoftwareVersion) {
});
fs.readFile('./package.json', "utf8", (err: Error, data: string) => {
if (err) {
throw err;
throwError(() => err);
}
const settings = JSON.parse(data);
settings.version = version.getVersionString();