Skip to content

Commit 3cfdc12

Browse files
committed
feat(cloud-security): add connectionId query parameter for run status
1 parent 90d9456 commit 3cfdc12

3 files changed

Lines changed: 36 additions & 36 deletions

File tree

apps/api/src/cloud-security/cloud-security.controller.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
Post,
44
Get,
55
Param,
6+
Query,
67
Headers,
78
Logger,
89
HttpException,
@@ -11,7 +12,10 @@ import {
1112
} from '@nestjs/common';
1213
import { HybridAuthGuard } from '../auth/hybrid-auth.guard';
1314
import { OrganizationId } from '../auth/auth-context.decorator';
14-
import { CloudSecurityService } from './cloud-security.service';
15+
import {
16+
CloudSecurityService,
17+
ConnectionNotFoundError,
18+
} from './cloud-security.service';
1519

1620
@Controller({ path: 'cloud-security', version: '1' })
1721
export class CloudSecurityController {
@@ -85,14 +89,26 @@ export class CloudSecurityController {
8589
@UseGuards(HybridAuthGuard)
8690
async getRunStatus(
8791
@Param('runId') runId: string,
92+
@Query('connectionId') connectionId: string,
8893
@OrganizationId() organizationId: string,
8994
) {
95+
if (!connectionId) {
96+
throw new HttpException(
97+
'connectionId query parameter is required',
98+
HttpStatus.BAD_REQUEST,
99+
);
100+
}
101+
90102
try {
91103
return await this.cloudSecurityService.getRunStatus(
92104
runId,
105+
connectionId,
93106
organizationId,
94107
);
95108
} catch (error) {
109+
if (error instanceof ConnectionNotFoundError) {
110+
throw new HttpException('Connection not found', HttpStatus.NOT_FOUND);
111+
}
96112
const message =
97113
error instanceof Error ? error.message : 'Failed to get run status';
98114
throw new HttpException(message, HttpStatus.INTERNAL_SERVER_ERROR);

apps/api/src/cloud-security/cloud-security.service.ts

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,16 @@ export interface ScanResult {
2929
error?: string;
3030
}
3131

32+
export class ConnectionNotFoundError extends Error {
33+
constructor() {
34+
super('Connection not found');
35+
}
36+
}
37+
3238
@Injectable()
3339
export class CloudSecurityService {
3440
private readonly logger = new Logger(CloudSecurityService.name);
3541

36-
// Track which organization owns each trigger.dev run for authorization
37-
private readonly runOwnership = new Map<
38-
string,
39-
{ organizationId: string; createdAt: number }
40-
>();
41-
42-
// Clean up stale entries older than 10 minutes
43-
private readonly RUN_OWNERSHIP_TTL_MS = 10 * 60 * 1000;
44-
4542
constructor(
4643
private readonly credentialVaultService: CredentialVaultService,
4744
private readonly oauthCredentialsService: OAuthCredentialsService,
@@ -259,49 +256,36 @@ export class CloudSecurityService {
259256
runId: handle.id,
260257
});
261258

262-
// Track ownership for authorization on status checks
263-
this.runOwnership.set(handle.id, {
264-
organizationId,
265-
createdAt: Date.now(),
266-
});
267-
this.cleanupStaleRuns();
268-
269259
return { runId: handle.id };
270260
}
271261

272262
async getRunStatus(
273263
runId: string,
264+
connectionId: string,
274265
organizationId: string,
275266
): Promise<{ completed: boolean; success: boolean; output: unknown }> {
276-
// Verify the caller's organization owns this run
277-
const ownership = this.runOwnership.get(runId);
278-
if (!ownership || ownership.organizationId !== organizationId) {
279-
throw new Error('Run not found');
267+
// Verify the connection belongs to the caller's organization
268+
const connection = await db.integrationConnection.findFirst({
269+
where: {
270+
id: connectionId,
271+
organizationId,
272+
},
273+
select: { id: true },
274+
});
275+
276+
if (!connection) {
277+
throw new ConnectionNotFoundError();
280278
}
281279

282280
const run = await runs.retrieve(runId);
283281

284-
// Clean up completed runs from the ownership map
285-
if (run.isCompleted) {
286-
this.runOwnership.delete(runId);
287-
}
288-
289282
return {
290283
completed: run.isCompleted,
291284
success: run.isCompleted ? run.isSuccess : false,
292285
output: run.isCompleted ? run.output : null,
293286
};
294287
}
295288

296-
private cleanupStaleRuns(): void {
297-
const now = Date.now();
298-
for (const [runId, entry] of this.runOwnership) {
299-
if (now - entry.createdAt > this.RUN_OWNERSHIP_TTL_MS) {
300-
this.runOwnership.delete(runId);
301-
}
302-
}
303-
}
304-
305289
private async storeFindings(
306290
connectionId: string,
307291
provider: string,

apps/app/src/app/(app)/[orgId]/cloud-tests/actions/run-platform-scan.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export const runPlatformScan = async (connectionId: string) => {
8989
provider?: string;
9090
scannedAt?: string;
9191
} | null;
92-
}>(`/v1/cloud-security/runs/${runId}`, authHeaders);
92+
}>(`/v1/cloud-security/runs/${runId}?connectionId=${connectionId}`, authHeaders);
9393

9494
if (statusResponse.error) {
9595
return {

0 commit comments

Comments
 (0)