fix workflow executions in modularistion (#12124)

This commit is contained in:
Akshay 2025-03-10 23:31:57 +05:30 committed by GitHub
parent ae3142dd4e
commit 528c354ed5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 102 additions and 17 deletions

View file

@ -7,7 +7,6 @@ import { getWorkspaceId, decodeEntities } from '@/_helpers/utils';
import { ButtonSolid } from '@/_ui/AppButton/AppButton';
import { useDataSources, useGlobalDataSources, useSampleDataSource } from '@/_stores/dataSourcesStore';
import { useDataQueriesActions } from '@/_stores/dataQueriesStore';
import { staticDataSources as staticDatasources } from '../constants';
import { useQueryPanelActions } from '@/_stores/queryPanelStore';
import Search from '@/_ui/Icon/solidIcons/Search';
import { Tooltip } from 'react-tooltip';
@ -16,7 +15,7 @@ import { canCreateDataSource } from '@/_helpers';
import './../queryManager.theme.scss';
import { DATA_SOURCE_TYPE } from '@/_helpers/constants';
function DataSourceSelect({ isDisabled, selectRef, closePopup, workflowDataSources, onNewNode, defaultDataSources }) {
function DataSourceSelect({ isDisabled, selectRef, closePopup, workflowDataSources, onNewNode, staticDataSources }) {
const dataSources = useDataSources();
const globalDataSources = useGlobalDataSources();
const sampleDataSource = useSampleDataSource();
@ -33,11 +32,6 @@ function DataSourceSelect({ isDisabled, selectRef, closePopup, workflowDataSourc
closePopup();
};
const workflowsEnabled = window.public_config?.ENABLE_WORKFLOWS_FEATURE == 'true';
const staticDataSources = workflowsEnabled
? staticDatasources
: staticDatasources.filter((ds) => ds?.kind !== 'workflows');
useEffect(() => {
const shouldAddSampleDataSource = !!sampleDataSource;
const allDataSources = [...dataSources, ...globalDataSources, shouldAddSampleDataSource && sampleDataSource].filter(
@ -148,7 +142,7 @@ function DataSourceSelect({ isDisabled, selectRef, closePopup, workflowDataSourc
</div>
),
isDisabled: true,
options: defaultDataSources?.map((source) => ({
options: staticDataSources?.map((source) => ({
label: (
<div>
<DataSourceIcon source={source} height={16} />{' '}

View file

@ -129,6 +129,7 @@ export const DATA_SOURCE_TYPE = {
LOCAL: 'local',
GLOBAL: 'global',
STATIC: 'static',
DEFAULT: 'default',
};
export const SAMPLE_DB_KIND = {

View file

@ -26,4 +26,17 @@ export class AppVersionUpdateDto {
@IsOptional()
pageSettings: any;
// Workflow related fields
@IsOptional()
@IsString()
@IsUUID()
currentEnvironmentId: string;
@IsOptional()
definition: any;
@IsOptional()
@IsBoolean()
is_user_switched_version: boolean;
}

View file

@ -1,6 +1,7 @@
import { sanitizeInput } from '@helpers/utils.helper';
import { IsString, IsOptional, IsNotEmpty, MaxLength, IsBoolean, IsUUID } from 'class-validator';
import { IsString, IsOptional, IsNotEmpty, MaxLength, IsBoolean, IsUUID, IsEnum } from 'class-validator';
import { Exclude, Expose, Transform } from 'class-transformer';
import { APP_TYPES } from '../constants';
export class AppCreateDto {
@IsNotEmpty()
@ -12,6 +13,11 @@ export class AppCreateDto {
@IsString()
@MaxLength(200, { message: 'Maximum length has been reached.' })
icon?: string;
@IsNotEmpty()
@IsString()
@IsEnum(APP_TYPES, { message: 'Invalid app type.' })
type: string;
}
export class AppUpdateDto {

View file

@ -60,9 +60,9 @@ export class AppsService implements IAppsService {
protected readonly aiUtilService: AiUtilService
) {}
async create(user: User, appCreateDto: AppCreateDto) {
const { name, icon } = appCreateDto;
const { name, icon, type } = appCreateDto;
return await dbTransactionWrap(async (manager: EntityManager) => {
const app = await this.appsUtilService.create(name, user, APP_TYPES.FRONT_END, manager);
const app = await this.appsUtilService.create(name, user, type, manager);
const appUpdateDto = new AppUpdateDto();
appUpdateDto.name = name;

View file

@ -11,7 +11,7 @@ import {
NotAcceptableException,
NotFoundException,
} from '@nestjs/common';
import { EntityManager, SelectQueryBuilder } from 'typeorm';
import { EntityManager, MoreThan, SelectQueryBuilder } from 'typeorm';
import { v4 as uuidv4 } from 'uuid';
import { AppsRepository } from './repository';
import { AppVersion } from '@entities/app_version.entity';
@ -36,6 +36,7 @@ import { AbilityService } from '@modules/ability/interfaces/IService';
import { DataSourcesRepository } from '@modules/data-sources/repository';
import { IAppsUtilService } from './interfaces/IUtilService';
import { DataSourcesUtilService } from '@modules/data-sources/util.service';
import { AppVersionUpdateDto } from '@dto/app-version-update.dto';
@Injectable()
export class AppsUtilService implements IAppsUtilService {
@ -281,6 +282,70 @@ export class AppsUtilService implements IAppsUtilService {
}, manager);
}
async updateWorflowVersion(version: AppVersion, body: AppVersionUpdateDto, app: App) {
const { name, currentEnvironmentId, definition } = body;
const { currentVersionId, organizationId } = app;
let currentEnvironment: AppEnvironment;
if (version.id === currentVersionId && !body?.is_user_switched_version)
throw new BadRequestException('You cannot update a released version');
if (currentEnvironmentId || definition) {
currentEnvironment = await AppEnvironment.findOne({
where: { id: version.currentEnvironmentId },
});
}
const editableParams = {};
if (name) {
//means user is trying to update the name
const versionNameExists = await this.versionRepository.findOne({
where: { name, appId: version.appId },
});
if (versionNameExists) {
throw new BadRequestException('Version name already exists.');
}
editableParams['name'] = name;
}
//check if the user is trying to promote the environment & raise an error if the currentEnvironmentId is not correct
if (currentEnvironmentId) {
if (!(await this.licenseTermsService.getLicenseTerms(LICENSE_FIELD.MULTI_ENVIRONMENT))) {
throw new BadRequestException('You do not have permissions to perform this action');
}
if (version.currentEnvironmentId !== currentEnvironmentId) {
throw new NotAcceptableException();
}
const nextEnvironment = await AppEnvironment.findOne({
select: ['id'],
where: {
priority: MoreThan(currentEnvironment.priority),
organizationId,
},
order: { priority: 'ASC' },
});
editableParams['currentEnvironmentId'] = nextEnvironment.id;
}
if (definition) {
const environments = await AppEnvironment.count({
where: {
organizationId,
},
});
if (environments > 1 && currentEnvironment.priority !== 1 && !body?.is_user_switched_version) {
throw new BadRequestException('You cannot update a promoted version');
}
editableParams['definition'] = definition;
}
editableParams['updatedAt'] = new Date();
return await this.versionRepository.update(version.id, editableParams);
}
protected async getEnvironmentOfVersion(versionId: string, manager: EntityManager): Promise<AppEnvironment> {
return manager
.createQueryBuilder(AppEnvironment, 'app_environments')

View file

@ -191,11 +191,12 @@ export class DataQueriesService implements IDataQueriesService {
async changeQueryDataSource(user: User, queryId: string, dataSource: DataSource, newDataSourceId: string) {
return dbTransactionWrap(async (manager: EntityManager) => {
const newDataSource = await this.dataSourceRepository.findOne({ where: { id: newDataSourceId } });
if (dataSource.kind !== newDataSource.kind) {
throw new BadRequestException();
}
return this.dataQueryRepository.updateOne(queryId, { dataSourceId: newDataSourceId }, manager);
const newDataSource = await this.dataSourceRepository.findOneOrFail({ where: { id: newDataSourceId } });
// FIXME: Disabling this check as workflows can change data source of a query with different kind
// if (dataSource.kind !== newDataSource.kind && dataSource) {
// throw new BadRequestException();
// }
return this.dataQueryRepository.updateOne(queryId, { dataSourceId: newDataSource.id }, manager);
// TODO: Audit logs
});

View file

@ -175,6 +175,10 @@ export class VersionService implements IVersionService {
await this.versionsUtilService.updateVersion(appVersion, appVersionUpdateDto);
if (app.type === 'workflow') {
await this.appUtilService.updateWorflowVersion(appVersion, appVersionUpdateDto, app);
}
this.eventEmitter.emit('auditLogEntry', {
userId: user.id,
organizationId: user.organizationId,

View file

@ -98,6 +98,7 @@ export class WorkflowsModule {
UserRepository,
DataSourcesRepository,
DataQueryRepository,
DataSourcesRepository,
OrganizationConstantRepository,
VersionRepository,
AppsService,