From c3cd2c2f2f96d75bb35dbbe1ce10e1be23cc36ab Mon Sep 17 00:00:00 2001 From: Muhsin Shah Date: Thu, 27 Jun 2024 13:25:53 +0530 Subject: [PATCH] migrating code to new typeorm version --- server/.eslintrc.js | 2 + ...tValuesForExistingOrganizationConstants.ts | 2 +- ...bPrimaryKeyConstraintsForExistingTables.ts | 6 +-- server/ee/services/oauth/oauth.service.ts | 3 +- server/src/app.module.ts | 6 +-- server/src/controllers/apps.controller.ts | 2 +- .../controllers/data_queries.controller.ts | 2 +- server/src/entities/app.entity.ts | 20 --------- server/src/helpers/database.helper.ts | 43 +++++++++++++++++++ server/src/helpers/getconnection.ts | 11 +++++ server/src/helpers/queries.ts | 15 ++++--- server/src/helpers/utils.helper.ts | 25 +---------- .../modules/auth/active-workspace.guard.ts | 6 ++- .../modules/auth/authorize-workspace-guard.ts | 8 +++- server/src/repositories/comment.repository.ts | 3 +- server/src/repositories/thread.repository.ts | 3 +- server/src/schedulers/session.scheduler.ts | 2 +- .../src/services/app_environments.service.ts | 3 +- .../src/services/app_import_export.service.ts | 2 +- server/src/services/apps.service.ts | 8 ++-- server/src/services/auth.service.ts | 2 +- server/src/services/comment.service.ts | 13 ++++-- server/src/services/components.service.ts | 6 +-- server/src/services/credentials.service.ts | 7 +-- server/src/services/data_queries.service.ts | 2 +- server/src/services/data_sources.service.ts | 12 +++--- server/src/services/encryption.service.ts | 6 +-- server/src/services/events_handler.service.ts | 2 +- server/src/services/folders.service.ts | 28 ++++++------ .../src/services/group_permissions.service.ts | 18 ++++---- server/src/services/metadata.service.ts | 10 +++-- .../organization_constants.service.ts | 2 +- .../services/organization_users.service.ts | 11 +++-- server/src/services/organizations.service.ts | 22 +++++----- server/src/services/page.service.ts | 2 +- server/src/services/plugins.service.ts | 14 +++--- server/src/services/session.service.ts | 2 +- server/src/services/thread.service.ts | 7 +-- server/src/services/users.service.ts | 14 +++--- 39 files changed, 198 insertions(+), 154 deletions(-) create mode 100644 server/src/helpers/database.helper.ts create mode 100644 server/src/helpers/getconnection.ts diff --git a/server/.eslintrc.js b/server/.eslintrc.js index 67bbe3eb12..db55f124ac 100644 --- a/server/.eslintrc.js +++ b/server/.eslintrc.js @@ -9,6 +9,7 @@ module.exports = { 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', 'plugin:cypress/recommended', + "plugin:deprecation/recommended", ], ignorePatterns: ['.eslintrc.js'], parser: '@typescript-eslint/parser', @@ -55,5 +56,6 @@ module.exports = { extendDefaults: true, }, ], + "deprecation/deprecation": "error", }, }; diff --git a/server/data-migrations/1709618105785-EncryptValuesForExistingOrganizationConstants.ts b/server/data-migrations/1709618105785-EncryptValuesForExistingOrganizationConstants.ts index 21ae046b69..1a098b0136 100644 --- a/server/data-migrations/1709618105785-EncryptValuesForExistingOrganizationConstants.ts +++ b/server/data-migrations/1709618105785-EncryptValuesForExistingOrganizationConstants.ts @@ -1,6 +1,6 @@ import { EncryptionService } from '@services/encryption.service'; import { OrgEnvironmentConstantValue } from 'src/entities/org_environment_constant_values.entity'; -import { dbTransactionWrap } from 'src/helpers/utils.helper'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; import { EntityManager, MigrationInterface, QueryRunner } from 'typeorm'; export class EncryptValuesForExistingOrganizationConstants1709618105790 implements MigrationInterface { diff --git a/server/data-migrations/1715105945504-ReplaceTjDbPrimaryKeyConstraintsForExistingTables.ts b/server/data-migrations/1715105945504-ReplaceTjDbPrimaryKeyConstraintsForExistingTables.ts index 1a0b2ec7b2..2854760994 100644 --- a/server/data-migrations/1715105945504-ReplaceTjDbPrimaryKeyConstraintsForExistingTables.ts +++ b/server/data-migrations/1715105945504-ReplaceTjDbPrimaryKeyConstraintsForExistingTables.ts @@ -1,7 +1,6 @@ import { InternalTable } from 'src/entities/internal_table.entity'; import { MigrationProgress, processDataInBatches } from 'src/helpers/utils.helper'; -import { EntityManager, MigrationInterface, QueryRunner } from 'typeorm'; -import { createConnection } from 'typeorm'; +import { DataSource, EntityManager, MigrationInterface, QueryRunner } from 'typeorm'; import { tooljetDbOrmconfig } from 'ormconfig'; // With the new changes in TJDB for primary and foreign keys, we are using @@ -14,10 +13,11 @@ export class ReplaceTjDbPrimaryKeyConstraintsForExistingTables1715105945504 impl if (process.env.ENABLE_TOOLJET_DB !== 'true') return; const batchSize = 1000; const entityManager = queryRunner.manager; - const tooljetDbConnection = await createConnection({ + const tooljetDbConnection = new DataSource({ ...tooljetDbOrmconfig, name: 'tooljetDbMigration', } as any); + await tooljetDbConnection.initialize(); const tooljetDbManager = tooljetDbConnection.createEntityManager(); const totalTables = await entityManager.count(InternalTable); console.log(`Tables to migrate: ${totalTables}`); diff --git a/server/ee/services/oauth/oauth.service.ts b/server/ee/services/oauth/oauth.service.ts index fa3bf45435..7419938949 100644 --- a/server/ee/services/oauth/oauth.service.ts +++ b/server/ee/services/oauth/oauth.service.ts @@ -17,13 +17,14 @@ import { URL_SSO_SOURCE, WORKSPACE_USER_STATUS, } from 'src/helpers/user_lifecycle'; -import { dbTransactionWrap, generateInviteURL, generateNextNameAndSlug, isValidDomain } from 'src/helpers/utils.helper'; +import { generateInviteURL, generateNextNameAndSlug, isValidDomain } from 'src/helpers/utils.helper'; import { DeepPartial, EntityManager } from 'typeorm'; import { GitOAuthService } from './git_oauth.service'; import { GoogleOAuthService } from './google_oauth.service'; import UserResponse from './models/user_response'; import { Response } from 'express'; import { SIGNUP_ERRORS } from 'src/helpers/errors.constants'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; const uuid = require('uuid'); @Injectable() diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 528e7ff241..2fdd5de61c 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -1,6 +1,5 @@ import { Module, OnModuleInit, RequestMethod, MiddlewareConsumer } from '@nestjs/common'; -import { Connection } from 'typeorm'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ormconfig, tooljetDbOrmconfig } from '../ormconfig'; import { getEnvVars } from '../scripts/database-config-utils'; @@ -47,6 +46,7 @@ import { ScheduleModule } from '@nestjs/schedule'; import { ImportExportResourcesModule } from './modules/import_export_resources/import_export_resources.module'; import { MailerModule } from '@nestjs-modules/mailer'; import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter'; +import { GetConnection } from './helpers/getconnection'; const imports = [ ScheduleModule.forRoot(), @@ -172,10 +172,10 @@ if (process.env.ENABLE_TOOLJET_DB === 'true') { @Module({ imports, controllers: [AppController], - providers: [EmailService, SeedsService], + providers: [EmailService, SeedsService, GetConnection], }) export class AppModule implements OnModuleInit { - constructor(private connection: Connection) {} + constructor() {} configure(consumer: MiddlewareConsumer): void { consumer.apply(Sentry.Handlers.requestHandler()).forRoutes({ diff --git a/server/src/controllers/apps.controller.ts b/server/src/controllers/apps.controller.ts index 84b275e3ee..ac0ebe9478 100644 --- a/server/src/controllers/apps.controller.ts +++ b/server/src/controllers/apps.controller.ts @@ -25,7 +25,7 @@ import { AppUpdateDto } from '@dto/app-update.dto'; import { AppCreateDto } from '@dto/app-create.dto'; import { VersionCreateDto } from '@dto/version-create.dto'; import { VersionEditDto } from '@dto/version-edit.dto'; -import { dbTransactionWrap } from 'src/helpers/utils.helper'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; import { EntityManager } from 'typeorm'; import { ValidAppInterceptor } from 'src/interceptors/valid.app.interceptor'; import { AppDecorator } from 'src/decorators/app.decorator'; diff --git a/server/src/controllers/data_queries.controller.ts b/server/src/controllers/data_queries.controller.ts index 84f73bdeba..ad91fd18e2 100644 --- a/server/src/controllers/data_queries.controller.ts +++ b/server/src/controllers/data_queries.controller.ts @@ -22,7 +22,7 @@ import { AppsService } from '@services/apps.service'; import { CreateDataQueryDto, UpdateDataQueryDto, UpdatingReferencesOptionsDto } from '@dto/data-query.dto'; import { User } from 'src/decorators/user.decorator'; import { decode } from 'js-base64'; -import { dbTransactionWrap } from 'src/helpers/utils.helper'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; import { EntityManager } from 'typeorm'; import { DataSource } from 'src/entities/data_source.entity'; import { DataSourceScopes, DataSourceTypes } from 'src/helpers/data_source.constants'; diff --git a/server/src/entities/app.entity.ts b/server/src/entities/app.entity.ts index a6c42dcc4b..9a5d43d57f 100644 --- a/server/src/entities/app.entity.ts +++ b/server/src/entities/app.entity.ts @@ -1,9 +1,5 @@ import { Entity, - AfterLoad, - AfterInsert, - getRepository, - getManager, Column, CreateDateColumn, JoinColumn, @@ -80,20 +76,4 @@ export class App extends BaseEntity { appGroupPermissions: AppGroupPermission[]; public editingVersion; - - @AfterInsert() - async updateSlug(): Promise { - if (!this.slug) { - const appRepository = getRepository(App); - await appRepository.update(this.id, { slug: this.id }); - } - } - - @AfterLoad() - async afterLoad(): Promise { - this.editingVersion = await getManager().findOne(AppVersion, { - where: { appId: this.id }, - order: { updatedAt: 'DESC' }, - }); - } } diff --git a/server/src/helpers/database.helper.ts b/server/src/helpers/database.helper.ts new file mode 100644 index 0000000000..8f20b63169 --- /dev/null +++ b/server/src/helpers/database.helper.ts @@ -0,0 +1,43 @@ +import { GetConnection } from './getconnection'; +import { AppModule } from 'src/app.module'; +import { NestFactory } from '@nestjs/core'; +import { DataSource, EntityManager } from 'typeorm'; +import { updateTimestampForAppVersion } from './utils.helper'; + +let getConnectionInstance: GetConnection; +export const getGetConnectionInstance = async (): Promise => { + if (!getConnectionInstance) { + const app = await NestFactory.createApplicationContext(AppModule); + getConnectionInstance = app.get(GetConnection); + } + return getConnectionInstance; +}; + +export async function dbTransactionWrap(operation: (...args) => any, manager?: EntityManager): Promise { + if (manager) { + return await operation(manager); + } else { + const connection = await getGetConnectionInstance(); + const manager = connection.dataSource.manager; + return await manager.transaction(async (manager) => { + return await operation(manager); + }); + } +} + +export async function dbTransactionForAppVersionAssociationsUpdate( + operation: (...args) => any, + appVersionId: string +): Promise { + const connection = await getGetConnectionInstance(); + const manager = connection.dataSource.manager; + return await manager.transaction(async (manager) => { + const result = await operation(manager); + + await updateTimestampForAppVersion(manager, appVersionId); + + return result; + }); +} + +export const getManager = (dataSource: DataSource) => dataSource.manager; diff --git a/server/src/helpers/getconnection.ts b/server/src/helpers/getconnection.ts new file mode 100644 index 0000000000..2718a12579 --- /dev/null +++ b/server/src/helpers/getconnection.ts @@ -0,0 +1,11 @@ +import { Injectable } from '@nestjs/common'; +import { DataSource } from 'typeorm'; + +@Injectable() +export class GetConnection { + constructor(private _dataSource?: DataSource) {} + + get dataSource() { + return this._dataSource; + } +} diff --git a/server/src/helpers/queries.ts b/server/src/helpers/queries.ts index fb749d3a0d..5adc33a586 100644 --- a/server/src/helpers/queries.ts +++ b/server/src/helpers/queries.ts @@ -2,10 +2,12 @@ import { AppBase } from 'src/entities/app_base.entity'; import { Folder } from 'src/entities/folder.entity'; import { User } from 'src/entities/user.entity'; import { UserGroupPermission } from 'src/entities/user_group_permission.entity'; -import { Brackets, createQueryBuilder, SelectQueryBuilder } from 'typeorm'; +import { Brackets, SelectQueryBuilder } from 'typeorm'; +import { getGetConnectionInstance } from './database.helper'; -export function viewableAppsQuery(user: User, searchKey?: string, select?: Array): SelectQueryBuilder { - const viewableAppsQb = createQueryBuilder(AppBase, 'viewable_apps'); +export async function viewableAppsQuery(user: User, searchKey?: string, select?: Array): Promise> { + const connection = await getGetConnectionInstance(); + const viewableAppsQb = connection.dataSource.createQueryBuilder(AppBase, 'viewable_apps'); if (select) { viewableAppsQb.select(select.map((col) => `viewable_apps.${col}`)); @@ -47,12 +49,13 @@ export function viewableAppsQuery(user: User, searchKey?: string, select?: Array return viewableAppsQb; } -export function getFolderQuery( +export async function getFolderQuery( getAllFolders: boolean, allViewableAppIds: Array, organizationId: string -): SelectQueryBuilder { - const query = createQueryBuilder(Folder, 'folders'); +): Promise> { + const connection = await getGetConnectionInstance(); + const query = connection.dataSource.createQueryBuilder(Folder, 'folders'); if (getAllFolders) { query.leftJoinAndSelect('folders.folderApps', 'folder_apps', 'folder_apps.app_id IN(:...allViewableAppIds)', { allViewableAppIds: [null, ...allViewableAppIds], diff --git a/server/src/helpers/utils.helper.ts b/server/src/helpers/utils.helper.ts index 8f6dbc647d..a5ac07081a 100644 --- a/server/src/helpers/utils.helper.ts +++ b/server/src/helpers/utils.helper.ts @@ -1,6 +1,6 @@ import { QueryError } from 'src/modules/data_sources/query.errors'; import * as sanitizeHtml from 'sanitize-html'; -import { EntityManager, getManager } from 'typeorm'; +import { EntityManager } from 'typeorm'; import { isEmpty } from 'lodash'; import { ConflictException } from '@nestjs/common'; import { DataBaseConstraints } from './db_constraints.constants'; @@ -71,16 +71,6 @@ export function lowercaseString(value: string) { return value?.toLowerCase()?.trim(); } -export async function dbTransactionWrap(operation: (...args) => any, manager?: EntityManager): Promise { - if (manager) { - return await operation(manager); - } else { - return await getManager().transaction(async (manager) => { - return await operation(manager); - }); - } -} - export const updateTimestampForAppVersion = async (manager, appVersionId) => { const appVersion = await manager.findOne('app_versions', appVersionId); if (appVersion) { @@ -88,19 +78,6 @@ export const updateTimestampForAppVersion = async (manager, appVersionId) => { } }; -export async function dbTransactionForAppVersionAssociationsUpdate( - operation: (...args) => any, - appVersionId: string -): Promise { - return await getManager().transaction(async (manager) => { - const result = await operation(manager); - - await updateTimestampForAppVersion(manager, appVersionId); - - return result; - }); -} - type DbContraintAndMsg = { dbConstraint: DataBaseConstraints; message: string; diff --git a/server/src/modules/auth/active-workspace.guard.ts b/server/src/modules/auth/active-workspace.guard.ts index 7c37ecc05d..8dbddd5200 100644 --- a/server/src/modules/auth/active-workspace.guard.ts +++ b/server/src/modules/auth/active-workspace.guard.ts @@ -1,11 +1,13 @@ import { Injectable, ExecutionContext, BadRequestException, CanActivate } from '@nestjs/common'; import { isEmpty } from 'lodash'; -import { getManager } from 'typeorm'; import { OrganizationUser } from 'src/entities/organization_user.entity'; import { User } from 'src/entities/user.entity'; +import { DataSource } from 'typeorm'; @Injectable() export class ActiveWorkspaceGuard implements CanActivate { + constructor(private readonly _dataSource: DataSource) {} + async canActivate(context: ExecutionContext): Promise { const request = context.switchToHttp().getRequest(); @@ -13,7 +15,7 @@ export class ActiveWorkspaceGuard implements CanActivate { } private async validateUserActiveOnOrganization(user: User, organizationId: string) { - const organizationUser = await getManager().findOne(OrganizationUser, { + const organizationUser = await this._dataSource.manager.findOne(OrganizationUser, { where: { userId: user.id, organizationId }, select: ['id', 'status'], }); diff --git a/server/src/modules/auth/authorize-workspace-guard.ts b/server/src/modules/auth/authorize-workspace-guard.ts index 5f145d3215..a68f5ad53b 100644 --- a/server/src/modules/auth/authorize-workspace-guard.ts +++ b/server/src/modules/auth/authorize-workspace-guard.ts @@ -1,10 +1,14 @@ import { ExecutionContext, Injectable, NotFoundException } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { Organization } from 'src/entities/organization.entity'; -import { getManager } from 'typeorm'; +import { DataSource } from 'typeorm'; @Injectable() export class AuthorizeWorkspaceGuard extends AuthGuard('jwt') { + constructor(private readonly _dataSource: DataSource) { + super(); + } + async canActivate(context: ExecutionContext): Promise { const request = context.switchToHttp().getRequest(); if (request?.cookies['tj_auth_token']) { @@ -14,7 +18,7 @@ export class AuthorizeWorkspaceGuard extends AuthGuard('jwt') { ? request.headers['tj-workspace-id'][0] : request.headers['tj-workspace-id']; if (organizationId) { - const org = await getManager().findOne(Organization, { + const org = await this._dataSource.manager.findOne(Organization, { where: { id: organizationId }, select: ['id'], }); diff --git a/server/src/repositories/comment.repository.ts b/server/src/repositories/comment.repository.ts index 4f1330773f..14d283d60e 100644 --- a/server/src/repositories/comment.repository.ts +++ b/server/src/repositories/comment.repository.ts @@ -1,8 +1,7 @@ -import { Repository, EntityRepository } from 'typeorm'; +import { Repository } from 'typeorm'; import { Comment } from '../entities/comment.entity'; import { CreateCommentDto, UpdateCommentDto } from '../dto/comment.dto'; -@EntityRepository(Comment) export class CommentRepository extends Repository { public async createComment( createCommentDto: CreateCommentDto, diff --git a/server/src/repositories/thread.repository.ts b/server/src/repositories/thread.repository.ts index a2f76e8ee1..e40b2f998a 100644 --- a/server/src/repositories/thread.repository.ts +++ b/server/src/repositories/thread.repository.ts @@ -1,8 +1,7 @@ -import { Repository, EntityRepository } from 'typeorm'; +import { Repository } from 'typeorm'; import { Thread } from '../entities/thread.entity'; import { CreateThreadDto, UpdateThreadDto } from '../dto/thread.dto'; -@EntityRepository(Thread) export class ThreadRepository extends Repository { public async createThread(createThreadDto: CreateThreadDto, userId: string, organizationId: string): Promise { const { x, y, appId, appVersionsId, pageId } = createThreadDto; diff --git a/server/src/schedulers/session.scheduler.ts b/server/src/schedulers/session.scheduler.ts index 4eb2fe1371..e21a22f6ec 100644 --- a/server/src/schedulers/session.scheduler.ts +++ b/server/src/schedulers/session.scheduler.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { Cron, CronExpression } from '@nestjs/schedule'; import { UserSessions } from 'src/entities/user_sessions.entity'; -import { dbTransactionWrap } from 'src/helpers/utils.helper'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; import { EntityManager } from 'typeorm'; @Injectable() diff --git a/server/src/services/app_environments.service.ts b/server/src/services/app_environments.service.ts index c681c8c79c..786774daec 100644 --- a/server/src/services/app_environments.service.ts +++ b/server/src/services/app_environments.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; import { AppEnvironment } from 'src/entities/app_environments.entity'; -import { dbTransactionWrap, defaultAppEnvironments } from 'src/helpers/utils.helper'; +import { defaultAppEnvironments } from 'src/helpers/utils.helper'; import { DataSourceOptions } from 'src/entities/data_source_options.entity'; import { OrgEnvironmentConstantValue } from 'src/entities/org_environment_constant_values.entity'; import { OrganizationConstant } from 'src/entities/organization_constants.entity'; @@ -8,6 +8,7 @@ import { EntityManager, FindOneOptions, In, DeleteResult } from 'typeorm'; import { AppVersion } from 'src/entities/app_version.entity'; import { AppEnvironmentActionParametersDto } from '@dto/environment_action_parameters.dto'; import { App } from 'src/entities/app.entity'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; interface ExtendedEnvironment extends AppEnvironment { appVersionsCount?: number; diff --git a/server/src/services/app_import_export.service.ts b/server/src/services/app_import_export.service.ts index 3f95e64e71..4a2b9b5f5c 100644 --- a/server/src/services/app_import_export.service.ts +++ b/server/src/services/app_import_export.service.ts @@ -12,7 +12,6 @@ import { User } from 'src/entities/user.entity'; import { EntityManager, In } from 'typeorm'; import { DataSourcesService } from './data_sources.service'; import { - dbTransactionWrap, defaultAppEnvironments, catchDbException, extractMajorVersion, @@ -33,6 +32,7 @@ import { Layout } from 'src/entities/layout.entity'; import { EventHandler, Target } from 'src/entities/event_handler.entity'; import { v4 as uuid } from 'uuid'; import { findAllEntityReferences, isValidUUID, updateEntityReferences } from 'src/helpers/import_export.helpers'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; interface AppResourceMappings { defaultDataSourceIdMapping: Record; dataQueryMapping: Record; diff --git a/server/src/services/apps.service.ts b/server/src/services/apps.service.ts index f7df992734..c5fc99c549 100644 --- a/server/src/services/apps.service.ts +++ b/server/src/services/apps.service.ts @@ -12,7 +12,7 @@ import { AppGroupPermission } from 'src/entities/app_group_permission.entity'; import { AppImportExportService } from './app_import_export.service'; import { DataSourcesService } from './data_sources.service'; import { Credential } from 'src/entities/credential.entity'; -import { catchDbException, cleanObject, dbTransactionWrap, defaultAppEnvironments } from 'src/helpers/utils.helper'; +import { catchDbException, cleanObject, defaultAppEnvironments } from 'src/helpers/utils.helper'; import { AppUpdateDto } from '@dto/app-update.dto'; import { viewableAppsQuery } from 'src/helpers/queries'; import { VersionEditDto } from '@dto/version-edit.dto'; @@ -33,6 +33,7 @@ import { findAllEntityReferences, isValidUUID, updateEntityReferences } from 'sr import { isEmpty } from 'lodash'; import { AppBase } from 'src/entities/app_base.entity'; import { LayoutDimensionUnits } from 'src/helpers/components.helper'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; const uuid = require('uuid'); @@ -222,7 +223,8 @@ export class AppsService { } async count(user: User, searchKey): Promise { - return await viewableAppsQuery(user, searchKey).getCount(); + const query = await viewableAppsQuery(user, searchKey); + return await query.getCount(); } getAppVersionsCount = async (appId: string) => { @@ -232,7 +234,7 @@ export class AppsService { }; async all(user: User, page: number, searchKey: string): Promise { - const viewableAppsQb = viewableAppsQuery(user, searchKey); + const viewableAppsQb = await viewableAppsQuery(user, searchKey); if (page) { return await viewableAppsQb diff --git a/server/src/services/auth.service.ts b/server/src/services/auth.service.ts index 0704a3be63..394ecb99e5 100644 --- a/server/src/services/auth.service.ts +++ b/server/src/services/auth.service.ts @@ -23,7 +23,6 @@ import { OrganizationUser } from 'src/entities/organization_user.entity'; import { CreateAdminDto, CreateUserDto } from '@dto/user.dto'; import { AcceptInviteDto } from '@dto/accept-organization-invite.dto'; import { - dbTransactionWrap, fullName, generateInviteURL, generateNextNameAndSlug, @@ -48,6 +47,7 @@ import * as requestIp from 'request-ip'; import { ActivateAccountWithTokenDto } from '@dto/activate-account-with-token.dto'; import { AppAuthenticationDto, AppSignupDto } from '@dto/app-authentication.dto'; import { SIGNUP_ERRORS } from 'src/helpers/errors.constants'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; const bcrypt = require('bcrypt'); const uuid = require('uuid'); diff --git a/server/src/services/comment.service.ts b/server/src/services/comment.service.ts index b842dd1bbb..8955457ae7 100644 --- a/server/src/services/comment.service.ts +++ b/server/src/services/comment.service.ts @@ -6,7 +6,7 @@ import { CommentRepository } from '../repositories/comment.repository'; import { CreateCommentDto, UpdateCommentDto } from '../dto/comment.dto'; import { groupBy, head } from 'lodash'; import { EmailService } from './email.service'; -import { createQueryBuilder, Repository } from 'typeorm'; +import { DataSource, Repository } from 'typeorm'; import { AppVersion } from 'src/entities/app_version.entity'; import { User } from 'src/entities/user.entity'; import { CommentUsers } from 'src/entities/comment_user.entity'; @@ -22,7 +22,8 @@ export class CommentService { private usersRepository: Repository, @InjectRepository(CommentUsers) private commentUsersRepository: Repository, - private emailService: EmailService + private emailService: EmailService, + private readonly _dataSource: DataSource ) {} public async createComment(createCommentDto: CreateCommentDto, user: User): Promise { @@ -64,7 +65,9 @@ export class CommentService { } public async getComments(threadId: string, appVersionsId: string): Promise { - return await createQueryBuilder(Comment, 'comment') + return await + this._dataSource. + createQueryBuilder(Comment, 'comment') .innerJoin('comment.user', 'user') .addSelect(['user.id', 'user.firstName', 'user.lastName']) .andWhere('comment.threadId = :threadId', { @@ -96,7 +99,9 @@ export class CommentService { appVersionsId: string, pageId: string ): Promise { - const comments = await createQueryBuilder(Comment, 'comment') + const comments = await + this._dataSource. + createQueryBuilder(Comment, 'comment') .innerJoin('comment.user', 'user') .addSelect(['user.id', 'user.firstName', 'user.lastName']) .innerJoin('comment.thread', 'thread') diff --git a/server/src/services/components.service.ts b/server/src/services/components.service.ts index cee9c9e987..53c76626e2 100644 --- a/server/src/services/components.service.ts +++ b/server/src/services/components.service.ts @@ -1,10 +1,10 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { EntityManager, Repository } from 'typeorm'; +import { EntityManager, In, Repository } from 'typeorm'; import { Component } from 'src/entities/component.entity'; import { Layout } from 'src/entities/layout.entity'; import { Page } from 'src/entities/page.entity'; -import { dbTransactionForAppVersionAssociationsUpdate, dbTransactionWrap } from 'src/helpers/utils.helper'; +import { dbTransactionForAppVersionAssociationsUpdate, dbTransactionWrap } from 'src/helpers/database.helper'; import { LayoutDimensionUnits, resolveGridPositionForComponent } from 'src/helpers/components.helper'; import { EventsService } from './events_handler.service'; @@ -121,7 +121,7 @@ export class ComponentsService { async delete(componentIds: string[], appVersionId: string, isComponentCut = false) { return dbTransactionForAppVersionAssociationsUpdate(async (manager: EntityManager) => { - const components = await manager.findByIds(Component, componentIds); + const components = await manager.find(Component, { where: In(componentIds)}); if (!components.length) { return { diff --git a/server/src/services/credentials.service.ts b/server/src/services/credentials.service.ts index c83a260373..8171a1de81 100644 --- a/server/src/services/credentials.service.ts +++ b/server/src/services/credentials.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Credential } from '../../src/entities/credential.entity'; -import { getManager, Repository } from 'typeorm'; +import { DataSource, Repository } from 'typeorm'; import { EncryptionService } from './encryption.service'; @Injectable() @@ -9,10 +9,11 @@ export class CredentialsService { constructor( private encryptionService: EncryptionService, @InjectRepository(Credential) - private credentialsRepository: Repository + private credentialsRepository: Repository, + private readonly _dataSource: DataSource ) {} - async create(value: string, entityManager = getManager()): Promise { + async create(value: string, entityManager = this._dataSource.manager): Promise { const credentialRepository = entityManager.getRepository(Credential); const newCredential = credentialRepository.create({ valueCiphertext: await this.encryptionService.encryptColumnValue('credentials', 'value', value), diff --git a/server/src/services/data_queries.service.ts b/server/src/services/data_queries.service.ts index 6dc164a179..1b7b363883 100644 --- a/server/src/services/data_queries.service.ts +++ b/server/src/services/data_queries.service.ts @@ -13,7 +13,7 @@ import { OrgEnvironmentVariable } from 'src/entities/org_envirnoment_variable.en import { EncryptionService } from './encryption.service'; import { App } from 'src/entities/app.entity'; import { AppEnvironmentService } from './app_environments.service'; -import { dbTransactionWrap } from 'src/helpers/utils.helper'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; import allPlugins from '@tooljet/plugins/dist/server'; import { DataSourceScopes } from 'src/helpers/data_source.constants'; import { EventHandler } from 'src/entities/event_handler.entity'; diff --git a/server/src/services/data_sources.service.ts b/server/src/services/data_sources.service.ts index 6398de3eda..b67247fa0d 100644 --- a/server/src/services/data_sources.service.ts +++ b/server/src/services/data_sources.service.ts @@ -1,15 +1,16 @@ import { Injectable, NotAcceptableException, NotImplementedException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { EntityManager, getManager, Repository } from 'typeorm'; +import { EntityManager, Repository, DataSource as TypeORMDatasource } from 'typeorm'; import { DataSource } from '../../src/entities/data_source.entity'; import { CredentialsService } from './credentials.service'; -import { cleanObject, dbTransactionWrap } from 'src/helpers/utils.helper'; +import { cleanObject } from 'src/helpers/utils.helper'; import { PluginsHelper } from '../helpers/plugins.helper'; import { AppEnvironmentService } from './app_environments.service'; import { App } from 'src/entities/app.entity'; import { DataSourceScopes, DataSourceTypes } from 'src/helpers/data_source.constants'; import { EncryptionService } from './encryption.service'; import { OrgEnvironmentVariable } from '../entities/org_envirnoment_variable.entity'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; @Injectable() export class DataSourcesService { @@ -20,7 +21,8 @@ export class DataSourcesService { private appEnvironmentService: AppEnvironmentService, @InjectRepository(DataSource) - private dataSourcesRepository: Repository + private dataSourcesRepository: Repository, + private readonly _dataSource: TypeORMDatasource ) {} async all( @@ -385,7 +387,7 @@ export class DataSourcesService { return options; } - async parseOptionsForCreate(options: Array, resetSecureData = false, entityManager = getManager()) { + async parseOptionsForCreate(options: Array, resetSecureData = false, entityManager = this._dataSource.manager) { if (!options) return {}; const optionsWithOauth = await this.parseOptionsForOauthDataSource(options); @@ -413,7 +415,7 @@ export class DataSourcesService { return parsedOptions; } - async parseOptionsForUpdate(dataSource: DataSource, options: Array, entityManager = getManager()) { + async parseOptionsForUpdate(dataSource: DataSource, options: Array, entityManager = this._dataSource.manager) { if (!options) return {}; const optionsWithOauth = await this.parseOptionsForOauthDataSource(options); diff --git a/server/src/services/encryption.service.ts b/server/src/services/encryption.service.ts index 33a422d67e..b1bc2c7e1e 100644 --- a/server/src/services/encryption.service.ts +++ b/server/src/services/encryption.service.ts @@ -29,9 +29,9 @@ export class EncryptionService { const key = Buffer.from(derivedKey, 'hex'); let ciphertext = Buffer.from(cipherText, 'base64'); - const nonce = ciphertext.slice(0, 12); - const auth_tag = ciphertext.slice(-16); - ciphertext = ciphertext.slice(12, -16); + const nonce = ciphertext.subarray(0, 12); + const auth_tag = ciphertext.subarray(-16); + ciphertext = ciphertext.subarray(12, -16); const aesgcm = crypto.createDecipheriv('aes-256-gcm', key, nonce); aesgcm.setAuthTag(auth_tag); diff --git a/server/src/services/events_handler.service.ts b/server/src/services/events_handler.service.ts index be4216fbeb..5de2a3759b 100644 --- a/server/src/services/events_handler.service.ts +++ b/server/src/services/events_handler.service.ts @@ -2,7 +2,7 @@ import { BadRequestException, Injectable, NotFoundException } from '@nestjs/comm import { InjectRepository } from '@nestjs/typeorm'; import { EntityManager, Repository } from 'typeorm'; import { EventHandler } from 'src/entities/event_handler.entity'; -import { dbTransactionWrap, dbTransactionForAppVersionAssociationsUpdate } from 'src/helpers/utils.helper'; +import { dbTransactionWrap, dbTransactionForAppVersionAssociationsUpdate } from 'src/helpers/database.helper'; import { CreateEventHandlerDto, UpdateEvent } from '@dto/event-handler.dto'; @Injectable() diff --git a/server/src/services/folders.service.ts b/server/src/services/folders.service.ts index e7ed508d40..b24eb25000 100644 --- a/server/src/services/folders.service.ts +++ b/server/src/services/folders.service.ts @@ -4,7 +4,7 @@ import { App } from 'src/entities/app.entity'; import { FolderApp } from 'src/entities/folder_app.entity'; import { UserGroupPermission } from 'src/entities/user_group_permission.entity'; import { getFolderQuery, viewableAppsQuery } from 'src/helpers/queries'; -import { createQueryBuilder, Repository, UpdateResult } from 'typeorm'; +import { DataSource, Repository, UpdateResult } from 'typeorm'; import { User } from '../../src/entities/user.entity'; import { Folder } from '../entities/folder.entity'; import { UsersService } from './users.service'; @@ -21,7 +21,8 @@ export class FoldersService { private folderAppsRepository: Repository, @InjectRepository(App) private appsRepository: Repository, - private usersService: UsersService + private usersService: UsersService, + private readonly _dataSource: DataSource ) {} async create(user: User, folderName): Promise { @@ -44,17 +45,20 @@ export class FoldersService { } async allFolders(user: User, searchKey?: string): Promise { - const allViewableApps = await viewableAppsQuery(user, searchKey, ['id']).getMany(); + const allViewableAppsQuery = await viewableAppsQuery(user, searchKey, ['id']); + const allViewableApps = await allViewableAppsQuery.getMany(); const allViewableAppIds = allViewableApps.map((app) => app.id); if (await this.usersService.userCan(user, 'create', 'Folder')) { - return await getFolderQuery(true, allViewableAppIds, user.organizationId).distinct().getMany(); + const folderQuery = await getFolderQuery(true, allViewableAppIds, user.organizationId); + return await folderQuery.distinct().getMany(); } if (allViewableAppIds.length === 0) return []; - return await getFolderQuery(false, allViewableAppIds, user.organizationId).distinct().getMany(); + const folderQuery = await getFolderQuery(false, allViewableAppIds, user.organizationId); + return await folderQuery.distinct().getMany(); } async all(user: User, searchKey: string): Promise { @@ -91,11 +95,11 @@ export class FoldersService { return 0; } - const viewableAppsQb = viewableAppsQuery(user, searchKey); + const viewableAppsQb = await viewableAppsQuery(user, searchKey); - const folderAppsQb = createQueryBuilder(App, 'apps_in_folder').whereInIds(folderAppIds); + const folderAppsQb = this._dataSource.createQueryBuilder(App, 'apps_in_folder').whereInIds(folderAppIds); - return await createQueryBuilder(App, 'apps') + return await this._dataSource.createQueryBuilder(App, 'apps') .innerJoin( '(' + viewableAppsQb.getQuery() + ')', 'viewable_apps_join', @@ -126,11 +130,11 @@ export class FoldersService { return []; } - const viewableAppsQb = viewableAppsQuery(user, searchKey); + const viewableAppsQb = await viewableAppsQuery(user, searchKey); - const folderAppsQb = createQueryBuilder(App, 'apps_in_folder').whereInIds(folderAppIds); + const folderAppsQb = this._dataSource.createQueryBuilder(App, 'apps_in_folder').whereInIds(folderAppIds); - const viewableAppsInFolder = await createQueryBuilder(AppBase, 'apps') + const viewableAppsInFolder = await this._dataSource.createQueryBuilder(AppBase, 'apps') .innerJoin( '(' + viewableAppsQb.getQuery() + ')', 'viewable_apps_join', @@ -157,7 +161,7 @@ export class FoldersService { async delete(user: User, id: string) { const folder = await this.foldersRepository.findOneOrFail({ where: { id, organizationId: user.organizationId } }); - const allViewableApps = await createQueryBuilder(App, 'apps') + const allViewableApps = await this._dataSource.createQueryBuilder(App, 'apps') .select('apps.id') .innerJoin('apps.groupPermissions', 'group_permissions') .innerJoin('apps.appGroupPermissions', 'app_group_permissions') diff --git a/server/src/services/group_permissions.service.ts b/server/src/services/group_permissions.service.ts index 3f69b10f3b..dcf8e0bfdd 100644 --- a/server/src/services/group_permissions.service.ts +++ b/server/src/services/group_permissions.service.ts @@ -1,14 +1,15 @@ import { BadRequestException, ConflictException, Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { Repository, createQueryBuilder, In, Not, EntityManager, Brackets } from 'typeorm'; +import { Repository, In, Not, EntityManager, Brackets, DataSource } from 'typeorm'; import { User } from 'src/entities/user.entity'; import { GroupPermission } from 'src/entities/group_permission.entity'; import { App } from 'src/entities/app.entity'; import { AppGroupPermission } from 'src/entities/app_group_permission.entity'; import { UserGroupPermission } from 'src/entities/user_group_permission.entity'; import { UsersService } from './users.service'; -import { dbTransactionWrap, getMaxCopyNumber } from 'src/helpers/utils.helper'; +import { getMaxCopyNumber } from 'src/helpers/utils.helper'; import { DuplucateGroupDto } from '@dto/group-permission.dto'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; @Injectable() export class GroupPermissionsService { @@ -28,7 +29,8 @@ export class GroupPermissionsService { @InjectRepository(App) private appRepository: Repository, - private usersService: UsersService + private usersService: UsersService, + private readonly _dataSource: DataSource ) {} async create(user: User, group: string, manager?: EntityManager): Promise { @@ -281,7 +283,7 @@ export class GroupPermissionsService { if (!groupToDuplicate) throw new BadRequestException('Wrong group id'); - const existNameList = await createQueryBuilder() + const existNameList = await this._dataSource.createQueryBuilder() .select(['group_permissions.group', 'group_permissions.id']) .from(GroupPermission, 'group_permissions') .where('group_permissions.group ~* :pattern', { pattern: `^${groupToDuplicate.group}_copy_[0-9]+$` }) @@ -393,7 +395,7 @@ export class GroupPermissionsService { } async findApps(user: User, groupPermissionId: string): Promise { - return createQueryBuilder(App, 'apps') + return this._dataSource.createQueryBuilder(App, 'apps') .innerJoinAndSelect('apps.groupPermissions', 'group_permissions') .innerJoinAndSelect('apps.appGroupPermissions', 'app_group_permissions') .where('group_permissions.id = :groupPermissionId', { @@ -429,7 +431,7 @@ export class GroupPermissionsService { } async findUsers(user: User, groupPermissionId: string): Promise { - return createQueryBuilder(User, 'users') + return this._dataSource.createQueryBuilder(User, 'users') .select(['users.id', 'users.firstName', 'users.lastName', 'users.email']) .innerJoin('users.groupPermissions', 'group_permissions') .innerJoin('users.userGroupPermissions', 'user_group_permissions') @@ -455,7 +457,7 @@ export class GroupPermissionsService { const userInGroup = await groupPermission.users; const usersInGroupIds = userInGroup.map((u) => u.id); - const adminUsers = await createQueryBuilder(UserGroupPermission, 'user_group_permissions') + const adminUsers = await this._dataSource.createQueryBuilder(UserGroupPermission, 'user_group_permissions') .innerJoin( GroupPermission, 'group_permissions', @@ -484,7 +486,7 @@ export class GroupPermissionsService { }); }; - const builtQuery = createQueryBuilder(User, 'user') + const builtQuery = this._dataSource.createQueryBuilder(User, 'user') .select(['user.id', 'user.firstName', 'user.lastName', 'user.email']) .innerJoin( 'user.organizationUsers', diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index 2189646de8..79b5426d82 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { createQueryBuilder, EntityManager, getManager, In, Repository } from 'typeorm'; +import { EntityManager, In, Repository, DataSource as TypeORMDatasource } from 'typeorm'; import { Metadata } from 'src/entities/metadata.entity'; import { gt } from 'semver'; import got from 'got'; @@ -15,7 +15,9 @@ export class MetadataService { constructor( @InjectRepository(Metadata) private metadataRepository: Repository, - private configService: ConfigService + private configService: ConfigService, + private readonly _dataSource: TypeORMDatasource + ) {} async getMetaData() { @@ -80,7 +82,7 @@ export class MetadataService { } async sendTelemetryData(metadata: Metadata) { - const manager = getManager(); + const manager = this._dataSource.manager; const totalUserCount = await manager.count(User); const totalAppCount = await manager.count(App); const totalInternalTableCount = await manager.count(InternalTable); @@ -148,7 +150,7 @@ export class MetadataService { ).map((record) => record.id); const userIdsOfAppOwners = ( - await createQueryBuilder(User, 'users').innerJoin('users.apps', 'apps').select('users.id').distinct().getMany() + await this._dataSource.createQueryBuilder(User, 'users').innerJoin('users.apps', 'apps').select('users.id').distinct().getMany() ).map((record) => record.id); const totalEditorCount = await manager.count(User, { diff --git a/server/src/services/organization_constants.service.ts b/server/src/services/organization_constants.service.ts index ab49c597b4..d9761b8ea7 100644 --- a/server/src/services/organization_constants.service.ts +++ b/server/src/services/organization_constants.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { OrganizationConstant } from '../entities/organization_constants.entity'; -import { dbTransactionWrap } from 'src/helpers/utils.helper'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; import { EncryptionService } from './encryption.service'; import { AppEnvironmentService } from './app_environments.service'; diff --git a/server/src/services/organization_users.service.ts b/server/src/services/organization_users.service.ts index 2b4d987e7d..299c732298 100644 --- a/server/src/services/organization_users.service.ts +++ b/server/src/services/organization_users.service.ts @@ -1,15 +1,14 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { User } from '../entities/user.entity'; -import { createQueryBuilder, DeepPartial, EntityManager, getRepository, Repository } from 'typeorm'; +import { DataSource, DeepPartial, EntityManager, Repository } from 'typeorm'; import { UsersService } from 'src/services/users.service'; import { OrganizationUser } from 'src/entities/organization_user.entity'; import { BadRequestException } from '@nestjs/common'; import { EmailService } from './email.service'; import { Organization } from 'src/entities/organization.entity'; import { GroupPermission } from 'src/entities/group_permission.entity'; -import { ConfigService } from '@nestjs/config'; -import { dbTransactionWrap } from 'src/helpers/utils.helper'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; import { WORKSPACE_USER_STATUS } from 'src/helpers/user_lifecycle'; const uuid = require('uuid'); @@ -26,7 +25,7 @@ export class OrganizationUsersService { private organizationUsersRepository: Repository, private usersService: UsersService, private emailService: EmailService, - private configService: ConfigService + private readonly _dataSource: DataSource ) {} async create( @@ -69,7 +68,7 @@ export class OrganizationUsersService { } async findByWorkspaceInviteToken(invitationToken: string): Promise { - const organizationUser = await getRepository(OrganizationUser) + const organizationUser = await this._dataSource.getRepository(OrganizationUser) .createQueryBuilder('organizationUser') .select([ 'organizationUser.organizationId', @@ -227,7 +226,7 @@ export class OrganizationUsersService { } async activeAdminCount(organizationId: string) { - return await createQueryBuilder(GroupPermission, 'group_permissions') + return await this._dataSource.createQueryBuilder(GroupPermission, 'group_permissions') .innerJoin('group_permissions.userGroupPermission', 'user_group_permission') .where('group_permissions.group = :admin', { admin: 'admin' }) .andWhere('group_permissions.organization = :organizationId', { organizationId }) diff --git a/server/src/services/organizations.service.ts b/server/src/services/organizations.service.ts index d00418831f..02615602bc 100644 --- a/server/src/services/organizations.service.ts +++ b/server/src/services/organizations.service.ts @@ -8,12 +8,11 @@ import { User } from 'src/entities/user.entity'; import { catchDbException, cleanObject, - dbTransactionWrap, isPlural, fullName, generateNextNameAndSlug, } from 'src/helpers/utils.helper'; -import { Brackets, createQueryBuilder, DeepPartial, EntityManager, getManager, Repository } from 'typeorm'; +import { Brackets, DeepPartial, EntityManager, Repository, DataSource as TypeORMDatasource } from 'typeorm'; import { OrganizationUser } from '../entities/organization_user.entity'; import { EmailService } from './email.service'; import { EncryptionService } from './encryption.service'; @@ -39,6 +38,7 @@ import { DataSourceScopes, DataSourceTypes } from 'src/helpers/data_source.const import { DataSource } from 'src/entities/data_source.entity'; import { AppEnvironment } from 'src/entities/app_environments.entity'; import { DataSourceOptions } from 'src/entities/data_source_options.entity'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; const MAX_ROW_COUNT = 500; @@ -87,7 +87,8 @@ export class OrganizationsService { private appEnvironmentService: AppEnvironmentService, private encryptionService: EncryptionService, private emailService: EmailService, - private configService: ConfigService + private configService: ConfigService, + private readonly _dataSource: TypeORMDatasource ) {} async create(name: string, slug: string, user: User, manager?: EntityManager): Promise { @@ -175,7 +176,8 @@ export class OrganizationsService { } async getSingleOrganization(): Promise { - return await this.organizationsRepository.findOne({ relations: ['ssoConfigs'] }); + const responses = await this.organizationsRepository.find({ take: 1, relations: ['ssoConfigs'] }); + return responses[0]; } async createDefaultGroupPermissionsForOrganization(organization: Organization, manager?: EntityManager) { @@ -263,7 +265,7 @@ export class OrganizationsService { }); }); }; - const query = createQueryBuilder(OrganizationUser, 'organization_user') + const query = this._dataSource.createQueryBuilder(OrganizationUser, 'organization_user') .innerJoinAndSelect('organization_user.user', 'user') .innerJoinAndSelect( 'user.groupPermissions', @@ -315,7 +317,7 @@ export class OrganizationsService { } async fetchOrganizations(user: any): Promise { - return await createQueryBuilder(Organization, 'organization') + return await this._dataSource.createQueryBuilder(Organization, 'organization') .innerJoin( 'organization.organizationUsers', 'organization_users', @@ -338,7 +340,7 @@ export class OrganizationsService { ): Promise { const statusList = status ? (typeof status === 'object' ? status : [status]) : [WORKSPACE_USER_STATUS.ACTIVE]; - const query = createQueryBuilder(Organization, 'organization') + const query = this._dataSource.createQueryBuilder(Organization, 'organization') .innerJoin('organization.ssoConfigs', 'organization_sso', 'organization_sso.sso = :form', { form: 'form', }) @@ -372,7 +374,7 @@ export class OrganizationsService { } async getSSOConfigs(organizationId: string, sso: string): Promise { - return await createQueryBuilder(Organization, 'organization') + return await this._dataSource.createQueryBuilder(Organization, 'organization') .leftJoinAndSelect('organization.ssoConfigs', 'organisation_sso', 'organisation_sso.sso = :sso', { sso, }) @@ -383,7 +385,7 @@ export class OrganizationsService { } constructOrgFindQuery(slug: string, id: string, statusList?: Array) { - const query = createQueryBuilder(Organization, 'organization').leftJoinAndSelect( + const query = this._dataSource.createQueryBuilder(Organization, 'organization').leftJoinAndSelect( 'organization.ssoConfigs', 'organisation_sso', 'organisation_sso.enabled IN (:...statusList)', @@ -713,7 +715,7 @@ export class OrganizationsService { const invalidGroups = []; let isUserInOtherGroupsAndAdmin = false; const emailPattern = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i; - const manager = getManager(); + const manager = this._dataSource.manager; const groupPermissions = await this.groupPermissionService.findAll(currentUser); const existingGroups = groupPermissions.map((groupPermission) => groupPermission.group); diff --git a/server/src/services/page.service.ts b/server/src/services/page.service.ts index 304294f13a..b8618faf0f 100644 --- a/server/src/services/page.service.ts +++ b/server/src/services/page.service.ts @@ -6,7 +6,7 @@ import { Page } from 'src/entities/page.entity'; import { ComponentsService } from './components.service'; import { CreatePageDto, UpdatePageDto } from '@dto/pages.dto'; import { AppsService } from './apps.service'; -import { dbTransactionWrap, dbTransactionForAppVersionAssociationsUpdate } from 'src/helpers/utils.helper'; +import { dbTransactionWrap, dbTransactionForAppVersionAssociationsUpdate } from 'src/helpers/database.helper'; import { EventsService } from './events_handler.service'; import { Component } from 'src/entities/component.entity'; import { Layout } from 'src/entities/layout.entity'; diff --git a/server/src/services/plugins.service.ts b/server/src/services/plugins.service.ts index a3d0960e31..8f9bfea32b 100644 --- a/server/src/services/plugins.service.ts +++ b/server/src/services/plugins.service.ts @@ -2,7 +2,7 @@ import { Injectable, InternalServerErrorException, NotFoundException } from '@ne import { InjectRepository } from '@nestjs/typeorm'; import { File } from 'src/entities/file.entity'; import { Plugin } from 'src/entities/plugin.entity'; -import { Repository, Connection, EntityManager } from 'typeorm'; +import { Repository, EntityManager, DataSource } from 'typeorm'; import { CreateFileDto } from '../dto/create-file.dto'; import { CreatePluginDto } from '../dto/create-plugin.dto'; import { UpdatePluginDto } from '../dto/update-plugin.dto'; @@ -10,7 +10,7 @@ import { FilesService } from './files.service'; import { encode } from 'js-base64'; import { ConfigService } from '@nestjs/config'; import * as jszip from 'jszip'; -import { dbTransactionWrap } from 'src/helpers/utils.helper'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; import { UpdateFileDto } from '@dto/update-file.dto'; const jszipInstance = new jszip(); @@ -20,10 +20,10 @@ const fs = require('fs'); export class PluginsService { constructor( private readonly filesService: FilesService, - private connection: Connection, @InjectRepository(Plugin) private pluginsRepository: Repository, - private configService: ConfigService + private configService: ConfigService, + private readonly _dataSource: DataSource ) {} async create( createPluginDto: CreatePluginDto, @@ -35,7 +35,7 @@ export class PluginsService { manifest: ArrayBuffer; } ) { - const queryRunner = this.connection.createQueryRunner(); + const queryRunner = this._dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); @@ -85,7 +85,7 @@ export class PluginsService { manifest: ArrayBuffer; } ) { - const queryRunner = this.connection.createQueryRunner(); + const queryRunner = this._dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); @@ -265,7 +265,7 @@ export class PluginsService { } async reload(id: string) { - const queryRunner = this.connection.createQueryRunner(); + const queryRunner = this._dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); diff --git a/server/src/services/session.service.ts b/server/src/services/session.service.ts index 03fdb2a183..8f50bcae32 100644 --- a/server/src/services/session.service.ts +++ b/server/src/services/session.service.ts @@ -1,6 +1,6 @@ import { Injectable, UnauthorizedException } from '@nestjs/common'; import { EntityManager } from 'typeorm'; -import { dbTransactionWrap } from 'src/helpers/utils.helper'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; import { USER_STATUS } from 'src/helpers/user_lifecycle'; import { UserSessions } from 'src/entities/user_sessions.entity'; import { ConfigService } from '@nestjs/config'; diff --git a/server/src/services/thread.service.ts b/server/src/services/thread.service.ts index e469d1ac6c..9e7b0c27d1 100644 --- a/server/src/services/thread.service.ts +++ b/server/src/services/thread.service.ts @@ -3,13 +3,14 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Thread } from '../entities/thread.entity'; import { CreateThreadDto, UpdateThreadDto } from '../dto/thread.dto'; import { ThreadRepository } from '../repositories/thread.repository'; -import { createQueryBuilder } from 'typeorm'; +import { DataSource } from 'typeorm'; @Injectable() export class ThreadService { constructor( @InjectRepository(ThreadRepository) - private threadRepository: ThreadRepository + private threadRepository: ThreadRepository, + private readonly _dataSource: DataSource ) {} public async createThread(createThreadDto: CreateThreadDto, userId: string, orgId: string): Promise { @@ -23,7 +24,7 @@ export class ThreadService { appVersionsId: string, threadId?: string ): Promise { - const query = createQueryBuilder(Thread, 'thread') + const query = this._dataSource.createQueryBuilder(Thread, 'thread') .innerJoin('thread.user', 'user') .addSelect(['user.id', 'user.firstName', 'user.lastName']) .andWhere('thread.appId = :appId', { diff --git a/server/src/services/users.service.ts b/server/src/services/users.service.ts index 77ee6a5695..7700a6f386 100644 --- a/server/src/services/users.service.ts +++ b/server/src/services/users.service.ts @@ -3,12 +3,13 @@ import { InjectRepository } from '@nestjs/typeorm'; import { User } from '../entities/user.entity'; import { FilesService } from '../services/files.service'; import { App } from 'src/entities/app.entity'; -import { createQueryBuilder, EntityManager, getRepository, In, Repository } from 'typeorm'; +import { DataSource, EntityManager, In, Repository } from 'typeorm'; import { AppGroupPermission } from 'src/entities/app_group_permission.entity'; import { UserGroupPermission } from 'src/entities/user_group_permission.entity'; import { GroupPermission } from 'src/entities/group_permission.entity'; import { BadRequestException } from '@nestjs/common'; -import { cleanObject, dbTransactionWrap } from 'src/helpers/utils.helper'; +import { cleanObject } from 'src/helpers/utils.helper'; +import { dbTransactionWrap } from 'src/helpers/database.helper'; import { CreateFileDto } from '@dto/create-file.dto'; import { WORKSPACE_USER_STATUS } from 'src/helpers/user_lifecycle'; import { Organization } from 'src/entities/organization.entity'; @@ -24,7 +25,8 @@ export class UsersService { @InjectRepository(App) private appsRepository: Repository, @InjectRepository(Organization) - private organizationsRepository: Repository + private organizationsRepository: Repository, + private readonly _dataSource: DataSource ) {} async getCount(): Promise { @@ -231,7 +233,7 @@ export class UsersService { const removingAdmin = removeGroups.includes('admin'); if (!removingAdmin) return; - const result = await createQueryBuilder(User, 'users') + const result = await this._dataSource.createQueryBuilder(User, 'users') .innerJoin('users.groupPermissions', 'group_permissions') .innerJoin('users.organizationUsers', 'organization_users') .where('organization_users.user_id != :userId', { userId: user.id }) @@ -449,12 +451,12 @@ export class UsersService { const orgUserGroupPermissions = await this.userGroupPermissions(user, user.organizationId, manager); const groupIds = orgUserGroupPermissions.map((p) => p.groupPermissionId); - return await manager.findByIds(GroupPermission, groupIds); + return await manager.find(GroupPermission, { where: { id: In(groupIds) }}); }, manager); } async groupPermissionsForOrganization(organizationId: string) { - const groupPermissionRepository = getRepository(GroupPermission); + const groupPermissionRepository = this._dataSource.getRepository(GroupPermission); return await groupPermissionRepository.find({ where: {organizationId} }); }