Reviewed-on: sh-edraft.de/kd_discord_bot#252 Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de> Closes #251
This commit is contained in:
		| @@ -483,18 +483,19 @@ class AuthService(AuthServiceABC): | ||||
|         if user_dto is None: | ||||
|             raise ServiceException(ServiceErrorCode.InvalidData, "User not set") | ||||
|  | ||||
|         members = self._users.get_users_by_discord_id(dc_id) | ||||
|         if members.count() == 0: | ||||
|             raise ServiceException(ServiceErrorCode.InvalidUser, f"Member not found") | ||||
|  | ||||
|         added_user = False | ||||
|         db_user = self._auth_users.find_auth_user_by_email(user_dto.email) | ||||
|         if db_user is None: | ||||
|             self.add_auth_user(user_dto) | ||||
|             added_user = True | ||||
|             # raise ServiceException(ServiceErrorCode.InvalidUser, f'User not found') | ||||
|  | ||||
|         db_user = self._auth_users.get_auth_user_by_email(user_dto.email) | ||||
|         if db_user.users.count() == 0: | ||||
|             self._users.get_users_by_discord_id(dc_id).for_each( | ||||
|                 lambda x: self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_user, x)) | ||||
|             ) | ||||
|             members.for_each(lambda x: self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_user, x))) | ||||
|  | ||||
|         if db_user.confirmation_id is not None and not added_user: | ||||
|             raise ServiceException(ServiceErrorCode.Forbidden, "E-Mail not verified") | ||||
|   | ||||
							
								
								
									
										9562
									
								
								kdb-web/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9562
									
								
								kdb-web/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "kdb-web", | ||||
|     "version": "1.0.0.rc2", | ||||
|     "version": "1.0.dev251", | ||||
|     "scripts": { | ||||
|         "ng": "ng", | ||||
|         "update-version": "ts-node-esm update-version.ts", | ||||
|   | ||||
| @@ -53,9 +53,9 @@ export class AppComponent implements OnInit, OnDestroy { | ||||
|     this.socket.startSocket(); | ||||
|   } | ||||
|  | ||||
|   ngOnDestroy() { | ||||
|   public ngOnDestroy(): void { | ||||
|     this.unsubscriber.next(); | ||||
|     this.unsubscriber.unsubscribe(); | ||||
|     this.unsubscriber.complete(); | ||||
|   } | ||||
|  | ||||
|   loadLang(): void { | ||||
|   | ||||
| @@ -1,26 +1,28 @@ | ||||
| <footer> | ||||
|     <div class="left"> | ||||
|         <div class="frontend-version"> | ||||
|   <div class="left"> | ||||
|     <div class="frontend-version"> | ||||
|             <span> | ||||
|                 {{'footer.frontend' | translate}}: | ||||
|             </span> | ||||
|             <span> | ||||
|       <span> | ||||
|                 {{frontendVersion.getVersionString()}} | ||||
|             </span> | ||||
|         </div> | ||||
|         <span class="version-divider"> | ||||
|     </div> | ||||
|     <span class="version-divider"> | ||||
|             | | ||||
|         </span> | ||||
|         <div class="backend-version"> | ||||
|     <div class="backend-version"> | ||||
|             <span> | ||||
|                 {{'footer.backend' | translate}}: | ||||
|             </span> | ||||
|             <span> | ||||
|       <span> | ||||
|                 {{backendVersion.getVersionString()}} | ||||
|             </span> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="right"> | ||||
|         <a href="https://www.sh-edraft.de/Impressum" target="_blank">{{'footer.imprint' | translate}}</a> | ||||
|     </div> | ||||
| </footer> | ||||
|   </div> | ||||
|   <div class="right"> | ||||
|     <button pButton label="{{'footer.privacy' | translate}}" class="btn text-btn" (click)="navigateToPrivacy()"></button> | ||||
|     <span> | </span> | ||||
|     <button pButton label="{{'footer.imprint' | translate}}" class="btn text-btn" (click)="navigateToImprint()"></button> | ||||
|   </div> | ||||
| </footer> | ||||
|   | ||||
| @@ -14,14 +14,17 @@ import { throwError } from "rxjs"; | ||||
| export class FooterComponent implements OnInit { | ||||
|  | ||||
|  | ||||
|   frontendVersion: SoftwareVersion = new SoftwareVersion("0", "0", "0"); | ||||
|   backendVersion: SoftwareVersion = new SoftwareVersion("0", "0", "0"); | ||||
|   public frontendVersion: SoftwareVersion = new SoftwareVersion("0", "0", "0"); | ||||
|   public backendVersion: SoftwareVersion = new SoftwareVersion("0", "0", "0"); | ||||
|  | ||||
|   public privacy: string = ""; | ||||
|   public imprint: string  = ""; | ||||
|  | ||||
|   constructor( | ||||
|     private settings: SettingsService, | ||||
|     private guiService: GuiService, | ||||
|     private spinnerService: SpinnerService | ||||
|   ) { } | ||||
|   ) {} | ||||
|  | ||||
|   ngOnInit(): void { | ||||
|     this.frontendVersion = this.settings.getWebVersion() ?? new SoftwareVersion('0', '0', '0'); | ||||
| @@ -42,4 +45,12 @@ export class FooterComponent implements OnInit { | ||||
|       }); | ||||
|   } | ||||
|  | ||||
|   public navigateToPrivacy(): void { | ||||
|     window.open(this.settings.getPrivacyURL(), "_blank"); | ||||
|   } | ||||
|  | ||||
|   public navigateToImprint(): void { | ||||
|     window.open(this.settings.getImprintURL(), "_blank"); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,8 @@ import { Theme } from '../view/theme'; | ||||
|  | ||||
| export interface Appsettings { | ||||
|     ApiURL: string; | ||||
|     PrivacyURL: string; | ||||
|     ImprintURL: string; | ||||
|     WebVersion: SoftwareVersion; | ||||
|     Themes: Theme[]; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { Component, OnInit } from "@angular/core"; | ||||
| import { Component, OnDestroy, OnInit } from "@angular/core"; | ||||
| import { catchError, debounceTime, takeUntil } from "rxjs/operators"; | ||||
| import { AuthRoles } from "src/app/models/auth/auth-roles.enum"; | ||||
| import { AuthUserDTO } from "src/app/models/auth/auth-user.dto"; | ||||
| @@ -22,7 +22,7 @@ import { TranslateService } from "@ngx-translate/core"; | ||||
|   templateUrl: "./auth-user.component.html", | ||||
|   styleUrls: ["./auth-user.component.scss"] | ||||
| }) | ||||
| export class AuthUserComponent implements OnInit { | ||||
| export class AuthUserComponent implements OnInit, OnDestroy { | ||||
|  | ||||
|   users!: AuthUserDTO[]; | ||||
|   statuses!: any[]; | ||||
| @@ -62,7 +62,7 @@ export class AuthUserComponent implements OnInit { | ||||
|   searchCriterions!: AuthUserSelectCriterion; | ||||
|   totalRecords!: number; | ||||
|  | ||||
|   private unsubscriber = new Subject(); | ||||
|   private unsubscriber = new Subject<void>(); | ||||
|  | ||||
|   constructor( | ||||
|     private authService: AuthService, | ||||
| @@ -91,6 +91,11 @@ export class AuthUserComponent implements OnInit { | ||||
|     this.loadNextPage(); | ||||
|   } | ||||
|  | ||||
|   public ngOnDestroy(): void { | ||||
|     this.unsubscriber.next(); | ||||
|     this.unsubscriber.complete(); | ||||
|   } | ||||
|  | ||||
|   setFilterForm() { | ||||
|     this.filterForm = this.fb.group({ | ||||
|       firstName: [""], | ||||
|   | ||||
| @@ -1,15 +1,14 @@ | ||||
| import { Component, OnInit } from '@angular/core'; | ||||
| import { FormBuilder, FormGroup, Validators } from '@angular/forms'; | ||||
| import { TranslateService } from '@ngx-translate/core'; | ||||
| import { catchError } from 'rxjs/operators'; | ||||
| import { SettingsDTO } from 'src/app/models/config/settings.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 { 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 { Component, OnInit } from "@angular/core"; | ||||
| import { FormBuilder, FormGroup, Validators } from "@angular/forms"; | ||||
| import { TranslateService } from "@ngx-translate/core"; | ||||
| import { catchError } from "rxjs/operators"; | ||||
| import { SettingsDTO } from "src/app/models/config/settings.dto"; | ||||
| import { ErrorDTO } from "src/app/models/error/error-dto"; | ||||
| import { ServiceErrorCode } from "src/app/models/error/service-error-code.enum"; | ||||
| 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({ | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import { AuthHeaderComponent } from './components/auth-header/auth-header.compon | ||||
| import { ForgetPasswordComponent } from './components/forget-password/forget-password.component'; | ||||
| import { LoginComponent } from './components/login/login.component'; | ||||
| import { RegistrationComponent } from './components/registration/registration.component'; | ||||
| import { AuthFooterComponent } from "./components/auth-footer/auth-footer.component"; | ||||
|  | ||||
|  | ||||
| @NgModule({ | ||||
| @@ -14,7 +15,8 @@ import { RegistrationComponent } from './components/registration/registration.co | ||||
|     ForgetPasswordComponent, | ||||
|     LoginComponent, | ||||
|     RegistrationComponent, | ||||
|     AuthHeaderComponent | ||||
|     AuthHeaderComponent, | ||||
|     AuthFooterComponent | ||||
|   ], | ||||
|   imports: [ | ||||
|     CommonModule, | ||||
|   | ||||
| @@ -0,0 +1,7 @@ | ||||
| <div class="auth-footer"> | ||||
|   <div class="logo-button-wrapper"> | ||||
|     <button pButton label="{{'footer.privacy' | translate}}" class="btn text-btn" (click)="navigateToPrivacy()"></button> | ||||
|     <span> | </span> | ||||
|     <button pButton label="{{'footer.imprint' | translate}}" class="btn text-btn" (click)="navigateToImprint()"></button> | ||||
|   </div> | ||||
| </div> | ||||
| @@ -0,0 +1,23 @@ | ||||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||||
|  | ||||
| import { AuthFooterComponent } from './auth-footer.component'; | ||||
|  | ||||
| describe('AuthFooterComponent', () => { | ||||
|   let component: AuthFooterComponent; | ||||
|   let fixture: ComponentFixture<AuthFooterComponent>; | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     await TestBed.configureTestingModule({ | ||||
|       declarations: [ AuthFooterComponent ] | ||||
|     }) | ||||
|     .compileComponents(); | ||||
|  | ||||
|     fixture = TestBed.createComponent(AuthFooterComponent); | ||||
|     component = fixture.componentInstance; | ||||
|     fixture.detectChanges(); | ||||
|   }); | ||||
|  | ||||
|   it('should create', () => { | ||||
|     expect(component).toBeTruthy(); | ||||
|   }); | ||||
| }); | ||||
| @@ -0,0 +1,32 @@ | ||||
| import { Component, OnInit } from "@angular/core"; | ||||
| import { Router } from "@angular/router"; | ||||
| import { SettingsService } from "../../../../services/settings/settings.service"; | ||||
|  | ||||
| @Component({ | ||||
|   selector: "app-auth-footer", | ||||
|   templateUrl: "./auth-footer.component.html", | ||||
|   styleUrls: ["./auth-footer.component.scss"] | ||||
| }) | ||||
| export class AuthFooterComponent implements OnInit { | ||||
|   private privacy: string = ""; | ||||
|   private imprint: string = ""; | ||||
|  | ||||
|   constructor( | ||||
|     private settings: SettingsService | ||||
|   ) { | ||||
|   } | ||||
|  | ||||
|   ngOnInit(): void { | ||||
|     this.privacy = this.settings.getPrivacyURL(); | ||||
|     this.imprint = this.settings.getImprintURL(); | ||||
|   } | ||||
|  | ||||
|   public navigateToPrivacy(): void { | ||||
|     window.open(this.settings.getPrivacyURL(), "_blank"); | ||||
|   } | ||||
|  | ||||
|   public navigateToImprint(): void { | ||||
|     window.open(this.settings.getImprintURL(), "_blank"); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -1,10 +1,10 @@ | ||||
| <div class="auth-header"> | ||||
|     <div class="logo-button-wrapper"> | ||||
|         <button type="button" pButton icon="pi pi-globe" class="btn icon-btn p-button-text" (click)="authLangMenu.toggle($event)"></button> | ||||
|         <p-menu #authLangMenu [popup]="true" [model]="langList" class="lang-menu"></p-menu> | ||||
|     </div> | ||||
|     <div class="logo-button-wrapper"> | ||||
|         <button type="button" pButton icon="pi pi-palette" class="btn icon-btn p-button-text" (click)="authThemeMenu.toggle($event)"></button> | ||||
|         <p-menu #authThemeMenu [popup]="true" [model]="themeList" class="theme-menu"></p-menu> | ||||
|     </div> | ||||
| </div> | ||||
|   <div class="logo-button-wrapper"> | ||||
|     <button type="button" pButton icon="pi pi-globe" class="btn icon-btn p-button-text" (click)="authLangMenu.toggle($event)"></button> | ||||
|     <p-menu #authLangMenu [popup]="true" [model]="langList" class="lang-menu"></p-menu> | ||||
|   </div> | ||||
|   <div class="logo-button-wrapper"> | ||||
|     <button type="button" pButton icon="pi pi-palette" class="btn icon-btn p-button-text" (click)="authThemeMenu.toggle($event)"></button> | ||||
|     <p-menu #authThemeMenu [popup]="true" [model]="themeList" class="theme-menu"></p-menu> | ||||
|   </div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,12 +1,10 @@ | ||||
| import { Component, OnInit } from '@angular/core'; | ||||
| import { Router } from '@angular/router'; | ||||
| import { TranslateService, LangChangeEvent } from '@ngx-translate/core'; | ||||
| import { MenuItem, PrimeNGConfig } from 'primeng/api'; | ||||
| import { catchError } from 'rxjs'; | ||||
| 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 { TranslateService } from "@ngx-translate/core"; | ||||
| import { MenuItem, PrimeNGConfig } from "primeng/api"; | ||||
| 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"; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-auth-header', | ||||
| @@ -14,9 +12,8 @@ import { ThemeService } from 'src/app/services/theme/theme.service'; | ||||
|   styleUrls: ['./auth-header.component.scss'] | ||||
| }) | ||||
| export class AuthHeaderComponent implements OnInit { | ||||
|   langList: MenuItem[] = []; | ||||
|   themeList: MenuItem[] = []; | ||||
|   userMenuList!: MenuItem[]; | ||||
|   public langList: MenuItem[] = []; | ||||
|   public themeList: MenuItem[] = []; | ||||
|  | ||||
|   constructor( | ||||
|     private router: Router, | ||||
| @@ -27,12 +24,12 @@ export class AuthHeaderComponent implements OnInit { | ||||
|     private config: PrimeNGConfig | ||||
|   ) { } | ||||
|  | ||||
|   ngOnInit(): void { | ||||
|   public ngOnInit(): void { | ||||
|     this.initMenuLists(); | ||||
|     this.loadLang(); | ||||
|   } | ||||
|  | ||||
|   initMenuLists(): void { | ||||
|   private initMenuLists(): void { | ||||
|     this.langList = [ | ||||
|       { | ||||
|         label: 'English', command: () => { | ||||
| @@ -58,16 +55,16 @@ export class AuthHeaderComponent implements OnInit { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   changeTheme(name: string): void { | ||||
|   private changeTheme(name: string): void { | ||||
|     this.themeService.setTheme(name, true); | ||||
|   } | ||||
|  | ||||
|   translate(lang: string) { | ||||
|   private translate(lang: string) { | ||||
|     this.translateService.use(lang); | ||||
|     this.translateService.get('primeng').subscribe(res => this.config.setTranslation(res)); | ||||
|   } | ||||
|  | ||||
|   loadLang(): void { | ||||
|   private loadLang(): void { | ||||
|     let lang = localStorage.getItem(`default_lang`); | ||||
|     if (!lang) { | ||||
|       lang = 'en'; | ||||
| @@ -76,7 +73,7 @@ export class AuthHeaderComponent implements OnInit { | ||||
|     this.translate(lang); | ||||
|   } | ||||
|  | ||||
|   setLang(lang: string): void { | ||||
|   private setLang(lang: string): void { | ||||
|     localStorage.setItem(`default_lang`, lang); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -1,63 +1,64 @@ | ||||
| <section class="login-wrapper"> | ||||
|     <div class="login-form-wrapper"> | ||||
|         <div class="login-form"> | ||||
|             <ng-container *ngIf="resetPasswordId === null; else resetPasswordForm"> | ||||
|                 <form [formGroup]="emailForm"> | ||||
|                     <h1>{{'auth.header' | translate}}</h1> | ||||
|                     <div *ngIf="!ready" class="input-field"> | ||||
|                         <input type="email" pInputText formControlName="email" | ||||
|                             placeholder="{{'common.email' | translate}}" autocomplete="username email"> | ||||
|                     </div> | ||||
|                     <div *ngIf="ready" class="input-field-info-text"> | ||||
|                         {{'auth.forgot_password.send_confirmation_url' | translate}} | ||||
|                     </div> | ||||
|                     <div class="login-form-submit"> | ||||
|                         <button pButton label="{{'auth.forgot_password.reset_password' | translate}}" | ||||
|                             class="btn login-form-submit-btn" (click)="forgotPassword()" | ||||
|                             [disabled]="emailForm.invalid || ready"></button> | ||||
|                     </div> | ||||
|   <div class="login-form-wrapper"> | ||||
|     <div class="login-form"> | ||||
|       <ng-container *ngIf="resetPasswordId === null; else resetPasswordForm"> | ||||
|         <form [formGroup]="emailForm"> | ||||
|           <h1>{{'auth.header' | translate}}</h1> | ||||
|           <div *ngIf="!ready" class="input-field"> | ||||
|             <input type="email" pInputText formControlName="email" | ||||
|                    placeholder="{{'common.email' | translate}}" autocomplete="username email"> | ||||
|           </div> | ||||
|           <div *ngIf="ready" class="input-field-info-text"> | ||||
|             {{'auth.forgot_password.send_confirmation_url' | translate}} | ||||
|           </div> | ||||
|           <div class="login-form-submit"> | ||||
|             <button pButton label="{{'auth.forgot_password.reset_password' | translate}}" | ||||
|                     class="btn login-form-submit-btn" (click)="forgotPassword()" | ||||
|                     [disabled]="emailForm.invalid || ready"></button> | ||||
|           </div> | ||||
|  | ||||
|                     <div class="login-form-sub-button-wrapper"> | ||||
|                         <div class="login-form-sub-btn-wrapper"> | ||||
|                             <button pButton label="{{'auth.forgot_password.login' | translate}}" | ||||
|                                 class="btn login-form-sub-btn" (click)="login()"></button> | ||||
|                         </div> | ||||
|                         <div class="login-form-sub-btn-wrapper"> | ||||
|                             <button pButton label="{{'auth.forgot_password.register' | translate}}" | ||||
|                                 class="btn login-form-sub-btn" (click)="register()"></button> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </form> | ||||
|             </ng-container> | ||||
|           <div class="login-form-sub-button-wrapper"> | ||||
|             <div class="login-form-sub-btn-wrapper"> | ||||
|               <button pButton label="{{'auth.forgot_password.login' | translate}}" | ||||
|                       class="btn login-form-sub-btn" (click)="login()"></button> | ||||
|             </div> | ||||
|             <div class="login-form-sub-btn-wrapper"> | ||||
|               <button pButton label="{{'auth.forgot_password.register' | translate}}" | ||||
|                       class="btn login-form-sub-btn" (click)="register()"></button> | ||||
|             </div> | ||||
|           </div> | ||||
|         </form> | ||||
|       </ng-container> | ||||
|  | ||||
|             <ng-template #resetPasswordForm> | ||||
|                 <form [formGroup]="passwordForm"> | ||||
|                     <h1>{{'auth.header' | translate}}</h1> | ||||
|       <ng-template #resetPasswordForm> | ||||
|         <form [formGroup]="passwordForm"> | ||||
|           <h1>{{'auth.header' | translate}}</h1> | ||||
|  | ||||
|                     <div class="input-field"> | ||||
|                         <input type="password" pInputText formControlName="password" | ||||
|                             placeholder="{{'auth.forgot_password.password' | translate}}" autocomplete="new-password"> | ||||
|                     </div> | ||||
|           <div class="input-field"> | ||||
|             <input type="password" pInputText formControlName="password" | ||||
|                    placeholder="{{'auth.forgot_password.password' | translate}}" autocomplete="new-password"> | ||||
|           </div> | ||||
|  | ||||
|                     <div class="input-field"> | ||||
|                         <input type="password" pInputText formControlName="passwordRepeat" | ||||
|                             placeholder="{{'auth.forgot_password.repeat_password' | translate}}" | ||||
|                             [ngClass]="{ 'invalid-feedback-input': submitted && repeatErrors.password}"> | ||||
|                         <div *ngIf="submitted" class="invalid-feedback"> | ||||
|                             <div *ngIf="repeatErrors.password">{{'auth.forgot_password.passwords_do_not_match' | | ||||
|                                 translate}}</div> | ||||
|                         </div> | ||||
|                     </div> | ||||
|           <div class="input-field"> | ||||
|             <input type="password" pInputText formControlName="passwordRepeat" | ||||
|                    placeholder="{{'auth.forgot_password.repeat_password' | translate}}" | ||||
|                    [ngClass]="{ 'invalid-feedback-input': submitted && repeatErrors.password}"> | ||||
|             <div *ngIf="submitted" class="invalid-feedback"> | ||||
|               <div *ngIf="repeatErrors.password">{{'auth.forgot_password.passwords_do_not_match' | | ||||
|                 translate}}</div> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|                     <div class="login-form-submit"> | ||||
|                         <button pButton label="{{'auth.forgot_password.reset_password' | translate}}" | ||||
|                             class="btn login-form-submit-btn" (click)="resetPassword()" | ||||
|                             [disabled]="passwordForm.invalid || ready"></button> | ||||
|                     </div> | ||||
|                 </form> | ||||
|             </ng-template> | ||||
|         </div> | ||||
|           <div class="login-form-submit"> | ||||
|             <button pButton label="{{'auth.forgot_password.reset_password' | translate}}" | ||||
|                     class="btn login-form-submit-btn" (click)="resetPassword()" | ||||
|                     [disabled]="passwordForm.invalid || ready"></button> | ||||
|           </div> | ||||
|         </form> | ||||
|       </ng-template> | ||||
|     </div> | ||||
|   </div> | ||||
|  | ||||
|     <app-auth-header></app-auth-header> | ||||
|   <app-auth-header></app-auth-header> | ||||
|   <app-auth-footer></app-auth-footer> | ||||
| </section> | ||||
|   | ||||
| @@ -62,4 +62,5 @@ | ||||
|   </div> | ||||
|  | ||||
|   <app-auth-header></app-auth-header> | ||||
|   <app-auth-footer></app-auth-footer> | ||||
| </section> | ||||
|   | ||||
| @@ -67,11 +67,16 @@ | ||||
|           </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="input-field"> | ||||
|           <p-checkbox id="confirmPrivacyCheckbox" [binary]="true" formControlName="confirmPrivacy"></p-checkbox> | ||||
|             | ||||
|           <label for="confirmPrivacyCheckbox" [innerHTML]="confirmPrivacyString"></label> | ||||
|         </div> | ||||
|  | ||||
|         <div class="login-form-submit"> | ||||
|           <button pButton label="{{'auth.register.register' | translate}}" class="btn login-form-submit-btn" (click)="register()" | ||||
|                   [disabled]="loginForm.invalid"></button> | ||||
|         </div> | ||||
|  | ||||
|         <div class="login-form-sub-button-wrapper"> | ||||
|           <div class="login-form-sub-btn-wrapper"> | ||||
|             <button pButton label="{{'auth.register.login' | translate}}" class="btn login-form-sub-btn" (click)="login()"></button> | ||||
| @@ -82,4 +87,5 @@ | ||||
|   </div> | ||||
|  | ||||
|   <app-auth-header></app-auth-header> | ||||
|   <app-auth-footer></app-auth-footer> | ||||
| </section> | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import { Component, OnInit } from "@angular/core"; | ||||
| import { Component, OnDestroy, OnInit } from "@angular/core"; | ||||
| import { FormBuilder, FormControl, FormGroup, Validators } from "@angular/forms"; | ||||
| import { ActivatedRoute, Router } from "@angular/router"; | ||||
| import { catchError, finalize } from "rxjs/operators"; | ||||
| import { catchError, takeUntil } 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 { AuthUserAtrErrors } from "src/app/models/auth/auth-user-atr-errors"; | ||||
| @@ -9,15 +9,16 @@ 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 { throwError } from "rxjs"; | ||||
| import { OAuthDTO } from "../../../../models/auth/oauth.dto"; | ||||
| import { Subject, throwError } from "rxjs"; | ||||
| import { TranslateService } from "@ngx-translate/core"; | ||||
| import { SettingsService } from "../../../../services/settings/settings.service"; | ||||
|  | ||||
| @Component({ | ||||
|   selector: "app-registration", | ||||
|   templateUrl: "./registration.component.html", | ||||
|   styleUrls: ["./registration.component.scss"] | ||||
| }) | ||||
| export class RegistrationComponent implements OnInit { | ||||
| export class RegistrationComponent implements OnInit, OnDestroy { | ||||
|  | ||||
|   loginForm!: FormGroup<{ | ||||
|     firstName: FormControl<string | null>, | ||||
| @@ -25,7 +26,8 @@ export class RegistrationComponent implements OnInit { | ||||
|     email: FormControl<string | null>, | ||||
|     emailRepeat: FormControl<string | null>, | ||||
|     password: FormControl<string | null>, | ||||
|     passwordRepeat: FormControl<string | null> | ||||
|     passwordRepeat: FormControl<string | null>, | ||||
|     confirmPrivacy: FormControl<boolean | null> | ||||
|   }>; | ||||
|   submitted = false; | ||||
|   authUserAtrErrors!: AuthUserAtrErrors; | ||||
| @@ -34,12 +36,17 @@ export class RegistrationComponent implements OnInit { | ||||
|     password: false | ||||
|   }; | ||||
|  | ||||
|   public confirmPrivacyString: string = ""; | ||||
|   private unsubscriber = new Subject<void>(); | ||||
|  | ||||
|   constructor( | ||||
|     private authService: AuthService, | ||||
|     private formBuilder: FormBuilder, | ||||
|     private router: Router, | ||||
|     private spinnerService: SpinnerService, | ||||
|     private route: ActivatedRoute | ||||
|     private route: ActivatedRoute, | ||||
|     private translate: TranslateService, | ||||
|     private settings: SettingsService | ||||
|   ) { | ||||
|     this.spinnerService.showSpinner(); | ||||
|     this.authService.isUserLoggedInAsync().then(res => { | ||||
| @@ -51,12 +58,22 @@ export class RegistrationComponent implements OnInit { | ||||
|   } | ||||
|  | ||||
|   ngOnInit(): void { | ||||
|     this.translate.onLangChange.pipe(takeUntil(this.unsubscriber)).subscribe(lang => { | ||||
|  | ||||
|       this.confirmPrivacyString = this.translate.instant("auth.register.confirm_privacy", { url: this.settings.getPrivacyURL() }); | ||||
|     }); | ||||
|  | ||||
|     this.confirmEMail(); | ||||
|     this.initData(); | ||||
|     this.spinnerService.showSpinner(); | ||||
|     this.initData(); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   public ngOnDestroy(): void { | ||||
|     this.unsubscriber.next(); | ||||
|     this.unsubscriber.complete(); | ||||
|   } | ||||
|  | ||||
|   initData() { | ||||
|     this.initLoginForm(); | ||||
|     this.resetStateFlags(); | ||||
| @@ -82,7 +99,8 @@ export class RegistrationComponent implements OnInit { | ||||
|       email: ["", [Validators.required, Validators.email]], | ||||
|       emailRepeat: ["", [Validators.required, Validators.email]], | ||||
|       password: ["", [Validators.required, Validators.minLength(8)]], | ||||
|       passwordRepeat: ["", [Validators.required, Validators.minLength(8)]] | ||||
|       passwordRepeat: ["", [Validators.required, Validators.minLength(8)]], | ||||
|       confirmPrivacy: [false, [Validators.required, Validators.requiredTrue]] | ||||
|     }); | ||||
|   } | ||||
|  | ||||
| @@ -143,7 +161,7 @@ export class RegistrationComponent implements OnInit { | ||||
|         .pipe(catchError(error => { | ||||
|           this.router.navigate(["/auth/login"]); | ||||
|           this.spinnerService.hideSpinner(); | ||||
|         return throwError(() => error); | ||||
|           return throwError(() => error); | ||||
|         })) | ||||
|         .subscribe(resp => { | ||||
|           this.spinnerService.hideSpinner(); | ||||
| @@ -151,4 +169,8 @@ export class RegistrationComponent implements OnInit { | ||||
|         }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   log($event: Event): void { | ||||
|     console.log($event); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -60,7 +60,7 @@ export class DashboardComponent implements OnInit, OnDestroy { | ||||
|     this.loadNextPage(); | ||||
|   } | ||||
|  | ||||
|   public ngOnDestroy() { | ||||
|   public ngOnDestroy(): void { | ||||
|     this.unsubscriber.next(); | ||||
|     this.unsubscriber.complete(); | ||||
|   } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { Component, OnInit } from "@angular/core"; | ||||
| import { Component, OnDestroy, OnInit } from "@angular/core"; | ||||
| import { DataService } from "../../../../../../services/data/data.service"; | ||||
| import { ActivatedRoute, Router } from "@angular/router"; | ||||
| import { AutoRoleRule, AutoRoleRuleFilter } from "../../../../../../models/data/auto_role.model"; | ||||
| @@ -28,7 +28,7 @@ import { Subject, throwError } from "rxjs"; | ||||
|   templateUrl: "./auto-roles-rules.component.html", | ||||
|   styleUrls: ["./auto-roles-rules.component.scss"] | ||||
| }) | ||||
| export class AutoRolesRulesComponent implements OnInit { | ||||
| export class AutoRolesRulesComponent implements OnInit, OnDestroy { | ||||
|  | ||||
|   rules: AutoRoleRule[] = []; | ||||
|   guild: Guild = { channels: [], emojis: [], roles: [] }; | ||||
| @@ -85,7 +85,6 @@ export class AutoRolesRulesComponent implements OnInit { | ||||
|   } | ||||
|  | ||||
|   public ngOnInit(): void { | ||||
|  | ||||
|     this.setFilterForm(); | ||||
|     this.data.getServerFromRoute(this.route).then(server => { | ||||
|       this.server = server; | ||||
| @@ -119,6 +118,11 @@ export class AutoRolesRulesComponent implements OnInit { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   public ngOnDestroy(): void { | ||||
|     this.unsubscriber.next(); | ||||
|     this.unsubscriber.complete(); | ||||
|   } | ||||
|  | ||||
|   public loadNextPage(): void { | ||||
|     this.loading = true; | ||||
|     this.data.query<AutoRoleRuleQuery>(Queries.autoRoleRulesQuery, { | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { Component, OnInit } from "@angular/core"; | ||||
| import { Component, OnDestroy, OnInit } from "@angular/core"; | ||||
| import { User } from "../../../../../../models/data/user.model"; | ||||
| import { LazyLoadEvent, MenuItem } from "primeng/api"; | ||||
| import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; | ||||
| @@ -28,7 +28,7 @@ import { Server } from "../../../../../../models/data/server.model"; | ||||
|   templateUrl: "./auto-roles.component.html", | ||||
|   styleUrls: ["./auto-roles.component.scss"] | ||||
| }) | ||||
| export class AutoRolesComponent implements OnInit { | ||||
| export class AutoRolesComponent implements OnInit, OnDestroy { | ||||
|   auto_roles: AutoRole[] = []; | ||||
|   guild: Guild = { channels: [], emojis: [], roles: [] }; | ||||
|   channels: MenuItem[] = []; | ||||
| @@ -100,6 +100,12 @@ export class AutoRolesComponent implements OnInit { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   public ngOnDestroy(): void { | ||||
|     this.unsubscriber.next(); | ||||
|     this.unsubscriber.complete(); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   public loadNextPage(): void { | ||||
|     this.loading = true; | ||||
|     this.data.query<AutoRoleQuery>(Queries.autoRolesQuery, { | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { Component, OnInit } from "@angular/core"; | ||||
| import { Component, OnDestroy, OnInit } from "@angular/core"; | ||||
| import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; | ||||
| import { AuthService } from "../../../../services/auth/auth.service"; | ||||
| import { SpinnerService } from "../../../../services/spinner/spinner.service"; | ||||
| @@ -26,7 +26,7 @@ import { Server } from "../../../../models/data/server.model"; | ||||
|   templateUrl: "./members.component.html", | ||||
|   styleUrls: ["./members.component.scss"] | ||||
| }) | ||||
| export class MembersComponent implements OnInit { | ||||
| export class MembersComponent implements OnInit, OnDestroy { | ||||
|   members!: User[]; | ||||
|   levels!: MenuItem[]; | ||||
|   leftServerOptions = [ | ||||
| @@ -114,6 +114,10 @@ export class MembersComponent implements OnInit { | ||||
|       this.loadNextPage(); | ||||
|     }); | ||||
|   } | ||||
|   public ngOnDestroy(): void { | ||||
|     this.unsubscriber.next(); | ||||
|     this.unsubscriber.complete(); | ||||
|   } | ||||
|  | ||||
|   loadNextPage() { | ||||
|     this.spinner.showSpinner(); | ||||
|   | ||||
| @@ -30,13 +30,29 @@ export class SettingsService { | ||||
|   } | ||||
|  | ||||
|   public getApiURL(): string { | ||||
|     if (!this.appsettings || !this.appsettings.Themes) { | ||||
|     if (!this.appsettings || !this.appsettings.ApiURL) { | ||||
|       console.error('ApiUrl is not set!'); | ||||
|       return ""; | ||||
|     } | ||||
|     return this.appsettings.ApiURL; | ||||
|   } | ||||
|  | ||||
|   public getPrivacyURL(): string { | ||||
|     if (!this.appsettings || !this.appsettings.PrivacyURL) { | ||||
|       console.error('PrivacyURL is not set!'); | ||||
|       return ""; | ||||
|     } | ||||
|     return this.appsettings.PrivacyURL; | ||||
|   } | ||||
|  | ||||
|   public getImprintURL(): string { | ||||
|     if (!this.appsettings || !this.appsettings.ImprintURL) { | ||||
|       console.error('ImprintURL is not set!'); | ||||
|       return ""; | ||||
|     } | ||||
|     return this.appsettings.ImprintURL; | ||||
|   } | ||||
|  | ||||
|   public getWebVersion(): SoftwareVersion | null { | ||||
|     if (!this.appsettings || !this.appsettings.WebVersion) { | ||||
|       console.error('WebVersion is not set!'); | ||||
|   | ||||
| @@ -1,9 +1,11 @@ | ||||
| { | ||||
|     "ApiURL": "http://localhost:8044", | ||||
|     "PrivacyURL": "https://www.sh-edraft.de/Datenschutz", | ||||
|     "ImprintURL": "https://www.sh-edraft.de/Impressum", | ||||
|     "WebVersion": { | ||||
|         "Major": "1", | ||||
|         "Minor": "0", | ||||
|         "Micro": "0.rc2" | ||||
|         "Micro": "dev251" | ||||
|     }, | ||||
|     "Themes": [ | ||||
|         { | ||||
|   | ||||
| @@ -113,7 +113,8 @@ | ||||
|       "register_with_discord": "Mit Discord Registrieren", | ||||
|       "repeat_email": "E-Mail wiederholen", | ||||
|       "repeat_password": "Passwort wiederholen", | ||||
|       "user_already_exists": "Benutzer existiert bereits" | ||||
|       "user_already_exists": "Benutzer existiert bereits", | ||||
|       "confirm_privacy": "Ich erkläre mich mit der <a href=\"{{url}}\">Datenschutzerklärung</a> einverstanden." | ||||
|     } | ||||
|   }, | ||||
|   "common": { | ||||
| @@ -163,7 +164,8 @@ | ||||
|   "footer": { | ||||
|     "backend": "API", | ||||
|     "frontend": "Webseite", | ||||
|     "imprint": "Impressum" | ||||
|     "imprint": "Impressum", | ||||
|     "privacy": "Datenschutz" | ||||
|   }, | ||||
|   "general": { | ||||
|     "days": "Tage", | ||||
|   | ||||
| @@ -113,7 +113,8 @@ | ||||
|       "register_with_discord": "Register with discord", | ||||
|       "repeat_email": "Repeat E-mail", | ||||
|       "repeat_password": "Repeat password", | ||||
|       "user_already_exists": "User already exists" | ||||
|       "user_already_exists": "User already exists", | ||||
|       "confirm_privacy": "I agree to the <a href=\"{{url}}\">Privacy Policy</a>." | ||||
|     } | ||||
|   }, | ||||
|   "common": { | ||||
| @@ -163,7 +164,8 @@ | ||||
|   "footer": { | ||||
|     "backend": "Website", | ||||
|     "frontend": "API", | ||||
|     "imprint": "Imprint" | ||||
|     "imprint": "Imprint", | ||||
|     "privacy": "Privacy" | ||||
|   }, | ||||
|   "general": { | ||||
|     "days": "Days", | ||||
|   | ||||
| @@ -100,6 +100,9 @@ header { | ||||
|   } | ||||
| } | ||||
|  | ||||
| .auth-footer { | ||||
| } | ||||
|  | ||||
| .app { | ||||
|   height: 100%; | ||||
|   display: flex; | ||||
| @@ -474,6 +477,9 @@ footer { | ||||
|   .right { | ||||
|     width: 50%; | ||||
|     text-align: right; | ||||
|     .p-button-label { | ||||
|       font-weight: unset !important; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -488,7 +494,8 @@ footer { | ||||
|   gap: 15px; | ||||
|  | ||||
|   .login-form-wrapper, | ||||
|   .auth-header { | ||||
|   .auth-header, | ||||
|   .auth-footer { | ||||
|     width: 350px; | ||||
|     height: 450px; | ||||
|  | ||||
| @@ -549,6 +556,11 @@ footer { | ||||
|     width: 350px; | ||||
|     height: 75px; | ||||
|   } | ||||
|  | ||||
|   .auth-footer { | ||||
|     width: 350px; | ||||
|     height: 75px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .input-field { | ||||
|   | ||||
| @@ -231,8 +231,10 @@ | ||||
|     background-color: $secondaryBackgroundColor; | ||||
|  | ||||
|     .login-form-wrapper, | ||||
|     .auth-header { | ||||
|     .auth-header, | ||||
|     .auth-footer { | ||||
|       background-color: $primaryBackgroundColor; | ||||
|       color: $primaryTextColor !important; | ||||
|  | ||||
|       .login-form { | ||||
|         .input-field { | ||||
|   | ||||
| @@ -231,8 +231,10 @@ | ||||
|     background-color: $secondaryBackgroundColor; | ||||
|  | ||||
|     .login-form-wrapper, | ||||
|     .auth-header { | ||||
|     .auth-header, | ||||
|     .auth-footer { | ||||
|       background-color: $primaryBackgroundColor; | ||||
|       color: $primaryTextColor !important; | ||||
|  | ||||
|       .login-form { | ||||
|         .input-field { | ||||
|   | ||||
| @@ -235,8 +235,10 @@ | ||||
|     background-color: $secondaryBackgroundColor; | ||||
|  | ||||
|     .login-form-wrapper, | ||||
|     .auth-header { | ||||
|     .auth-header, | ||||
|     .auth-footer { | ||||
|       background-color: $primaryBackgroundColor; | ||||
|       color: $primaryTextColor !important; | ||||
|  | ||||
|       .login-form { | ||||
|         .input-field { | ||||
|   | ||||
| @@ -231,8 +231,10 @@ | ||||
|     background-color: $secondaryBackgroundColor; | ||||
|  | ||||
|     .login-form-wrapper, | ||||
|     .auth-header { | ||||
|     .auth-header, | ||||
|     .auth-footer { | ||||
|       background-color: $primaryBackgroundColor; | ||||
|       color: $primaryTextColor !important; | ||||
|  | ||||
|       .login-form { | ||||
|         .input-field { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user