mirror of
https://github.com/ToolJet/ToolJet
synced 2026-04-21 21:47:17 +00:00
* add: columns and migrations for data queries and sources * add: migrations for app environments * fix: datasources and queries api * fix: import apis * add: radixui colors * create: global datasource page * fix: version creation not including global datasources queries * fix: version deletion failure * fix: ui and other bugs * add: check for abilities on global ds * fix: bugs * fix: existing test cases * fix: migration and bugs * fix: rest api oauthorize bugs * hide: add button for local ds * fix: query bugs * fix: new organization environment creation * fix: local ds label showing for new apps * fix: on page load queries for preview app and published app * fix: import bugs from v1 * fix: merge conflicts * fix: import apis * fix: apss with mulit envs * fix: ui bugs * fix: environments not being created on db:seed * fix: ui bugs * fix: route settings for global datasources * fix: customer dashboard template * fix: local ds queries not being saved * fix: runpy issues * changes: ui * fix: migration issues * fix: ui * hide datasources when no local datasources * fix: test cases * fix: unit test cases and global queries on app import/export * cleanup * add: package-lock file * undo: migration rename * cleanup * fix: ui bugs * migration fixes * fix: dark mode issues * fix: change datasource failing on query create mode * fix: workspace selector issues * fix: clickoutside for change scope option * migration changes * fix: open api issue * reverting configs changes * [Fix] Global datasources & Environment Id issue (#5830) * fix: oauth env id issue * code changes --------- Co-authored-by: gsmithun4 <gsmithun4@gmail.com> Co-authored-by: Muhsin Shah <muhsinshah21@gmail.com>
114 lines
4 KiB
TypeScript
114 lines
4 KiB
TypeScript
import { AppEnvironment } from 'src/entities/app_environments.entity';
|
|
import { AppVersion } from 'src/entities/app_version.entity';
|
|
import { DataSourceOptions } from 'src/entities/data_source_options.entity';
|
|
import { EntityManager, MigrationInterface, QueryRunner } from 'typeorm';
|
|
import { defaultAppEnvironments } from 'src/helpers/utils.helper';
|
|
import { NestFactory } from '@nestjs/core';
|
|
import { AppModule } from 'src/app.module';
|
|
import { EncryptionService } from '@services/encryption.service';
|
|
import { Credential } from 'src/entities/credential.entity';
|
|
|
|
export class moveDataSourceOptionsToEnvironment1669054493160 implements MigrationInterface {
|
|
private nestApp;
|
|
|
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
// Create default environment for all apps
|
|
this.nestApp = await NestFactory.createApplicationContext(AppModule);
|
|
const entityManager = queryRunner.manager;
|
|
const appVersions = await entityManager.find(AppVersion);
|
|
if (appVersions?.length) {
|
|
for (const appVersion of appVersions) {
|
|
await this.associateDataQueriesAndSources(entityManager, appVersion);
|
|
}
|
|
}
|
|
}
|
|
|
|
private async associateDataQueriesAndSources(entityManager: EntityManager, appVersion: AppVersion) {
|
|
const encryptionService = this.nestApp.get(EncryptionService);
|
|
|
|
for (const { name, isDefault } of defaultAppEnvironments) {
|
|
const environment: AppEnvironment = await entityManager.query(
|
|
'insert into app_environments (name, is_default, app_version_id, created_at, updated_at) values ($1, $2, $3, $4, $4) returning *',
|
|
[name, isDefault, appVersion.id, new Date()]
|
|
);
|
|
// Get all data sources under app version
|
|
const dataSources = await entityManager.query('select * from data_sources where app_version_id = $1', [
|
|
appVersion.id,
|
|
]);
|
|
|
|
if (dataSources?.length) {
|
|
for (const dataSource of dataSources) {
|
|
const options = !environment.isDefault
|
|
? await this.filterEncryptedFromOptions(dataSource.options, encryptionService, entityManager)
|
|
: dataSource.options;
|
|
await entityManager.save(
|
|
entityManager.create(DataSourceOptions, {
|
|
dataSourceId: dataSource.id,
|
|
environmentId: environment.id,
|
|
options,
|
|
})
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private convertToArrayOfKeyValuePairs(options): Array<object> {
|
|
if (!options) return;
|
|
return Object.keys(options).map((key) => {
|
|
return {
|
|
key: key,
|
|
value: options[key]['value'],
|
|
encrypted: options[key]['encrypted'],
|
|
credential_id: options[key]['credential_id'],
|
|
};
|
|
});
|
|
}
|
|
|
|
private async filterEncryptedFromOptions(
|
|
options: Array<object>,
|
|
encryptionService: EncryptionService,
|
|
entityManager: EntityManager
|
|
) {
|
|
const kvOptions = this.convertToArrayOfKeyValuePairs(options);
|
|
|
|
if (!kvOptions) return;
|
|
|
|
const parsedOptions = {};
|
|
|
|
for (const option of kvOptions) {
|
|
if (option['encrypted']) {
|
|
const credential = await this.createCredential('', encryptionService, entityManager);
|
|
|
|
parsedOptions[option['key']] = {
|
|
credential_id: credential.id,
|
|
encrypted: option['encrypted'],
|
|
};
|
|
} else {
|
|
parsedOptions[option['key']] = {
|
|
value: option['value'],
|
|
encrypted: false,
|
|
};
|
|
}
|
|
}
|
|
|
|
return parsedOptions;
|
|
}
|
|
|
|
async createCredential(
|
|
value: string,
|
|
encryptionService: EncryptionService,
|
|
entityManager: EntityManager
|
|
): Promise<Credential> {
|
|
const credentialRepository = entityManager.getRepository(Credential);
|
|
const newCredential = credentialRepository.create({
|
|
valueCiphertext: await encryptionService.encryptColumnValue('credentials', 'value', value),
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
});
|
|
const credential = await credentialRepository.save(newCredential);
|
|
return credential;
|
|
}
|
|
|
|
public async down(queryRunner: QueryRunner): Promise<void> {}
|
|
}
|