@mintplayer/ng-spark-auth 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, signal, computed, Injectable, Pipe, makeEnvironmentProviders, Component } from '@angular/core';
|
|
3
|
-
import { HttpClient, withInterceptors, withXsrfConfiguration } from '@angular/common/http';
|
|
4
|
-
import {
|
|
2
|
+
import { InjectionToken, inject, signal, computed, Injectable, Pipe, makeEnvironmentProviders, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { HttpClient, withInterceptors, withXsrfConfiguration, HttpErrorResponse } from '@angular/common/http';
|
|
4
|
+
import { firstValueFrom, tap } from 'rxjs';
|
|
5
5
|
import { Router, RouterLink, ActivatedRoute } from '@angular/router';
|
|
6
6
|
import * as i1 from '@angular/forms';
|
|
7
7
|
import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
8
|
+
import { Color } from '@mintplayer/ng-bootstrap';
|
|
9
|
+
import { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';
|
|
10
|
+
import { BsCardComponent, BsCardHeaderComponent } from '@mintplayer/ng-bootstrap/card';
|
|
11
|
+
import { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';
|
|
12
|
+
import { BsToggleButtonComponent } from '@mintplayer/ng-bootstrap/toggle-button';
|
|
13
|
+
import { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';
|
|
12
14
|
|
|
13
15
|
const SPARK_AUTH_CONFIG = new InjectionToken('SPARK_AUTH_CONFIG');
|
|
14
16
|
const defaultSparkAuthConfig = {
|
|
@@ -26,52 +28,57 @@ class SparkAuthService {
|
|
|
26
28
|
user = this.currentUser.asReadonly();
|
|
27
29
|
isAuthenticated = computed(() => this.currentUser()?.isAuthenticated === true, ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : []));
|
|
28
30
|
constructor() {
|
|
29
|
-
this.checkAuth()
|
|
31
|
+
this.checkAuth();
|
|
30
32
|
}
|
|
31
|
-
login(email, password) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
async login(email, password) {
|
|
34
|
+
await firstValueFrom(this.http.post(`${this.config.apiBasePath}/login?useCookies=true`, { email, password }));
|
|
35
|
+
await this.csrfRefresh();
|
|
36
|
+
await this.checkAuth();
|
|
35
37
|
}
|
|
36
|
-
loginTwoFactor(twoFactorCode, twoFactorRecoveryCode) {
|
|
37
|
-
|
|
38
|
-
.post(`${this.config.apiBasePath}/login?useCookies=true`, {
|
|
38
|
+
async loginTwoFactor(twoFactorCode, twoFactorRecoveryCode) {
|
|
39
|
+
await firstValueFrom(this.http.post(`${this.config.apiBasePath}/login?useCookies=true`, {
|
|
39
40
|
twoFactorCode,
|
|
40
41
|
twoFactorRecoveryCode,
|
|
41
|
-
})
|
|
42
|
-
|
|
42
|
+
}));
|
|
43
|
+
await this.csrfRefresh();
|
|
44
|
+
await this.checkAuth();
|
|
43
45
|
}
|
|
44
|
-
register(email, password) {
|
|
45
|
-
|
|
46
|
+
async register(email, password) {
|
|
47
|
+
await firstValueFrom(this.http.post(`${this.config.apiBasePath}/register`, { email, password }));
|
|
46
48
|
}
|
|
47
|
-
logout() {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
async logout() {
|
|
50
|
+
await firstValueFrom(this.http.post(`${this.config.apiBasePath}/logout`, {}));
|
|
51
|
+
await this.csrfRefresh();
|
|
52
|
+
this.currentUser.set(null);
|
|
51
53
|
}
|
|
52
|
-
csrfRefresh() {
|
|
53
|
-
|
|
54
|
+
async csrfRefresh() {
|
|
55
|
+
await firstValueFrom(this.http.post(`${this.config.apiBasePath}/csrf-refresh`, {}));
|
|
54
56
|
}
|
|
55
|
-
checkAuth() {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
async checkAuth() {
|
|
58
|
+
try {
|
|
59
|
+
const user = await firstValueFrom(this.http.get(`${this.config.apiBasePath}/me`));
|
|
60
|
+
this.currentUser.set(user);
|
|
61
|
+
return user;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
this.currentUser.set(null);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
60
67
|
}
|
|
61
|
-
forgotPassword(email) {
|
|
62
|
-
|
|
68
|
+
async forgotPassword(email) {
|
|
69
|
+
await firstValueFrom(this.http.post(`${this.config.apiBasePath}/forgotPassword`, { email }));
|
|
63
70
|
}
|
|
64
|
-
resetPassword(email, resetCode, newPassword) {
|
|
65
|
-
|
|
71
|
+
async resetPassword(email, resetCode, newPassword) {
|
|
72
|
+
await firstValueFrom(this.http.post(`${this.config.apiBasePath}/resetPassword`, {
|
|
66
73
|
email,
|
|
67
74
|
resetCode,
|
|
68
75
|
newPassword,
|
|
69
|
-
});
|
|
76
|
+
}));
|
|
70
77
|
}
|
|
71
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
72
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.
|
|
78
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkAuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
79
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkAuthService, providedIn: 'root' });
|
|
73
80
|
}
|
|
74
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
81
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkAuthService, decorators: [{
|
|
75
82
|
type: Injectable,
|
|
76
83
|
args: [{ providedIn: 'root' }]
|
|
77
84
|
}], ctorParameters: () => [] });
|
|
@@ -80,9 +87,16 @@ class SparkAuthTranslationService {
|
|
|
80
87
|
http = inject(HttpClient);
|
|
81
88
|
translationsMap = signal({}, ...(ngDevMode ? [{ debugName: "translationsMap" }] : []));
|
|
82
89
|
constructor() {
|
|
83
|
-
this.
|
|
90
|
+
this.loadTranslations();
|
|
91
|
+
}
|
|
92
|
+
async loadTranslations() {
|
|
93
|
+
try {
|
|
94
|
+
const t = await firstValueFrom(this.http.get('/spark/translations'));
|
|
84
95
|
this.translationsMap.set(t);
|
|
85
|
-
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// Translations failed to load; keys will be shown as-is
|
|
99
|
+
}
|
|
86
100
|
}
|
|
87
101
|
t(key) {
|
|
88
102
|
const ts = this.translationsMap()[key];
|
|
@@ -91,10 +105,10 @@ class SparkAuthTranslationService {
|
|
|
91
105
|
const lang = localStorage.getItem('spark-lang') ?? navigator.language?.split('-')[0] ?? 'en';
|
|
92
106
|
return ts[lang] ?? ts['en'] ?? Object.values(ts)[0] ?? key;
|
|
93
107
|
}
|
|
94
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
95
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.
|
|
108
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkAuthTranslationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
109
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkAuthTranslationService, providedIn: 'root' });
|
|
96
110
|
}
|
|
97
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
111
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkAuthTranslationService, decorators: [{
|
|
98
112
|
type: Injectable,
|
|
99
113
|
args: [{ providedIn: 'root' }]
|
|
100
114
|
}], ctorParameters: () => [] });
|
|
@@ -104,10 +118,10 @@ class TranslateKeyPipe {
|
|
|
104
118
|
transform(key) {
|
|
105
119
|
return this.translation.t(key);
|
|
106
120
|
}
|
|
107
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
108
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
121
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TranslateKeyPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
122
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: TranslateKeyPipe, isStandalone: true, name: "t", pure: false });
|
|
109
123
|
}
|
|
110
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
124
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TranslateKeyPipe, decorators: [{
|
|
111
125
|
type: Pipe,
|
|
112
126
|
args: [{ name: 't', pure: false, standalone: true }]
|
|
113
127
|
}] });
|
|
@@ -202,36 +216,16 @@ class SparkAuthBarComponent {
|
|
|
202
216
|
authService = inject(SparkAuthService);
|
|
203
217
|
config = inject(SPARK_AUTH_CONFIG);
|
|
204
218
|
router = inject(Router);
|
|
205
|
-
onLogout() {
|
|
206
|
-
this.authService.logout()
|
|
207
|
-
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: SparkAuthBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
211
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: SparkAuthBarComponent, isStandalone: true, selector: "spark-auth-bar", ngImport: i0, template: `
|
|
212
|
-
@if (authService.isAuthenticated()) {
|
|
213
|
-
<span class="me-2">{{ authService.user()?.userName }}</span>
|
|
214
|
-
<button class="btn btn-outline-light btn-sm" (click)="onLogout()">{{ 'authLogout' | t }}</button>
|
|
215
|
-
} @else {
|
|
216
|
-
<a class="btn btn-outline-light btn-sm" [routerLink]="config.loginUrl">{{ 'authLogin' | t }}</a>
|
|
219
|
+
async onLogout() {
|
|
220
|
+
await this.authService.logout();
|
|
221
|
+
this.router.navigateByUrl('/');
|
|
217
222
|
}
|
|
218
|
-
|
|
223
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkAuthBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
224
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SparkAuthBarComponent, isStandalone: true, selector: "spark-auth-bar", ngImport: i0, template: "@if (authService.isAuthenticated()) {\n <span class=\"me-2\">{{ authService.user()?.userName }}</span>\n <button class=\"btn btn-outline-light btn-sm\" (click)=\"onLogout()\">{{ 'authLogout' | t }}</button>\n} @else {\n <a class=\"btn btn-outline-light btn-sm\" [routerLink]=\"config.loginUrl\">{{ 'authLogin' | t }}</a>\n}\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
219
225
|
}
|
|
220
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
226
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkAuthBarComponent, decorators: [{
|
|
221
227
|
type: Component,
|
|
222
|
-
args: [{
|
|
223
|
-
selector: 'spark-auth-bar',
|
|
224
|
-
standalone: true,
|
|
225
|
-
imports: [RouterLink, TranslateKeyPipe],
|
|
226
|
-
template: `
|
|
227
|
-
@if (authService.isAuthenticated()) {
|
|
228
|
-
<span class="me-2">{{ authService.user()?.userName }}</span>
|
|
229
|
-
<button class="btn btn-outline-light btn-sm" (click)="onLogout()">{{ 'authLogout' | t }}</button>
|
|
230
|
-
} @else {
|
|
231
|
-
<a class="btn btn-outline-light btn-sm" [routerLink]="config.loginUrl">{{ 'authLogin' | t }}</a>
|
|
232
|
-
}
|
|
233
|
-
`,
|
|
234
|
-
}]
|
|
228
|
+
args: [{ selector: 'spark-auth-bar', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [RouterLink, TranslateKeyPipe], template: "@if (authService.isAuthenticated()) {\n <span class=\"me-2\">{{ authService.user()?.userName }}</span>\n <button class=\"btn btn-outline-light btn-sm\" (click)=\"onLogout()\">{{ 'authLogout' | t }}</button>\n} @else {\n <a class=\"btn btn-outline-light btn-sm\" [routerLink]=\"config.loginUrl\">{{ 'authLogin' | t }}</a>\n}\n" }]
|
|
235
229
|
}] });
|
|
236
230
|
|
|
237
231
|
class SparkLoginComponent {
|
|
@@ -242,6 +236,7 @@ class SparkLoginComponent {
|
|
|
242
236
|
config = inject(SPARK_AUTH_CONFIG);
|
|
243
237
|
translation = inject(SparkAuthTranslationService);
|
|
244
238
|
routePaths = inject(SPARK_AUTH_ROUTE_PATHS);
|
|
239
|
+
colors = Color;
|
|
245
240
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
246
241
|
errorMessage = signal('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
|
|
247
242
|
form = this.fb.group({
|
|
@@ -249,159 +244,38 @@ class SparkLoginComponent {
|
|
|
249
244
|
password: ['', Validators.required],
|
|
250
245
|
rememberMe: [false],
|
|
251
246
|
});
|
|
252
|
-
onSubmit() {
|
|
247
|
+
async onSubmit() {
|
|
253
248
|
if (this.form.invalid)
|
|
254
249
|
return;
|
|
255
250
|
this.loading.set(true);
|
|
256
251
|
this.errorMessage.set('');
|
|
257
252
|
const { email, password } = this.form.value;
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
253
|
+
try {
|
|
254
|
+
await this.authService.login(email, password);
|
|
255
|
+
const returnUrl = this.route.snapshot.queryParamMap.get('returnUrl');
|
|
256
|
+
this.router.navigateByUrl(returnUrl || this.config.defaultRedirectUrl);
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
if (err instanceof HttpErrorResponse && err.status === 401 && err.error?.detail === 'RequiresTwoFactor') {
|
|
261
260
|
const returnUrl = this.route.snapshot.queryParamMap.get('returnUrl');
|
|
262
|
-
this.router.
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
this.errorMessage.set(this.translation.t('authInvalidCredentials'));
|
|
274
|
-
}
|
|
275
|
-
},
|
|
276
|
-
});
|
|
261
|
+
this.router.navigate([this.routePaths.twoFactor], {
|
|
262
|
+
queryParams: returnUrl ? { returnUrl } : undefined,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
this.errorMessage.set(this.translation.t('authInvalidCredentials'));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
finally {
|
|
270
|
+
this.loading.set(false);
|
|
271
|
+
}
|
|
277
272
|
}
|
|
278
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
279
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
280
|
-
<div class="d-flex justify-content-center">
|
|
281
|
-
<div class="card" style="width: 100%; max-width: 400px;">
|
|
282
|
-
<div class="card-body">
|
|
283
|
-
<h3 class="card-title text-center mb-4">{{ 'authLogin' | t }}</h3>
|
|
284
|
-
|
|
285
|
-
@if (errorMessage()) {
|
|
286
|
-
<div class="alert alert-danger" role="alert">{{ errorMessage() }}</div>
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
<bs-form>
|
|
290
|
-
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
291
|
-
<div class="mb-3">
|
|
292
|
-
<label for="email" class="form-label">{{ 'authEmail' | t }}</label>
|
|
293
|
-
<input
|
|
294
|
-
type="text"
|
|
295
|
-
id="email"
|
|
296
|
-
formControlName="email"
|
|
297
|
-
autocomplete="username"
|
|
298
|
-
/>
|
|
299
|
-
</div>
|
|
300
|
-
|
|
301
|
-
<div class="mb-3">
|
|
302
|
-
<label for="password" class="form-label">{{ 'authPassword' | t }}</label>
|
|
303
|
-
<input
|
|
304
|
-
type="password"
|
|
305
|
-
id="password"
|
|
306
|
-
formControlName="password"
|
|
307
|
-
autocomplete="current-password"
|
|
308
|
-
/>
|
|
309
|
-
</div>
|
|
310
|
-
|
|
311
|
-
<div class="mb-3">
|
|
312
|
-
<bs-toggle-button [type]="'checkbox'" formControlName="rememberMe" [name]="'rememberMe'">{{ 'authRememberMe' | t }}</bs-toggle-button>
|
|
313
|
-
</div>
|
|
314
|
-
|
|
315
|
-
<button
|
|
316
|
-
type="submit"
|
|
317
|
-
class="btn btn-primary w-100"
|
|
318
|
-
[disabled]="loading()"
|
|
319
|
-
>
|
|
320
|
-
@if (loading()) {
|
|
321
|
-
<span class="spinner-border spinner-border-sm me-1" role="status"></span>
|
|
322
|
-
}
|
|
323
|
-
{{ 'authLogin' | t }}
|
|
324
|
-
</button>
|
|
325
|
-
</form>
|
|
326
|
-
</bs-form>
|
|
327
|
-
|
|
328
|
-
<div class="mt-3 text-center">
|
|
329
|
-
<a [routerLink]="routePaths.register">{{ 'authCreateAccount' | t }}</a>
|
|
330
|
-
</div>
|
|
331
|
-
<div class="mt-2 text-center">
|
|
332
|
-
<a [routerLink]="routePaths.forgotPassword">{{ 'authForgotPassword' | t }}</a>
|
|
333
|
-
</div>
|
|
334
|
-
</div>
|
|
335
|
-
</div>
|
|
336
|
-
</div>
|
|
337
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: BsFormModule }, { kind: "component", type: i2.BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: i2.BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "ngmodule", type: BsToggleButtonModule }, { kind: "component", type: i3.BsToggleButtonComponent, selector: "bs-toggle-button", inputs: ["type", "isToggled", "name", "value", "group"], outputs: ["isToggledChange"] }, { kind: "directive", type: i3.BsToggleButtonValueAccessor, selector: "bs-toggle-button" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }] });
|
|
273
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkLoginComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
274
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SparkLoginComponent, isStandalone: true, selector: "spark-login", ngImport: i0, template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'authLogin' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"email\" class=\"form-label\">{{ 'authEmail' | t }}</label>\n <input\n type=\"text\"\n id=\"email\"\n formControlName=\"email\"\n autocomplete=\"username\"\n />\n </div>\n\n <div class=\"mb-3\">\n <label for=\"password\" class=\"form-label\">{{ 'authPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"password\"\n formControlName=\"password\"\n autocomplete=\"current-password\"\n />\n </div>\n\n <div class=\"mb-3\">\n <bs-toggle-button [type]=\"'checkbox'\" formControlName=\"rememberMe\" [name]=\"'rememberMe'\">{{ 'authRememberMe' | t }}</bs-toggle-button>\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'authLogin' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.register\">{{ 'authCreateAccount' | t }}</a>\n </div>\n <div class=\"mt-2 text-center\">\n <a [routerLink]=\"routePaths.forgotPassword\">{{ 'authForgotPassword' | t }}</a>\n </div>\n </div>\n </bs-card>\n</div>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["rounded"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["noPadding"] }, { kind: "component", type: BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "component", type: BsToggleButtonComponent, selector: "bs-toggle-button", inputs: ["type", "isToggled", "name", "value", "group"], outputs: ["isToggledChange"] }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
338
275
|
}
|
|
339
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
276
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkLoginComponent, decorators: [{
|
|
340
277
|
type: Component,
|
|
341
|
-
args: [{
|
|
342
|
-
selector: 'spark-login',
|
|
343
|
-
standalone: true,
|
|
344
|
-
imports: [ReactiveFormsModule, RouterLink, BsFormModule, BsToggleButtonModule, TranslateKeyPipe],
|
|
345
|
-
template: `
|
|
346
|
-
<div class="d-flex justify-content-center">
|
|
347
|
-
<div class="card" style="width: 100%; max-width: 400px;">
|
|
348
|
-
<div class="card-body">
|
|
349
|
-
<h3 class="card-title text-center mb-4">{{ 'authLogin' | t }}</h3>
|
|
350
|
-
|
|
351
|
-
@if (errorMessage()) {
|
|
352
|
-
<div class="alert alert-danger" role="alert">{{ errorMessage() }}</div>
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
<bs-form>
|
|
356
|
-
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
357
|
-
<div class="mb-3">
|
|
358
|
-
<label for="email" class="form-label">{{ 'authEmail' | t }}</label>
|
|
359
|
-
<input
|
|
360
|
-
type="text"
|
|
361
|
-
id="email"
|
|
362
|
-
formControlName="email"
|
|
363
|
-
autocomplete="username"
|
|
364
|
-
/>
|
|
365
|
-
</div>
|
|
366
|
-
|
|
367
|
-
<div class="mb-3">
|
|
368
|
-
<label for="password" class="form-label">{{ 'authPassword' | t }}</label>
|
|
369
|
-
<input
|
|
370
|
-
type="password"
|
|
371
|
-
id="password"
|
|
372
|
-
formControlName="password"
|
|
373
|
-
autocomplete="current-password"
|
|
374
|
-
/>
|
|
375
|
-
</div>
|
|
376
|
-
|
|
377
|
-
<div class="mb-3">
|
|
378
|
-
<bs-toggle-button [type]="'checkbox'" formControlName="rememberMe" [name]="'rememberMe'">{{ 'authRememberMe' | t }}</bs-toggle-button>
|
|
379
|
-
</div>
|
|
380
|
-
|
|
381
|
-
<button
|
|
382
|
-
type="submit"
|
|
383
|
-
class="btn btn-primary w-100"
|
|
384
|
-
[disabled]="loading()"
|
|
385
|
-
>
|
|
386
|
-
@if (loading()) {
|
|
387
|
-
<span class="spinner-border spinner-border-sm me-1" role="status"></span>
|
|
388
|
-
}
|
|
389
|
-
{{ 'authLogin' | t }}
|
|
390
|
-
</button>
|
|
391
|
-
</form>
|
|
392
|
-
</bs-form>
|
|
393
|
-
|
|
394
|
-
<div class="mt-3 text-center">
|
|
395
|
-
<a [routerLink]="routePaths.register">{{ 'authCreateAccount' | t }}</a>
|
|
396
|
-
</div>
|
|
397
|
-
<div class="mt-2 text-center">
|
|
398
|
-
<a [routerLink]="routePaths.forgotPassword">{{ 'authForgotPassword' | t }}</a>
|
|
399
|
-
</div>
|
|
400
|
-
</div>
|
|
401
|
-
</div>
|
|
402
|
-
</div>
|
|
403
|
-
`,
|
|
404
|
-
}]
|
|
278
|
+
args: [{ selector: 'spark-login', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsToggleButtonComponent, BsSpinnerComponent, TranslateKeyPipe], template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'authLogin' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"email\" class=\"form-label\">{{ 'authEmail' | t }}</label>\n <input\n type=\"text\"\n id=\"email\"\n formControlName=\"email\"\n autocomplete=\"username\"\n />\n </div>\n\n <div class=\"mb-3\">\n <label for=\"password\" class=\"form-label\">{{ 'authPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"password\"\n formControlName=\"password\"\n autocomplete=\"current-password\"\n />\n </div>\n\n <div class=\"mb-3\">\n <bs-toggle-button [type]=\"'checkbox'\" formControlName=\"rememberMe\" [name]=\"'rememberMe'\">{{ 'authRememberMe' | t }}</bs-toggle-button>\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'authLogin' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.register\">{{ 'authCreateAccount' | t }}</a>\n </div>\n <div class=\"mt-2 text-center\">\n <a [routerLink]=\"routePaths.forgotPassword\">{{ 'authForgotPassword' | t }}</a>\n </div>\n </div>\n </bs-card>\n</div>\n" }]
|
|
405
279
|
}] });
|
|
406
280
|
|
|
407
281
|
var sparkLogin_component = /*#__PURE__*/Object.freeze({
|
|
@@ -418,6 +292,7 @@ class SparkTwoFactorComponent {
|
|
|
418
292
|
config = inject(SPARK_AUTH_CONFIG);
|
|
419
293
|
translation = inject(SparkAuthTranslationService);
|
|
420
294
|
routePaths = inject(SPARK_AUTH_ROUTE_PATHS);
|
|
295
|
+
colors = Color;
|
|
421
296
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
422
297
|
errorMessage = signal('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
|
|
423
298
|
useRecoveryCode = signal(false, ...(ngDevMode ? [{ debugName: "useRecoveryCode" }] : []));
|
|
@@ -429,7 +304,7 @@ class SparkTwoFactorComponent {
|
|
|
429
304
|
this.useRecoveryCode.update(v => !v);
|
|
430
305
|
this.errorMessage.set('');
|
|
431
306
|
}
|
|
432
|
-
onSubmit() {
|
|
307
|
+
async onSubmit() {
|
|
433
308
|
const isRecovery = this.useRecoveryCode();
|
|
434
309
|
const code = isRecovery ? this.form.value.recoveryCode : this.form.value.code;
|
|
435
310
|
if (!code?.trim()) {
|
|
@@ -442,159 +317,24 @@ class SparkTwoFactorComponent {
|
|
|
442
317
|
this.errorMessage.set('');
|
|
443
318
|
const twoFactorCode = isRecovery ? undefined : code;
|
|
444
319
|
const twoFactorRecoveryCode = isRecovery ? code : undefined;
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
320
|
+
try {
|
|
321
|
+
await this.authService.loginTwoFactor(twoFactorCode ?? '', twoFactorRecoveryCode);
|
|
322
|
+
const returnUrl = this.route.snapshot.queryParamMap.get('returnUrl');
|
|
323
|
+
this.router.navigateByUrl(returnUrl || this.config.defaultRedirectUrl);
|
|
324
|
+
}
|
|
325
|
+
catch {
|
|
326
|
+
this.errorMessage.set(this.translation.t('authInvalidCode'));
|
|
327
|
+
}
|
|
328
|
+
finally {
|
|
329
|
+
this.loading.set(false);
|
|
330
|
+
}
|
|
456
331
|
}
|
|
457
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
458
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
459
|
-
<div class="d-flex justify-content-center">
|
|
460
|
-
<div class="card" style="width: 100%; max-width: 400px;">
|
|
461
|
-
<div class="card-body">
|
|
462
|
-
<h3 class="card-title text-center mb-4">{{ 'authTwoFactorTitle' | t }}</h3>
|
|
463
|
-
|
|
464
|
-
@if (errorMessage()) {
|
|
465
|
-
<div class="alert alert-danger" role="alert">{{ errorMessage() }}</div>
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
<bs-form>
|
|
469
|
-
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
470
|
-
@if (!useRecoveryCode()) {
|
|
471
|
-
<div class="mb-3">
|
|
472
|
-
<label for="code" class="form-label">{{ 'authCode' | t }}</label>
|
|
473
|
-
<input
|
|
474
|
-
type="text"
|
|
475
|
-
id="code"
|
|
476
|
-
formControlName="code"
|
|
477
|
-
autocomplete="one-time-code"
|
|
478
|
-
maxlength="6"
|
|
479
|
-
[placeholder]="'authEnterCode' | t"
|
|
480
|
-
/>
|
|
481
|
-
</div>
|
|
482
|
-
} @else {
|
|
483
|
-
<div class="mb-3">
|
|
484
|
-
<label for="recoveryCode" class="form-label">{{ 'authRecoveryCode' | t }}</label>
|
|
485
|
-
<input
|
|
486
|
-
type="text"
|
|
487
|
-
id="recoveryCode"
|
|
488
|
-
formControlName="recoveryCode"
|
|
489
|
-
autocomplete="off"
|
|
490
|
-
[placeholder]="'authEnterRecoveryCode' | t"
|
|
491
|
-
/>
|
|
492
|
-
</div>
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
<button
|
|
496
|
-
type="submit"
|
|
497
|
-
class="btn btn-primary w-100"
|
|
498
|
-
[disabled]="loading()"
|
|
499
|
-
>
|
|
500
|
-
@if (loading()) {
|
|
501
|
-
<span class="spinner-border spinner-border-sm me-1" role="status"></span>
|
|
502
|
-
}
|
|
503
|
-
{{ 'authVerify' | t }}
|
|
504
|
-
</button>
|
|
505
|
-
</form>
|
|
506
|
-
</bs-form>
|
|
507
|
-
|
|
508
|
-
<div class="mt-3 text-center">
|
|
509
|
-
<button class="btn btn-link" (click)="toggleRecoveryCode()">
|
|
510
|
-
@if (useRecoveryCode()) {
|
|
511
|
-
{{ 'authUseAuthCode' | t }}
|
|
512
|
-
} @else {
|
|
513
|
-
{{ 'authUseRecoveryCode' | t }}
|
|
514
|
-
}
|
|
515
|
-
</button>
|
|
516
|
-
</div>
|
|
517
|
-
<div class="mt-2 text-center">
|
|
518
|
-
<a [routerLink]="routePaths.login">{{ 'authBackToLogin' | t }}</a>
|
|
519
|
-
</div>
|
|
520
|
-
</div>
|
|
521
|
-
</div>
|
|
522
|
-
</div>
|
|
523
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: BsFormModule }, { kind: "component", type: i2.BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: i2.BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }] });
|
|
332
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkTwoFactorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
333
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SparkTwoFactorComponent, isStandalone: true, selector: "spark-two-factor", ngImport: i0, template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'authTwoFactorTitle' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n @if (!useRecoveryCode()) {\n <div class=\"mb-3\">\n <label for=\"code\" class=\"form-label\">{{ 'authCode' | t }}</label>\n <input\n type=\"text\"\n id=\"code\"\n formControlName=\"code\"\n autocomplete=\"one-time-code\"\n maxlength=\"6\"\n [placeholder]=\"'authEnterCode' | t\"\n />\n </div>\n } @else {\n <div class=\"mb-3\">\n <label for=\"recoveryCode\" class=\"form-label\">{{ 'authRecoveryCode' | t }}</label>\n <input\n type=\"text\"\n id=\"recoveryCode\"\n formControlName=\"recoveryCode\"\n autocomplete=\"off\"\n [placeholder]=\"'authEnterRecoveryCode' | t\"\n />\n </div>\n }\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'authVerify' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <button class=\"btn btn-link\" (click)=\"toggleRecoveryCode()\">\n @if (useRecoveryCode()) {\n {{ 'authUseAuthCode' | t }}\n } @else {\n {{ 'authUseRecoveryCode' | t }}\n }\n </button>\n </div>\n <div class=\"mt-2 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'authBackToLogin' | t }}</a>\n </div>\n </div>\n </bs-card>\n</div>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["rounded"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["noPadding"] }, { kind: "component", type: BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
524
334
|
}
|
|
525
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
335
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkTwoFactorComponent, decorators: [{
|
|
526
336
|
type: Component,
|
|
527
|
-
args: [{
|
|
528
|
-
selector: 'spark-two-factor',
|
|
529
|
-
standalone: true,
|
|
530
|
-
imports: [ReactiveFormsModule, RouterLink, BsFormModule, TranslateKeyPipe],
|
|
531
|
-
template: `
|
|
532
|
-
<div class="d-flex justify-content-center">
|
|
533
|
-
<div class="card" style="width: 100%; max-width: 400px;">
|
|
534
|
-
<div class="card-body">
|
|
535
|
-
<h3 class="card-title text-center mb-4">{{ 'authTwoFactorTitle' | t }}</h3>
|
|
536
|
-
|
|
537
|
-
@if (errorMessage()) {
|
|
538
|
-
<div class="alert alert-danger" role="alert">{{ errorMessage() }}</div>
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
<bs-form>
|
|
542
|
-
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
543
|
-
@if (!useRecoveryCode()) {
|
|
544
|
-
<div class="mb-3">
|
|
545
|
-
<label for="code" class="form-label">{{ 'authCode' | t }}</label>
|
|
546
|
-
<input
|
|
547
|
-
type="text"
|
|
548
|
-
id="code"
|
|
549
|
-
formControlName="code"
|
|
550
|
-
autocomplete="one-time-code"
|
|
551
|
-
maxlength="6"
|
|
552
|
-
[placeholder]="'authEnterCode' | t"
|
|
553
|
-
/>
|
|
554
|
-
</div>
|
|
555
|
-
} @else {
|
|
556
|
-
<div class="mb-3">
|
|
557
|
-
<label for="recoveryCode" class="form-label">{{ 'authRecoveryCode' | t }}</label>
|
|
558
|
-
<input
|
|
559
|
-
type="text"
|
|
560
|
-
id="recoveryCode"
|
|
561
|
-
formControlName="recoveryCode"
|
|
562
|
-
autocomplete="off"
|
|
563
|
-
[placeholder]="'authEnterRecoveryCode' | t"
|
|
564
|
-
/>
|
|
565
|
-
</div>
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
<button
|
|
569
|
-
type="submit"
|
|
570
|
-
class="btn btn-primary w-100"
|
|
571
|
-
[disabled]="loading()"
|
|
572
|
-
>
|
|
573
|
-
@if (loading()) {
|
|
574
|
-
<span class="spinner-border spinner-border-sm me-1" role="status"></span>
|
|
575
|
-
}
|
|
576
|
-
{{ 'authVerify' | t }}
|
|
577
|
-
</button>
|
|
578
|
-
</form>
|
|
579
|
-
</bs-form>
|
|
580
|
-
|
|
581
|
-
<div class="mt-3 text-center">
|
|
582
|
-
<button class="btn btn-link" (click)="toggleRecoveryCode()">
|
|
583
|
-
@if (useRecoveryCode()) {
|
|
584
|
-
{{ 'authUseAuthCode' | t }}
|
|
585
|
-
} @else {
|
|
586
|
-
{{ 'authUseRecoveryCode' | t }}
|
|
587
|
-
}
|
|
588
|
-
</button>
|
|
589
|
-
</div>
|
|
590
|
-
<div class="mt-2 text-center">
|
|
591
|
-
<a [routerLink]="routePaths.login">{{ 'authBackToLogin' | t }}</a>
|
|
592
|
-
</div>
|
|
593
|
-
</div>
|
|
594
|
-
</div>
|
|
595
|
-
</div>
|
|
596
|
-
`,
|
|
597
|
-
}]
|
|
337
|
+
args: [{ selector: 'spark-two-factor', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsSpinnerComponent, TranslateKeyPipe], template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'authTwoFactorTitle' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n @if (!useRecoveryCode()) {\n <div class=\"mb-3\">\n <label for=\"code\" class=\"form-label\">{{ 'authCode' | t }}</label>\n <input\n type=\"text\"\n id=\"code\"\n formControlName=\"code\"\n autocomplete=\"one-time-code\"\n maxlength=\"6\"\n [placeholder]=\"'authEnterCode' | t\"\n />\n </div>\n } @else {\n <div class=\"mb-3\">\n <label for=\"recoveryCode\" class=\"form-label\">{{ 'authRecoveryCode' | t }}</label>\n <input\n type=\"text\"\n id=\"recoveryCode\"\n formControlName=\"recoveryCode\"\n autocomplete=\"off\"\n [placeholder]=\"'authEnterRecoveryCode' | t\"\n />\n </div>\n }\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'authVerify' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <button class=\"btn btn-link\" (click)=\"toggleRecoveryCode()\">\n @if (useRecoveryCode()) {\n {{ 'authUseAuthCode' | t }}\n } @else {\n {{ 'authUseRecoveryCode' | t }}\n }\n </button>\n </div>\n <div class=\"mt-2 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'authBackToLogin' | t }}</a>\n </div>\n </div>\n </bs-card>\n</div>\n" }]
|
|
598
338
|
}] });
|
|
599
339
|
|
|
600
340
|
var sparkTwoFactor_component = /*#__PURE__*/Object.freeze({
|
|
@@ -617,6 +357,7 @@ class SparkRegisterComponent {
|
|
|
617
357
|
router = inject(Router);
|
|
618
358
|
translation = inject(SparkAuthTranslationService);
|
|
619
359
|
routePaths = inject(SPARK_AUTH_ROUTE_PATHS);
|
|
360
|
+
colors = Color;
|
|
620
361
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
621
362
|
errorMessage = signal('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
|
|
622
363
|
form = this.fb.group({
|
|
@@ -624,7 +365,7 @@ class SparkRegisterComponent {
|
|
|
624
365
|
password: ['', Validators.required],
|
|
625
366
|
confirmPassword: ['', Validators.required],
|
|
626
367
|
}, { validators: passwordMatchValidator$1 });
|
|
627
|
-
onSubmit() {
|
|
368
|
+
async onSubmit() {
|
|
628
369
|
if (this.form.invalid) {
|
|
629
370
|
this.form.markAllAsTouched();
|
|
630
371
|
return;
|
|
@@ -632,15 +373,14 @@ class SparkRegisterComponent {
|
|
|
632
373
|
this.loading.set(true);
|
|
633
374
|
this.errorMessage.set('');
|
|
634
375
|
const { email, password } = this.form.value;
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
this.loading.set(false);
|
|
376
|
+
try {
|
|
377
|
+
await this.authService.register(email, password);
|
|
378
|
+
this.router.navigate([this.routePaths.login], {
|
|
379
|
+
queryParams: { registered: 'true' },
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
catch (err) {
|
|
383
|
+
if (err instanceof HttpErrorResponse) {
|
|
644
384
|
if (err.status === 400 && err.error?.errors) {
|
|
645
385
|
const messages = [].concat(...Object.values(err.error.errors));
|
|
646
386
|
this.errorMessage.set(messages.join(' '));
|
|
@@ -651,156 +391,21 @@ class SparkRegisterComponent {
|
|
|
651
391
|
else {
|
|
652
392
|
this.errorMessage.set(this.translation.t('authRegistrationFailed'));
|
|
653
393
|
}
|
|
654
|
-
}
|
|
655
|
-
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
this.errorMessage.set(this.translation.t('authRegistrationFailed'));
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
finally {
|
|
400
|
+
this.loading.set(false);
|
|
401
|
+
}
|
|
656
402
|
}
|
|
657
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
658
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
659
|
-
<div class="d-flex justify-content-center">
|
|
660
|
-
<div class="card" style="width: 100%; max-width: 400px;">
|
|
661
|
-
<div class="card-body">
|
|
662
|
-
<h3 class="card-title text-center mb-4">{{ 'authRegister' | t }}</h3>
|
|
663
|
-
|
|
664
|
-
@if (errorMessage()) {
|
|
665
|
-
<div class="alert alert-danger" role="alert">{{ errorMessage() }}</div>
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
<bs-form>
|
|
669
|
-
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
670
|
-
<div class="mb-3">
|
|
671
|
-
<label for="email" class="form-label">{{ 'authEmail' | t }}</label>
|
|
672
|
-
<input
|
|
673
|
-
type="email"
|
|
674
|
-
id="email"
|
|
675
|
-
formControlName="email"
|
|
676
|
-
autocomplete="email"
|
|
677
|
-
/>
|
|
678
|
-
@if (form.get('email')?.touched && form.get('email')?.hasError('email')) {
|
|
679
|
-
<div class="text-danger mt-1">{{ 'authInvalidEmail' | t }}</div>
|
|
680
|
-
}
|
|
681
|
-
</div>
|
|
682
|
-
|
|
683
|
-
<div class="mb-3">
|
|
684
|
-
<label for="password" class="form-label">{{ 'authPassword' | t }}</label>
|
|
685
|
-
<input
|
|
686
|
-
type="password"
|
|
687
|
-
id="password"
|
|
688
|
-
formControlName="password"
|
|
689
|
-
autocomplete="new-password"
|
|
690
|
-
/>
|
|
691
|
-
</div>
|
|
692
|
-
|
|
693
|
-
<div class="mb-3">
|
|
694
|
-
<label for="confirmPassword" class="form-label">{{ 'authConfirmPassword' | t }}</label>
|
|
695
|
-
<input
|
|
696
|
-
type="password"
|
|
697
|
-
id="confirmPassword"
|
|
698
|
-
formControlName="confirmPassword"
|
|
699
|
-
autocomplete="new-password"
|
|
700
|
-
/>
|
|
701
|
-
@if (form.touched && form.hasError('passwordMismatch')) {
|
|
702
|
-
<div class="text-danger mt-1">{{ 'authPasswordMismatch' | t }}</div>
|
|
703
|
-
}
|
|
704
|
-
</div>
|
|
705
|
-
|
|
706
|
-
<button
|
|
707
|
-
type="submit"
|
|
708
|
-
class="btn btn-primary w-100"
|
|
709
|
-
[disabled]="loading()"
|
|
710
|
-
>
|
|
711
|
-
@if (loading()) {
|
|
712
|
-
<span class="spinner-border spinner-border-sm me-1" role="status"></span>
|
|
713
|
-
}
|
|
714
|
-
{{ 'authRegister' | t }}
|
|
715
|
-
</button>
|
|
716
|
-
</form>
|
|
717
|
-
</bs-form>
|
|
718
|
-
|
|
719
|
-
<div class="mt-3 text-center">
|
|
720
|
-
<span>{{ 'authAlreadyHaveAccount' | t }} </span>
|
|
721
|
-
<a [routerLink]="routePaths.login">{{ 'authLogin' | t }}</a>
|
|
722
|
-
</div>
|
|
723
|
-
</div>
|
|
724
|
-
</div>
|
|
725
|
-
</div>
|
|
726
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: BsFormModule }, { kind: "component", type: i2.BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: i2.BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }] });
|
|
403
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkRegisterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
404
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SparkRegisterComponent, isStandalone: true, selector: "spark-register", ngImport: i0, template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'authRegister' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"email\" class=\"form-label\">{{ 'authEmail' | t }}</label>\n <input\n type=\"email\"\n id=\"email\"\n formControlName=\"email\"\n autocomplete=\"email\"\n />\n @if (form.get('email')?.touched && form.get('email')?.hasError('email')) {\n <div class=\"text-danger mt-1\">{{ 'authInvalidEmail' | t }}</div>\n }\n </div>\n\n <div class=\"mb-3\">\n <label for=\"password\" class=\"form-label\">{{ 'authPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"password\"\n formControlName=\"password\"\n autocomplete=\"new-password\"\n />\n </div>\n\n <div class=\"mb-3\">\n <label for=\"confirmPassword\" class=\"form-label\">{{ 'authConfirmPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"confirmPassword\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\"\n />\n @if (form.touched && form.hasError('passwordMismatch')) {\n <div class=\"text-danger mt-1\">{{ 'authPasswordMismatch' | t }}</div>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'authRegister' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <span>{{ 'authAlreadyHaveAccount' | t }} </span>\n <a [routerLink]=\"routePaths.login\">{{ 'authLogin' | t }}</a>\n </div>\n </div>\n </bs-card>\n</div>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["rounded"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["noPadding"] }, { kind: "component", type: BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
727
405
|
}
|
|
728
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
406
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkRegisterComponent, decorators: [{
|
|
729
407
|
type: Component,
|
|
730
|
-
args: [{
|
|
731
|
-
selector: 'spark-register',
|
|
732
|
-
standalone: true,
|
|
733
|
-
imports: [ReactiveFormsModule, RouterLink, BsFormModule, TranslateKeyPipe],
|
|
734
|
-
template: `
|
|
735
|
-
<div class="d-flex justify-content-center">
|
|
736
|
-
<div class="card" style="width: 100%; max-width: 400px;">
|
|
737
|
-
<div class="card-body">
|
|
738
|
-
<h3 class="card-title text-center mb-4">{{ 'authRegister' | t }}</h3>
|
|
739
|
-
|
|
740
|
-
@if (errorMessage()) {
|
|
741
|
-
<div class="alert alert-danger" role="alert">{{ errorMessage() }}</div>
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
<bs-form>
|
|
745
|
-
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
746
|
-
<div class="mb-3">
|
|
747
|
-
<label for="email" class="form-label">{{ 'authEmail' | t }}</label>
|
|
748
|
-
<input
|
|
749
|
-
type="email"
|
|
750
|
-
id="email"
|
|
751
|
-
formControlName="email"
|
|
752
|
-
autocomplete="email"
|
|
753
|
-
/>
|
|
754
|
-
@if (form.get('email')?.touched && form.get('email')?.hasError('email')) {
|
|
755
|
-
<div class="text-danger mt-1">{{ 'authInvalidEmail' | t }}</div>
|
|
756
|
-
}
|
|
757
|
-
</div>
|
|
758
|
-
|
|
759
|
-
<div class="mb-3">
|
|
760
|
-
<label for="password" class="form-label">{{ 'authPassword' | t }}</label>
|
|
761
|
-
<input
|
|
762
|
-
type="password"
|
|
763
|
-
id="password"
|
|
764
|
-
formControlName="password"
|
|
765
|
-
autocomplete="new-password"
|
|
766
|
-
/>
|
|
767
|
-
</div>
|
|
768
|
-
|
|
769
|
-
<div class="mb-3">
|
|
770
|
-
<label for="confirmPassword" class="form-label">{{ 'authConfirmPassword' | t }}</label>
|
|
771
|
-
<input
|
|
772
|
-
type="password"
|
|
773
|
-
id="confirmPassword"
|
|
774
|
-
formControlName="confirmPassword"
|
|
775
|
-
autocomplete="new-password"
|
|
776
|
-
/>
|
|
777
|
-
@if (form.touched && form.hasError('passwordMismatch')) {
|
|
778
|
-
<div class="text-danger mt-1">{{ 'authPasswordMismatch' | t }}</div>
|
|
779
|
-
}
|
|
780
|
-
</div>
|
|
781
|
-
|
|
782
|
-
<button
|
|
783
|
-
type="submit"
|
|
784
|
-
class="btn btn-primary w-100"
|
|
785
|
-
[disabled]="loading()"
|
|
786
|
-
>
|
|
787
|
-
@if (loading()) {
|
|
788
|
-
<span class="spinner-border spinner-border-sm me-1" role="status"></span>
|
|
789
|
-
}
|
|
790
|
-
{{ 'authRegister' | t }}
|
|
791
|
-
</button>
|
|
792
|
-
</form>
|
|
793
|
-
</bs-form>
|
|
794
|
-
|
|
795
|
-
<div class="mt-3 text-center">
|
|
796
|
-
<span>{{ 'authAlreadyHaveAccount' | t }} </span>
|
|
797
|
-
<a [routerLink]="routePaths.login">{{ 'authLogin' | t }}</a>
|
|
798
|
-
</div>
|
|
799
|
-
</div>
|
|
800
|
-
</div>
|
|
801
|
-
</div>
|
|
802
|
-
`,
|
|
803
|
-
}]
|
|
408
|
+
args: [{ selector: 'spark-register', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsSpinnerComponent, TranslateKeyPipe], template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'authRegister' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"email\" class=\"form-label\">{{ 'authEmail' | t }}</label>\n <input\n type=\"email\"\n id=\"email\"\n formControlName=\"email\"\n autocomplete=\"email\"\n />\n @if (form.get('email')?.touched && form.get('email')?.hasError('email')) {\n <div class=\"text-danger mt-1\">{{ 'authInvalidEmail' | t }}</div>\n }\n </div>\n\n <div class=\"mb-3\">\n <label for=\"password\" class=\"form-label\">{{ 'authPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"password\"\n formControlName=\"password\"\n autocomplete=\"new-password\"\n />\n </div>\n\n <div class=\"mb-3\">\n <label for=\"confirmPassword\" class=\"form-label\">{{ 'authConfirmPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"confirmPassword\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\"\n />\n @if (form.touched && form.hasError('passwordMismatch')) {\n <div class=\"text-danger mt-1\">{{ 'authPasswordMismatch' | t }}</div>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'authRegister' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <span>{{ 'authAlreadyHaveAccount' | t }} </span>\n <a [routerLink]=\"routePaths.login\">{{ 'authLogin' | t }}</a>\n </div>\n </div>\n </bs-card>\n</div>\n" }]
|
|
804
409
|
}] });
|
|
805
410
|
|
|
806
411
|
var sparkRegister_component = /*#__PURE__*/Object.freeze({
|
|
@@ -814,13 +419,14 @@ class SparkForgotPasswordComponent {
|
|
|
814
419
|
authService = inject(SparkAuthService);
|
|
815
420
|
translation = inject(SparkAuthTranslationService);
|
|
816
421
|
routePaths = inject(SPARK_AUTH_ROUTE_PATHS);
|
|
422
|
+
colors = Color;
|
|
817
423
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
818
424
|
errorMessage = signal('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
|
|
819
425
|
successMessage = signal('', ...(ngDevMode ? [{ debugName: "successMessage" }] : []));
|
|
820
426
|
form = this.fb.group({
|
|
821
427
|
email: ['', [Validators.required, Validators.email]],
|
|
822
428
|
});
|
|
823
|
-
onSubmit() {
|
|
429
|
+
async onSubmit() {
|
|
824
430
|
if (this.form.invalid) {
|
|
825
431
|
this.form.markAllAsTouched();
|
|
826
432
|
return;
|
|
@@ -829,131 +435,21 @@ class SparkForgotPasswordComponent {
|
|
|
829
435
|
this.errorMessage.set('');
|
|
830
436
|
this.successMessage.set('');
|
|
831
437
|
const { email } = this.form.value;
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
this.successMessage.set(this.translation.t('authForgotPasswordSuccess'));
|
|
841
|
-
},
|
|
842
|
-
});
|
|
438
|
+
try {
|
|
439
|
+
await this.authService.forgotPassword(email);
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
// Don't reveal whether the email exists
|
|
443
|
+
}
|
|
444
|
+
this.successMessage.set(this.translation.t('authForgotPasswordSuccess'));
|
|
445
|
+
this.loading.set(false);
|
|
843
446
|
}
|
|
844
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
845
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
846
|
-
<div class="d-flex justify-content-center">
|
|
847
|
-
<div class="card" style="width: 100%; max-width: 400px;">
|
|
848
|
-
<div class="card-body">
|
|
849
|
-
<h3 class="card-title text-center mb-4">{{ 'authForgotPasswordTitle' | t }}</h3>
|
|
850
|
-
|
|
851
|
-
@if (successMessage()) {
|
|
852
|
-
<div class="alert alert-success" role="alert">{{ successMessage() }}</div>
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
@if (errorMessage()) {
|
|
856
|
-
<div class="alert alert-danger" role="alert">{{ errorMessage() }}</div>
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
@if (!successMessage()) {
|
|
860
|
-
<p class="text-muted mb-3">
|
|
861
|
-
{{ 'authForgotPasswordDescription' | t }}
|
|
862
|
-
</p>
|
|
863
|
-
|
|
864
|
-
<bs-form>
|
|
865
|
-
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
866
|
-
<div class="mb-3">
|
|
867
|
-
<label for="email" class="form-label">{{ 'authEmail' | t }}</label>
|
|
868
|
-
<input
|
|
869
|
-
type="email"
|
|
870
|
-
id="email"
|
|
871
|
-
formControlName="email"
|
|
872
|
-
autocomplete="email"
|
|
873
|
-
/>
|
|
874
|
-
</div>
|
|
875
|
-
|
|
876
|
-
<button
|
|
877
|
-
type="submit"
|
|
878
|
-
class="btn btn-primary w-100"
|
|
879
|
-
[disabled]="loading()"
|
|
880
|
-
>
|
|
881
|
-
@if (loading()) {
|
|
882
|
-
<span class="spinner-border spinner-border-sm me-1" role="status"></span>
|
|
883
|
-
}
|
|
884
|
-
{{ 'authSendResetLink' | t }}
|
|
885
|
-
</button>
|
|
886
|
-
</form>
|
|
887
|
-
</bs-form>
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
<div class="mt-3 text-center">
|
|
891
|
-
<a [routerLink]="routePaths.login">{{ 'authBackToLogin' | t }}</a>
|
|
892
|
-
</div>
|
|
893
|
-
</div>
|
|
894
|
-
</div>
|
|
895
|
-
</div>
|
|
896
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: BsFormModule }, { kind: "component", type: i2.BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: i2.BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }] });
|
|
447
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkForgotPasswordComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
448
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SparkForgotPasswordComponent, isStandalone: true, selector: "spark-forgot-password", ngImport: i0, template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'authForgotPasswordTitle' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (successMessage()) {\n <bs-alert [type]=\"colors.success\" class=\"mb-3\">{{ successMessage() }}</bs-alert>\n }\n\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n @if (!successMessage()) {\n <p class=\"text-muted mb-3\">\n {{ 'authForgotPasswordDescription' | t }}\n </p>\n\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"email\" class=\"form-label\">{{ 'authEmail' | t }}</label>\n <input\n type=\"email\"\n id=\"email\"\n formControlName=\"email\"\n autocomplete=\"email\"\n />\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'authSendResetLink' | t }}\n </button>\n </form>\n </bs-form>\n }\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'authBackToLogin' | t }}</a>\n </div>\n </div>\n </bs-card>\n</div>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["rounded"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["noPadding"] }, { kind: "component", type: BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
897
449
|
}
|
|
898
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
450
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkForgotPasswordComponent, decorators: [{
|
|
899
451
|
type: Component,
|
|
900
|
-
args: [{
|
|
901
|
-
selector: 'spark-forgot-password',
|
|
902
|
-
standalone: true,
|
|
903
|
-
imports: [ReactiveFormsModule, RouterLink, BsFormModule, TranslateKeyPipe],
|
|
904
|
-
template: `
|
|
905
|
-
<div class="d-flex justify-content-center">
|
|
906
|
-
<div class="card" style="width: 100%; max-width: 400px;">
|
|
907
|
-
<div class="card-body">
|
|
908
|
-
<h3 class="card-title text-center mb-4">{{ 'authForgotPasswordTitle' | t }}</h3>
|
|
909
|
-
|
|
910
|
-
@if (successMessage()) {
|
|
911
|
-
<div class="alert alert-success" role="alert">{{ successMessage() }}</div>
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
@if (errorMessage()) {
|
|
915
|
-
<div class="alert alert-danger" role="alert">{{ errorMessage() }}</div>
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
@if (!successMessage()) {
|
|
919
|
-
<p class="text-muted mb-3">
|
|
920
|
-
{{ 'authForgotPasswordDescription' | t }}
|
|
921
|
-
</p>
|
|
922
|
-
|
|
923
|
-
<bs-form>
|
|
924
|
-
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
925
|
-
<div class="mb-3">
|
|
926
|
-
<label for="email" class="form-label">{{ 'authEmail' | t }}</label>
|
|
927
|
-
<input
|
|
928
|
-
type="email"
|
|
929
|
-
id="email"
|
|
930
|
-
formControlName="email"
|
|
931
|
-
autocomplete="email"
|
|
932
|
-
/>
|
|
933
|
-
</div>
|
|
934
|
-
|
|
935
|
-
<button
|
|
936
|
-
type="submit"
|
|
937
|
-
class="btn btn-primary w-100"
|
|
938
|
-
[disabled]="loading()"
|
|
939
|
-
>
|
|
940
|
-
@if (loading()) {
|
|
941
|
-
<span class="spinner-border spinner-border-sm me-1" role="status"></span>
|
|
942
|
-
}
|
|
943
|
-
{{ 'authSendResetLink' | t }}
|
|
944
|
-
</button>
|
|
945
|
-
</form>
|
|
946
|
-
</bs-form>
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
<div class="mt-3 text-center">
|
|
950
|
-
<a [routerLink]="routePaths.login">{{ 'authBackToLogin' | t }}</a>
|
|
951
|
-
</div>
|
|
952
|
-
</div>
|
|
953
|
-
</div>
|
|
954
|
-
</div>
|
|
955
|
-
`,
|
|
956
|
-
}]
|
|
452
|
+
args: [{ selector: 'spark-forgot-password', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsSpinnerComponent, TranslateKeyPipe], template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'authForgotPasswordTitle' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (successMessage()) {\n <bs-alert [type]=\"colors.success\" class=\"mb-3\">{{ successMessage() }}</bs-alert>\n }\n\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n @if (!successMessage()) {\n <p class=\"text-muted mb-3\">\n {{ 'authForgotPasswordDescription' | t }}\n </p>\n\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"email\" class=\"form-label\">{{ 'authEmail' | t }}</label>\n <input\n type=\"email\"\n id=\"email\"\n formControlName=\"email\"\n autocomplete=\"email\"\n />\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'authSendResetLink' | t }}\n </button>\n </form>\n </bs-form>\n }\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'authBackToLogin' | t }}</a>\n </div>\n </div>\n </bs-card>\n</div>\n" }]
|
|
957
453
|
}] });
|
|
958
454
|
|
|
959
455
|
var sparkForgotPassword_component = /*#__PURE__*/Object.freeze({
|
|
@@ -977,6 +473,7 @@ class SparkResetPasswordComponent {
|
|
|
977
473
|
route = inject(ActivatedRoute);
|
|
978
474
|
translation = inject(SparkAuthTranslationService);
|
|
979
475
|
routePaths = inject(SPARK_AUTH_ROUTE_PATHS);
|
|
476
|
+
colors = Color;
|
|
980
477
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
981
478
|
errorMessage = signal('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
|
|
982
479
|
successMessage = signal('', ...(ngDevMode ? [{ debugName: "successMessage" }] : []));
|
|
@@ -993,7 +490,7 @@ class SparkResetPasswordComponent {
|
|
|
993
490
|
this.errorMessage.set(this.translation.t('authInvalidResetLink'));
|
|
994
491
|
}
|
|
995
492
|
}
|
|
996
|
-
onSubmit() {
|
|
493
|
+
async onSubmit() {
|
|
997
494
|
if (this.form.invalid) {
|
|
998
495
|
this.form.markAllAsTouched();
|
|
999
496
|
return;
|
|
@@ -1006,163 +503,28 @@ class SparkResetPasswordComponent {
|
|
|
1006
503
|
this.errorMessage.set('');
|
|
1007
504
|
this.successMessage.set('');
|
|
1008
505
|
const { newPassword } = this.form.value;
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
this.
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
}
|
|
506
|
+
try {
|
|
507
|
+
await this.authService.resetPassword(this.email, this.code, newPassword);
|
|
508
|
+
this.successMessage.set(this.translation.t('authResetSuccess'));
|
|
509
|
+
}
|
|
510
|
+
catch (err) {
|
|
511
|
+
if (err instanceof HttpErrorResponse && err.error?.detail) {
|
|
512
|
+
this.errorMessage.set(err.error.detail);
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
515
|
+
this.errorMessage.set(this.translation.t('authResetFailed'));
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
finally {
|
|
519
|
+
this.loading.set(false);
|
|
520
|
+
}
|
|
1024
521
|
}
|
|
1025
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
1026
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
1027
|
-
<div class="d-flex justify-content-center">
|
|
1028
|
-
<div class="card" style="width: 100%; max-width: 400px;">
|
|
1029
|
-
<div class="card-body">
|
|
1030
|
-
<h3 class="card-title text-center mb-4">{{ 'authResetPassword' | t }}</h3>
|
|
1031
|
-
|
|
1032
|
-
@if (successMessage()) {
|
|
1033
|
-
<div class="alert alert-success" role="alert">
|
|
1034
|
-
{{ successMessage() }}
|
|
1035
|
-
<div class="mt-2">
|
|
1036
|
-
<a [routerLink]="routePaths.login">{{ 'authGoToLogin' | t }}</a>
|
|
1037
|
-
</div>
|
|
1038
|
-
</div>
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
@if (errorMessage()) {
|
|
1042
|
-
<div class="alert alert-danger" role="alert">{{ errorMessage() }}</div>
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
@if (!successMessage()) {
|
|
1046
|
-
<bs-form>
|
|
1047
|
-
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
1048
|
-
<div class="mb-3">
|
|
1049
|
-
<label for="newPassword" class="form-label">{{ 'authNewPassword' | t }}</label>
|
|
1050
|
-
<input
|
|
1051
|
-
type="password"
|
|
1052
|
-
id="newPassword"
|
|
1053
|
-
formControlName="newPassword"
|
|
1054
|
-
autocomplete="new-password"
|
|
1055
|
-
/>
|
|
1056
|
-
</div>
|
|
1057
|
-
|
|
1058
|
-
<div class="mb-3">
|
|
1059
|
-
<label for="confirmPassword" class="form-label">{{ 'authConfirmPassword' | t }}</label>
|
|
1060
|
-
<input
|
|
1061
|
-
type="password"
|
|
1062
|
-
id="confirmPassword"
|
|
1063
|
-
formControlName="confirmPassword"
|
|
1064
|
-
autocomplete="new-password"
|
|
1065
|
-
/>
|
|
1066
|
-
@if (form.touched && form.hasError('passwordMismatch')) {
|
|
1067
|
-
<div class="text-danger mt-1">{{ 'authPasswordMismatch' | t }}</div>
|
|
1068
|
-
}
|
|
1069
|
-
</div>
|
|
1070
|
-
|
|
1071
|
-
<button
|
|
1072
|
-
type="submit"
|
|
1073
|
-
class="btn btn-primary w-100"
|
|
1074
|
-
[disabled]="loading()"
|
|
1075
|
-
>
|
|
1076
|
-
@if (loading()) {
|
|
1077
|
-
<span class="spinner-border spinner-border-sm me-1" role="status"></span>
|
|
1078
|
-
}
|
|
1079
|
-
{{ 'authResetPassword' | t }}
|
|
1080
|
-
</button>
|
|
1081
|
-
</form>
|
|
1082
|
-
</bs-form>
|
|
1083
|
-
|
|
1084
|
-
<div class="mt-3 text-center">
|
|
1085
|
-
<a [routerLink]="routePaths.login">{{ 'authBackToLogin' | t }}</a>
|
|
1086
|
-
</div>
|
|
1087
|
-
}
|
|
1088
|
-
</div>
|
|
1089
|
-
</div>
|
|
1090
|
-
</div>
|
|
1091
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: BsFormModule }, { kind: "component", type: i2.BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: i2.BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }] });
|
|
522
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkResetPasswordComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
523
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SparkResetPasswordComponent, isStandalone: true, selector: "spark-reset-password", ngImport: i0, template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'authResetPassword' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (successMessage()) {\n <bs-alert [type]=\"colors.success\" class=\"mb-3\">\n {{ successMessage() }}\n <div class=\"mt-2\">\n <a [routerLink]=\"routePaths.login\">{{ 'authGoToLogin' | t }}</a>\n </div>\n </bs-alert>\n }\n\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n @if (!successMessage()) {\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"newPassword\" class=\"form-label\">{{ 'authNewPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"newPassword\"\n formControlName=\"newPassword\"\n autocomplete=\"new-password\"\n />\n </div>\n\n <div class=\"mb-3\">\n <label for=\"confirmPassword\" class=\"form-label\">{{ 'authConfirmPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"confirmPassword\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\"\n />\n @if (form.touched && form.hasError('passwordMismatch')) {\n <div class=\"text-danger mt-1\">{{ 'authPasswordMismatch' | t }}</div>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'authResetPassword' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'authBackToLogin' | t }}</a>\n </div>\n }\n </div>\n </bs-card>\n</div>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["rounded"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["noPadding"] }, { kind: "component", type: BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1092
524
|
}
|
|
1093
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
525
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkResetPasswordComponent, decorators: [{
|
|
1094
526
|
type: Component,
|
|
1095
|
-
args: [{
|
|
1096
|
-
selector: 'spark-reset-password',
|
|
1097
|
-
standalone: true,
|
|
1098
|
-
imports: [ReactiveFormsModule, RouterLink, BsFormModule, TranslateKeyPipe],
|
|
1099
|
-
template: `
|
|
1100
|
-
<div class="d-flex justify-content-center">
|
|
1101
|
-
<div class="card" style="width: 100%; max-width: 400px;">
|
|
1102
|
-
<div class="card-body">
|
|
1103
|
-
<h3 class="card-title text-center mb-4">{{ 'authResetPassword' | t }}</h3>
|
|
1104
|
-
|
|
1105
|
-
@if (successMessage()) {
|
|
1106
|
-
<div class="alert alert-success" role="alert">
|
|
1107
|
-
{{ successMessage() }}
|
|
1108
|
-
<div class="mt-2">
|
|
1109
|
-
<a [routerLink]="routePaths.login">{{ 'authGoToLogin' | t }}</a>
|
|
1110
|
-
</div>
|
|
1111
|
-
</div>
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
|
-
@if (errorMessage()) {
|
|
1115
|
-
<div class="alert alert-danger" role="alert">{{ errorMessage() }}</div>
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
@if (!successMessage()) {
|
|
1119
|
-
<bs-form>
|
|
1120
|
-
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
1121
|
-
<div class="mb-3">
|
|
1122
|
-
<label for="newPassword" class="form-label">{{ 'authNewPassword' | t }}</label>
|
|
1123
|
-
<input
|
|
1124
|
-
type="password"
|
|
1125
|
-
id="newPassword"
|
|
1126
|
-
formControlName="newPassword"
|
|
1127
|
-
autocomplete="new-password"
|
|
1128
|
-
/>
|
|
1129
|
-
</div>
|
|
1130
|
-
|
|
1131
|
-
<div class="mb-3">
|
|
1132
|
-
<label for="confirmPassword" class="form-label">{{ 'authConfirmPassword' | t }}</label>
|
|
1133
|
-
<input
|
|
1134
|
-
type="password"
|
|
1135
|
-
id="confirmPassword"
|
|
1136
|
-
formControlName="confirmPassword"
|
|
1137
|
-
autocomplete="new-password"
|
|
1138
|
-
/>
|
|
1139
|
-
@if (form.touched && form.hasError('passwordMismatch')) {
|
|
1140
|
-
<div class="text-danger mt-1">{{ 'authPasswordMismatch' | t }}</div>
|
|
1141
|
-
}
|
|
1142
|
-
</div>
|
|
1143
|
-
|
|
1144
|
-
<button
|
|
1145
|
-
type="submit"
|
|
1146
|
-
class="btn btn-primary w-100"
|
|
1147
|
-
[disabled]="loading()"
|
|
1148
|
-
>
|
|
1149
|
-
@if (loading()) {
|
|
1150
|
-
<span class="spinner-border spinner-border-sm me-1" role="status"></span>
|
|
1151
|
-
}
|
|
1152
|
-
{{ 'authResetPassword' | t }}
|
|
1153
|
-
</button>
|
|
1154
|
-
</form>
|
|
1155
|
-
</bs-form>
|
|
1156
|
-
|
|
1157
|
-
<div class="mt-3 text-center">
|
|
1158
|
-
<a [routerLink]="routePaths.login">{{ 'authBackToLogin' | t }}</a>
|
|
1159
|
-
</div>
|
|
1160
|
-
}
|
|
1161
|
-
</div>
|
|
1162
|
-
</div>
|
|
1163
|
-
</div>
|
|
1164
|
-
`,
|
|
1165
|
-
}]
|
|
527
|
+
args: [{ selector: 'spark-reset-password', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsSpinnerComponent, TranslateKeyPipe], template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'authResetPassword' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (successMessage()) {\n <bs-alert [type]=\"colors.success\" class=\"mb-3\">\n {{ successMessage() }}\n <div class=\"mt-2\">\n <a [routerLink]=\"routePaths.login\">{{ 'authGoToLogin' | t }}</a>\n </div>\n </bs-alert>\n }\n\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n @if (!successMessage()) {\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"newPassword\" class=\"form-label\">{{ 'authNewPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"newPassword\"\n formControlName=\"newPassword\"\n autocomplete=\"new-password\"\n />\n </div>\n\n <div class=\"mb-3\">\n <label for=\"confirmPassword\" class=\"form-label\">{{ 'authConfirmPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"confirmPassword\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\"\n />\n @if (form.touched && form.hasError('passwordMismatch')) {\n <div class=\"text-danger mt-1\">{{ 'authPasswordMismatch' | t }}</div>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'authResetPassword' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'authBackToLogin' | t }}</a>\n </div>\n }\n </div>\n </bs-card>\n</div>\n" }]
|
|
1166
528
|
}] });
|
|
1167
529
|
|
|
1168
530
|
var sparkResetPassword_component = /*#__PURE__*/Object.freeze({
|