Browse Source

add account module for resource owner password flow

pull/7861/head
mehmet-erim 6 years ago
parent
commit
499229ad21
  1. 37
      npm/ng-packs/angular.json
  2. 3
      npm/ng-packs/packages/account/README.md
  3. 7
      npm/ng-packs/packages/account/config/ng-package.json
  4. 22
      npm/ng-packs/packages/account/config/src/account-config.module.ts
  5. 1
      npm/ng-packs/packages/account/config/src/enums/index.ts
  6. 6
      npm/ng-packs/packages/account/config/src/enums/route-names.ts
  7. 1
      npm/ng-packs/packages/account/config/src/handlers/index.ts
  8. 1
      npm/ng-packs/packages/account/config/src/providers/index.ts
  9. 39
      npm/ng-packs/packages/account/config/src/providers/route.provider.ts
  10. 4
      npm/ng-packs/packages/account/config/src/public-api.ts
  11. 6
      npm/ng-packs/packages/account/jest.config.js
  12. 8
      npm/ng-packs/packages/account/ng-package.json
  13. 6
      npm/ng-packs/packages/account/ngcc.config.js
  14. 16
      npm/ng-packs/packages/account/package.json
  15. 93
      npm/ng-packs/packages/account/src/lib/account-routing.module.ts
  16. 65
      npm/ng-packs/packages/account/src/lib/account.module.ts
  17. 25
      npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.html
  18. 28
      npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.ts
  19. 48
      npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.html
  20. 99
      npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.ts
  21. 40
      npm/ng-packs/packages/account/src/lib/components/forgot-password/forgot-password.component.html
  22. 35
      npm/ng-packs/packages/account/src/lib/components/forgot-password/forgot-password.component.ts
  23. 8
      npm/ng-packs/packages/account/src/lib/components/index.ts
  24. 60
      npm/ng-packs/packages/account/src/lib/components/login/login.component.html
  25. 80
      npm/ng-packs/packages/account/src/lib/components/login/login.component.ts
  26. 62
      npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.html
  27. 45
      npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts
  28. 46
      npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.html
  29. 60
      npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts
  30. 51
      npm/ng-packs/packages/account/src/lib/components/register/register.component.html
  31. 96
      npm/ng-packs/packages/account/src/lib/components/register/register.component.ts
  32. 49
      npm/ng-packs/packages/account/src/lib/components/reset-password/reset-password.component.html
  33. 70
      npm/ng-packs/packages/account/src/lib/components/reset-password/reset-password.component.ts
  34. 63
      npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.html
  35. 75
      npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.ts
  36. 11
      npm/ng-packs/packages/account/src/lib/enums/components.ts
  37. 1
      npm/ng-packs/packages/account/src/lib/enums/index.ts
  38. 15
      npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts
  39. 1
      npm/ng-packs/packages/account/src/lib/guards/index.ts
  40. 12
      npm/ng-packs/packages/account/src/lib/models/account.ts
  41. 2
      npm/ng-packs/packages/account/src/lib/models/index.ts
  42. 3
      npm/ng-packs/packages/account/src/lib/models/options.ts
  43. 55
      npm/ng-packs/packages/account/src/lib/services/authentication.service.ts
  44. 2
      npm/ng-packs/packages/account/src/lib/services/index.ts
  45. 28
      npm/ng-packs/packages/account/src/lib/services/manage-profile.state.service.ts
  46. 1
      npm/ng-packs/packages/account/src/lib/tokens/index.ts
  47. 4
      npm/ng-packs/packages/account/src/lib/tokens/options.token.ts
  48. 8
      npm/ng-packs/packages/account/src/lib/utils/factory-utils.ts
  49. 1
      npm/ng-packs/packages/account/src/lib/utils/index.ts
  50. 9
      npm/ng-packs/packages/account/src/public-api.ts
  51. 19
      npm/ng-packs/packages/account/tsconfig.lib.json
  52. 6
      npm/ng-packs/packages/account/tsconfig.lib.prod.json
  53. 11
      npm/ng-packs/packages/account/tsconfig.spec.json
  54. 17
      npm/ng-packs/packages/account/tslint.json
  55. 2
      npm/ng-packs/tsconfig.json

37
npm/ng-packs/angular.json

@ -184,6 +184,43 @@
}
}
},
"account": {
"projectType": "library",
"root": "packages/account",
"sourceRoot": "packages/account/src",
"prefix": "abp",
"architect": {
"build": {
"builder": "@angular-devkit/build-ng-packagr:build",
"options": {
"tsConfig": "packages/account/tsconfig.lib.json",
"project": "packages/account/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "packages/account/tsconfig.lib.prod.json"
}
}
},
"test": {
"builder": "@angular-builders/jest:run",
"options": {
"coverage": true,
"passWithNoTests": true
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"packages/account/tsconfig.lib.json",
"packages/account/tsconfig.spec.json"
],
"exclude": ["**/node_modules/**"]
}
}
}
},
"identity": {
"projectType": "library",
"root": "packages/identity",

3
npm/ng-packs/packages/account/README.md

@ -0,0 +1,3 @@
<h1> @abp/ng.account </h1>
[docs.abp.io](https://docs.abp.io)

7
npm/ng-packs/packages/account/config/ng-package.json

@ -0,0 +1,7 @@
{
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/account/config",
"lib": {
"entryFile": "src/public-api.ts"
}
}

22
npm/ng-packs/packages/account/config/src/account-config.module.ts

@ -0,0 +1,22 @@
import { noop } from '@abp/ng.core';
import { APP_INITIALIZER, ModuleWithProviders, NgModule } from '@angular/core';
import { SessionHandler } from './handlers/session.handler';
import { ACCOUNT_ROUTE_PROVIDERS } from './providers/route.provider';
@NgModule()
export class AccountConfigModule {
static forRoot(): ModuleWithProviders<AccountConfigModule> {
return {
ngModule: AccountConfigModule,
providers: [
ACCOUNT_ROUTE_PROVIDERS,
{
provide: APP_INITIALIZER,
multi: true,
deps: [SessionHandler],
useFactory: noop,
},
],
};
}
}

1
npm/ng-packs/packages/account/config/src/enums/index.ts

@ -0,0 +1 @@
export * from './route-names';

6
npm/ng-packs/packages/account/config/src/enums/route-names.ts

@ -0,0 +1,6 @@
export const enum eAccountRouteNames {
Account = 'AbpAccount::Menu:Account',
Login = 'AbpAccount::Login',
Register = 'AbpAccount::Register',
ManageProfile = 'AbpAccount::ManageYourProfile',
}

1
npm/ng-packs/packages/account/config/src/handlers/index.ts

@ -0,0 +1 @@
export * from './session.handler';

1
npm/ng-packs/packages/account/config/src/providers/index.ts

@ -0,0 +1 @@
export * from './route.provider';

39
npm/ng-packs/packages/account/config/src/providers/route.provider.ts

@ -0,0 +1,39 @@
import { eLayoutType, RoutesService } from '@abp/ng.core';
import { APP_INITIALIZER } from '@angular/core';
import { eAccountRouteNames } from '../enums/route-names';
export const ACCOUNT_ROUTE_PROVIDERS = [
{ provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService], multi: true },
];
export function configureRoutes(routes: RoutesService) {
return () => {
routes.add([
{
path: '/account',
name: eAccountRouteNames.Account,
invisible: true,
layout: eLayoutType.application,
order: 1,
},
{
path: '/account/login',
name: eAccountRouteNames.Login,
parentName: eAccountRouteNames.Account,
order: 1,
},
{
path: '/account/register',
name: eAccountRouteNames.Register,
parentName: eAccountRouteNames.Account,
order: 2,
},
{
path: '/account/manage-profile',
name: eAccountRouteNames.ManageProfile,
parentName: eAccountRouteNames.Account,
order: 3,
},
]);
};
}

4
npm/ng-packs/packages/account/config/src/public-api.ts

@ -0,0 +1,4 @@
export * from './account-config.module';
export * from './enums';
export * from './providers';
export * from './handlers';

6
npm/ng-packs/packages/account/jest.config.js

@ -0,0 +1,6 @@
const jestConfig = require('../../jest.config');
module.exports = {
...jestConfig,
name: 'account',
};

8
npm/ng-packs/packages/account/ng-package.json

@ -0,0 +1,8 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/account",
"lib": {
"entryFile": "src/public-api.ts"
},
"whitelistedNonPeerDependencies": ["@abp/ng.theme.shared"]
}

6
npm/ng-packs/packages/account/ngcc.config.js

@ -0,0 +1,6 @@
module.exports = {
entryPoints: {
'.': {},
'./config': {}
},
};

16
npm/ng-packs/packages/account/package.json

@ -0,0 +1,16 @@
{
"name": "@abp/ng.account",
"version": "4.3.0",
"homepage": "https://abp.io",
"repository": {
"type": "git",
"url": "https://github.com/abpframework/abp.git"
},
"dependencies": {
"@abp/ng.theme.shared": "~3.3.2",
"tslib": "^2.0.0"
},
"publishConfig": {
"access": "public"
}
}

93
npm/ng-packs/packages/account/src/lib/account-routing.module.ts

@ -0,0 +1,93 @@
import {
AuthGuard,
DynamicLayoutComponent,
ReplaceableComponents,
ReplaceableRouteContainerComponent,
} from '@abp/ng.core';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthWrapperComponent } from './components/auth-wrapper/auth-wrapper.component';
import { ForgotPasswordComponent } from './components/forgot-password/forgot-password.component';
import { LoginComponent } from './components/login/login.component';
import { ManageProfileComponent } from './components/manage-profile/manage-profile.component';
import { RegisterComponent } from './components/register/register.component';
import { ResetPasswordComponent } from './components/reset-password/reset-password.component';
import { eAccountComponents } from './enums/components';
import { AuthenticationFlowGuard } from './guards/authentication-flow.guard';
const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'login' },
{
path: '',
component: DynamicLayoutComponent,
children: [
{
path: '',
component: AuthWrapperComponent,
children: [
{
path: 'login',
component: ReplaceableRouteContainerComponent,
canActivate: [AuthenticationFlowGuard],
data: {
replaceableComponent: {
key: eAccountComponents.Login,
defaultComponent: LoginComponent,
} as ReplaceableComponents.RouteData<LoginComponent>,
},
},
{
path: 'register',
component: ReplaceableRouteContainerComponent,
canActivate: [AuthenticationFlowGuard],
data: {
replaceableComponent: {
key: eAccountComponents.Register,
defaultComponent: RegisterComponent,
} as ReplaceableComponents.RouteData<RegisterComponent>,
},
},
{
path: 'forgot-password',
component: ReplaceableRouteContainerComponent,
canActivate: [AuthenticationFlowGuard],
data: {
replaceableComponent: {
key: eAccountComponents.ForgotPassword,
defaultComponent: ForgotPasswordComponent,
} as ReplaceableComponents.RouteData<ForgotPasswordComponent>,
},
},
{
path: 'reset-password',
component: ReplaceableRouteContainerComponent,
canActivate: [AuthenticationFlowGuard],
data: {
replaceableComponent: {
key: eAccountComponents.ResetPassword,
defaultComponent: ResetPasswordComponent,
} as ReplaceableComponents.RouteData<ResetPasswordComponent>,
},
},
],
},
{
path: 'manage-profile',
component: ReplaceableRouteContainerComponent,
canActivate: [AuthGuard],
data: {
replaceableComponent: {
key: eAccountComponents.ManageProfile,
defaultComponent: ManageProfileComponent,
} as ReplaceableComponents.RouteData<ManageProfileComponent>,
},
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class AccountRoutingModule {}

65
npm/ng-packs/packages/account/src/lib/account.module.ts

@ -0,0 +1,65 @@
import { CoreModule, LazyModuleFactory } from '@abp/ng.core';
import { ThemeSharedModule } from '@abp/ng.theme.shared';
import { ModuleWithProviders, NgModule, NgModuleFactory } from '@angular/core';
import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
import { NgxValidateCoreModule } from '@ngx-validate/core';
import { AccountRoutingModule } from './account-routing.module';
import { AuthWrapperComponent } from './components/auth-wrapper/auth-wrapper.component';
import { ChangePasswordComponent } from './components/change-password/change-password.component';
import { LoginComponent } from './components/login/login.component';
import { ManageProfileComponent } from './components/manage-profile/manage-profile.component';
import { PersonalSettingsComponent } from './components/personal-settings/personal-settings.component';
import { RegisterComponent } from './components/register/register.component';
import { TenantBoxComponent } from './components/tenant-box/tenant-box.component';
import { Options } from './models/options';
import { ACCOUNT_OPTIONS } from './tokens/options.token';
import { accountOptionsFactory } from './utils/factory-utils';
import { AuthenticationFlowGuard } from './guards/authentication-flow.guard';
import { AuthenticationService } from './services/authentication.service';
import { ForgotPasswordComponent } from './components/forgot-password/forgot-password.component';
import { ResetPasswordComponent } from './components/reset-password/reset-password.component';
const declarations = [
AuthWrapperComponent,
LoginComponent,
RegisterComponent,
TenantBoxComponent,
ChangePasswordComponent,
ManageProfileComponent,
PersonalSettingsComponent,
ForgotPasswordComponent,
ResetPasswordComponent,
];
@NgModule({
declarations: [...declarations],
imports: [
CoreModule,
AccountRoutingModule,
ThemeSharedModule,
NgbDropdownModule,
NgxValidateCoreModule,
],
exports: [...declarations],
})
export class AccountModule {
static forChild(options = {} as Options): ModuleWithProviders<AccountModule> {
return {
ngModule: AccountModule,
providers: [
AuthenticationFlowGuard,
AuthenticationService,
{ provide: ACCOUNT_OPTIONS, useValue: options },
{
provide: 'ACCOUNT_OPTIONS',
useFactory: accountOptionsFactory,
deps: [ACCOUNT_OPTIONS],
},
],
};
}
static forLazy(options = {} as Options): NgModuleFactory<AccountModule> {
return new LazyModuleFactory(AccountModule.forChild(options));
}
}

25
npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.html

@ -0,0 +1,25 @@
<div class="row">
<div class="mx-auto col col-md-5">
<ng-container *ngIf="(isMultiTenancyEnabled$ | async) && multiTenancy.isTenantBoxVisible">
<abp-tenant-box *abpReplaceableTemplate="{ componentKey: tenantBoxKey }"></abp-tenant-box>
</ng-container>
<div class="abp-account-container">
<div
*ngIf="enableLocalLogin$ | async; else disableLocalLoginTemplate"
class="card mt-3 shadow-sm rounded"
>
<div class="card-body p-5">
<router-outlet></router-outlet>
</div>
</div>
</div>
</div>
</div>
<ng-template #disableLocalLoginTemplate>
<div class="alert alert-warning">
<strong>{{ 'AbpAccount::InvalidLoginRequest' | abpLocalization }}</strong>
{{ 'AbpAccount::ThereAreNoLoginSchemesConfiguredForThisClient' | abpLocalization }}
</div>
</ng-template>

28
npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.ts

@ -0,0 +1,28 @@
import { ConfigStateService, MultiTenancyService, SubscriptionService } from '@abp/ng.core';
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { eAccountComponents } from '../../enums/components';
@Component({
selector: 'abp-auth-wrapper',
templateUrl: './auth-wrapper.component.html',
exportAs: 'abpAuthWrapper',
providers: [SubscriptionService],
})
export class AuthWrapperComponent {
isMultiTenancyEnabled$ = this.configState.getDeep$('multiTenancy.isEnabled');
get enableLocalLogin$(): Observable<boolean> {
return this.configState
.getSetting$('Abp.Account.EnableLocalLogin')
.pipe(map(value => value?.toLowerCase() !== 'false'));
}
tenantBoxKey = eAccountComponents.TenantBox;
constructor(
public readonly multiTenancy: MultiTenancyService,
private configState: ConfigStateService,
) {}
}

48
npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.html

@ -0,0 +1,48 @@
<form [formGroup]="form" (ngSubmit)="onSubmit()" [mapErrorsFn]="mapErrorsFn" validateOnSubmit>
<div *ngIf="!hideCurrentPassword" class="form-group">
<label for="current-password">{{
'AbpIdentity::DisplayName:CurrentPassword' | abpLocalization
}}</label
><span> * </span
><input
type="password"
id="current-password"
class="form-control"
formControlName="password"
autofocus
autocomplete="current-password"
/>
</div>
<div class="form-group">
<label for="new-password">{{ 'AbpIdentity::DisplayName:NewPassword' | abpLocalization }}</label
><span> * </span
><input
type="password"
id="new-password"
class="form-control"
formControlName="newPassword"
autocomplete="new-password"
/>
</div>
<div class="form-group">
<label for="confirm-new-password">{{
'AbpIdentity::DisplayName:NewPasswordConfirm' | abpLocalization
}}</label
><span> * </span
><input
type="password"
id="confirm-new-password"
class="form-control"
formControlName="repeatNewPassword"
autocomplete="new-password"
/>
</div>
<abp-button
iconClass="fa fa-check"
buttonClass="btn btn-primary color-white"
buttonType="submit"
[loading]="inProgress"
[disabled]="form?.invalid"
>{{ 'AbpIdentity::Save' | abpLocalization }}</abp-button
>
</form>

99
npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.ts

@ -0,0 +1,99 @@
import { Profile, ProfileService } from '@abp/ng.core';
import { getPasswordValidators, ToasterService } from '@abp/ng.theme.shared';
import { Component, Injector, Input, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { comparePasswords, Validation } from '@ngx-validate/core';
import { finalize } from 'rxjs/operators';
import snq from 'snq';
import { Account } from '../../models/account';
import { ManageProfileStateService } from '../../services/manage-profile.state.service';
const { required } = Validators;
const PASSWORD_FIELDS = ['newPassword', 'repeatNewPassword'];
@Component({
selector: 'abp-change-password-form',
templateUrl: './change-password.component.html',
exportAs: 'abpChangePasswordForm',
})
export class ChangePasswordComponent
implements OnInit, Account.ChangePasswordComponentInputs, Account.ChangePasswordComponentOutputs {
form: FormGroup;
inProgress: boolean;
hideCurrentPassword: boolean;
mapErrorsFn: Validation.MapErrorsFn = (errors, groupErrors, control) => {
if (PASSWORD_FIELDS.indexOf(String(control.name)) < 0) return errors;
return errors.concat(groupErrors.filter(({ key }) => key === 'passwordMismatch'));
};
constructor(
private fb: FormBuilder,
private injector: Injector,
private toasterService: ToasterService,
private profileService: ProfileService,
private manageProfileState: ManageProfileStateService,
) {}
ngOnInit(): void {
this.hideCurrentPassword = !this.manageProfileState.getProfile()?.hasPassword;
const passwordValidations = getPasswordValidators(this.injector);
this.form = this.fb.group(
{
password: ['', required],
newPassword: [
'',
{
validators: [required, ...passwordValidations],
},
],
repeatNewPassword: [
'',
{
validators: [required, ...passwordValidations],
},
],
},
{
validators: [comparePasswords(PASSWORD_FIELDS)],
},
);
if (this.hideCurrentPassword) this.form.removeControl('password');
}
onSubmit() {
if (this.form.invalid) return;
this.inProgress = true;
this.profileService
.changePassword({
...(!this.hideCurrentPassword && { currentPassword: this.form.get('password').value }),
newPassword: this.form.get('newPassword').value,
})
.pipe(finalize(() => (this.inProgress = false)))
.subscribe({
next: () => {
this.form.reset();
this.toasterService.success('AbpAccount::PasswordChangedMessage', '', {
life: 5000,
});
if (this.hideCurrentPassword) {
this.hideCurrentPassword = false;
this.form.addControl('password', new FormControl('', [required]));
}
},
error: err => {
this.toasterService.error(
snq(() => err.error.error.message, 'AbpAccount::DefaultErrorMessage'),
);
},
});
}
}

40
npm/ng-packs/packages/account/src/lib/components/forgot-password/forgot-password.component.html

@ -0,0 +1,40 @@
<h4>{{ 'AbpAccount::ForgotPassword' | abpLocalization }}</h4>
<form
*ngIf="!isEmailSent; else emailSentTemplate"
[formGroup]="form"
(ngSubmit)="onSubmit()"
validateOnSubmit
>
<p>{{ 'AbpAccount::SendPasswordResetLink_Information' | abpLocalization }}</p>
<div class="form-group">
<label for="input-email-address">{{ 'AbpAccount::EmailAddress' | abpLocalization }}</label
><span> * </span>
<input type="email" id="input-email-address" class="form-control" formControlName="email" />
</div>
<abp-button
class="d-block"
buttonClass="mt-2 mb-3 btn btn-primary btn-block"
[loading]="inProgress"
buttonType="submit"
[disabled]="form?.invalid"
>
{{ 'AbpAccount::Submit' | abpLocalization }}
</abp-button>
<a routerLink="/account/login"
><i class="fa fa-long-arrow-left mr-1"></i>{{ 'AbpAccount::Login' | abpLocalization }}</a
>
</form>
<ng-template #emailSentTemplate>
<p>
{{ 'AbpAccount::PasswordResetMailSentMessage' | abpLocalization }}
</p>
<a routerLink="/account/login">
<button class="d-block mt-2 mb-3 btn btn-primary btn-block">
<i class="fa fa-long-arrow-left mr-1"></i>
{{ 'AbpAccount::BackToLogin' | abpLocalization }}
</button>
</a>
</ng-template>

35
npm/ng-packs/packages/account/src/lib/components/forgot-password/forgot-password.component.ts

@ -0,0 +1,35 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { finalize } from 'rxjs/operators';
import { AccountService } from '../../proxy/account/account.service';
@Component({
selector: 'abp-forgot-password',
templateUrl: 'forgot-password.component.html',
})
export class ForgotPasswordComponent {
form: FormGroup;
inProgress: boolean;
isEmailSent: boolean = false;
constructor(private fb: FormBuilder, private accountService: AccountService) {
this.form = this.fb.group({
email: ['', [Validators.required, Validators.email]],
});
}
onSubmit() {
if (this.form.invalid) return;
this.inProgress = true;
this.accountService
.sendPasswordResetCode({ email: this.form.get('email').value, appName: 'Angular' })
.pipe(finalize(() => (this.inProgress = false)))
.subscribe(() => {
this.isEmailSent = true;
});
}
}

8
npm/ng-packs/packages/account/src/lib/components/index.ts

@ -0,0 +1,8 @@
export * from './change-password/change-password.component';
export * from './forgot-password/forgot-password.component';
export * from './login/login.component';
export * from './manage-profile/manage-profile.component';
export * from './register/register.component';
export * from './personal-settings/personal-settings.component';
export * from './reset-password/reset-password.component';
export * from './tenant-box/tenant-box.component';

60
npm/ng-packs/packages/account/src/lib/components/login/login.component.html

@ -0,0 +1,60 @@
<h4>{{ 'AbpAccount::Login' | abpLocalization }}</h4>
<strong *ngIf="isSelfRegistrationEnabled">
{{ 'AbpAccount::AreYouANewUser' | abpLocalization }}
<a class="text-decoration-none" routerLink="/account/register">{{
'AbpAccount::Register' | abpLocalization
}}</a>
</strong>
<form [formGroup]="form" (ngSubmit)="onSubmit()" validateOnSubmit class="mt-4">
<div class="form-group">
<label for="login-input-user-name-or-email-address">{{
'AbpAccount::UserNameOrEmailAddress' | abpLocalization
}}</label>
<input
class="form-control"
type="text"
id="login-input-user-name-or-email-address"
formControlName="username"
autocomplete="username"
autofocus
/>
</div>
<div class="form-group">
<label for="login-input-password">{{ 'AbpAccount::Password' | abpLocalization }}</label>
<input
class="form-control"
type="password"
id="login-input-password"
formControlName="password"
autocomplete="current-password"
/>
</div>
<div class="row">
<div class="col">
<label class="custom-checkbox custom-control mb-2" for="login-input-remember-me">
<input
class="form-check-input"
type="checkbox"
id="login-input-remember-me"
formControlName="remember"
/>
{{ 'AbpAccount::RememberMe' | abpLocalization }}
</label>
</div>
<div class="text-right col">
<a routerLink="/account/forgot-password">{{
'AbpAccount::ForgotPassword' | abpLocalization
}}</a>
</div>
</div>
<abp-button
[loading]="inProgress"
buttonType="submit"
name="Action"
buttonClass="btn-block btn-lg mt-3 btn btn-primary"
>
{{ 'AbpAccount::Login' | abpLocalization }}
</abp-button>
</form>

80
npm/ng-packs/packages/account/src/lib/components/login/login.component.ts

@ -0,0 +1,80 @@
import { ConfigStateService } from '@abp/ng.core';
import { ToasterService } from '@abp/ng.theme.shared';
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngxs/store';
import { throwError } from 'rxjs';
import { catchError, finalize } from 'rxjs/operators';
import snq from 'snq';
import { eAccountComponents } from '../../enums/components';
import { AuthenticationService } from '../../services/authentication.service';
const { maxLength, minLength, required } = Validators;
@Component({
selector: 'abp-login',
templateUrl: './login.component.html',
})
export class LoginComponent implements OnInit {
form: FormGroup;
inProgress: boolean;
isSelfRegistrationEnabled = true;
authWrapperKey = eAccountComponents.AuthWrapper;
constructor(
private fb: FormBuilder,
private store: Store,
private toasterService: ToasterService,
private authenticationService: AuthenticationService,
private configState: ConfigStateService,
) {}
ngOnInit() {
this.init();
this.buildForm();
}
protected init() {
this.isSelfRegistrationEnabled =
(
(this.configState.getSetting('Abp.Account.IsSelfRegistrationEnabled') as string) || ''
).toLowerCase() !== 'false';
}
protected buildForm() {
this.form = this.fb.group({
username: ['', [required, maxLength(255)]],
password: ['', [required, maxLength(128)]],
remember: [false],
});
}
onSubmit() {
if (this.form.invalid) return;
this.inProgress = true;
const { username, password, remember } = this.form.value;
this.authenticationService
.login(username, password, remember)
.pipe(
catchError(err => {
this.toasterService.error(
snq(() => err.error.error_description) ||
snq(() => err.error.error.message, 'AbpAccount::DefaultErrorMessage'),
'Error',
{ life: 7000 },
);
return throwError(err);
}),
finalize(() => (this.inProgress = false)),
)
.subscribe(() => {
// TODO: this.store.dispatch(new SetRemember(this.form.get('remember').value));
});
}
}

62
npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.html

@ -0,0 +1,62 @@
<div id="AbpContentToolbar"></div>
<div class="card border-0 shadow-sm min-h-400" [abpLoading]="!(profile$ | async)">
<div class="card-body">
<div class="row">
<div class="col-12 col-md-3">
<ul class="nav flex-column nav-pills" id="nav-tab" role="tablist">
<li
*ngIf="!hideChangePasswordTab && (profile$ | async)"
class="nav-item"
(click)="selectedTab = 0"
>
<a
class="nav-link"
[ngClass]="{ active: selectedTab === 0 }"
role="tab"
href="javascript:void(0)"
>{{ 'AbpUi::ChangePassword' | abpLocalization }}</a
>
</li>
<li class="nav-item mb-2" (click)="selectedTab = 1">
<a
class="nav-link"
[ngClass]="{ active: selectedTab === 1 }"
role="tab"
href="javascript:void(0)"
>{{ 'AbpAccount::PersonalSettings' | abpLocalization }}</a
>
</li>
</ul>
</div>
<div *ngIf="profile$ | async" class="col-12 col-md-9">
<div class="tab-content" *ngIf="selectedTab === 0" [@fadeIn]>
<div class="tab-pane active" role="tabpanel">
<h4>
{{ 'AbpIdentity::ChangePassword' | abpLocalization }}
<hr />
</h4>
<abp-change-password-form
*abpReplaceableTemplate="{
componentKey: changePasswordKey
}"
></abp-change-password-form>
</div>
</div>
<div class="tab-content" *ngIf="selectedTab === 1" [@fadeIn]>
<div class="tab-pane active" role="tabpanel">
<h4>
{{ 'AbpIdentity::PersonalSettings' | abpLocalization }}
<hr />
</h4>
<abp-personal-settings-form
*abpReplaceableTemplate="{
componentKey: personalSettingsKey
}"
></abp-personal-settings-form>
</div>
</div>
</div>
</div>
</div>
</div>

45
npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts

@ -0,0 +1,45 @@
import { Profile, ProfileService } from '@abp/ng.core';
import { fadeIn } from '@abp/ng.theme.shared';
import { transition, trigger, useAnimation } from '@angular/animations';
import { Component, OnInit } from '@angular/core';
import { eAccountComponents } from '../../enums/components';
import { ManageProfileStateService } from '../../services/manage-profile.state.service';
@Component({
selector: 'abp-manage-profile',
templateUrl: './manage-profile.component.html',
animations: [trigger('fadeIn', [transition(':enter', useAnimation(fadeIn))])],
styles: [
`
.min-h-400 {
min-height: 400px;
}
`,
],
})
export class ManageProfileComponent implements OnInit {
selectedTab = 0;
changePasswordKey = eAccountComponents.ChangePassword;
personalSettingsKey = eAccountComponents.PersonalSettings;
profile$ = this.manageProfileState.getProfile$();
hideChangePasswordTab: boolean;
constructor(
protected profileService: ProfileService,
protected manageProfileState: ManageProfileStateService,
) {}
ngOnInit() {
this.profileService.get().subscribe(profile => {
this.manageProfileState.setProfile(profile);
if (profile.isExternal) {
this.hideChangePasswordTab = true;
this.selectedTab = 1;
}
});
}
}

46
npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.html

@ -0,0 +1,46 @@
<form validateOnSubmit *ngIf="form" [formGroup]="form" (ngSubmit)="submit()">
<div class="form-group">
<label for="username">{{ 'AbpIdentity::DisplayName:UserName' | abpLocalization }}</label
><span> * </span
><input
type="text"
id="username"
class="form-control"
formControlName="userName"
autofocus
(keydown.space)="$event.preventDefault()"
/>
</div>
<div class="row">
<div class="col col-md-6">
<div class="form-group">
<label for="name">{{ 'AbpIdentity::DisplayName:Name' | abpLocalization }}</label
><input type="text" id="name" class="form-control" formControlName="name" />
</div>
</div>
<div class="col col-md-6">
<div class="form-group">
<label for="surname">{{ 'AbpIdentity::DisplayName:Surname' | abpLocalization }}</label
><input type="text" id="surname" class="form-control" formControlName="surname" />
</div>
</div>
</div>
<div class="form-group">
<label for="email-address">{{ 'AbpIdentity::DisplayName:Email' | abpLocalization }}</label
><span> * </span
><input type="text" id="email-address" class="form-control" formControlName="email" />
</div>
<div class="form-group">
<label for="phone-number">{{ 'AbpIdentity::DisplayName:PhoneNumber' | abpLocalization }}</label
><input type="text" id="phone-number" class="form-control" formControlName="phoneNumber" />
</div>
<abp-button
buttonType="submit"
iconClass="fa fa-check"
buttonClass="btn btn-primary color-white"
[loading]="inProgress"
[disabled]="form?.invalid"
>
{{ 'AbpIdentity::Save' | abpLocalization }}</abp-button
>
</form>

60
npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts

@ -0,0 +1,60 @@
import { Profile, ProfileService } from '@abp/ng.core';
import { ToasterService } from '@abp/ng.theme.shared';
import { Component, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngxs/store';
import { finalize } from 'rxjs/operators';
import { Account } from '../../models/account';
import { ManageProfileStateService } from '../../services/manage-profile.state.service';
const { maxLength, required, email } = Validators;
@Component({
selector: 'abp-personal-settings-form',
templateUrl: './personal-settings.component.html',
exportAs: 'abpPersonalSettingsForm',
})
export class PersonalSettingsComponent
implements
OnInit,
Account.PersonalSettingsComponentInputs,
Account.PersonalSettingsComponentOutputs {
form: FormGroup;
inProgress: boolean;
constructor(
private fb: FormBuilder,
private store: Store,
private toasterService: ToasterService,
private profileService: ProfileService,
private manageProfileState: ManageProfileStateService,
) {}
ngOnInit() {
this.buildForm();
}
buildForm() {
const profile = this.manageProfileState.getProfile();
this.form = this.fb.group({
userName: [profile.userName, [required, maxLength(256)]],
email: [profile.email, [required, email, maxLength(256)]],
name: [profile.name || '', [maxLength(64)]],
surname: [profile.surname || '', [maxLength(64)]],
phoneNumber: [profile.phoneNumber || '', [maxLength(16)]],
});
}
submit() {
if (this.form.invalid) return;
this.inProgress = true;
this.profileService
.update(this.form.value)
.pipe(finalize(() => (this.inProgress = false)))
.subscribe(profile => {
this.manageProfileState.setProfile(profile);
this.toasterService.success('AbpAccount::PersonalSettingsSaved', 'Success', { life: 5000 });
});
}
}

51
npm/ng-packs/packages/account/src/lib/components/register/register.component.html

@ -0,0 +1,51 @@
<h4>{{ 'AbpAccount::Register' | abpLocalization }}</h4>
<strong>
{{ 'AbpAccount::AlreadyRegistered' | abpLocalization }}
<a class="text-decoration-none" routerLink="/account/login">{{
'AbpAccount::Login' | abpLocalization
}}</a>
</strong>
<form
*ngIf="isSelfRegistrationEnabled"
[formGroup]="form"
(ngSubmit)="onSubmit()"
validateOnSubmit
class="mt-4"
>
<div class="form-group">
<label for="input-user-name">{{ 'AbpAccount::UserName' | abpLocalization }}</label
><span> * </span
><input
autofocus
type="text"
id="input-user-name"
class="form-control"
formControlName="username"
autocomplete="username"
/>
</div>
<div class="form-group">
<label for="input-email-address">{{ 'AbpAccount::EmailAddress' | abpLocalization }}</label
><span> * </span
><input type="email" id="input-email-address" class="form-control" formControlName="email" />
</div>
<div class="form-group">
<label for="input-password">{{ 'AbpAccount::Password' | abpLocalization }}</label
><span> * </span
><input
type="password"
id="input-password"
class="form-control"
formControlName="password"
autocomplete="current-password"
/>
</div>
<abp-button
[loading]="inProgress"
buttonType="submit"
name="Action"
buttonClass="btn-block btn-lg mt-3 btn btn-primary"
>
{{ 'AbpAccount::Register' | abpLocalization }}
</abp-button>
</form>

96
npm/ng-packs/packages/account/src/lib/components/register/register.component.ts

@ -0,0 +1,96 @@
import { ConfigStateService } from '@abp/ng.core';
import { getPasswordValidators, ToasterService } from '@abp/ng.theme.shared';
import { Component, Injector, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { throwError } from 'rxjs';
import { catchError, finalize, switchMap } from 'rxjs/operators';
import snq from 'snq';
import { eAccountComponents } from '../../enums/components';
import { AccountService } from '../../proxy/account/account.service';
import { RegisterDto } from '../../proxy/account/models';
import { AuthenticationService } from '../../services';
const { maxLength, required, email } = Validators;
@Component({
selector: 'abp-register',
templateUrl: './register.component.html',
})
export class RegisterComponent implements OnInit {
form: FormGroup;
inProgress: boolean;
isSelfRegistrationEnabled = true;
authWrapperKey = eAccountComponents.AuthWrapper;
constructor(
private fb: FormBuilder,
private accountService: AccountService,
private configState: ConfigStateService,
private toasterService: ToasterService,
private authenticationSerivice: AuthenticationService,
private injector: Injector,
) {}
ngOnInit() {
this.init();
this.buildForm();
}
protected init() {
this.isSelfRegistrationEnabled =
(this.configState.getSetting('Abp.Account.IsSelfRegistrationEnabled') || '').toLowerCase() !==
'false';
if (!this.isSelfRegistrationEnabled) {
this.toasterService.warn(
{
key: 'AbpAccount::SelfRegistrationDisabledMessage',
defaultValue: 'Self registration is disabled.',
},
null,
{ life: 10000 },
);
return;
}
}
protected buildForm() {
this.form = this.fb.group({
username: ['', [required, maxLength(255)]],
password: ['', [required, ...getPasswordValidators(this.injector)]],
email: ['', [required, email]],
});
}
onSubmit() {
if (this.form.invalid) return;
this.inProgress = true;
const newUser = {
userName: this.form.get('username').value,
password: this.form.get('password').value,
emailAddress: this.form.get('email').value,
appName: 'Angular',
} as RegisterDto;
this.accountService
.register(newUser)
.pipe(
switchMap(() => this.authenticationSerivice.login(newUser.userName, newUser.password)),
catchError(err => {
this.toasterService.error(
snq(() => err.error.error_description) ||
snq(() => err.error.error.message, 'AbpAccount::DefaultErrorMessage'),
'Error',
{ life: 7000 },
);
return throwError(err);
}),
finalize(() => (this.inProgress = false)),
)
.subscribe();
}
}

49
npm/ng-packs/packages/account/src/lib/components/reset-password/reset-password.component.html

@ -0,0 +1,49 @@
<h4>{{ 'AbpAccount::ResetPassword' | abpLocalization }}</h4>
<form
*ngIf="!isPasswordReset; else passwordResetTemplate"
[formGroup]="form"
[mapErrorsFn]="mapErrorsFn"
(ngSubmit)="onSubmit()"
validateOnSubmit
>
<p>{{ 'AbpAccount::ResetPassword_Information' | abpLocalization }}</p>
<div class="form-group">
<label for="input-password">{{ 'AbpAccount::Password' | abpLocalization }}</label
><span> * </span>
<input type="password" id="input-password" class="form-control" formControlName="password" />
</div>
<div class="form-group">
<label for="input-confirm-password">{{ 'AbpAccount::ConfirmPassword' | abpLocalization }}</label
><span> * </span>
<input
type="password"
id="input-confirm-password"
class="form-control"
formControlName="confirmPassword"
/>
</div>
<button class="mr-2 btn btn-secondary" type="button" routerLink="/account/login">
{{ 'AbpAccount::Cancel' | abpLocalization }}
</button>
<abp-button
buttonType="submit"
buttonClass="mr-2 btn btn-primary"
[loading]="inProgress"
(click)="onSubmit()"
>
{{ 'AbpAccount::Submit' | abpLocalization }}
</abp-button>
</form>
<ng-template #passwordResetTemplate>
<p>
{{ 'AbpAccount::YourPasswordIsSuccessfullyReset' | abpLocalization }}
</p>
<a routerLink="/account/login">
<button class="d-block mt-2 mb-3 btn btn-primary">
{{ 'AbpAccount::BackToLogin' | abpLocalization }}
</button>
</a>
</ng-template>

70
npm/ng-packs/packages/account/src/lib/components/reset-password/reset-password.component.ts

@ -0,0 +1,70 @@
import { getPasswordValidators } from '@abp/ng.theme.shared';
import { Component, Injector, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { comparePasswords, Validation } from '@ngx-validate/core';
import { finalize } from 'rxjs/operators';
import { AccountService } from '../../proxy/account/account.service';
const PASSWORD_FIELDS = ['password', 'confirmPassword'];
@Component({
selector: 'abp-reset-password',
templateUrl: './reset-password.component.html',
})
export class ResetPasswordComponent implements OnInit {
form: FormGroup;
inProgress: boolean = false;
isPasswordReset: boolean = false;
mapErrorsFn: Validation.MapErrorsFn = (errors, groupErrors, control) => {
if (PASSWORD_FIELDS.indexOf(String(control.name)) < 0) return errors;
return errors.concat(groupErrors.filter(({ key }) => key === 'passwordMismatch'));
};
constructor(
private fb: FormBuilder,
private accountService: AccountService,
private route: ActivatedRoute,
private router: Router,
private injector: Injector,
) {}
ngOnInit(): void {
this.route.queryParams.subscribe(({ userId, resetToken }) => {
if (!userId || !resetToken) this.router.navigateByUrl('/account/login');
this.form = this.fb.group(
{
userId: [userId, [Validators.required]],
resetToken: [resetToken, [Validators.required]],
password: ['', [Validators.required, ...getPasswordValidators(this.injector)]],
confirmPassword: ['', [Validators.required, ...getPasswordValidators(this.injector)]],
},
{
validators: [comparePasswords(PASSWORD_FIELDS)],
},
);
});
}
onSubmit() {
if (this.form.invalid || this.inProgress) return;
this.inProgress = true;
this.accountService
.resetPassword({
userId: this.form.get('userId').value,
resetToken: this.form.get('resetToken').value,
password: this.form.get('password').value,
})
.pipe(finalize(() => (this.inProgress = false)))
.subscribe(() => {
this.isPasswordReset = true;
});
}
}

63
npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.html

@ -0,0 +1,63 @@
<ng-container *ngIf="(currentTenant$ | async) || {} as currentTenant">
<div class="card shadow-sm rounded mb-3">
<div class="card-body px-5">
<div class="row">
<div class="col">
<span style="font-size: 0.8em;" class="text-uppercase text-muted">{{
'AbpUiMultiTenancy::Tenant' | abpLocalization
}}</span
><br />
<h6 class="m-0 d-inline-block">
<i>{{ currentTenant.name || ('AbpUiMultiTenancy::NotSelected' | abpLocalization) }}</i>
</h6>
</div>
<div class="col-auto">
<a
id="AbpTenantSwitchLink"
href="javascript:void(0);"
class="btn btn-sm mt-3 btn-outline-primary"
(click)="onSwitch()"
>{{ 'AbpUiMultiTenancy::Switch' | abpLocalization }}</a
>
</div>
</div>
</div>
</div>
<abp-modal size="md" [(visible)]="isModalVisible" [busy]="modalBusy">
<ng-template #abpHeader>
<h5>Switch Tenant</h5>
</ng-template>
<ng-template #abpBody>
<form (ngSubmit)="save()">
<div class="mt-2">
<div class="form-group">
<label for="name">{{ 'AbpUiMultiTenancy::Name' | abpLocalization }}</label>
<input
[(ngModel)]="name"
type="text"
id="name"
name="tenant"
class="form-control"
autofocus
/>
</div>
<p>{{ 'AbpUiMultiTenancy::SwitchTenantHint' | abpLocalization }}</p>
</div>
</form>
</ng-template>
<ng-template #abpFooter>
<button #abpClose type="button" class="btn btn-secondary">
{{ 'AbpTenantManagement::Cancel' | abpLocalization }}
</button>
<abp-button
type="abp-button"
iconClass="fa fa-check"
(click)="save()"
[disabled]="currentTenant?.name === name"
>
<span>{{ 'AbpTenantManagement::Save' | abpLocalization }}</span>
</abp-button>
</ng-template>
</abp-modal>
</ng-container>

75
npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.ts

@ -0,0 +1,75 @@
import {
AbpApplicationConfigurationService,
AbpTenantService,
ConfigStateService,
CurrentTenantDto,
SessionStateService,
} from '@abp/ng.core';
import { ToasterService } from '@abp/ng.theme.shared';
import { Component } from '@angular/core';
import { Store } from '@ngxs/store';
import { finalize } from 'rxjs/operators';
import { Account } from '../../models/account';
@Component({
selector: 'abp-tenant-box',
templateUrl: './tenant-box.component.html',
})
export class TenantBoxComponent
implements Account.TenantBoxComponentInputs, Account.TenantBoxComponentOutputs {
currentTenant$ = this.sessionState.getTenant$();
name: string;
isModalVisible: boolean;
modalBusy: boolean;
constructor(
private store: Store,
private toasterService: ToasterService,
private tenantService: AbpTenantService,
private sessionState: SessionStateService,
private configState: ConfigStateService,
private appConfigService: AbpApplicationConfigurationService,
) {}
onSwitch() {
const tenant = this.sessionState.getTenant();
this.name = tenant?.name;
this.isModalVisible = true;
}
save() {
if (!this.name) {
this.setTenant(null);
this.isModalVisible = false;
return;
}
this.modalBusy = true;
this.tenantService
.findTenantByName(this.name, {})
.pipe(finalize(() => (this.modalBusy = false)))
.subscribe(({ success, ...tenant }) => {
if (!success) {
this.showError();
return;
}
this.setTenant({ ...tenant, isAvailable: true });
this.isModalVisible = false;
});
}
private setTenant(tenant: CurrentTenantDto) {
this.sessionState.setTenant(tenant);
this.appConfigService.get().subscribe(res => this.configState.setState(res));
}
private showError() {
this.toasterService.error('AbpUiMultiTenancy::GivenTenantIsNotAvailable', 'AbpUi::Error', {
messageLocalizationParams: [this.name],
});
}
}

11
npm/ng-packs/packages/account/src/lib/enums/components.ts

@ -0,0 +1,11 @@
export const enum eAccountComponents {
Login = 'Account.LoginComponent',
Register = 'Account.RegisterComponent',
ForgotPassword = 'Account.ForgotPasswordComponent',
ResetPassword = 'Account.ResetPasswordComponent',
ManageProfile = 'Account.ManageProfileComponent',
TenantBox = 'Account.TenantBoxComponent',
AuthWrapper = 'Account.AuthWrapperComponent',
ChangePassword = 'Account.ChangePasswordComponent',
PersonalSettings = 'Account.PersonalSettingsComponent',
}

1
npm/ng-packs/packages/account/src/lib/enums/index.ts

@ -0,0 +1 @@
export * from './components';

15
npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts

@ -0,0 +1,15 @@
import { AuthService } from '@abp/ng.core';
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
@Injectable()
export class AuthenticationFlowGuard implements CanActivate {
constructor(private authService: AuthService) {}
canActivate() {
if (this.authService.isInternalAuth) return true;
this.authService.initLogin();
return false;
}
}

1
npm/ng-packs/packages/account/src/lib/guards/index.ts

@ -0,0 +1 @@
export * from './authentication-flow.guard';

12
npm/ng-packs/packages/account/src/lib/models/account.ts

@ -0,0 +1,12 @@
import { TemplateRef } from '@angular/core';
export namespace Account {
//tslint:disable
export interface TenantBoxComponentInputs {}
export interface TenantBoxComponentOutputs {}
export interface PersonalSettingsComponentInputs {}
export interface PersonalSettingsComponentOutputs {}
export interface ChangePasswordComponentInputs {}
export interface ChangePasswordComponentOutputs {}
// tslint:enable
}

2
npm/ng-packs/packages/account/src/lib/models/index.ts

@ -0,0 +1,2 @@
export * from './account';
export * from './options';

3
npm/ng-packs/packages/account/src/lib/models/options.ts

@ -0,0 +1,3 @@
export interface Options {
redirectUrl?: string;
}

55
npm/ng-packs/packages/account/src/lib/services/authentication.service.ts

@ -0,0 +1,55 @@
import { Inject, Injectable, Optional } from '@angular/core';
import {
AbpApplicationConfigurationService,
ConfigStateService,
RestService,
SessionStateService,
} from '@abp/ng.core';
import { from, Observable } from 'rxjs';
import { OAuthService } from 'angular-oauth2-oidc';
import { HttpHeaders } from '@angular/common/http';
import { switchMap, take, tap } from 'rxjs/operators';
import { ACCOUNT_OPTIONS } from '../tokens/options.token';
import { Options } from '../models/options';
import snq from 'snq';
import { Router } from '@angular/router';
import { SessionHandler } from '@abp/ng.account/config';
@Injectable()
export class AuthenticationService {
constructor(
protected rest: RestService,
protected sessionState: SessionStateService,
protected oAuthService: OAuthService,
protected appConfigService: AbpApplicationConfigurationService,
protected configState: ConfigStateService,
@Inject(ACCOUNT_OPTIONS) protected options: Options,
protected router: Router,
@Optional() protected sessionHandler: SessionHandler,
) {}
login(username: string, password: string, remember = false): Observable<any> {
const tenant = this.sessionState.getTenant();
return from(
this.oAuthService.fetchTokenUsingPasswordFlow(
username,
password,
new HttpHeaders({ ...(tenant && tenant.id && { __tenant: tenant.id }) }),
),
).pipe(
switchMap(() => this.appConfigService.get()),
tap(res => {
this.configState.setState(res);
const redirectUrl =
snq(() => window.history.state.redirectUrl) || (this.options || {}).redirectUrl || '/';
this.router.navigate([redirectUrl]);
if (this.sessionHandler) this.sessionHandler.setRememberInfo(remember);
}),
take(1),
);
}
}

2
npm/ng-packs/packages/account/src/lib/services/index.ts

@ -0,0 +1,2 @@
export * from './authentication.service';
export * from './manage-profile.state.service';

28
npm/ng-packs/packages/account/src/lib/services/manage-profile.state.service.ts

@ -0,0 +1,28 @@
import { Injectable } from '@angular/core';
import { InternalStore, Profile } from '@abp/ng.core';
import { Observable } from 'rxjs';
export interface ManageProfileState {
profile: Profile.Response;
}
@Injectable({ providedIn: 'root' })
export class ManageProfileStateService {
private readonly store = new InternalStore({} as ManageProfileState);
get createOnUpdateStream() {
return this.store.sliceUpdate;
}
getProfile$(): Observable<Profile.Response> {
return this.store.sliceState(state => state.profile);
}
getProfile(): Profile.Response {
return this.store.state.profile;
}
setProfile(profile: Profile.Response) {
this.store.patch({ profile });
}
}

1
npm/ng-packs/packages/account/src/lib/tokens/index.ts

@ -0,0 +1 @@
export * from './options.token';

4
npm/ng-packs/packages/account/src/lib/tokens/options.token.ts

@ -0,0 +1,4 @@
import { InjectionToken } from '@angular/core';
import { Options } from '../models/options';
export const ACCOUNT_OPTIONS = new InjectionToken<Options>('ACCOUNT_OPTIONS');

8
npm/ng-packs/packages/account/src/lib/utils/factory-utils.ts

@ -0,0 +1,8 @@
import { Options } from '../models/options';
export function accountOptionsFactory(options: Options) {
return {
redirectUrl: '/',
...options,
};
}

1
npm/ng-packs/packages/account/src/lib/utils/index.ts

@ -0,0 +1 @@
export * from './factory-utils';

9
npm/ng-packs/packages/account/src/public-api.ts

@ -0,0 +1,9 @@
export * from './lib/account.module';
export * from './lib/components';
export * from './lib/enums';
export * from './lib/guards';
export * from './lib/models';
export * from './lib/services';
export * from './lib/tokens';
export * from './lib/proxy/account';
export * from './lib/proxy/identity';

19
npm/ng-packs/packages/account/tsconfig.lib.json

@ -0,0 +1,19 @@
{
"extends": "../../tsconfig.prod.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"target": "es2015",
"declaration": true,
"inlineSources": true,
"types": [],
"lib": ["dom", "es2018"]
},
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true,
"enableResourceInlining": true
},
"exclude": ["src/test.ts", "**/*.spec.ts"]
}

6
npm/ng-packs/packages/account/tsconfig.lib.prod.json

@ -0,0 +1,6 @@
{
"extends": "./tsconfig.lib.json",
"angularCompilerOptions": {
"enableIvy": false
}
}

11
npm/ng-packs/packages/account/tsconfig.spec.json

@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.prod.json",
"compilerOptions": {
"emitDecoratorMetadata": true,
"esModuleInterop": true,
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": ["**/*.spec.ts", "**/*.d.ts"]
}

17
npm/ng-packs/packages/account/tslint.json

@ -0,0 +1,17 @@
{
"extends": "../../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"abp",
"camelCase"
],
"component-selector": [
true,
"element",
"abp",
"kebab-case"
]
}
}

2
npm/ng-packs/tsconfig.json

@ -22,6 +22,8 @@
"@abp/ng.theme.shared/extensions": ["packages/theme-shared/extensions/src/public-api.ts"],
"@abp/ng.components/tree": ["packages/components/tree/src/public-api.ts"],
"@abp/ng.theme.basic": ["packages/theme-basic/src/public-api.ts"],
"@abp/ng.account": ["packages/account/src/public-api.ts"],
"@abp/ng.account/config": ["packages/account/config/src/public-api.ts"],
"@abp/ng.identity": ["packages/identity/src/public-api.ts"],
"@abp/ng.identity/config": ["packages/identity/config/src/public-api.ts"],
"@abp/ng.tenant-management": ["packages/tenant-management/src/public-api.ts"],

Loading…
Cancel
Save