@mintplayer/ng-spark-auth 22.2.1 → 22.6.0
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.
- package/fesm2022/mintplayer-ng-spark-auth-auth-bar.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-core.mjs +6 -6
- package/fesm2022/mintplayer-ng-spark-auth-forgot-password.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-login.mjs +4 -4
- package/fesm2022/mintplayer-ng-spark-auth-login.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-auth-models.mjs +2 -1
- package/fesm2022/mintplayer-ng-spark-auth-models.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-auth-pipes.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-register.mjs +9 -5
- package/fesm2022/mintplayer-ng-spark-auth-register.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-auth-reset-password.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-routes.mjs +122 -34
- package/fesm2022/mintplayer-ng-spark-auth-routes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-auth-sign-in.mjs +82 -17
- package/fesm2022/mintplayer-ng-spark-auth-sign-in.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-auth-two-factor.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth.mjs +11 -3
- package/fesm2022/mintplayer-ng-spark-auth.mjs.map +1 -1
- package/package.json +2 -1
- package/types/mintplayer-ng-spark-auth-forgot-password.d.ts +1 -1
- package/types/mintplayer-ng-spark-auth-login.d.ts +1 -1
- package/types/mintplayer-ng-spark-auth-models.d.ts +32 -27
- package/types/mintplayer-ng-spark-auth-register.d.ts +1 -1
- package/types/mintplayer-ng-spark-auth-reset-password.d.ts +1 -1
- package/types/mintplayer-ng-spark-auth-routes.d.ts +82 -12
- package/types/mintplayer-ng-spark-auth-sign-in.d.ts +58 -7
- package/types/mintplayer-ng-spark-auth-two-factor.d.ts +1 -1
|
@@ -22,10 +22,10 @@ class SparkAuthBarComponent {
|
|
|
22
22
|
this.router.navigateByUrl('/');
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
26
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.
|
|
25
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkAuthBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
26
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", 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()\">{{ 'auth.logout' | t }}</button>\n} @else {\n <a class=\"btn btn-outline-light btn-sm\" [routerLink]=\"signInUrl\">{{ 'auth.login' | t }}</a>\n}\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
27
27
|
}
|
|
28
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
28
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkAuthBarComponent, decorators: [{
|
|
29
29
|
type: Component,
|
|
30
30
|
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()\">{{ 'auth.logout' | t }}</button>\n} @else {\n <a class=\"btn btn-outline-light btn-sm\" [routerLink]=\"signInUrl\">{{ 'auth.login' | t }}</a>\n}\n" }]
|
|
31
31
|
}] });
|
|
@@ -131,10 +131,10 @@ class SparkAuthService {
|
|
|
131
131
|
newPassword,
|
|
132
132
|
}));
|
|
133
133
|
}
|
|
134
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
135
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.
|
|
134
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkAuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
135
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkAuthService, providedIn: 'root' });
|
|
136
136
|
}
|
|
137
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
137
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkAuthService, decorators: [{
|
|
138
138
|
type: Injectable,
|
|
139
139
|
args: [{ providedIn: 'root' }]
|
|
140
140
|
}], ctorParameters: () => [] });
|
|
@@ -164,10 +164,10 @@ class SparkAuthTranslationService {
|
|
|
164
164
|
const lang = currentLanguage();
|
|
165
165
|
return ts[lang] ?? ts['en'] ?? Object.values(ts)[0] ?? key;
|
|
166
166
|
}
|
|
167
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
168
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.
|
|
167
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkAuthTranslationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
168
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkAuthTranslationService, providedIn: 'root' });
|
|
169
169
|
}
|
|
170
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
170
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkAuthTranslationService, decorators: [{
|
|
171
171
|
type: Injectable,
|
|
172
172
|
args: [{ providedIn: 'root' }]
|
|
173
173
|
}], ctorParameters: () => [] });
|
|
@@ -45,10 +45,10 @@ class SparkForgotPasswordComponent {
|
|
|
45
45
|
this.successMessage.set(this.translation.t('auth.forgotPasswordSuccess'));
|
|
46
46
|
this.loading.set(false);
|
|
47
47
|
}
|
|
48
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
49
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.
|
|
48
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkForgotPasswordComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
49
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", 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\">{{ 'auth.forgotPasswordTitle' | 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 {{ 'auth.forgotPasswordDescription' | 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\">{{ 'auth.email' | 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 {{ 'auth.sendResetLink' | t }}\n </button>\n </form>\n </bs-form>\n }\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'auth.backToLogin' | 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]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[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", "browserUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "announce", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["color", "outline"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["color", "navStyle"] }, { 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 });
|
|
50
50
|
}
|
|
51
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
51
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkForgotPasswordComponent, decorators: [{
|
|
52
52
|
type: Component,
|
|
53
53
|
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\">{{ 'auth.forgotPasswordTitle' | 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 {{ 'auth.forgotPasswordDescription' | 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\">{{ 'auth.email' | 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 {{ 'auth.sendResetLink' | t }}\n </button>\n </form>\n </bs-form>\n }\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'auth.backToLogin' | t }}</a>\n </div>\n </div>\n </bs-card>\n</div>\n" }]
|
|
54
54
|
}] });
|
|
@@ -63,12 +63,12 @@ class SparkLoginComponent {
|
|
|
63
63
|
this.loading.set(false);
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
67
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.
|
|
66
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkLoginComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
67
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", 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\">{{ 'auth.login' | 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\">{{ 'auth.email' | 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\">{{ 'auth.password' | 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-checkbox [type]=\"'checkbox'\" formControlName=\"rememberMe\" [name]=\"'rememberMe'\">{{ 'auth.rememberMe' | t }}</bs-checkbox>\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 {{ 'auth.login' | t }}\n </button>\n </form>\n </bs-form>\n\n <!-- Registration is a separate opt-in feature (withRegistration()), so it may not be mounted\n even though this page is. A [routerLink] bound to undefined navigates to the current\n route instead of failing, which reads as a dead link. -->\n @if (routePaths.register) {\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.register\">{{ 'auth.createAccount' | t }}</a>\n </div>\n }\n <div class=\"mt-2 text-center\">\n <a [routerLink]=\"routePaths.forgotPassword\">{{ 'auth.forgotPassword' | 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]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[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", "browserUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "announce", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["color", "outline"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["color", "navStyle"] }, { 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: BsCheckboxComponent, selector: "bs-checkbox", inputs: ["type", "isToggled", "indeterminate", "name", "value", "group"], outputs: ["isToggledChange", "indeterminateChange"] }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
68
68
|
}
|
|
69
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
69
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkLoginComponent, decorators: [{
|
|
70
70
|
type: Component,
|
|
71
|
-
args: [{ selector: 'spark-login', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsCheckboxComponent, 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\">{{ 'auth.login' | 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\">{{ 'auth.email' | 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\">{{ 'auth.password' | 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-checkbox [type]=\"'checkbox'\" formControlName=\"rememberMe\" [name]=\"'rememberMe'\">{{ 'auth.rememberMe' | t }}</bs-checkbox>\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 {{ 'auth.login' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n
|
|
71
|
+
args: [{ selector: 'spark-login', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsCheckboxComponent, 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\">{{ 'auth.login' | 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\">{{ 'auth.email' | 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\">{{ 'auth.password' | 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-checkbox [type]=\"'checkbox'\" formControlName=\"rememberMe\" [name]=\"'rememberMe'\">{{ 'auth.rememberMe' | t }}</bs-checkbox>\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 {{ 'auth.login' | t }}\n </button>\n </form>\n </bs-form>\n\n <!-- Registration is a separate opt-in feature (withRegistration()), so it may not be mounted\n even though this page is. A [routerLink] bound to undefined navigates to the current\n route instead of failing, which reads as a dead link. -->\n @if (routePaths.register) {\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.register\">{{ 'auth.createAccount' | t }}</a>\n </div>\n }\n <div class=\"mt-2 text-center\">\n <a [routerLink]=\"routePaths.forgotPassword\">{{ 'auth.forgotPassword' | t }}</a>\n </div>\n </div>\n </bs-card>\n</div>\n" }]
|
|
72
72
|
}] });
|
|
73
73
|
|
|
74
74
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mintplayer-ng-spark-auth-login.mjs","sources":["../../login/src/spark-login.component.ts","../../login/src/spark-login.component.html","../../login/mintplayer-ng-spark-auth-login.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';\nimport { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';\nimport { RouterLink, ActivatedRoute, Router } from '@angular/router';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';\nimport { BsCardComponent, BsCardHeaderComponent } from '@mintplayer/ng-bootstrap/card';\nimport { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';\nimport { BsCheckboxComponent } from '@mintplayer/ng-bootstrap/checkbox';\nimport { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';\nimport { SPARK_AUTH_CONFIG, SPARK_AUTH_ROUTE_PATHS, sanitizeReturnUrl } from '@mintplayer/ng-spark-auth/models';\nimport { SparkAuthService, SparkAuthTranslationService } from '@mintplayer/ng-spark-auth/core';\nimport { TranslateKeyPipe } from '@mintplayer/ng-spark-auth/pipes';\n\n@Component({\n selector: 'spark-login',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsCheckboxComponent, BsSpinnerComponent, TranslateKeyPipe],\n templateUrl: './spark-login.component.html',\n})\nexport class SparkLoginComponent {\n private readonly fb = inject(FormBuilder);\n private readonly authService = inject(SparkAuthService);\n private readonly router = inject(Router);\n private readonly route = inject(ActivatedRoute);\n private readonly config = inject(SPARK_AUTH_CONFIG);\n private readonly translation = inject(SparkAuthTranslationService);\n readonly routePaths = inject(SPARK_AUTH_ROUTE_PATHS);\n\n colors = Color;\n readonly loading = signal(false);\n readonly errorMessage = signal('');\n\n readonly form = this.fb.group({\n email: ['', Validators.required],\n password: ['', Validators.required],\n rememberMe: [false],\n });\n\n async onSubmit(): Promise<void> {\n if (this.form.invalid) return;\n\n this.loading.set(true);\n this.errorMessage.set('');\n\n const { email, password } = this.form.value;\n\n try {\n await this.authService.login(email!, password!);\n // R2-H9: validate returnUrl against the local-path rule. navigateByUrl\n // accepts some external shapes (protocol-relative '//attacker'); reject\n // and fall back to the default to close the open-redirect.\n const returnUrl = sanitizeReturnUrl(\n this.route.snapshot.queryParamMap.get('returnUrl'),\n this.config.defaultRedirectUrl);\n this.router.navigateByUrl(returnUrl);\n } catch (err: any) {\n if (err instanceof HttpErrorResponse && err.status === 401 && err.error?.detail === 'RequiresTwoFactor') {\n // Forward the same sanitized returnUrl to the 2FA step so the user\n // lands on the intended in-app page after completing the challenge.\n const returnUrl = sanitizeReturnUrl(\n this.route.snapshot.queryParamMap.get('returnUrl'),\n this.config.defaultRedirectUrl);\n this.router.navigate([this.routePaths.twoFactor], {\n queryParams: { returnUrl },\n });\n } else {\n this.errorMessage.set(this.translation.t('auth.invalidCredentials'));\n }\n } finally {\n this.loading.set(false);\n }\n }\n}\n\nexport default SparkLoginComponent;\n","<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\">{{ 'auth.login' | 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\">{{ 'auth.email' | 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\">{{ 'auth.password' | 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-checkbox [type]=\"'checkbox'\" formControlName=\"rememberMe\" [name]=\"'rememberMe'\">{{ 'auth.rememberMe' | t }}</bs-checkbox>\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 {{ 'auth.login' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n
|
|
1
|
+
{"version":3,"file":"mintplayer-ng-spark-auth-login.mjs","sources":["../../login/src/spark-login.component.ts","../../login/src/spark-login.component.html","../../login/mintplayer-ng-spark-auth-login.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';\nimport { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';\nimport { RouterLink, ActivatedRoute, Router } from '@angular/router';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';\nimport { BsCardComponent, BsCardHeaderComponent } from '@mintplayer/ng-bootstrap/card';\nimport { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';\nimport { BsCheckboxComponent } from '@mintplayer/ng-bootstrap/checkbox';\nimport { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';\nimport { SPARK_AUTH_CONFIG, SPARK_AUTH_ROUTE_PATHS, sanitizeReturnUrl } from '@mintplayer/ng-spark-auth/models';\nimport { SparkAuthService, SparkAuthTranslationService } from '@mintplayer/ng-spark-auth/core';\nimport { TranslateKeyPipe } from '@mintplayer/ng-spark-auth/pipes';\n\n@Component({\n selector: 'spark-login',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsCheckboxComponent, BsSpinnerComponent, TranslateKeyPipe],\n templateUrl: './spark-login.component.html',\n})\nexport class SparkLoginComponent {\n private readonly fb = inject(FormBuilder);\n private readonly authService = inject(SparkAuthService);\n private readonly router = inject(Router);\n private readonly route = inject(ActivatedRoute);\n private readonly config = inject(SPARK_AUTH_CONFIG);\n private readonly translation = inject(SparkAuthTranslationService);\n readonly routePaths = inject(SPARK_AUTH_ROUTE_PATHS);\n\n colors = Color;\n readonly loading = signal(false);\n readonly errorMessage = signal('');\n\n readonly form = this.fb.group({\n email: ['', Validators.required],\n password: ['', Validators.required],\n rememberMe: [false],\n });\n\n async onSubmit(): Promise<void> {\n if (this.form.invalid) return;\n\n this.loading.set(true);\n this.errorMessage.set('');\n\n const { email, password } = this.form.value;\n\n try {\n await this.authService.login(email!, password!);\n // R2-H9: validate returnUrl against the local-path rule. navigateByUrl\n // accepts some external shapes (protocol-relative '//attacker'); reject\n // and fall back to the default to close the open-redirect.\n const returnUrl = sanitizeReturnUrl(\n this.route.snapshot.queryParamMap.get('returnUrl'),\n this.config.defaultRedirectUrl);\n this.router.navigateByUrl(returnUrl);\n } catch (err: any) {\n if (err instanceof HttpErrorResponse && err.status === 401 && err.error?.detail === 'RequiresTwoFactor') {\n // Forward the same sanitized returnUrl to the 2FA step so the user\n // lands on the intended in-app page after completing the challenge.\n const returnUrl = sanitizeReturnUrl(\n this.route.snapshot.queryParamMap.get('returnUrl'),\n this.config.defaultRedirectUrl);\n this.router.navigate([this.routePaths.twoFactor], {\n queryParams: { returnUrl },\n });\n } else {\n this.errorMessage.set(this.translation.t('auth.invalidCredentials'));\n }\n } finally {\n this.loading.set(false);\n }\n }\n}\n\nexport default SparkLoginComponent;\n","<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\">{{ 'auth.login' | 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\">{{ 'auth.email' | 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\">{{ 'auth.password' | 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-checkbox [type]=\"'checkbox'\" formControlName=\"rememberMe\" [name]=\"'rememberMe'\">{{ 'auth.rememberMe' | t }}</bs-checkbox>\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 {{ 'auth.login' | t }}\n </button>\n </form>\n </bs-form>\n\n <!-- Registration is a separate opt-in feature (withRegistration()), so it may not be mounted\n even though this page is. A [routerLink] bound to undefined navigates to the current\n route instead of failing, which reads as a dead link. -->\n @if (routePaths.register) {\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.register\">{{ 'auth.createAccount' | t }}</a>\n </div>\n }\n <div class=\"mt-2 text-center\">\n <a [routerLink]=\"routePaths.forgotPassword\">{{ 'auth.forgotPassword' | t }}</a>\n </div>\n </div>\n </bs-card>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ const defaultSparkAuthConfig = {
|
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
const SPARK_AUTH_ROUTE_PATHS = new InjectionToken('SPARK_AUTH_ROUTE_PATHS');
|
|
11
|
+
const SPARK_EXTERNAL_PROVIDERS = new InjectionToken('SPARK_EXTERNAL_PROVIDERS');
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Shared validator for `returnUrl` query parameters consumed by the auth
|
|
@@ -82,5 +83,5 @@ function matches(routes, target, prefix = '') {
|
|
|
82
83
|
* Generated bundle index. Do not edit.
|
|
83
84
|
*/
|
|
84
85
|
|
|
85
|
-
export { SPARK_AUTH_CONFIG, SPARK_AUTH_ROUTE_PATHS, SPARK_EXTERNAL_LOGIN_MESSAGE_TYPE, defaultSparkAuthConfig, isSafeReturnUrl, resolveSignInUrl, sanitizeReturnUrl };
|
|
86
|
+
export { SPARK_AUTH_CONFIG, SPARK_AUTH_ROUTE_PATHS, SPARK_EXTERNAL_LOGIN_MESSAGE_TYPE, SPARK_EXTERNAL_PROVIDERS, defaultSparkAuthConfig, isSafeReturnUrl, resolveSignInUrl, sanitizeReturnUrl };
|
|
86
87
|
//# sourceMappingURL=mintplayer-ng-spark-auth-models.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mintplayer-ng-spark-auth-models.mjs","sources":["../../models/src/auth-config.ts","../../models/src/auth-route-config.ts","../../models/src/return-url.ts","../../models/src/external-login.ts","../../models/src/sign-in-redirect.ts","../../models/mintplayer-ng-spark-auth-models.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\nexport interface SparkAuthConfig {\n apiBasePath: string;\n defaultRedirectUrl: string;\n loginUrl: string;\n}\n\nexport const SPARK_AUTH_CONFIG = new InjectionToken<SparkAuthConfig>('SPARK_AUTH_CONFIG');\n\nexport const defaultSparkAuthConfig: SparkAuthConfig = {\n apiBasePath: '/spark/auth',\n defaultRedirectUrl: '/',\n loginUrl: '/login',\n};\n","import { InjectionToken, Type } from '@angular/core';\n\nexport type SparkAuthRouteEntry = string | { path: string; component?: Type<unknown> };\n\n
|
|
1
|
+
{"version":3,"file":"mintplayer-ng-spark-auth-models.mjs","sources":["../../models/src/auth-config.ts","../../models/src/auth-route-config.ts","../../models/src/return-url.ts","../../models/src/external-login.ts","../../models/src/sign-in-redirect.ts","../../models/mintplayer-ng-spark-auth-models.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\nexport interface SparkAuthConfig {\n apiBasePath: string;\n defaultRedirectUrl: string;\n loginUrl: string;\n}\n\nexport const SPARK_AUTH_CONFIG = new InjectionToken<SparkAuthConfig>('SPARK_AUTH_CONFIG');\n\nexport const defaultSparkAuthConfig: SparkAuthConfig = {\n apiBasePath: '/spark/auth',\n defaultRedirectUrl: '/',\n loginUrl: '/login',\n};\n","import { InjectionToken, Type } from '@angular/core';\n\nexport type SparkAuthRouteEntry = string | { path: string; component?: Type<unknown> };\n\n/** The routable authentication pages. */\nexport interface SparkAuthRouteEntries {\n /** The provider-button landing page, mounted by `withExternalLogin()`. */\n signIn?: SparkAuthRouteEntry;\n login?: SparkAuthRouteEntry;\n twoFactor?: SparkAuthRouteEntry;\n register?: SparkAuthRouteEntry;\n forgotPassword?: SparkAuthRouteEntry;\n resetPassword?: SparkAuthRouteEntry;\n}\n\n/**\n * The paths of the pages that were actually mounted.\n *\n * Partial, and that is the change: pages are opted into individually now, so a template cannot\n * assume its siblings exist. `login` links to `register` only when registration was opted into, and\n * the sign-in landing page links to `login` only when local login was. A `[routerLink]` bound to\n * `undefined` silently navigates to the current route, so every cross-feature link is guarded.\n */\nexport type SparkAuthRoutePaths = Partial<Record<keyof SparkAuthRouteEntries, string>>;\n\nexport const SPARK_AUTH_ROUTE_PATHS = new InjectionToken<SparkAuthRoutePaths>('SPARK_AUTH_ROUTE_PATHS');\n\n/**\n * Presentation for one external provider's button — an icon, a label, an ordering.\n *\n * **It decorates; it does not declare.** The server stays authoritative over which providers exist\n * (`GET /spark/auth/capabilities`), because letting the client declare them would reintroduce exactly\n * the string-literal mismatch that endpoint exists to prevent. A scheme the server reports with no\n * matching declaration falls back to the default button, so adding a provider server-side never\n * yields a blank page; a declaration matching no reported scheme is simply unused.\n */\nexport interface SparkExternalProviderPresentation {\n /** The ASP.NET Core authentication scheme, as the server reports it. Matched case-insensitively. */\n scheme: string;\n /** Overrides the server's display name. */\n displayName?: string;\n /** A CSS class for an icon element rendered before the label. */\n iconClass?: string;\n /** Lower sorts first. Providers with no declared order keep the server's order, after declared ones. */\n order?: number;\n}\n\nexport const SPARK_EXTERNAL_PROVIDERS = new InjectionToken<SparkExternalProviderPresentation[]>(\n 'SPARK_EXTERNAL_PROVIDERS',\n);\n","/**\n * Shared validator for `returnUrl` query parameters consumed by the auth\n * components and interceptor. The framework-side equivalent in\n * `SparkAuthenticationExtensions.SanitizeReturnUrl` enforces the same rule;\n * keep them in sync.\n *\n * Accepts only local in-app paths:\n * - Must start with a single `/`.\n * - Must not start with `//` or `/\\` (protocol-relative navigation that some\n * browsers and routers interpret as an external host).\n * - Must not contain CR/LF (defensive — the value flows into Router state and\n * eventually back into a `router.navigateByUrl` call).\n *\n * Returns the supplied default for anything else, never throws. Per R2-H9.\n */\nexport function isSafeReturnUrl(value: string | null | undefined): boolean {\n if (!value) return false;\n if (/[\\r\\n]/.test(value)) return false;\n if (!value.startsWith('/')) return false;\n if (value.length >= 2 && (value[1] === '/' || value[1] === '\\\\')) return false;\n return true;\n}\n\nexport function sanitizeReturnUrl(\n value: string | null | undefined,\n defaultUrl: string,\n): string {\n return isSafeReturnUrl(value) ? (value as string) : defaultUrl;\n}\n","/** How the user is sent to the external provider, and how the result comes back. */\nexport type SparkExternalLoginMode = 'popup' | 'redirect';\n\nexport interface SparkExternalLoginOptions {\n /** Where to land after a successful sign-in. Server-side sanitized to an in-app path. */\n returnUrl?: string;\n /** Defaults to `'popup'`. */\n mode?: SparkExternalLoginMode;\n}\n\n/**\n * Why an external login did not sign anyone in. The three `no_login_info` /\n * `email_not_verified` / `account_creation_failed` codes come from the server; the two\n * `popup_*` codes are raised here, because the browser is the only place that can observe\n * them. Deliberately coarse — never enough to tell \"no such account\" from anything else.\n */\nexport type SparkExternalLoginError =\n | 'no_login_info'\n | 'email_not_verified'\n | 'account_creation_failed'\n | 'popup_blocked'\n | 'popup_closed';\n\nexport interface SparkExternalLoginResult {\n success: boolean;\n error?: SparkExternalLoginError;\n}\n\n/** The message the callback page posts back to the window that opened it. */\nexport interface SparkExternalLoginMessage {\n type: 'spark:external-login';\n success: boolean;\n error?: SparkExternalLoginError;\n}\n\nexport const SPARK_EXTERNAL_LOGIN_MESSAGE_TYPE = 'spark:external-login';\n","import { isDevMode } from '@angular/core';\nimport { Route, Router } from '@angular/router';\nimport { SparkAuthConfig } from './auth-config';\n\n/**\n * Where to send someone who is not signed in.\n *\n * `loginUrl` is the single source of truth for this, and the only thing the guard, the interceptor\n * and the auth bar should consult — an application that turns off local credentials points it at\n * its own sign-in landing route.\n *\n * The reason this is a function rather than a property read is the failure mode it closes: nothing\n * connects `loginUrl` to the routes that actually exist, so pointing it at a route that was never\n * registered produces a redirect into a blank page with no type error, no build failure and no\n * runtime error. In development that now warns, once, naming the value and the fix.\n */\nexport function resolveSignInUrl(config: SparkAuthConfig, router: Router): string {\n if (isDevMode() && !warned && !routeExists(router, config.loginUrl)) {\n warned = true;\n console.warn(\n `[ng-spark-auth] loginUrl is \"${config.loginUrl}\", but no route matches it, so redirecting an `\n + `unauthenticated user will land on a blank page. If this app runs with local credentials `\n + `disabled, point loginUrl at its sign-in route (for example provideSparkAuth({ loginUrl: '/sign-in' })).`,\n );\n }\n\n return config.loginUrl;\n}\n\nlet warned = false;\n\nfunction routeExists(router: Router, url: string): boolean {\n const target = url.replace(/^\\/+/, '').split('?')[0].split('#')[0];\n return matches(router.config, target);\n}\n\nfunction matches(routes: Route[], target: string, prefix = ''): boolean {\n return routes.some(route => {\n const path = [prefix, route.path ?? ''].filter(Boolean).join('/');\n if (path === target) return true;\n // A wildcard route would match anything, including a URL nobody registered — treating it as a\n // match would make this check always pass and warn about nothing.\n return route.children ? matches(route.children, target, path) : false;\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;MAQa,iBAAiB,GAAG,IAAI,cAAc,CAAkB,mBAAmB;AAEjF,MAAM,sBAAsB,GAAoB;AACrD,IAAA,WAAW,EAAE,aAAa;AAC1B,IAAA,kBAAkB,EAAE,GAAG;AACvB,IAAA,QAAQ,EAAE,QAAQ;;;MCYP,sBAAsB,GAAG,IAAI,cAAc,CAAsB,wBAAwB;MAsBzF,wBAAwB,GAAG,IAAI,cAAc,CACxD,0BAA0B;;AChD5B;;;;;;;;;;;;;;AAcG;AACG,SAAU,eAAe,CAAC,KAAgC,EAAA;AAC9D,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,OAAO,KAAK;AACxB,IAAA,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;AAAE,QAAA,OAAO,KAAK;AACtC,IAAA,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;AAAE,QAAA,OAAO,KAAK;IACxC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AAAE,QAAA,OAAO,KAAK;AAC9E,IAAA,OAAO,IAAI;AACb;AAEM,SAAU,iBAAiB,CAC/B,KAAgC,EAChC,UAAkB,EAAA;AAElB,IAAA,OAAO,eAAe,CAAC,KAAK,CAAC,GAAI,KAAgB,GAAG,UAAU;AAChE;;ACOO,MAAM,iCAAiC,GAAG;;AC/BjD;;;;;;;;;;;AAWG;AACG,SAAU,gBAAgB,CAAC,MAAuB,EAAE,MAAc,EAAA;AACtE,IAAA,IAAI,SAAS,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE;QACnE,MAAM,GAAG,IAAI;AACb,QAAA,OAAO,CAAC,IAAI,CACV,gCAAgC,MAAM,CAAC,QAAQ,CAAA,8CAAA;cAC7C,CAAA,wFAAA;AACA,cAAA,CAAA,uGAAA,CAAyG,CAC5G;IACH;IAEA,OAAO,MAAM,CAAC,QAAQ;AACxB;AAEA,IAAI,MAAM,GAAG,KAAK;AAElB,SAAS,WAAW,CAAC,MAAc,EAAE,GAAW,EAAA;IAC9C,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAClE,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;AACvC;AAEA,SAAS,OAAO,CAAC,MAAe,EAAE,MAAc,EAAE,MAAM,GAAG,EAAE,EAAA;AAC3D,IAAA,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,IAAG;QACzB,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACjE,IAAI,IAAI,KAAK,MAAM;AAAE,YAAA,OAAO,IAAI;;;QAGhC,OAAO,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,KAAK;AACvE,IAAA,CAAC,CAAC;AACJ;;AC5CA;;AAEG;;;;"}
|
|
@@ -7,10 +7,10 @@ class TranslateKeyPipe {
|
|
|
7
7
|
transform(key) {
|
|
8
8
|
return this.translation.t(key);
|
|
9
9
|
}
|
|
10
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
11
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.
|
|
10
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: TranslateKeyPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
11
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: TranslateKeyPipe, isStandalone: true, name: "t", pure: false });
|
|
12
12
|
}
|
|
13
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
13
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: TranslateKeyPipe, decorators: [{
|
|
14
14
|
type: Pipe,
|
|
15
15
|
args: [{ name: 't', pure: false, standalone: true }]
|
|
16
16
|
}] });
|
|
@@ -47,7 +47,11 @@ class SparkRegisterComponent {
|
|
|
47
47
|
const { email, password } = this.form.value;
|
|
48
48
|
try {
|
|
49
49
|
await this.authService.register(email, password);
|
|
50
|
-
|
|
50
|
+
// An app can mount registration without the password form (external-only sign-in with
|
|
51
|
+
// self-service account creation). Landing on the site root beats navigating to `undefined`,
|
|
52
|
+
// which the router resolves to the current route — leaving the user on a form they just
|
|
53
|
+
// submitted successfully.
|
|
54
|
+
this.router.navigate([this.routePaths.login ?? '/'], {
|
|
51
55
|
queryParams: { registered: 'true' },
|
|
52
56
|
});
|
|
53
57
|
}
|
|
@@ -72,12 +76,12 @@ class SparkRegisterComponent {
|
|
|
72
76
|
this.loading.set(false);
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
76
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.
|
|
79
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkRegisterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
80
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", 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\">{{ 'auth.register' | 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\">{{ 'auth.email' | 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\">{{ 'auth.invalidEmail' | t }}</div>\n }\n </div>\n\n <div class=\"mb-3\">\n <label for=\"password\" class=\"form-label\">{{ 'auth.password' | 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\">{{ 'auth.confirmPassword' | 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\">{{ 'auth.passwordMismatch' | 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 {{ 'auth.register' | t }}\n </button>\n </form>\n </bs-form>\n\n <!-- withRegistration() is opt-in independently of withLocalLogin(), so the password form may\n not be mounted. An unguarded [routerLink]=\"undefined\" navigates to the current route. -->\n @if (routePaths.login) {\n <div class=\"mt-3 text-center\">\n <span>{{ 'auth.alreadyHaveAccount' | t }} </span>\n <a [routerLink]=\"routePaths.login\">{{ 'auth.login' | 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]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[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", "browserUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "announce", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["color", "outline"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["color", "navStyle"] }, { 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 });
|
|
77
81
|
}
|
|
78
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
82
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkRegisterComponent, decorators: [{
|
|
79
83
|
type: Component,
|
|
80
|
-
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\">{{ 'auth.register' | 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\">{{ 'auth.email' | 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\">{{ 'auth.invalidEmail' | t }}</div>\n }\n </div>\n\n <div class=\"mb-3\">\n <label for=\"password\" class=\"form-label\">{{ 'auth.password' | 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\">{{ 'auth.confirmPassword' | 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\">{{ 'auth.passwordMismatch' | 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 {{ 'auth.register' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n
|
|
84
|
+
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\">{{ 'auth.register' | 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\">{{ 'auth.email' | 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\">{{ 'auth.invalidEmail' | t }}</div>\n }\n </div>\n\n <div class=\"mb-3\">\n <label for=\"password\" class=\"form-label\">{{ 'auth.password' | 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\">{{ 'auth.confirmPassword' | 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\">{{ 'auth.passwordMismatch' | 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 {{ 'auth.register' | t }}\n </button>\n </form>\n </bs-form>\n\n <!-- withRegistration() is opt-in independently of withLocalLogin(), so the password form may\n not be mounted. An unguarded [routerLink]=\"undefined\" navigates to the current route. -->\n @if (routePaths.login) {\n <div class=\"mt-3 text-center\">\n <span>{{ 'auth.alreadyHaveAccount' | t }} </span>\n <a [routerLink]=\"routePaths.login\">{{ 'auth.login' | t }}</a>\n </div>\n }\n </div>\n </bs-card>\n</div>\n" }]
|
|
81
85
|
}] });
|
|
82
86
|
|
|
83
87
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mintplayer-ng-spark-auth-register.mjs","sources":["../../register/src/spark-register.component.ts","../../register/src/spark-register.component.html","../../register/mintplayer-ng-spark-auth-register.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';\nimport { ReactiveFormsModule, FormBuilder, Validators, AbstractControl, ValidationErrors } from '@angular/forms';\nimport { RouterLink, Router } from '@angular/router';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';\nimport { BsCardComponent, BsCardHeaderComponent } from '@mintplayer/ng-bootstrap/card';\nimport { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';\nimport { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';\nimport { SPARK_AUTH_ROUTE_PATHS } from '@mintplayer/ng-spark-auth/models';\nimport { SparkAuthService, SparkAuthTranslationService } from '@mintplayer/ng-spark-auth/core';\nimport { TranslateKeyPipe } from '@mintplayer/ng-spark-auth/pipes';\n\nfunction passwordMatchValidator(control: AbstractControl): ValidationErrors | null {\n const password = control.get('password');\n const confirmPassword = control.get('confirmPassword');\n if (password && confirmPassword && password.value !== confirmPassword.value) {\n return { passwordMismatch: true };\n }\n return null;\n}\n\n@Component({\n selector: 'spark-register',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsSpinnerComponent, TranslateKeyPipe],\n templateUrl: './spark-register.component.html',\n})\nexport class SparkRegisterComponent {\n private readonly fb = inject(FormBuilder);\n private readonly authService = inject(SparkAuthService);\n private readonly router = inject(Router);\n private readonly translation = inject(SparkAuthTranslationService);\n readonly routePaths = inject(SPARK_AUTH_ROUTE_PATHS);\n\n colors = Color;\n readonly loading = signal(false);\n readonly errorMessage = signal('');\n\n readonly form = this.fb.group({\n email: ['', [Validators.required, Validators.email]],\n password: ['', Validators.required],\n confirmPassword: ['', Validators.required],\n }, { validators: passwordMatchValidator });\n\n async onSubmit(): Promise<void> {\n if (this.form.invalid) {\n this.form.markAllAsTouched();\n return;\n }\n\n this.loading.set(true);\n this.errorMessage.set('');\n\n const { email, password } = this.form.value;\n\n try {\n await this.authService.register(email!, password!);\n this.router.navigate([this.routePaths.login], {\n queryParams: { registered: 'true' },\n });\n } catch (err: any) {\n if (err instanceof HttpErrorResponse) {\n if (err.status === 400 && err.error?.errors) {\n const messages = ([] as string[]).concat(...Object.values(err.error.errors) as string[][]);\n this.errorMessage.set(messages.join(' '));\n } else if (err.error?.detail) {\n this.errorMessage.set(err.error.detail);\n } else {\n this.errorMessage.set(this.translation.t('auth.registrationFailed'));\n }\n } else {\n this.errorMessage.set(this.translation.t('auth.registrationFailed'));\n }\n } finally {\n this.loading.set(false);\n }\n }\n}\n\nexport default SparkRegisterComponent;\n","<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\">{{ 'auth.register' | 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\">{{ 'auth.email' | 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\">{{ 'auth.invalidEmail' | t }}</div>\n }\n </div>\n\n <div class=\"mb-3\">\n <label for=\"password\" class=\"form-label\">{{ 'auth.password' | 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\">{{ 'auth.confirmPassword' | 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\">{{ 'auth.passwordMismatch' | 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 {{ 'auth.register' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <span>{{ 'auth.alreadyHaveAccount' | t }} </span>\n <a [routerLink]=\"routePaths.login\">{{ 'auth.login' | t }}</a>\n </div>\n </div>\n </bs-card>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mintplayer-ng-spark-auth-register.mjs","sources":["../../register/src/spark-register.component.ts","../../register/src/spark-register.component.html","../../register/mintplayer-ng-spark-auth-register.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';\nimport { ReactiveFormsModule, FormBuilder, Validators, AbstractControl, ValidationErrors } from '@angular/forms';\nimport { RouterLink, Router } from '@angular/router';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';\nimport { BsCardComponent, BsCardHeaderComponent } from '@mintplayer/ng-bootstrap/card';\nimport { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';\nimport { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';\nimport { SPARK_AUTH_ROUTE_PATHS } from '@mintplayer/ng-spark-auth/models';\nimport { SparkAuthService, SparkAuthTranslationService } from '@mintplayer/ng-spark-auth/core';\nimport { TranslateKeyPipe } from '@mintplayer/ng-spark-auth/pipes';\n\nfunction passwordMatchValidator(control: AbstractControl): ValidationErrors | null {\n const password = control.get('password');\n const confirmPassword = control.get('confirmPassword');\n if (password && confirmPassword && password.value !== confirmPassword.value) {\n return { passwordMismatch: true };\n }\n return null;\n}\n\n@Component({\n selector: 'spark-register',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsSpinnerComponent, TranslateKeyPipe],\n templateUrl: './spark-register.component.html',\n})\nexport class SparkRegisterComponent {\n private readonly fb = inject(FormBuilder);\n private readonly authService = inject(SparkAuthService);\n private readonly router = inject(Router);\n private readonly translation = inject(SparkAuthTranslationService);\n readonly routePaths = inject(SPARK_AUTH_ROUTE_PATHS);\n\n colors = Color;\n readonly loading = signal(false);\n readonly errorMessage = signal('');\n\n readonly form = this.fb.group({\n email: ['', [Validators.required, Validators.email]],\n password: ['', Validators.required],\n confirmPassword: ['', Validators.required],\n }, { validators: passwordMatchValidator });\n\n async onSubmit(): Promise<void> {\n if (this.form.invalid) {\n this.form.markAllAsTouched();\n return;\n }\n\n this.loading.set(true);\n this.errorMessage.set('');\n\n const { email, password } = this.form.value;\n\n try {\n await this.authService.register(email!, password!);\n // An app can mount registration without the password form (external-only sign-in with\n // self-service account creation). Landing on the site root beats navigating to `undefined`,\n // which the router resolves to the current route — leaving the user on a form they just\n // submitted successfully.\n this.router.navigate([this.routePaths.login ?? '/'], {\n queryParams: { registered: 'true' },\n });\n } catch (err: any) {\n if (err instanceof HttpErrorResponse) {\n if (err.status === 400 && err.error?.errors) {\n const messages = ([] as string[]).concat(...Object.values(err.error.errors) as string[][]);\n this.errorMessage.set(messages.join(' '));\n } else if (err.error?.detail) {\n this.errorMessage.set(err.error.detail);\n } else {\n this.errorMessage.set(this.translation.t('auth.registrationFailed'));\n }\n } else {\n this.errorMessage.set(this.translation.t('auth.registrationFailed'));\n }\n } finally {\n this.loading.set(false);\n }\n }\n}\n\nexport default SparkRegisterComponent;\n","<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\">{{ 'auth.register' | 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\">{{ 'auth.email' | 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\">{{ 'auth.invalidEmail' | t }}</div>\n }\n </div>\n\n <div class=\"mb-3\">\n <label for=\"password\" class=\"form-label\">{{ 'auth.password' | 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\">{{ 'auth.confirmPassword' | 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\">{{ 'auth.passwordMismatch' | 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 {{ 'auth.register' | t }}\n </button>\n </form>\n </bs-form>\n\n <!-- withRegistration() is opt-in independently of withLocalLogin(), so the password form may\n not be mounted. An unguarded [routerLink]=\"undefined\" navigates to the current route. -->\n @if (routePaths.login) {\n <div class=\"mt-3 text-center\">\n <span>{{ 'auth.alreadyHaveAccount' | t }} </span>\n <a [routerLink]=\"routePaths.login\">{{ 'auth.login' | t }}</a>\n </div>\n }\n </div>\n </bs-card>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -77,10 +77,10 @@ class SparkResetPasswordComponent {
|
|
|
77
77
|
this.loading.set(false);
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
81
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.
|
|
80
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkResetPasswordComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
81
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", 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\">{{ 'auth.resetPassword' | 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\">{{ 'auth.goToLogin' | 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\">{{ 'auth.newPassword' | 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\">{{ 'auth.confirmPassword' | 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\">{{ 'auth.passwordMismatch' | 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 {{ 'auth.resetPassword' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'auth.backToLogin' | 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]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[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", "browserUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "announce", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["color", "outline"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["color", "navStyle"] }, { 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 });
|
|
82
82
|
}
|
|
83
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
83
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkResetPasswordComponent, decorators: [{
|
|
84
84
|
type: Component,
|
|
85
85
|
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\">{{ 'auth.resetPassword' | 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\">{{ 'auth.goToLogin' | 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\">{{ 'auth.newPassword' | 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\">{{ 'auth.confirmPassword' | 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\">{{ 'auth.passwordMismatch' | 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 {{ 'auth.resetPassword' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'auth.backToLogin' | t }}</a>\n </div>\n }\n </div>\n </bs-card>\n</div>\n" }]
|
|
86
86
|
}] });
|