diff --git a/backend/app/routers/tests.py b/backend/app/routers/tests.py index 98c1f63..dce26df 100644 --- a/backend/app/routers/tests.py +++ b/backend/app/routers/tests.py @@ -185,6 +185,11 @@ def create_test_from_template( template_id=payload.template_id, technique_id_or_mitre=payload.technique_id, creator_id=current_user.id, + name_override=payload.name, + description_override=payload.description, + platform_override=payload.platform, + procedure_text_override=payload.procedure_text, + tool_used_override=payload.tool_used, ) log_action( db, diff --git a/backend/app/schemas/test_template.py b/backend/app/schemas/test_template.py index 54a45e5..18f7753 100644 --- a/backend/app/schemas/test_template.py +++ b/backend/app/schemas/test_template.py @@ -72,7 +72,17 @@ class TestTemplateSummary(BaseModel): class TestTemplateInstantiate(BaseModel): - """Payload to create a real test from an existing template.""" + """Payload to create a real test from an existing template. + + Optional override fields take precedence over the template values when provided. + """ template_id: uuid.UUID technique_id: str # accepts both UUID and MITRE ID (e.g. "T1059.001") + + # User-editable overrides (if omitted the template value is used) + name: str | None = None + description: str | None = None + platform: str | None = None + procedure_text: str | None = None + tool_used: str | None = None diff --git a/backend/app/services/test_crud_service.py b/backend/app/services/test_crud_service.py index 92027c4..5c41f84 100644 --- a/backend/app/services/test_crud_service.py +++ b/backend/app/services/test_crud_service.py @@ -93,10 +93,17 @@ def create_test_from_template( template_id: uuid.UUID, technique_id_or_mitre: str, creator_id: uuid.UUID, + # Optional user-edited overrides (take priority over template values) + name_override: str | None = None, + description_override: str | None = None, + platform_override: str | None = None, + procedure_text_override: str | None = None, + tool_used_override: str | None = None, ) -> Test: """Instantiate a Test from a TestTemplate. technique_id_or_mitre can be a UUID string or MITRE ID (e.g. T1059.001). + Override fields, when provided, take precedence over the template's values. Raises EntityNotFoundError if template or technique not found. Does not commit; caller uses UnitOfWork. """ @@ -121,11 +128,11 @@ def create_test_from_template( test = Test( technique_id=technique.id, - name=template.name, - description=template.description, - platform=template.platform, - procedure_text=template.attack_procedure, - tool_used=template.tool_suggested, + name=name_override if name_override is not None else template.name, + description=description_override if description_override is not None else template.description, + platform=platform_override if platform_override is not None else template.platform, + procedure_text=procedure_text_override if procedure_text_override is not None else template.attack_procedure, + tool_used=tool_used_override if tool_used_override is not None else template.tool_suggested, remediation_steps=template.suggested_remediation, created_by=creator_id, state=TestState.draft, diff --git a/frontend/src/api/tests.ts b/frontend/src/api/tests.ts index 0463cd3..069ad6d 100644 --- a/frontend/src/api/tests.ts +++ b/frontend/src/api/tests.ts @@ -91,14 +91,22 @@ export async function createTest(payload: TestCreatePayload): Promise { return data; } -/** Create a test from an existing template. */ +/** Create a test from an existing template, with optional field overrides. */ export async function createTestFromTemplate( templateId: string, techniqueId: string, + overrides?: { + name?: string; + description?: string; + platform?: string; + procedure_text?: string; + tool_used?: string; + }, ): Promise { const { data } = await client.post("/tests/from-template", { template_id: templateId, technique_id: techniqueId, + ...overrides, }); return data; } diff --git a/frontend/src/components/TestFromTemplateForm.tsx b/frontend/src/components/TestFromTemplateForm.tsx index 3aa7aba..932b8d7 100644 --- a/frontend/src/components/TestFromTemplateForm.tsx +++ b/frontend/src/components/TestFromTemplateForm.tsx @@ -68,7 +68,14 @@ export default function TestFromTemplateForm({ // ── Submit ───────────────────────────────────────────────────── const createMutation = useMutation({ - mutationFn: () => createTestFromTemplate(templateId, technique), + mutationFn: () => + createTestFromTemplate(templateId, technique, { + name: name.trim() || undefined, + description: description.trim() || undefined, + platform: platform.trim() || undefined, + procedure_text: procedureText.trim() || undefined, + tool_used: toolUsed.trim() || undefined, + }), onSuccess: (test) => { navigate(`/tests/${test.id}`); },