mirror of https://github.com/abpframework/abp
parent
70308947b6
commit
57cd025ba5
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
export class FindTenantResultDto {
|
||||||
|
success: boolean;
|
||||||
|
tenantId?: string;
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
constructor(initialValues: Partial<FindTenantResultDto> = {}) {
|
||||||
|
if (initialValues) {
|
||||||
|
for (const key in initialValues) {
|
||||||
|
if (initialValues.hasOwnProperty(key)) {
|
||||||
|
this[key] = initialValues[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,156 @@
|
|||||||
|
class ExtractionResult {
|
||||||
|
public isMatch: boolean;
|
||||||
|
public matches: any[];
|
||||||
|
|
||||||
|
constructor(isMatch: boolean) {
|
||||||
|
this.isMatch = isMatch;
|
||||||
|
this.matches = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FormatStringTokenType {
|
||||||
|
ConstantText,
|
||||||
|
DynamicValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
class FormatStringToken {
|
||||||
|
public text: string;
|
||||||
|
public type: FormatStringTokenType;
|
||||||
|
|
||||||
|
constructor(text: string, type: FormatStringTokenType) {
|
||||||
|
this.text = text;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FormatStringTokenizer {
|
||||||
|
tokenize(format: string, includeBracketsForDynamicValues: boolean = false): FormatStringToken[] {
|
||||||
|
const tokens: FormatStringToken[] = [];
|
||||||
|
|
||||||
|
let currentText = '';
|
||||||
|
let inDynamicValue = false;
|
||||||
|
|
||||||
|
for (let i = 0; i < format.length; i++) {
|
||||||
|
const c = format[i];
|
||||||
|
switch (c) {
|
||||||
|
case '{':
|
||||||
|
if (inDynamicValue) {
|
||||||
|
throw new Error(
|
||||||
|
'Incorrect syntax at char ' +
|
||||||
|
i +
|
||||||
|
'! format string can not contain nested dynamic value expression!',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inDynamicValue = true;
|
||||||
|
|
||||||
|
if (currentText.length > 0) {
|
||||||
|
tokens.push(new FormatStringToken(currentText, FormatStringTokenType.ConstantText));
|
||||||
|
currentText = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case '}':
|
||||||
|
if (!inDynamicValue) {
|
||||||
|
throw new Error(
|
||||||
|
'Incorrect syntax at char ' +
|
||||||
|
i +
|
||||||
|
'! These is no opening brackets for the closing bracket }.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inDynamicValue = false;
|
||||||
|
|
||||||
|
if (currentText.length <= 0) {
|
||||||
|
throw new Error(
|
||||||
|
'Incorrect syntax at char ' + i + '! Brackets does not containt any chars.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let dynamicValue = currentText;
|
||||||
|
if (includeBracketsForDynamicValues) {
|
||||||
|
dynamicValue = '{' + dynamicValue + '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens.push(new FormatStringToken(dynamicValue, FormatStringTokenType.DynamicValue));
|
||||||
|
currentText = '';
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
currentText += c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inDynamicValue) {
|
||||||
|
throw new Error('There is no closing } char for an opened { char.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentText.length > 0) {
|
||||||
|
tokens.push(new FormatStringToken(currentText, FormatStringTokenType.ConstantText));
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FormattedStringValueExtractor {
|
||||||
|
extract(str: string, format: string): ExtractionResult {
|
||||||
|
if (str === format) {
|
||||||
|
return new ExtractionResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatTokens = new FormatStringTokenizer().tokenize(format);
|
||||||
|
if (!formatTokens) {
|
||||||
|
return new ExtractionResult(str === '');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = new ExtractionResult(true);
|
||||||
|
|
||||||
|
for (let i = 0; i < formatTokens.length; i++) {
|
||||||
|
const currentToken = formatTokens[i];
|
||||||
|
const previousToken = i > 0 ? formatTokens[i - 1] : null;
|
||||||
|
|
||||||
|
if (currentToken.type === FormatStringTokenType.ConstantText) {
|
||||||
|
if (i === 0) {
|
||||||
|
if (str.indexOf(currentToken.text) !== 0) {
|
||||||
|
result.isMatch = false;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = str.substr(currentToken.text.length, str.length - currentToken.text.length);
|
||||||
|
} else {
|
||||||
|
const matchIndex = str.indexOf(currentToken.text);
|
||||||
|
if (matchIndex < 0) {
|
||||||
|
result.isMatch = false;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.matches.push({ name: previousToken.text, value: str.substr(0, matchIndex) });
|
||||||
|
str = str.substring(0, matchIndex + currentToken.text.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastToken = formatTokens[formatTokens.length - 1];
|
||||||
|
if (lastToken.type === FormatStringTokenType.DynamicValue) {
|
||||||
|
result.matches.push({ name: lastToken.text, value: str });
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
isMatch(str: string, format: string): string[] {
|
||||||
|
const result = new FormattedStringValueExtractor().extract(str, format);
|
||||||
|
if (!result.isMatch) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const values = [];
|
||||||
|
for (let i = 0; i < result.matches.length; i++) {
|
||||||
|
values.push(result.matches[i].value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
import { Injector } from '@angular/core';
|
||||||
|
import { Store } from '@ngxs/store';
|
||||||
|
import { ConfigState } from '../states/config.state';
|
||||||
|
import { Config } from '../models/config';
|
||||||
|
import { FormattedStringValueExtractor } from './formatted-string-value-extractor';
|
||||||
|
import { MultiTenancyService } from '../services/multi-tenancy.service';
|
||||||
|
import { tap, switchMap } from 'rxjs/operators';
|
||||||
|
import { SetTenant, SetEnvironment } from '../actions';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
|
const tenancyPlaceholder = '{TENANCY_NAME}';
|
||||||
|
|
||||||
|
export function getCurrentTenancyNameOrNull(appBaseUrl: string): string {
|
||||||
|
if (appBaseUrl.indexOf(tenancyPlaceholder) < 0) return null;
|
||||||
|
|
||||||
|
const currentRootAddress = document.location.href;
|
||||||
|
|
||||||
|
const formattedStringValueExtracter = new FormattedStringValueExtractor();
|
||||||
|
const values: any[] = formattedStringValueExtracter.isMatch(currentRootAddress, appBaseUrl);
|
||||||
|
if (!values.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return values[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function parseTenantFromUrl(injector: Injector) {
|
||||||
|
const store: Store = injector.get(Store);
|
||||||
|
const multiTenancyService = injector.get(MultiTenancyService);
|
||||||
|
const environment = store.selectSnapshot(ConfigState.getOne('environment')) as Config.Environment;
|
||||||
|
|
||||||
|
const { baseUrl = '' } = environment.application;
|
||||||
|
const tenancyName = getCurrentTenancyNameOrNull(baseUrl);
|
||||||
|
|
||||||
|
if (tenancyName) {
|
||||||
|
multiTenancyService.isTenantBoxVisible = false;
|
||||||
|
|
||||||
|
return setEnvironment(store, tenancyName)
|
||||||
|
.pipe(
|
||||||
|
switchMap(() => multiTenancyService.findTenantByName(tenancyName, { __tenant: '' })),
|
||||||
|
tap(res => {
|
||||||
|
if (!res.success) return;
|
||||||
|
const tenant = { id: res.tenantId, name: res.name };
|
||||||
|
multiTenancyService.domainTenant = tenant;
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.toPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setEnvironment(store: Store, tenancyName: string) {
|
||||||
|
const environment = store.selectSnapshot(ConfigState.getOne('environment')) as Config.Environment;
|
||||||
|
|
||||||
|
if (environment.application.baseUrl) {
|
||||||
|
environment.application.baseUrl = environment.application.baseUrl.replace(
|
||||||
|
tenancyPlaceholder,
|
||||||
|
tenancyName,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(environment.apis).forEach(api => {
|
||||||
|
Object.keys(environment.apis[api]).forEach(key => {
|
||||||
|
environment.apis[api][key] = environment.apis[api][key].replace(
|
||||||
|
tenancyPlaceholder,
|
||||||
|
tenancyName,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return store.dispatch(new SetEnvironment(environment));
|
||||||
|
}
|
||||||
Loading…
Reference in new issue