Browse Source

Merge pull request #4995 from abpframework/feat/volo-2917

Implemented "Authorization Code Grant with PKCE" for the Angular UI
pull/4791/head
Mehmet Erim 6 years ago
committed by GitHub
parent
commit
a0d17cc7cc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      npm/ng-packs/apps/dev-app/src/app/home/home.component.html
  2. 7
      npm/ng-packs/apps/dev-app/src/app/home/home.component.ts
  3. 11
      npm/ng-packs/apps/dev-app/src/environments/environment.prod.ts
  4. 11
      npm/ng-packs/apps/dev-app/src/environments/environment.ts
  5. 4
      npm/ng-packs/package.json
  6. 3
      npm/ng-packs/packages/account/src/lib/account-routing.module.ts
  7. 2
      npm/ng-packs/packages/account/src/lib/account.module.ts
  8. 15
      npm/ng-packs/packages/account/src/lib/guards/authentication-flow.guard.ts
  9. 1
      npm/ng-packs/packages/account/src/lib/guards/index.ts
  10. 3
      npm/ng-packs/packages/account/src/public-api.ts
  11. 2
      npm/ng-packs/packages/core/package.json
  12. 2
      npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts
  13. 70
      npm/ng-packs/packages/core/src/lib/services/auth.service.ts
  14. 108
      npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts
  15. 1
      npm/ng-packs/packages/core/src/lib/strategies/index.ts
  16. 3
      npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts
  17. 2
      npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts
  18. 9
      npm/ng-packs/packages/identity/src/lib/identity-routing.module.ts
  19. 2
      npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts
  20. 2
      npm/ng-packs/packages/theme-shared/package.json
  21. 90
      npm/ng-packs/yarn.lock
  22. 8
      templates/app/angular/src/app/home/home.component.html
  23. 7
      templates/app/angular/src/app/home/home.component.ts
  24. 14
      templates/app/angular/src/environments/environment.prod.ts
  25. 15
      templates/app/angular/src/environments/environment.ts

7
npm/ng-packs/apps/dev-app/src/app/home/home.component.html

@ -8,12 +8,7 @@
</div>
</div>
<a href="https://abp.io?ref=tmpl" target="_blank" class="btn btn-primary px-4">abp.io</a>
<a
*ngIf="!hasLoggedIn"
routerLink="/account/login"
[state]="{ redirectUrl: '/' }"
class="px-4 btn btn-primary ml-1"
role="button"
<a *ngIf="!hasLoggedIn" (click)="login()" class="px-4 btn btn-primary ml-1" role="button"
><i class="fa fa-sign-in"></i> {{ 'AbpIdentity::Login' | abpLocalization }}</a
>
</div>

7
npm/ng-packs/apps/dev-app/src/app/home/home.component.ts

@ -1,3 +1,4 @@
import { AuthService } from '@abp/ng.core';
import { Component } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
@ -10,5 +11,9 @@ export class HomeComponent {
return this.oAuthService.hasValidAccessToken();
}
constructor(private oAuthService: OAuthService) {}
constructor(private oAuthService: OAuthService, private authService: AuthService) {}
login() {
this.authService.initLogin();
}
}

11
npm/ng-packs/apps/dev-app/src/environments/environment.prod.ts

@ -1,20 +1,21 @@
import { Config } from '@abp/ng.core';
const baseUrl = 'http://localhost:4200';
export const environment = {
production: true,
hmr: false,
application: {
baseUrl: 'http://localhost:4200/',
baseUrl,
name: 'MyProjectName',
logoUrl: '',
},
oAuthConfig: {
issuer: 'https://localhost:44305',
redirectUri: baseUrl,
clientId: 'MyProjectName_App',
dummyClientSecret: '1q2w3e*',
scope: 'MyProjectName',
oidc: false,
requireHttps: true,
responseType: 'code',
scope: 'offline_access MyProjectName',
},
apis: {
default: {

11
npm/ng-packs/apps/dev-app/src/environments/environment.ts

@ -1,20 +1,21 @@
import { Config } from '@abp/ng.core';
const baseUrl = 'http://localhost:4200';
export const environment = {
production: false,
hmr: false,
application: {
baseUrl: 'http://localhost:4200/',
baseUrl,
name: 'MyProjectName',
logoUrl: '',
},
oAuthConfig: {
issuer: 'https://localhost:44305',
redirectUri: baseUrl,
clientId: 'MyProjectName_App',
dummyClientSecret: '1q2w3e*',
scope: 'MyProjectName',
oidc: false,
requireHttps: true,
responseType: 'code',
scope: 'offline_access MyProjectName',
},
apis: {
default: {

4
npm/ng-packs/package.json

@ -51,7 +51,7 @@
"@fortawesome/fontawesome-free": "^5.13.0",
"@ng-bootstrap/ng-bootstrap": "^6.1.0",
"@ngneat/spectator": "^5.11.0",
"@ngx-validate/core": "^0.0.10",
"@ngx-validate/core": "^0.0.11",
"@ngxs/devtools-plugin": "^3.6.2",
"@ngxs/logger-plugin": "^3.6.2",
"@ngxs/router-plugin": "^3.6.2",
@ -60,7 +60,7 @@
"@swimlane/ngx-datatable": "^17.0.0",
"@types/jest": "^25.2.3",
"@types/node": "^12.11.1",
"angular-oauth2-oidc": "^9.2.2",
"angular-oauth2-oidc": "^10.0.3",
"bootstrap": "^4.5.0",
"chart.js": "^2.9.3",
"codelyzer": "^5.1.2",

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

@ -10,6 +10,7 @@ import { LoginComponent } from './components/login/login.component';
import { ManageProfileComponent } from './components/manage-profile/manage-profile.component';
import { RegisterComponent } from './components/register/register.component';
import { eAccountComponents } from './enums/components';
import { AuthenticationFlowGuard } from './guards/authentication-flow.guard';
const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'login' },
@ -20,6 +21,7 @@ const routes: Routes = [
{
path: 'login',
component: ReplaceableRouteContainerComponent,
canActivate: [AuthenticationFlowGuard],
data: {
replaceableComponent: {
key: eAccountComponents.Login,
@ -30,6 +32,7 @@ const routes: Routes = [
{
path: 'register',
component: ReplaceableRouteContainerComponent,
canActivate: [AuthenticationFlowGuard],
data: {
replaceableComponent: {
key: eAccountComponents.Register,

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

@ -14,6 +14,7 @@ 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';
@NgModule({
declarations: [
@ -39,6 +40,7 @@ export class AccountModule {
return {
ngModule: AccountModule,
providers: [
AuthenticationFlowGuard,
{ provide: ACCOUNT_OPTIONS, useValue: options },
{
provide: 'ACCOUNT_OPTIONS',

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';

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

@ -1,6 +1,7 @@
export * from './lib/account.module';
export * from './lib/components';
export * from './lib/enums';
export * from './lib/tokens';
export * from './lib/guards';
export * from './lib/models';
export * from './lib/services';
export * from './lib/tokens';

2
npm/ng-packs/packages/core/package.json

@ -12,7 +12,7 @@
"@ngxs/router-plugin": "^3.6.2",
"@ngxs/storage-plugin": "^3.6.2",
"@ngxs/store": "^3.6.2",
"angular-oauth2-oidc": "^9.2.2",
"angular-oauth2-oidc": "^10.0.0",
"just-clone": "^3.1.0",
"just-compare": "^1.3.0",
"snq": "^1.0.3",

2
npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts

@ -16,8 +16,6 @@ export class OAuthConfigurationHandler {
private oAuthService: OAuthService,
@Inject(CORE_OPTIONS) private options: ABP.Root,
) {
this.oAuthService.configure(this.options.environment.oAuthConfig);
this.listenToSetEnvironment();
}

70
npm/ng-packs/packages/core/src/lib/services/auth.service.ts

@ -1,26 +1,58 @@
import { HttpHeaders } from '@angular/common/http';
import { Inject, Injectable, Optional } from '@angular/core';
import { Inject, Injectable, Injector, Optional } from '@angular/core';
import { Navigate } from '@ngxs/router-plugin';
import { Store } from '@ngxs/store';
import { Actions, ofActionSuccessful, Store } from '@ngxs/store';
import { OAuthService } from 'angular-oauth2-oidc';
import { from, Observable } from 'rxjs';
import { switchMap, tap, take } from 'rxjs/operators';
import { switchMap, take, tap } from 'rxjs/operators';
import snq from 'snq';
import { GetAppConfiguration } from '../actions/config.actions';
import { GetAppConfiguration, SetEnvironment } from '../actions/config.actions';
import { ConfigState } from '../states/config.state';
import { SessionState } from '../states/session.state';
import { AuthFlowStrategy, AUTH_FLOW_STRATEGY } from '../strategies/auth-flow.strategy';
import { RestService } from './rest.service';
import { ConfigState } from '../states/config.state';
@Injectable({
providedIn: 'root',
})
export class AuthService {
private flow: string;
private strategy: AuthFlowStrategy;
get isInternalAuth() {
return this.strategy.isInternalAuth;
}
constructor(
private actions: Actions,
private injector: Injector,
private rest: RestService,
private oAuthService: OAuthService,
private store: Store,
@Optional() @Inject('ACCOUNT_OPTIONS') private options: any,
) {}
) {
this.setStrategy();
this.listenToSetEnvironment();
}
private setStrategy = () => {
const flow =
this.store.selectSnapshot(ConfigState.getDeep('environment.oAuthConfig.responseType')) ||
'password';
if (this.flow === flow) return;
if (this.strategy) this.strategy.destroy();
this.flow = flow;
this.strategy =
this.flow === 'code'
? AUTH_FLOW_STRATEGY.Code(this.injector)
: AUTH_FLOW_STRATEGY.Password(this.injector);
};
private listenToSetEnvironment() {
this.actions.pipe(ofActionSuccessful(SetEnvironment)).subscribe(this.setStrategy);
}
login(username: string, password: string): Observable<any> {
const tenant = this.store.selectSnapshot(SessionState.getTenant);
@ -45,23 +77,15 @@ export class AuthService {
);
}
logout(): Observable<void> {
const issuer = this.store.selectSnapshot(ConfigState.getDeep('environment.oAuthConfig.issuer'));
async init() {
return await this.strategy.init();
}
logout(): Observable<any> {
return this.strategy.logout();
}
return this.rest
.request(
{
method: 'GET',
url: '/api/account/logout',
},
null,
issuer,
)
.pipe(
switchMap(() => {
this.oAuthService.logOut(true);
return this.store.dispatch(new GetAppConfiguration());
}),
);
initLogin() {
this.strategy.login();
}
}

108
npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts

@ -0,0 +1,108 @@
import { Injector } from '@angular/core';
import { Store } from '@ngxs/store';
import { AuthConfig, OAuthService } from 'angular-oauth2-oidc';
import { ConfigState } from '../states/config.state';
import { CORE_OPTIONS } from '../tokens/options.token';
import { Router } from '@angular/router';
import { Observable, of } from 'rxjs';
import { RestService } from '../services/rest.service';
import { switchMap } from 'rxjs/operators';
import { GetAppConfiguration } from '../actions/config.actions';
export abstract class AuthFlowStrategy {
abstract readonly isInternalAuth: boolean;
protected oAuthService: OAuthService;
protected oAuthConfig: AuthConfig;
abstract checkIfInternalAuth(): boolean;
abstract login(): void;
abstract logout(): Observable<any>;
abstract destroy(): void;
private catchError = err => {
// TODO: handle the error
};
constructor(protected injector: Injector) {
this.oAuthService = injector.get(OAuthService);
this.oAuthConfig = injector.get(CORE_OPTIONS).environment.oAuthConfig;
}
async init(): Promise<any> {
this.oAuthService.configure(this.oAuthConfig);
return this.oAuthService.loadDiscoveryDocument().catch(this.catchError);
}
}
export class AuthCodeFlowStrategy extends AuthFlowStrategy {
readonly isInternalAuth = false;
async init() {
return super
.init()
.then(() => this.oAuthService.tryLogin())
.then(() => this.oAuthService.setupAutomaticSilentRefresh());
}
login() {
this.oAuthService.initCodeFlow();
}
checkIfInternalAuth() {
this.oAuthService.initCodeFlow();
return false;
}
logout() {
this.oAuthService.logOut();
return of(null);
}
destroy() {}
}
export class AuthPasswordFlowStrategy extends AuthFlowStrategy {
readonly isInternalAuth = true;
login() {
const router = this.injector.get(Router);
router.navigateByUrl('/account/login');
}
checkIfInternalAuth() {
return true;
}
logout() {
const store = this.injector.get(Store);
const rest = this.injector.get(RestService);
const issuer = store.selectSnapshot(ConfigState.getDeep('environment.oAuthConfig.issuer'));
return rest
.request(
{
method: 'GET',
url: '/api/account/logout',
},
null,
issuer,
)
.pipe(
switchMap(() => {
this.oAuthService.logOut();
return store.dispatch(new GetAppConfiguration());
}),
);
}
destroy() {}
}
export const AUTH_FLOW_STRATEGY = {
Code(injector: Injector) {
return new AuthCodeFlowStrategy(injector);
},
Password(injector: Injector) {
return new AuthPasswordFlowStrategy(injector);
},
};

1
npm/ng-packs/packages/core/src/lib/strategies/index.ts

@ -1,3 +1,4 @@
export * from './auth-flow.strategy';
export * from './container.strategy';
export * from './content-security.strategy';
export * from './content.strategy';

3
npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts

@ -6,8 +6,8 @@ import { of } from 'rxjs';
import { GetAppConfiguration } from '../actions';
import { CORE_OPTIONS } from '../tokens/options.token';
import { checkAccessToken, getInitialData, localeInitializer } from '../utils';
import * as multiTenancyUtils from '../utils/multi-tenancy-utils';
import * as environmentUtils from '../utils/environment-utils';
import * as multiTenancyUtils from '../utils/multi-tenancy-utils';
@Component({
selector: 'abp-dummy',
@ -40,6 +40,7 @@ describe('InitialUtils', () => {
injectorSpy.mockReturnValueOnce(store);
injectorSpy.mockReturnValueOnce({ skipGetAppConfiguration: false });
injectorSpy.mockReturnValueOnce({ init: () => null });
injectorSpy.mockReturnValueOnce({ hasValidAccessToken: () => false });
dispatchSpy.mockReturnValue(of('test'));

2
npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts

@ -5,6 +5,7 @@ import { OAuthService } from 'angular-oauth2-oidc';
import { tap } from 'rxjs/operators';
import { GetAppConfiguration } from '../actions/config.actions';
import { ABP } from '../models/common';
import { AuthService } from '../services/auth.service';
import { ConfigState } from '../states/config.state';
import { CORE_OPTIONS } from '../tokens/options.token';
import { getRemoteEnv } from './environment-utils';
@ -17,6 +18,7 @@ export function getInitialData(injector: Injector) {
await getRemoteEnv(injector, options.environment);
await parseTenantFromUrl(injector);
await injector.get(AuthService).init();
if (options.skipGetAppConfiguration) return;

9
npm/ng-packs/packages/identity/src/lib/identity-routing.module.ts

@ -2,12 +2,11 @@ import {
AuthGuard,
DynamicLayoutComponent,
PermissionGuard,
CoreModule,
ReplaceableRouteContainerComponent,
ReplaceableComponents,
ReplaceableRouteContainerComponent,
} from '@abp/ng.core';
import { NgModule, Type } from '@angular/core';
import { RouterModule, Routes, Router, ActivatedRoute } from '@angular/router';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { RolesComponent } from './components/roles/roles.component';
import { UsersComponent } from './components/users/users.component';
import { eIdentityComponents } from './enums/components';
@ -46,7 +45,7 @@ const routes: Routes = [
];
@NgModule({
imports: [RouterModule.forChild(routes), CoreModule],
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class IdentityRoutingModule {}

2
npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts

@ -1,4 +1,4 @@
import { ApplicationConfiguration, AuthService, ConfigState } from '@abp/ng.core';
import { ApplicationConfiguration, ConfigState, AuthService } from '@abp/ng.core';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Select } from '@ngxs/store';

2
npm/ng-packs/packages/theme-shared/package.json

@ -10,7 +10,7 @@
"@abp/ng.core": "~3.0.5",
"@fortawesome/fontawesome-free": "^5.13.1",
"@ng-bootstrap/ng-bootstrap": "^6.1.0",
"@ngx-validate/core": "^0.0.10",
"@ngx-validate/core": "^0.0.11",
"@swimlane/ngx-datatable": "^17.0.0",
"bootstrap": "^4.5.0",
"chart.js": "^2.9.3",

90
npm/ng-packs/yarn.lock

@ -715,9 +715,9 @@
js-tokens "^4.0.0"
"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.1", "@babel/parser@^7.8.3", "@babel/parser@^7.8.6", "@babel/parser@^7.9.6":
version "7.11.1"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.1.tgz#d91a387990b21e5d20047b336bb19b0553f02ff5"
integrity sha512-u9QMIRdKVF7hfEkb3nu2LgZDIzCQPv+yHD9Eg6ruoJLjkrQ9fFz4IBSlF/9XwoNri9+2F1IY+dYuOfZrXq8t3w==
version "7.11.2"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.2.tgz#0882ab8a455df3065ea2dcb4c753b2460a24bead"
integrity sha512-Vuj/+7vLo6l1Vi7uuO+1ngCDNeVmNbTngcJFKCR/oEtz8tKz0CJxZEGmPt9KcIloZhOZ3Zit6xbpXT2MDlS9Vw==
"@babel/plugin-proposal-async-generator-functions@^7.8.3":
version "7.10.5"
@ -1224,9 +1224,9 @@
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4":
version "7.11.1"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.1.tgz#087afc57e7bf1073e792fe54f8fb3cfa752f9230"
integrity sha512-nH5y8fLvVl3HAb+ezbgcgwrH8QbClWo8xzkOu7+oyqngo3EVorwpWJQaqXPjGRpfj7mQvsJCl/S8knkfkPWqrw==
version "7.11.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
dependencies:
regenerator-runtime "^0.13.4"
@ -2736,9 +2736,9 @@
integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==
"@types/node@^12.11.1":
version "12.12.53"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.53.tgz#be0d375933c3d15ef2380dafb3b0350ea7021129"
integrity sha512-51MYTDTyCziHb70wtGNFRwB4l+5JNvdqzFSkbDvpbftEgVUBEE+T5f7pROhWMp/fxp07oNIEQZd5bbfAH22ohQ==
version "12.12.54"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.54.tgz#a4b58d8df3a4677b6c08bfbc94b7ad7a7a5f82d1"
integrity sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w==
"@types/node@^8.0.31":
version "8.10.62"
@ -2814,9 +2814,9 @@
integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==
"@types/yargs@^13.0.0":
version "13.0.9"
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.9.tgz#44028e974343c7afcf3960f1a2b1099c39a7b5e1"
integrity sha512-xrvhZ4DZewMDhoH1utLtOAwYQy60eYFoXeje30TzM3VOvQlBwQaEpKFq5m34k1wOw2AKIi2pwtiAjdmhvlBUzg==
version "13.0.10"
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.10.tgz#e77bf3fc73c781d48c2eb541f87c453e321e5f4b"
integrity sha512-MU10TSgzNABgdzKvQVW1nuuT+sgBMWeXNc3XOs5YXV5SDAK+PPja2eUuBNB9iqElu03xyEDqlnGw0jgl4nbqGQ==
dependencies:
"@types/yargs-parser" "*"
@ -3120,6 +3120,13 @@ alphanum-sort@^1.0.0:
resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=
angular-oauth2-oidc@^10.0.3:
version "10.0.3"
resolved "https://registry.yarnpkg.com/angular-oauth2-oidc/-/angular-oauth2-oidc-10.0.3.tgz#612ef75c2e07b56592d2506f9618ee6a61857ad9"
integrity sha512-9wC8I3e3cN6rMBOlo5JB2y3Fd2erp8pJ67t4vEVzyPbnRG6BJ4rreSOznSL9zw/2SjhC9kRV2OfFie29CUCzEg==
dependencies:
tslib "^2.0.0"
angular-oauth2-oidc@^9.2.2:
version "9.2.2"
resolved "https://registry.yarnpkg.com/angular-oauth2-oidc/-/angular-oauth2-oidc-9.2.2.tgz#2b888337953a8773e0269b5ef1709f30316448f1"
@ -3678,9 +3685,9 @@ boolbase@^1.0.0, boolbase@~1.0.0:
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
bootstrap@^4.5.0:
version "4.5.1"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.1.tgz#f7322c7dd3e6376d430efc0c3f57e4d8005eb5b2"
integrity sha512-bxUooHBSbvefnIZfjD0LE8nfdPKrtiFy2sgrxQwUZ0UpFzpjVbVMUxaGIoo9XWT4B2LG1HX6UQg0UMOakT0prQ==
version "4.5.2"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.2.tgz#a85c4eda59155f0d71186b6e6ad9b875813779ab"
integrity sha512-vlGn0bcySYl/iV+BGA544JkkZP5LB3jsmkeKLFQakCOwCM3AOk7VkldBz4jrzSe+Z0Ezn99NVXa1o45cQY4R6A==
boxen@^4.2.0:
version "4.2.0"
@ -3806,14 +3813,14 @@ browserify-zlib@^0.2.0:
pako "~1.0.5"
browserslist@^4.0.0, browserslist@^4.11.1, browserslist@^4.12.0, browserslist@^4.7.0, browserslist@^4.8.5, browserslist@^4.9.1:
version "4.13.0"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.13.0.tgz#42556cba011e1b0a2775b611cba6a8eca18e940d"
integrity sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ==
version "4.14.0"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.0.tgz#2908951abfe4ec98737b72f34c3bcedc8d43b000"
integrity sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==
dependencies:
caniuse-lite "^1.0.30001093"
electron-to-chromium "^1.3.488"
escalade "^3.0.1"
node-releases "^1.1.58"
caniuse-lite "^1.0.30001111"
electron-to-chromium "^1.3.523"
escalade "^3.0.2"
node-releases "^1.1.60"
browserstack@^1.5.1:
version "1.6.0"
@ -4095,10 +4102,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001032, caniuse-lite@^1.0.30001061, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001109:
version "1.0.30001111"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001111.tgz#dd0ce822c70eb6c7c068e4a55c22e19ec1501298"
integrity sha512-xnDje2wchd/8mlJu8sXvWxOGvMgv+uT3iZ3bkIAynKOzToCssWCmkz/ZIkQBs/2pUB4uwnJKVORWQ31UkbVjOg==
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001032, caniuse-lite@^1.0.30001061, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001111:
version "1.0.30001112"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001112.tgz#0fffc3b934ff56ff0548c37bc9dad7d882bcf672"
integrity sha512-J05RTQlqsatidif/38aN3PGULCLrg8OYQOlJUKbeYVzC2mGZkZLIztwRlB3MtrfLmawUmjFlNJvy/uhwniIe1Q==
canonical-path@1.0.0:
version "1.0.0"
@ -4182,9 +4189,9 @@ chartjs-color@^2.1.0:
color-convert "^1.9.3"
"chokidar@>=2.0.0 <4.0.0", chokidar@^3.0.0, chokidar@^3.0.2, chokidar@^3.2.1, chokidar@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.1.tgz#e905bdecf10eaa0a0b1db0c664481cc4cbc22ba1"
integrity sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g==
version "3.4.2"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d"
integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==
dependencies:
anymatch "~3.1.1"
braces "~3.0.2"
@ -5675,10 +5682,10 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
electron-to-chromium@^1.3.488:
version "1.3.520"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.520.tgz#dfda0a14a4aed785cbddfdb505ea122f75978392"
integrity sha512-q6H9E1sXDCjRHP+X06vcP+N0ki8ZvYoRPZfKnDuiRX10WWXxEHzKFVf4O9rBFMpuPtR3M+2KAdJnugJoBBp3Rw==
electron-to-chromium@^1.3.523:
version "1.3.524"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.524.tgz#dd49646594466192de35956a5369bb20d616aa78"
integrity sha512-ZUvklIBkfXQyA6IeiEss1nfKRICcdB5afAGZAaPGaExdfrkpUu/WWVO+X7QpNnphaVMllXnAcvKnVPdyM+DCPQ==
elliptic@^6.5.3:
version "6.5.3"
@ -5848,7 +5855,7 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.3:
d "^1.0.1"
ext "^1.1.2"
escalade@^3.0.1:
escalade@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4"
integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==
@ -9565,7 +9572,7 @@ node-notifier@^6.0.0:
shellwords "^0.1.1"
which "^1.3.1"
node-releases@^1.1.58:
node-releases@^1.1.60:
version "1.1.60"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084"
integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==
@ -13092,16 +13099,16 @@ ts-pnp@^1.1.6:
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
ts-toolbelt@^6.9.9:
version "6.14.0"
resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.14.0.tgz#6f1082c5f59b39ff5d71ff427207bb92ffca4534"
integrity sha512-/EihMSk7AQn1n1zad6765tZNr7OCxAP75nS/VGzcZlWLlDa2izLJZV7SJSNDweSKusKuTDyHZhKFyUZW6UUnqg==
version "6.15.0"
resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.15.0.tgz#e1806c4904f5dc819d8dd2c48e09ccc60bfb742f"
integrity sha512-WuXbnXmVgzAGdruH7jbYf4j/0Y4anfMOD0KUU8iw6/4SbzdQVpfso4BJ1Z/t7hKLN2++gWYIseaw/ciyWKLreQ==
tsickle@^0.38.1:
version "0.38.1"
resolved "https://registry.yarnpkg.com/tsickle/-/tsickle-0.38.1.tgz#30762db759d40c435943093b6972c7f2efb384ef"
integrity sha512-4xZfvC6+etRu6ivKCNqMOd1FqcY/m6JY3Y+yr5+Xw+i751ciwrWINi6x/3l1ekcODH9GZhlf0ny2LpzWxnjWYA==
tslib@2.0.0, tslib@^2.0.0:
tslib@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3"
integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g==
@ -13111,6 +13118,11 @@ tslib@^1.10.0, tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
tslib@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==
tslint@~6.1.0:
version "6.1.3"
resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904"

8
templates/app/angular/src/app/home/home.component.html

@ -8,13 +8,7 @@
</div>
</div>
<a href="https://abp.io?ref=tmpl" target="_blank" class="btn btn-primary px-4">abp.io</a>
<a
*ngIf="!hasLoggedIn"
routerLink="/account/login"
[state]="{ redirectUrl: '/' }"
class="px-4 btn btn-primary ml-1"
role="button"
id="login-button"
<a *ngIf="!hasLoggedIn" (click)="login()" class="px-4 btn btn-primary ml-1" role="button"
><i class="fa fa-sign-in"></i> {{ 'AbpAccount::Login' | abpLocalization }}</a
>
</div>

7
templates/app/angular/src/app/home/home.component.ts

@ -1,3 +1,4 @@
import { AuthService } from '@abp/ng.core';
import { Component } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
@ -10,5 +11,9 @@ export class HomeComponent {
return this.oAuthService.hasValidAccessToken();
}
constructor(private oAuthService: OAuthService) {}
constructor(private oAuthService: OAuthService, private authService: AuthService) {}
login() {
this.authService.initLogin();
}
}

14
templates/app/angular/src/environments/environment.prod.ts

@ -1,26 +1,24 @@
import { Config } from '@abp/ng.core';
const baseUrl = 'http://localhost:4200';
export const environment = {
production: true,
application: {
baseUrl: 'http://localhost:4200/',
baseUrl,
name: 'MyProjectName',
logoUrl: '',
},
oAuthConfig: {
issuer: 'https://localhost:44305',
redirectUri: baseUrl,
clientId: 'MyProjectName_App',
dummyClientSecret: '1q2w3e*',
scope: 'MyProjectName',
oidc: false,
requireHttps: true,
responseType: 'code',
scope: 'offline_access MyProjectName',
},
apis: {
default: {
url: 'https://localhost:44305',
},
},
localization: {
defaultResourceName: 'MyProjectName',
},
} as Config.Environment;

15
templates/app/angular/src/environments/environment.ts

@ -1,27 +1,24 @@
import { Config } from '@abp/ng.core';
const baseUrl = 'http://localhost:4200';
export const environment = {
production: false,
application: {
baseUrl: 'http://localhost:4200/',
baseUrl,
name: 'MyProjectName',
logoUrl: '',
},
oAuthConfig: {
issuer: 'https://localhost:44305',
redirectUri: baseUrl,
clientId: 'MyProjectName_App',
dummyClientSecret: '1q2w3e*',
scope: 'MyProjectName',
showDebugInformation: true,
oidc: false,
requireHttps: true,
responseType: 'code',
scope: 'offline_access MyProjectName',
},
apis: {
default: {
url: 'https://localhost:44305',
},
},
localization: {
defaultResourceName: 'MyProjectName',
},
} as Config.Environment;

Loading…
Cancel
Save