diff --git a/assets/frontend/inertia.jsx b/assets/frontend/inertia.jsx index 22b8cd2..7f81aec 100644 --- a/assets/frontend/inertia.jsx +++ b/assets/frontend/inertia.jsx @@ -9,6 +9,7 @@ import * as dvsc from "./pages/DeliverableVersions/ShowComponent"; import * as dvnc from "./pages/DeliverableVersions/NewComponent"; import * as vssc from "./pages/VersionSboms/ShowComponent"; import * as vanc from "./pages/VulnerabilityAnalyses/NewComponent"; +import * as vaec from "./pages/VulnerabilityAnalyses/EditComponent"; import * as vaic from "./pages/VulnerabilityAnalyses/IndexComponent"; import * as hic from "./pages/Home/IndexComponent"; import axios from "axios"; @@ -23,6 +24,7 @@ const pages = { 'VersionSboms/ShowComponent': vssc, 'VulnerabilityAnalyses/IndexComponent': vaic, 'VulnerabilityAnalyses/NewComponent': vanc, + 'VulnerabilityAnalyses/EditComponent': vaec, 'Home/IndexComponent': hic } diff --git a/assets/frontend/pages/VulnerabilityAnalyses/EditComponent.tsx b/assets/frontend/pages/VulnerabilityAnalyses/EditComponent.tsx new file mode 100644 index 0000000..9911cf2 --- /dev/null +++ b/assets/frontend/pages/VulnerabilityAnalyses/EditComponent.tsx @@ -0,0 +1,98 @@ +import { Head, usePage, router } from '@inertiajs/react' +import { useState } from 'react' +import { SeverityOrder, VulnerablityAnalysisJustificationList, VulnerablityAnalysisResponseList, VulnerablityAnalysisStateList } from '../../cyclonedx/models' +import React from 'react' +import "./NewComponent.css"; + + +export default function EditComponent({ vulnerability_analysis, update_url}) { + const { errors } = usePage().props + + const [values, setValues] = useState({ + id: vulnerability_analysis.id, + state: vulnerability_analysis.state, + justification: vulnerability_analysis.justification, + response: vulnerability_analysis.response, + detail: vulnerability_analysis.detail, + adjusted_severity: vulnerability_analysis.adjusted_severity + }); + + function handleChange(e) { + setValues(values => ({ + ...values, + [e.target.id]: e.target.value, + })) + } + + function optionsForState() { + return VulnerablityAnalysisStateList.map(vas => ); + } + + function optionsForJustification() { + return ( + [].concat(VulnerablityAnalysisJustificationList.map(vas => )) + ); + } + + function optionsForResponse() { + return ( + [].concat(VulnerablityAnalysisResponseList.map(vas => )) + ); + } + + function optionsForSeverity() { + return ( + [].concat(SeverityOrder.map(vas => )) + ); + } + + function handleSubmit(e) { + e.preventDefault() + router.put(update_url, values) + } + + return ( + <> + +

{vulnerability_analysis.vulnerability_identifier}

+
+
+ + + {errors.state &&
{errors.state}
} + + + {errors.justification &&
{errors.justification}
} + + + {errors.response &&
{errors.response}
} + + + {errors.adjusted_severity &&
{errors.adjusted_severity}
} + + + {errors.detail &&
{errors.detail}
} + +
+
+ + ) +} \ No newline at end of file diff --git a/assets/frontend/pages/VulnerabilityAnalyses/IndexTableRowComponent.tsx b/assets/frontend/pages/VulnerabilityAnalyses/IndexTableRowComponent.tsx index d9d08d8..9a86075 100644 --- a/assets/frontend/pages/VulnerabilityAnalyses/IndexTableRowComponent.tsx +++ b/assets/frontend/pages/VulnerabilityAnalyses/IndexTableRowComponent.tsx @@ -33,6 +33,11 @@ export function IndexTableRowComponent({ vulnerability_analysis_scope }) {
{vulnerability_analysis_scope.detail}
+ + + Edit + + ) } \ No newline at end of file diff --git a/lib/sectory/builders/edit_vulnerability_analysis.ex b/lib/sectory/builders/edit_vulnerability_analysis.ex new file mode 100644 index 0000000..8836fc4 --- /dev/null +++ b/lib/sectory/builders/edit_vulnerability_analysis.ex @@ -0,0 +1,70 @@ +defmodule Sectory.Builders.EditVulnerabilityAnalysis do + use Ecto.Schema + import Ecto.Changeset + + @moduledoc """ + Validate, and update existing analysis data presented by a user. + """ + + schema "sectory_builders.edit_vulnerability_analysis" do + field :state, :string + field :justification, :string + field :response, :string + field :adjusted_severity, :string + field :detail, :string + end + + def changeset(vulnerability_analysis, params \\ %{}) do + vulnerability_analysis + |> cast(params, [ + :state, + :justification, + :response, + :adjusted_severity, + :detail + ]) + |> validate_required([ + :detail, + :state, + :adjusted_severity + ]) + |> validate_length(:state, min: 1, max: 128) + |> validate_length(:justification, max: 128) + |> validate_length(:response, max: 128) + |> validate_length(:adjusted_severity, max: 128) + |> validate_length(:detail, min: 5) + end + + def edit(params) do + record = Sectory.Repo.get!(Sectory.Records.VulnerabilityAnalysis, params["id"]) + %{ + id: record.id, + state: record.state, + justification: record.justification, + response: record.response, + adjusted_severity: record.adjusted_severity, + detail: record.detail + } + end + + def update(params) do + record = Sectory.Repo.get!(Sectory.Records.VulnerabilityAnalysis, params["id"]) + changeset(record, params) + end + + def save(changeset) do + data = Ecto.Changeset.apply_changes(changeset) + record = Sectory.Repo.get!(Sectory.Records.VulnerabilityAnalysis, data.id) + va_cs = Sectory.Records.VulnerabilityAnalysis.changeset( + record, + %{ + state: data.state, + detail: data.detail, + response: data.response, + adjusted_severity: data.adjusted_severity, + justification: data.justification + } + ) + {:ok, _va_record} = Sectory.Repo.update(va_cs) + end +end diff --git a/lib/sectory/builders/vulnerability_analysis.ex b/lib/sectory/builders/new_vulnerability_analysis.ex similarity index 94% rename from lib/sectory/builders/vulnerability_analysis.ex rename to lib/sectory/builders/new_vulnerability_analysis.ex index 3242d51..edd58ff 100644 --- a/lib/sectory/builders/vulnerability_analysis.ex +++ b/lib/sectory/builders/new_vulnerability_analysis.ex @@ -1,4 +1,4 @@ -defmodule Sectory.Builders.VulnerabilityAnalysis do +defmodule Sectory.Builders.NewVulnerabilityAnalysis do use Ecto.Schema import Ecto.Changeset @@ -6,7 +6,7 @@ defmodule Sectory.Builders.VulnerabilityAnalysis do Build, validate, and persist new analysis data presented by a user. """ - schema "sectory_builders.deliverable_versions" do + schema "sectory_builders.new_vulnerability_analysis" do field :state, :string field :vulnerability_identifier, :string field :justification, :string diff --git a/lib/sectory_web/controllers/vulnerability_analysis_controller.ex b/lib/sectory_web/controllers/vulnerability_analysis_controller.ex index 423b7f9..46627c6 100644 --- a/lib/sectory_web/controllers/vulnerability_analysis_controller.ex +++ b/lib/sectory_web/controllers/vulnerability_analysis_controller.ex @@ -37,19 +37,52 @@ defmodule SectoryWeb.VulnerabilityAnalysisController do end def create(conn, params) do - cs = Sectory.Builders.VulnerabilityAnalysis.new(params) + cs = Sectory.Builders.NewVulnerabilityAnalysis.new(params) case cs.valid? do false -> conn |> assign_errors(cs) |> redirect(to: ~p"/vulnerability_analyses/new?suggested_deliverable_version_id=#{params["suggested_deliverable_version_id"]}&vulnerability_identifier=#{params["vulnerability_identifier"]}") _ -> - Sectory.Builders.VulnerabilityAnalysis.save(cs) + Sectory.Builders.NewVulnerabilityAnalysis.save(cs) conn |> redirect(to: ~p"/deliverable_versions/#{params["suggested_deliverable_version_id"]}") end end + def edit(conn, params) do + vulnerability_analysis = Sectory.Builders.EditVulnerabilityAnalysis.edit(params) + conn + |> render_inertia( + "VulnerabilityAnalyses/EditComponent", + %{ + vulnerability_analysis: %{ + id: vulnerability_analysis.id, + state: vulnerability_analysis.state, + response: vulnerability_analysis.response, + justification: vulnerability_analysis.justification, + adjusted_severity: vulnerability_analysis.adjusted_severity, + detail: vulnerability_analysis.detail + }, + update_url: ~p"/vulnerability_analyses/#{vulnerability_analysis.id}" + } + ) + end + + def update(conn, params) do + cs = Sectory.Builders.EditVulnerabilityAnalysis.update(params) + case cs.valid? do + false -> + conn + |> assign_errors(cs) + |> redirect(to: ~p"/vulnerability_analyses/#{params["id"]}/edit") + _ -> + Sectory.Builders.EditVulnerabilityAnalysis.save(cs) + conn + |> redirect(to: ~p"/vulnerability_analyses") + end + end + def deliverable_version_for_display(deliverable_version) do case deliverable_version.version do nil -> deliverable_version.git_sha @@ -66,7 +99,8 @@ defmodule SectoryWeb.VulnerabilityAnalysisController do response: r.vulnerability_analysis.response, justification: r.vulnerability_analysis.justification, adjusted_severity: r.vulnerability_analysis.adjusted_severity, - detail: r.vulnerability_analysis.detail + detail: r.vulnerability_analysis.detail, + edit_url: ~p"/vulnerability_analyses/#{r.vulnerability_analysis.id}/edit" } with_deliverable = case r.deliverable do nil -> base_scope diff --git a/lib/sectory_web/router.ex b/lib/sectory_web/router.ex index 9bfb49b..5b2b132 100644 --- a/lib/sectory_web/router.ex +++ b/lib/sectory_web/router.ex @@ -67,7 +67,7 @@ defmodule SectoryWeb.Router do scope "/version_artifacts" do get "/:id/download", VersionArtifactController, :download end - resources "/vulnerability_analyses", VulnerabilityAnalysisController, only: [:new, :create, :index] + resources "/vulnerability_analyses", VulnerabilityAnalysisController, only: [:new, :create, :edit, :update, :index] end scope "/", SectoryWeb do