Browse Source

Merge pull request #7164 from abpframework/fix/7087

[Angular] Fixed the domain tenant resolver problems
pull/7167/head
Levent Arman Özak 6 years ago
committed by GitHub
parent
commit
4439a5ad2e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      docs/en/UI/Angular/Multi-Tenancy.md
  2. 67
      npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts
  3. 13
      npm/ng-packs/packages/core/src/lib/tests/multi-tenancy-utils.spec.ts
  4. 7
      npm/ng-packs/packages/core/src/lib/utils/multi-tenancy-utils.ts
  5. 5
      npm/ng-packs/packages/theme-shared/src/lib/components/index.ts

10
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;
<p style="font-size:small;text-align:center;">Tenant Switching Component</p>
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:

67
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<any>;
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<ABP.Route>;
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<ABP.Route>;
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() {

13
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',

7
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,

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

Loading…
Cancel
Save