From da4553beb2cf8d7cdb76d1537ae42c6d9abdd73a Mon Sep 17 00:00:00 2001 From: Sacha Al Himdani Date: Thu, 28 Aug 2025 17:57:12 +0200 Subject: [PATCH] Check snapshot type and id from url Signed-off-by: Sacha Al Himdani --- apps/console/src/components/PageError.tsx | 2 +- .../console/src/components/SnapshotBanner.tsx | 13 ++ .../SnapshotBannerQuery.graphql.ts | 23 +++- apps/console/src/hooks/graph/DatumGraph.ts | 1 + .../hooks/graph/NonconformityRegistryGraph.ts | 1 + .../DatumGraphNodeQuery.graphql.ts | 36 ++++-- ...onformityRegistryGraphNodeQuery.graphql.ts | 56 +++++---- .../organizations/data/DatumDetailsPage.tsx | 3 + .../NonconformityRegistryDetailsPage.tsx | 4 +- packages/helpers/src/index.ts | 2 +- packages/helpers/src/snapshots.ts | 13 ++ pkg/server/api/console/v1/schema.graphql | 2 + pkg/server/api/console/v1/schema/schema.go | 112 ++++++++++++++++++ pkg/server/api/console/v1/types/datum.go | 1 + .../v1/types/nonconformity_registry.go | 1 + pkg/server/api/console/v1/types/types.go | 2 + 16 files changed, 227 insertions(+), 45 deletions(-) diff --git a/apps/console/src/components/PageError.tsx b/apps/console/src/components/PageError.tsx index 893486e74..a8c414fce 100644 --- a/apps/console/src/components/PageError.tsx +++ b/apps/console/src/components/PageError.tsx @@ -32,7 +32,7 @@ export function PageError({ resetErrorBoundary, error: propsError }: Props) { } }, [location, resetErrorBoundary]); - if (!error) { + if (!error || (error && error.toString().includes("PAGE_NOT_FOUND"))) { return (

diff --git a/apps/console/src/components/SnapshotBanner.tsx b/apps/console/src/components/SnapshotBanner.tsx index 2764b2346..e8a30c43a 100644 --- a/apps/console/src/components/SnapshotBanner.tsx +++ b/apps/console/src/components/SnapshotBanner.tsx @@ -1,7 +1,9 @@ import { IconClock } from "@probo/ui"; import { useTranslate } from "@probo/i18n"; import { useLazyLoadQuery, graphql } from "react-relay"; +import { useLocation } from "react-router"; import type { SnapshotBannerQuery } from "./__generated__/SnapshotBannerQuery.graphql"; +import { getSnapshotTypeUrlPath } from "@probo/helpers"; const snapshotQuery = graphql` query SnapshotBannerQuery($snapshotId: ID!) { @@ -9,18 +11,25 @@ const snapshotQuery = graphql` ... on Snapshot { id name + type createdAt } } } `; +const isSnapshotTypeValidForUrl = (type: string, pathname: string) => { + const urlPath = getSnapshotTypeUrlPath(type); + return pathname.includes(urlPath); +}; + type Props = { snapshotId: string; }; export function SnapshotBanner({ snapshotId }: Props) { const { __, dateFormat } = useTranslate(); + const location = useLocation(); const data = useLazyLoadQuery(snapshotQuery, { snapshotId }); const snapshot = data.node; @@ -29,6 +38,10 @@ export function SnapshotBanner({ snapshotId }: Props) { return null; } + if (snapshot.type && !isSnapshotTypeValidForUrl(snapshot.type, location.pathname)) { + throw new Error("PAGE_NOT_FOUND"); + } + return (
diff --git a/apps/console/src/components/__generated__/SnapshotBannerQuery.graphql.ts b/apps/console/src/components/__generated__/SnapshotBannerQuery.graphql.ts index 5cd8f56a6..8ad92badd 100644 --- a/apps/console/src/components/__generated__/SnapshotBannerQuery.graphql.ts +++ b/apps/console/src/components/__generated__/SnapshotBannerQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<3c8b528580116deec511c979e209cfc3>> * @lightSyntaxTransform * @nogrep */ @@ -9,6 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; +export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "DATA" | "NONCONFORMITY_REGISTRIES" | "RISKS" | "VENDORS"; export type SnapshotBannerQuery$variables = { snapshotId: string; }; @@ -17,6 +18,7 @@ export type SnapshotBannerQuery$data = { readonly createdAt?: any; readonly id?: string; readonly name?: string; + readonly type?: SnapshotsType; }; }; export type SnapshotBannerQuery = { @@ -54,6 +56,13 @@ v3 = { "storageKey": null }, v4 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "type", + "storageKey": null +}, +v5 = { "alias": null, "args": null, "kind": "ScalarField", @@ -80,7 +89,8 @@ return { "selections": [ (v2/*: any*/), (v3/*: any*/), - (v4/*: any*/) + (v4/*: any*/), + (v5/*: any*/) ], "type": "Snapshot", "abstractKey": null @@ -118,7 +128,8 @@ return { "kind": "InlineFragment", "selections": [ (v3/*: any*/), - (v4/*: any*/) + (v4/*: any*/), + (v5/*: any*/) ], "type": "Snapshot", "abstractKey": null @@ -129,16 +140,16 @@ return { ] }, "params": { - "cacheID": "8f21371ececf96444bb6b00e52783573", + "cacheID": "7e026c7c030cd116b4794260934c394f", "id": null, "metadata": {}, "name": "SnapshotBannerQuery", "operationKind": "query", - "text": "query SnapshotBannerQuery(\n $snapshotId: ID!\n) {\n node(id: $snapshotId) {\n __typename\n ... on Snapshot {\n id\n name\n createdAt\n }\n id\n }\n}\n" + "text": "query SnapshotBannerQuery(\n $snapshotId: ID!\n) {\n node(id: $snapshotId) {\n __typename\n ... on Snapshot {\n id\n name\n type\n createdAt\n }\n id\n }\n}\n" } }; })(); -(node as any).hash = "1602d5b6c0ae4a3122998e4d3419af05"; +(node as any).hash = "e50a4bb5133d8e918b8b2b9d2a42f1d1"; export default node; diff --git a/apps/console/src/hooks/graph/DatumGraph.ts b/apps/console/src/hooks/graph/DatumGraph.ts index b8dfa8898..0326da523 100644 --- a/apps/console/src/hooks/graph/DatumGraph.ts +++ b/apps/console/src/hooks/graph/DatumGraph.ts @@ -19,6 +19,7 @@ export const datumNodeQuery = graphql` node(id: $dataId) { ... on Datum { id + snapshotId name dataClassification owner { diff --git a/apps/console/src/hooks/graph/NonconformityRegistryGraph.ts b/apps/console/src/hooks/graph/NonconformityRegistryGraph.ts index dd668a760..fa5648d18 100644 --- a/apps/console/src/hooks/graph/NonconformityRegistryGraph.ts +++ b/apps/console/src/hooks/graph/NonconformityRegistryGraph.ts @@ -22,6 +22,7 @@ export const nonconformityRegistryNodeQuery = graphql` node(id: $nonconformityRegistryId) { ... on NonconformityRegistry { id + snapshotId referenceId description dateIdentified diff --git a/apps/console/src/hooks/graph/__generated__/DatumGraphNodeQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/DatumGraphNodeQuery.graphql.ts index 2e51a6138..a7839444b 100644 --- a/apps/console/src/hooks/graph/__generated__/DatumGraphNodeQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/DatumGraphNodeQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<5cfbdbc980894977800a18064306f2c1>> * @lightSyntaxTransform * @nogrep */ @@ -27,6 +27,7 @@ export type DatumGraphNodeQuery$data = { readonly fullName: string; readonly id: string; }; + readonly snapshotId?: string | null | undefined; readonly updatedAt?: any; readonly vendors?: { readonly edges: ReadonlyArray<{ @@ -71,17 +72,24 @@ v3 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "name", + "name": "snapshotId", "storageKey": null }, v4 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "dataClassification", + "name": "name", "storageKey": null }, v5 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "dataClassification", + "storageKey": null +}, +v6 = { "alias": null, "args": null, "concreteType": "People", @@ -100,7 +108,7 @@ v5 = { ], "storageKey": null }, -v6 = { +v7 = { "alias": null, "args": [ { @@ -131,7 +139,7 @@ v6 = { "plural": false, "selections": [ (v2/*: any*/), - (v3/*: any*/), + (v4/*: any*/), { "alias": null, "args": null, @@ -155,7 +163,7 @@ v6 = { ], "storageKey": "vendors(first:50)" }, -v7 = { +v8 = { "alias": null, "args": null, "concreteType": "Organization", @@ -167,14 +175,14 @@ v7 = { ], "storageKey": null }, -v8 = { +v9 = { "alias": null, "args": null, "kind": "ScalarField", "name": "createdAt", "storageKey": null }, -v9 = { +v10 = { "alias": null, "args": null, "kind": "ScalarField", @@ -206,7 +214,8 @@ return { (v6/*: any*/), (v7/*: any*/), (v8/*: any*/), - (v9/*: any*/) + (v9/*: any*/), + (v10/*: any*/) ], "type": "Datum", "abstractKey": null @@ -249,7 +258,8 @@ return { (v6/*: any*/), (v7/*: any*/), (v8/*: any*/), - (v9/*: any*/) + (v9/*: any*/), + (v10/*: any*/) ], "type": "Datum", "abstractKey": null @@ -260,16 +270,16 @@ return { ] }, "params": { - "cacheID": "7dcd0ba0b57e917592a333f2368f65c4", + "cacheID": "6ed49a3413c0214dc95da9a422e484b4", "id": null, "metadata": {}, "name": "DatumGraphNodeQuery", "operationKind": "query", - "text": "query DatumGraphNodeQuery(\n $dataId: ID!\n) {\n node(id: $dataId) {\n __typename\n ... on Datum {\n id\n name\n dataClassification\n owner {\n id\n fullName\n }\n vendors(first: 50) {\n edges {\n node {\n id\n name\n websiteUrl\n category\n }\n }\n }\n organization {\n id\n }\n createdAt\n updatedAt\n }\n id\n }\n}\n" + "text": "query DatumGraphNodeQuery(\n $dataId: ID!\n) {\n node(id: $dataId) {\n __typename\n ... on Datum {\n id\n snapshotId\n name\n dataClassification\n owner {\n id\n fullName\n }\n vendors(first: 50) {\n edges {\n node {\n id\n name\n websiteUrl\n category\n }\n }\n }\n organization {\n id\n }\n createdAt\n updatedAt\n }\n id\n }\n}\n" } }; })(); -(node as any).hash = "c8a8fc6a37cce32b83f53379317d8f67"; +(node as any).hash = "2f4df20b67f8b21eda5f510f250abda1"; export default node; diff --git a/apps/console/src/hooks/graph/__generated__/NonconformityRegistryGraphNodeQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/NonconformityRegistryGraphNodeQuery.graphql.ts index b21f652a3..583ad8c9c 100644 --- a/apps/console/src/hooks/graph/__generated__/NonconformityRegistryGraphNodeQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/NonconformityRegistryGraphNodeQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<7b7982ce6c305e82103ca4422bbb7c2f>> + * @generated SignedSource<<4ea62d99e8a73491f8125cb3e8d8e4b5>> * @lightSyntaxTransform * @nogrep */ @@ -39,6 +39,7 @@ export type NonconformityRegistryGraphNodeQuery$data = { }; readonly referenceId?: string; readonly rootCause?: string; + readonly snapshotId?: string | null | undefined; readonly status?: NonconformityRegistryStatus; readonly updatedAt?: any; }; @@ -74,59 +75,66 @@ v3 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "referenceId", + "name": "snapshotId", "storageKey": null }, v4 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "description", + "name": "referenceId", "storageKey": null }, v5 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "dateIdentified", + "name": "description", "storageKey": null }, v6 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "rootCause", + "name": "dateIdentified", "storageKey": null }, v7 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "correctiveAction", + "name": "rootCause", "storageKey": null }, v8 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "dueDate", + "name": "correctiveAction", "storageKey": null }, v9 = { "alias": null, "args": null, "kind": "ScalarField", - "name": "status", + "name": "dueDate", "storageKey": null }, v10 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "status", + "storageKey": null +}, +v11 = { "alias": null, "args": null, "kind": "ScalarField", "name": "effectivenessCheck", "storageKey": null }, -v11 = [ +v12 = [ (v2/*: any*/), { "alias": null, @@ -136,7 +144,7 @@ v11 = [ "storageKey": null } ], -v12 = { +v13 = { "alias": null, "args": null, "concreteType": "Audit", @@ -152,13 +160,13 @@ v12 = { "kind": "LinkedField", "name": "framework", "plural": false, - "selections": (v11/*: any*/), + "selections": (v12/*: any*/), "storageKey": null } ], "storageKey": null }, -v13 = { +v14 = { "alias": null, "args": null, "concreteType": "People", @@ -177,24 +185,24 @@ v13 = { ], "storageKey": null }, -v14 = { +v15 = { "alias": null, "args": null, "concreteType": "Organization", "kind": "LinkedField", "name": "organization", "plural": false, - "selections": (v11/*: any*/), + "selections": (v12/*: any*/), "storageKey": null }, -v15 = { +v16 = { "alias": null, "args": null, "kind": "ScalarField", "name": "createdAt", "storageKey": null }, -v16 = { +v17 = { "alias": null, "args": null, "kind": "ScalarField", @@ -228,11 +236,12 @@ return { (v8/*: any*/), (v9/*: any*/), (v10/*: any*/), - (v12/*: any*/), + (v11/*: any*/), (v13/*: any*/), (v14/*: any*/), (v15/*: any*/), - (v16/*: any*/) + (v16/*: any*/), + (v17/*: any*/) ], "type": "NonconformityRegistry", "abstractKey": null @@ -277,11 +286,12 @@ return { (v8/*: any*/), (v9/*: any*/), (v10/*: any*/), - (v12/*: any*/), + (v11/*: any*/), (v13/*: any*/), (v14/*: any*/), (v15/*: any*/), - (v16/*: any*/) + (v16/*: any*/), + (v17/*: any*/) ], "type": "NonconformityRegistry", "abstractKey": null @@ -292,16 +302,16 @@ return { ] }, "params": { - "cacheID": "fd9bf2453d001f33ed1e32ad5784b647", + "cacheID": "ab9100da91dff02cc103e6cf3f04b9e2", "id": null, "metadata": {}, "name": "NonconformityRegistryGraphNodeQuery", "operationKind": "query", - "text": "query NonconformityRegistryGraphNodeQuery(\n $nonconformityRegistryId: ID!\n) {\n node(id: $nonconformityRegistryId) {\n __typename\n ... on NonconformityRegistry {\n id\n referenceId\n description\n dateIdentified\n rootCause\n correctiveAction\n dueDate\n status\n effectivenessCheck\n audit {\n id\n framework {\n id\n name\n }\n }\n owner {\n id\n fullName\n }\n organization {\n id\n name\n }\n createdAt\n updatedAt\n }\n id\n }\n}\n" + "text": "query NonconformityRegistryGraphNodeQuery(\n $nonconformityRegistryId: ID!\n) {\n node(id: $nonconformityRegistryId) {\n __typename\n ... on NonconformityRegistry {\n id\n snapshotId\n referenceId\n description\n dateIdentified\n rootCause\n correctiveAction\n dueDate\n status\n effectivenessCheck\n audit {\n id\n framework {\n id\n name\n }\n }\n owner {\n id\n fullName\n }\n organization {\n id\n name\n }\n createdAt\n updatedAt\n }\n id\n }\n}\n" } }; })(); -(node as any).hash = "3395719bf2203fba19ccc94d6f740014"; +(node as any).hash = "207465c315f95b9b26e7687c4ef17cbf"; export default node; diff --git a/apps/console/src/pages/organizations/data/DatumDetailsPage.tsx b/apps/console/src/pages/organizations/data/DatumDetailsPage.tsx index 401cee9ee..0e8428d03 100644 --- a/apps/console/src/pages/organizations/data/DatumDetailsPage.tsx +++ b/apps/console/src/pages/organizations/data/DatumDetailsPage.tsx @@ -27,6 +27,7 @@ import { VendorsMultiSelectField } from "/components/form/VendorsMultiSelectFiel import { useFormWithSchema } from "/hooks/useFormWithSchema"; import z from "zod"; import { SnapshotBanner } from "/components/SnapshotBanner"; +import { validateSnapshotConsistency } from "@probo/helpers"; import type { DatumGraphNodeQuery } from "/hooks/graph/__generated__/DatumGraphNodeQuery.graphql"; const updateDatumSchema = z.object({ @@ -51,6 +52,8 @@ export default function DatumDetailsPage(props: Props) { const datumEntry = queryData.node; + validateSnapshotConsistency(datumEntry, snapshotId); + const { __ } = useTranslate(); const organizationId = useOrganizationId(); diff --git a/apps/console/src/pages/organizations/nonconformityRegistries/NonconformityRegistryDetailsPage.tsx b/apps/console/src/pages/organizations/nonconformityRegistries/NonconformityRegistryDetailsPage.tsx index 0fdce356a..07548d335 100644 --- a/apps/console/src/pages/organizations/nonconformityRegistries/NonconformityRegistryDetailsPage.tsx +++ b/apps/console/src/pages/organizations/nonconformityRegistries/NonconformityRegistryDetailsPage.tsx @@ -32,7 +32,7 @@ import { PeopleSelectField } from "/components/form/PeopleSelectField"; import { AuditSelectField } from "/components/form/AuditSelectField"; import { useFormWithSchema } from "/hooks/useFormWithSchema"; import z from "zod"; -import { getStatusVariant, getStatusLabel, formatDatetime, getNonconformityRegistryStatusOptions } from "@probo/helpers"; +import { getStatusVariant, getStatusLabel, formatDatetime, getNonconformityRegistryStatusOptions, validateSnapshotConsistency } from "@probo/helpers"; import type { NonconformityRegistryGraphNodeQuery } from "/hooks/graph/__generated__/NonconformityRegistryGraphNodeQuery.graphql"; const updateRegistrySchema = z.object({ @@ -63,6 +63,8 @@ export default function NonconformityRegistryDetailsPage(props: Props) { const { snapshotId } = useParams<{ snapshotId?: string }>(); const isSnapshotMode = Boolean(snapshotId); + validateSnapshotConsistency(registry, snapshotId); + const deleteRegistry = useDeleteNonconformityRegistry( { id: registry.id!, referenceId: registry.referenceId! }, ConnectionHandler.getConnectionID( diff --git a/packages/helpers/src/index.ts b/packages/helpers/src/index.ts index a6ee4ebf8..e340e3b18 100644 --- a/packages/helpers/src/index.ts +++ b/packages/helpers/src/index.ts @@ -15,7 +15,7 @@ export { certificationCategoryLabel, certifications } from "./certifications"; export { availableFrameworks } from "./frameworks"; export { getDocumentTypeLabel, documentTypes } from "./documents"; export { getAssetTypeVariant, getCriticityVariant } from "./assets"; -export { getSnapshotTypeLabel, getSnapshotTypeUrlPath, snapshotTypes } from "./snapshots"; +export { getSnapshotTypeLabel, getSnapshotTypeUrlPath, snapshotTypes, validateSnapshotConsistency } from "./snapshots"; export { getAuditStateLabel, getAuditStateVariant, auditStates } from "./audits"; export { getStatusVariant, getStatusLabel, getNonconformityRegistryStatusOptions, getComplianceRegistryStatusOptions, registryStatuses } from "./registryStatus"; export { promisifyMutation } from "./relay"; diff --git a/packages/helpers/src/snapshots.ts b/packages/helpers/src/snapshots.ts index 8948ba3aa..1d4f3203d 100644 --- a/packages/helpers/src/snapshots.ts +++ b/packages/helpers/src/snapshots.ts @@ -38,3 +38,16 @@ export function getSnapshotTypeUrlPath(type?: string): string { return ""; } } + +export interface SnapshotableResource { + snapshotId?: string | null | undefined; +} + +export function validateSnapshotConsistency( + resource: SnapshotableResource | null | undefined, + urlSnapshotId?: string | null | undefined +): void { + if (resource && resource.snapshotId !== (urlSnapshotId ?? null)) { + throw new Error("PAGE_NOT_FOUND"); + } +} diff --git a/pkg/server/api/console/v1/schema.graphql b/pkg/server/api/console/v1/schema.graphql index 25ce434a8..983f4d792 100644 --- a/pkg/server/api/console/v1/schema.graphql +++ b/pkg/server/api/console/v1/schema.graphql @@ -1703,6 +1703,7 @@ type Audit implements Node { type NonconformityRegistry implements Node { id: ID! + snapshotId: ID organization: Organization! @goField(forceResolver: true) referenceId: String! description: String @@ -3689,6 +3690,7 @@ type DeleteAssetPayload { type Datum implements Node { id: ID! + snapshotId: ID name: String! dataClassification: DataClassification! owner: People! @goField(forceResolver: true) diff --git a/pkg/server/api/console/v1/schema/schema.go b/pkg/server/api/console/v1/schema/schema.go index b49966185..6145ff623 100644 --- a/pkg/server/api/console/v1/schema/schema.go +++ b/pkg/server/api/console/v1/schema/schema.go @@ -403,6 +403,7 @@ type ComplexityRoot struct { Name func(childComplexity int) int Organization func(childComplexity int) int Owner func(childComplexity int) int + SnapshotID func(childComplexity int) int UpdatedAt func(childComplexity int) int Vendors func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorOrderBy) int } @@ -851,6 +852,7 @@ type ComplexityRoot struct { Owner func(childComplexity int) int ReferenceID func(childComplexity int) int RootCause func(childComplexity int) int + SnapshotID func(childComplexity int) int Status func(childComplexity int) int UpdatedAt func(childComplexity int) int } @@ -2831,6 +2833,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.Datum.Owner(childComplexity), true + case "Datum.snapshotId": + if e.complexity.Datum.SnapshotID == nil { + break + } + + return e.complexity.Datum.SnapshotID(childComplexity), true + case "Datum.updatedAt": if e.complexity.Datum.UpdatedAt == nil { break @@ -5271,6 +5280,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.NonconformityRegistry.RootCause(childComplexity), true + case "NonconformityRegistry.snapshotId": + if e.complexity.NonconformityRegistry.SnapshotID == nil { + break + } + + return e.complexity.NonconformityRegistry.SnapshotID(childComplexity), true + case "NonconformityRegistry.status": if e.complexity.NonconformityRegistry.Status == nil { break @@ -9579,6 +9595,7 @@ type Audit implements Node { type NonconformityRegistry implements Node { id: ID! + snapshotId: ID organization: Organization! @goField(forceResolver: true) referenceId: String! description: String @@ -11565,6 +11582,7 @@ type DeleteAssetPayload { type Datum implements Node { id: ID! + snapshotId: ID name: String! dataClassification: DataClassification! owner: People! @goField(forceResolver: true) @@ -26001,6 +26019,47 @@ func (ec *executionContext) fieldContext_Datum_id(_ context.Context, field graph return fc, nil } +func (ec *executionContext) _Datum_snapshotId(ctx context.Context, field graphql.CollectedField, obj *types.Datum) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Datum_snapshotId(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.SnapshotID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*gid.GID) + fc.Result = res + return ec.marshalOID2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Datum_snapshotId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Datum", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _Datum_name(ctx context.Context, field graphql.CollectedField, obj *types.Datum) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Datum_name(ctx, field) if err != nil { @@ -26633,6 +26692,8 @@ func (ec *executionContext) fieldContext_DatumEdge_node(_ context.Context, field switch field.Name { case "id": return ec.fieldContext_Datum_id(ctx, field) + case "snapshotId": + return ec.fieldContext_Datum_snapshotId(ctx, field) case "name": return ec.fieldContext_Datum_name(ctx, field) case "dataClassification": @@ -39897,6 +39958,47 @@ func (ec *executionContext) fieldContext_NonconformityRegistry_id(_ context.Cont return fc, nil } +func (ec *executionContext) _NonconformityRegistry_snapshotId(ctx context.Context, field graphql.CollectedField, obj *types.NonconformityRegistry) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_NonconformityRegistry_snapshotId(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.SnapshotID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*gid.GID) + fc.Result = res + return ec.marshalOID2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_NonconformityRegistry_snapshotId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "NonconformityRegistry", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _NonconformityRegistry_organization(ctx context.Context, field graphql.CollectedField, obj *types.NonconformityRegistry) (ret graphql.Marshaler) { fc, err := ec.fieldContext_NonconformityRegistry_organization(ctx, field) if err != nil { @@ -40787,6 +40889,8 @@ func (ec *executionContext) fieldContext_NonconformityRegistryEdge_node(_ contex switch field.Name { case "id": return ec.fieldContext_NonconformityRegistry_id(ctx, field) + case "snapshotId": + return ec.fieldContext_NonconformityRegistry_snapshotId(ctx, field) case "organization": return ec.fieldContext_NonconformityRegistry_organization(ctx, field) case "referenceId": @@ -49740,6 +49844,8 @@ func (ec *executionContext) fieldContext_UpdateDatumPayload_datum(_ context.Cont switch field.Name { case "id": return ec.fieldContext_Datum_id(ctx, field) + case "snapshotId": + return ec.fieldContext_Datum_snapshotId(ctx, field) case "name": return ec.fieldContext_Datum_name(ctx, field) case "dataClassification": @@ -50072,6 +50178,8 @@ func (ec *executionContext) fieldContext_UpdateNonconformityRegistryPayload_nonc switch field.Name { case "id": return ec.fieldContext_NonconformityRegistry_id(ctx, field) + case "snapshotId": + return ec.fieldContext_NonconformityRegistry_snapshotId(ctx, field) case "organization": return ec.fieldContext_NonconformityRegistry_organization(ctx, field) case "referenceId": @@ -68827,6 +68935,8 @@ func (ec *executionContext) _Datum(ctx context.Context, sel ast.SelectionSet, ob if out.Values[i] == graphql.Null { atomic.AddUint32(&out.Invalids, 1) } + case "snapshotId": + out.Values[i] = ec._Datum_snapshotId(ctx, field, obj) case "name": out.Values[i] = ec._Datum_name(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -73267,6 +73377,8 @@ func (ec *executionContext) _NonconformityRegistry(ctx context.Context, sel ast. if out.Values[i] == graphql.Null { atomic.AddUint32(&out.Invalids, 1) } + case "snapshotId": + out.Values[i] = ec._NonconformityRegistry_snapshotId(ctx, field, obj) case "organization": field := field diff --git a/pkg/server/api/console/v1/types/datum.go b/pkg/server/api/console/v1/types/datum.go index a30605c3d..ca5c90c42 100644 --- a/pkg/server/api/console/v1/types/datum.go +++ b/pkg/server/api/console/v1/types/datum.go @@ -56,6 +56,7 @@ func NewDatum(d *coredata.Datum) *Datum { return &Datum{ ID: d.ID, Name: d.Name, + SnapshotID: d.SnapshotID, DataClassification: d.DataClassification, CreatedAt: d.CreatedAt, UpdatedAt: d.UpdatedAt, diff --git a/pkg/server/api/console/v1/types/nonconformity_registry.go b/pkg/server/api/console/v1/types/nonconformity_registry.go index a71b9a846..3ce81d9ce 100644 --- a/pkg/server/api/console/v1/types/nonconformity_registry.go +++ b/pkg/server/api/console/v1/types/nonconformity_registry.go @@ -59,6 +59,7 @@ func NewNonconformityRegistry(nr *coredata.NonconformityRegistry) *Nonconformity return &NonconformityRegistry{ ID: nr.ID, ReferenceID: nr.ReferenceID, + SnapshotID: nr.SnapshotID, Description: nr.Description, DateIdentified: nr.DateIdentified, RootCause: nr.RootCause, diff --git a/pkg/server/api/console/v1/types/types.go b/pkg/server/api/console/v1/types/types.go index ee0b99e1f..a88d6c677 100644 --- a/pkg/server/api/console/v1/types/types.go +++ b/pkg/server/api/console/v1/types/types.go @@ -600,6 +600,7 @@ type CreateVendorServicePayload struct { type Datum struct { ID gid.GID `json:"id"` + SnapshotID *gid.GID `json:"snapshotId,omitempty"` Name string `json:"name"` DataClassification coredata.DataClassification `json:"dataClassification"` Owner *People `json:"owner"` @@ -1115,6 +1116,7 @@ type Mutation struct { type NonconformityRegistry struct { ID gid.GID `json:"id"` + SnapshotID *gid.GID `json:"snapshotId,omitempty"` Organization *Organization `json:"organization"` ReferenceID string `json:"referenceId"` Description *string `json:"description,omitempty"`