Add mutations and inputs to manage brand logos

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-01-29 18:16:41 +04:00
parent 8b5b9e732f
commit 96391b4822
8 changed files with 935 additions and 47 deletions

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<be7955648260f44b4b42a2b342db2b05>>
* @generated SignedSource<<6ae7a5c203ff61690408ec2753fe2f11>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -14,10 +14,17 @@ export type CompliancePageBrandPageQuery$variables = {
};
export type CompliancePageBrandPageQuery$data = {
readonly organization: {
readonly compliancePage?: {
readonly __typename: "Organization";
readonly compliancePage: {
readonly canUpdate: boolean;
readonly darkLogoFileUrl: string | null | undefined;
readonly id: string;
readonly logoFileUrl: string | null | undefined;
} | null | undefined;
};
} | {
// This will never be '%other', but we need some
// value in case none of the concrete values match.
readonly __typename: "%other";
};
};
export type CompliancePageBrandPageQuery = {
@@ -44,21 +51,53 @@ v2 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "logoFileUrl",
"name": "__typename",
"storageKey": null
},
v3 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "darkLogoFileUrl",
"name": "id",
"storageKey": null
},
v4 = {
"alias": null,
"alias": "compliancePage",
"args": null,
"kind": "ScalarField",
"name": "id",
"concreteType": "TrustCenter",
"kind": "LinkedField",
"name": "trustCenter",
"plural": false,
"selections": [
(v3/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "logoFileUrl",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "darkLogoFileUrl",
"storageKey": null
},
{
"alias": "canUpdate",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:trust-center:update"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:trust-center:update\")"
}
],
"storageKey": null
};
return {
@@ -76,21 +115,14 @@ return {
"name": "node",
"plural": false,
"selections": [
(v2/*: any*/),
{
"kind": "InlineFragment",
"selections": [
{
"alias": "compliancePage",
"args": null,
"concreteType": "TrustCenter",
"kind": "LinkedField",
"name": "trustCenter",
"plural": false,
"selections": [
(v2/*: any*/),
(v3/*: any*/)
],
"storageKey": null
"kind": "RequiredField",
"field": (v4/*: any*/),
"action": "THROW"
}
],
"type": "Organization",
@@ -117,51 +149,32 @@ return {
"name": "node",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
},
(v2/*: any*/),
{
"kind": "InlineFragment",
"selections": [
{
"alias": "compliancePage",
"args": null,
"concreteType": "TrustCenter",
"kind": "LinkedField",
"name": "trustCenter",
"plural": false,
"selections": [
(v2/*: any*/),
(v3/*: any*/),
(v4/*: any*/)
],
"storageKey": null
}
(v4/*: any*/)
],
"type": "Organization",
"abstractKey": null
},
(v4/*: any*/)
(v3/*: any*/)
],
"storageKey": null
}
]
},
"params": {
"cacheID": "17e4be042ed0e09a4b299d38f33dff32",
"cacheID": "a0e24c6bb927ff34274492952df0346b",
"id": null,
"metadata": {},
"name": "CompliancePageBrandPageQuery",
"operationKind": "query",
"text": "query CompliancePageBrandPageQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n compliancePage: trustCenter {\n logoFileUrl\n darkLogoFileUrl\n id\n }\n }\n id\n }\n}\n"
"text": "query CompliancePageBrandPageQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n compliancePage: trustCenter {\n id\n logoFileUrl\n darkLogoFileUrl\n canUpdate: permission(action: \"core:trust-center:update\")\n }\n }\n id\n }\n}\n"
}
};
})();
(node as any).hash = "3364d36a8dd77d39d00d50f451a027a7";
(node as any).hash = "3d2d6ef82bb9cf232aad738c906b8a54";
export default node;

View File

@@ -0,0 +1,123 @@
/**
* @generated SignedSource<<b0dc20be7382cf67a0906b4f06e713e0>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type UpdateTrustCenterBrandInput = {
darkLogoFile?: any | null | undefined;
logoFile?: any | null | undefined;
trustCenterId: string;
};
export type CompliancePageBrandPage_updateMutation$variables = {
input: UpdateTrustCenterBrandInput;
};
export type CompliancePageBrandPage_updateMutation$data = {
readonly updateTrustCenterBrand: {
readonly trustCenter: {
readonly darkLogoFileUrl: string | null | undefined;
readonly id: string;
readonly logoFileUrl: string | null | undefined;
};
};
};
export type CompliancePageBrandPage_updateMutation = {
response: CompliancePageBrandPage_updateMutation$data;
variables: CompliancePageBrandPage_updateMutation$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "input"
}
],
v1 = [
{
"alias": null,
"args": [
{
"kind": "Variable",
"name": "input",
"variableName": "input"
}
],
"concreteType": "UpdateTrustCenterBrandPayload",
"kind": "LinkedField",
"name": "updateTrustCenterBrand",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "TrustCenter",
"kind": "LinkedField",
"name": "trustCenter",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "logoFileUrl",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "darkLogoFileUrl",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "CompliancePageBrandPage_updateMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "CompliancePageBrandPage_updateMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "fb398aa8a46a93ca7b68e4ef9841a4d6",
"id": null,
"metadata": {},
"name": "CompliancePageBrandPage_updateMutation",
"operationKind": "mutation",
"text": "mutation CompliancePageBrandPage_updateMutation(\n $input: UpdateTrustCenterBrandInput!\n) {\n updateTrustCenterBrand(input: $input) {\n trustCenter {\n id\n logoFileUrl\n darkLogoFileUrl\n }\n }\n}\n"
}
};
})();
(node as any).hash = "cb158c24dbd3824e6fa9cc3e4632dc81";
export default node;

View File

@@ -1,25 +1,312 @@
import { useTranslate } from "@probo/i18n";
import {
Button,
Card,
Dropzone,
FileButton,
IconTrashCan,
Label,
Spinner,
} from "@probo/ui";
import { type ChangeEventHandler, useState } from "react";
import { type PreloadedQuery, usePreloadedQuery } from "react-relay";
import { graphql } from "relay-runtime";
import type { CompliancePageBrandPage_updateMutation } from "#/__generated__/core/CompliancePageBrandPage_updateMutation.graphql";
import type { CompliancePageBrandPageQuery } from "#/__generated__/core/CompliancePageBrandPageQuery.graphql";
import { useMutationWithToasts } from "#/hooks/useMutationWithToasts";
export const compliancePageBrandPageQuery = graphql`
query CompliancePageBrandPageQuery($organizationId: ID!) {
organization: node(id: $organizationId) {
__typename
... on Organization {
compliancePage: trustCenter {
compliancePage: trustCenter @required(action: THROW) {
id
logoFileUrl
darkLogoFileUrl
canUpdate: permission(action: "core:trust-center:update")
}
}
}
}
`;
const updateTrustCenterBrandMutation = graphql`
mutation CompliancePageBrandPage_updateMutation($input: UpdateTrustCenterBrandInput!) {
updateTrustCenterBrand(input: $input) {
trustCenter {
id
logoFileUrl
darkLogoFileUrl
}
}
}
`;
export function CompliancePageBrandPage(props: { queryRef: PreloadedQuery<CompliancePageBrandPageQuery> }) {
const { queryRef } = props;
const { __ } = useTranslate();
const { organization } = usePreloadedQuery<CompliancePageBrandPageQuery>(compliancePageBrandPageQuery, queryRef);
if (organization.__typename !== "Organization") {
throw new Error("invalid type for node");
}
return <pre>{JSON.stringify(organization, null, 2)}</pre>;
const trustCenterId = organization.compliancePage.id;
const logoFileUrl = organization.compliancePage.logoFileUrl;
const darkLogoFileUrl = organization.compliancePage.darkLogoFileUrl;
const [logoPreview, setLogoPreview] = useState<string | null>(null);
const [darkLogoPreview, setDarkLogoPreview] = useState<string | null>(null);
const [updateBrand, isUpdating] = useMutationWithToasts<CompliancePageBrandPage_updateMutation>(
updateTrustCenterBrandMutation,
{
successMessage: __("Compliance page branding updated successfully"),
errorMessage: __("Failed to update compliance page branding"),
},
);
const disabled = isUpdating || !organization.compliancePage.canUpdate;
const processLogoFile = (file: File, setPreview: (url: string) => void) => {
const reader = new FileReader();
reader.onload = () => {
setPreview(reader.result as string);
};
reader.readAsDataURL(file);
};
const handleLogoChange: ChangeEventHandler<HTMLInputElement> = (e) => {
const file = e.target.files?.[0];
if (!file) return;
processLogoFile(file, setLogoPreview);
void updateBrand({
variables: {
input: {
trustCenterId,
logoFile: null,
},
},
uploadables: {
"input.logoFile": file,
},
onCompleted: () => {
setLogoPreview(null);
},
});
};
const handleDarkLogoChange: ChangeEventHandler<HTMLInputElement> = (e) => {
const file = e.target.files?.[0];
if (!file) return;
processLogoFile(file, setDarkLogoPreview);
void updateBrand({
variables: {
input: {
trustCenterId,
darkLogoFile: null,
},
},
uploadables: {
"input.darkLogoFile": file,
},
onCompleted: () => {
setDarkLogoPreview(null);
},
});
};
const handleLogoDrop = (files: File[]) => {
const file = files[0];
if (!file) return;
processLogoFile(file, setLogoPreview);
void updateBrand({
variables: {
input: {
trustCenterId,
logoFile: null,
},
},
uploadables: {
"input.logoFile": file,
},
onCompleted: () => {
setLogoPreview(null);
},
});
};
const handleDarkLogoDrop = (files: File[]) => {
const file = files[0];
if (!file) return;
processLogoFile(file, setDarkLogoPreview);
void updateBrand({
variables: {
input: {
trustCenterId,
darkLogoFile: null,
},
},
uploadables: {
"input.darkLogoFile": file,
},
onCompleted: () => {
setDarkLogoPreview(null);
},
});
};
const handleRemoveLogo = async () => {
await updateBrand({
variables: {
input: {
trustCenterId,
logoFile: null,
},
},
onSuccess: () => {
setLogoPreview(null);
},
});
};
const handleRemoveDarkLogo = async () => {
await updateBrand({
variables: {
input: {
trustCenterId,
darkLogoFile: null,
},
},
onSuccess: () => {
setDarkLogoPreview(null);
},
});
};
const currentLogoUrl = logoPreview || logoFileUrl;
const currentDarkLogoUrl = darkLogoPreview || darkLogoFileUrl;
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<h2 className="text-base font-medium">{__("Branding")}</h2>
{isUpdating && <Spinner />}
</div>
<Card padded className="space-y-4">
<div className="flex gap-6 items-start">
<div className="flex-1">
<Label>{__("Logo")}</Label>
<p className="text-sm text-txt-tertiary mb-3">
{__("This logo will be displayed on your public compliance page.")}
</p>
{currentLogoUrl
? (
<div className="flex items-center gap-4">
<div className="border border-border-solid rounded-md p-4 bg-surface-secondary">
<img
src={currentLogoUrl}
alt={__("Compliance page logo")}
className="h-16 max-w-xs object-contain"
/>
</div>
<FileButton
disabled={disabled}
onChange={handleLogoChange}
variant="secondary"
accept="image/png,image/jpeg,image/jpg,image/svg+xml,image/webp"
>
{isUpdating ? __("Uploading...") : __("Change logo")}
</FileButton>
<Button
type="button"
variant="quaternary"
icon={IconTrashCan}
onClick={() => void handleRemoveLogo()}
disabled={disabled}
aria-label={__("Remove logo")}
className="text-red-600 hover:text-red-700"
/>
</div>
)
: (
<Dropzone
description={__("Upload logo image (PNG, JPG, SVG, WEBP up to 5MB)")}
isUploading={isUpdating}
onDrop={handleLogoDrop}
accept={{
"image/png": [".png"],
"image/jpeg": [".jpg", ".jpeg"],
"image/svg+xml": [".svg"],
"image/webp": [".webp"],
}}
maxSize={5}
/>
)}
</div>
<div className="flex-1">
<Label>{__("Dark mode logo")}</Label>
<p className="text-sm text-txt-tertiary mb-3">
{__("This logo will be used when dark mode is enabled.")}
</p>
{currentDarkLogoUrl
? (
<div className="flex items-center gap-4">
<div className="border border-border-solid rounded-md p-4 bg-gray-900">
<img
src={currentDarkLogoUrl}
alt={__("Compliance page dark logo")}
className="h-16 max-w-xs object-contain"
/>
</div>
<FileButton
disabled={disabled}
onChange={handleDarkLogoChange}
variant="secondary"
accept="image/png,image/jpeg,image/jpg,image/svg+xml,image/webp"
>
{isUpdating ? __("Uploading...") : __("Change dark logo")}
</FileButton>
<Button
type="button"
variant="quaternary"
icon={IconTrashCan}
onClick={() => void handleRemoveDarkLogo()}
disabled={disabled}
aria-label={__("Remove dark logo")}
className="text-red-600 hover:text-red-700"
/>
</div>
)
: (
<Dropzone
description={__("Upload dark logo image (PNG, JPG, SVG, WEBP up to 5MB)")}
isUploading={isUpdating}
onDrop={handleDarkLogoDrop}
accept={{
"image/png": [".png"],
"image/jpeg": [".jpg", ".jpeg"],
"image/svg+xml": [".svg"],
"image/webp": [".webp"],
}}
maxSize={5}
/>
)}
</div>
</div>
</Card>
</div>
);
}

View File

@@ -48,6 +48,12 @@ type (
File io.Reader
FileName string
}
UpdateTrustCenterBrandRequest struct {
TrustCenterID gid.GID
LogoFile **FileUpload
DarkLogoFile **FileUpload
}
)
func (utcr *UpdateTrustCenterRequest) Validate() error {
@@ -302,6 +308,132 @@ func (s TrustCenterService) DeleteNDA(
return trustCenter, nil, nil
}
func (s TrustCenterService) UpdateTrustCenterBrand(
ctx context.Context,
req *UpdateTrustCenterBrandRequest,
) (*coredata.TrustCenter, *coredata.File, error) {
var trustCenter *coredata.TrustCenter
var ndaFile *coredata.File
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
trustCenter = &coredata.TrustCenter{}
if err := trustCenter.LoadByID(ctx, conn, s.svc.scope, req.TrustCenterID); err != nil {
return fmt.Errorf("cannot load trust center: %w", err)
}
now := time.Now()
if req.LogoFile != nil {
if *req.LogoFile == nil {
trustCenter.LogoFileID = nil
} else {
file, err := s.uploadFile(ctx, conn, *req.LogoFile, "trust-center-logo", trustCenter)
if err != nil {
return fmt.Errorf("cannot upload logo file: %w", err)
}
trustCenter.LogoFileID = &file.ID
}
}
if req.DarkLogoFile != nil {
if *req.DarkLogoFile == nil {
trustCenter.DarkLogoFileID = nil
} else {
file, err := s.uploadFile(ctx, conn, *req.DarkLogoFile, "trust-center-dark-logo", trustCenter)
if err != nil {
return fmt.Errorf("cannot upload dark logo file: %w", err)
}
trustCenter.DarkLogoFileID = &file.ID
}
}
trustCenter.UpdatedAt = now
if err := trustCenter.Update(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot update trust center: %w", err)
}
if trustCenter.NonDisclosureAgreementFileID != nil {
ndaFile = &coredata.File{}
if err := ndaFile.LoadByID(ctx, conn, s.svc.scope, *trustCenter.NonDisclosureAgreementFileID); err != nil {
return fmt.Errorf("cannot load nda file: %w", err)
}
}
return nil
},
)
if err != nil {
return nil, nil, err
}
return trustCenter, ndaFile, nil
}
func (s TrustCenterService) uploadFile(
ctx context.Context,
conn pg.Conn,
fileUpload *FileUpload,
fileType string,
trustCenter *coredata.TrustCenter,
) (*coredata.File, error) {
objectKey, err := uuid.NewV7()
if err != nil {
return nil, fmt.Errorf("cannot generate object key: %w", err)
}
mimeType := fileUpload.ContentType
if mimeType == "" {
mimeType = mime.TypeByExtension(filepath.Ext(fileUpload.Filename))
}
_, err = s.svc.s3.PutObject(ctx, &s3.PutObjectInput{
Bucket: &s.svc.bucket,
Key: aws.String(objectKey.String()),
Body: fileUpload.Content,
ContentType: &mimeType,
Metadata: map[string]string{
"type": fileType,
"trust-center-id": trustCenter.ID.String(),
"organization-id": trustCenter.OrganizationID.String(),
},
})
if err != nil {
return nil, fmt.Errorf("cannot upload file to S3: %w", err)
}
headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{
Bucket: aws.String(s.svc.bucket),
Key: aws.String(objectKey.String()),
})
if err != nil {
return nil, fmt.Errorf("cannot get object metadata: %w", err)
}
now := time.Now()
fileID := gid.New(s.svc.scope.GetTenantID(), coredata.FileEntityType)
file := &coredata.File{
ID: fileID,
BucketName: s.svc.bucket,
MimeType: mimeType,
FileName: fileUpload.Filename,
FileKey: objectKey.String(),
FileSize: *headOutput.ContentLength,
CreatedAt: now,
UpdatedAt: now,
}
if err := file.Insert(ctx, conn, s.svc.scope); err != nil {
return nil, fmt.Errorf("cannot insert file: %w", err)
}
return file, nil
}
func (s TrustCenterService) GenerateNDAFileURL(
ctx context.Context,
trustCenterID gid.GID,
@@ -421,7 +553,7 @@ func (s TrustCenterService) GenerateDarkLogoURL(
return nil, err
}
if compliancePage.LogoFileID == nil {
if compliancePage.DarkLogoFileID == nil {
return nil, nil
}

View File

@@ -3071,6 +3071,9 @@ type Mutation {
deleteTrustCenterNDA(
input: DeleteTrustCenterNDAInput!
): DeleteTrustCenterNDAPayload!
updateTrustCenterBrand(
input: UpdateTrustCenterBrandInput!
): UpdateTrustCenterBrandPayload!
# Trust Center Access CRUD mutations
createTrustCenterAccess(
input: CreateTrustCenterAccessInput!
@@ -3445,6 +3448,12 @@ input DeleteTrustCenterNDAInput {
trustCenterId: ID!
}
input UpdateTrustCenterBrandInput {
trustCenterId: ID!
logoFile: Upload @goField(omittable: true)
darkLogoFile: Upload @goField(omittable: true)
}
input CreateTrustCenterAccessInput {
trustCenterId: ID!
email: EmailAddr!
@@ -4308,6 +4317,10 @@ type DeleteTrustCenterNDAPayload {
trustCenter: TrustCenter!
}
type UpdateTrustCenterBrandPayload {
trustCenter: TrustCenter!
}
type CreateTrustCenterAccessPayload {
trustCenterAccessEdge: TrustCenterAccessEdge!
}

View File

@@ -1063,6 +1063,7 @@ type ComplexityRoot struct {
UpdateTransferImpactAssessment func(childComplexity int, input types.UpdateTransferImpactAssessmentInput) int
UpdateTrustCenter func(childComplexity int, input types.UpdateTrustCenterInput) int
UpdateTrustCenterAccess func(childComplexity int, input types.UpdateTrustCenterAccessInput) int
UpdateTrustCenterBrand func(childComplexity int, input types.UpdateTrustCenterBrandInput) int
UpdateTrustCenterFile func(childComplexity int, input types.UpdateTrustCenterFileInput) int
UpdateTrustCenterReference func(childComplexity int, input types.UpdateTrustCenterReferenceInput) int
UpdateVendor func(childComplexity int, input types.UpdateVendorInput) int
@@ -1701,6 +1702,10 @@ type ComplexityRoot struct {
TrustCenterAccess func(childComplexity int) int
}
UpdateTrustCenterBrandPayload struct {
TrustCenter func(childComplexity int) int
}
UpdateTrustCenterFilePayload struct {
TrustCenterFile func(childComplexity int) int
}
@@ -2089,6 +2094,7 @@ type MutationResolver interface {
UpdateTrustCenter(ctx context.Context, input types.UpdateTrustCenterInput) (*types.UpdateTrustCenterPayload, error)
UploadTrustCenterNda(ctx context.Context, input types.UploadTrustCenterNDAInput) (*types.UploadTrustCenterNDAPayload, error)
DeleteTrustCenterNda(ctx context.Context, input types.DeleteTrustCenterNDAInput) (*types.DeleteTrustCenterNDAPayload, error)
UpdateTrustCenterBrand(ctx context.Context, input types.UpdateTrustCenterBrandInput) (*types.UpdateTrustCenterBrandPayload, error)
CreateTrustCenterAccess(ctx context.Context, input types.CreateTrustCenterAccessInput) (*types.CreateTrustCenterAccessPayload, error)
UpdateTrustCenterAccess(ctx context.Context, input types.UpdateTrustCenterAccessInput) (*types.UpdateTrustCenterAccessPayload, error)
DeleteTrustCenterAccess(ctx context.Context, input types.DeleteTrustCenterAccessInput) (*types.DeleteTrustCenterAccessPayload, error)
@@ -6457,6 +6463,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.Mutation.UpdateTrustCenterAccess(childComplexity, args["input"].(types.UpdateTrustCenterAccessInput)), true
case "Mutation.updateTrustCenterBrand":
if e.complexity.Mutation.UpdateTrustCenterBrand == nil {
break
}
args, err := ec.field_Mutation_updateTrustCenterBrand_args(ctx, rawArgs)
if err != nil {
return 0, false
}
return e.complexity.Mutation.UpdateTrustCenterBrand(childComplexity, args["input"].(types.UpdateTrustCenterBrandInput)), true
case "Mutation.updateTrustCenterFile":
if e.complexity.Mutation.UpdateTrustCenterFile == nil {
break
@@ -9188,6 +9205,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.UpdateTrustCenterAccessPayload.TrustCenterAccess(childComplexity), true
case "UpdateTrustCenterBrandPayload.trustCenter":
if e.complexity.UpdateTrustCenterBrandPayload.TrustCenter == nil {
break
}
return e.complexity.UpdateTrustCenterBrandPayload.TrustCenter(childComplexity), true
case "UpdateTrustCenterFilePayload.trustCenterFile":
if e.complexity.UpdateTrustCenterFilePayload.TrustCenterFile == nil {
break
@@ -10209,6 +10233,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
ec.unmarshalInputUpdateTaskInput,
ec.unmarshalInputUpdateTransferImpactAssessmentInput,
ec.unmarshalInputUpdateTrustCenterAccessInput,
ec.unmarshalInputUpdateTrustCenterBrandInput,
ec.unmarshalInputUpdateTrustCenterFileInput,
ec.unmarshalInputUpdateTrustCenterInput,
ec.unmarshalInputUpdateTrustCenterReferenceInput,
@@ -13399,6 +13424,9 @@ type Mutation {
deleteTrustCenterNDA(
input: DeleteTrustCenterNDAInput!
): DeleteTrustCenterNDAPayload!
updateTrustCenterBrand(
input: UpdateTrustCenterBrandInput!
): UpdateTrustCenterBrandPayload!
# Trust Center Access CRUD mutations
createTrustCenterAccess(
input: CreateTrustCenterAccessInput!
@@ -13773,6 +13801,12 @@ input DeleteTrustCenterNDAInput {
trustCenterId: ID!
}
input UpdateTrustCenterBrandInput {
trustCenterId: ID!
logoFile: Upload @goField(omittable: true)
darkLogoFile: Upload @goField(omittable: true)
}
input CreateTrustCenterAccessInput {
trustCenterId: ID!
email: EmailAddr!
@@ -14636,6 +14670,10 @@ type DeleteTrustCenterNDAPayload {
trustCenter: TrustCenter!
}
type UpdateTrustCenterBrandPayload {
trustCenter: TrustCenter!
}
type CreateTrustCenterAccessPayload {
trustCenterAccessEdge: TrustCenterAccessEdge!
}
@@ -17681,6 +17719,17 @@ func (ec *executionContext) field_Mutation_updateTrustCenterAccess_args(ctx cont
return args, nil
}
func (ec *executionContext) field_Mutation_updateTrustCenterBrand_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, "input", ec.unmarshalNUpdateTrustCenterBrandInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐUpdateTrustCenterBrandInput)
if err != nil {
return nil, err
}
args["input"] = arg0
return args, nil
}
func (ec *executionContext) field_Mutation_updateTrustCenterFile_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
@@ -33518,6 +33567,51 @@ func (ec *executionContext) fieldContext_Mutation_deleteTrustCenterNDA(ctx conte
return fc, nil
}
func (ec *executionContext) _Mutation_updateTrustCenterBrand(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_Mutation_updateTrustCenterBrand,
func(ctx context.Context) (any, error) {
fc := graphql.GetFieldContext(ctx)
return ec.resolvers.Mutation().UpdateTrustCenterBrand(ctx, fc.Args["input"].(types.UpdateTrustCenterBrandInput))
},
nil,
ec.marshalNUpdateTrustCenterBrandPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐUpdateTrustCenterBrandPayload,
true,
true,
)
}
func (ec *executionContext) fieldContext_Mutation_updateTrustCenterBrand(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Mutation",
Field: field,
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "trustCenter":
return ec.fieldContext_UpdateTrustCenterBrandPayload_trustCenter(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type UpdateTrustCenterBrandPayload", 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_Mutation_updateTrustCenterBrand_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
ec.Error(ctx, err)
return fc, err
}
return fc, nil
}
func (ec *executionContext) _Mutation_createTrustCenterAccess(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -54304,6 +54398,61 @@ func (ec *executionContext) fieldContext_UpdateTrustCenterAccessPayload_trustCen
return fc, nil
}
func (ec *executionContext) _UpdateTrustCenterBrandPayload_trustCenter(ctx context.Context, field graphql.CollectedField, obj *types.UpdateTrustCenterBrandPayload) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_UpdateTrustCenterBrandPayload_trustCenter,
func(ctx context.Context) (any, error) {
return obj.TrustCenter, nil
},
nil,
ec.marshalNTrustCenter2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTrustCenter,
true,
true,
)
}
func (ec *executionContext) fieldContext_UpdateTrustCenterBrandPayload_trustCenter(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "UpdateTrustCenterBrandPayload",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "id":
return ec.fieldContext_TrustCenter_id(ctx, field)
case "active":
return ec.fieldContext_TrustCenter_active(ctx, field)
case "logoFileUrl":
return ec.fieldContext_TrustCenter_logoFileUrl(ctx, field)
case "darkLogoFileUrl":
return ec.fieldContext_TrustCenter_darkLogoFileUrl(ctx, field)
case "ndaFileName":
return ec.fieldContext_TrustCenter_ndaFileName(ctx, field)
case "ndaFileUrl":
return ec.fieldContext_TrustCenter_ndaFileUrl(ctx, field)
case "createdAt":
return ec.fieldContext_TrustCenter_createdAt(ctx, field)
case "updatedAt":
return ec.fieldContext_TrustCenter_updatedAt(ctx, field)
case "organization":
return ec.fieldContext_TrustCenter_organization(ctx, field)
case "accesses":
return ec.fieldContext_TrustCenter_accesses(ctx, field)
case "references":
return ec.fieldContext_TrustCenter_references(ctx, field)
case "permission":
return ec.fieldContext_TrustCenter_permission(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type TrustCenter", field.Name)
},
}
return fc, nil
}
func (ec *executionContext) _UpdateTrustCenterFilePayload_trustCenterFile(ctx context.Context, field graphql.CollectedField, obj *types.UpdateTrustCenterFilePayload) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -67961,6 +68110,47 @@ func (ec *executionContext) unmarshalInputUpdateTrustCenterAccessInput(ctx conte
return it, nil
}
func (ec *executionContext) unmarshalInputUpdateTrustCenterBrandInput(ctx context.Context, obj any) (types.UpdateTrustCenterBrandInput, error) {
var it types.UpdateTrustCenterBrandInput
asMap := map[string]any{}
for k, v := range obj.(map[string]any) {
asMap[k] = v
}
fieldsInOrder := [...]string{"trustCenterId", "logoFile", "darkLogoFile"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
continue
}
switch k {
case "trustCenterId":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("trustCenterId"))
data, err := ec.unmarshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v)
if err != nil {
return it, err
}
it.TrustCenterID = data
case "logoFile":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("logoFile"))
data, err := ec.unmarshalOUpload2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx, v)
if err != nil {
return it, err
}
it.LogoFile = graphql.OmittableOf(data)
case "darkLogoFile":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("darkLogoFile"))
data, err := ec.unmarshalOUpload2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx, v)
if err != nil {
return it, err
}
it.DarkLogoFile = graphql.OmittableOf(data)
}
}
return it, nil
}
func (ec *executionContext) unmarshalInputUpdateTrustCenterFileInput(ctx context.Context, obj any) (types.UpdateTrustCenterFileInput, error) {
var it types.UpdateTrustCenterFileInput
asMap := map[string]any{}
@@ -78429,6 +78619,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "updateTrustCenterBrand":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_updateTrustCenterBrand(ctx, field)
})
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "createTrustCenterAccess":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_createTrustCenterAccess(ctx, field)
@@ -87121,6 +87318,45 @@ func (ec *executionContext) _UpdateTrustCenterAccessPayload(ctx context.Context,
return out
}
var updateTrustCenterBrandPayloadImplementors = []string{"UpdateTrustCenterBrandPayload"}
func (ec *executionContext) _UpdateTrustCenterBrandPayload(ctx context.Context, sel ast.SelectionSet, obj *types.UpdateTrustCenterBrandPayload) graphql.Marshaler {
fields := graphql.CollectFields(ec.OperationContext, sel, updateTrustCenterBrandPayloadImplementors)
out := graphql.NewFieldSet(fields)
deferred := make(map[string]*graphql.FieldSet)
for i, field := range fields {
switch field.Name {
case "__typename":
out.Values[i] = graphql.MarshalString("UpdateTrustCenterBrandPayload")
case "trustCenter":
out.Values[i] = ec._UpdateTrustCenterBrandPayload_trustCenter(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
}
default:
panic("unknown field " + strconv.Quote(field.Name))
}
}
out.Dispatch(ctx)
if out.Invalids > 0 {
return graphql.Null
}
atomic.AddInt32(&ec.deferred, int32(len(deferred)))
for label, dfs := range deferred {
ec.processDeferredGroup(graphql.DeferredGroup{
Label: label,
Path: graphql.GetPath(ctx),
FieldSet: dfs,
Context: ctx,
})
}
return out
}
var updateTrustCenterFilePayloadImplementors = []string{"UpdateTrustCenterFilePayload"}
func (ec *executionContext) _UpdateTrustCenterFilePayload(ctx context.Context, sel ast.SelectionSet, obj *types.UpdateTrustCenterFilePayload) graphql.Marshaler {
@@ -97541,6 +97777,25 @@ func (ec *executionContext) marshalNUpdateTrustCenterAccessPayload2ᚖgoᚗprobo
return ec._UpdateTrustCenterAccessPayload(ctx, sel, v)
}
func (ec *executionContext) unmarshalNUpdateTrustCenterBrandInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐUpdateTrustCenterBrandInput(ctx context.Context, v any) (types.UpdateTrustCenterBrandInput, error) {
res, err := ec.unmarshalInputUpdateTrustCenterBrandInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNUpdateTrustCenterBrandPayload2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐUpdateTrustCenterBrandPayload(ctx context.Context, sel ast.SelectionSet, v types.UpdateTrustCenterBrandPayload) graphql.Marshaler {
return ec._UpdateTrustCenterBrandPayload(ctx, sel, &v)
}
func (ec *executionContext) marshalNUpdateTrustCenterBrandPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐUpdateTrustCenterBrandPayload(ctx context.Context, sel ast.SelectionSet, v *types.UpdateTrustCenterBrandPayload) graphql.Marshaler {
if v == nil {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow")
}
return graphql.Null
}
return ec._UpdateTrustCenterBrandPayload(ctx, sel, v)
}
func (ec *executionContext) unmarshalNUpdateTrustCenterFileInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐUpdateTrustCenterFileInput(ctx context.Context, v any) (types.UpdateTrustCenterFileInput, error) {
res, err := ec.unmarshalInputUpdateTrustCenterFileInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)

View File

@@ -2266,6 +2266,16 @@ type UpdateTrustCenterAccessPayload struct {
TrustCenterAccess *TrustCenterAccess `json:"trustCenterAccess"`
}
type UpdateTrustCenterBrandInput struct {
TrustCenterID gid.GID `json:"trustCenterId"`
LogoFile graphql.Omittable[*graphql.Upload] `json:"logoFile,omitempty"`
DarkLogoFile graphql.Omittable[*graphql.Upload] `json:"darkLogoFile,omitempty"`
}
type UpdateTrustCenterBrandPayload struct {
TrustCenter *TrustCenter `json:"trustCenter"`
}
type UpdateTrustCenterFileInput struct {
ID gid.GID `json:"id"`
Name *string `json:"name,omitempty"`

View File

@@ -1789,6 +1789,61 @@ func (r *mutationResolver) DeleteTrustCenterNda(ctx context.Context, input types
}, nil
}
// UpdateTrustCenterBrand is the resolver for the updateTrustCenterBrand field.
func (r *mutationResolver) UpdateTrustCenterBrand(ctx context.Context, input types.UpdateTrustCenterBrandInput) (*types.UpdateTrustCenterBrandPayload, error) {
if err := r.authorize(ctx, input.TrustCenterID, probo.ActionTrustCenterUpdate); err != nil {
return nil, err
}
prb := r.ProboService(ctx, input.TrustCenterID.TenantID())
req := &probo.UpdateTrustCenterBrandRequest{
TrustCenterID: input.TrustCenterID,
}
if input.LogoFile.IsSet() {
logoFile := input.LogoFile.Value()
if logoFile == nil {
var nilFile *probo.FileUpload
req.LogoFile = &nilFile
} else {
fileUpload := &probo.FileUpload{
Content: logoFile.File,
Filename: logoFile.Filename,
Size: logoFile.Size,
ContentType: logoFile.ContentType,
}
req.LogoFile = &fileUpload
}
}
if input.DarkLogoFile.IsSet() {
darkLogoFile := input.DarkLogoFile.Value()
if darkLogoFile == nil {
var nilFile *probo.FileUpload
req.DarkLogoFile = &nilFile
} else {
fileUpload := &probo.FileUpload{
Content: darkLogoFile.File,
Filename: darkLogoFile.Filename,
Size: darkLogoFile.Size,
ContentType: darkLogoFile.ContentType,
}
req.DarkLogoFile = &fileUpload
}
}
trustCenter, file, err := prb.TrustCenters.UpdateTrustCenterBrand(ctx, req)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot update trust center brand", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return &types.UpdateTrustCenterBrandPayload{
TrustCenter: types.NewTrustCenter(trustCenter, file),
}, nil
}
// CreateTrustCenterAccess is the resolver for the createTrustCenterAccess field.
func (r *mutationResolver) CreateTrustCenterAccess(ctx context.Context, input types.CreateTrustCenterAccessInput) (*types.CreateTrustCenterAccessPayload, error) {
if err := r.authorize(ctx, input.TrustCenterID, probo.ActionTrustCenterAccessCreate); err != nil {