Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add applied control duplication #940

Merged
merged 30 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
6c96748
Add applied control duplication
monsieurswag Oct 15, 2024
aefec25
fix: add missing import
Mohamed-Hacene Oct 15, 2024
fc7135b
Formatter
monsieurswag Oct 15, 2024
8d22523
Fix missing fetch for model foreign keys
monsieurswag Oct 16, 2024
af3e7c9
Add an option to bring the evidences with the duplicated applied control
monsieurswag Oct 16, 2024
526d867
Merge branch 'main' into CA-503-Duplicate-applied-controls
monsieurswag Oct 16, 2024
a3df53d
Merge branch 'main' into CA-503-Duplicate-applied-controls
monsieurswag Oct 17, 2024
da4e076
Fix conflicts
monsieurswag Oct 21, 2024
edecfa0
Fix missing edit button
monsieurswag Oct 21, 2024
60c091d
Codefactor fix 1
monsieurswag Oct 21, 2024
6a78979
Codefactor fix 2
monsieurswag Oct 21, 2024
dc80e5b
Formatter
monsieurswag Oct 21, 2024
b6cf0f9
Remove dead code
monsieurswag Oct 21, 2024
6ccdfbe
Remove useless comments
monsieurswag Oct 23, 2024
e9ce72e
Merge branch 'main' into CA-503-Duplicate-applied-controls
monsieurswag Nov 12, 2024
e391800
Attempt to fix startup tests
monsieurswag Nov 12, 2024
f765433
Fix conflicts
monsieurswag Nov 26, 2024
4cf0ec0
Fix conflicts
monsieurswag Nov 26, 2024
07d09e2
Light optimization
monsieurswag Nov 26, 2024
2cd22e5
Fix non-working duplicate modal and remove 2 useless values from the …
monsieurswag Nov 27, 2024
4904783
Set the default translations
monsieurswag Nov 27, 2024
3e72c9e
chore: update translations with Fink 🐦
monsieurswag Nov 27, 2024
0756134
Fix conflicts
monsieurswag Dec 3, 2024
2d6595d
Merge branch 'main' into CA-503-Duplicate-applied-controls
monsieurswag Dec 4, 2024
40cd65a
Also copy ref_id when duplicating an AppliedControl
monsieurswag Dec 4, 2024
b413b5f
Fix conflicts
monsieurswag Dec 4, 2024
841e781
Formatter
monsieurswag Dec 4, 2024
0acd167
Copy owner when duplicating AppliedControl
monsieurswag Dec 4, 2024
9a555ff
Fix wrong assignment to AppliedControl.owner ManyToManyField
monsieurswag Dec 4, 2024
a9fc211
Merge branch 'main' into CA-503-Duplicate-applied-controls
monsieurswag Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions backend/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1374,9 +1374,6 @@ def risk_assessments(self):
def projects(self):
return {risk_assessment.project for risk_assessment in self.risk_assessments}

def parent_project(self):
pass

def __str__(self):
return self.name

Expand Down
6 changes: 6 additions & 0 deletions backend/core/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,12 @@ class AppliedControlReadSerializer(AppliedControlWriteSerializer):
owner = FieldsRelatedField(many=True)


class AppliedControlDuplicateSerializer(BaseModelSerializer):
class Meta:
model = AppliedControl
fields = ["name", "description", "folder"]


class PolicyWriteSerializer(AppliedControlWriteSerializer):
class Meta:
model = Policy
Expand Down
36 changes: 36 additions & 0 deletions backend/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,42 @@ def get_timeline_info(self, request):
colorMap[domain.name] = next(color_cycle)
return Response({"entries": entries, "colorMap": colorMap})

@action(
detail=True,
name="Duplicate applied control",
methods=["post"],
serializer_class=AppliedControlDuplicateSerializer,
)
def duplicate(self, request, pk):
(object_ids_view, _, _) = RoleAssignment.get_accessible_object_ids(
Folder.get_root_folder(), request.user, AppliedControl
)
if UUID(pk) in object_ids_view:
applied_control = self.get_object()
data = request.data
duplicate_applied_control = AppliedControl.objects.create(
reference_control=applied_control.reference_control,
name=data["name"],
description=data["description"],
folder=Folder.objects.get(id=data["folder"]),
category=applied_control.category,
csf_function=applied_control.csf_function,
status=applied_control.status,
start_date=applied_control.start_date,
eta=applied_control.eta,
expiry_date=applied_control.expiry_date,
link=applied_control.link,
effort=applied_control.effort,
cost=applied_control.cost,
)
# Should we duplicate the owners and evidences ?
# duplicate_applied_control.owner.set(applied_control.owner.all())
# The evidences must be cloned before being linked to the applied_control if they are not in the same scope (an applied_control with a scope FOLDER1/PROJECT1 must have evidences into FOLDER1/PROJECT1)
# duplicate_applied_control.evidences.set(applied_control.evidences.all())
# duplicate_applied_control.save() # This line must be used if one of the ManyToManyField of the applied_control is modified during this function execution.

return Response({"results": "applied control duplicated"})


class PolicyViewSet(AppliedControlViewSet):
model = Policy
Expand Down
1 change: 1 addition & 0 deletions frontend/messages/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@
"ssoSettingsDescription": "قم بتكوين إعدادات تسجيل الدخول الموحد هنا.",
"sso": "SSO",
"isSso": "هل هو SSO",
"duplicateAppliedControl": "تكرار عنصر التحكم المطبق",
"requirementMappingSets": "ربط الأطر",
"size": "الحجم",
"financial": "المالي",
Expand Down
1 change: 1 addition & 0 deletions frontend/messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@
"back": "Zurückkehren",
"duplicate": "Duplikat",
"duplicateRiskAssessment": "Duplizieren Sie die Risikobewertung",
"duplicateAppliedControl": "Duplizieren Sie das angewendete kontrolle",
"size": "Größe",
"entity": "Juristische Person",
"entities": "Entitäten",
Expand Down
1 change: 1 addition & 0 deletions frontend/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@
"back": "Back",
"duplicate": "Duplicate",
"duplicateRiskAssessment": "Duplicate the risk assessment",
"duplicateAppliedControl": "Duplicate the applied control",
"size": "Size",
"favicon": "Favicon",
"logo": "Logo",
Expand Down
1 change: 1 addition & 0 deletions frontend/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@
"back": "Devolver",
"duplicate": "Duplicar",
"duplicateRiskAssessment": "Duplicar la evaluación de riesgo",
"duplicateAppliedControl": "Duplicar el control aplicado",
"size": "Tamaño",
"entity": "Entidad",
"entities": "Entidades",
Expand Down
1 change: 1 addition & 0 deletions frontend/messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@
"back": "Retour",
"duplicate": "Dupliquer",
"duplicateRiskAssessment": "Dupliquer l’évaluation de risque",
"duplicateAppliedControl": "Dupliquer la mesure appliquée",
"size": "Taille",
"entity": "Entité",
"entities": "Entités",
Expand Down
1 change: 1 addition & 0 deletions frontend/messages/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@
"back": "वापस",
"duplicate": "प्रतिलिपि",
"duplicateRiskAssessment": "जोखिम आकलन की प्रतिलिपि बनाएँ",
"duplicateAppliedControl": "लागू नियंत्रण की प्रतिलिपि बनाएँ",
"size": "आकार",
"financial": "वित्तीय",
"legal": "कानूनी",
Expand Down
1 change: 1 addition & 0 deletions frontend/messages/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@
"back": "Ritorno",
"duplicate": "Duplicare",
"duplicateRiskAssessment": "Duplicare la valutazione del rischio",
"duplicateAppliedControl": "Duplica il controllo applicato",
"size": "Dimensione",
"entity": "Entità",
"entities": "Entità",
Expand Down
1 change: 1 addition & 0 deletions frontend/messages/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@
"back": "Opbrengst",
"duplicate": "Duplicaat",
"duplicateRiskAssessment": "Dupliceer de risicobeoordeling",
"duplicateAppliedControl": "Dupliceer de toegepaste controle",
"size": "Grootte",
"entity": "Entiteit",
"entities": "Entiteiten",
Expand Down
1 change: 1 addition & 0 deletions frontend/messages/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,7 @@
"back": "Powrót",
"duplicate": "Duplikować",
"duplicateRiskAssessment": "Powielić ocenę ryzyka",
"duplicateAppliedControl": "Duplikuj zastosowaną kontrolę",
"size": "Rozmiar",
"entity": "Podmiot",
"entities": "Podmioty",
Expand Down
1 change: 1 addition & 0 deletions frontend/messages/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@
"back": "Retornar",
"duplicate": "Duplicado",
"duplicateRiskAssessment": "Duplicar a avaliação de risco",
"duplicateAppliedControl": "Duplicar o controle aplicado",
"size": "Tamanho",
"entity": "Entidade",
"entities": "Entidades",
Expand Down
1 change: 1 addition & 0 deletions frontend/messages/ro.json
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,7 @@
"back": "Înapoi",
"duplicate": "Dublică",
"duplicateRiskAssessment": "Dublarea evaluării riscului",
"duplicateAppliedControl": "Duplicați control aplicat",
"size": "Mărime",
"financial": "Finanțe",
"legal": "Juridic",
Expand Down
1 change: 1 addition & 0 deletions frontend/messages/ur.json
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@
"back": "واپس",
"duplicate": "نقل کریں",
"duplicateRiskAssessment": "خطرے کی تشخیص کو نقل کریں",
"duplicateAppliedControl": "لاگو کنٹرول کی نقل تیار کریں۔",
"size": "سائز",
"financial": "مالیاتی",
"legal": "قانونی",
Expand Down
43 changes: 38 additions & 5 deletions frontend/src/lib/components/DetailView/DetailView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,26 @@
modalStore.trigger(modal);
}

function modalAppliedControlDuplicateForm(): void {
const modalComponent: ModalComponent = {
ref: CreateModal,
props: {
form: data.duplicateForm,
model: data.model,
debug: false,
duplicate: true,
formAction: '?/duplicate'
}
};

const modal: ModalSettings = {
type: 'component',
component: modalComponent,
title: m.duplicateAppliedControl()
};
modalStore.trigger(modal);
}

function modalMailConfirm(id: string, name: string, action: string): void {
const modalComponent: ModalComponent = {
ref: ConfirmModal,
Expand Down Expand Up @@ -321,11 +341,24 @@
</button>
{/if}
{#if displayEditButton()}
<a
href={`${$page.url.pathname}/edit?next=${$page.url.pathname}`}
class="btn variant-filled-primary h-fit"
><i class="fa-solid fa-pen-to-square mr-2" data-testid="edit-button" />{m.edit()}</a
>
<div class="flex flex-col space-y-2 ml-4">
<a
href={`${$page.url.pathname}/edit?next=${$page.url.pathname}`}
class="btn variant-filled-primary h-fit"
><i class="fa-solid fa-pen-to-square mr-2" data-testid="edit-button" />{m.edit()}</a
>
{#if data.urlModel === 'applied-controls'}
<span class="pt-4 font-light text-sm">Power-ups:</span>
<button
class="btn text-gray-100 bg-gradient-to-l from-sky-500 to-green-600"
on:click={(_) => modalAppliedControlDuplicateForm()}
data-testid="duplicate-button"
>
<i class="fa-solid fa-copy mr-2"></i>
{m.duplicate()}</button
>
{/if}
</div>
{/if}
</div>
</div>
Expand Down
9 changes: 5 additions & 4 deletions frontend/src/lib/components/Forms/ModelForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
export let parent: any;
export let suggestions: { [key: string]: any } = {};
export let cancelButton = true;
export let riskAssessmentDuplication = false;
export let duplicate = false;

const URLModel = model.urlModel as urlModel;
export let schema = modelSchema(URLModel);
Expand Down Expand Up @@ -119,7 +119,7 @@
<input type="hidden" name="urlmodel" value={model.urlModel} />
<!--NOTE: Not the cleanest pattern, will refactor-->
<!--TODO: Refactor-->
{#if shape.reference_control}
{#if shape.reference_control && !duplicate}
<AutocompleteSelect
{form}
options={getOptions({
Expand Down Expand Up @@ -178,11 +178,11 @@
<ProjectForm {form} {model} {cacheLocks} {formDataCache} {initialData} />
{:else if URLModel === 'folders'}
<FolderForm {form} {model} {cacheLocks} {formDataCache} {initialData} />
{:else if URLModel === 'risk-assessments' || URLModel === 'risk-assessment-duplicate'}
{:else if URLModel === 'risk-assessments'}
<RiskAssessmentForm
{form}
{model}
{riskAssessmentDuplication}
{duplicate}
{cacheLocks}
{formDataCache}
{initialData}
Expand All @@ -198,6 +198,7 @@
<AppliedControlsPoliciesForm
{form}
{model}
{duplicate}
{cacheLocks}
{formDataCache}
{schema}
Expand Down
Loading
Loading