diff --git a/CHANGELOG.md b/CHANGELOG.md index 91153bcfd..8fd677f3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Next * Diff-view for version history +* Set form fields readonly instead of disabled ## v2024.3 - 2024-01-09 diff --git a/api/src/reportcreator_api/pentests/permissions.py b/api/src/reportcreator_api/pentests/permissions.py index d97da4f3a..4953b0040 100644 --- a/api/src/reportcreator_api/pentests/permissions.py +++ b/api/src/reportcreator_api/pentests/permissions.py @@ -39,9 +39,12 @@ def has_object_permission(self, request, view, obj): elif obj.scope == ProjectTypeScope.PROJECT: if request.user not in set(map(lambda m: m.user, obj.linked_project.members.all())): return False - return request.method in permissions.SAFE_METHODS or view.action in self.public_actions or \ - (view.action in self.private_actions and obj.source == SourceEnum.CUSTOMIZED) or \ - (request.user.is_designer and obj.source == SourceEnum.CUSTOMIZED) + if request.method in permissions.SAFE_METHODS or view.action in self.public_actions: + return True + if obj.linked_project.readonly: + return False + return (view.action in self.private_actions and obj.source == SourceEnum.CUSTOMIZED) or \ + (request.user.is_designer and obj.source == SourceEnum.CUSTOMIZED) return False diff --git a/frontend/src/components/Design/CodeEditor.vue b/frontend/src/components/Design/CodeEditor.vue index c540c90e1..2f259d85b 100644 --- a/frontend/src/components/Design/CodeEditor.vue +++ b/frontend/src/components/Design/CodeEditor.vue @@ -34,10 +34,10 @@ monaco.languages.html.htmlDefaults.setOptions({ const props = withDefaults(defineProps<{ modelValue: string, language?: string, - disabled?: boolean, + readonly?: boolean, }>(), { language: 'plaintext', - disabled: false, + readonly: false, }); const emits = defineEmits< { (e: 'update:modelValue', modelValue: string): void @@ -52,7 +52,7 @@ onMounted(() => { editor = monaco.editor.create(editorElement.value!, { value: props.modelValue, language: props.language, - readOnly: props.disabled, + readOnly: props.readonly, theme: theme.current.value.dark ? 'vs-dark' : 'vs', minimap: { enabled: false, @@ -80,7 +80,7 @@ watch(() => props.modelValue, (val) => { editor.setValue(val); } }); -watch(() => props.disabled, (val) => { +watch(() => props.readonly, (val) => { if (editor) { editor.updateOptions({ readOnly: val }); } diff --git a/frontend/src/components/Design/FindingOrderingDefinition.vue b/frontend/src/components/Design/FindingOrderingDefinition.vue index 41f5aa19f..a4d4f6d42 100644 --- a/frontend/src/components/Design/FindingOrderingDefinition.vue +++ b/frontend/src/components/Design/FindingOrderingDefinition.vue @@ -11,7 +11,7 @@ :model-value="props.modelValue" @update:model-value="emit('update:modelValue', $event)" item-key="field" - :disabled="props.disabled" + :disabled="props.readonly" handle=".draggable-handle" > @@ -175,7 +179,7 @@ @@ -189,7 +193,8 @@ @@ -208,7 +213,7 @@ @@ -219,23 +224,23 @@ v-if="![FieldDataType.OBJECT, FieldDataType.LIST, FieldDataType.USER].includes(props.modelValue.type as any)" :model-value="props.modelValue.default" @update:model-value="updateProperty('default', $event)" - :definition="{...props.modelValue, label: 'Default Value', required: false, pattern: null} as FieldDefinition" + :definition="({...props.modelValue, label: 'Default Value', required: false, pattern: null} as FieldDefinition)" :lang="props.lang" v-model:spellcheck-enabled="localSettings.designSpellcheckEnabled" v-model:markdown-editor-mode="localSettings.designMarkdownEditorMode" - :disabled="props.disabled" + :readonly="props.readonly" :disable-validation="true" /> @@ -247,13 +252,13 @@ :is-object-property="true" :can-change-structure="props.canChangeStructure" :lang="props.lang" - :disabled="props.disabled" + :readonly="props.readonly" /> @@ -263,7 +268,7 @@ @@ -284,7 +289,7 @@ const props = defineProps<{ canChangeStructure?: boolean; isListItem?: boolean; isObjectProperty?: boolean; - disabled?: boolean; + readonly?: boolean; lang?: string|null; }>(); const emit = defineEmits<{ diff --git a/frontend/src/components/Design/PreviewDataForm.vue b/frontend/src/components/Design/PreviewDataForm.vue index f5baf425f..0fa456bcd 100644 --- a/frontend/src/components/Design/PreviewDataForm.vue +++ b/frontend/src/components/Design/PreviewDataForm.vue @@ -17,7 +17,7 @@ v-model="findings" item-key="id" handle=".draggable-handle" - :disabled="disabled || projectType.finding_ordering.length !== 0" + :disabled="props.readonly || projectType.finding_ordering.length !== 0" > diff --git a/frontend/src/pages/notes/personal/[noteId].vue b/frontend/src/pages/notes/personal/[noteId].vue index e33bbef87..c9603603c 100644 --- a/frontend/src/pages/notes/personal/[noteId].vue +++ b/frontend/src/pages/notes/personal/[noteId].vue @@ -17,7 +17,7 @@ v-if="note.checked === null" v-model="note.icon_emoji" :empty-icon="hasChildNotes ? 'mdi-folder-outline' : 'mdi-note-text-outline'" - :disabled="readonly" + :readonly="readonly" density="comfortable" /> @@ -98,7 +98,7 @@ function rewriteFileUrl(imgSrc: string) { return urlJoin('/api/v1/pentestusers/self/notes/', imgSrc); } const inputFieldAttrs = computed(() => ({ - disabled: readonly.value, + readonly: readonly.value, lang: 'auto', spellcheckSupported: true, spellcheckEnabled: localSettings.userNoteSpellcheckEnabled, diff --git a/frontend/src/pages/projects/[projectId]/designer.vue b/frontend/src/pages/projects/[projectId]/designer.vue index f97f0d806..b3afdc349 100644 --- a/frontend/src/pages/projects/[projectId]/designer.vue +++ b/frontend/src/pages/projects/[projectId]/designer.vue @@ -82,11 +82,17 @@ const cssEditor = ref(); const pdfRenderingInProgress = computed(() => pdfPreviewRef.value?.renderingInProgress); const project = await useAsyncDataE(async () => await projectStore.getById(route.params.projectId as string), { key: 'projectdesigner:project' }) -const { projectType, toolbarAttrs, readonly } = useProjectTypeLockEdit(await useProjectTypeLockEditOptions({ - id: project.value.project_type, - save: true, - saveFields: ['report_template', 'report_styles', 'report_preview_data'], -})); +const { projectType, toolbarAttrs, readonly } = useProjectTypeLockEdit({ + ...await useProjectTypeLockEditOptions({ + id: project.value.project_type, + save: true, + saveFields: ['report_template', 'report_styles', 'report_preview_data'], + }), + hasEditPermissions: computed(() => !project.value.readonly), + errorMessage: computed(() => project.value.readonly ? + 'This project is finished and cannot be changed anymore. In order to edit this project, re-activate it in the project settings.' : + null), +}); async function fetchPdf() { return await $fetch(`/api/v1/pentestprojects/${project.value.id}/preview/`, { diff --git a/frontend/src/pages/projects/[projectId]/index.vue b/frontend/src/pages/projects/[projectId]/index.vue index 7687a65a6..144fc96a8 100644 --- a/frontend/src/pages/projects/[projectId]/index.vue +++ b/frontend/src/pages/projects/[projectId]/index.vue @@ -61,17 +61,17 @@ v-model="project.name" label="Name" :error-messages="serverErrors?.name || []" - :disabled="readonly" + :readonly="readonly" spellcheck="false" class="mt-4" /> (`/api/v1/pentestprojects/${route.params.projectId}/`, { method: 'GET', key: 'projectSettings:project' }); const serverErrors = ref(null); -const projectType = ref(null); +const projectType = ref(null); const historyVisible = ref(false); const formRef = ref(); diff --git a/frontend/src/pages/projects/[projectId]/notes/[noteId]/history/[historyDate].vue b/frontend/src/pages/projects/[projectId]/notes/[noteId]/history/[historyDate].vue index 5c8ba8ac4..0064d7d02 100644 --- a/frontend/src/pages/projects/[projectId]/notes/[noteId]/history/[historyDate].vue +++ b/frontend/src/pages/projects/[projectId]/notes/[noteId]/history/[historyDate].vue @@ -17,13 +17,13 @@ v-if="note.checked === null" v-model="note.icon_emoji" :empty-icon="hasChildNotes ? 'mdi-folder-outline' : 'mdi-note-text-outline'" - :disabled="true" + :readonly="true" density="comfortable" /> diff --git a/frontend/src/pages/projects/[projectId]/reporting/findings/[findingId]/history/[historyDate].vue b/frontend/src/pages/projects/[projectId]/reporting/findings/[findingId]/history/[historyDate].vue index 9bf766f2f..e4c8681d2 100644 --- a/frontend/src/pages/projects/[projectId]/reporting/findings/[findingId]/history/[historyDate].vue +++ b/frontend/src/pages/projects/[projectId]/reporting/findings/[findingId]/history/[historyDate].vue @@ -3,13 +3,13 @@
- +
- +
- +
- +