Compare commits
No commits in common. "b14a4a38a0118d7e9ce00f2849eadf483f08251a" and "0be5c36194a5b59cf56bb0c7e649bf04a3100afe" have entirely different histories.
b14a4a38a0
...
0be5c36194
|
@ -28,9 +28,6 @@
|
||||||
"@angular/platform-browser": "^17.3.0",
|
"@angular/platform-browser": "^17.3.0",
|
||||||
"@angular/platform-browser-dynamic": "^17.3.0",
|
"@angular/platform-browser-dynamic": "^17.3.0",
|
||||||
"@angular/router": "^17.3.0",
|
"@angular/router": "^17.3.0",
|
||||||
"@types/dompurify": "^3.0.5",
|
|
||||||
"crypto-js": "^4.2.0",
|
|
||||||
"dompurify": "^3.1.3",
|
|
||||||
"primeng": "^17.11.0",
|
"primeng": "^17.11.0",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
"tslib": "^2.3.0",
|
"tslib": "^2.3.0",
|
||||||
|
@ -48,7 +45,6 @@
|
||||||
"@stylistic/eslint-plugin": "^2.1.0",
|
"@stylistic/eslint-plugin": "^2.1.0",
|
||||||
"@stylistic/eslint-plugin-migrate": "^2.1.0",
|
"@stylistic/eslint-plugin-migrate": "^2.1.0",
|
||||||
"@stylistic/eslint-plugin-ts": "^2.1.0",
|
"@stylistic/eslint-plugin-ts": "^2.1.0",
|
||||||
"@types/crypto-js": "^4.2.2",
|
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"@typescript-eslint/eslint-plugin": "6.19.0",
|
"@typescript-eslint/eslint-plugin": "6.19.0",
|
||||||
"@typescript-eslint/parser": "6.19.0",
|
"@typescript-eslint/parser": "6.19.0",
|
||||||
|
|
|
@ -29,15 +29,6 @@ dependencies:
|
||||||
'@angular/router':
|
'@angular/router':
|
||||||
specifier: ^17.3.0
|
specifier: ^17.3.0
|
||||||
version: 17.3.0(@angular/common@17.3.0)(@angular/core@17.3.0)(@angular/platform-browser@17.3.0)(rxjs@7.8.1)
|
version: 17.3.0(@angular/common@17.3.0)(@angular/core@17.3.0)(@angular/platform-browser@17.3.0)(rxjs@7.8.1)
|
||||||
'@types/dompurify':
|
|
||||||
specifier: ^3.0.5
|
|
||||||
version: 3.0.5
|
|
||||||
crypto-js:
|
|
||||||
specifier: ^4.2.0
|
|
||||||
version: 4.2.0
|
|
||||||
dompurify:
|
|
||||||
specifier: ^3.1.3
|
|
||||||
version: 3.1.3
|
|
||||||
primeng:
|
primeng:
|
||||||
specifier: ^17.11.0
|
specifier: ^17.11.0
|
||||||
version: 17.11.0(@angular/common@17.3.0)(@angular/core@17.3.0)(@angular/forms@17.3.0)(rxjs@7.8.1)(zone.js@0.14.4)
|
version: 17.11.0(@angular/common@17.3.0)(@angular/core@17.3.0)(@angular/forms@17.3.0)(rxjs@7.8.1)(zone.js@0.14.4)
|
||||||
|
@ -85,9 +76,6 @@ devDependencies:
|
||||||
'@stylistic/eslint-plugin-ts':
|
'@stylistic/eslint-plugin-ts':
|
||||||
specifier: ^2.1.0
|
specifier: ^2.1.0
|
||||||
version: 2.1.0(eslint@8.57.0)(typescript@5.4.2)
|
version: 2.1.0(eslint@8.57.0)(typescript@5.4.2)
|
||||||
'@types/crypto-js':
|
|
||||||
specifier: ^4.2.2
|
|
||||||
version: 4.2.2
|
|
||||||
'@types/jest':
|
'@types/jest':
|
||||||
specifier: ^29.5.12
|
specifier: ^29.5.12
|
||||||
version: 29.5.12
|
version: 29.5.12
|
||||||
|
@ -3243,16 +3231,6 @@ packages:
|
||||||
'@types/node': 20.11.27
|
'@types/node': 20.11.27
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/crypto-js@4.2.2:
|
|
||||||
resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/dompurify@3.0.5:
|
|
||||||
resolution: {integrity: sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==}
|
|
||||||
dependencies:
|
|
||||||
'@types/trusted-types': 2.0.7
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/eslint-scope@3.7.7:
|
/@types/eslint-scope@3.7.7:
|
||||||
resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==}
|
resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -3422,10 +3400,6 @@ packages:
|
||||||
resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==}
|
resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/trusted-types@2.0.7:
|
|
||||||
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@types/ws@8.5.10:
|
/@types/ws@8.5.10:
|
||||||
resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==}
|
resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -4736,10 +4710,6 @@ packages:
|
||||||
which: 2.0.2
|
which: 2.0.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/crypto-js@4.2.0:
|
|
||||||
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/css-loader@6.10.0(webpack@5.90.3):
|
/css-loader@6.10.0(webpack@5.90.3):
|
||||||
resolution: {integrity: sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==}
|
resolution: {integrity: sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==}
|
||||||
engines: {node: '>= 12.13.0'}
|
engines: {node: '>= 12.13.0'}
|
||||||
|
@ -5028,10 +4998,6 @@ packages:
|
||||||
domelementtype: 2.3.0
|
domelementtype: 2.3.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/dompurify@3.1.3:
|
|
||||||
resolution: {integrity: sha512-5sOWYSNPaxz6o2MUPvtyxTTqR4D3L77pr5rUQoWgD5ROQtVIZQgJkXbo1DLlK3vj11YGw5+LnF4SYti4gZmwng==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/domutils@3.1.0:
|
/domutils@3.1.0:
|
||||||
resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==}
|
resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
|
@ -6,16 +6,16 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="content-zone">
|
<div class="content-zone">
|
||||||
<h1>
|
<h1>
|
||||||
@if (isSignupSignal()) {
|
@if (this.isSignupSignal()) {
|
||||||
Anmelden
|
Anmelden
|
||||||
} @else if (isRegisterSignal()) {
|
} @else if (this.isRegisterSignal()) {
|
||||||
Registrieren
|
Registrieren
|
||||||
} @else {
|
} @else {
|
||||||
Erste Schritte
|
Erste Schritte
|
||||||
}
|
}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
@if (isDisplayButtons()) {
|
@if (this.isDisplayButtons()) {
|
||||||
<div class="action">
|
<div class="action">
|
||||||
<button
|
<button
|
||||||
pButton
|
pButton
|
||||||
|
@ -30,10 +30,10 @@
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (isSignupSignal() || isRegisterSignal()) {
|
<div
|
||||||
<div class="register-wrapper">
|
class="register-wrapper"
|
||||||
@if (form) {
|
*ngIf="isSignupSignal() || isRegisterSignal()">
|
||||||
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
<form [formGroup]="form" *ngIf="form" (ngSubmit)="onSubmit()">
|
||||||
<div class="e-mail">
|
<div class="e-mail">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<label for="email">E-Mail</label>
|
<label for="email">E-Mail</label>
|
||||||
|
@ -55,13 +55,13 @@
|
||||||
aria-describedby="password"
|
aria-describedby="password"
|
||||||
[toggleMask]="true"></p-password>
|
[toggleMask]="true"></p-password>
|
||||||
</div>
|
</div>
|
||||||
@if (isRegisterSignal()) {
|
@if (this.isRegisterSignal()) {
|
||||||
<div class="terms">
|
<div class="terms">
|
||||||
<p-checkbox
|
<p-checkbox
|
||||||
formControlName="terms"
|
formControlName="terms"
|
||||||
label="Ich habe die AGB gelesen und stimme zu."
|
label="Ich habe die AGB gelesen und stimme zu."
|
||||||
name="terms"
|
name="terms"
|
||||||
[binary]="true"></p-checkbox>
|
[binary]="true" />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div class="signup">
|
<div class="signup">
|
||||||
|
@ -69,17 +69,12 @@
|
||||||
pButton
|
pButton
|
||||||
type="submit"
|
type="submit"
|
||||||
[label]="
|
[label]="
|
||||||
isSignupSignal()
|
isSignupSignal() ? 'Anmelden' : '✨ Jetzt KOSTENFREI loslegen ✨'
|
||||||
? 'Anmelden'
|
|
||||||
: '✨ Jetzt KOSTENFREI loslegen ✨'
|
|
||||||
"></button>
|
"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="change-mask">
|
<div class="change-mask">
|
||||||
<a
|
<a (click)="switchMask()" (keyup.enter)="switchMask()" tabindex="0">
|
||||||
(click)="switchMask()"
|
@if (this.isSignupSignal()) {
|
||||||
(keyup.enter)="switchMask()"
|
|
||||||
tabindex="0">
|
|
||||||
@if (isSignupSignal()) {
|
|
||||||
Kein Account? Erstellen Sie jetzt KOSTENFREI einen!
|
Kein Account? Erstellen Sie jetzt KOSTENFREI einen!
|
||||||
} @else {
|
} @else {
|
||||||
Schon einen Account? Hier einloggen
|
Schon einen Account? Hier einloggen
|
||||||
|
@ -87,8 +82,6 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
}
|
</div>
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,77 +1,38 @@
|
||||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
|
||||||
|
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { LoginCredentials, Tokens } from '../types';
|
import { LoginCredentials, Tokens } from '../types';
|
||||||
|
|
||||||
import { LocalStorageService } from './local-storage.service';
|
|
||||||
import { SessionStorageService } from './session-storage.service';
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
private readonly path: string = '/api/auth';
|
private isAuthenticated: boolean = false;
|
||||||
private access_token: string | null = null;
|
private access_token: string | null = null;
|
||||||
private refresh_token: string | null = null;
|
private refresh_token: string | null = null;
|
||||||
private isAuthenticated$: BehaviorSubject<boolean> =
|
|
||||||
new BehaviorSubject<boolean>(false);
|
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private readonly httpClient: HttpClient,
|
private readonly httpClient: HttpClient,
|
||||||
private readonly localStorageService: LocalStorageService,
|
private readonly router: Router
|
||||||
private readonly sessionStorageService: SessionStorageService
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public signin(credentials: LoginCredentials): void {
|
public signin(credentials: LoginCredentials): void {
|
||||||
this.httpClient
|
this.httpClient
|
||||||
.post<Tokens>(environment.api.base + `${this.path}/signin`, credentials)
|
.post<Tokens>(environment.api.base + '/api/auth/signin', credentials)
|
||||||
.subscribe((response: Tokens) => {
|
.subscribe((response: Tokens) => {
|
||||||
this.handleSuccess(response);
|
this.access_token = response.access_token;
|
||||||
|
this.refresh_token = response.refresh_token;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public signup(credentials: LoginCredentials): void {
|
public signup(credentials: LoginCredentials): void {
|
||||||
this.httpClient
|
this.httpClient
|
||||||
.post<Tokens>(environment.api.base + `${this.path}/signup`, credentials)
|
.post<Tokens>(environment.api.base + '/api/auth/signup', credentials)
|
||||||
.subscribe((response: Tokens) => {
|
.subscribe((response: Tokens) => {
|
||||||
// The checked accept terms should be saved with a timestamp in the db
|
this.access_token = response.access_token;
|
||||||
this.handleSuccess(response);
|
this.refresh_token = response.refresh_token;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public signout(): void {
|
|
||||||
this.access_token = null;
|
|
||||||
this.refresh_token = null;
|
|
||||||
this.localStorageService.removeItem('access_token');
|
|
||||||
this.sessionStorageService.removeItem('refresh_token');
|
|
||||||
this.isAuthenticated$.next(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public refreshToken(): void {
|
|
||||||
const headers = new HttpHeaders().set(
|
|
||||||
'Authorization',
|
|
||||||
'Bearer ' + this.refresh_token
|
|
||||||
);
|
|
||||||
|
|
||||||
this.httpClient
|
|
||||||
.post<Tokens>(
|
|
||||||
environment.api.base + `${this.path}/refresh`,
|
|
||||||
{},
|
|
||||||
{ headers: headers }
|
|
||||||
)
|
|
||||||
.subscribe((response: Tokens) => {
|
|
||||||
this.handleSuccess(response);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleSuccess(tokens: Tokens): void {
|
|
||||||
this.access_token = tokens.access_token;
|
|
||||||
this.refresh_token = tokens.refresh_token;
|
|
||||||
this.localStorageService.setItem('access_token', tokens.access_token);
|
|
||||||
this.sessionStorageService.setItem('refresh_token', tokens.refresh_token);
|
|
||||||
this.isAuthenticated$.next(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
import { EncryptionService } from './encryption.service';
|
|
||||||
import { SanitizationService } from './sanitization.service';
|
|
||||||
|
|
||||||
export abstract class BaseStorageService {
|
|
||||||
protected abstract getStorage(): Storage;
|
|
||||||
|
|
||||||
public setItem<T>(key: string, value: T): void {
|
|
||||||
const sanitizedValue = SanitizationService.sanitize(JSON.stringify(value));
|
|
||||||
const encryptedValue = EncryptionService.encrypt(sanitizedValue);
|
|
||||||
|
|
||||||
this.getStorage().setItem(key, encryptedValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getItem<T>(key: string): T | null {
|
|
||||||
const encryptedValue = this.getStorage().getItem(key);
|
|
||||||
|
|
||||||
if (encryptedValue) {
|
|
||||||
const decryptedValue = EncryptionService.decrypt(encryptedValue);
|
|
||||||
const sanitizedValue = SanitizationService.sanitize(decryptedValue);
|
|
||||||
|
|
||||||
return JSON.parse(sanitizedValue) as T;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeItem(key: string): void {
|
|
||||||
this.getStorage().removeItem(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public clear(): void {
|
|
||||||
this.getStorage().clear();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import * as CryptoJS from 'crypto-js';
|
|
||||||
|
|
||||||
import { environment } from '../../../environments/environment';
|
|
||||||
|
|
||||||
export class EncryptionService {
|
|
||||||
private static readonly key: string = environment.security.encryptionKey;
|
|
||||||
|
|
||||||
public static encrypt(data: string): string {
|
|
||||||
return CryptoJS.AES.encrypt(data, this.key).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static decrypt(data: string): string {
|
|
||||||
return CryptoJS.AES.decrypt(data, this.key).toString(CryptoJS.enc.Utf8);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +1 @@
|
||||||
export * from './auth.service';
|
export * from './auth.service';
|
||||||
export * from './local-storage.service';
|
|
||||||
export * from './session-storage.service';
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
import { BaseStorageService } from './base-storage.service';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root',
|
|
||||||
})
|
|
||||||
export class LocalStorageService extends BaseStorageService {
|
|
||||||
protected getStorage(): Storage {
|
|
||||||
return localStorage;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
import DOMPurify from 'dompurify';
|
|
||||||
|
|
||||||
export class SanitizationService {
|
|
||||||
public static sanitize(data: string): string {
|
|
||||||
return DOMPurify.sanitize(data);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
import { BaseStorageService } from './base-storage.service';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root',
|
|
||||||
})
|
|
||||||
export class SessionStorageService extends BaseStorageService {
|
|
||||||
protected getStorage(): Storage {
|
|
||||||
return sessionStorage;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,9 +3,6 @@ export const environment = {
|
||||||
api: {
|
api: {
|
||||||
base: 'http://localhost:3000',
|
base: 'http://localhost:3000',
|
||||||
},
|
},
|
||||||
security: {
|
|
||||||
encryptionKey: 'my-secret',
|
|
||||||
},
|
|
||||||
oauth: {
|
oauth: {
|
||||||
clinetId: 'app_FLXnxSBnnaKkXoYCgk3J62iA',
|
clinetId: 'app_FLXnxSBnnaKkXoYCgk3J62iA',
|
||||||
redirectUri: 'https://commonly-hot-airedale.ngrok-free.app/oauth',
|
redirectUri: 'https://commonly-hot-airedale.ngrok-free.app/oauth',
|
||||||
|
|
Loading…
Reference in New Issue