From 6306126399a3e804d451514014663e3ca5fbefd6 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Mon, 11 Jan 2021 14:08:29 +0300 Subject: [PATCH 1/9] add info on authorization to Angular UI docs --- docs/en/UI/Angular/Authorization.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 docs/en/UI/Angular/Authorization.md diff --git a/docs/en/UI/Angular/Authorization.md b/docs/en/UI/Angular/Authorization.md new file mode 100644 index 00000000000..75d6107341a --- /dev/null +++ b/docs/en/UI/Angular/Authorization.md @@ -0,0 +1,28 @@ +# Authorization in Angular UI + +OAuth is preconfigured in Angular application templates. So, when you start a project using the CLI (or Suite, for that matter), authorization already works. You can find **OAuth configuration** in the _environment.ts_ files. + +```js +import { Config } from '@abp/ng.core'; + +const baseUrl = 'http://localhost:4200'; + +export const environment = { + // other options removed for sake of brevity + + oAuthConfig: { + issuer: 'https://localhost:44305', + redirectUri: baseUrl, + clientId: 'MyProjectName_App', + responseType: 'code', + scope: 'offline_access MyProjectName', + }, + + // other options removed for sake of brevity +} as Config.Environment; + +``` + +This configuration results in an [OAuth authorization code flow with PKCE](https://tools.ietf.org/html/rfc7636) and we are using [angular-oauth2-oidc library](https://github.com/manfredsteyer/angular-oauth2-oidc#logging-in) for managing OAuth in the Angular client. + +According to this flow, the user is redirected to an external login page which is built with MVC. So, if you need **to customize the login page**, please follow [this community article](https://community.abp.io/articles/how-to-customize-the-login-page-for-mvc-razor-page-applications-9a40f3cd). From 245f73db4cc20637023340d17b3946e79bee1c07 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Mon, 11 Jan 2021 14:09:48 +0300 Subject: [PATCH 2/9] add Angular UI authorization doc to nav --- docs/en/docs-nav.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index be24432203b..ec9d665373c 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -755,6 +755,10 @@ "text": "Config State Service", "path": "UI/Angular/Config-State-Service.md" }, + { + "text": "Authorization", + "path": "UI/Angular/Authorization.md" + }, { "text": "HTTP Requests", "path": "UI/Angular/HTTP-Requests.md" From 56f1e34328dd9116a65da8bb92c90e7dbd0d5156 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Mon, 11 Jan 2021 17:00:57 +0300 Subject: [PATCH 3/9] cli: fix nuget config api-key in for module-template --- .../Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs index 5e8db9a346d..ef8385d479f 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs @@ -75,7 +75,7 @@ private void RandomizeSslPorts(ProjectBuildContext context, List steps) { - steps.Add(new UpdateNuGetConfigStep("/NuGet.Config")); + steps.Add(new UpdateNuGetConfigStep("/aspnet-core/NuGet.Config")); } private void CleanupFolderHierarchy(ProjectBuildContext context, List steps) From 93fac338af641ae48ef9983103038807282ec4c4 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 12 Jan 2021 13:46:09 +0300 Subject: [PATCH 4/9] replace oAuthConfig.redirectUri if tenancyPlaceholder exists --- .../packages/core/src/lib/utils/multi-tenancy-utils.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/npm/ng-packs/packages/core/src/lib/utils/multi-tenancy-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/multi-tenancy-utils.ts index abfc33d723b..390a46db8e0 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/multi-tenancy-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/multi-tenancy-utils.ts @@ -58,6 +58,13 @@ function setEnvironment(injector: Injector, tenancyName: string) { ); } + if (environment.oAuthConfig.redirectUri) { + environment.oAuthConfig.redirectUri = environment.oAuthConfig.redirectUri.replace( + tenancyPlaceholder, + tenancyName, + ); + } + environment.oAuthConfig.issuer = environment.oAuthConfig.issuer.replace( tenancyPlaceholder, tenancyName, From 41f017cf877a53d06a4169047b7c8f288f88fcd1 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 12 Jan 2021 13:46:32 +0300 Subject: [PATCH 5/9] update Angular/Multi-Tenancy document --- docs/en/UI/Angular/Multi-Tenancy.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/en/UI/Angular/Multi-Tenancy.md b/docs/en/UI/Angular/Multi-Tenancy.md index e7e284bb0dd..7622db6de09 100644 --- a/docs/en/UI/Angular/Multi-Tenancy.md +++ b/docs/en/UI/Angular/Multi-Tenancy.md @@ -1,4 +1,4 @@ -# Multi Tenancy in Angular UI +# Multi-Tenancy in Angular UI ABP Angular UI supports the multi-tenancy. The following features related to multi-tenancy are available in the startup templates. @@ -8,7 +8,7 @@ ABP Angular UI supports the multi-tenancy. The following features related to mul On the page above, you can; -- See the all tenants. +- See all tenants. - Create a new tenant. - Edit an existing tenant. - Delete a tenant. @@ -17,9 +17,11 @@ On the page above, you can;

Tenant Switching Component

-You can switch between existing tenants by using the tenant switching component in the child pages of the `AccountLayoutComponent` (like Login page). Angular UI sends the selected tenant id to the backend as `__tenant` header on each request. +You can switch between existing tenants by using the tenant switching box in the child pages of the MVC Account Public Module (like Login page). Angular UI gets selected tenant from `application-configuration` response and sends the tenant id to the backend as `__tenant` header on each request. -## Domain Tenant Resolver +## Domain/Subdomain Tenant Resolver + +> **Note:** If you are going to implement the steps below, you should also implement the domain/subdomain tenant resolver feature for the backend. See the [Domain/Subdomain Tenant Resolver section in Multi-Tenancy document](../../Multi-Tenancy#domain-subdomain-tenant-resolver) to learn the backend implementation. Angular UI can get the tenant name from the app running URL. You can determine the current tenant by subdomain (like mytenant1.mydomain.com) or by the whole domain (like mytenant.com). To do this, you need to set the `application.baseUrl` property in the environment: From 48cc369c7ccfc9ba3b3b33653ff0a2457b39f9f3 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 12 Jan 2021 13:46:52 +0300 Subject: [PATCH 6/9] fix dynamic layout get component problem --- .../components/dynamic-layout.component.ts | 67 ++++++++++++------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts index 387437cc04d..87ad976491f 100644 --- a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts +++ b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts @@ -1,5 +1,6 @@ import { Component, Injector, Optional, SkipSelf, Type } from '@angular/core'; import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; +import { filter } from 'rxjs/operators'; import { eLayoutType } from '../enums/common'; import { ABP } from '../models'; import { ReplaceableComponents } from '../models/replaceable-components'; @@ -23,6 +24,7 @@ import { TreeNode } from '../utils/tree-utils'; }) export class DynamicLayoutComponent { layout: Type; + layoutKey: eLayoutType; // TODO: Consider a shared enum (eThemeSharedComponents) for known layouts readonly layouts = new Map([ @@ -33,6 +35,10 @@ export class DynamicLayoutComponent { isLayoutVisible = true; + private router: Router; + private route: ActivatedRoute; + private routes: RoutesService; + constructor( injector: Injector, private localizationService: LocalizationService, @@ -41,36 +47,45 @@ export class DynamicLayoutComponent { @Optional() @SkipSelf() dynamicLayoutComponent: DynamicLayoutComponent, ) { if (dynamicLayoutComponent) return; - const route = injector.get(ActivatedRoute); - const router = injector.get(Router); - const routes = injector.get(RoutesService); - - this.subscription.addOne(router.events, event => { - if (event instanceof NavigationEnd) { - let expectedLayout = (route.snapshot.data || {}).layout; - - if (!expectedLayout) { - let node = findRoute(routes, getRoutePath(router)); - node = { parent: node } as TreeNode; - - while (node.parent) { - node = node.parent; - - if (node.layout) { - expectedLayout = node.layout; - break; - } - } - } + this.route = injector.get(ActivatedRoute); + this.router = injector.get(Router); + this.routes = injector.get(RoutesService); + + this.getLayout(); + this.subscription.addOne( + this.router.events.pipe(filter(event => event instanceof NavigationEnd)), + () => { + this.getLayout(); + }, + ); + + this.listenToLanguageChange(); + } + + private getLayout() { + let expectedLayout = (this.route.snapshot.data || {}).layout; - if (!expectedLayout) expectedLayout = eLayoutType.empty; + if (!expectedLayout) { + let node = findRoute(this.routes, getRoutePath(this.router)); + node = { parent: node } as TreeNode; - const key = this.layouts.get(expectedLayout); - this.layout = this.getComponent(key)?.component; + while (node.parent) { + node = node.parent; + + if (node.layout) { + expectedLayout = node.layout; + break; + } } - }); + } - this.listenToLanguageChange(); + if (!expectedLayout) expectedLayout = eLayoutType.empty; + + if (this.layoutKey === expectedLayout) return; + + const key = this.layouts.get(expectedLayout); + this.layout = this.getComponent(key)?.component; + this.layoutKey = expectedLayout; } private listenToLanguageChange() { From 2b30db1b168bfd5f106b800e6198ba56f3cd94b7 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Tue, 12 Jan 2021 13:51:58 +0300 Subject: [PATCH 7/9] allow path binding source replacement with original case too --- npm/ng-packs/packages/schematics/src/models/method.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/schematics/src/models/method.ts b/npm/ng-packs/packages/schematics/src/models/method.ts index c2833a7bfda..7dca1668f52 100644 --- a/npm/ng-packs/packages/schematics/src/models/method.ts +++ b/npm/ng-packs/packages/schematics/src/models/method.ts @@ -54,7 +54,7 @@ export class Body { this.body = value; break; case eBindingSourceId.Path: - const regex = new RegExp('{' + camelName + '}', 'g'); + const regex = new RegExp('{(' + camelName + '|' + name + ')}', 'g'); this.url = this.url.replace(regex, '${' + value + '}'); break; default: From 9ddf7eab4e9e84895516fc957bf908e74e765fa0 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 12 Jan 2021 15:00:17 +0300 Subject: [PATCH 8/9] export http-wrapper.component --- .../packages/theme-shared/src/lib/components/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts index 3163d963a75..608dbb8ba84 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts @@ -2,11 +2,12 @@ export * from './breadcrumb/breadcrumb.component'; export * from './button/button.component'; export * from './chart/chart.component'; export * from './confirmation/confirmation.component'; -export * from './loading/loading.component'; +export * from './http-error-wrapper/http-error-wrapper.component'; export * from './loader-bar/loader-bar.component'; +export * from './loading/loading.component'; export * from './modal/modal.component'; export * from './sort-order-icon/sort-order-icon.component'; export * from './table-empty-message/table-empty-message.component'; export * from './table/table.component'; -export * from './toast/toast.component'; export * from './toast-container/toast-container.component'; +export * from './toast/toast.component'; From 005f58737d8601fe4c9cfd071edb338580a769ca Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 12 Jan 2021 15:11:05 +0300 Subject: [PATCH 9/9] update environment in multi-tenancy-utils.spec --- .../core/src/lib/tests/multi-tenancy-utils.spec.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/tests/multi-tenancy-utils.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/multi-tenancy-utils.spec.ts index 5af037b7d01..66188f0bb3a 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/multi-tenancy-utils.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/multi-tenancy-utils.spec.ts @@ -20,11 +20,10 @@ const environment = { }, oAuthConfig: { issuer: 'https://{0}.api.volosoft.com', + redirectUri: 'https://{0}.volosoft.com', clientId: 'MyProjectName_App', - dummyClientSecret: '1q2w3e*', - scope: 'MyProjectName', - oidc: false, - requireHttps: true, + responseType: 'code', + scope: 'offline_access MyProjectName', }, apis: { default: { @@ -91,7 +90,11 @@ describe('MultiTenancyUtils', () => { const replacedEnv = { ...environment, application: { ...environment.application, baseUrl: 'https://abp.volosoft.com' }, - oAuthConfig: { ...environment.oAuthConfig, issuer: 'https://abp.api.volosoft.com' }, + oAuthConfig: { + ...environment.oAuthConfig, + issuer: 'https://abp.api.volosoft.com', + redirectUri: 'https://abp.volosoft.com', + }, apis: { default: { url: 'https://abp.api.volosoft.com',