Skip to content

Commit

Permalink
Merge pull request #7170 from abpframework/auto-merge/rel-4-1/66
Browse files Browse the repository at this point in the history
Merge branch dev with rel-4.1
  • Loading branch information
armanozak authored Jan 12, 2021
2 parents fc98098 + 35ca3bb commit b9219f4
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 39 deletions.
28 changes: 28 additions & 0 deletions docs/en/UI/Angular/Authorization.md
Original file line number Diff line number Diff line change
@@ -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).
10 changes: 6 additions & 4 deletions docs/en/UI/Angular/Multi-Tenancy.md
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -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.
Expand All @@ -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:

Expand Down
4 changes: 4 additions & 0 deletions docs/en/docs-nav.json
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ private void RandomizeSslPorts(ProjectBuildContext context, List<ProjectBuildPip

private static void UpdateNuGetConfig(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
steps.Add(new UpdateNuGetConfigStep("/NuGet.Config"));
steps.Add(new UpdateNuGetConfigStep("/aspnet-core/NuGet.Config"));
}

private void CleanupFolderHierarchy(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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([
Expand All @@ -33,6 +35,10 @@ export class DynamicLayoutComponent {

isLayoutVisible = true;

private router: Router;
private route: ActivatedRoute;
private routes: RoutesService;

constructor(
injector: Injector,
private localizationService: LocalizationService,
Expand All @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -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',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion npm/ng-packs/packages/schematics/src/models/method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

0 comments on commit b9219f4

Please sign in to comment.