diff --git a/docker-compose.yml b/docker-compose.yml index 3c55754132b..827c906a327 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: activepieces: - image: ghcr.io/activepieces/activepieces:0.77.1 + image: ghcr.io/activepieces/activepieces:0.77.2 container_name: activepieces restart: unless-stopped ## Enable the following line if you already use AP_EXECUTION_MODE with SANDBOX_PROCESS or old activepieces, checking the breaking change documentation for more info. diff --git a/package.json b/package.json index adafc00b769..f264b75447b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "activepieces", - "version": "0.77.1", + "version": "0.77.2", "rcVersion": "0.78.0-rc.0", "scripts": { "prepare": "husky install", diff --git a/packages/react-ui/src/app/builder/run-details/flow-step-input-output.tsx b/packages/react-ui/src/app/builder/run-details/flow-step-input-output.tsx index d46df4aa8d3..3de40e99f2b 100644 --- a/packages/react-ui/src/app/builder/run-details/flow-step-input-output.tsx +++ b/packages/react-ui/src/app/builder/run-details/flow-step-input-output.tsx @@ -9,12 +9,17 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { AgentTimeline } from '@/features/agents/agent-timeline'; import { StepStatusIcon } from '@/features/flow-runs/components/step-status-icon'; import { flowRunUtils } from '@/features/flow-runs/lib/flow-run-utils'; +import { flagsHooks } from '@/hooks/flags-hooks'; import { formatUtils } from '@/lib/utils'; import { StepOutputStatus, flowStructureUtil, AgentResult, isFlowRunStateTerminal, + FlowRun, + FlowRunStatus, + isNil, + ApFlagId, } from '@activepieces/shared'; import { useBuilderStateContext } from '../builder-hooks'; @@ -62,10 +67,27 @@ export const FlowStepInputOutput = () => { status: run.status, ignoreInternalError: true, }); + const { data: rententionDays } = flagsHooks.useFlag( + ApFlagId.EXECUTION_DATA_RETENTION_DAYS, + ); + + const message = handleRunFailureOrEmptyLog(run, rententionDays); + if (message) { + return ( +
+ +

+ {message} +

+
+ ); + } + + if (!isRunDone) { + return ; + } + if (!selectedStepOutput || !selectedStep) { - if (!isRunDone) { - return ; - } return (
@@ -137,3 +159,25 @@ const OutputSkeleton = () => {
); }; + +function handleRunFailureOrEmptyLog( + run: FlowRun | null, + retentionDays: number | null, +) { + if (isNil(run)) { + return null; + } + if ([FlowRunStatus.INTERNAL_ERROR].includes(run.status)) { + return t( + 'There are no logs captured for this run, because of an internal error, please contact support.', + ); + } + + if (isNil(run.logsFileId)) { + return t( + 'Logs are kept for {days} days after execution and then deleted.', + { days: retentionDays }, + ); + } + return null; +} diff --git a/packages/react-ui/src/app/builder/step-settings/index.tsx b/packages/react-ui/src/app/builder/step-settings/index.tsx index e1ed563a5e8..eb9d1346445 100644 --- a/packages/react-ui/src/app/builder/step-settings/index.tsx +++ b/packages/react-ui/src/app/builder/step-settings/index.tsx @@ -256,7 +256,10 @@ const StepSettingsContainer = () => { onResize={(size) => setHeight(size)} className="min-h-[130px]" > - + {showGenerateSampleData && ( { updatedBy: null, agentIds: [], connectionIds: [], + notes: selectedFlow.notes ?? [], }, }; }, [template, selectedFlowIndex]); diff --git a/packages/server/api/src/app/ee/oauth-apps/oauth-app.module.ts b/packages/server/api/src/app/ee/oauth-apps/oauth-app.module.ts index 63e49e82117..a0a03234ae7 100644 --- a/packages/server/api/src/app/ee/oauth-apps/oauth-app.module.ts +++ b/packages/server/api/src/app/ee/oauth-apps/oauth-app.module.ts @@ -22,7 +22,7 @@ const oauthAppController: FastifyPluginAsyncTypebox = async (app) => { '/', { config: { - security: securityAccess.platformAdminOnly([PrincipalType.USER]), + security: securityAccess.publicPlatform([PrincipalType.USER]), }, schema: { querystring: ListOAuth2AppRequest, diff --git a/packages/server/api/src/app/ee/platform/admin/templates/admin-platform-templates-cloud.controller.ts b/packages/server/api/src/app/ee/platform/admin/templates/admin-platform-templates-cloud.controller.ts index a1b7333d182..465787fb198 100644 --- a/packages/server/api/src/app/ee/platform/admin/templates/admin-platform-templates-cloud.controller.ts +++ b/packages/server/api/src/app/ee/platform/admin/templates/admin-platform-templates-cloud.controller.ts @@ -3,6 +3,7 @@ import { ActivepiecesError, ApFlagId, CreateTemplateRequestBody, ErrorCode, Temp import { FastifyPluginAsyncTypebox } from '@fastify/type-provider-typebox' import { Type } from '@sinclair/typebox' import { flagService } from '../../../../flags/flag.service' +import { migrateFlowVersionTemplateList } from '../../../../flows/flow-version/migrations' import { templateService } from '../../../../template/template.service' export const adminPlatformTemplatesCloudController: FastifyPluginAsyncTypebox = async ( @@ -29,7 +30,13 @@ export const adminPlatformTemplatesCloudController: FastifyPluginAsyncTypebox = }) - app.post('/', CreateTemplateRequest, async (request) => { + app.post('/', { + ...CreateTemplateRequest, + preValidation: async (request) => { + const migratedFlows = await migrateFlowVersionTemplateList(request.body.flows ?? []) + request.body.flows = migratedFlows + }, + }, async (request) => { const { type } = request.body if (type !== TemplateType.OFFICIAL) { throw new ActivepiecesError({ @@ -45,7 +52,13 @@ export const adminPlatformTemplatesCloudController: FastifyPluginAsyncTypebox = }) }) - app.post('/:id', UpdateTemplateRequest, async (request) => { + app.post('/:id', { + ...UpdateTemplateRequest, + preValidation: async (request) => { + const migratedFlows = await migrateFlowVersionTemplateList(request.body.flows ?? []) + request.body.flows = migratedFlows + }, + }, async (request) => { const template = await templateService(app.log).getOneOrThrow({ id: request.params.id }) if (template.type !== TemplateType.OFFICIAL) { diff --git a/packages/server/api/src/app/flows/flow-version/migrations/index.ts b/packages/server/api/src/app/flows/flow-version/migrations/index.ts index d8ce5e4c153..1d056ef57f4 100644 --- a/packages/server/api/src/app/flows/flow-version/migrations/index.ts +++ b/packages/server/api/src/app/flows/flow-version/migrations/index.ts @@ -49,7 +49,7 @@ export const flowMigrations = { }, } -export const migrateFlowVersionTemplate = async (trigger: FlowVersion['trigger'], schemaVersion: FlowVersion['schemaVersion'], notes: FlowVersion['notes']): Promise => { +export const migrateFlowVersionTemplate = async ({ trigger, schemaVersion, notes, valid }: Pick): Promise => { return flowMigrations.apply({ agentIds: [], connectionIds: [], @@ -59,10 +59,16 @@ export const migrateFlowVersionTemplate = async (trigger: FlowVersion['trigger'] id: '', updated: new Date().toISOString(), updatedBy: '', - valid: false, + valid, trigger, state: FlowVersionState.DRAFT, schemaVersion, - notes, + notes: notes ?? [], }) +} + +export const migrateFlowVersionTemplateList = async (flowVersions: FlowVersionTemplate[]): Promise => { + return Promise.all(flowVersions.map(async (flowVersion) => { + return migrateFlowVersionTemplate(flowVersion) + })) } \ No newline at end of file diff --git a/packages/server/api/src/app/flows/flow-version/migrations/migrate-v12-fix-piece-version.ts b/packages/server/api/src/app/flows/flow-version/migrations/migrate-v12-fix-piece-version.ts index c9ea9edda64..777e50ebe74 100644 --- a/packages/server/api/src/app/flows/flow-version/migrations/migrate-v12-fix-piece-version.ts +++ b/packages/server/api/src/app/flows/flow-version/migrations/migrate-v12-fix-piece-version.ts @@ -27,7 +27,12 @@ export const migrateV12FixPieceVersion: Migration = { } const flow = await flowService(system.globalLogger()).getOneById(flowVersion.flowId) - assertNotNullOrUndefined(flow, 'Flow not found') + if (isNil(flow)) { + return { + ...flowVersion, + schemaVersion: '13', + } + } const platformId = await projectService.getPlatformId(flow.projectId) const stepNameToPieceVersion: Record = {} const steps = flowStructureUtil.getAllSteps(flowVersion.trigger) diff --git a/packages/server/api/src/app/flows/flow/flow.controller.ts b/packages/server/api/src/app/flows/flow/flow.controller.ts index 2737fe9e5b2..1ec3324894f 100644 --- a/packages/server/api/src/app/flows/flow/flow.controller.ts +++ b/packages/server/api/src/app/flows/flow/flow.controller.ts @@ -80,7 +80,12 @@ export const flowController: FastifyPluginAsyncTypebox = async (app) => { }, preValidation: async (request) => { if (request.body?.type === FlowOperationType.IMPORT_FLOW) { - const migratedFlowTemplate = await migrateFlowVersionTemplate(request.body.request.trigger, request.body.request.schemaVersion, request.body.request.notes ?? []) + const migratedFlowTemplate = await migrateFlowVersionTemplate({ + trigger: request.body.request.trigger, + schemaVersion: request.body.request.schemaVersion, + notes: request.body.request.notes ?? [], + valid: false, + }) request.body.request = { ...request.body.request, trigger: migratedFlowTemplate.trigger, diff --git a/packages/server/api/src/app/template/template-validator.ts b/packages/server/api/src/app/template/template-validator.ts index 71f28bdfeed..af9e485ac75 100644 --- a/packages/server/api/src/app/template/template-validator.ts +++ b/packages/server/api/src/app/template/template-validator.ts @@ -14,6 +14,7 @@ function createMinimalFlowVersion(template: FlowVersionTemplate): FlowVersion { agentIds: [], connectionIds: [], backupFiles: null, + notes: template.notes ?? [], } } diff --git a/packages/server/api/src/app/template/template.controller.ts b/packages/server/api/src/app/template/template.controller.ts index 1d0a0898e29..6687bce86af 100644 --- a/packages/server/api/src/app/template/template.controller.ts +++ b/packages/server/api/src/app/template/template.controller.ts @@ -6,7 +6,6 @@ import { ApFlagId, CreateTemplateRequestBody, ErrorCode, - FlowVersionTemplate, isNil, ListTemplatesRequestQuery, Principal, @@ -22,7 +21,7 @@ import { FastifyBaseLogger } from 'fastify' import { StatusCodes } from 'http-status-codes' import { platformMustBeOwnedByCurrentUser } from '../ee/authentication/ee-authorization' import { flagService } from '../flags/flag.service' -import { migrateFlowVersionTemplate } from '../flows/flow-version/migrations' +import { migrateFlowVersionTemplateList } from '../flows/flow-version/migrations' import { system } from '../helper/system/system' import { platformService } from '../platform/platform.service' import { communityTemplates } from './community-flow-template.service' @@ -71,14 +70,7 @@ export const templateController: FastifyPluginAsyncTypebox = async (app) => { app.post('/', { ...CreateParams, preValidation: async (request) => { - const migratedFlows = await Promise.all((request.body.flows ?? []).map(async (flow: FlowVersionTemplate) => { - const migratedFlow = await migrateFlowVersionTemplate(flow.trigger, flow.schemaVersion, flow.notes) - return { - ...flow, - trigger: migratedFlow.trigger, - schemaVersion: migratedFlow.schemaVersion, - } - })) + const migratedFlows = await migrateFlowVersionTemplateList(request.body.flows ?? []) request.body.flows = migratedFlows }, }, async (request, reply) => { @@ -106,7 +98,12 @@ export const templateController: FastifyPluginAsyncTypebox = async (app) => { return reply.status(StatusCodes.CREATED).send(result) }) - app.post('/:id', UpdateParams, async (request, reply) => { + app.post('/:id', { ...UpdateParams, + preValidation: async (request) => { + const migratedFlows = await migrateFlowVersionTemplateList(request.body.flows ?? []) + request.body.flows = migratedFlows + }, + }, async (request, reply) => { const result = await templateService(app.log).update({ id: request.params.id, params: request.body }) return reply.status(StatusCodes.OK).send(result) }) diff --git a/packages/server/api/test/integration/cloud/oauth-app/oauth-app.test.ts b/packages/server/api/test/integration/cloud/oauth-app/oauth-app.test.ts index 1a5ab6c8df6..fb61a4e9453 100644 --- a/packages/server/api/test/integration/cloud/oauth-app/oauth-app.test.ts +++ b/packages/server/api/test/integration/cloud/oauth-app/oauth-app.test.ts @@ -195,7 +195,13 @@ describe('OAuth App API', () => { it('should list OAuth Apps by platform member', async () => { // arrange const { mockPlatform: mockPlatformOne } = await mockAndSaveBasicSetup() - const { mockOwner: mockUserTwo, mockPlatform: mockPlatformTwo } = await mockAndSaveBasicSetup() + const { mockPlatform: mockPlatformTwo } = await mockAndSaveBasicSetup() + const { mockUser: mockUserTwo } = await mockBasicUser({ + user: { + platformId: mockPlatformTwo.id, + platformRole: PlatformRole.MEMBER, + }, + }) const mockOAuthAppsOne = await createMockOAuthApp({ platformId: mockPlatformOne.id, @@ -211,7 +217,7 @@ describe('OAuth App API', () => { const testToken = await generateMockToken({ type: PrincipalType.USER, id: mockUserTwo.id, - platform: { id: mockPlatformOne.id }, + platform: { id: mockPlatformTwo.id }, }) // act const response = await app?.inject({ @@ -227,7 +233,7 @@ describe('OAuth App API', () => { expect(response?.statusCode).toBe(StatusCodes.OK) expect(responseBody.data).toHaveLength(1) - expect(responseBody.data[0].id).toBe(mockOAuthAppsOne.id) + expect(responseBody.data[0].id).toBe(mockOAuthAppsTwo.id) expect(responseBody.data[0].clientSecret).toBeUndefined() }) }) diff --git a/packages/server/shared/package.json b/packages/server/shared/package.json index 789d1f565fc..52083408051 100644 --- a/packages/server/shared/package.json +++ b/packages/server/shared/package.json @@ -6,7 +6,7 @@ "typings": "./src/index.d.ts", "dependencies": { "@activepieces/pieces-framework": "0.23.0", - "@activepieces/shared": "0.30.4", + "@activepieces/shared": "0.31.1", "tslib": "2.6.2", "pino": "10.1.0", "@hyperdx/node-opentelemetry": "0.8.2", diff --git a/packages/server/worker/package.json b/packages/server/worker/package.json index 503f913e479..502f828e838 100644 --- a/packages/server/worker/package.json +++ b/packages/server/worker/package.json @@ -7,7 +7,7 @@ "dependencies": { "@activepieces/pieces-framework": "0.23.0", "@activepieces/server-shared": "0.0.2", - "@activepieces/shared": "0.31.0", + "@activepieces/shared": "0.31.1", "write-file-atomic": "5.0.1", "tslib": "2.6.2", "@opentelemetry/api": "1.9.0", diff --git a/packages/shared/package.json b/packages/shared/package.json index 87f25ed1bf2..0ad412652e6 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,5 +1,5 @@ { "name": "@activepieces/shared", - "version": "0.31.0", + "version": "0.31.1", "type": "commonjs" } diff --git a/packages/shared/src/lib/template/template.ts b/packages/shared/src/lib/template/template.ts index 9750138b6c3..323d4b01122 100644 --- a/packages/shared/src/lib/template/template.ts +++ b/packages/shared/src/lib/template/template.ts @@ -1,5 +1,6 @@ import { Omit, Static, Type } from '@sinclair/typebox' import { BaseModelSchema, ColorHex, Metadata, Nullable } from '../common' +import { Note } from '../flows' import { FlowVersion } from '../flows/flow-version' export const TemplateTag = Type.Object({ @@ -18,9 +19,11 @@ export enum TemplateType { export const FlowVersionTemplate = Type.Composite([Type.Omit( FlowVersion, - ['id', 'created', 'updated', 'flowId', 'state', 'updatedBy', 'agentIds', 'connectionIds', 'backupFiles'], + ['id', 'created', 'updated', 'flowId', 'state', 'updatedBy', 'agentIds', 'connectionIds', 'backupFiles', 'notes'], ), Type.Object({ description: Type.Optional(Type.String()), + //notes were optional for old json templates + notes: Type.Optional(Type.Array(Note)), })]) export type FlowVersionTemplate = Static