Expire vendor risk assement
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
@@ -94,6 +94,13 @@ const vendorViewQuery = graphql`
|
||||
organization: node(id: $organizationId) {
|
||||
...PeopleSelector_organization
|
||||
}
|
||||
viewer {
|
||||
user {
|
||||
people(organizationId: $organizationId) {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -675,6 +682,13 @@ function RiskAssessmentsTable({
|
||||
});
|
||||
};
|
||||
|
||||
// Check if assessment is expired
|
||||
const isExpired = (expiresAt: string) => {
|
||||
console.log(new Date(expiresAt) < new Date());
|
||||
|
||||
return new Date(expiresAt) < new Date();
|
||||
};
|
||||
|
||||
// Get severity label based on data sensitivity and business impact
|
||||
const getSeverityLabel = (dataSensitivity: string, businessImpact: string) => {
|
||||
// Simple logic to determine severity - can be adjusted based on requirements
|
||||
@@ -731,35 +745,67 @@ function RiskAssessmentsTable({
|
||||
<tbody>
|
||||
{assessments.map((assessment) => {
|
||||
const severity = getSeverityLabel(assessment.dataSensitivity, assessment.businessImpact);
|
||||
const expired = isExpired(assessment.expiresAt);
|
||||
return (
|
||||
<tr key={assessment.id} className="border-b border-[rgba(2,42,2,0.08)]">
|
||||
<tr
|
||||
key={assessment.id}
|
||||
className={cn(
|
||||
"border-b border-[rgba(2,42,2,0.08)]",
|
||||
expired && "bg-[#F7F7F7] text-[#A0A5A0]"
|
||||
)}
|
||||
>
|
||||
<td className="px-4 py-3">
|
||||
<span className="text-sm font-normal text-[#141E12]">
|
||||
<span className={cn(
|
||||
"text-sm font-normal",
|
||||
expired ? "text-[#A0A5A0]" : "text-[#141E12]"
|
||||
)}>
|
||||
{formatDate(assessment.assessedAt)}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
<span className="text-sm font-normal text-[#141E12]">
|
||||
{formatDate(assessment.expiresAt)}
|
||||
</span>
|
||||
<div className="flex items-center">
|
||||
<span className={cn(
|
||||
"text-sm font-normal",
|
||||
expired ? "text-[#A0A5A0]" : "text-[#141E12]"
|
||||
)}>
|
||||
{formatDate(assessment.expiresAt)}
|
||||
</span>
|
||||
{expired && (
|
||||
<span className="ml-2 text-xs py-0.5 px-1.5 bg-[#F0F0F0] text-[#818780] rounded">
|
||||
Expired
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
<span className="text-sm font-normal text-[#141E12]">
|
||||
<span className={cn(
|
||||
"text-sm font-normal",
|
||||
expired ? "text-[#A0A5A0]" : "text-[#141E12]"
|
||||
)}>
|
||||
{assessment.dataSensitivity.charAt(0) + assessment.dataSensitivity.slice(1).toLowerCase()}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
<span className="text-sm font-normal text-[#141E12]">
|
||||
<span className={cn(
|
||||
"text-sm font-normal",
|
||||
expired ? "text-[#A0A5A0]" : "text-[#141E12]"
|
||||
)}>
|
||||
{assessment.businessImpact.charAt(0) + assessment.businessImpact.slice(1).toLowerCase()}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
<span className={`text-sm font-normal px-2 py-1 rounded-full ${severity.color}`}>
|
||||
<span className={cn(
|
||||
"text-sm font-normal px-2 py-1 rounded-full",
|
||||
expired ? "bg-[#F0F0F0] text-[#818780]" : severity.color
|
||||
)}>
|
||||
{severity.label}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
<span className="text-sm font-normal text-[#141E12]">
|
||||
<span className={cn(
|
||||
"text-sm font-normal",
|
||||
expired ? "text-[#A0A5A0]" : "text-[#141E12]"
|
||||
)}>
|
||||
{assessment.assessedBy?.fullName || 'N/A'}
|
||||
</span>
|
||||
</td>
|
||||
@@ -770,9 +816,9 @@ function RiskAssessmentsTable({
|
||||
onClick={() => setShowDropdown(showDropdown === assessment.id ? null : assessment.id)}
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 9.5C8.82843 9.5 9.5 8.82843 9.5 8C9.5 7.17157 8.82843 6.5 8 6.5C7.17157 6.5 6.5 7.17157 6.5 8C6.5 8.82843 7.17157 9.5 8 9.5Z" fill="#141E12"/>
|
||||
<path d="M3 9.5C3.82843 9.5 4.5 8.82843 4.5 8C4.5 7.17157 3.82843 6.5 3 6.5C2.17157 6.5 1.5 7.17157 1.5 8C1.5 8.82843 2.17157 9.5 3 9.5Z" fill="#141E12"/>
|
||||
<path d="M13 9.5C13.8284 9.5 14.5 8.82843 14.5 8C14.5 7.17157 13.8284 6.5 13 6.5C12.1716 6.5 11.5 7.17157 11.5 8C11.5 8.82843 12.1716 9.5 13 9.5Z" fill="#141E12"/>
|
||||
<path d="M8 9.5C8.82843 9.5 9.5 8.82843 9.5 8C9.5 7.17157 8.82843 6.5 8 6.5C7.17157 6.5 6.5 7.17157 6.5 8C6.5 8.82843 7.17157 9.5 8 9.5Z" fill={expired ? "#A0A5A0" : "#141E12"}/>
|
||||
<path d="M3 9.5C3.82843 9.5 4.5 8.82843 4.5 8C4.5 7.17157 3.82843 6.5 3 6.5C2.17157 6.5 1.5 7.17157 1.5 8C1.5 8.82843 2.17157 9.5 3 9.5Z" fill={expired ? "#A0A5A0" : "#141E12"}/>
|
||||
<path d="M13 9.5C13.8284 9.5 14.5 8.82843 14.5 8C14.5 7.17157 13.8284 6.5 13 6.5C12.1716 6.5 11.5 7.17157 11.5 8C11.5 8.82843 12.1716 9.5 13 9.5Z" fill={expired ? "#A0A5A0" : "#141E12"}/>
|
||||
</svg>
|
||||
</button>
|
||||
{showDropdown === assessment.id && (
|
||||
@@ -1270,27 +1316,9 @@ function VendorViewContent({
|
||||
businessImpact: BusinessImpact;
|
||||
notes: string;
|
||||
}) => {
|
||||
// Close the modal
|
||||
setShowRiskAssessmentModal(false);
|
||||
|
||||
// Current date for assessedAt, and 1 year later for expiresAt
|
||||
const today = new Date();
|
||||
const nextYear = new Date(today);
|
||||
const nextYear = new Date();
|
||||
nextYear.setFullYear(nextYear.getFullYear() + 1);
|
||||
|
||||
// Check if there's a business owner assigned
|
||||
const businessOwnerId = data.node.businessOwner?.id;
|
||||
if (!businessOwnerId) {
|
||||
// This check is now redundant as it's handled in the modal
|
||||
// but keeping it as a safeguard
|
||||
toast({
|
||||
title: "Error",
|
||||
description: "Please assign a Business Owner to the vendor before creating a risk assessment",
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
createRiskAssessment({
|
||||
variables: {
|
||||
connections: [
|
||||
@@ -1301,12 +1329,11 @@ function VendorViewContent({
|
||||
],
|
||||
input: {
|
||||
vendorId: data.node.id!,
|
||||
assessedBy: businessOwnerId,
|
||||
assessedBy: data.viewer.user.people?.id!,
|
||||
expiresAt: nextYear.toISOString(),
|
||||
dataSensitivity: formValues.dataSensitivity,
|
||||
businessImpact: formValues.businessImpact,
|
||||
notes: formValues.notes || "Risk assessment",
|
||||
attachments: []
|
||||
},
|
||||
},
|
||||
onCompleted: () => {
|
||||
@@ -1315,6 +1342,7 @@ function VendorViewContent({
|
||||
description: "Risk assessment created successfully",
|
||||
variant: "default",
|
||||
});
|
||||
setShowRiskAssessmentModal(false);
|
||||
loadQuery({
|
||||
vendorId: data.node.id!,
|
||||
organizationId: organizationId!,
|
||||
@@ -1328,7 +1356,7 @@ function VendorViewContent({
|
||||
});
|
||||
},
|
||||
});
|
||||
}, [createRiskAssessment, data.node.id, data.node.businessOwner?.id, loadQuery, toast, organizationId]);
|
||||
}, [createRiskAssessment, data.node.id, data.viewer.user.people?.id, loadQuery, toast, organizationId]);
|
||||
|
||||
const formatDate = (dateStr: string | null | undefined) => {
|
||||
if (!dateStr) return "N/A";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<8372d50934049d43afb678c894f40dbd>>
|
||||
* @generated SignedSource<<08de2d8758474132b472d63f413b59a5>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -13,7 +13,6 @@ export type BusinessImpact = "CRITICAL" | "HIGH" | "LOW" | "MEDIUM";
|
||||
export type DataSensitivity = "CRITICAL" | "HIGH" | "LOW" | "MEDIUM" | "NONE";
|
||||
export type CreateVendorRiskAssessmentInput = {
|
||||
assessedBy: string;
|
||||
attachments?: ReadonlyArray<string> | null | undefined;
|
||||
businessImpact: BusinessImpact;
|
||||
dataSensitivity: DataSensitivity;
|
||||
expiresAt: string;
|
||||
|
||||
101
apps/console/src/pages/organizations/vendors/__generated__/VendorViewQuery.graphql.ts
generated
vendored
101
apps/console/src/pages/organizations/vendors/__generated__/VendorViewQuery.graphql.ts
generated
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<bbfa9d7b4ab300f8ab96380582d2d9b7>>
|
||||
* @generated SignedSource<<c189e0079d6d90c845d93a6a108a0b76>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -78,6 +78,13 @@ export type VendorViewQuery$data = {
|
||||
readonly organization: {
|
||||
readonly " $fragmentSpreads": FragmentRefs<"PeopleSelector_organization">;
|
||||
};
|
||||
readonly viewer: {
|
||||
readonly user: {
|
||||
readonly people: {
|
||||
readonly id: string;
|
||||
} | null | undefined;
|
||||
};
|
||||
};
|
||||
};
|
||||
export type VendorViewQuery = {
|
||||
response: VendorViewQuery$data;
|
||||
@@ -444,15 +451,33 @@ v30 = [
|
||||
}
|
||||
],
|
||||
v31 = {
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "organizationId",
|
||||
"variableName": "organizationId"
|
||||
}
|
||||
],
|
||||
"concreteType": "People",
|
||||
"kind": "LinkedField",
|
||||
"name": "people",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
v32 = {
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
},
|
||||
v32 = [
|
||||
(v31/*: any*/)
|
||||
],
|
||||
v33 = [
|
||||
(v31/*: any*/),
|
||||
(v32/*: any*/)
|
||||
],
|
||||
v34 = [
|
||||
(v32/*: any*/),
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "orderBy",
|
||||
@@ -545,6 +570,29 @@ return {
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Viewer",
|
||||
"kind": "LinkedField",
|
||||
"name": "viewer",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "User",
|
||||
"kind": "LinkedField",
|
||||
"name": "user",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v31/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
@@ -593,7 +641,7 @@ return {
|
||||
(v24/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v32/*: any*/),
|
||||
"args": (v33/*: any*/),
|
||||
"concreteType": "VendorComplianceReportConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "complianceReports",
|
||||
@@ -603,7 +651,7 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v32/*: any*/),
|
||||
"args": (v33/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "VendorView_complianceReports",
|
||||
@@ -612,7 +660,7 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v32/*: any*/),
|
||||
"args": (v33/*: any*/),
|
||||
"concreteType": "VendorRiskAssessmentConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "riskAssessments",
|
||||
@@ -622,7 +670,7 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v32/*: any*/),
|
||||
"args": (v33/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "VendorView_riskAssessments",
|
||||
@@ -651,7 +699,7 @@ return {
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v33/*: any*/),
|
||||
"args": (v34/*: any*/),
|
||||
"concreteType": "PeopleConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "peoples",
|
||||
@@ -696,7 +744,7 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v33/*: any*/),
|
||||
"args": (v34/*: any*/),
|
||||
"filters": [
|
||||
"orderBy"
|
||||
],
|
||||
@@ -711,11 +759,36 @@ return {
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Viewer",
|
||||
"kind": "LinkedField",
|
||||
"name": "viewer",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "User",
|
||||
"kind": "LinkedField",
|
||||
"name": "user",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v31/*: any*/),
|
||||
(v3/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v3/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "5df12f781d305bd4bd6b6c0ccb4d947e",
|
||||
"cacheID": "9b2a625a96210e0168dceed7e4b98ed0",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
@@ -741,11 +814,11 @@ return {
|
||||
},
|
||||
"name": "VendorViewQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query VendorViewQuery(\n $vendorId: ID!\n $organizationId: ID!\n) {\n node(id: $vendorId) {\n __typename\n ... on Vendor {\n id\n name\n description\n serviceStartAt\n serviceTerminationAt\n statusPageUrl\n termsOfServiceUrl\n privacyPolicyUrl\n serviceLevelAgreementUrl\n dataProcessingAgreementUrl\n securityPageUrl\n trustPageUrl\n certifications\n headquarterAddress\n legalName\n websiteUrl\n businessOwner {\n id\n fullName\n }\n securityOwner {\n id\n fullName\n }\n createdAt\n updatedAt\n complianceReports(first: 100) {\n edges {\n node {\n id\n reportName\n reportDate\n validUntil\n fileUrl\n fileSize\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n riskAssessments(first: 100) {\n edges {\n node {\n id\n assessedAt\n expiresAt\n dataSensitivity\n businessImpact\n notes\n assessedBy {\n id\n fullName\n }\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n id\n }\n organization: node(id: $organizationId) {\n __typename\n ...PeopleSelector_organization\n id\n }\n}\n\nfragment PeopleSelector_organization on Organization {\n id\n peoples(first: 100, orderBy: {direction: ASC, field: FULL_NAME}) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n"
|
||||
"text": "query VendorViewQuery(\n $vendorId: ID!\n $organizationId: ID!\n) {\n node(id: $vendorId) {\n __typename\n ... on Vendor {\n id\n name\n description\n serviceStartAt\n serviceTerminationAt\n statusPageUrl\n termsOfServiceUrl\n privacyPolicyUrl\n serviceLevelAgreementUrl\n dataProcessingAgreementUrl\n securityPageUrl\n trustPageUrl\n certifications\n headquarterAddress\n legalName\n websiteUrl\n businessOwner {\n id\n fullName\n }\n securityOwner {\n id\n fullName\n }\n createdAt\n updatedAt\n complianceReports(first: 100) {\n edges {\n node {\n id\n reportName\n reportDate\n validUntil\n fileUrl\n fileSize\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n riskAssessments(first: 100) {\n edges {\n node {\n id\n assessedAt\n expiresAt\n dataSensitivity\n businessImpact\n notes\n assessedBy {\n id\n fullName\n }\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n id\n }\n organization: node(id: $organizationId) {\n __typename\n ...PeopleSelector_organization\n id\n }\n viewer {\n user {\n people(organizationId: $organizationId) {\n id\n }\n id\n }\n id\n }\n}\n\nfragment PeopleSelector_organization on Organization {\n id\n peoples(first: 100, orderBy: {direction: ASC, field: FULL_NAME}) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "2b856ea721d1bfb6b853fc281ee1aac6";
|
||||
(node as any).hash = "7f9a178bd20cefd76440ea8d71c3b2fa";
|
||||
|
||||
export default node;
|
||||
|
||||
2
pkg/coredata/migrations/20250422T033400Z.sql
Normal file
2
pkg/coredata/migrations/20250422T033400Z.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE vendor_risk_assessments ALTER COLUMN approved_at DROP NOT NULL;
|
||||
ALTER TABLE vendor_risk_assessments ALTER COLUMN approved_by DROP NOT NULL;
|
||||
3
pkg/coredata/migrations/20250422T152800Z.sql
Normal file
3
pkg/coredata/migrations/20250422T152800Z.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
ALTER TABLE vendor_risk_assessments DROP COLUMN accessed_at;
|
||||
ALTER TABLE vendor_risk_assessments DROP COLUMN accessed_by;
|
||||
@@ -98,6 +98,53 @@ LIMIT 1;
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *People) LoadByUserID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
userID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
kind,
|
||||
user_id,
|
||||
full_name,
|
||||
primary_email_address,
|
||||
additional_email_addresses,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
peoples
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND user_id = @user_id
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID, "user_id": userID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query people: %w", err)
|
||||
}
|
||||
|
||||
people, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[People])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect people: %w", err)
|
||||
}
|
||||
|
||||
*p = people
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p People) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
|
||||
@@ -350,3 +350,37 @@ WHERE %s
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
return err
|
||||
}
|
||||
|
||||
func (v Vendor) ExpireNonExpiredRiskAssessments(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
now := time.Now()
|
||||
|
||||
q := `
|
||||
UPDATE vendor_risk_assessments
|
||||
SET
|
||||
expires_at = @now,
|
||||
updated_at = @now
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = @vendor_id
|
||||
AND expires_at > @now
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"vendor_id": v.ID,
|
||||
"now": now,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot expire existing risk assessments: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -33,9 +33,8 @@ type (
|
||||
VendorID gid.GID `db:"vendor_id"`
|
||||
AssessedAt time.Time `db:"assessed_at"`
|
||||
AssessedBy gid.GID `db:"assessed_by"`
|
||||
AccessedAt time.Time `db:"accessed_at"`
|
||||
ApprovedBy gid.GID `db:"approved_by"`
|
||||
ApprovedAt time.Time `db:"approved_at"`
|
||||
ApprovedBy *gid.GID `db:"approved_by"`
|
||||
ApprovedAt *time.Time `db:"approved_at"`
|
||||
ExpiresAt time.Time `db:"expires_at"`
|
||||
DataSensitivity DataSensitivity `db:"data_sensitivity"`
|
||||
BusinessImpact BusinessImpact `db:"business_impact"`
|
||||
@@ -96,7 +95,6 @@ INSERT INTO
|
||||
vendor_id,
|
||||
assessed_at,
|
||||
assessed_by,
|
||||
accessed_at,
|
||||
approved_by,
|
||||
approved_at,
|
||||
expires_at,
|
||||
@@ -112,11 +110,12 @@ VALUES (
|
||||
@vendor_id,
|
||||
@assessed_at,
|
||||
@assessed_by,
|
||||
@approved_by,
|
||||
@approved_at,
|
||||
@expires_at,
|
||||
@data_sensitivity,
|
||||
@business_impact,
|
||||
@notes,
|
||||
@attachments,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
@@ -128,7 +127,6 @@ VALUES (
|
||||
"vendor_id": r.VendorID,
|
||||
"assessed_at": r.AssessedAt,
|
||||
"assessed_by": r.AssessedBy,
|
||||
"accessed_at": r.AccessedAt,
|
||||
"approved_by": r.ApprovedBy,
|
||||
"approved_at": r.ApprovedAt,
|
||||
"expires_at": r.ExpiresAt,
|
||||
@@ -155,7 +153,6 @@ SELECT
|
||||
vendor_id,
|
||||
assessed_at,
|
||||
assessed_by,
|
||||
accessed_at,
|
||||
approved_by,
|
||||
approved_at,
|
||||
expires_at,
|
||||
@@ -206,7 +203,6 @@ SELECT
|
||||
vendor_id,
|
||||
assessed_at,
|
||||
assessed_by,
|
||||
accessed_at,
|
||||
approved_by,
|
||||
approved_at,
|
||||
expires_at,
|
||||
@@ -260,7 +256,6 @@ SELECT
|
||||
vendor_id,
|
||||
assessed_at,
|
||||
assessed_by,
|
||||
accessed_at,
|
||||
approved_by,
|
||||
approved_at,
|
||||
expires_at,
|
||||
|
||||
@@ -69,6 +69,27 @@ func (s PeopleService) Get(
|
||||
return people, nil
|
||||
}
|
||||
|
||||
func (s PeopleService) GetByUserID(
|
||||
ctx context.Context,
|
||||
organizationID gid.GID,
|
||||
userID gid.GID,
|
||||
) (*coredata.People, error) {
|
||||
people := &coredata.People{}
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
return people.LoadByUserID(ctx, conn, s.svc.scope, organizationID, userID)
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return people, nil
|
||||
}
|
||||
|
||||
func (s PeopleService) ListForOrganizationID(
|
||||
ctx context.Context,
|
||||
organizationID gid.GID,
|
||||
|
||||
@@ -359,6 +359,7 @@ func (s VendorService) CreateRiskAssessment(
|
||||
ID: vendorRiskAssessmentID,
|
||||
VendorID: req.VendorID,
|
||||
AssessedBy: req.AssessedByID,
|
||||
AssessedAt: now,
|
||||
ExpiresAt: req.ExpiresAt,
|
||||
DataSensitivity: req.DataSensitivity,
|
||||
BusinessImpact: req.BusinessImpact,
|
||||
@@ -369,11 +370,15 @@ func (s VendorService) CreateRiskAssessment(
|
||||
|
||||
err = s.svc.pg.WithTx(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
if err := vendorRiskAssessment.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert vendor risk assessment: %w", err)
|
||||
func(tx pg.Conn) error {
|
||||
vendor := coredata.Vendor{ID: req.VendorID}
|
||||
if err := vendor.ExpireNonExpiredRiskAssessments(ctx, tx, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot expire vendor risk assessments: %w", err)
|
||||
}
|
||||
|
||||
if err := vendorRiskAssessment.Insert(ctx, tx, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert vendor risk assessment: %w", err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
@@ -384,3 +389,23 @@ func (s VendorService) CreateRiskAssessment(
|
||||
|
||||
return vendorRiskAssessment, nil
|
||||
}
|
||||
|
||||
func (s VendorService) GetRiskAssessment(
|
||||
ctx context.Context,
|
||||
vendorRiskAssessmentID gid.GID,
|
||||
) (*coredata.VendorRiskAssessment, error) {
|
||||
vendorRiskAssessment := &coredata.VendorRiskAssessment{}
|
||||
|
||||
err := s.svc.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
return vendorRiskAssessment.LoadByID(ctx, conn, s.svc.scope, vendorRiskAssessmentID)
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return vendorRiskAssessment, nil
|
||||
}
|
||||
|
||||
@@ -455,6 +455,8 @@ type User implements Node {
|
||||
email: String!
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
|
||||
people(organizationId: ID!): People @goField(forceResolver: true)
|
||||
}
|
||||
|
||||
type Connector implements Node {
|
||||
@@ -1463,7 +1465,6 @@ type VendorRiskAssessment implements Node {
|
||||
dataSensitivity: DataSensitivity!
|
||||
businessImpact: BusinessImpact!
|
||||
notes: String
|
||||
attachments: [String!]!
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
}
|
||||
@@ -1487,7 +1488,6 @@ input CreateVendorRiskAssessmentInput {
|
||||
dataSensitivity: DataSensitivity!
|
||||
businessImpact: BusinessImpact!
|
||||
notes: String
|
||||
attachments: [String!]
|
||||
}
|
||||
|
||||
type CreateVendorRiskAssessmentPayload {
|
||||
|
||||
@@ -52,6 +52,7 @@ type ResolverRoot interface {
|
||||
Query() QueryResolver
|
||||
Risk() RiskResolver
|
||||
Task() TaskResolver
|
||||
User() UserResolver
|
||||
Vendor() VendorResolver
|
||||
VendorComplianceReport() VendorComplianceReportResolver
|
||||
VendorRiskAssessment() VendorRiskAssessmentResolver
|
||||
@@ -538,6 +539,7 @@ type ComplexityRoot struct {
|
||||
Email func(childComplexity int) int
|
||||
FullName func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
People func(childComplexity int, organizationID gid.GID) int
|
||||
UpdatedAt func(childComplexity int) int
|
||||
}
|
||||
|
||||
@@ -611,7 +613,6 @@ type ComplexityRoot struct {
|
||||
VendorRiskAssessment struct {
|
||||
AssessedAt func(childComplexity int) int
|
||||
AssessedBy func(childComplexity int) int
|
||||
Attachments func(childComplexity int) int
|
||||
BusinessImpact func(childComplexity int) int
|
||||
CreatedAt func(childComplexity int) int
|
||||
DataSensitivity func(childComplexity int) int
|
||||
@@ -730,6 +731,9 @@ type TaskResolver interface {
|
||||
AssignedTo(ctx context.Context, obj *types.Task) (*types.People, error)
|
||||
Evidences(ctx context.Context, obj *types.Task, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.EvidenceOrderBy) (*types.EvidenceConnection, error)
|
||||
}
|
||||
type UserResolver interface {
|
||||
People(ctx context.Context, obj *types.User, organizationID gid.GID) (*types.People, error)
|
||||
}
|
||||
type VendorResolver interface {
|
||||
ComplianceReports(ctx context.Context, obj *types.Vendor, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorComplianceReportOrderBy) (*types.VendorComplianceReportConnection, error)
|
||||
RiskAssessments(ctx context.Context, obj *types.Vendor, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorRiskAssessmentOrder) (*types.VendorRiskAssessmentConnection, error)
|
||||
@@ -2760,6 +2764,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.User.ID(childComplexity), true
|
||||
|
||||
case "User.people":
|
||||
if e.complexity.User.People == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_User_people_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.User.People(childComplexity, args["organizationId"].(gid.GID)), true
|
||||
|
||||
case "User.updatedAt":
|
||||
if e.complexity.User.UpdatedAt == nil {
|
||||
break
|
||||
@@ -3092,13 +3108,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.VendorRiskAssessment.AssessedBy(childComplexity), true
|
||||
|
||||
case "VendorRiskAssessment.attachments":
|
||||
if e.complexity.VendorRiskAssessment.Attachments == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.VendorRiskAssessment.Attachments(childComplexity), true
|
||||
|
||||
case "VendorRiskAssessment.businessImpact":
|
||||
if e.complexity.VendorRiskAssessment.BusinessImpact == nil {
|
||||
break
|
||||
@@ -3830,6 +3839,8 @@ type User implements Node {
|
||||
email: String!
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
|
||||
people(organizationId: ID!): People @goField(forceResolver: true)
|
||||
}
|
||||
|
||||
type Connector implements Node {
|
||||
@@ -4838,7 +4849,6 @@ type VendorRiskAssessment implements Node {
|
||||
dataSensitivity: DataSensitivity!
|
||||
businessImpact: BusinessImpact!
|
||||
notes: String
|
||||
attachments: [String!]!
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
}
|
||||
@@ -4862,7 +4872,6 @@ input CreateVendorRiskAssessmentInput {
|
||||
dataSensitivity: DataSensitivity!
|
||||
businessImpact: BusinessImpact!
|
||||
notes: String
|
||||
attachments: [String!]
|
||||
}
|
||||
|
||||
type CreateVendorRiskAssessmentPayload {
|
||||
@@ -7762,6 +7771,29 @@ func (ec *executionContext) field_Task_evidences_argsOrderBy(
|
||||
return zeroVal, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_User_people_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
arg0, err := ec.field_User_people_argsOrganizationID(ctx, rawArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["organizationId"] = arg0
|
||||
return args, nil
|
||||
}
|
||||
func (ec *executionContext) field_User_people_argsOrganizationID(
|
||||
ctx context.Context,
|
||||
rawArgs map[string]any,
|
||||
) (gid.GID, error) {
|
||||
ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationId"))
|
||||
if tmp, ok := rawArgs["organizationId"]; ok {
|
||||
return ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, tmp)
|
||||
}
|
||||
|
||||
var zeroVal gid.GID
|
||||
return zeroVal, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Vendor_complianceReports_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
@@ -20538,6 +20570,74 @@ func (ec *executionContext) fieldContext_User_updatedAt(_ context.Context, field
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _User_people(ctx context.Context, field graphql.CollectedField, obj *types.User) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_User_people(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.User().People(rctx, obj, fc.Args["organizationId"].(gid.GID))
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*types.People)
|
||||
fc.Result = res
|
||||
return ec.marshalOPeople2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐPeople(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_User_people(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "User",
|
||||
Field: field,
|
||||
IsMethod: true,
|
||||
IsResolver: true,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
switch field.Name {
|
||||
case "id":
|
||||
return ec.fieldContext_People_id(ctx, field)
|
||||
case "fullName":
|
||||
return ec.fieldContext_People_fullName(ctx, field)
|
||||
case "primaryEmailAddress":
|
||||
return ec.fieldContext_People_primaryEmailAddress(ctx, field)
|
||||
case "additionalEmailAddresses":
|
||||
return ec.fieldContext_People_additionalEmailAddresses(ctx, field)
|
||||
case "kind":
|
||||
return ec.fieldContext_People_kind(ctx, field)
|
||||
case "createdAt":
|
||||
return ec.fieldContext_People_createdAt(ctx, field)
|
||||
case "updatedAt":
|
||||
return ec.fieldContext_People_updatedAt(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type People", 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_User_people_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return fc, err
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _UserConnection_edges(ctx context.Context, field graphql.CollectedField, obj *types.UserConnection) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_UserConnection_edges(ctx, field)
|
||||
if err != nil {
|
||||
@@ -20735,6 +20835,8 @@ func (ec *executionContext) fieldContext_UserEdge_node(_ context.Context, field
|
||||
return ec.fieldContext_User_createdAt(ctx, field)
|
||||
case "updatedAt":
|
||||
return ec.fieldContext_User_updatedAt(ctx, field)
|
||||
case "people":
|
||||
return ec.fieldContext_User_people(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||
},
|
||||
@@ -23034,50 +23136,6 @@ func (ec *executionContext) fieldContext_VendorRiskAssessment_notes(_ context.Co
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _VendorRiskAssessment_attachments(ctx context.Context, field graphql.CollectedField, obj *types.VendorRiskAssessment) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_VendorRiskAssessment_attachments(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Attachments, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.([]string)
|
||||
fc.Result = res
|
||||
return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_VendorRiskAssessment_attachments(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "VendorRiskAssessment",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _VendorRiskAssessment_createdAt(ctx context.Context, field graphql.CollectedField, obj *types.VendorRiskAssessment) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_VendorRiskAssessment_createdAt(ctx, field)
|
||||
if err != nil {
|
||||
@@ -23369,8 +23427,6 @@ func (ec *executionContext) fieldContext_VendorRiskAssessmentEdge_node(_ context
|
||||
return ec.fieldContext_VendorRiskAssessment_businessImpact(ctx, field)
|
||||
case "notes":
|
||||
return ec.fieldContext_VendorRiskAssessment_notes(ctx, field)
|
||||
case "attachments":
|
||||
return ec.fieldContext_VendorRiskAssessment_attachments(ctx, field)
|
||||
case "createdAt":
|
||||
return ec.fieldContext_VendorRiskAssessment_createdAt(ctx, field)
|
||||
case "updatedAt":
|
||||
@@ -23475,6 +23531,8 @@ func (ec *executionContext) fieldContext_Viewer_user(_ context.Context, field gr
|
||||
return ec.fieldContext_User_createdAt(ctx, field)
|
||||
case "updatedAt":
|
||||
return ec.fieldContext_User_updatedAt(ctx, field)
|
||||
case "people":
|
||||
return ec.fieldContext_User_people(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type User", field.Name)
|
||||
},
|
||||
@@ -26366,7 +26424,7 @@ func (ec *executionContext) unmarshalInputCreateVendorRiskAssessmentInput(ctx co
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"vendorId", "assessedBy", "expiresAt", "dataSensitivity", "businessImpact", "notes", "attachments"}
|
||||
fieldsInOrder := [...]string{"vendorId", "assessedBy", "expiresAt", "dataSensitivity", "businessImpact", "notes"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -26415,13 +26473,6 @@ func (ec *executionContext) unmarshalInputCreateVendorRiskAssessmentInput(ctx co
|
||||
return it, err
|
||||
}
|
||||
it.Notes = data
|
||||
case "attachments":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("attachments"))
|
||||
data, err := ec.unmarshalOString2ᚕstringᚄ(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.Attachments = data
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32945,28 +32996,61 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj
|
||||
case "id":
|
||||
out.Values[i] = ec._User_id(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "fullName":
|
||||
out.Values[i] = ec._User_fullName(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "email":
|
||||
out.Values[i] = ec._User_email(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "createdAt":
|
||||
out.Values[i] = ec._User_createdAt(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "updatedAt":
|
||||
out.Values[i] = ec._User_updatedAt(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "people":
|
||||
field := field
|
||||
|
||||
innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._User_people(ctx, field, obj)
|
||||
return res
|
||||
}
|
||||
|
||||
if field.Deferrable != nil {
|
||||
dfs, ok := deferred[field.Deferrable.Label]
|
||||
di := 0
|
||||
if ok {
|
||||
dfs.AddField(field)
|
||||
di = len(dfs.Values) - 1
|
||||
} else {
|
||||
dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
|
||||
deferred[field.Deferrable.Label] = dfs
|
||||
}
|
||||
dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
|
||||
return innerFunc(ctx, dfs)
|
||||
})
|
||||
|
||||
// don't run the out.Concurrently() call below
|
||||
out.Values[i] = graphql.Null
|
||||
continue
|
||||
}
|
||||
|
||||
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
@@ -33728,11 +33812,6 @@ func (ec *executionContext) _VendorRiskAssessment(ctx context.Context, sel ast.S
|
||||
}
|
||||
case "notes":
|
||||
out.Values[i] = ec._VendorRiskAssessment_notes(ctx, field, obj)
|
||||
case "attachments":
|
||||
out.Values[i] = ec._VendorRiskAssessment_attachments(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "createdAt":
|
||||
out.Values[i] = ec._VendorRiskAssessment_createdAt(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
|
||||
@@ -252,7 +252,6 @@ type CreateVendorRiskAssessmentInput struct {
|
||||
DataSensitivity coredata.DataSensitivity `json:"dataSensitivity"`
|
||||
BusinessImpact coredata.BusinessImpact `json:"businessImpact"`
|
||||
Notes *string `json:"notes,omitempty"`
|
||||
Attachments []string `json:"attachments,omitempty"`
|
||||
}
|
||||
|
||||
type CreateVendorRiskAssessmentPayload struct {
|
||||
@@ -799,6 +798,7 @@ type User struct {
|
||||
Email string `json:"email"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
People *People `json:"people,omitempty"`
|
||||
}
|
||||
|
||||
func (User) IsNode() {}
|
||||
@@ -886,7 +886,6 @@ type VendorRiskAssessment struct {
|
||||
DataSensitivity coredata.DataSensitivity `json:"dataSensitivity"`
|
||||
BusinessImpact coredata.BusinessImpact `json:"businessImpact"`
|
||||
Notes *string `json:"notes,omitempty"`
|
||||
Attachments []string `json:"attachments"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
@@ -1049,16 +1049,19 @@ func (r *mutationResolver) DeletePolicy(ctx context.Context, input types.DeleteP
|
||||
// CreateVendorRiskAssessment is the resolver for the createVendorRiskAssessment field.
|
||||
func (r *mutationResolver) CreateVendorRiskAssessment(ctx context.Context, input types.CreateVendorRiskAssessmentInput) (*types.CreateVendorRiskAssessmentPayload, error) {
|
||||
svc := GetTenantService(ctx, r.proboSvc, input.VendorID.TenantID())
|
||||
user := UserFromContext(ctx)
|
||||
|
||||
expiresAt := time.Now().Add(time.Hour * 24 * 365)
|
||||
fmt.Println("input.AssessedBy", input.AssessedBy)
|
||||
fmt.Println("input.ExpiresAt", input.ExpiresAt)
|
||||
fmt.Println("input.DataSensitivity", input.DataSensitivity)
|
||||
fmt.Println("input.BusinessImpact", input.BusinessImpact)
|
||||
fmt.Println("input.Notes", input.Notes)
|
||||
|
||||
vendorRiskAssessment, err := svc.Vendors.CreateRiskAssessment(
|
||||
ctx,
|
||||
probo.CreateVendorRiskAssessmentRequest{
|
||||
VendorID: input.VendorID,
|
||||
AssessedByID: user.ID,
|
||||
ExpiresAt: expiresAt,
|
||||
AssessedByID: input.AssessedBy,
|
||||
ExpiresAt: input.ExpiresAt,
|
||||
DataSensitivity: input.DataSensitivity,
|
||||
BusinessImpact: input.BusinessImpact,
|
||||
Notes: input.Notes,
|
||||
@@ -1558,6 +1561,18 @@ func (r *taskResolver) Evidences(ctx context.Context, obj *types.Task, first *in
|
||||
return types.NewEvidenceConnection(page), nil
|
||||
}
|
||||
|
||||
// People is the resolver for the people field.
|
||||
func (r *userResolver) People(ctx context.Context, obj *types.User, organizationID gid.GID) (*types.People, error) {
|
||||
svc := GetTenantService(ctx, r.proboSvc, organizationID.TenantID())
|
||||
|
||||
people, err := svc.Peoples.GetByUserID(ctx, organizationID, obj.ID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to get people: %w", err))
|
||||
}
|
||||
|
||||
return types.NewPeople(people), nil
|
||||
}
|
||||
|
||||
// ComplianceReports is the resolver for the complianceReports field.
|
||||
func (r *vendorResolver) ComplianceReports(ctx context.Context, obj *types.Vendor, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorComplianceReportOrderBy) (*types.VendorComplianceReportConnection, error) {
|
||||
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
|
||||
@@ -1676,12 +1691,31 @@ func (r *vendorComplianceReportResolver) FileURL(ctx context.Context, obj *types
|
||||
|
||||
// Vendor is the resolver for the vendor field.
|
||||
func (r *vendorRiskAssessmentResolver) Vendor(ctx context.Context, obj *types.VendorRiskAssessment) (*types.Vendor, error) {
|
||||
panic(fmt.Errorf("not implemented: Vendor - vendor"))
|
||||
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
|
||||
|
||||
vendor, err := svc.Vendors.Get(ctx, obj.ID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to get vendor: %w", err))
|
||||
}
|
||||
|
||||
return types.NewVendor(vendor), nil
|
||||
}
|
||||
|
||||
// AssessedBy is the resolver for the assessedBy field.
|
||||
func (r *vendorRiskAssessmentResolver) AssessedBy(ctx context.Context, obj *types.VendorRiskAssessment) (*types.People, error) {
|
||||
panic(fmt.Errorf("not implemented: AssessedBy - assessedBy"))
|
||||
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
|
||||
|
||||
vendorRiskAssessment, err := svc.Vendors.GetRiskAssessment(ctx, obj.ID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to get vendor risk assessment: %w", err))
|
||||
}
|
||||
|
||||
people, err := svc.Peoples.Get(ctx, vendorRiskAssessment.AssessedBy)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to get assessed by: %w", err))
|
||||
}
|
||||
|
||||
return types.NewPeople(people), nil
|
||||
}
|
||||
|
||||
// Organizations is the resolver for the organizations field.
|
||||
@@ -1739,6 +1773,9 @@ func (r *Resolver) Risk() schema.RiskResolver { return &riskResolver{r} }
|
||||
// Task returns schema.TaskResolver implementation.
|
||||
func (r *Resolver) Task() schema.TaskResolver { return &taskResolver{r} }
|
||||
|
||||
// User returns schema.UserResolver implementation.
|
||||
func (r *Resolver) User() schema.UserResolver { return &userResolver{r} }
|
||||
|
||||
// Vendor returns schema.VendorResolver implementation.
|
||||
func (r *Resolver) Vendor() schema.VendorResolver { return &vendorResolver{r} }
|
||||
|
||||
@@ -1765,6 +1802,7 @@ type policyResolver struct{ *Resolver }
|
||||
type queryResolver struct{ *Resolver }
|
||||
type riskResolver struct{ *Resolver }
|
||||
type taskResolver struct{ *Resolver }
|
||||
type userResolver struct{ *Resolver }
|
||||
type vendorResolver struct{ *Resolver }
|
||||
type vendorComplianceReportResolver struct{ *Resolver }
|
||||
type vendorRiskAssessmentResolver struct{ *Resolver }
|
||||
|
||||
Reference in New Issue
Block a user