ToolJet/server/data-migrations/1669054493160-moveDataSourceOptionsToEnvironment.ts
vjaris42 bb9a211e55
[Feature] :: Global datasources (#5504)
* 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>
2023-03-24 21:41:21 +05:30

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> {}
}