Skip to content

Commit e432288

Browse files
authored
Merge pull request #2593 from trycompai/lewis/comp-framework-controls
[dev] [carhartlewis] lewis/comp-framework-controls
2 parents b4f6cf6 + 2ffc0bd commit e432288

64 files changed

Lines changed: 4094 additions & 326 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/api/src/admin-organizations/admin-policies.controller.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -130,20 +130,41 @@ export class AdminPoliciesController {
130130
) {
131131
const instances = await db.frameworkInstance.findMany({
132132
where: { organizationId: orgId },
133-
include: { framework: true },
133+
include: { framework: true, customFramework: true },
134134
});
135135

136+
const normalized = instances.map((fi) => {
137+
if (fi.framework) {
138+
return {
139+
id: fi.framework.id,
140+
name: fi.framework.name,
141+
version: fi.framework.version,
142+
description: fi.framework.description,
143+
visible: fi.framework.visible,
144+
createdAt: fi.framework.createdAt,
145+
updatedAt: fi.framework.updatedAt,
146+
};
147+
}
148+
if (fi.customFramework) {
149+
return {
150+
id: fi.customFramework.id,
151+
name: fi.customFramework.name,
152+
version: fi.customFramework.version,
153+
description: fi.customFramework.description,
154+
visible: true,
155+
createdAt: fi.customFramework.createdAt,
156+
updatedAt: fi.customFramework.updatedAt,
157+
};
158+
}
159+
return null;
160+
});
136161
const uniqueFrameworks = Array.from(
137-
new Map(instances.map((fi) => [fi.framework.id, fi.framework])).values(),
138-
).map((f) => ({
139-
id: f.id,
140-
name: f.name,
141-
version: f.version,
142-
description: f.description,
143-
visible: f.visible,
144-
createdAt: f.createdAt,
145-
updatedAt: f.updatedAt,
146-
}));
162+
new Map(
163+
normalized
164+
.filter((f): f is NonNullable<typeof f> => f !== null)
165+
.map((f) => [f.id, f]),
166+
).values(),
167+
);
147168

148169
const contextEntries = await db.context.findMany({
149170
where: { organizationId: orgId },

apps/api/src/controls/controls.controller.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
Delete,
55
Get,
66
Param,
7+
ParseEnumPipe,
78
Post,
89
Query,
910
UseGuards,
@@ -20,6 +21,11 @@ import { RequirePermission } from '../auth/require-permission.decorator';
2021
import { OrganizationId } from '../auth/auth-context.decorator';
2122
import { ControlsService } from './controls.service';
2223
import { CreateControlDto } from './dto/create-control.dto';
24+
import { LinkPoliciesDto } from './dto/link-policies.dto';
25+
import { LinkTasksDto } from './dto/link-tasks.dto';
26+
import { LinkRequirementsToControlDto } from './dto/link-requirements.dto';
27+
import { LinkDocumentTypesDto } from './dto/link-document-types.dto';
28+
import { EvidenceFormType } from '@db';
2329

2430
@ApiTags('Controls')
2531
@ApiBearerAuth()
@@ -92,6 +98,78 @@ export class ControlsController {
9298
return this.controlsService.create(organizationId, dto);
9399
}
94100

101+
@Post(':id/policies/link')
102+
@RequirePermission('control', 'update')
103+
@ApiOperation({ summary: 'Link existing policies to a control' })
104+
async linkPolicies(
105+
@OrganizationId() organizationId: string,
106+
@Param('id') id: string,
107+
@Body() dto: LinkPoliciesDto,
108+
) {
109+
return this.controlsService.linkPolicies(
110+
id,
111+
organizationId,
112+
dto.policyIds,
113+
);
114+
}
115+
116+
@Post(':id/tasks/link')
117+
@RequirePermission('control', 'update')
118+
@ApiOperation({ summary: 'Link existing tasks to a control' })
119+
async linkTasks(
120+
@OrganizationId() organizationId: string,
121+
@Param('id') id: string,
122+
@Body() dto: LinkTasksDto,
123+
) {
124+
return this.controlsService.linkTasks(id, organizationId, dto.taskIds);
125+
}
126+
127+
@Post(':id/requirements/link')
128+
@RequirePermission('control', 'update')
129+
@ApiOperation({ summary: 'Link existing requirements to a control' })
130+
async linkRequirements(
131+
@OrganizationId() organizationId: string,
132+
@Param('id') id: string,
133+
@Body() dto: LinkRequirementsToControlDto,
134+
) {
135+
return this.controlsService.linkRequirements(
136+
id,
137+
organizationId,
138+
dto.requirements,
139+
);
140+
}
141+
142+
@Post(':id/document-types/link')
143+
@RequirePermission('control', 'update')
144+
@ApiOperation({ summary: 'Link required document types to a control' })
145+
async linkDocumentTypes(
146+
@OrganizationId() organizationId: string,
147+
@Param('id') id: string,
148+
@Body() dto: LinkDocumentTypesDto,
149+
) {
150+
return this.controlsService.linkDocumentTypes(
151+
id,
152+
organizationId,
153+
dto.formTypes,
154+
);
155+
}
156+
157+
@Delete(':id/document-types/:formType')
158+
@RequirePermission('control', 'update')
159+
@ApiOperation({ summary: 'Remove a required document type from a control' })
160+
async unlinkDocumentType(
161+
@OrganizationId() organizationId: string,
162+
@Param('id') id: string,
163+
@Param('formType', new ParseEnumPipe(EvidenceFormType))
164+
formType: EvidenceFormType,
165+
) {
166+
return this.controlsService.unlinkDocumentType(
167+
id,
168+
organizationId,
169+
formType,
170+
);
171+
}
172+
95173
@Delete(':id')
96174
@RequirePermission('control', 'delete')
97175
@ApiOperation({ summary: 'Delete a control' })

0 commit comments

Comments
 (0)