mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-24 09:28:31 +00:00
Add in-mem-cache setup to reuse auth code
This commit is contained in:
parent
d80b54143e
commit
09e0a94de1
3 changed files with 81 additions and 40 deletions
22
server/src/helpers/in_memory_cache.service.ts
Normal file
22
server/src/helpers/in_memory_cache.service.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class InMemoryCacheService {
|
||||
private static cacheStore: Map<string, Promise<any>> = new Map();
|
||||
|
||||
set(key: string, value: Promise<any>): void {
|
||||
InMemoryCacheService.cacheStore.set(key, value);
|
||||
}
|
||||
|
||||
get(key: string): Promise<any> | undefined {
|
||||
return InMemoryCacheService.cacheStore.get(key);
|
||||
}
|
||||
|
||||
has(key: string): boolean {
|
||||
return InMemoryCacheService.cacheStore.has(key);
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
InMemoryCacheService.cacheStore.clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import { AppsRepository } from '@modules/apps/repository';
|
|||
import { TooljetDbModule } from '@modules/tooljet-db/module';
|
||||
import { SessionModule } from '@modules/session/module';
|
||||
import { SampleDBScheduler } from './schedulers/sample-db.scheduler';
|
||||
import { InMemoryCacheService } from '@helpers/in_memory_cache.service';
|
||||
|
||||
export class DataSourcesModule {
|
||||
static async register(configs?: { IS_GET_CONTEXT: boolean }): Promise<DynamicModule> {
|
||||
|
|
@ -43,6 +44,7 @@ export class DataSourcesModule {
|
|||
SampleDataSourceService,
|
||||
FeatureAbilityFactory,
|
||||
SampleDBScheduler,
|
||||
InMemoryCacheService,
|
||||
],
|
||||
controllers: [DataSourcesController],
|
||||
exports: [DataSourcesUtilService, SampleDataSourceService, PluginsServiceSelector],
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import { PluginsServiceSelector } from './services/plugin-selector.service';
|
|||
import { OrganizationConstantsUtilService } from '@modules/organization-constants/util.service';
|
||||
import { DataSourceOptions } from '@entities/data_source_options.entity';
|
||||
import { IDataSourcesUtilService } from './interfaces/IUtilService';
|
||||
import { InMemoryCacheService } from '@helpers/in_memory_cache.service';
|
||||
|
||||
@Injectable()
|
||||
export class DataSourcesUtilService implements IDataSourcesUtilService {
|
||||
|
|
@ -31,7 +32,8 @@ export class DataSourcesUtilService implements IDataSourcesUtilService {
|
|||
protected readonly licenseTermsService: LicenseTermsService,
|
||||
protected readonly encryptionService: EncryptionService,
|
||||
protected readonly pluginsServiceSelector: PluginsServiceSelector,
|
||||
protected readonly organizationConstantsUtilService: OrganizationConstantsUtilService
|
||||
protected readonly organizationConstantsUtilService: OrganizationConstantsUtilService,
|
||||
protected readonly inMemoryCacheService: InMemoryCacheService
|
||||
) {}
|
||||
async create(createArgumentsDto: CreateArgumentsDto, user: User): Promise<DataSource> {
|
||||
return await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
|
|
@ -135,7 +137,17 @@ export class DataSourcesUtilService implements IDataSourcesUtilService {
|
|||
const queryService = await this.pluginsServiceSelector.getService(plugin_id, provider);
|
||||
|
||||
// const queryService = new allPlugins[provider]();
|
||||
const accessDetails = await queryService.accessDetailsFrom(authCode, options, resetSecureData);
|
||||
let accessDetailsPromise: Promise<any>;
|
||||
|
||||
const cacheKey = `${provider}_${authCode}`;
|
||||
|
||||
if (this.inMemoryCacheService.has(cacheKey)) {
|
||||
accessDetailsPromise = this.inMemoryCacheService.get(cacheKey);
|
||||
} else {
|
||||
accessDetailsPromise = queryService.accessDetailsFrom(authCode, options, resetSecureData);
|
||||
this.inMemoryCacheService.set(cacheKey, accessDetailsPromise);
|
||||
}
|
||||
const accessDetails = await accessDetailsPromise;
|
||||
|
||||
for (const row of accessDetails) {
|
||||
const option = {};
|
||||
|
|
@ -165,52 +177,56 @@ export class DataSourcesUtilService implements IDataSourcesUtilService {
|
|||
throw new BadRequestException('Cannot update configuration of sample data source');
|
||||
}
|
||||
|
||||
await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const isMultiEnvEnabled = await this.licenseTermsService.getLicenseTerms(LICENSE_FIELD.MULTI_ENVIRONMENT);
|
||||
const envToUpdate = await this.appEnvironmentUtilService.get(organizationId, environmentId, false, manager);
|
||||
try {
|
||||
await dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const isMultiEnvEnabled = await this.licenseTermsService.getLicenseTerms(LICENSE_FIELD.MULTI_ENVIRONMENT);
|
||||
const envToUpdate = await this.appEnvironmentUtilService.get(organizationId, environmentId, false, manager);
|
||||
|
||||
// if datasource is restapi then reset the token data
|
||||
if (dataSource.kind === 'restapi')
|
||||
options.push({
|
||||
key: 'tokenData',
|
||||
value: undefined,
|
||||
encrypted: false,
|
||||
});
|
||||
// if datasource is restapi then reset the token data
|
||||
if (dataSource.kind === 'restapi')
|
||||
options.push({
|
||||
key: 'tokenData',
|
||||
value: undefined,
|
||||
encrypted: false,
|
||||
});
|
||||
|
||||
if (isMultiEnvEnabled) {
|
||||
dataSource.options = (
|
||||
await this.appEnvironmentUtilService.getOptions(dataSourceId, organizationId, envToUpdate.id)
|
||||
).options;
|
||||
|
||||
const newOptions = await this.parseOptionsForUpdate(dataSource, options, manager);
|
||||
await this.appEnvironmentUtilService.updateOptions(newOptions, envToUpdate.id, dataSource.id, manager);
|
||||
} else {
|
||||
const allEnvs = await this.appEnvironmentUtilService.getAll(organizationId);
|
||||
/*
|
||||
Basic plan customer. lets update all environment options.
|
||||
this will help us to run the queries successfully when the user buys enterprise plan
|
||||
*/
|
||||
|
||||
const newOptions = await this.parseOptionsForUpdate(dataSource, options, manager);
|
||||
for (const env of allEnvs) {
|
||||
if (isMultiEnvEnabled) {
|
||||
dataSource.options = (
|
||||
await this.appEnvironmentUtilService.getOptions(dataSourceId, organizationId, env.id)
|
||||
await this.appEnvironmentUtilService.getOptions(dataSourceId, organizationId, envToUpdate.id)
|
||||
).options;
|
||||
|
||||
await this.appEnvironmentUtilService.updateOptions(newOptions, env.id, dataSource.id, manager);
|
||||
const newOptions = await this.parseOptionsForUpdate(dataSource, options, manager);
|
||||
await this.appEnvironmentUtilService.updateOptions(newOptions, envToUpdate.id, dataSource.id, manager);
|
||||
} else {
|
||||
const allEnvs = await this.appEnvironmentUtilService.getAll(organizationId);
|
||||
/*
|
||||
Basic plan customer. lets update all environment options.
|
||||
this will help us to run the queries successfully when the user buys enterprise plan
|
||||
*/
|
||||
|
||||
for (const env of allEnvs) {
|
||||
dataSource.options = (
|
||||
await this.appEnvironmentUtilService.getOptions(dataSourceId, organizationId, env.id)
|
||||
).options;
|
||||
const newOptions = await this.parseOptionsForUpdate(dataSource, options, manager);
|
||||
|
||||
await this.appEnvironmentUtilService.updateOptions(newOptions, env.id, dataSource.id, manager);
|
||||
}
|
||||
}
|
||||
}
|
||||
const updatableParams = {
|
||||
id: dataSourceId,
|
||||
name,
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
const updatableParams = {
|
||||
id: dataSourceId,
|
||||
name,
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
// Remove keys with undefined values
|
||||
cleanObject(updatableParams);
|
||||
// Remove keys with undefined values
|
||||
cleanObject(updatableParams);
|
||||
|
||||
await manager.save(DataSource, updatableParams);
|
||||
});
|
||||
await manager.save(DataSource, updatableParams);
|
||||
});
|
||||
} finally {
|
||||
this.inMemoryCacheService.clear();
|
||||
}
|
||||
}
|
||||
|
||||
async decrypt(options: Record<string, any>) {
|
||||
|
|
@ -612,6 +628,7 @@ export class DataSourcesUtilService implements IDataSourcesUtilService {
|
|||
|
||||
for (const key of Object.keys(options)) {
|
||||
const currentOption = options[key]?.['value'];
|
||||
constantMatcher.lastIndex = 0;
|
||||
|
||||
//! request options are nested arrays with constants and variables
|
||||
if (Array.isArray(currentOption)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue