Add multi-approver support
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
committed by
Sacha Al Himdani
parent
3d8c7c4dd6
commit
93c7b0c2dc
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<91bce548869c16de31b1edc3445874d2>>
|
||||
* @generated SignedSource<<0948c131a30705ee3921f60bbd40c3cb>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -14,7 +14,7 @@ export type DocumentClassification = "CONFIDENTIAL" | "INTERNAL" | "PUBLIC" | "S
|
||||
export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE";
|
||||
export type TrustCenterVisibility = "NONE" | "PRIVATE" | "PUBLIC";
|
||||
export type UpdateDocumentInput = {
|
||||
approverId?: string | null | undefined;
|
||||
approverIds?: ReadonlyArray<string> | null | undefined;
|
||||
classification?: DocumentClassification | null | undefined;
|
||||
content?: string | null | undefined;
|
||||
documentType?: DocumentType | null | undefined;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<4aabb7a5e515082b00152627b1f7c2f1>>
|
||||
* @generated SignedSource<<a96a88e4c176f254788930b251e7108e>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -14,7 +14,7 @@ export type DocumentClassification = "CONFIDENTIAL" | "INTERNAL" | "PUBLIC" | "S
|
||||
export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE";
|
||||
export type TrustCenterVisibility = "NONE" | "PRIVATE" | "PUBLIC";
|
||||
export type CreateDocumentInput = {
|
||||
approverId: string;
|
||||
approverIds: ReadonlyArray<string>;
|
||||
classification: DocumentClassification;
|
||||
content: string;
|
||||
documentType: DocumentType;
|
||||
@@ -210,22 +210,50 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"args": [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
}
|
||||
],
|
||||
"concreteType": "ProfileConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "approver",
|
||||
"name": "approvers",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"concreteType": "ProfileEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
"storageKey": "approvers(first:100)"
|
||||
},
|
||||
{
|
||||
"alias": "lastVersion",
|
||||
@@ -358,12 +386,12 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "1ec326debfa93388837c2779cb693dca",
|
||||
"cacheID": "927e922143fa7eac4270e7ac0ae7da39",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "CreateDocumentDialogMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation CreateDocumentDialogMutation(\n $input: CreateDocumentInput!\n) {\n createDocument(input: $input) {\n documentEdge {\n node {\n id\n ...DocumentListItemFragment\n }\n }\n }\n}\n\nfragment DocumentListItemFragment on Document {\n id\n title\n documentType\n classification\n updatedAt\n canDelete: permission(action: \"core:document:delete\")\n approver {\n id\n fullName\n }\n lastVersion: versions(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n status\n version\n signatures(first: 0, filter: {activeContract: true}) {\n totalCount\n }\n signedSignatures: signatures(first: 0, filter: {states: [SIGNED], activeContract: true}) {\n totalCount\n }\n }\n }\n }\n}\n"
|
||||
"text": "mutation CreateDocumentDialogMutation(\n $input: CreateDocumentInput!\n) {\n createDocument(input: $input) {\n documentEdge {\n node {\n id\n ...DocumentListItemFragment\n }\n }\n }\n}\n\nfragment DocumentListItemFragment on Document {\n id\n title\n documentType\n classification\n updatedAt\n canDelete: permission(action: \"core:document:delete\")\n approvers(first: 100) {\n edges {\n node {\n id\n fullName\n }\n }\n }\n lastVersion: versions(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n status\n version\n signatures(first: 0, filter: {activeContract: true}) {\n totalCount\n }\n signedSignatures: signatures(first: 0, filter: {states: [SIGNED], activeContract: true}) {\n totalCount\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<5cb0be6e5ab775bdf7d509d9789e9821>>
|
||||
* @generated SignedSource<<54fdf6ba6490381a269cd77379fe1810>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -13,7 +13,7 @@ export type DocumentClassification = "CONFIDENTIAL" | "INTERNAL" | "PUBLIC" | "S
|
||||
export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE";
|
||||
export type TrustCenterVisibility = "NONE" | "PRIVATE" | "PUBLIC";
|
||||
export type UpdateDocumentInput = {
|
||||
approverId?: string | null | undefined;
|
||||
approverIds?: ReadonlyArray<string> | null | undefined;
|
||||
classification?: DocumentClassification | null | undefined;
|
||||
content?: string | null | undefined;
|
||||
documentType?: DocumentType | null | undefined;
|
||||
@@ -27,9 +27,13 @@ export type DocumentLayoutDrawerMutation$variables = {
|
||||
export type DocumentLayoutDrawerMutation$data = {
|
||||
readonly updateDocument: {
|
||||
readonly document: {
|
||||
readonly approver: {
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
readonly approvers: {
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly classification: DocumentClassification;
|
||||
readonly documentType: DocumentType;
|
||||
@@ -97,22 +101,50 @@ v2 = [
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"args": [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
}
|
||||
],
|
||||
"concreteType": "ProfileConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "approver",
|
||||
"name": "approvers",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"concreteType": "ProfileEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
"storageKey": "approvers(first:100)"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
@@ -139,16 +171,16 @@ return {
|
||||
"selections": (v2/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "717ce480e61acba39409ff42ee5344cb",
|
||||
"cacheID": "e92e7774c449389137a3e5fb1b037e8a",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "DocumentLayoutDrawerMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation DocumentLayoutDrawerMutation(\n $input: UpdateDocumentInput!\n) {\n updateDocument(input: $input) {\n document {\n id\n documentType\n classification\n approver {\n id\n fullName\n }\n }\n }\n}\n"
|
||||
"text": "mutation DocumentLayoutDrawerMutation(\n $input: UpdateDocumentInput!\n) {\n updateDocument(input: $input) {\n document {\n id\n documentType\n classification\n approvers(first: 100) {\n edges {\n node {\n id\n fullName\n }\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "815cb617b0685f018afe95e97c910771";
|
||||
(node as any).hash = "6e9b5aa2c9ba01c18bf26c514c3fbcd3";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<f22c42dfa1b8b70ebed9f29c56d42069>>
|
||||
* @generated SignedSource<<547f6c8756b51ff46a73158262f78e8e>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -12,6 +12,14 @@ import { ReaderFragment } from 'relay-runtime';
|
||||
export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE";
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type DocumentLayoutDrawer_documentFragment$data = {
|
||||
readonly approvers: {
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly canUpdate: boolean;
|
||||
readonly documentType: DocumentType;
|
||||
readonly id: string;
|
||||
@@ -22,19 +30,21 @@ export type DocumentLayoutDrawer_documentFragment$key = {
|
||||
readonly " $fragmentSpreads": FragmentRefs<"DocumentLayoutDrawer_documentFragment">;
|
||||
};
|
||||
|
||||
const node: ReaderFragment = {
|
||||
const node: ReaderFragment = (function(){
|
||||
var v0 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"argumentDefinitions": [],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "DocumentLayoutDrawer_documentFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -54,12 +64,60 @@ const node: ReaderFragment = {
|
||||
"kind": "ScalarField",
|
||||
"name": "permission",
|
||||
"storageKey": "permission(action:\"core:document:update\")"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
}
|
||||
],
|
||||
"concreteType": "ProfileConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "approvers",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ProfileEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": "approvers(first:100)"
|
||||
}
|
||||
],
|
||||
"type": "Document",
|
||||
"abstractKey": null
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "0f2e539cf30c4e116fe81392605b1481";
|
||||
(node as any).hash = "ffc32318ed0df6b2992eca91bef297e5";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<a1338ba7fb986ab8e4f5d1e0355a4671>>
|
||||
* @generated SignedSource<<7464a4e3e5b2b5b72a6ecda47b5dace7>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -13,10 +13,6 @@ export type DocumentClassification = "CONFIDENTIAL" | "INTERNAL" | "PUBLIC" | "S
|
||||
export type DocumentStatus = "DRAFT" | "PUBLISHED";
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type DocumentLayoutDrawer_versionFragment$data = {
|
||||
readonly approver: {
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
};
|
||||
readonly classification: DocumentClassification;
|
||||
readonly id: string;
|
||||
readonly publishedAt: string | null | undefined;
|
||||
@@ -30,45 +26,24 @@ export type DocumentLayoutDrawer_versionFragment$key = {
|
||||
readonly " $fragmentSpreads": FragmentRefs<"DocumentLayoutDrawer_versionFragment">;
|
||||
};
|
||||
|
||||
const node: ReaderFragment = (function(){
|
||||
var v0 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
const node: ReaderFragment = {
|
||||
"argumentDefinitions": [],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "DocumentLayoutDrawer_versionFragment",
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "classification",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"kind": "LinkedField",
|
||||
"name": "approver",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"kind": "ScalarField",
|
||||
"name": "classification",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
@@ -103,8 +78,7 @@ return {
|
||||
"type": "DocumentVersion",
|
||||
"abstractKey": null
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "63b956326e98c7620715250f4e7d1129";
|
||||
(node as any).hash = "ebe62fad4b4044be35adb9ba4979a45a";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<41d49c06d7dfad15f6c1d39cd9eddc80>>
|
||||
* @generated SignedSource<<fa40a22c2297c683c649ccac9f6ebe50>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -275,32 +275,13 @@ v19 = {
|
||||
"storageKey": null
|
||||
},
|
||||
v20 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"kind": "LinkedField",
|
||||
"name": "approver",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
v21 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "updatedAt",
|
||||
"storageKey": null
|
||||
},
|
||||
v22 = {
|
||||
v21 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
@@ -572,6 +553,53 @@ return {
|
||||
"name": "documentType",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
}
|
||||
],
|
||||
"concreteType": "ProfileConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "approvers",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ProfileEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": "approvers(first:100)"
|
||||
},
|
||||
{
|
||||
"condition": "versionSpecified",
|
||||
"kind": "Condition",
|
||||
@@ -608,7 +636,6 @@ return {
|
||||
(v19/*: any*/),
|
||||
(v20/*: any*/),
|
||||
(v21/*: any*/),
|
||||
(v22/*: any*/),
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/)
|
||||
],
|
||||
@@ -653,7 +680,6 @@ return {
|
||||
(v19/*: any*/),
|
||||
(v20/*: any*/),
|
||||
(v21/*: any*/),
|
||||
(v22/*: any*/),
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/)
|
||||
],
|
||||
@@ -668,12 +694,12 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "3e4d94e71ac7cf5c557b5ee59e0917ed",
|
||||
"cacheID": "4291fe2afc2c86c77cbfd01d05f16e75",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "DocumentLayoutQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query DocumentLayoutQuery(\n $documentId: ID!\n $versionId: ID!\n $versionSpecified: Boolean!\n) {\n version: node(id: $versionId) @include(if: $versionSpecified) {\n __typename\n ... on DocumentVersion {\n id\n status\n ...DocumentActionsDropdown_versionFragment\n ...DocumentLayoutDrawer_versionFragment\n signatures(first: 0, filter: {activeContract: true}) {\n totalCount\n }\n signedSignatures: signatures(first: 0, filter: {states: [SIGNED], activeContract: true}) {\n totalCount\n }\n }\n id\n }\n document: node(id: $documentId) {\n __typename\n ... on Document {\n id\n title\n canPublish: permission(action: \"core:document-version:publish\")\n controlInfo: controls(first: 0) {\n totalCount\n }\n ...DocumentTitleFormFragment\n ...DocumentActionsDropdown_documentFragment\n ...DocumentLayoutDrawer_documentFragment\n lastVersion: versions(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) @skip(if: $versionSpecified) {\n edges {\n node {\n id\n status\n ...DocumentActionsDropdown_versionFragment\n ...DocumentLayoutDrawer_versionFragment\n signatures(first: 0, filter: {activeContract: true}) {\n totalCount\n }\n signedSignatures: signatures(first: 0, filter: {states: [SIGNED], activeContract: true}) {\n totalCount\n }\n }\n }\n }\n }\n id\n }\n}\n\nfragment DocumentActionsDropdown_documentFragment on Document {\n id\n title\n canUpdate: permission(action: \"core:document:update\")\n canDelete: permission(action: \"core:document:delete\")\n versions(first: 20) {\n totalCount\n }\n ...UpdateVersionDialogFragment\n}\n\nfragment DocumentActionsDropdown_versionFragment on DocumentVersion {\n id\n version\n status\n canDeleteDraft: permission(action: \"core:document-version:delete-draft\")\n}\n\nfragment DocumentLayoutDrawer_documentFragment on Document {\n id\n documentType\n canUpdate: permission(action: \"core:document:update\")\n}\n\nfragment DocumentLayoutDrawer_versionFragment on DocumentVersion {\n id\n classification\n approver {\n id\n fullName\n }\n version\n status\n updatedAt\n publishedAt\n}\n\nfragment DocumentTitleFormFragment on Document {\n id\n title\n canUpdate: permission(action: \"core:document:update\")\n}\n\nfragment UpdateVersionDialogFragment on Document {\n id\n versions(first: 20) {\n edges {\n node {\n id\n status\n content\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n"
|
||||
"text": "query DocumentLayoutQuery(\n $documentId: ID!\n $versionId: ID!\n $versionSpecified: Boolean!\n) {\n version: node(id: $versionId) @include(if: $versionSpecified) {\n __typename\n ... on DocumentVersion {\n id\n status\n ...DocumentActionsDropdown_versionFragment\n ...DocumentLayoutDrawer_versionFragment\n signatures(first: 0, filter: {activeContract: true}) {\n totalCount\n }\n signedSignatures: signatures(first: 0, filter: {states: [SIGNED], activeContract: true}) {\n totalCount\n }\n }\n id\n }\n document: node(id: $documentId) {\n __typename\n ... on Document {\n id\n title\n canPublish: permission(action: \"core:document-version:publish\")\n controlInfo: controls(first: 0) {\n totalCount\n }\n ...DocumentTitleFormFragment\n ...DocumentActionsDropdown_documentFragment\n ...DocumentLayoutDrawer_documentFragment\n lastVersion: versions(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) @skip(if: $versionSpecified) {\n edges {\n node {\n id\n status\n ...DocumentActionsDropdown_versionFragment\n ...DocumentLayoutDrawer_versionFragment\n signatures(first: 0, filter: {activeContract: true}) {\n totalCount\n }\n signedSignatures: signatures(first: 0, filter: {states: [SIGNED], activeContract: true}) {\n totalCount\n }\n }\n }\n }\n }\n id\n }\n}\n\nfragment DocumentActionsDropdown_documentFragment on Document {\n id\n title\n canUpdate: permission(action: \"core:document:update\")\n canDelete: permission(action: \"core:document:delete\")\n versions(first: 20) {\n totalCount\n }\n ...UpdateVersionDialogFragment\n}\n\nfragment DocumentActionsDropdown_versionFragment on DocumentVersion {\n id\n version\n status\n canDeleteDraft: permission(action: \"core:document-version:delete-draft\")\n}\n\nfragment DocumentLayoutDrawer_documentFragment on Document {\n id\n documentType\n canUpdate: permission(action: \"core:document:update\")\n approvers(first: 100) {\n edges {\n node {\n id\n fullName\n }\n }\n }\n}\n\nfragment DocumentLayoutDrawer_versionFragment on DocumentVersion {\n id\n classification\n version\n status\n updatedAt\n publishedAt\n}\n\nfragment DocumentTitleFormFragment on Document {\n id\n title\n canUpdate: permission(action: \"core:document:update\")\n}\n\nfragment UpdateVersionDialogFragment on Document {\n id\n versions(first: 20) {\n edges {\n node {\n id\n status\n content\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<ac954cbaf8e5e859cbf2112ce60b3047>>
|
||||
* @generated SignedSource<<de4e9afc3a3f6d68664e55bfad5952ff>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -14,9 +14,13 @@ export type DocumentStatus = "DRAFT" | "PUBLISHED";
|
||||
export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE";
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type DocumentListItemFragment$data = {
|
||||
readonly approver: {
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
readonly approvers: {
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly canDelete: boolean;
|
||||
readonly classification: DocumentClassification;
|
||||
@@ -118,22 +122,50 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"args": [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
}
|
||||
],
|
||||
"concreteType": "ProfileConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "approver",
|
||||
"name": "approvers",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"concreteType": "ProfileEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
"storageKey": "approvers(first:100)"
|
||||
},
|
||||
{
|
||||
"alias": "lastVersion",
|
||||
@@ -244,6 +276,6 @@ return {
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "18456198eadac7ae24bbeebf0f75b5c9";
|
||||
(node as any).hash = "440108e302ffc0f15018c14a9e922e88";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<7ed1236265330f981095a621f4462123>>
|
||||
* @generated SignedSource<<5e613b9c850d6b80e1f133ee1d190845>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -14,7 +14,7 @@ export type DocumentClassification = "CONFIDENTIAL" | "INTERNAL" | "PUBLIC" | "S
|
||||
export type DocumentType = "ISMS" | "OTHER" | "POLICY" | "PROCEDURE";
|
||||
export type TrustCenterVisibility = "NONE" | "PRIVATE" | "PUBLIC";
|
||||
export type UpdateDocumentInput = {
|
||||
approverId?: string | null | undefined;
|
||||
approverIds?: ReadonlyArray<string> | null | undefined;
|
||||
classification?: DocumentClassification | null | undefined;
|
||||
content?: string | null | undefined;
|
||||
documentType?: DocumentType | null | undefined;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<bbb5bdb7a678a554aeb043bc7e2941f0>>
|
||||
* @generated SignedSource<<e4b70bd5e8e7ea7e8bb4f66fac469dde>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -298,22 +298,50 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"args": [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
}
|
||||
],
|
||||
"concreteType": "ProfileConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "approver",
|
||||
"name": "approvers",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v12/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"concreteType": "ProfileEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v12/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
"storageKey": "approvers(first:100)"
|
||||
},
|
||||
{
|
||||
"alias": "lastVersion",
|
||||
@@ -507,12 +535,12 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "0e6f334d4bea09ecf47fe18b87ef3b84",
|
||||
"cacheID": "232b7e2c41d7603f54a3de844506ce08",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "DocumentsListQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query DocumentsListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 50\n $last: Int = null\n $order: DocumentOrder = {field: TITLE, direction: ASC}\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...DocumentListFragment_16fISc\n id\n }\n}\n\nfragment DocumentListFragment_16fISc on Organization {\n documents(first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n edges {\n node {\n id\n canUpdate: permission(action: \"core:document:update\")\n canDelete: permission(action: \"core:document:delete\")\n canRequestSignatures: permission(action: \"core:document-version:request-signature\")\n ...DocumentListItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment DocumentListItemFragment on Document {\n id\n title\n documentType\n classification\n updatedAt\n canDelete: permission(action: \"core:document:delete\")\n approver {\n id\n fullName\n }\n lastVersion: versions(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n status\n version\n signatures(first: 0, filter: {activeContract: true}) {\n totalCount\n }\n signedSignatures: signatures(first: 0, filter: {states: [SIGNED], activeContract: true}) {\n totalCount\n }\n }\n }\n }\n}\n"
|
||||
"text": "query DocumentsListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 50\n $last: Int = null\n $order: DocumentOrder = {field: TITLE, direction: ASC}\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...DocumentListFragment_16fISc\n id\n }\n}\n\nfragment DocumentListFragment_16fISc on Organization {\n documents(first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n edges {\n node {\n id\n canUpdate: permission(action: \"core:document:update\")\n canDelete: permission(action: \"core:document:delete\")\n canRequestSignatures: permission(action: \"core:document-version:request-signature\")\n ...DocumentListItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment DocumentListItemFragment on Document {\n id\n title\n documentType\n classification\n updatedAt\n canDelete: permission(action: \"core:document:delete\")\n approvers(first: 100) {\n edges {\n node {\n id\n fullName\n }\n }\n }\n lastVersion: versions(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n status\n version\n signatures(first: 0, filter: {activeContract: true}) {\n totalCount\n }\n signedSignatures: signatures(first: 0, filter: {states: [SIGNED], activeContract: true}) {\n totalCount\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<dcfc5a0f97ee1ee02c8679797141e265>>
|
||||
* @generated SignedSource<<ea3e34a592ca995eba32df84e7f42c24>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -313,22 +313,50 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"args": [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
}
|
||||
],
|
||||
"concreteType": "ProfileConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "approver",
|
||||
"name": "approvers",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v8/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"concreteType": "ProfileEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v8/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
"storageKey": "approvers(first:100)"
|
||||
},
|
||||
{
|
||||
"alias": "lastVersion",
|
||||
@@ -523,12 +551,12 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "5d465e00a354c06dc571df056624dd39",
|
||||
"cacheID": "638d1d0f41916e750ecb5ac9312b0c8c",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "DocumentsPageQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query DocumentsPageQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n canCreateDocument: permission(action: \"core:document:create\")\n ...DocumentListFragment_1WMmEg\n documents(first: 50, orderBy: {field: TITLE, direction: ASC}) {\n edges {\n node {\n canSendSigningNotifications: permission(action: \"core:document:send-signing-notifications\")\n id\n }\n }\n }\n }\n id\n }\n}\n\nfragment DocumentListFragment_1WMmEg on Organization {\n documents(first: 50, orderBy: {field: TITLE, direction: ASC}) {\n edges {\n node {\n id\n canUpdate: permission(action: \"core:document:update\")\n canDelete: permission(action: \"core:document:delete\")\n canRequestSignatures: permission(action: \"core:document-version:request-signature\")\n ...DocumentListItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment DocumentListItemFragment on Document {\n id\n title\n documentType\n classification\n updatedAt\n canDelete: permission(action: \"core:document:delete\")\n approver {\n id\n fullName\n }\n lastVersion: versions(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n status\n version\n signatures(first: 0, filter: {activeContract: true}) {\n totalCount\n }\n signedSignatures: signatures(first: 0, filter: {states: [SIGNED], activeContract: true}) {\n totalCount\n }\n }\n }\n }\n}\n"
|
||||
"text": "query DocumentsPageQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n canCreateDocument: permission(action: \"core:document:create\")\n ...DocumentListFragment_1WMmEg\n documents(first: 50, orderBy: {field: TITLE, direction: ASC}) {\n edges {\n node {\n canSendSigningNotifications: permission(action: \"core:document:send-signing-notifications\")\n id\n }\n }\n }\n }\n id\n }\n}\n\nfragment DocumentListFragment_1WMmEg on Organization {\n documents(first: 50, orderBy: {field: TITLE, direction: ASC}) {\n edges {\n node {\n id\n canUpdate: permission(action: \"core:document:update\")\n canDelete: permission(action: \"core:document:delete\")\n canRequestSignatures: permission(action: \"core:document-version:request-signature\")\n ...DocumentListItemFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n\nfragment DocumentListItemFragment on Document {\n id\n title\n documentType\n classification\n updatedAt\n canDelete: permission(action: \"core:document:delete\")\n approvers(first: 100) {\n edges {\n node {\n id\n fullName\n }\n }\n }\n lastVersion: versions(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n status\n version\n signatures(first: 0, filter: {activeContract: true}) {\n totalCount\n }\n signedSignatures: signatures(first: 0, filter: {states: [SIGNED], activeContract: true}) {\n totalCount\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<ca358b419eca687c5ba8119e7de24829>>
|
||||
* @generated SignedSource<<3d906005c4507bfced1f9d7036939157>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -192,22 +192,50 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"args": [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
}
|
||||
],
|
||||
"concreteType": "ProfileConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "approver",
|
||||
"name": "approvers",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"concreteType": "ProfileEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Profile",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
"storageKey": "approvers(first:100)"
|
||||
},
|
||||
{
|
||||
"alias": "lastVersion",
|
||||
@@ -324,12 +352,12 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "0672eb52643ef05e90565df777644a7b",
|
||||
"cacheID": "a62979260c1527e43c12c1effa025815",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "PublishDocumentsDialogMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation PublishDocumentsDialogMutation(\n $input: BulkPublishDocumentVersionsInput!\n) {\n bulkPublishDocumentVersions(input: $input) {\n documentEdges {\n node {\n id\n ...DocumentListItemFragment\n }\n }\n }\n}\n\nfragment DocumentListItemFragment on Document {\n id\n title\n documentType\n classification\n updatedAt\n canDelete: permission(action: \"core:document:delete\")\n approver {\n id\n fullName\n }\n lastVersion: versions(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n status\n version\n signatures(first: 0, filter: {activeContract: true}) {\n totalCount\n }\n signedSignatures: signatures(first: 0, filter: {states: [SIGNED], activeContract: true}) {\n totalCount\n }\n }\n }\n }\n}\n"
|
||||
"text": "mutation PublishDocumentsDialogMutation(\n $input: BulkPublishDocumentVersionsInput!\n) {\n bulkPublishDocumentVersions(input: $input) {\n documentEdges {\n node {\n id\n ...DocumentListItemFragment\n }\n }\n }\n}\n\nfragment DocumentListItemFragment on Document {\n id\n title\n documentType\n classification\n updatedAt\n canDelete: permission(action: \"core:document:delete\")\n approvers(first: 100) {\n edges {\n node {\n id\n fullName\n }\n }\n }\n lastVersion: versions(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {\n edges {\n node {\n id\n status\n version\n signatures(first: 0, filter: {activeContract: true}) {\n totalCount\n }\n signedSignatures: signatures(first: 0, filter: {states: [SIGNED], activeContract: true}) {\n totalCount\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useFormWithSchema } from "../useFormWithSchema";
|
||||
export const documentSchema = z.object({
|
||||
title: z.string().min(1, "Title is required"),
|
||||
content: z.string().min(1, "Content is required"),
|
||||
approverId: z.string().min(1, "Approver is required"),
|
||||
approverIds: z.array(z.string()).min(1, "At least one approver is required"),
|
||||
documentType: z.enum(["OTHER", "ISMS", "POLICY", "PROCEDURE"]),
|
||||
classification: z.enum(["PUBLIC", "INTERNAL", "CONFIDENTIAL", "SECRET"]),
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ import type { CreateDocumentDialogMutation } from "#/__generated__/core/CreateDo
|
||||
import { ControlledField } from "#/components/form/ControlledField";
|
||||
import { DocumentClassificationOptions } from "#/components/form/DocumentClassificationOptions";
|
||||
import { DocumentTypeOptions } from "#/components/form/DocumentTypeOptions";
|
||||
import { PeopleSelectField } from "#/components/form/PeopleSelectField";
|
||||
import { PeopleMultiSelectField } from "#/components/form/PeopleMultiSelectField";
|
||||
import { documentSchema, useDocumentForm } from "#/hooks/forms/useDocumentForm";
|
||||
import { useMutationWithToasts } from "#/hooks/useMutationWithToasts";
|
||||
import { useOrganizationId } from "#/hooks/useOrganizationId";
|
||||
@@ -143,12 +143,12 @@ export function CreateDocumentDialog({ trigger, connection }: Props) {
|
||||
</PropertyRow>
|
||||
|
||||
<PropertyRow
|
||||
id="approverId"
|
||||
label={__("Approver")}
|
||||
error={errors.approverId?.message}
|
||||
id="approverIds"
|
||||
label={__("Approvers")}
|
||||
error={errors.approverIds?.message}
|
||||
>
|
||||
<PeopleSelectField
|
||||
name="approverId"
|
||||
<PeopleMultiSelectField
|
||||
name="approverIds"
|
||||
control={control}
|
||||
organizationId={organizationId}
|
||||
/>
|
||||
|
||||
@@ -12,7 +12,7 @@ import type { DocumentLayoutDrawerMutation } from "#/__generated__/core/Document
|
||||
import { ControlledField } from "#/components/form/ControlledField";
|
||||
import { DocumentClassificationOptions } from "#/components/form/DocumentClassificationOptions";
|
||||
import { DocumentTypeOptions } from "#/components/form/DocumentTypeOptions";
|
||||
import { PeopleSelectField } from "#/components/form/PeopleSelectField";
|
||||
import { PeopleMultiSelectField } from "#/components/form/PeopleMultiSelectField";
|
||||
import { useFormWithSchema } from "#/hooks/useFormWithSchema";
|
||||
import { useMutationWithToasts } from "#/hooks/useMutationWithToasts";
|
||||
import { useOrganizationId } from "#/hooks/useOrganizationId";
|
||||
@@ -22,6 +22,14 @@ const documentFragment = graphql`
|
||||
id
|
||||
documentType
|
||||
canUpdate: permission(action: "core:document:update")
|
||||
approvers(first: 100) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
fullName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -29,10 +37,6 @@ const versionFragment = graphql`
|
||||
fragment DocumentLayoutDrawer_versionFragment on DocumentVersion {
|
||||
id
|
||||
classification
|
||||
approver {
|
||||
id
|
||||
fullName
|
||||
}
|
||||
version
|
||||
status
|
||||
updatedAt
|
||||
@@ -47,9 +51,13 @@ const updateDocumentMutation = graphql`
|
||||
id
|
||||
documentType
|
||||
classification
|
||||
approver {
|
||||
id
|
||||
fullName
|
||||
approvers(first: 100) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
fullName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,7 +65,7 @@ const updateDocumentMutation = graphql`
|
||||
`;
|
||||
|
||||
const schema = z.object({
|
||||
approverId: z.string().min(1, "Approver is required"),
|
||||
approverIds: z.array(z.string()).min(1, "At least one approver is required"),
|
||||
documentType: z.enum(documentTypes),
|
||||
classification: z.enum(documentClassifications),
|
||||
});
|
||||
@@ -80,11 +88,13 @@ export function DocumentLayoutDrawer(props: {
|
||||
|
||||
const isDraft = version.status === "DRAFT";
|
||||
|
||||
const approvers = document.approvers.edges.map(e => e.node);
|
||||
|
||||
const { control, handleSubmit, reset } = useFormWithSchema(
|
||||
schema,
|
||||
{
|
||||
defaultValues: {
|
||||
approverId: version.approver.id,
|
||||
approverIds: approvers.map(a => a.id),
|
||||
documentType: document.documentType,
|
||||
classification: version.classification,
|
||||
},
|
||||
@@ -100,12 +110,12 @@ export function DocumentLayoutDrawer(props: {
|
||||
},
|
||||
);
|
||||
|
||||
const handleUpdateApprover = async (data: { approverId: string }) => {
|
||||
const handleUpdateApprover = async (data: { approverIds: string[] }) => {
|
||||
await updateDocument({
|
||||
variables: {
|
||||
input: {
|
||||
id: document.id,
|
||||
approverId: data.approverId,
|
||||
approverIds: data.approverIds,
|
||||
},
|
||||
},
|
||||
onSuccess: () => {
|
||||
@@ -151,7 +161,7 @@ export function DocumentLayoutDrawer(props: {
|
||||
<div className="text-base text-txt-primary font-medium mb-4">
|
||||
{__("Properties")}
|
||||
</div>
|
||||
<PropertyRow label={__("Approver")}>
|
||||
<PropertyRow label={__("Approvers")}>
|
||||
{isEditingApprover
|
||||
? (
|
||||
<EditablePropertyContent
|
||||
@@ -162,10 +172,11 @@ export function DocumentLayoutDrawer(props: {
|
||||
}}
|
||||
disabled={isUpdatingDocument}
|
||||
>
|
||||
<PeopleSelectField
|
||||
name="approverId"
|
||||
<PeopleMultiSelectField
|
||||
name="approverIds"
|
||||
control={control}
|
||||
organizationId={organizationId}
|
||||
selectedPeople={approvers}
|
||||
/>
|
||||
</EditablePropertyContent>
|
||||
)
|
||||
@@ -174,10 +185,14 @@ export function DocumentLayoutDrawer(props: {
|
||||
onEdit={() => setIsEditingApprover(true)}
|
||||
canEdit={document.canUpdate}
|
||||
>
|
||||
<Badge variant="highlight" size="md" className="gap-2">
|
||||
<Avatar name={version.approver.fullName} />
|
||||
{version.approver.fullName}
|
||||
</Badge>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{approvers.map(approver => (
|
||||
<Badge key={approver.id} variant="highlight" size="md" className="gap-2">
|
||||
<Avatar name={approver.fullName} />
|
||||
{approver.fullName}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</ReadOnlyPropertyContent>
|
||||
)}
|
||||
</PropertyRow>
|
||||
|
||||
@@ -167,7 +167,7 @@ export function DocumentList(props: {
|
||||
{__("Type")}
|
||||
</SortableTh>
|
||||
<Th className="w-32">{__("Classification")}</Th>
|
||||
<Th className="w-60">{__("Approver")}</Th>
|
||||
<Th className="w-60">{__("Approvers")}</Th>
|
||||
<Th className="w-60">{__("Last update")}</Th>
|
||||
<Th className="w-20">{__("Signatures")}</Th>
|
||||
{hasAnyAction && <Th className="w-18"></Th>}
|
||||
|
||||
@@ -17,9 +17,13 @@ const fragment = graphql`
|
||||
classification
|
||||
updatedAt
|
||||
canDelete: permission(action: "core:document:delete")
|
||||
approver {
|
||||
id
|
||||
fullName
|
||||
approvers(first: 100) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
fullName
|
||||
}
|
||||
}
|
||||
}
|
||||
lastVersion: versions(first: 1 orderBy: { field: CREATED_AT direction: DESC }) {
|
||||
edges {
|
||||
@@ -129,8 +133,12 @@ export function DocumentListItem(props: {
|
||||
</Td>
|
||||
<Td className="w-60">
|
||||
<div className="flex gap-2 items-center">
|
||||
<Avatar name={document.approver?.fullName ?? ""} />
|
||||
{document.approver?.fullName}
|
||||
{document.approvers.edges.map(({ node }) => (
|
||||
<div key={node.id} className="flex gap-1 items-center">
|
||||
<Avatar name={node.fullName} />
|
||||
{node.fullName}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Td>
|
||||
<Td className="w-60">{formatDate(document.updatedAt)}</Td>
|
||||
|
||||
@@ -113,7 +113,7 @@ func TestDocument_Create(t *testing.T) {
|
||||
|
||||
input := map[string]any{
|
||||
"organizationId": owner.GetOrganizationID().String(),
|
||||
"approverId": approverProfileID.String(),
|
||||
"approverIds": []string{approverProfileID.String()},
|
||||
}
|
||||
for k, v := range tt.input {
|
||||
input[k] = v
|
||||
@@ -172,7 +172,7 @@ func TestDocument_Create_Validation(t *testing.T) {
|
||||
wantErrorContains: "organizationId",
|
||||
},
|
||||
{
|
||||
name: "missing approverId",
|
||||
name: "missing approverIds",
|
||||
input: map[string]any{
|
||||
"title": "Test Document",
|
||||
"content": "Test content",
|
||||
@@ -180,7 +180,7 @@ func TestDocument_Create_Validation(t *testing.T) {
|
||||
"classification": "INTERNAL",
|
||||
},
|
||||
skipApprover: true,
|
||||
wantErrorContains: "approverId",
|
||||
wantErrorContains: "approverIds",
|
||||
},
|
||||
{
|
||||
name: "title with HTML tags",
|
||||
@@ -293,7 +293,7 @@ func TestDocument_Create_Validation(t *testing.T) {
|
||||
input["organizationId"] = owner.GetOrganizationID().String()
|
||||
}
|
||||
if !tt.skipApprover {
|
||||
input["approverId"] = approverProfileID.String()
|
||||
input["approverIds"] = []string{approverProfileID.String()}
|
||||
}
|
||||
for k, v := range tt.input {
|
||||
input[k] = v
|
||||
@@ -655,7 +655,7 @@ func TestDocument_Timestamps(t *testing.T) {
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"organizationId": owner.GetOrganizationID().String(),
|
||||
"approverId": approverProfileID.String(),
|
||||
"approverIds": []string{approverProfileID.String()},
|
||||
"title": "Timestamp Test Document",
|
||||
"content": "Test content",
|
||||
"documentType": "POLICY",
|
||||
@@ -736,15 +736,20 @@ func TestDocument_SubResolvers(t *testing.T) {
|
||||
approverProfileID := testutil.NewClientInOrg(t, testutil.RoleViewer, owner).GetProfileID()
|
||||
documentID := factory.NewDocument(owner, approverProfileID.String()).WithTitle("SubResolver Test Document").Create()
|
||||
|
||||
t.Run("approver sub-resolver", func(t *testing.T) {
|
||||
t.Run("approvers sub-resolver", func(t *testing.T) {
|
||||
query := `
|
||||
query($id: ID!) {
|
||||
node(id: $id) {
|
||||
... on Document {
|
||||
id
|
||||
approver {
|
||||
id
|
||||
fullName
|
||||
approvers {
|
||||
totalCount
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
fullName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -753,17 +758,24 @@ func TestDocument_SubResolvers(t *testing.T) {
|
||||
|
||||
var result struct {
|
||||
Node struct {
|
||||
ID string `json:"id"`
|
||||
Approver struct {
|
||||
ID string `json:"id"`
|
||||
FullName string `json:"fullName"`
|
||||
} `json:"approver"`
|
||||
ID string `json:"id"`
|
||||
Approvers struct {
|
||||
TotalCount int `json:"totalCount"`
|
||||
Edges []struct {
|
||||
Node struct {
|
||||
ID string `json:"id"`
|
||||
FullName string `json:"fullName"`
|
||||
} `json:"node"`
|
||||
} `json:"edges"`
|
||||
} `json:"approvers"`
|
||||
} `json:"node"`
|
||||
}
|
||||
|
||||
err := owner.Execute(query, map[string]any{"id": documentID}, &result)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, approverProfileID.String(), result.Node.Approver.ID)
|
||||
assert.Equal(t, 1, result.Node.Approvers.TotalCount)
|
||||
require.Len(t, result.Node.Approvers.Edges, 1)
|
||||
assert.Equal(t, approverProfileID.String(), result.Node.Approvers.Edges[0].Node.ID)
|
||||
})
|
||||
|
||||
t.Run("organization sub-resolver", func(t *testing.T) {
|
||||
@@ -815,7 +827,7 @@ func TestDocument_RBAC(t *testing.T) {
|
||||
`, map[string]any{
|
||||
"input": map[string]any{
|
||||
"organizationId": owner.GetOrganizationID().String(),
|
||||
"approverId": approverProfileID.String(),
|
||||
"approverIds": []string{approverProfileID.String()},
|
||||
"title": "RBAC Test Document",
|
||||
"content": "Test content",
|
||||
"documentType": "POLICY",
|
||||
@@ -839,7 +851,7 @@ func TestDocument_RBAC(t *testing.T) {
|
||||
`, map[string]any{
|
||||
"input": map[string]any{
|
||||
"organizationId": admin.GetOrganizationID().String(),
|
||||
"approverId": approverProfileID.String(),
|
||||
"approverIds": []string{approverProfileID.String()},
|
||||
"title": "RBAC Test Document",
|
||||
"content": "Test content",
|
||||
"documentType": "POLICY",
|
||||
@@ -863,7 +875,7 @@ func TestDocument_RBAC(t *testing.T) {
|
||||
`, map[string]any{
|
||||
"input": map[string]any{
|
||||
"organizationId": viewer.GetOrganizationID().String(),
|
||||
"approverId": approverProfileID.String(),
|
||||
"approverIds": []string{approverProfileID.String()},
|
||||
"title": "RBAC Test Document",
|
||||
"content": "Test content",
|
||||
"documentType": "POLICY",
|
||||
@@ -1088,7 +1100,7 @@ func TestDocument_MaxLength_Validation(t *testing.T) {
|
||||
_, err := owner.Do(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"organizationId": owner.GetOrganizationID().String(),
|
||||
"approverId": approverProfileID.String(),
|
||||
"approverIds": []string{approverProfileID.String()},
|
||||
"title": longTitle,
|
||||
"content": "Test content",
|
||||
"documentType": "POLICY",
|
||||
|
||||
@@ -68,7 +68,7 @@ func createTestDocument(t *testing.T, owner *testutil.Client) (docID string, doc
|
||||
"organizationId": owner.GetOrganizationID().String(),
|
||||
"title": "Test Document",
|
||||
"content": "Initial content",
|
||||
"approverId": profileID.String(),
|
||||
"approverIds": []string{profileID.String()},
|
||||
"documentType": "POLICY",
|
||||
"classification": "INTERNAL",
|
||||
},
|
||||
|
||||
@@ -394,7 +394,7 @@ func TestControlDocumentMapping_CreateDelete(t *testing.T) {
|
||||
"organizationId": owner.GetOrganizationID().String(),
|
||||
"title": "Document for Control Mapping",
|
||||
"content": "Document content",
|
||||
"ownerId": profileID.String(),
|
||||
"approverIds": []string{profileID.String()},
|
||||
"documentType": "POLICY",
|
||||
"classification": "INTERNAL",
|
||||
},
|
||||
@@ -784,7 +784,7 @@ func TestRiskDocumentMapping_CreateDelete(t *testing.T) {
|
||||
"organizationId": owner.GetOrganizationID().String(),
|
||||
"title": "Document for Risk Mapping",
|
||||
"content": "Document content",
|
||||
"ownerId": profileID.String(),
|
||||
"approverIds": []string{profileID.String()},
|
||||
"documentType": "POLICY",
|
||||
"classification": "INTERNAL",
|
||||
},
|
||||
|
||||
@@ -784,7 +784,7 @@ func CreateDocument(c *testutil.Client, approverID string, attrs ...Attrs) strin
|
||||
|
||||
input := map[string]any{
|
||||
"organizationId": c.GetOrganizationID().String(),
|
||||
"approverId": approverID,
|
||||
"approverIds": []string{approverID},
|
||||
"title": a.getString("title", SafeName("Document")),
|
||||
"content": a.getString("content", "Document content"),
|
||||
"documentType": a.getString("documentType", "POLICY"),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { type FC, Fragment, useState } from "react";
|
||||
// eslint-disable-next-line import-x/no-unresolved -- storybook v10 subpath export
|
||||
import { fn } from "storybook/test";
|
||||
|
||||
import { Badge } from "../../Atoms/Badge/Badge";
|
||||
@@ -15,7 +16,8 @@ export default {
|
||||
title: "Atoms/DataTable/Cells",
|
||||
component: Fragment as Component,
|
||||
argTypes: {},
|
||||
args: { onUpdate: fn() },
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call -- fn type unresolvable due to storybook/test subpath
|
||||
args: { onUpdate: fn() as (key: string, value: unknown) => void },
|
||||
} satisfies Meta<Component>;
|
||||
|
||||
type Story = StoryObj<Component>;
|
||||
|
||||
@@ -32,7 +32,6 @@ type (
|
||||
Document struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
ApproverID gid.GID `db:"approver_profile_id"`
|
||||
Title string `db:"title"`
|
||||
DocumentType DocumentType `db:"document_type"`
|
||||
Classification DocumentClassification `db:"classification"`
|
||||
@@ -83,7 +82,6 @@ func (p *Document) LoadByID(
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
approver_profile_id,
|
||||
title,
|
||||
document_type,
|
||||
classification,
|
||||
@@ -135,7 +133,6 @@ func (p *Document) LoadByIDWithFilter(
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
approver_profile_id,
|
||||
title,
|
||||
document_type,
|
||||
classification,
|
||||
@@ -188,7 +185,6 @@ func (p *Documents) LoadByIDs(
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
approver_profile_id,
|
||||
title,
|
||||
document_type,
|
||||
classification,
|
||||
@@ -270,7 +266,6 @@ func (p *Documents) LoadByOrganizationID(
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
approver_profile_id,
|
||||
title,
|
||||
document_type,
|
||||
classification,
|
||||
@@ -321,7 +316,6 @@ func (p *Documents) LoadAllByOrganizationID(
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
approver_profile_id,
|
||||
title,
|
||||
document_type,
|
||||
classification,
|
||||
@@ -371,7 +365,6 @@ INSERT INTO
|
||||
tenant_id,
|
||||
id,
|
||||
organization_id,
|
||||
approver_profile_id,
|
||||
title,
|
||||
document_type,
|
||||
classification,
|
||||
@@ -384,7 +377,6 @@ VALUES (
|
||||
@tenant_id,
|
||||
@document_id,
|
||||
@organization_id,
|
||||
@approver_profile_id,
|
||||
@title,
|
||||
@document_type,
|
||||
@classification,
|
||||
@@ -399,7 +391,6 @@ VALUES (
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"document_id": p.ID,
|
||||
"organization_id": p.OrganizationID,
|
||||
"approver_profile_id": p.ApproverID,
|
||||
"title": p.Title,
|
||||
"document_type": p.DocumentType,
|
||||
"classification": p.Classification,
|
||||
@@ -460,7 +451,6 @@ UPDATE
|
||||
SET
|
||||
title = @title,
|
||||
current_published_version = @current_published_version,
|
||||
approver_profile_id = @approver_profile_id,
|
||||
document_type = @document_type,
|
||||
classification = @classification,
|
||||
trust_center_visibility = @trust_center_visibility,
|
||||
@@ -477,7 +467,6 @@ WHERE
|
||||
"updated_at": time.Now(),
|
||||
"title": p.Title,
|
||||
"current_published_version": p.CurrentPublishedVersion,
|
||||
"approver_profile_id": p.ApproverID,
|
||||
"document_type": p.DocumentType,
|
||||
"classification": p.Classification,
|
||||
"trust_center_visibility": p.TrustCenterVisibility,
|
||||
@@ -548,7 +537,6 @@ WITH scoped_documents AS (
|
||||
SELECT
|
||||
scoped_documents.id,
|
||||
scoped_documents.organization_id,
|
||||
scoped_documents.approver_profile_id,
|
||||
scoped_documents.title,
|
||||
scoped_documents.document_type,
|
||||
scoped_documents.classification,
|
||||
@@ -638,7 +626,6 @@ WITH scoped_documents AS (
|
||||
SELECT
|
||||
scoped_documents.id,
|
||||
scoped_documents.organization_id,
|
||||
scoped_documents.approver_profile_id,
|
||||
scoped_documents.title,
|
||||
scoped_documents.document_type,
|
||||
scoped_documents.classification,
|
||||
|
||||
154
pkg/coredata/document_approver.go
Normal file
154
pkg/coredata/document_approver.go
Normal file
@@ -0,0 +1,154 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
)
|
||||
|
||||
type (
|
||||
DocumentApprover struct {
|
||||
DocumentID gid.GID `db:"document_id"`
|
||||
ApproverProfileID gid.GID `db:"approver_profile_id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
TenantID gid.TenantID `db:"tenant_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
}
|
||||
|
||||
DocumentApprovers []*DocumentApprover
|
||||
)
|
||||
|
||||
func (da DocumentApprover) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO
|
||||
document_approvers (
|
||||
document_id,
|
||||
approver_profile_id,
|
||||
organization_id,
|
||||
tenant_id,
|
||||
created_at
|
||||
)
|
||||
VALUES (
|
||||
@document_id,
|
||||
@approver_profile_id,
|
||||
@organization_id,
|
||||
@tenant_id,
|
||||
@created_at
|
||||
)
|
||||
ON CONFLICT (document_id, approver_profile_id) DO NOTHING;
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"document_id": da.DocumentID,
|
||||
"approver_profile_id": da.ApproverProfileID,
|
||||
"organization_id": da.OrganizationID,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"created_at": da.CreatedAt,
|
||||
}
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert document approver: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (da *DocumentApprovers) LoadByDocumentID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
documentID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
document_id,
|
||||
approver_profile_id,
|
||||
organization_id,
|
||||
tenant_id,
|
||||
created_at
|
||||
FROM
|
||||
document_approvers
|
||||
WHERE
|
||||
%s
|
||||
AND document_id = @document_id
|
||||
ORDER BY created_at ASC
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"document_id": documentID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query document approvers: %w", err)
|
||||
}
|
||||
|
||||
approvers, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[DocumentApprover])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect document approvers: %w", err)
|
||||
}
|
||||
|
||||
*da = approvers
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (da *DocumentApprovers) DeleteByDocumentID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
documentID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
DELETE FROM
|
||||
document_approvers
|
||||
WHERE
|
||||
%s
|
||||
AND document_id = @document_id
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"document_id": documentID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete document approvers: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (da *DocumentApprovers) ApproverProfileIDs() []gid.GID {
|
||||
ids := make([]gid.GID, len(*da))
|
||||
for i, a := range *da {
|
||||
ids[i] = a.ApproverProfileID
|
||||
}
|
||||
return ids
|
||||
}
|
||||
@@ -34,7 +34,6 @@ type (
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
DocumentID gid.GID `db:"document_id"`
|
||||
Title string `db:"title"`
|
||||
ApproverID gid.GID `db:"approver_profile_id"`
|
||||
VersionNumber int `db:"version_number"`
|
||||
Classification DocumentClassification `db:"classification"`
|
||||
Content string `db:"content"`
|
||||
@@ -77,7 +76,6 @@ SELECT
|
||||
organization_id,
|
||||
document_id,
|
||||
title,
|
||||
approver_profile_id,
|
||||
version_number,
|
||||
classification,
|
||||
content,
|
||||
@@ -139,7 +137,6 @@ SELECT
|
||||
organization_id,
|
||||
document_id,
|
||||
title,
|
||||
approver_profile_id,
|
||||
version_number,
|
||||
classification,
|
||||
content,
|
||||
@@ -190,7 +187,6 @@ INSERT INTO document_versions (
|
||||
organization_id,
|
||||
document_id,
|
||||
title,
|
||||
approver_profile_id,
|
||||
version_number,
|
||||
classification,
|
||||
content,
|
||||
@@ -205,7 +201,6 @@ VALUES (
|
||||
@organization_id,
|
||||
@document_id,
|
||||
@title,
|
||||
@approver_profile_id,
|
||||
@version_number,
|
||||
@classification,
|
||||
@content,
|
||||
@@ -216,19 +211,18 @@ VALUES (
|
||||
)
|
||||
`
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"id": dv.ID,
|
||||
"organization_id": dv.OrganizationID,
|
||||
"document_id": dv.DocumentID,
|
||||
"title": dv.Title,
|
||||
"approver_profile_id": dv.ApproverID,
|
||||
"version_number": dv.VersionNumber,
|
||||
"classification": dv.Classification,
|
||||
"content": dv.Content,
|
||||
"changelog": dv.Changelog,
|
||||
"status": dv.Status,
|
||||
"created_at": dv.CreatedAt,
|
||||
"updated_at": dv.UpdatedAt,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"id": dv.ID,
|
||||
"organization_id": dv.OrganizationID,
|
||||
"document_id": dv.DocumentID,
|
||||
"title": dv.Title,
|
||||
"version_number": dv.VersionNumber,
|
||||
"classification": dv.Classification,
|
||||
"content": dv.Content,
|
||||
"changelog": dv.Changelog,
|
||||
"status": dv.Status,
|
||||
"created_at": dv.CreatedAt,
|
||||
"updated_at": dv.UpdatedAt,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
@@ -260,7 +254,6 @@ SELECT
|
||||
organization_id,
|
||||
document_id,
|
||||
title,
|
||||
approver_profile_id,
|
||||
version_number,
|
||||
classification,
|
||||
content,
|
||||
@@ -313,7 +306,6 @@ SELECT
|
||||
organization_id,
|
||||
document_id,
|
||||
title,
|
||||
approver_profile_id,
|
||||
version_number,
|
||||
classification,
|
||||
content,
|
||||
@@ -364,7 +356,6 @@ SELECT
|
||||
organization_id,
|
||||
document_id,
|
||||
title,
|
||||
approver_profile_id,
|
||||
version_number,
|
||||
classification,
|
||||
content,
|
||||
@@ -413,7 +404,6 @@ func (dv DocumentVersion) Update(
|
||||
q := `
|
||||
UPDATE document_versions SET
|
||||
title = @title,
|
||||
approver_profile_id = @approver_profile_id,
|
||||
changelog = @changelog,
|
||||
status = @status,
|
||||
content = @content,
|
||||
@@ -429,7 +419,6 @@ WHERE %s
|
||||
args := pgx.StrictNamedArgs{
|
||||
"document_version_id": dv.ID,
|
||||
"title": dv.Title,
|
||||
"approver_profile_id": dv.ApproverID,
|
||||
"changelog": dv.Changelog,
|
||||
"status": dv.Status,
|
||||
"content": dv.Content,
|
||||
|
||||
154
pkg/coredata/document_version_approver.go
Normal file
154
pkg/coredata/document_version_approver.go
Normal file
@@ -0,0 +1,154 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
)
|
||||
|
||||
type (
|
||||
DocumentVersionApprover struct {
|
||||
DocumentVersionID gid.GID `db:"document_version_id"`
|
||||
ApproverProfileID gid.GID `db:"approver_profile_id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
TenantID gid.TenantID `db:"tenant_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
}
|
||||
|
||||
DocumentVersionApprovers []*DocumentVersionApprover
|
||||
)
|
||||
|
||||
func (dva DocumentVersionApprover) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO
|
||||
document_version_approvers (
|
||||
document_version_id,
|
||||
approver_profile_id,
|
||||
organization_id,
|
||||
tenant_id,
|
||||
created_at
|
||||
)
|
||||
VALUES (
|
||||
@document_version_id,
|
||||
@approver_profile_id,
|
||||
@organization_id,
|
||||
@tenant_id,
|
||||
@created_at
|
||||
)
|
||||
ON CONFLICT (document_version_id, approver_profile_id) DO NOTHING;
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"document_version_id": dva.DocumentVersionID,
|
||||
"approver_profile_id": dva.ApproverProfileID,
|
||||
"organization_id": dva.OrganizationID,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"created_at": dva.CreatedAt,
|
||||
}
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert document version approver: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dva *DocumentVersionApprovers) LoadByDocumentVersionID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
documentVersionID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
document_version_id,
|
||||
approver_profile_id,
|
||||
organization_id,
|
||||
tenant_id,
|
||||
created_at
|
||||
FROM
|
||||
document_version_approvers
|
||||
WHERE
|
||||
%s
|
||||
AND document_version_id = @document_version_id
|
||||
ORDER BY created_at ASC
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"document_version_id": documentVersionID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query document version approvers: %w", err)
|
||||
}
|
||||
|
||||
approvers, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[DocumentVersionApprover])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect document version approvers: %w", err)
|
||||
}
|
||||
|
||||
*dva = approvers
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dva *DocumentVersionApprovers) DeleteByDocumentVersionID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
documentVersionID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
DELETE FROM
|
||||
document_version_approvers
|
||||
WHERE
|
||||
%s
|
||||
AND document_version_id = @document_version_id
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"document_version_id": documentVersionID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete document version approvers: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dva *DocumentVersionApprovers) ApproverProfileIDs() []gid.GID {
|
||||
ids := make([]gid.GID, len(*dva))
|
||||
for i, a := range *dva {
|
||||
ids[i] = a.ApproverProfileID
|
||||
}
|
||||
return ids
|
||||
}
|
||||
@@ -364,7 +364,7 @@ WITH sigs AS (
|
||||
FROM
|
||||
document_version_signatures dvs
|
||||
INNER JOIN
|
||||
iam_membership_profile_id p ON dvs.signed_by_profile_id = p.id
|
||||
iam_membership_profiles p ON dvs.signed_by_profile_id = p.id
|
||||
WHERE
|
||||
dvs.document_version_id = @document_version_id
|
||||
ORDER BY
|
||||
|
||||
@@ -368,6 +368,212 @@ INNER JOIN identities i ON i.id = p.identity_id
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *MembershipProfiles) LoadByDocumentID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
documentID gid.GID,
|
||||
cursor *page.Cursor[MembershipProfileOrderField],
|
||||
) error {
|
||||
q := `
|
||||
WITH profiles AS (
|
||||
SELECT
|
||||
mp.id,
|
||||
mp.identity_id,
|
||||
mp.organization_id,
|
||||
mp.membership_id,
|
||||
mp.full_name,
|
||||
mp.kind,
|
||||
mp.additional_email_addresses,
|
||||
mp.position,
|
||||
mp.contract_start_date,
|
||||
mp.contract_end_date,
|
||||
mp.created_at,
|
||||
mp.updated_at
|
||||
FROM
|
||||
iam_membership_profiles mp
|
||||
WHERE
|
||||
mp.%s
|
||||
AND mp.id IN (
|
||||
SELECT approver_profile_id
|
||||
FROM document_approvers
|
||||
WHERE document_id = @document_id
|
||||
)
|
||||
AND %s
|
||||
)
|
||||
SELECT
|
||||
p.id,
|
||||
p.identity_id,
|
||||
p.organization_id,
|
||||
p.membership_id,
|
||||
i.email_address,
|
||||
p.full_name,
|
||||
p.kind,
|
||||
p.additional_email_addresses,
|
||||
p.position,
|
||||
p.contract_start_date,
|
||||
p.contract_end_date,
|
||||
p.created_at,
|
||||
p.updated_at
|
||||
FROM profiles p
|
||||
INNER JOIN identities i ON i.id = p.identity_id
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
|
||||
|
||||
args := pgx.NamedArgs{"document_id": documentID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, cursor.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query document approver profiles: %w", err)
|
||||
}
|
||||
|
||||
profiles, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[MembershipProfile])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect document approver profiles: %w", err)
|
||||
}
|
||||
|
||||
*p = profiles
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *MembershipProfiles) CountByDocumentID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
documentID gid.GID,
|
||||
) (int, error) {
|
||||
q := `
|
||||
SELECT
|
||||
COUNT(*)
|
||||
FROM
|
||||
iam_membership_profiles mp
|
||||
INNER JOIN document_approvers da ON mp.id = da.approver_profile_id
|
||||
WHERE
|
||||
mp.%s
|
||||
AND da.document_id = @document_id
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"document_id": documentID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
var count int
|
||||
err := conn.QueryRow(ctx, q, args).Scan(&count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot query document approver profiles count: %w", err)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (p *MembershipProfiles) LoadByDocumentVersionID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
documentVersionID gid.GID,
|
||||
cursor *page.Cursor[MembershipProfileOrderField],
|
||||
) error {
|
||||
q := `
|
||||
WITH profiles AS (
|
||||
SELECT
|
||||
mp.id,
|
||||
mp.identity_id,
|
||||
mp.organization_id,
|
||||
mp.membership_id,
|
||||
mp.full_name,
|
||||
mp.kind,
|
||||
mp.additional_email_addresses,
|
||||
mp.position,
|
||||
mp.contract_start_date,
|
||||
mp.contract_end_date,
|
||||
mp.created_at,
|
||||
mp.updated_at
|
||||
FROM
|
||||
iam_membership_profiles mp
|
||||
WHERE
|
||||
mp.%s
|
||||
AND mp.id IN (
|
||||
SELECT approver_profile_id
|
||||
FROM document_version_approvers
|
||||
WHERE document_version_id = @document_version_id
|
||||
)
|
||||
AND %s
|
||||
)
|
||||
SELECT
|
||||
p.id,
|
||||
p.identity_id,
|
||||
p.organization_id,
|
||||
p.membership_id,
|
||||
i.email_address,
|
||||
p.full_name,
|
||||
p.kind,
|
||||
p.additional_email_addresses,
|
||||
p.position,
|
||||
p.contract_start_date,
|
||||
p.contract_end_date,
|
||||
p.created_at,
|
||||
p.updated_at
|
||||
FROM profiles p
|
||||
INNER JOIN identities i ON i.id = p.identity_id
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
|
||||
|
||||
args := pgx.NamedArgs{"document_version_id": documentVersionID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, cursor.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query document version approver profiles: %w", err)
|
||||
}
|
||||
|
||||
profiles, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[MembershipProfile])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect document version approver profiles: %w", err)
|
||||
}
|
||||
|
||||
*p = profiles
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *MembershipProfiles) CountByDocumentVersionID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
documentVersionID gid.GID,
|
||||
) (int, error) {
|
||||
q := `
|
||||
SELECT
|
||||
COUNT(*)
|
||||
FROM
|
||||
iam_membership_profiles mp
|
||||
INNER JOIN document_version_approvers dva ON mp.id = dva.approver_profile_id
|
||||
WHERE
|
||||
mp.%s
|
||||
AND dva.document_version_id = @document_version_id
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"document_version_id": documentVersionID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
var count int
|
||||
err := conn.QueryRow(ctx, q, args).Scan(&count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot query document version approver profiles count: %w", err)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (p *MembershipProfiles) LoadByMeetingID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
|
||||
36
pkg/coredata/migrations/20260213T120000Z.sql
Normal file
36
pkg/coredata/migrations/20260213T120000Z.sql
Normal file
@@ -0,0 +1,36 @@
|
||||
-- Create document_approvers join table
|
||||
CREATE TABLE document_approvers (
|
||||
document_id TEXT NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
|
||||
approver_profile_id TEXT NOT NULL REFERENCES iam_membership_profiles(id) ON UPDATE CASCADE ON DELETE RESTRICT,
|
||||
tenant_id TEXT NOT NULL,
|
||||
organization_id TEXT NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
PRIMARY KEY (document_id, approver_profile_id)
|
||||
);
|
||||
|
||||
-- Create document_version_approvers join table
|
||||
CREATE TABLE document_version_approvers (
|
||||
document_version_id TEXT NOT NULL REFERENCES document_versions(id) ON DELETE CASCADE,
|
||||
approver_profile_id TEXT NOT NULL REFERENCES iam_membership_profiles(id) ON UPDATE CASCADE ON DELETE RESTRICT,
|
||||
tenant_id TEXT NOT NULL,
|
||||
organization_id TEXT NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
PRIMARY KEY (document_version_id, approver_profile_id)
|
||||
);
|
||||
|
||||
-- Migrate existing approver data from documents to document_approvers
|
||||
INSERT INTO document_approvers (document_id, approver_profile_id, tenant_id, organization_id, created_at)
|
||||
SELECT id, approver_profile_id, tenant_id, organization_id, created_at
|
||||
FROM documents
|
||||
WHERE approver_profile_id IS NOT NULL
|
||||
AND deleted_at IS NULL;
|
||||
|
||||
-- Migrate existing approver data from document_versions to document_version_approvers
|
||||
INSERT INTO document_version_approvers (document_version_id, approver_profile_id, tenant_id, organization_id, created_at)
|
||||
SELECT id, approver_profile_id, tenant_id, organization_id, created_at
|
||||
FROM document_versions
|
||||
WHERE approver_profile_id IS NOT NULL;
|
||||
|
||||
-- Drop the old columns
|
||||
ALTER TABLE documents DROP COLUMN approver_profile_id;
|
||||
ALTER TABLE document_versions DROP COLUMN approver_profile_id;
|
||||
@@ -50,7 +50,7 @@ type (
|
||||
OrganizationID gid.GID
|
||||
Title string
|
||||
Content string
|
||||
ApproverID gid.GID
|
||||
ApproverIDs []gid.GID
|
||||
Classification coredata.DocumentClassification
|
||||
DocumentType coredata.DocumentType
|
||||
TrustCenterVisibility *coredata.TrustCenterVisibility
|
||||
@@ -59,7 +59,7 @@ type (
|
||||
UpdateDocumentRequest struct {
|
||||
DocumentID gid.GID
|
||||
Title *string
|
||||
ApproverID *gid.GID
|
||||
ApproverIDs []gid.GID
|
||||
Classification *coredata.DocumentClassification
|
||||
DocumentType *coredata.DocumentType
|
||||
TrustCenterVisibility *coredata.TrustCenterVisibility
|
||||
@@ -102,7 +102,10 @@ func (cdr *CreateDocumentRequest) Validate() error {
|
||||
v.Check(cdr.OrganizationID, "organization_id", validator.Required(), validator.GID(coredata.OrganizationEntityType))
|
||||
v.Check(cdr.Title, "title", validator.Required(), validator.SafeTextNoNewLine(TitleMaxLength))
|
||||
v.Check(cdr.Content, "content", validator.Required(), validator.NotEmpty(), validator.MaxLen(documentMaxLength))
|
||||
v.Check(cdr.ApproverID, "approver_id", validator.Required(), validator.GID(coredata.MembershipProfileEntityType))
|
||||
v.Check(cdr.ApproverIDs, "approver_ids", validator.Required(), validator.NotEmpty())
|
||||
for _, id := range cdr.ApproverIDs {
|
||||
v.Check(id, "approver_ids", validator.Required(), validator.GID(coredata.MembershipProfileEntityType))
|
||||
}
|
||||
v.Check(cdr.Classification, "classification", validator.Required(), validator.OneOfSlice(coredata.DocumentClassifications()))
|
||||
v.Check(cdr.DocumentType, "document_type", validator.Required(), validator.OneOfSlice(coredata.DocumentTypes()))
|
||||
v.Check(cdr.TrustCenterVisibility, "trust_center_visibility", validator.OneOfSlice(coredata.TrustCenterVisibilities()))
|
||||
@@ -115,7 +118,9 @@ func (udr *UpdateDocumentRequest) Validate() error {
|
||||
|
||||
v.Check(udr.DocumentID, "document_id", validator.Required(), validator.GID(coredata.DocumentEntityType))
|
||||
v.Check(udr.Title, "title", validator.SafeTextNoNewLine(TitleMaxLength))
|
||||
v.Check(udr.ApproverID, "approver_id", validator.GID(coredata.MembershipProfileEntityType))
|
||||
for _, id := range udr.ApproverIDs {
|
||||
v.Check(id, "approver_ids", validator.Required(), validator.GID(coredata.MembershipProfileEntityType))
|
||||
}
|
||||
v.Check(udr.Classification, "classification", validator.OneOfSlice(coredata.DocumentClassifications()))
|
||||
v.Check(udr.DocumentType, "document_type", validator.OneOfSlice(coredata.DocumentTypes()))
|
||||
v.Check(udr.TrustCenterVisibility, "trust_center_visibility", validator.OneOfSlice(coredata.TrustCenterVisibilities()))
|
||||
@@ -177,6 +182,108 @@ func (s *DocumentService) Get(
|
||||
return document, nil
|
||||
}
|
||||
|
||||
func (s *DocumentService) ListApprovers(
|
||||
ctx context.Context,
|
||||
documentID gid.GID,
|
||||
cursor *page.Cursor[coredata.MembershipProfileOrderField],
|
||||
) (*page.Page[*coredata.MembershipProfile, coredata.MembershipProfileOrderField], error) {
|
||||
var profiles coredata.MembershipProfiles
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
if err := profiles.LoadByDocumentID(ctx, conn, s.svc.scope, documentID, cursor); err != nil {
|
||||
return fmt.Errorf("cannot load document approvers: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return page.NewPage(profiles, cursor), nil
|
||||
}
|
||||
|
||||
func (s *DocumentService) CountApprovers(
|
||||
ctx context.Context,
|
||||
documentID gid.GID,
|
||||
) (int, error) {
|
||||
var count int
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) (err error) {
|
||||
profiles := coredata.MembershipProfiles{}
|
||||
count, err = profiles.CountByDocumentID(ctx, conn, s.svc.scope, documentID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot count document approvers: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (s *DocumentService) ListVersionApprovers(
|
||||
ctx context.Context,
|
||||
documentVersionID gid.GID,
|
||||
cursor *page.Cursor[coredata.MembershipProfileOrderField],
|
||||
) (*page.Page[*coredata.MembershipProfile, coredata.MembershipProfileOrderField], error) {
|
||||
var profiles coredata.MembershipProfiles
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
if err := profiles.LoadByDocumentVersionID(ctx, conn, s.svc.scope, documentVersionID, cursor); err != nil {
|
||||
return fmt.Errorf("cannot load document version approvers: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return page.NewPage(profiles, cursor), nil
|
||||
}
|
||||
|
||||
func (s *DocumentService) CountVersionApprovers(
|
||||
ctx context.Context,
|
||||
documentVersionID gid.GID,
|
||||
) (int, error) {
|
||||
var count int
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) (err error) {
|
||||
profiles := coredata.MembershipProfiles{}
|
||||
count, err = profiles.CountByDocumentVersionID(ctx, conn, s.svc.scope, documentVersionID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot count document version approvers: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (s *DocumentService) GetWithFilter(
|
||||
ctx context.Context,
|
||||
documentID gid.GID,
|
||||
@@ -354,8 +461,7 @@ func (s *DocumentService) publishVersionInTx(
|
||||
return nil, nil, fmt.Errorf("cannot load published version: %w", err)
|
||||
}
|
||||
if publishedVersion.Content == documentVersion.Content &&
|
||||
publishedVersion.Title == documentVersion.Title &&
|
||||
publishedVersion.ApproverID == documentVersion.ApproverID {
|
||||
publishedVersion.Title == documentVersion.Title {
|
||||
return nil, nil, &ErrDocumentVersionNoChanges{}
|
||||
}
|
||||
}
|
||||
@@ -395,7 +501,6 @@ func (s *DocumentService) Create(
|
||||
documentVersionID := gid.New(s.svc.scope.GetTenantID(), coredata.DocumentVersionEntityType)
|
||||
|
||||
organization := &coredata.Organization{}
|
||||
approver := &coredata.MembershipProfile{}
|
||||
|
||||
document := &coredata.Document{
|
||||
ID: documentID,
|
||||
@@ -415,7 +520,6 @@ func (s *DocumentService) Create(
|
||||
ID: documentVersionID,
|
||||
DocumentID: documentID,
|
||||
Title: req.Title,
|
||||
ApproverID: req.ApproverID,
|
||||
VersionNumber: 1,
|
||||
Content: req.Content,
|
||||
Status: coredata.DocumentStatusDraft,
|
||||
@@ -431,23 +535,54 @@ func (s *DocumentService) Create(
|
||||
return fmt.Errorf("cannot load organization: %w", err)
|
||||
}
|
||||
|
||||
if err := approver.LoadByID(ctx, conn, s.svc.scope, req.ApproverID); err != nil {
|
||||
return fmt.Errorf("cannot load approver profile: %w", err)
|
||||
// Validate all approver profiles exist
|
||||
approverProfiles := coredata.MembershipProfiles{}
|
||||
if err := approverProfiles.LoadByIDs(ctx, conn, s.svc.scope, req.ApproverIDs); err != nil {
|
||||
return fmt.Errorf("cannot load approver profiles: %w", err)
|
||||
}
|
||||
|
||||
if len(approverProfiles) != len(req.ApproverIDs) {
|
||||
return fmt.Errorf("one or more approver profiles not found")
|
||||
}
|
||||
|
||||
document.OrganizationID = organization.ID
|
||||
document.ApproverID = approver.ID
|
||||
|
||||
if err := document.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert document: %w", err)
|
||||
}
|
||||
|
||||
// Insert document approvers
|
||||
for _, approverID := range req.ApproverIDs {
|
||||
da := coredata.DocumentApprover{
|
||||
DocumentID: documentID,
|
||||
ApproverProfileID: approverID,
|
||||
OrganizationID: organization.ID,
|
||||
CreatedAt: now,
|
||||
}
|
||||
if err := da.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert document approver: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
documentVersion.OrganizationID = organization.ID
|
||||
|
||||
if err := documentVersion.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot create document version: %w", err)
|
||||
}
|
||||
|
||||
// Insert document version approvers
|
||||
for _, approverID := range req.ApproverIDs {
|
||||
dva := coredata.DocumentVersionApprover{
|
||||
DocumentVersionID: documentVersionID,
|
||||
ApproverProfileID: approverID,
|
||||
OrganizationID: organization.ID,
|
||||
CreatedAt: now,
|
||||
}
|
||||
if err := dva.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert document version approver: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
@@ -706,7 +841,6 @@ func (s *DocumentService) UpdateVersion(
|
||||
}
|
||||
|
||||
documentVersion.Title = document.Title
|
||||
documentVersion.ApproverID = document.ApproverID
|
||||
documentVersion.Classification = document.Classification
|
||||
documentVersion.Content = req.Content
|
||||
documentVersion.UpdatedAt = time.Now()
|
||||
@@ -715,6 +849,28 @@ func (s *DocumentService) UpdateVersion(
|
||||
return fmt.Errorf("cannot update document version: %w", err)
|
||||
}
|
||||
|
||||
docApprovers := &coredata.DocumentApprovers{}
|
||||
if err := docApprovers.LoadByDocumentID(ctx, conn, s.svc.scope, document.ID); err != nil {
|
||||
return fmt.Errorf("cannot load document approvers: %w", err)
|
||||
}
|
||||
|
||||
versionApprovers := &coredata.DocumentVersionApprovers{}
|
||||
if err := versionApprovers.DeleteByDocumentVersionID(ctx, conn, s.svc.scope, documentVersion.ID); err != nil {
|
||||
return fmt.Errorf("cannot delete document version approvers: %w", err)
|
||||
}
|
||||
|
||||
for _, da := range *docApprovers {
|
||||
dva := coredata.DocumentVersionApprover{
|
||||
DocumentVersionID: documentVersion.ID,
|
||||
ApproverProfileID: da.ApproverProfileID,
|
||||
OrganizationID: da.OrganizationID,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
if err := dva.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert document version approver: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
@@ -944,7 +1100,6 @@ func (s *DocumentService) CreateDraft(
|
||||
draftVersion.OrganizationID = document.OrganizationID
|
||||
draftVersion.DocumentID = documentID
|
||||
draftVersion.Title = document.Title
|
||||
draftVersion.ApproverID = document.ApproverID
|
||||
draftVersion.VersionNumber = latestVersion.VersionNumber + 1
|
||||
draftVersion.Classification = document.Classification
|
||||
draftVersion.Content = latestVersion.Content
|
||||
@@ -956,6 +1111,23 @@ func (s *DocumentService) CreateDraft(
|
||||
return fmt.Errorf("cannot create draft: %w", err)
|
||||
}
|
||||
|
||||
docApprovers := &coredata.DocumentApprovers{}
|
||||
if err := docApprovers.LoadByDocumentID(ctx, conn, s.svc.scope, documentID); err != nil {
|
||||
return fmt.Errorf("cannot load document approvers: %w", err)
|
||||
}
|
||||
|
||||
for _, da := range *docApprovers {
|
||||
dva := coredata.DocumentVersionApprover{
|
||||
DocumentVersionID: draftVersionID,
|
||||
ApproverProfileID: da.ApproverProfileID,
|
||||
OrganizationID: da.OrganizationID,
|
||||
CreatedAt: now,
|
||||
}
|
||||
if err := dva.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert document version approver: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
@@ -1384,7 +1556,6 @@ func (s *DocumentService) Update(
|
||||
}
|
||||
|
||||
document := &coredata.Document{}
|
||||
approver := &coredata.MembershipProfile{}
|
||||
now := time.Now()
|
||||
|
||||
err := s.svc.pg.WithTx(
|
||||
@@ -1414,11 +1585,31 @@ func (s *DocumentService) Update(
|
||||
document.TrustCenterVisibility = *req.TrustCenterVisibility
|
||||
}
|
||||
|
||||
if req.ApproverID != nil {
|
||||
if err := approver.LoadByID(ctx, tx, s.svc.scope, *req.ApproverID); err != nil {
|
||||
return fmt.Errorf("cannot load approver profile %q: %w", *req.ApproverID, err)
|
||||
if len(req.ApproverIDs) > 0 {
|
||||
approverProfiles := coredata.MembershipProfiles{}
|
||||
if err := approverProfiles.LoadByIDs(ctx, tx, s.svc.scope, req.ApproverIDs); err != nil {
|
||||
return fmt.Errorf("cannot load approver profiles: %w", err)
|
||||
}
|
||||
if len(approverProfiles) != len(req.ApproverIDs) {
|
||||
return fmt.Errorf("one or more approver profiles not found")
|
||||
}
|
||||
|
||||
docApprovers := &coredata.DocumentApprovers{}
|
||||
if err := docApprovers.DeleteByDocumentID(ctx, tx, s.svc.scope, req.DocumentID); err != nil {
|
||||
return fmt.Errorf("cannot delete document approvers: %w", err)
|
||||
}
|
||||
|
||||
for _, approverID := range req.ApproverIDs {
|
||||
da := coredata.DocumentApprover{
|
||||
DocumentID: req.DocumentID,
|
||||
ApproverProfileID: approverID,
|
||||
OrganizationID: document.OrganizationID,
|
||||
CreatedAt: now,
|
||||
}
|
||||
if err := da.Insert(ctx, tx, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert document approver: %w", err)
|
||||
}
|
||||
}
|
||||
document.ApproverID = approver.ID
|
||||
}
|
||||
|
||||
document.UpdatedAt = now
|
||||
@@ -1427,18 +1618,35 @@ func (s *DocumentService) Update(
|
||||
return fmt.Errorf("cannot update document: %w", err)
|
||||
}
|
||||
|
||||
// Update the draft version if it exists to keep it in sync with the document
|
||||
draftVersion := &coredata.DocumentVersion{}
|
||||
err := draftVersion.LoadLatestVersion(ctx, tx, s.svc.scope, req.DocumentID)
|
||||
if err == nil && draftVersion.Status == coredata.DocumentStatusDraft {
|
||||
draftVersion.Title = document.Title
|
||||
draftVersion.ApproverID = document.ApproverID
|
||||
draftVersion.Classification = document.Classification
|
||||
draftVersion.UpdatedAt = now
|
||||
|
||||
if err := draftVersion.Update(ctx, tx, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot update draft version: %w", err)
|
||||
}
|
||||
|
||||
if len(req.ApproverIDs) > 0 {
|
||||
versionApprovers := &coredata.DocumentVersionApprovers{}
|
||||
if err := versionApprovers.DeleteByDocumentVersionID(ctx, tx, s.svc.scope, draftVersion.ID); err != nil {
|
||||
return fmt.Errorf("cannot delete draft version approvers: %w", err)
|
||||
}
|
||||
|
||||
for _, approverID := range req.ApproverIDs {
|
||||
dva := coredata.DocumentVersionApprover{
|
||||
DocumentVersionID: draftVersion.ID,
|
||||
ApproverProfileID: approverID,
|
||||
OrganizationID: document.OrganizationID,
|
||||
CreatedAt: now,
|
||||
}
|
||||
if err := dva.Insert(ctx, tx, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert draft version approver: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -1638,7 +1846,6 @@ func exportDocumentPDF(
|
||||
) ([]byte, error) {
|
||||
document := &coredata.Document{}
|
||||
version := &coredata.DocumentVersion{}
|
||||
approver := &coredata.MembershipProfile{}
|
||||
organization := &coredata.Organization{}
|
||||
|
||||
if err := version.LoadByID(ctx, conn, scope, documentVersionID); err != nil {
|
||||
@@ -1649,8 +1856,26 @@ func exportDocumentPDF(
|
||||
return nil, fmt.Errorf("cannot load document: %w", err)
|
||||
}
|
||||
|
||||
if err := approver.LoadByID(ctx, conn, scope, document.ApproverID); err != nil {
|
||||
return nil, fmt.Errorf("cannot load document approver profile: %w", err)
|
||||
versionApprovers := &coredata.DocumentVersionApprovers{}
|
||||
if err := versionApprovers.LoadByDocumentVersionID(ctx, conn, scope, documentVersionID); err != nil {
|
||||
return nil, fmt.Errorf("cannot load document version approvers: %w", err)
|
||||
}
|
||||
|
||||
approverProfiles := coredata.MembershipProfiles{}
|
||||
if err := approverProfiles.LoadByIDs(ctx, conn, scope, versionApprovers.ApproverProfileIDs()); err != nil {
|
||||
return nil, fmt.Errorf("cannot load document approver profiles: %w", err)
|
||||
}
|
||||
|
||||
profileByID := make(map[gid.GID]*coredata.MembershipProfile, len(approverProfiles))
|
||||
for _, p := range approverProfiles {
|
||||
profileByID[p.ID] = p
|
||||
}
|
||||
|
||||
approverNames := make([]string, 0, len(*versionApprovers))
|
||||
for _, a := range *versionApprovers {
|
||||
if p, ok := profileByID[a.ApproverProfileID]; ok {
|
||||
approverNames = append(approverNames, p.FullName)
|
||||
}
|
||||
}
|
||||
|
||||
if err := organization.LoadByID(ctx, conn, scope, document.OrganizationID); err != nil {
|
||||
@@ -1702,7 +1927,7 @@ func exportDocumentPDF(
|
||||
Content: version.Content,
|
||||
Version: version.VersionNumber,
|
||||
Classification: classification,
|
||||
Approver: approver.FullName,
|
||||
Approver: strings.Join(approverNames, ", "),
|
||||
PublishedAt: version.PublishedAt,
|
||||
Signatures: signatureData,
|
||||
CompanyHorizontalLogoBase64: horizontalLogoBase64,
|
||||
|
||||
@@ -2208,7 +2208,13 @@ type Document implements Node {
|
||||
classification: DocumentClassification!
|
||||
currentPublishedVersion: Int
|
||||
trustCenterVisibility: TrustCenterVisibility!
|
||||
approver: Profile! @goField(forceResolver: true)
|
||||
approvers(
|
||||
first: Int
|
||||
after: CursorKey
|
||||
last: Int
|
||||
before: CursorKey
|
||||
orderBy: ProfileOrder
|
||||
): ProfileConnection! @goField(forceResolver: true)
|
||||
organization: Organization! @goField(forceResolver: true)
|
||||
|
||||
versions(
|
||||
@@ -4018,7 +4024,7 @@ input CreateDocumentInput {
|
||||
organizationId: ID!
|
||||
title: String!
|
||||
content: String!
|
||||
approverId: ID!
|
||||
approverIds: [ID!]!
|
||||
documentType: DocumentType!
|
||||
classification: DocumentClassification!
|
||||
trustCenterVisibility: TrustCenterVisibility
|
||||
@@ -4028,7 +4034,7 @@ input UpdateDocumentInput {
|
||||
id: ID!
|
||||
title: String
|
||||
content: String
|
||||
approverId: ID
|
||||
approverIds: [ID!]
|
||||
documentType: DocumentType
|
||||
classification: DocumentClassification
|
||||
trustCenterVisibility: TrustCenterVisibility
|
||||
@@ -4862,7 +4868,13 @@ type DocumentVersion implements Node {
|
||||
changelog: String!
|
||||
title: String!
|
||||
classification: DocumentClassification!
|
||||
approver: Profile! @goField(forceResolver: true)
|
||||
approvers(
|
||||
first: Int
|
||||
after: CursorKey
|
||||
last: Int
|
||||
before: CursorKey
|
||||
orderBy: ProfileOrder
|
||||
): ProfileConnection! @goField(forceResolver: true)
|
||||
|
||||
signatures(
|
||||
first: Int
|
||||
|
||||
@@ -702,7 +702,7 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
Document struct {
|
||||
Approver func(childComplexity int) int
|
||||
Approvers func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy) int
|
||||
Classification func(childComplexity int) int
|
||||
Controls func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) int
|
||||
CreatedAt func(childComplexity int) int
|
||||
@@ -730,7 +730,7 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
DocumentVersion struct {
|
||||
Approver func(childComplexity int) int
|
||||
Approvers func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy) int
|
||||
Changelog func(childComplexity int) int
|
||||
Classification func(childComplexity int) int
|
||||
Content func(childComplexity int) int
|
||||
@@ -2058,7 +2058,7 @@ type DatumConnectionResolver interface {
|
||||
TotalCount(ctx context.Context, obj *types.DatumConnection) (int, error)
|
||||
}
|
||||
type DocumentResolver interface {
|
||||
Approver(ctx context.Context, obj *types.Document) (*types.Profile, error)
|
||||
Approvers(ctx context.Context, obj *types.Document, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy) (*types.ProfileConnection, error)
|
||||
Organization(ctx context.Context, obj *types.Document) (*types.Organization, error)
|
||||
Versions(ctx context.Context, obj *types.Document, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentVersionOrderBy, filter *types.DocumentVersionFilter) (*types.DocumentVersionConnection, error)
|
||||
Controls(ctx context.Context, obj *types.Document, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) (*types.ControlConnection, error)
|
||||
@@ -2071,7 +2071,7 @@ type DocumentConnectionResolver interface {
|
||||
type DocumentVersionResolver interface {
|
||||
Document(ctx context.Context, obj *types.DocumentVersion) (*types.Document, error)
|
||||
|
||||
Approver(ctx context.Context, obj *types.DocumentVersion) (*types.Profile, error)
|
||||
Approvers(ctx context.Context, obj *types.DocumentVersion, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy) (*types.ProfileConnection, error)
|
||||
Signatures(ctx context.Context, obj *types.DocumentVersion, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentVersionSignatureOrder, filter *types.DocumentVersionSignatureFilter) (*types.DocumentVersionSignatureConnection, error)
|
||||
Signed(ctx context.Context, obj *types.DocumentVersion) (bool, error)
|
||||
|
||||
@@ -4208,12 +4208,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
|
||||
return e.complexity.DeleteWebhookSubscriptionPayload.DeletedWebhookSubscriptionID(childComplexity), true
|
||||
|
||||
case "Document.approver":
|
||||
if e.complexity.Document.Approver == nil {
|
||||
case "Document.approvers":
|
||||
if e.complexity.Document.Approvers == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Document.Approver(childComplexity), true
|
||||
args, err := ec.field_Document_approvers_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Document.Approvers(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.ProfileOrderBy)), true
|
||||
case "Document.classification":
|
||||
if e.complexity.Document.Classification == nil {
|
||||
break
|
||||
@@ -4340,12 +4345,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
|
||||
return e.complexity.DocumentEdge.Node(childComplexity), true
|
||||
|
||||
case "DocumentVersion.approver":
|
||||
if e.complexity.DocumentVersion.Approver == nil {
|
||||
case "DocumentVersion.approvers":
|
||||
if e.complexity.DocumentVersion.Approvers == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.DocumentVersion.Approver(childComplexity), true
|
||||
args, err := ec.field_DocumentVersion_approvers_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.DocumentVersion.Approvers(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.ProfileOrderBy)), true
|
||||
case "DocumentVersion.changelog":
|
||||
if e.complexity.DocumentVersion.Changelog == nil {
|
||||
break
|
||||
@@ -12795,7 +12805,13 @@ type Document implements Node {
|
||||
classification: DocumentClassification!
|
||||
currentPublishedVersion: Int
|
||||
trustCenterVisibility: TrustCenterVisibility!
|
||||
approver: Profile! @goField(forceResolver: true)
|
||||
approvers(
|
||||
first: Int
|
||||
after: CursorKey
|
||||
last: Int
|
||||
before: CursorKey
|
||||
orderBy: ProfileOrder
|
||||
): ProfileConnection! @goField(forceResolver: true)
|
||||
organization: Organization! @goField(forceResolver: true)
|
||||
|
||||
versions(
|
||||
@@ -14605,7 +14621,7 @@ input CreateDocumentInput {
|
||||
organizationId: ID!
|
||||
title: String!
|
||||
content: String!
|
||||
approverId: ID!
|
||||
approverIds: [ID!]!
|
||||
documentType: DocumentType!
|
||||
classification: DocumentClassification!
|
||||
trustCenterVisibility: TrustCenterVisibility
|
||||
@@ -14615,7 +14631,7 @@ input UpdateDocumentInput {
|
||||
id: ID!
|
||||
title: String
|
||||
content: String
|
||||
approverId: ID
|
||||
approverIds: [ID!]
|
||||
documentType: DocumentType
|
||||
classification: DocumentClassification
|
||||
trustCenterVisibility: TrustCenterVisibility
|
||||
@@ -15449,7 +15465,13 @@ type DocumentVersion implements Node {
|
||||
changelog: String!
|
||||
title: String!
|
||||
classification: DocumentClassification!
|
||||
approver: Profile! @goField(forceResolver: true)
|
||||
approvers(
|
||||
first: Int
|
||||
after: CursorKey
|
||||
last: Int
|
||||
before: CursorKey
|
||||
orderBy: ProfileOrder
|
||||
): ProfileConnection! @goField(forceResolver: true)
|
||||
|
||||
signatures(
|
||||
first: Int
|
||||
@@ -16362,6 +16384,37 @@ func (ec *executionContext) field_DocumentVersionSignature_permission_args(ctx c
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_DocumentVersion_approvers_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
arg0, err := graphql.ProcessArgField(ctx, rawArgs, "first", ec.unmarshalOInt2ᚖint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["first"] = arg0
|
||||
arg1, err := graphql.ProcessArgField(ctx, rawArgs, "after", ec.unmarshalOCursorKey2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋpageᚐCursorKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["after"] = arg1
|
||||
arg2, err := graphql.ProcessArgField(ctx, rawArgs, "last", ec.unmarshalOInt2ᚖint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["last"] = arg2
|
||||
arg3, err := graphql.ProcessArgField(ctx, rawArgs, "before", ec.unmarshalOCursorKey2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋpageᚐCursorKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["before"] = arg3
|
||||
arg4, err := graphql.ProcessArgField(ctx, rawArgs, "orderBy", ec.unmarshalOProfileOrder2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐProfileOrderBy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["orderBy"] = arg4
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_DocumentVersion_permission_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
@@ -16409,6 +16462,37 @@ func (ec *executionContext) field_DocumentVersion_signatures_args(ctx context.Co
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Document_approvers_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
arg0, err := graphql.ProcessArgField(ctx, rawArgs, "first", ec.unmarshalOInt2ᚖint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["first"] = arg0
|
||||
arg1, err := graphql.ProcessArgField(ctx, rawArgs, "after", ec.unmarshalOCursorKey2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋpageᚐCursorKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["after"] = arg1
|
||||
arg2, err := graphql.ProcessArgField(ctx, rawArgs, "last", ec.unmarshalOInt2ᚖint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["last"] = arg2
|
||||
arg3, err := graphql.ProcessArgField(ctx, rawArgs, "before", ec.unmarshalOCursorKey2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋpageᚐCursorKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["before"] = arg3
|
||||
arg4, err := graphql.ProcessArgField(ctx, rawArgs, "orderBy", ec.unmarshalOProfileOrder2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐProfileOrderBy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["orderBy"] = arg4
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Document_controls_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
@@ -29115,23 +29199,24 @@ func (ec *executionContext) fieldContext_Document_trustCenterVisibility(_ contex
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Document_approver(ctx context.Context, field graphql.CollectedField, obj *types.Document) (ret graphql.Marshaler) {
|
||||
func (ec *executionContext) _Document_approvers(ctx context.Context, field graphql.CollectedField, obj *types.Document) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
ec.OperationContext,
|
||||
field,
|
||||
ec.fieldContext_Document_approver,
|
||||
ec.fieldContext_Document_approvers,
|
||||
func(ctx context.Context) (any, error) {
|
||||
return ec.resolvers.Document().Approver(ctx, obj)
|
||||
fc := graphql.GetFieldContext(ctx)
|
||||
return ec.resolvers.Document().Approvers(ctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.ProfileOrderBy))
|
||||
},
|
||||
nil,
|
||||
ec.marshalNProfile2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐProfile,
|
||||
ec.marshalNProfileConnection2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐProfileConnection,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Document_approver(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
func (ec *executionContext) fieldContext_Document_approvers(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Document",
|
||||
Field: field,
|
||||
@@ -29139,32 +29224,27 @@ func (ec *executionContext) fieldContext_Document_approver(_ context.Context, fi
|
||||
IsResolver: true,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
switch field.Name {
|
||||
case "id":
|
||||
return ec.fieldContext_Profile_id(ctx, field)
|
||||
case "fullName":
|
||||
return ec.fieldContext_Profile_fullName(ctx, field)
|
||||
case "emailAddress":
|
||||
return ec.fieldContext_Profile_emailAddress(ctx, field)
|
||||
case "additionalEmailAddresses":
|
||||
return ec.fieldContext_Profile_additionalEmailAddresses(ctx, field)
|
||||
case "kind":
|
||||
return ec.fieldContext_Profile_kind(ctx, field)
|
||||
case "position":
|
||||
return ec.fieldContext_Profile_position(ctx, field)
|
||||
case "contractStartDate":
|
||||
return ec.fieldContext_Profile_contractStartDate(ctx, field)
|
||||
case "contractEndDate":
|
||||
return ec.fieldContext_Profile_contractEndDate(ctx, field)
|
||||
case "createdAt":
|
||||
return ec.fieldContext_Profile_createdAt(ctx, field)
|
||||
case "updatedAt":
|
||||
return ec.fieldContext_Profile_updatedAt(ctx, field)
|
||||
case "permission":
|
||||
return ec.fieldContext_Profile_permission(ctx, field)
|
||||
case "totalCount":
|
||||
return ec.fieldContext_ProfileConnection_totalCount(ctx, field)
|
||||
case "edges":
|
||||
return ec.fieldContext_ProfileConnection_edges(ctx, field)
|
||||
case "pageInfo":
|
||||
return ec.fieldContext_ProfileConnection_pageInfo(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type Profile", field.Name)
|
||||
return nil, fmt.Errorf("no field named %q was found under type ProfileConnection", field.Name)
|
||||
},
|
||||
}
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = ec.Recover(ctx, r)
|
||||
ec.Error(ctx, err)
|
||||
}
|
||||
}()
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
if fc.Args, err = ec.field_Document_approvers_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return fc, err
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
@@ -29642,8 +29722,8 @@ func (ec *executionContext) fieldContext_DocumentEdge_node(_ context.Context, fi
|
||||
return ec.fieldContext_Document_currentPublishedVersion(ctx, field)
|
||||
case "trustCenterVisibility":
|
||||
return ec.fieldContext_Document_trustCenterVisibility(ctx, field)
|
||||
case "approver":
|
||||
return ec.fieldContext_Document_approver(ctx, field)
|
||||
case "approvers":
|
||||
return ec.fieldContext_Document_approvers(ctx, field)
|
||||
case "organization":
|
||||
return ec.fieldContext_Document_organization(ctx, field)
|
||||
case "versions":
|
||||
@@ -29730,8 +29810,8 @@ func (ec *executionContext) fieldContext_DocumentVersion_document(_ context.Cont
|
||||
return ec.fieldContext_Document_currentPublishedVersion(ctx, field)
|
||||
case "trustCenterVisibility":
|
||||
return ec.fieldContext_Document_trustCenterVisibility(ctx, field)
|
||||
case "approver":
|
||||
return ec.fieldContext_Document_approver(ctx, field)
|
||||
case "approvers":
|
||||
return ec.fieldContext_Document_approvers(ctx, field)
|
||||
case "organization":
|
||||
return ec.fieldContext_Document_organization(ctx, field)
|
||||
case "versions":
|
||||
@@ -29925,23 +30005,24 @@ func (ec *executionContext) fieldContext_DocumentVersion_classification(_ contex
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _DocumentVersion_approver(ctx context.Context, field graphql.CollectedField, obj *types.DocumentVersion) (ret graphql.Marshaler) {
|
||||
func (ec *executionContext) _DocumentVersion_approvers(ctx context.Context, field graphql.CollectedField, obj *types.DocumentVersion) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
ec.OperationContext,
|
||||
field,
|
||||
ec.fieldContext_DocumentVersion_approver,
|
||||
ec.fieldContext_DocumentVersion_approvers,
|
||||
func(ctx context.Context) (any, error) {
|
||||
return ec.resolvers.DocumentVersion().Approver(ctx, obj)
|
||||
fc := graphql.GetFieldContext(ctx)
|
||||
return ec.resolvers.DocumentVersion().Approvers(ctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.ProfileOrderBy))
|
||||
},
|
||||
nil,
|
||||
ec.marshalNProfile2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐProfile,
|
||||
ec.marshalNProfileConnection2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐProfileConnection,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_DocumentVersion_approver(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
func (ec *executionContext) fieldContext_DocumentVersion_approvers(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "DocumentVersion",
|
||||
Field: field,
|
||||
@@ -29949,32 +30030,27 @@ func (ec *executionContext) fieldContext_DocumentVersion_approver(_ context.Cont
|
||||
IsResolver: true,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
switch field.Name {
|
||||
case "id":
|
||||
return ec.fieldContext_Profile_id(ctx, field)
|
||||
case "fullName":
|
||||
return ec.fieldContext_Profile_fullName(ctx, field)
|
||||
case "emailAddress":
|
||||
return ec.fieldContext_Profile_emailAddress(ctx, field)
|
||||
case "additionalEmailAddresses":
|
||||
return ec.fieldContext_Profile_additionalEmailAddresses(ctx, field)
|
||||
case "kind":
|
||||
return ec.fieldContext_Profile_kind(ctx, field)
|
||||
case "position":
|
||||
return ec.fieldContext_Profile_position(ctx, field)
|
||||
case "contractStartDate":
|
||||
return ec.fieldContext_Profile_contractStartDate(ctx, field)
|
||||
case "contractEndDate":
|
||||
return ec.fieldContext_Profile_contractEndDate(ctx, field)
|
||||
case "createdAt":
|
||||
return ec.fieldContext_Profile_createdAt(ctx, field)
|
||||
case "updatedAt":
|
||||
return ec.fieldContext_Profile_updatedAt(ctx, field)
|
||||
case "permission":
|
||||
return ec.fieldContext_Profile_permission(ctx, field)
|
||||
case "totalCount":
|
||||
return ec.fieldContext_ProfileConnection_totalCount(ctx, field)
|
||||
case "edges":
|
||||
return ec.fieldContext_ProfileConnection_edges(ctx, field)
|
||||
case "pageInfo":
|
||||
return ec.fieldContext_ProfileConnection_pageInfo(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type Profile", field.Name)
|
||||
return nil, fmt.Errorf("no field named %q was found under type ProfileConnection", field.Name)
|
||||
},
|
||||
}
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = ec.Recover(ctx, r)
|
||||
ec.Error(ctx, err)
|
||||
}
|
||||
}()
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
if fc.Args, err = ec.field_DocumentVersion_approvers_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return fc, err
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
@@ -30356,8 +30432,8 @@ func (ec *executionContext) fieldContext_DocumentVersionEdge_node(_ context.Cont
|
||||
return ec.fieldContext_DocumentVersion_title(ctx, field)
|
||||
case "classification":
|
||||
return ec.fieldContext_DocumentVersion_classification(ctx, field)
|
||||
case "approver":
|
||||
return ec.fieldContext_DocumentVersion_approver(ctx, field)
|
||||
case "approvers":
|
||||
return ec.fieldContext_DocumentVersion_approvers(ctx, field)
|
||||
case "signatures":
|
||||
return ec.fieldContext_DocumentVersion_signatures(ctx, field)
|
||||
case "signed":
|
||||
@@ -30446,8 +30522,8 @@ func (ec *executionContext) fieldContext_DocumentVersionSignature_documentVersio
|
||||
return ec.fieldContext_DocumentVersion_title(ctx, field)
|
||||
case "classification":
|
||||
return ec.fieldContext_DocumentVersion_classification(ctx, field)
|
||||
case "approver":
|
||||
return ec.fieldContext_DocumentVersion_approver(ctx, field)
|
||||
case "approvers":
|
||||
return ec.fieldContext_DocumentVersion_approvers(ctx, field)
|
||||
case "signatures":
|
||||
return ec.fieldContext_DocumentVersion_signatures(ctx, field)
|
||||
case "signed":
|
||||
@@ -45461,8 +45537,8 @@ func (ec *executionContext) fieldContext_PublishDocumentVersionPayload_documentV
|
||||
return ec.fieldContext_DocumentVersion_title(ctx, field)
|
||||
case "classification":
|
||||
return ec.fieldContext_DocumentVersion_classification(ctx, field)
|
||||
case "approver":
|
||||
return ec.fieldContext_DocumentVersion_approver(ctx, field)
|
||||
case "approvers":
|
||||
return ec.fieldContext_DocumentVersion_approvers(ctx, field)
|
||||
case "signatures":
|
||||
return ec.fieldContext_DocumentVersion_signatures(ctx, field)
|
||||
case "signed":
|
||||
@@ -45520,8 +45596,8 @@ func (ec *executionContext) fieldContext_PublishDocumentVersionPayload_document(
|
||||
return ec.fieldContext_Document_currentPublishedVersion(ctx, field)
|
||||
case "trustCenterVisibility":
|
||||
return ec.fieldContext_Document_trustCenterVisibility(ctx, field)
|
||||
case "approver":
|
||||
return ec.fieldContext_Document_approver(ctx, field)
|
||||
case "approvers":
|
||||
return ec.fieldContext_Document_approvers(ctx, field)
|
||||
case "organization":
|
||||
return ec.fieldContext_Document_organization(ctx, field)
|
||||
case "versions":
|
||||
@@ -52250,8 +52326,8 @@ func (ec *executionContext) fieldContext_TrustCenterDocumentAccess_document(_ co
|
||||
return ec.fieldContext_Document_currentPublishedVersion(ctx, field)
|
||||
case "trustCenterVisibility":
|
||||
return ec.fieldContext_Document_trustCenterVisibility(ctx, field)
|
||||
case "approver":
|
||||
return ec.fieldContext_Document_approver(ctx, field)
|
||||
case "approvers":
|
||||
return ec.fieldContext_Document_approvers(ctx, field)
|
||||
case "organization":
|
||||
return ec.fieldContext_Document_organization(ctx, field)
|
||||
case "versions":
|
||||
@@ -54047,8 +54123,8 @@ func (ec *executionContext) fieldContext_UpdateDocumentPayload_document(_ contex
|
||||
return ec.fieldContext_Document_currentPublishedVersion(ctx, field)
|
||||
case "trustCenterVisibility":
|
||||
return ec.fieldContext_Document_trustCenterVisibility(ctx, field)
|
||||
case "approver":
|
||||
return ec.fieldContext_Document_approver(ctx, field)
|
||||
case "approvers":
|
||||
return ec.fieldContext_Document_approvers(ctx, field)
|
||||
case "organization":
|
||||
return ec.fieldContext_Document_organization(ctx, field)
|
||||
case "versions":
|
||||
@@ -54108,8 +54184,8 @@ func (ec *executionContext) fieldContext_UpdateDocumentVersionPayload_documentVe
|
||||
return ec.fieldContext_DocumentVersion_title(ctx, field)
|
||||
case "classification":
|
||||
return ec.fieldContext_DocumentVersion_classification(ctx, field)
|
||||
case "approver":
|
||||
return ec.fieldContext_DocumentVersion_approver(ctx, field)
|
||||
case "approvers":
|
||||
return ec.fieldContext_DocumentVersion_approvers(ctx, field)
|
||||
case "signatures":
|
||||
return ec.fieldContext_DocumentVersion_signatures(ctx, field)
|
||||
case "signed":
|
||||
@@ -63387,7 +63463,7 @@ func (ec *executionContext) unmarshalInputCreateDocumentInput(ctx context.Contex
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"organizationId", "title", "content", "approverId", "documentType", "classification", "trustCenterVisibility"}
|
||||
fieldsInOrder := [...]string{"organizationId", "title", "content", "approverIds", "documentType", "classification", "trustCenterVisibility"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -63415,13 +63491,13 @@ func (ec *executionContext) unmarshalInputCreateDocumentInput(ctx context.Contex
|
||||
return it, err
|
||||
}
|
||||
it.Content = data
|
||||
case "approverId":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("approverId"))
|
||||
data, err := ec.unmarshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v)
|
||||
case "approverIds":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("approverIds"))
|
||||
data, err := ec.unmarshalNID2ᚕgoᚗproboᚗincᚋproboᚋpkgᚋgidᚐGIDᚄ(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.ApproverID = data
|
||||
it.ApproverIds = data
|
||||
case "documentType":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("documentType"))
|
||||
data, err := ec.unmarshalNDocumentType2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐDocumentType(ctx, v)
|
||||
@@ -68341,7 +68417,7 @@ func (ec *executionContext) unmarshalInputUpdateDocumentInput(ctx context.Contex
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"id", "title", "content", "approverId", "documentType", "classification", "trustCenterVisibility"}
|
||||
fieldsInOrder := [...]string{"id", "title", "content", "approverIds", "documentType", "classification", "trustCenterVisibility"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -68369,13 +68445,13 @@ func (ec *executionContext) unmarshalInputUpdateDocumentInput(ctx context.Contex
|
||||
return it, err
|
||||
}
|
||||
it.Content = data
|
||||
case "approverId":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("approverId"))
|
||||
data, err := ec.unmarshalOID2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v)
|
||||
case "approverIds":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("approverIds"))
|
||||
data, err := ec.unmarshalOID2ᚕgoᚗproboᚗincᚋproboᚋpkgᚋgidᚐGIDᚄ(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.ApproverID = data
|
||||
it.ApproverIds = data
|
||||
case "documentType":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("documentType"))
|
||||
data, err := ec.unmarshalODocumentType2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐDocumentType(ctx, v)
|
||||
@@ -77056,7 +77132,7 @@ func (ec *executionContext) _Document(ctx context.Context, sel ast.SelectionSet,
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "approver":
|
||||
case "approvers":
|
||||
field := field
|
||||
|
||||
innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
|
||||
@@ -77065,7 +77141,7 @@ func (ec *executionContext) _Document(ctx context.Context, sel ast.SelectionSet,
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._Document_approver(ctx, field, obj)
|
||||
res = ec._Document_approvers(ctx, field, obj)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&fs.Invalids, 1)
|
||||
}
|
||||
@@ -77475,7 +77551,7 @@ func (ec *executionContext) _DocumentVersion(ctx context.Context, sel ast.Select
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "approver":
|
||||
case "approvers":
|
||||
field := field
|
||||
|
||||
innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
|
||||
@@ -77484,7 +77560,7 @@ func (ec *executionContext) _DocumentVersion(ctx context.Context, sel ast.Select
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._DocumentVersion_approver(ctx, field, obj)
|
||||
res = ec._DocumentVersion_approvers(ctx, field, obj)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&fs.Invalids, 1)
|
||||
}
|
||||
|
||||
@@ -80,9 +80,6 @@ func NewDocument(document *coredata.Document) *Document {
|
||||
Organization: &Organization{
|
||||
ID: document.OrganizationID,
|
||||
},
|
||||
Approver: &Profile{
|
||||
ID: document.ApproverID,
|
||||
},
|
||||
DocumentType: document.DocumentType,
|
||||
Classification: document.Classification,
|
||||
CurrentPublishedVersion: document.CurrentPublishedVersion,
|
||||
|
||||
@@ -76,9 +76,6 @@ func NewDocumentVersion(documentVersion *coredata.DocumentVersion) *DocumentVers
|
||||
Document: &Document{
|
||||
ID: documentVersion.DocumentID,
|
||||
},
|
||||
Approver: &Profile{
|
||||
ID: documentVersion.ApproverID,
|
||||
},
|
||||
Version: documentVersion.VersionNumber,
|
||||
Title: documentVersion.Title,
|
||||
Content: documentVersion.Content,
|
||||
|
||||
@@ -369,7 +369,7 @@ type CreateDocumentInput struct {
|
||||
OrganizationID gid.GID `json:"organizationId"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
ApproverID gid.GID `json:"approverId"`
|
||||
ApproverIds []gid.GID `json:"approverIds"`
|
||||
DocumentType coredata.DocumentType `json:"documentType"`
|
||||
Classification coredata.DocumentClassification `json:"classification"`
|
||||
TrustCenterVisibility *coredata.TrustCenterVisibility `json:"trustCenterVisibility,omitempty"`
|
||||
@@ -1129,7 +1129,7 @@ type Document struct {
|
||||
Classification coredata.DocumentClassification `json:"classification"`
|
||||
CurrentPublishedVersion *int `json:"currentPublishedVersion,omitempty"`
|
||||
TrustCenterVisibility coredata.TrustCenterVisibility `json:"trustCenterVisibility"`
|
||||
Approver *Profile `json:"approver"`
|
||||
Approvers *ProfileConnection `json:"approvers"`
|
||||
Organization *Organization `json:"organization"`
|
||||
Versions *DocumentVersionConnection `json:"versions"`
|
||||
Controls *ControlConnection `json:"controls"`
|
||||
@@ -1159,7 +1159,7 @@ type DocumentVersion struct {
|
||||
Changelog string `json:"changelog"`
|
||||
Title string `json:"title"`
|
||||
Classification coredata.DocumentClassification `json:"classification"`
|
||||
Approver *Profile `json:"approver"`
|
||||
Approvers *ProfileConnection `json:"approvers"`
|
||||
Signatures *DocumentVersionSignatureConnection `json:"signatures"`
|
||||
Signed bool `json:"signed"`
|
||||
PublishedAt *time.Time `json:"publishedAt,omitempty"`
|
||||
@@ -2036,7 +2036,7 @@ type UpdateDocumentInput struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Title *string `json:"title,omitempty"`
|
||||
Content *string `json:"content,omitempty"`
|
||||
ApproverID *gid.GID `json:"approverId,omitempty"`
|
||||
ApproverIds []gid.GID `json:"approverIds,omitempty"`
|
||||
DocumentType *coredata.DocumentType `json:"documentType,omitempty"`
|
||||
Classification *coredata.DocumentClassification `json:"classification,omitempty"`
|
||||
TrustCenterVisibility *coredata.TrustCenterVisibility `json:"trustCenterVisibility,omitempty"`
|
||||
|
||||
@@ -862,23 +862,39 @@ func (r *datumConnectionResolver) TotalCount(ctx context.Context, obj *types.Dat
|
||||
panic(fmt.Errorf("unsupported resolver: %T", obj.Resolver))
|
||||
}
|
||||
|
||||
// Approver is the resolver for the approver field.
|
||||
func (r *documentResolver) Approver(ctx context.Context, obj *types.Document) (*types.Profile, error) {
|
||||
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileGet); err != nil {
|
||||
// Approvers is the resolver for the approvers field.
|
||||
func (r *documentResolver) Approvers(ctx context.Context, obj *types.Document, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy) (*types.ProfileConnection, error) {
|
||||
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileList); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
approver, err := r.iam.OrganizationService.GetProfile(ctx, obj.Approver.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||
return nil, gqlutils.NotFound(ctx, err)
|
||||
}
|
||||
|
||||
// TODO no panic use gqlutils.InternalError
|
||||
panic(fmt.Errorf("cannot get approver: %w", err))
|
||||
if gqlutils.OnlyTotalCountSelected(ctx) {
|
||||
return &types.ProfileConnection{
|
||||
Resolver: r,
|
||||
ParentID: obj.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return types.NewProfile(approver), nil
|
||||
prb := r.ProboService(ctx, obj.ID.TenantID())
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
|
||||
Field: coredata.MembershipProfileOrderFieldCreatedAt,
|
||||
Direction: page.OrderDirectionDesc,
|
||||
}
|
||||
if orderBy != nil {
|
||||
pageOrderBy.Field = coredata.MembershipProfileOrderField(orderBy.Field)
|
||||
pageOrderBy.Direction = page.OrderDirection(orderBy.Direction)
|
||||
}
|
||||
|
||||
c := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||
|
||||
p, err := prb.Documents.ListApprovers(ctx, obj.ID, c)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot list document approvers", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return types.NewProfileConnection(p, r, obj.ID, nil), nil
|
||||
}
|
||||
|
||||
// Organization is the resolver for the organization field.
|
||||
@@ -1031,23 +1047,39 @@ func (r *documentVersionResolver) Document(ctx context.Context, obj *types.Docum
|
||||
return types.NewDocument(document), nil
|
||||
}
|
||||
|
||||
// Approver is the resolver for the approver field.
|
||||
func (r *documentVersionResolver) Approver(ctx context.Context, obj *types.DocumentVersion) (*types.Profile, error) {
|
||||
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileGet); err != nil {
|
||||
// Approvers is the resolver for the approvers field.
|
||||
func (r *documentVersionResolver) Approvers(ctx context.Context, obj *types.DocumentVersion, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy) (*types.ProfileConnection, error) {
|
||||
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileList); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
approver, err := r.iam.OrganizationService.GetProfile(ctx, obj.Approver.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||
return nil, gqlutils.NotFound(ctx, err)
|
||||
}
|
||||
|
||||
// TODO no panic use gqlutils.InternalError
|
||||
panic(fmt.Errorf("cannot get approver: %w", err))
|
||||
if gqlutils.OnlyTotalCountSelected(ctx) {
|
||||
return &types.ProfileConnection{
|
||||
Resolver: r,
|
||||
ParentID: obj.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return types.NewProfile(approver), nil
|
||||
prb := r.ProboService(ctx, obj.ID.TenantID())
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
|
||||
Field: coredata.MembershipProfileOrderFieldCreatedAt,
|
||||
Direction: page.OrderDirectionDesc,
|
||||
}
|
||||
if orderBy != nil {
|
||||
pageOrderBy.Field = coredata.MembershipProfileOrderField(orderBy.Field)
|
||||
pageOrderBy.Direction = page.OrderDirection(orderBy.Direction)
|
||||
}
|
||||
|
||||
c := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||
|
||||
p, err := prb.Documents.ListVersionApprovers(ctx, obj.ID, c)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot list document version approvers", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return types.NewProfileConnection(p, r, obj.ID, nil), nil
|
||||
}
|
||||
|
||||
// Signatures is the resolver for the signatures field.
|
||||
@@ -3528,7 +3560,7 @@ func (r *mutationResolver) CreateDocument(ctx context.Context, input types.Creat
|
||||
OrganizationID: input.OrganizationID,
|
||||
DocumentType: input.DocumentType,
|
||||
Title: input.Title,
|
||||
ApproverID: input.ApproverID,
|
||||
ApproverIDs: input.ApproverIds,
|
||||
Content: input.Content,
|
||||
Classification: input.Classification,
|
||||
TrustCenterVisibility: input.TrustCenterVisibility,
|
||||
@@ -3562,7 +3594,7 @@ func (r *mutationResolver) UpdateDocument(ctx context.Context, input types.Updat
|
||||
probo.UpdateDocumentRequest{
|
||||
DocumentID: input.ID,
|
||||
Title: input.Title,
|
||||
ApproverID: input.ApproverID,
|
||||
ApproverIDs: input.ApproverIds,
|
||||
Classification: input.Classification,
|
||||
DocumentType: input.DocumentType,
|
||||
TrustCenterVisibility: input.TrustCenterVisibility,
|
||||
@@ -6576,6 +6608,20 @@ func (r *profileConnectionResolver) TotalCount(ctx context.Context, obj *types.P
|
||||
panic(fmt.Errorf("cannot count profiles: %w", err))
|
||||
}
|
||||
return count, nil
|
||||
case *documentResolver:
|
||||
prb := r.ProboService(ctx, obj.ParentID.TenantID())
|
||||
count, err := prb.Documents.CountApprovers(ctx, obj.ParentID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot count document approvers: %w", err))
|
||||
}
|
||||
return count, nil
|
||||
case *documentVersionResolver:
|
||||
prb := r.ProboService(ctx, obj.ParentID.TenantID())
|
||||
count, err := prb.Documents.CountVersionApprovers(ctx, obj.ParentID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot count document version approvers: %w", err))
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("not implemented: TotalCount for parent type %T", obj.Resolver))
|
||||
|
||||
36
pkg/server/api/mcp/v1/helpers.go
Normal file
36
pkg/server/api/mcp/v1/helpers.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package mcp_v1
|
||||
|
||||
import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
func allApproversCursor() *page.Cursor[coredata.MembershipProfileOrderField] {
|
||||
return page.NewCursor(100, nil, page.Head, page.OrderBy[coredata.MembershipProfileOrderField]{
|
||||
Field: coredata.MembershipProfileOrderFieldCreatedAt,
|
||||
Direction: page.OrderDirectionDesc,
|
||||
})
|
||||
}
|
||||
|
||||
func profileIDs(p *page.Page[*coredata.MembershipProfile, coredata.MembershipProfileOrderField]) []gid.GID {
|
||||
ids := make([]gid.GID, len(p.Data))
|
||||
for i, profile := range p.Data {
|
||||
ids[i] = profile.ID
|
||||
}
|
||||
return ids
|
||||
}
|
||||
@@ -1553,12 +1553,21 @@ func (r *Resolver) ListDocumentsTool(ctx context.Context, req *mcp.CallToolReque
|
||||
documentFilter = coredata.NewDocumentFilter(query)
|
||||
}
|
||||
|
||||
page, err := prb.Documents.ListByOrganizationID(ctx, input.OrganizationID, cursor, documentFilter)
|
||||
docPage, err := prb.Documents.ListByOrganizationID(ctx, input.OrganizationID, cursor, documentFilter)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list organization documents: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.NewListDocumentsOutput(page), nil
|
||||
approverIDsMap := make(map[gid.GID][]gid.GID)
|
||||
for _, d := range docPage.Data {
|
||||
approverPage, err := prb.Documents.ListApprovers(ctx, d.ID, allApproversCursor())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list document approvers: %w", err))
|
||||
}
|
||||
approverIDsMap[d.ID] = profileIDs(approverPage)
|
||||
}
|
||||
|
||||
return nil, types.NewListDocumentsOutput(docPage, approverIDsMap), nil
|
||||
}
|
||||
|
||||
func (r *Resolver) GetDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentInput) (*mcp.CallToolResult, types.GetDocumentOutput, error) {
|
||||
@@ -1571,8 +1580,13 @@ func (r *Resolver) GetDocumentTool(ctx context.Context, req *mcp.CallToolRequest
|
||||
panic(fmt.Errorf("cannot get document: %w", err))
|
||||
}
|
||||
|
||||
approverPage, err := prb.Documents.ListApprovers(ctx, input.ID, allApproversCursor())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list document approvers: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.GetDocumentOutput{
|
||||
Document: types.NewDocument(document),
|
||||
Document: types.NewDocument(document, profileIDs(approverPage)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1592,7 +1606,7 @@ func (r *Resolver) AddDocumentTool(ctx context.Context, req *mcp.CallToolRequest
|
||||
OrganizationID: input.OrganizationID,
|
||||
Title: input.Title,
|
||||
Content: input.Content,
|
||||
ApproverID: input.ApproverID,
|
||||
ApproverIDs: input.ApproverIds,
|
||||
Classification: input.Classification,
|
||||
DocumentType: input.DocumentType,
|
||||
TrustCenterVisibility: trustCenterVisibility,
|
||||
@@ -1602,7 +1616,7 @@ func (r *Resolver) AddDocumentTool(ctx context.Context, req *mcp.CallToolRequest
|
||||
panic(fmt.Errorf("cannot create document: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.NewAddDocumentOutput(document, documentVersion), nil
|
||||
return nil, types.NewAddDocumentOutput(document, documentVersion, input.ApproverIds, input.ApproverIds), nil
|
||||
}
|
||||
|
||||
func (r *Resolver) UpdateDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateDocumentInput) (*mcp.CallToolResult, types.UpdateDocumentOutput, error) {
|
||||
@@ -1615,7 +1629,7 @@ func (r *Resolver) UpdateDocumentTool(ctx context.Context, req *mcp.CallToolRequ
|
||||
probo.UpdateDocumentRequest{
|
||||
DocumentID: input.ID,
|
||||
Title: input.Title,
|
||||
ApproverID: input.ApproverID,
|
||||
ApproverIDs: input.ApproverIds,
|
||||
Classification: input.Classification,
|
||||
DocumentType: input.DocumentType,
|
||||
TrustCenterVisibility: input.TrustCenterVisibility,
|
||||
@@ -1625,8 +1639,13 @@ func (r *Resolver) UpdateDocumentTool(ctx context.Context, req *mcp.CallToolRequ
|
||||
panic(fmt.Errorf("cannot update document: %w", err))
|
||||
}
|
||||
|
||||
approverPage, err := svc.Documents.ListApprovers(ctx, input.ID, allApproversCursor())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list document approvers: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.UpdateDocumentOutput{
|
||||
Document: types.NewDocument(document),
|
||||
Document: types.NewDocument(document, profileIDs(approverPage)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1647,12 +1666,21 @@ func (r *Resolver) ListDocumentVersionsTool(ctx context.Context, req *mcp.CallTo
|
||||
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
||||
svc := r.ProboService(ctx, input.DocumentID)
|
||||
|
||||
page, err := svc.Documents.ListVersions(ctx, input.DocumentID, cursor, coredata.NewDocumentVersionFilter())
|
||||
versionPage, err := svc.Documents.ListVersions(ctx, input.DocumentID, cursor, coredata.NewDocumentVersionFilter())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list document versions: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.NewListDocumentVersionsOutput(page), nil
|
||||
approverIDsMap := make(map[gid.GID][]gid.GID)
|
||||
for _, v := range versionPage.Data {
|
||||
approverPage, err := svc.Documents.ListVersionApprovers(ctx, v.ID, allApproversCursor())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list document version approvers: %w", err))
|
||||
}
|
||||
approverIDsMap[v.ID] = profileIDs(approverPage)
|
||||
}
|
||||
|
||||
return nil, types.NewListDocumentVersionsOutput(versionPage, approverIDsMap), nil
|
||||
}
|
||||
|
||||
func (r *Resolver) GetDocumentVersionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentVersionInput) (*mcp.CallToolResult, types.GetDocumentVersionOutput, error) {
|
||||
@@ -1665,8 +1693,13 @@ func (r *Resolver) GetDocumentVersionTool(ctx context.Context, req *mcp.CallTool
|
||||
panic(fmt.Errorf("cannot get document version: %w", err))
|
||||
}
|
||||
|
||||
approverPage, err := svc.Documents.ListVersionApprovers(ctx, input.ID, allApproversCursor())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list document version approvers: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.GetDocumentVersionOutput{
|
||||
DocumentVersion: types.NewDocumentVersion(version),
|
||||
DocumentVersion: types.NewDocumentVersion(version, profileIDs(approverPage)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1680,8 +1713,13 @@ func (r *Resolver) CreateDraftDocumentVersionTool(ctx context.Context, req *mcp.
|
||||
panic(fmt.Errorf("cannot create draft document version: %w", err))
|
||||
}
|
||||
|
||||
approverPage, err := svc.Documents.ListVersionApprovers(ctx, draftVersion.ID, allApproversCursor())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list document version approvers: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.CreateDraftDocumentVersionOutput{
|
||||
DocumentVersion: types.NewDocumentVersion(draftVersion),
|
||||
DocumentVersion: types.NewDocumentVersion(draftVersion, profileIDs(approverPage)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1701,8 +1739,13 @@ func (r *Resolver) UpdateDocumentVersionTool(ctx context.Context, req *mcp.CallT
|
||||
panic(fmt.Errorf("cannot update document version: %w", err))
|
||||
}
|
||||
|
||||
versionApproverPage, err := svc.Documents.ListVersionApprovers(ctx, documentVersion.ID, allApproversCursor())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list document version approvers: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.UpdateDocumentVersionOutput{
|
||||
DocumentVersion: types.NewDocumentVersion(documentVersion),
|
||||
DocumentVersion: types.NewDocumentVersion(documentVersion, profileIDs(versionApproverPage)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1718,9 +1761,19 @@ func (r *Resolver) PublishDocumentVersionTool(ctx context.Context, req *mcp.Call
|
||||
panic(fmt.Errorf("cannot publish document version: %w", err))
|
||||
}
|
||||
|
||||
docApproverPage, err := svc.Documents.ListApprovers(ctx, document.ID, allApproversCursor())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list document approvers: %w", err))
|
||||
}
|
||||
|
||||
versionApproverPage, err := svc.Documents.ListVersionApprovers(ctx, documentVersion.ID, allApproversCursor())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list document version approvers: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.PublishDocumentVersionOutput{
|
||||
Document: types.NewDocument(document),
|
||||
DocumentVersion: types.NewDocumentVersion(documentVersion),
|
||||
Document: types.NewDocument(document, profileIDs(docApproverPage)),
|
||||
DocumentVersion: types.NewDocumentVersion(documentVersion, profileIDs(versionApproverPage)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3649,7 +3649,7 @@ components:
|
||||
required:
|
||||
- id
|
||||
- organization_id
|
||||
- owner_id
|
||||
- approver_ids
|
||||
- title
|
||||
- document_type
|
||||
- classification
|
||||
@@ -3663,9 +3663,11 @@ components:
|
||||
organization_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Organization ID
|
||||
owner_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Owner ID
|
||||
approver_ids:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Approver IDs
|
||||
title:
|
||||
type: string
|
||||
description: Document title
|
||||
@@ -3699,7 +3701,7 @@ components:
|
||||
- organization_id
|
||||
- document_id
|
||||
- title
|
||||
- owner_id
|
||||
- approver_ids
|
||||
- version_number
|
||||
- classification
|
||||
- content
|
||||
@@ -3720,9 +3722,11 @@ components:
|
||||
title:
|
||||
type: string
|
||||
description: Document version title
|
||||
owner_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Owner ID
|
||||
approver_ids:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Approver IDs
|
||||
version_number:
|
||||
type: integer
|
||||
description: Version number
|
||||
@@ -3864,7 +3868,7 @@ components:
|
||||
- organization_id
|
||||
- title
|
||||
- content
|
||||
- owner_id
|
||||
- approver_ids
|
||||
- classification
|
||||
- document_type
|
||||
properties:
|
||||
@@ -3877,9 +3881,11 @@ components:
|
||||
content:
|
||||
type: string
|
||||
description: Document content
|
||||
owner_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Owner ID
|
||||
approver_ids:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Approver IDs
|
||||
classification:
|
||||
$ref: "#/components/schemas/DocumentClassification"
|
||||
description: Document classification
|
||||
@@ -3912,9 +3918,11 @@ components:
|
||||
title:
|
||||
type: string
|
||||
description: Document title
|
||||
owner_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Owner ID
|
||||
approver_ids:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Approver IDs
|
||||
classification:
|
||||
$ref: "#/components/schemas/DocumentClassification"
|
||||
description: Document classification
|
||||
|
||||
@@ -16,14 +16,15 @@ package types
|
||||
|
||||
import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
func NewDocument(d *coredata.Document) *Document {
|
||||
func NewDocument(d *coredata.Document, approverIDs []gid.GID) *Document {
|
||||
return &Document{
|
||||
ID: d.ID,
|
||||
OrganizationID: d.OrganizationID,
|
||||
ApproverID: d.ApproverID,
|
||||
ApproverIds: approverIDs,
|
||||
Title: d.Title,
|
||||
DocumentType: d.DocumentType,
|
||||
Classification: d.Classification,
|
||||
@@ -34,10 +35,10 @@ func NewDocument(d *coredata.Document) *Document {
|
||||
}
|
||||
}
|
||||
|
||||
func NewListDocumentsOutput(documentPage *page.Page[*coredata.Document, coredata.DocumentOrderField]) ListDocumentsOutput {
|
||||
func NewListDocumentsOutput(documentPage *page.Page[*coredata.Document, coredata.DocumentOrderField], approverIDsMap map[gid.GID][]gid.GID) ListDocumentsOutput {
|
||||
documents := make([]*Document, 0, len(documentPage.Data))
|
||||
for _, d := range documentPage.Data {
|
||||
documents = append(documents, NewDocument(d))
|
||||
documents = append(documents, NewDocument(d, approverIDsMap[d.ID]))
|
||||
}
|
||||
|
||||
var nextCursor *page.CursorKey
|
||||
@@ -52,20 +53,20 @@ func NewListDocumentsOutput(documentPage *page.Page[*coredata.Document, coredata
|
||||
}
|
||||
}
|
||||
|
||||
func NewAddDocumentOutput(doc *coredata.Document, docVersion *coredata.DocumentVersion) AddDocumentOutput {
|
||||
func NewAddDocumentOutput(doc *coredata.Document, docVersion *coredata.DocumentVersion, docApproverIDs []gid.GID, versionApproverIDs []gid.GID) AddDocumentOutput {
|
||||
return AddDocumentOutput{
|
||||
Document: NewDocument(doc),
|
||||
DocumentVersion: NewDocumentVersion(docVersion),
|
||||
Document: NewDocument(doc, docApproverIDs),
|
||||
DocumentVersion: NewDocumentVersion(docVersion, versionApproverIDs),
|
||||
}
|
||||
}
|
||||
|
||||
func NewDocumentVersion(dv *coredata.DocumentVersion) *DocumentVersion {
|
||||
func NewDocumentVersion(dv *coredata.DocumentVersion, approverIDs []gid.GID) *DocumentVersion {
|
||||
return &DocumentVersion{
|
||||
ID: dv.ID,
|
||||
OrganizationID: dv.OrganizationID,
|
||||
DocumentID: dv.DocumentID,
|
||||
Title: dv.Title,
|
||||
ApproverID: dv.ApproverID,
|
||||
ApproverIds: approverIDs,
|
||||
VersionNumber: dv.VersionNumber,
|
||||
Classification: dv.Classification,
|
||||
Content: dv.Content,
|
||||
@@ -77,10 +78,10 @@ func NewDocumentVersion(dv *coredata.DocumentVersion) *DocumentVersion {
|
||||
}
|
||||
}
|
||||
|
||||
func NewListDocumentVersionsOutput(versionPage *page.Page[*coredata.DocumentVersion, coredata.DocumentVersionOrderField]) ListDocumentVersionsOutput {
|
||||
func NewListDocumentVersionsOutput(versionPage *page.Page[*coredata.DocumentVersion, coredata.DocumentVersionOrderField], approverIDsMap map[gid.GID][]gid.GID) ListDocumentVersionsOutput {
|
||||
versions := make([]*DocumentVersion, 0, len(versionPage.Data))
|
||||
for _, v := range versionPage.Data {
|
||||
versions = append(versions, NewDocumentVersion(v))
|
||||
versions = append(versions, NewDocumentVersion(v, approverIDsMap[v.ID]))
|
||||
}
|
||||
|
||||
var nextCursor *page.CursorKey
|
||||
|
||||
@@ -25,8 +25,8 @@ var (
|
||||
AddControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"exclusion_justification":{"description":"Exclusion justification"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"status":{"type":"string","enum":["INCLUDED","EXCLUDED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","status","created_at","updated_at"]}},"required":["control"]}`)
|
||||
AddDatumToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"vendor_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Vendor IDs"}},"required":["organization_id","name","data_classification","owner_id"]}`)
|
||||
AddDatumToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"datum":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","data_classification","owner_id","created_at","updated_at"]}},"required":["datum"]}`)
|
||||
AddDocumentToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"organization_id":{"type":"string","format":"string"},"approver_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]}},"required":["organization_id","title","content","approver_id","classification","document_type"]}`)
|
||||
AddDocumentToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document":{"type":"object","properties":{"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"current_published_version":{"description":"Current published version number"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"approver_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","approver_id","title","document_type","classification","trust_center_visibility","created_at","updated_at"]},"document_version":{"type":"object","properties":{"changelog":{"type":"string","description":"Changelog"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"approver_id":{"type":"string","format":"string"},"published_at":{"description":"Published timestamp","format":"date-time"},"status":{"type":"string","enum":["DRAFT","PUBLISHED"]},"title":{"type":"string","description":"Document version title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"version_number":{"type":"integer","description":"Version number"}},"required":["id","organization_id","document_id","title","approver_id","version_number","classification","content","changelog","status","created_at","updated_at"]}},"required":["document","document_version"]}`)
|
||||
AddDocumentToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"organization_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]}},"required":["organization_id","title","content","approver_ids","classification","document_type"]}`)
|
||||
AddDocumentToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document":{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"current_published_version":{"description":"Current published version number"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","approver_ids","title","document_type","classification","trust_center_visibility","created_at","updated_at"]},"document_version":{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"changelog":{"type":"string","description":"Changelog"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"published_at":{"description":"Published timestamp","format":"date-time"},"status":{"type":"string","enum":["DRAFT","PUBLISHED"]},"title":{"type":"string","description":"Document version title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"version_number":{"type":"integer","description":"Version number"}},"required":["id","organization_id","document_id","title","approver_ids","version_number","classification","content","changelog","status","created_at","updated_at"]}},"required":["document","document_version"]}`)
|
||||
AddFrameworkToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"type":"string","description":"Framework description"},"name":{"type":"string","description":"Framework name"},"organization_id":{"type":"string","format":"string"}},"required":["organization_id","name"]}`)
|
||||
AddFrameworkToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"framework":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Framework description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Framework name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","created_at","updated_at"]}},"required":["framework"]}`)
|
||||
AddMeasureToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"category":{"type":"string","description":"Measure category"},"description":{"type":"string","description":"Measure description"},"name":{"type":"string","description":"Measure name"},"organization_id":{"type":"string","format":"string"}},"required":["organization_id","name","category"]}`)
|
||||
@@ -48,7 +48,7 @@ var (
|
||||
CancelSignatureRequestToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version_signature_id":{"type":"string","format":"string"}},"required":["document_version_signature_id"]}`)
|
||||
CancelSignatureRequestToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"deleted_document_version_signature_id":{"type":"string","format":"string"}},"required":["deleted_document_version_signature_id"]}`)
|
||||
CreateDraftDocumentVersionToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_id":{"type":"string","format":"string"}},"required":["document_id"]}`)
|
||||
CreateDraftDocumentVersionToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version":{"type":"object","properties":{"changelog":{"type":"string","description":"Changelog"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"published_at":{"description":"Published timestamp","format":"date-time"},"status":{"type":"string","enum":["DRAFT","PUBLISHED"]},"title":{"type":"string","description":"Document version title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"version_number":{"type":"integer","description":"Version number"}},"required":["id","organization_id","document_id","title","owner_id","version_number","classification","content","changelog","status","created_at","updated_at"]}},"required":["document_version"]}`)
|
||||
CreateDraftDocumentVersionToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version":{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"changelog":{"type":"string","description":"Changelog"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"published_at":{"description":"Published timestamp","format":"date-time"},"status":{"type":"string","enum":["DRAFT","PUBLISHED"]},"title":{"type":"string","description":"Document version title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"version_number":{"type":"integer","description":"Version number"}},"required":["id","organization_id","document_id","title","approver_ids","version_number","classification","content","changelog","status","created_at","updated_at"]}},"required":["document_version"]}`)
|
||||
DeleteDocumentToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_id":{"type":"string","format":"string"}},"required":["document_id"]}`)
|
||||
DeleteDocumentToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"deleted_document_id":{"type":"string","format":"string"}},"required":["deleted_document_id"]}`)
|
||||
DeleteDraftDocumentVersionToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version_id":{"type":"string","format":"string"}},"required":["document_version_id"]}`)
|
||||
@@ -70,11 +70,11 @@ var (
|
||||
GetDatumToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
GetDatumToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"datum":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","data_classification","owner_id","created_at","updated_at"]}},"required":["datum"]}`)
|
||||
GetDocumentToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
GetDocumentToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document":{"type":"object","properties":{"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"current_published_version":{"description":"Current published version number"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"approver_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","approver_id","title","document_type","classification","trust_center_visibility","created_at","updated_at"]}},"required":["document"]}`)
|
||||
GetDocumentToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document":{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"current_published_version":{"description":"Current published version number"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","approver_ids","title","document_type","classification","trust_center_visibility","created_at","updated_at"]}},"required":["document"]}`)
|
||||
GetDocumentVersionSignatureToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
GetDocumentVersionSignatureToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version_signature":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_version_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"requested_at":{"type":"string","description":"Requested timestamp","format":"date-time"},"signed_at":{"description":"Signed timestamp","format":"date-time"},"signed_by":{"type":"string","format":"string"},"state":{"type":"string","enum":["REQUESTED","SIGNED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","document_version_id","state","signed_by","requested_at","created_at","updated_at"]}},"required":["document_version_signature"]}`)
|
||||
GetDocumentVersionToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
GetDocumentVersionToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version":{"type":"object","properties":{"changelog":{"type":"string","description":"Changelog"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"published_at":{"description":"Published timestamp","format":"date-time"},"status":{"type":"string","enum":["DRAFT","PUBLISHED"]},"title":{"type":"string","description":"Document version title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"version_number":{"type":"integer","description":"Version number"}},"required":["id","organization_id","document_id","title","owner_id","version_number","classification","content","changelog","status","created_at","updated_at"]}},"required":["document_version"]}`)
|
||||
GetDocumentVersionToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version":{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"changelog":{"type":"string","description":"Changelog"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"published_at":{"description":"Published timestamp","format":"date-time"},"status":{"type":"string","enum":["DRAFT","PUBLISHED"]},"title":{"type":"string","description":"Document version title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"version_number":{"type":"integer","description":"Version number"}},"required":["id","organization_id","document_id","title","approver_ids","version_number","classification","content","changelog","status","created_at","updated_at"]}},"required":["document_version"]}`)
|
||||
GetFrameworkToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
GetFrameworkToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"framework":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Framework description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Framework name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","created_at","updated_at"]}},"required":["framework"]}`)
|
||||
GetMeasureToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
|
||||
@@ -114,9 +114,9 @@ var (
|
||||
ListDocumentVersionSignaturesToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"document_version_id":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"active_contract":{"type":"boolean","description":"Signatory contract status"},"states":{"type":"array","items":{"type":"string","enum":["REQUESTED","SIGNED"]},"description":"Signature states"}}},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","SIGNED_AT"]}},"required":["field","direction"]},"size":{"type":"integer","description":"Page size"}},"required":["document_version_id"]}`)
|
||||
ListDocumentVersionSignaturesToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version_signatures":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_version_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"requested_at":{"type":"string","description":"Requested timestamp","format":"date-time"},"signed_at":{"description":"Signed timestamp","format":"date-time"},"signed_by":{"type":"string","format":"string"},"state":{"type":"string","enum":["REQUESTED","SIGNED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","document_version_id","state","signed_by","requested_at","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["document_version_signatures"]}`)
|
||||
ListDocumentVersionsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"document_id":{"type":"string","format":"string"},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","VERSION"]}},"required":["field","direction"]},"size":{"type":"integer","description":"Page size"}},"required":["document_id"]}`)
|
||||
ListDocumentVersionsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_versions":{"type":"array","items":{"type":"object","properties":{"changelog":{"type":"string","description":"Changelog"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"approver_id":{"type":"string","format":"string"},"published_at":{"description":"Published timestamp","format":"date-time"},"status":{"type":"string","enum":["DRAFT","PUBLISHED"]},"title":{"type":"string","description":"Document version title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"version_number":{"type":"integer","description":"Version number"}},"required":["id","organization_id","document_id","title","approver_id","version_number","classification","content","changelog","status","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["document_versions"]}`)
|
||||
ListDocumentVersionsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_versions":{"type":"array","items":{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"changelog":{"type":"string","description":"Changelog"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"published_at":{"description":"Published timestamp","format":"date-time"},"status":{"type":"string","enum":["DRAFT","PUBLISHED"]},"title":{"type":"string","description":"Document version title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"version_number":{"type":"integer","description":"Version number"}},"required":["id","organization_id","document_id","title","approver_ids","version_number","classification","content","changelog","status","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["document_versions"]}`)
|
||||
ListDocumentsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"query":{"type":"string","description":"Search query"},"trust_center_visibilities":{"type":"array","items":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"description":"Trust center visibilities"}}},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","TITLE","DOCUMENT_TYPE"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
|
||||
ListDocumentsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"documents":{"type":"array","items":{"type":"object","properties":{"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"current_published_version":{"description":"Current published version number"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"approver_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","approver_id","title","document_type","classification","trust_center_visibility","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["documents"]}`)
|
||||
ListDocumentsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"documents":{"type":"array","items":{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"current_published_version":{"description":"Current published version number"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","approver_ids","title","document_type","classification","trust_center_visibility","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["documents"]}`)
|
||||
ListFrameworksToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
|
||||
ListFrameworksToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"frameworks":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Framework description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Framework name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["frameworks"]}`)
|
||||
ListMeasuresToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"query":{"type":"string","description":"Search query"},"state":{"type":"string","enum":["NOT_STARTED","IN_PROGRESS","NOT_APPLICABLE","IMPLEMENTED"]}}},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","NAME"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
|
||||
@@ -142,7 +142,7 @@ var (
|
||||
ListVendorsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"snapshot_id":{"type":"string","format":"string"}}},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","UPDATED_AT","NAME"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
|
||||
ListVendorsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"next_cursor":{"type":"string","format":"string"},"vendors":{"type":"array","items":{"type":"object","properties":{"business_associate_agreement_url":{"description":"Business associate agreement URL"},"business_owner_id":{"description":"Business owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"category":{"type":"string","description":"Vendor category","enum":["ANALYTICS","CLOUD_MONITORING","CLOUD_PROVIDER","COLLABORATION","CUSTOMER_SUPPORT","DATA_STORAGE_AND_PROCESSING","DOCUMENT_MANAGEMENT","EMPLOYEE_MANAGEMENT","ENGINEERING","FINANCE","IDENTITY_PROVIDER","IT","MARKETING","OFFICE_OPERATIONS","OTHER","PASSWORD_MANAGEMENT","PRODUCT_AND_DESIGN","PROFESSIONAL_SERVICES","RECRUITING","SALES","SECURITY","VERSION_CONTROL"]},"certifications":{"type":"array","items":{"type":"string"},"description":"Certifications"},"countries":{"type":"array","items":{"type":"string"},"description":"Countries (ISO 3166-1 alpha-2 country codes)"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_processing_agreement_url":{"description":"Data processing agreement URL"},"description":{"description":"Vendor description"},"headquarter_address":{"description":"Headquarter address"},"id":{"type":"string","format":"string"},"legal_name":{"description":"Legal name"},"name":{"type":"string","description":"Vendor name"},"organization_id":{"type":"string","format":"string"},"privacy_policy_url":{"description":"Privacy policy URL"},"security_owner_id":{"description":"Security owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"security_page_url":{"description":"Security page URL"},"service_level_agreement_url":{"description":"Service level agreement URL"},"status_page_url":{"description":"Status page URL"},"subprocessors_list_url":{"description":"Subprocessors list URL"},"terms_of_service_url":{"description":"Terms of service URL"},"trust_page_url":{"description":"Trust page URL"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"website_url":{"description":"Website URL"}},"required":["id","name","organization_id","category","created_at","updated_at"]}}},"required":["vendors"]}`)
|
||||
PublishDocumentVersionToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"changelog":{"type":"string","description":"Changelog"},"document_id":{"type":"string","format":"string"}},"required":["document_id"]}`)
|
||||
PublishDocumentVersionToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document":{"type":"object","properties":{"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"current_published_version":{"description":"Current published version number"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","owner_id","title","document_type","classification","trust_center_visibility","created_at","updated_at"]},"document_version":{"type":"object","properties":{"changelog":{"type":"string","description":"Changelog"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"published_at":{"description":"Published timestamp","format":"date-time"},"status":{"type":"string","enum":["DRAFT","PUBLISHED"]},"title":{"type":"string","description":"Document version title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"version_number":{"type":"integer","description":"Version number"}},"required":["id","organization_id","document_id","title","owner_id","version_number","classification","content","changelog","status","created_at","updated_at"]}},"required":["document","document_version"]}`)
|
||||
PublishDocumentVersionToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document":{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"current_published_version":{"description":"Current published version number"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","approver_ids","title","document_type","classification","trust_center_visibility","created_at","updated_at"]},"document_version":{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"changelog":{"type":"string","description":"Changelog"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"published_at":{"description":"Published timestamp","format":"date-time"},"status":{"type":"string","enum":["DRAFT","PUBLISHED"]},"title":{"type":"string","description":"Document version title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"version_number":{"type":"integer","description":"Version number"}},"required":["id","organization_id","document_id","title","approver_ids","version_number","classification","content","changelog","status","created_at","updated_at"]}},"required":["document","document_version"]}`)
|
||||
RequestDocumentVersionSignatureToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version_id":{"type":"string","format":"string"},"signatory_id":{"type":"string","format":"string"}},"required":["document_version_id","signatory_id"]}`)
|
||||
RequestDocumentVersionSignatureToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version_signature":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_version_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"requested_at":{"type":"string","description":"Requested timestamp","format":"date-time"},"signed_at":{"description":"Signed timestamp","format":"date-time"},"signed_by":{"type":"string","format":"string"},"state":{"type":"string","enum":["REQUESTED","SIGNED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","document_version_id","state","signed_by","requested_at","created_at","updated_at"]}},"required":["document_version_signature"]}`)
|
||||
TakeSnapshotToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"type":"string","description":"Snapshot description"},"name":{"type":"string","description":"Snapshot name"},"organization_id":{"type":"string","format":"string"},"type":{"type":"string","enum":["RISKS","VENDORS","ASSETS","DATA","NONCONFORMITIES","OBLIGATIONS","CONTINUAL_IMPROVEMENTS","PROCESSING_ACTIVITIES","STATES_OF_APPLICABILITY"]}},"required":["organization_id","name","type"]}`)
|
||||
@@ -167,10 +167,10 @@ var (
|
||||
UpdateControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"exclusion_justification":{"description":"Exclusion justification"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"status":{"type":"string","enum":["INCLUDED","EXCLUDED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","status","created_at","updated_at"]}},"required":["control"]}`)
|
||||
UpdateDatumToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"owner_id":{"description":"Owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"vendor_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Vendor IDs"}},"required":["id"]}`)
|
||||
UpdateDatumToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"datum":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","data_classification","owner_id","created_at","updated_at"]}},"required":["datum"]}`)
|
||||
UpdateDocumentToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"approver_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]}},"required":["id"]}`)
|
||||
UpdateDocumentToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document":{"type":"object","properties":{"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"current_published_version":{"description":"Current published version number"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"approver_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","approver_id","title","document_type","classification","trust_center_visibility","created_at","updated_at"]}},"required":["document"]}`)
|
||||
UpdateDocumentToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]}},"required":["id"]}`)
|
||||
UpdateDocumentToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document":{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"current_published_version":{"description":"Current published version number"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","approver_ids","title","document_type","classification","trust_center_visibility","created_at","updated_at"]}},"required":["document"]}`)
|
||||
UpdateDocumentVersionToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"content":{"type":"string","description":"Document content"},"document_version_id":{"type":"string","format":"string"}},"required":["document_version_id","content"]}`)
|
||||
UpdateDocumentVersionToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version":{"type":"object","properties":{"changelog":{"type":"string","description":"Changelog"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"published_at":{"description":"Published timestamp","format":"date-time"},"status":{"type":"string","enum":["DRAFT","PUBLISHED"]},"title":{"type":"string","description":"Document version title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"version_number":{"type":"integer","description":"Version number"}},"required":["id","organization_id","document_id","title","owner_id","version_number","classification","content","changelog","status","created_at","updated_at"]}},"required":["document_version"]}`)
|
||||
UpdateDocumentVersionToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version":{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"changelog":{"type":"string","description":"Changelog"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"document_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"published_at":{"description":"Published timestamp","format":"date-time"},"status":{"type":"string","enum":["DRAFT","PUBLISHED"]},"title":{"type":"string","description":"Document version title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"version_number":{"type":"integer","description":"Version number"}},"required":["id","organization_id","document_id","title","approver_ids","version_number","classification","content","changelog","status","created_at","updated_at"]}},"required":["document_version"]}`)
|
||||
UpdateFrameworkToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"description":"Framework description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Framework name"}},"required":["id"]}`)
|
||||
UpdateFrameworkToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"framework":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Framework description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Framework name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","created_at","updated_at"]}},"required":["framework"]}`)
|
||||
UpdateMeasureToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"category":{"type":"string","description":"Measure category"},"description":{"description":"Measure description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Measure name"},"state":{"type":"string","enum":["NOT_STARTED","IN_PROGRESS","NOT_APPLICABLE","IMPLEMENTED"]}},"required":["id"]}`)
|
||||
@@ -604,6 +604,8 @@ type AddDatumOutput struct {
|
||||
|
||||
// AddDocumentInput represents the schema
|
||||
type AddDocumentInput struct {
|
||||
// Approver IDs
|
||||
ApproverIds []gid.GID `json:"approver_ids"`
|
||||
// Document classification
|
||||
Classification coredata.DocumentClassification `json:"classification"`
|
||||
// Document content
|
||||
@@ -612,8 +614,6 @@ type AddDocumentInput struct {
|
||||
DocumentType coredata.DocumentType `json:"document_type"`
|
||||
// Organization ID
|
||||
OrganizationID gid.GID `json:"organization_id"`
|
||||
// Approver ID
|
||||
ApproverID gid.GID `json:"approver_id"`
|
||||
// Document title
|
||||
Title string `json:"title"`
|
||||
// Trust center visibility
|
||||
@@ -1090,6 +1090,8 @@ type DeleteRiskOutput struct {
|
||||
|
||||
// Document represents the schema
|
||||
type Document struct {
|
||||
// Approver IDs
|
||||
ApproverIds []gid.GID `json:"approver_ids"`
|
||||
// Document classification
|
||||
Classification coredata.DocumentClassification `json:"classification"`
|
||||
// Creation timestamp
|
||||
@@ -1102,8 +1104,6 @@ type Document struct {
|
||||
ID gid.GID `json:"id"`
|
||||
// Organization ID
|
||||
OrganizationID gid.GID `json:"organization_id"`
|
||||
// Approver ID
|
||||
ApproverID gid.GID `json:"approver_id"`
|
||||
// Document title
|
||||
Title string `json:"title"`
|
||||
// Trust center visibility
|
||||
@@ -1122,6 +1122,8 @@ type DocumentOrderBy struct {
|
||||
|
||||
// DocumentVersion represents the schema
|
||||
type DocumentVersion struct {
|
||||
// Approver IDs
|
||||
ApproverIds []gid.GID `json:"approver_ids"`
|
||||
// Changelog
|
||||
Changelog string `json:"changelog"`
|
||||
// Document classification
|
||||
@@ -1136,8 +1138,6 @@ type DocumentVersion struct {
|
||||
ID gid.GID `json:"id"`
|
||||
// Organization ID
|
||||
OrganizationID gid.GID `json:"organization_id"`
|
||||
// Approver ID
|
||||
ApproverID gid.GID `json:"approver_id"`
|
||||
// Published timestamp
|
||||
PublishedAt *time.Time `json:"published_at,omitempty"`
|
||||
// Document status
|
||||
@@ -2342,14 +2342,14 @@ type UpdateDatumOutput struct {
|
||||
|
||||
// UpdateDocumentInput represents the schema
|
||||
type UpdateDocumentInput struct {
|
||||
// Approver IDs
|
||||
ApproverIds []gid.GID `json:"approver_ids,omitempty"`
|
||||
// Document classification
|
||||
Classification *coredata.DocumentClassification `json:"classification,omitempty"`
|
||||
// Document type
|
||||
DocumentType *coredata.DocumentType `json:"document_type,omitempty"`
|
||||
// Document ID
|
||||
ID gid.GID `json:"id"`
|
||||
// Approver ID
|
||||
ApproverID *gid.GID `json:"approver_id,omitempty"`
|
||||
// Document title
|
||||
Title *string `json:"title,omitempty"`
|
||||
// Trust center visibility
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
@@ -142,8 +143,8 @@ func (s *DocumentService) exportPDFData(
|
||||
) ([]byte, error) {
|
||||
document := &coredata.Document{}
|
||||
version := &coredata.DocumentVersion{}
|
||||
approver := &coredata.MembershipProfile{}
|
||||
organization := &coredata.Organization{}
|
||||
var approverNames []string
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
@@ -160,8 +161,19 @@ func (s *DocumentService) exportPDFData(
|
||||
return fmt.Errorf("cannot load latest published document version: %w", err)
|
||||
}
|
||||
|
||||
if err := approver.LoadByID(ctx, conn, s.svc.scope, document.ApproverID); err != nil {
|
||||
return fmt.Errorf("cannot load document approver profile: %w", err)
|
||||
// Load approvers
|
||||
docApprovers := &coredata.DocumentApprovers{}
|
||||
if err := docApprovers.LoadByDocumentID(ctx, conn, s.svc.scope, documentID); err != nil {
|
||||
return fmt.Errorf("cannot load document approvers: %w", err)
|
||||
}
|
||||
|
||||
profiles := coredata.MembershipProfiles{}
|
||||
if err := profiles.LoadByIDs(ctx, conn, s.svc.scope, docApprovers.ApproverProfileIDs()); err != nil {
|
||||
return fmt.Errorf("cannot load document approver profiles: %w", err)
|
||||
}
|
||||
|
||||
for _, p := range profiles {
|
||||
approverNames = append(approverNames, p.FullName)
|
||||
}
|
||||
|
||||
if err := organization.LoadByID(ctx, conn, s.svc.scope, document.OrganizationID); err != nil {
|
||||
@@ -203,7 +215,7 @@ func (s *DocumentService) exportPDFData(
|
||||
Content: version.Content,
|
||||
Version: version.VersionNumber,
|
||||
Classification: classification,
|
||||
Approver: approver.FullName,
|
||||
Approver: strings.Join(approverNames, ", "),
|
||||
PublishedAt: version.PublishedAt,
|
||||
CompanyHorizontalLogoBase64: horizontalLogoBase64,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user