- {organization.compliancePage.ndaFileName
+ {organization.compliancePage.nda?.fileName
|| __("Non-Disclosure Agreement")}
@@ -137,9 +139,9 @@ export function CompliancePageNDASection(props: { fragmentRef: CompliancePageNDA
type="button"
variant="secondary"
onClick={() => {
- if (organization.compliancePage?.ndaFileUrl) {
+ if (organization.compliancePage?.nda?.downloadUrl) {
window.open(
- organization.compliancePage.ndaFileUrl,
+ organization.compliancePage.nda.downloadUrl,
"_blank",
"noopener,noreferrer",
);
diff --git a/apps/console/src/pages/organizations/compliance-page/references/_components/CompliancePageReferenceListItem.tsx b/apps/console/src/pages/organizations/compliance-page/references/_components/CompliancePageReferenceListItem.tsx
index 324baf166..abb15129a 100644
--- a/apps/console/src/pages/organizations/compliance-page/references/_components/CompliancePageReferenceListItem.tsx
+++ b/apps/console/src/pages/organizations/compliance-page/references/_components/CompliancePageReferenceListItem.tsx
@@ -24,7 +24,9 @@ import { DeleteTrustCenterReferenceDialog } from "#/components/trustCenter/Delet
const fragment = graphql`
fragment CompliancePageReferenceListItemFragment on TrustCenterReference {
id
- logoUrl
+ logo {
+ downloadUrl
+ }
name
description
websiteUrl
@@ -81,7 +83,7 @@ export function CompliancePageReferenceListItem(props: {
>
|
diff --git a/apps/console/src/pages/organizations/frameworks/FrameworkDetailPage.tsx b/apps/console/src/pages/organizations/frameworks/FrameworkDetailPage.tsx
index 99c9c8afa..11462700c 100644
--- a/apps/console/src/pages/organizations/frameworks/FrameworkDetailPage.tsx
+++ b/apps/console/src/pages/organizations/frameworks/FrameworkDetailPage.tsx
@@ -53,10 +53,13 @@ const frameworkDetailFragment = graphql`
name
# eslint-disable-next-line relay/unused-fields
description
+ lightLogo {
+ downloadUrl
+ }
# eslint-disable-next-line relay/unused-fields
- lightLogoURL
- # eslint-disable-next-line relay/unused-fields
- darkLogoURL
+ darkLogo {
+ downloadUrl
+ }
canExport: permission(action: "core:franework:export")
canUpdate: permission(action: "core:framework:update")
canDelete: permission(action: "core:framework:delete")
@@ -147,7 +150,11 @@ export default function FrameworkDetailPage(props: Props) {
-
+
{framework.name}
>
)}
diff --git a/apps/console/src/pages/organizations/frameworks/FrameworksPage.tsx b/apps/console/src/pages/organizations/frameworks/FrameworksPage.tsx
index 55647aadb..3df36c938 100644
--- a/apps/console/src/pages/organizations/frameworks/FrameworksPage.tsx
+++ b/apps/console/src/pages/organizations/frameworks/FrameworksPage.tsx
@@ -187,8 +187,12 @@ const frameworkCardFragment = graphql`
id
name
description
- lightLogoURL
- darkLogoURL
+ lightLogo {
+ downloadUrl
+ }
+ darkLogo {
+ downloadUrl
+ }
canUpdate: permission(action: "core:framework:update")
canDelete: permission(action: "core:framework:delete")
}
@@ -220,8 +224,8 @@ function FrameworkCard(props: FrameworkCardProps) {
{props.hasAnyAction && (
diff --git a/apps/console/src/pages/organizations/third-parties/dialogs/CommonThirdPartyCombobox.tsx b/apps/console/src/pages/organizations/third-parties/dialogs/CommonThirdPartyCombobox.tsx
index 06852fea3..2ebd8b3e7 100644
--- a/apps/console/src/pages/organizations/third-parties/dialogs/CommonThirdPartyCombobox.tsx
+++ b/apps/console/src/pages/organizations/third-parties/dialogs/CommonThirdPartyCombobox.tsx
@@ -30,7 +30,9 @@ export type CommonThirdPartyRef
export const commonThirdPartyFragment = graphql`
fragment CommonThirdPartyCombobox_commonThirdParty on CommonThirdParty @inline {
name
- logoUrl
+ logo {
+ downloadUrl
+ }
category
websiteUrl
headquarterAddress
@@ -51,7 +53,9 @@ export const commonThirdPartiesQuery = graphql`
commonThirdParties(name: $name) {
id
name
- logoUrl
+ logo {
+ downloadUrl
+ }
...CommonThirdPartyCombobox_commonThirdParty
}
}
@@ -107,7 +111,7 @@ export function CommonThirdPartyCombobox({
>
{thirdParty.name}
diff --git a/apps/console/src/pages/organizations/third-parties/dialogs/EditBusinessAssociateAgreementDialog.tsx b/apps/console/src/pages/organizations/third-parties/dialogs/EditBusinessAssociateAgreementDialog.tsx
index 4303a00e7..438bab56c 100644
--- a/apps/console/src/pages/organizations/third-parties/dialogs/EditBusinessAssociateAgreementDialog.tsx
+++ b/apps/console/src/pages/organizations/third-parties/dialogs/EditBusinessAssociateAgreementDialog.tsx
@@ -36,7 +36,9 @@ const updateBusinessAssociateAgreementMutation = graphql`
updateThirdPartyBusinessAssociateAgreement(input: $input) {
thirdPartyBusinessAssociateAgreement {
id
- fileUrl
+ file {
+ downloadUrl
+ }
validFrom
validUntil
createdAt
diff --git a/apps/console/src/pages/organizations/third-parties/dialogs/EditDataPrivacyAgreementDialog.tsx b/apps/console/src/pages/organizations/third-parties/dialogs/EditDataPrivacyAgreementDialog.tsx
index c42553606..b112e0b54 100644
--- a/apps/console/src/pages/organizations/third-parties/dialogs/EditDataPrivacyAgreementDialog.tsx
+++ b/apps/console/src/pages/organizations/third-parties/dialogs/EditDataPrivacyAgreementDialog.tsx
@@ -36,7 +36,9 @@ const updateDataPrivacyAgreementMutation = graphql`
updateThirdPartyDataPrivacyAgreement(input: $input) {
thirdPartyDataPrivacyAgreement {
id
- fileUrl
+ file {
+ downloadUrl
+ }
validFrom
validUntil
createdAt
diff --git a/apps/console/src/pages/organizations/third-parties/dialogs/UploadBusinessAssociateAgreementDialog.tsx b/apps/console/src/pages/organizations/third-parties/dialogs/UploadBusinessAssociateAgreementDialog.tsx
index 12219dc36..845f37f95 100644
--- a/apps/console/src/pages/organizations/third-parties/dialogs/UploadBusinessAssociateAgreementDialog.tsx
+++ b/apps/console/src/pages/organizations/third-parties/dialogs/UploadBusinessAssociateAgreementDialog.tsx
@@ -38,8 +38,10 @@ const uploadBusinessAssociateAgreementMutation = graphql`
uploadThirdPartyBusinessAssociateAgreement(input: $input) {
thirdPartyBusinessAssociateAgreement {
id
- fileName
- fileUrl
+ file {
+ fileName
+ downloadUrl
+ }
validFrom
validUntil
createdAt
diff --git a/apps/console/src/pages/organizations/third-parties/dialogs/UploadDataPrivacyAgreementDialog.tsx b/apps/console/src/pages/organizations/third-parties/dialogs/UploadDataPrivacyAgreementDialog.tsx
index 675660844..7ffeeeec0 100644
--- a/apps/console/src/pages/organizations/third-parties/dialogs/UploadDataPrivacyAgreementDialog.tsx
+++ b/apps/console/src/pages/organizations/third-parties/dialogs/UploadDataPrivacyAgreementDialog.tsx
@@ -38,8 +38,10 @@ const uploadDataPrivacyAgreementMutation = graphql`
uploadThirdPartyDataPrivacyAgreement(input: $input) {
thirdPartyDataPrivacyAgreement {
id
- fileName
- fileUrl
+ file {
+ fileName
+ downloadUrl
+ }
validFrom
validUntil
createdAt
diff --git a/apps/console/src/pages/organizations/third-parties/tabs/ThirdPartyOverviewTab.tsx b/apps/console/src/pages/organizations/third-parties/tabs/ThirdPartyOverviewTab.tsx
index 72ffc0f16..434d73f41 100644
--- a/apps/console/src/pages/organizations/third-parties/tabs/ThirdPartyOverviewTab.tsx
+++ b/apps/console/src/pages/organizations/third-parties/tabs/ThirdPartyOverviewTab.tsx
@@ -50,8 +50,10 @@ const thirdPartyBusinessAssociateAgreementFragment = graphql`
fragment ThirdPartyOverviewTabBusinessAssociateAgreementFragment on ThirdParty {
businessAssociateAgreement {
id
- fileName
- fileUrl
+ file {
+ fileName
+ downloadUrl
+ }
validFrom
validUntil
canUpdate: permission(
@@ -68,8 +70,10 @@ const thirdPartyDataPrivacyAgreementFragment = graphql`
fragment ThirdPartyOverviewTabDataPrivacyAgreementFragment on ThirdParty {
dataPrivacyAgreement {
id
- fileName
- fileUrl
+ file {
+ fileName
+ downloadUrl
+ }
validFrom
validUntil
canUpdate: permission(action: "core:thirdParty-data-privacy-agreement:update")
@@ -299,7 +303,7 @@ export default function ThirdPartyOverviewTab() {
{businessAssociateAgreement
- ? businessAssociateAgreement.fileName
+ ? businessAssociateAgreement.file.fileName
: __("No business associate agreement available")}
{(businessAssociateAgreement?.validFrom
@@ -322,8 +326,8 @@ export default function ThirdPartyOverviewTab() {
variant="secondary"
onClick={() =>
downloadFile(
- businessAssociateAgreement.fileUrl,
- businessAssociateAgreement.fileName,
+ businessAssociateAgreement.file.downloadUrl,
+ businessAssociateAgreement.file.fileName,
)}
>
{__("Download PDF")}
@@ -343,7 +347,7 @@ export default function ThirdPartyOverviewTab() {
{businessAssociateAgreement.canDelete && (
window.location.reload()}
>
@@ -373,7 +377,7 @@ export default function ThirdPartyOverviewTab() {
{dataPrivacyAgreement
- ? dataPrivacyAgreement.fileName
+ ? dataPrivacyAgreement.file.fileName
: __("No data privacy agreement available")}
{(dataPrivacyAgreement?.validFrom
@@ -396,8 +400,8 @@ export default function ThirdPartyOverviewTab() {
variant="secondary"
onClick={() =>
downloadFile(
- dataPrivacyAgreement.fileUrl,
- dataPrivacyAgreement.fileName,
+ dataPrivacyAgreement.file.downloadUrl,
+ dataPrivacyAgreement.file.fileName,
)}
>
{__("Download PDF")}
@@ -417,7 +421,7 @@ export default function ThirdPartyOverviewTab() {
{dataPrivacyAgreement.canDelete && (
window.location.reload()}
>
diff --git a/e2e/console/common_third_party_test.go b/e2e/console/common_third_party_test.go
index 101d2a29d..830f06bc9 100644
--- a/e2e/console/common_third_party_test.go
+++ b/e2e/console/common_third_party_test.go
@@ -29,7 +29,7 @@ import (
"go.probo.inc/probo/pkg/gid"
)
-func TestCommonThirdParties_QueryWithLogoURL(t *testing.T) {
+func TestCommonThirdParties_QueryWithLogo(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
@@ -42,25 +42,29 @@ func TestCommonThirdParties_QueryWithLogoURL(t *testing.T) {
commonThirdParties(name: $name) {
id
name
- logoUrl
+ logo {
+ downloadUrl
+ }
}
}
`
var result struct {
CommonThirdParties []struct {
- ID string `json:"id"`
- Name string `json:"name"`
- LogoURL *string `json:"logoUrl"`
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Logo *struct {
+ DownloadURL string `json:"downloadUrl"`
+ } `json:"logo"`
} `json:"commonThirdParties"`
}
err := owner.Execute(query, map[string]any{"name": name}, &result)
- require.NoError(t, err, "querying commonThirdParties.logoUrl must not surface a resource-not-found error")
+ require.NoError(t, err, "querying commonThirdParties.logo must not surface a resource-not-found error")
require.Len(t, result.CommonThirdParties, 1)
assert.Equal(t, id.String(), result.CommonThirdParties[0].ID)
assert.Equal(t, name, result.CommonThirdParties[0].Name)
- assert.Nil(t, result.CommonThirdParties[0].LogoURL)
+ assert.Nil(t, result.CommonThirdParties[0].Logo)
}
func seedCommonThirdParty(t *testing.T, name string) gid.GID {
diff --git a/e2e/console/trust_center_nda_test.go b/e2e/console/trust_center_nda_test.go
new file mode 100644
index 000000000..4b4d004de
--- /dev/null
+++ b/e2e/console/trust_center_nda_test.go
@@ -0,0 +1,113 @@
+// Copyright (c) 2026 Probo Inc .
+//
+// 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 console_test
+
+import (
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "go.probo.inc/probo/e2e/internal/testutil"
+)
+
+func TestTrustCenter_UploadNDA(t *testing.T) {
+ t.Parallel()
+
+ owner := testutil.NewClient(t, testutil.RoleOwner)
+ organizationID := owner.GetOrganizationID().String()
+
+ const trustCenterQuery = `
+ query($organizationId: ID!) {
+ node(id: $organizationId) {
+ ... on Organization {
+ trustCenter {
+ id
+ }
+ }
+ }
+ }
+ `
+
+ var trustCenterLookup struct {
+ Node struct {
+ TrustCenter struct {
+ ID string `json:"id"`
+ } `json:"trustCenter"`
+ } `json:"node"`
+ }
+
+ err := owner.Execute(trustCenterQuery, map[string]any{
+ "organizationId": organizationID,
+ }, &trustCenterLookup)
+ require.NoError(t, err)
+ require.NotEmpty(t, trustCenterLookup.Node.TrustCenter.ID)
+
+ trustCenterID := trustCenterLookup.Node.TrustCenter.ID
+
+ const uploadMutation = `
+ mutation UploadTrustCenterNDA($input: UploadTrustCenterNDAInput!) {
+ uploadTrustCenterNDA(input: $input) {
+ trustCenter {
+ id
+ nda {
+ id
+ fileName
+ downloadUrl
+ }
+ }
+ }
+ }
+ `
+
+ pdfContent := []byte("%PDF-1.4\n1 0 obj\n<< /Type /Catalog >>\nendobj\ntrailer\n<< /Root 1 0 R >>\n%%EOF")
+
+ var uploadResult struct {
+ UploadTrustCenterNDA struct {
+ TrustCenter struct {
+ ID string `json:"id"`
+ Nda *struct {
+ ID string `json:"id"`
+ FileName string `json:"fileName"`
+ DownloadURL string `json:"downloadUrl"`
+ } `json:"nda"`
+ } `json:"trustCenter"`
+ } `json:"uploadTrustCenterNDA"`
+ }
+
+ err = owner.ExecuteWithFile(uploadMutation, map[string]any{
+ "input": map[string]any{
+ "trustCenterId": trustCenterID,
+ "fileName": "nda.pdf",
+ "file": nil,
+ },
+ }, "input.file", testutil.UploadFile{
+ Filename: "nda.pdf",
+ ContentType: "application/pdf",
+ Content: pdfContent,
+ }, &uploadResult)
+ require.NoError(t, err)
+
+ assert.Equal(t, trustCenterID, uploadResult.UploadTrustCenterNDA.TrustCenter.ID)
+ require.NotNil(t, uploadResult.UploadTrustCenterNDA.TrustCenter.Nda)
+ assert.Equal(t, "nda.pdf", uploadResult.UploadTrustCenterNDA.TrustCenter.Nda.FileName)
+ assert.NotEmpty(t, uploadResult.UploadTrustCenterNDA.TrustCenter.Nda.DownloadURL)
+ assert.True(
+ t,
+ strings.Contains(uploadResult.UploadTrustCenterNDA.TrustCenter.Nda.DownloadURL, "/api/files/v1/"),
+ "downloadUrl must route through the files API, got %q",
+ uploadResult.UploadTrustCenterNDA.TrustCenter.Nda.DownloadURL,
+ )
+}
diff --git a/pkg/filemanager/service.go b/pkg/filemanager/service.go
index 23a1c4a74..18f0b7ad6 100644
--- a/pkg/filemanager/service.go
+++ b/pkg/filemanager/service.go
@@ -166,6 +166,25 @@ func (s *Service) GeneratePresignedFileURL(
return presignedReq.URL, nil
}
+// DownloadAPIPath returns the stable files API path for a stored file.
+func DownloadAPIPath(file *coredata.File) string {
+ if file.Visibility == coredata.FileVisibilityPublic {
+ return "/api/files/v1/public/" + file.ID.String()
+ }
+
+ return "/api/files/v1/" + file.ID.String()
+}
+
+// BuildDownloadURL returns the absolute app URL that routes through the files API.
+func (s *Service) BuildDownloadURL(file *coredata.File) (string, error) {
+ url, err := s.baseURL.AppendPath(DownloadAPIPath(file)).String()
+ if err != nil {
+ return "", fmt.Errorf("cannot build file URL: %w", err)
+ }
+
+ return url, nil
+}
+
// GenerateFileURL loads a public file from DB and returns the stable app URL
// /api/files/v1/public/{id}. Used when a long-lived embeddable URL is needed
// (e.g. trust center logos).
@@ -188,12 +207,7 @@ func (s *Service) GenerateFileURL(
return "", err
}
- url, err := s.baseURL.AppendPath("/api/files/v1/public/" + fileID.String()).String()
- if err != nil {
- return "", fmt.Errorf("cannot build file URL: %w", err)
- }
-
- return url, nil
+ return s.BuildDownloadURL(file)
}
// GeneratePublicPresignedFileURL loads a public file from DB and returns a
diff --git a/pkg/filemanager/service_test.go b/pkg/filemanager/service_test.go
index 9b5e4a3b9..10cf30c82 100644
--- a/pkg/filemanager/service_test.go
+++ b/pkg/filemanager/service_test.go
@@ -19,8 +19,33 @@ import (
"github.com/stretchr/testify/assert"
"go.probo.inc/probo/pkg/baseurl"
+ "go.probo.inc/probo/pkg/coredata"
+ "go.probo.inc/probo/pkg/filemanager"
+ "go.probo.inc/probo/pkg/gid"
)
+func TestDownloadAPIPath_IncludesPublicSegmentForPublicFiles(t *testing.T) {
+ t.Parallel()
+
+ file := &coredata.File{
+ ID: gid.New(gid.NilTenant, coredata.FileEntityType),
+ Visibility: coredata.FileVisibilityPublic,
+ }
+
+ assert.Equal(t, "/api/files/v1/public/"+file.ID.String(), filemanager.DownloadAPIPath(file))
+}
+
+func TestDownloadAPIPath_UsesPrivateSegmentForPrivateFiles(t *testing.T) {
+ t.Parallel()
+
+ file := &coredata.File{
+ ID: gid.New(gid.NilTenant, coredata.FileEntityType),
+ Visibility: coredata.FileVisibilityPrivate,
+ }
+
+ assert.Equal(t, "/api/files/v1/"+file.ID.String(), filemanager.DownloadAPIPath(file))
+}
+
func TestGenerateFileURL_PathIncludesPublicSegment(t *testing.T) {
t.Parallel()
@@ -29,10 +54,15 @@ func TestGenerateFileURL_PathIncludesPublicSegment(t *testing.T) {
t.Fatalf("cannot parse base URL: %v", err)
}
- url, err := base.AppendPath("/api/files/v1/public/some-id").String()
+ file := &coredata.File{
+ ID: gid.New(gid.NilTenant, coredata.FileEntityType),
+ Visibility: coredata.FileVisibilityPublic,
+ }
+
+ url, err := base.AppendPath(filemanager.DownloadAPIPath(file)).String()
if err != nil {
t.Fatalf("cannot build URL: %v", err)
}
- assert.Equal(t, "https://app.example.com/api/files/v1/public/some-id", url)
+ assert.Equal(t, "https://app.example.com/api/files/v1/public/"+file.ID.String(), url)
}
diff --git a/pkg/iam/organization_service.go b/pkg/iam/organization_service.go
index 5d5d9f5b9..e13732762 100644
--- a/pkg/iam/organization_service.go
+++ b/pkg/iam/organization_service.go
@@ -1410,12 +1410,12 @@ func (s OrganizationService) GenerateLogoURL(
return nil, fmt.Errorf("cannot generate logo URL: %w", err)
}
- presignedURL, err := s.fm.GeneratePresignedFileURL(ctx, file, expiresIn)
+ downloadURL, err := s.fm.BuildDownloadURL(file)
if err != nil {
return nil, fmt.Errorf("cannot generate file URL: %w", err)
}
- return &presignedURL, nil
+ return &downloadURL, nil
}
func (s OrganizationService) GenerateHorizontalLogoURL(
@@ -1456,12 +1456,12 @@ func (s OrganizationService) GenerateHorizontalLogoURL(
return nil, err
}
- presignedURL, err := s.fm.GeneratePresignedFileURL(ctx, file, expiresIn)
+ downloadURL, err := s.fm.BuildDownloadURL(file)
if err != nil {
return nil, fmt.Errorf("cannot generate file URL: %w", err)
}
- return &presignedURL, nil
+ return &downloadURL, nil
}
func (s OrganizationService) DeleteSAMLConfiguration(
diff --git a/pkg/probo/trust_center_service.go b/pkg/probo/trust_center_service.go
index e7b968946..56b934d33 100644
--- a/pkg/probo/trust_center_service.go
+++ b/pkg/probo/trust_center_service.go
@@ -216,17 +216,12 @@ func (s TrustCenterService) UploadNDA(
return nil, nil, err
}
- objectKey, err := uuid.NewV7()
- if err != nil {
- return nil, nil, fmt.Errorf("cannot generate object key: %w", err)
- }
-
var (
trustCenter *coredata.TrustCenter
file *coredata.File
)
- err = s.svc.pg.WithTx(
+ err := s.svc.pg.WithTx(
ctx,
func(ctx context.Context, conn pg.Tx) error {
trustCenter = &coredata.TrustCenter{}
@@ -234,30 +229,18 @@ func (s TrustCenterService) UploadNDA(
return fmt.Errorf("cannot load trust center: %w", err)
}
- mimeType := mime.TypeByExtension(filepath.Ext(req.FileName))
-
- _, err := s.svc.s3.PutObject(ctx, &s3.PutObjectInput{
- Bucket: &s.svc.bucket,
- Key: new(objectKey.String()),
- Body: req.File,
- ContentType: &mimeType,
- CacheControl: new("private, max-age=3600"),
- Metadata: map[string]string{
- "type": "trust-center-nda",
- "trust-center-id": req.TrustCenterID.String(),
- "organization-id": trustCenter.OrganizationID.String(),
- },
- })
- if err != nil {
- return fmt.Errorf("cannot upload file to S3: %w", err)
+ if trustCenter.OrganizationID == gid.Nil {
+ return fmt.Errorf("trust center %s has no organization", req.TrustCenterID)
}
- headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{
- Bucket: new(s.svc.bucket),
- Key: new(objectKey.String()),
- })
+ objectKey, err := uuid.NewV7()
if err != nil {
- return fmt.Errorf("cannot get object metadata: %w", err)
+ return fmt.Errorf("cannot generate object key: %w", err)
+ }
+
+ mimeType := mime.TypeByExtension(filepath.Ext(req.FileName))
+ if mimeType == "" {
+ mimeType = "application/octet-stream"
}
now := time.Now()
@@ -270,12 +253,27 @@ func (s TrustCenterService) UploadNDA(
MimeType: mimeType,
FileName: req.FileName,
FileKey: objectKey.String(),
- FileSize: *headOutput.ContentLength,
Visibility: coredata.FileVisibilityPrivate,
CreatedAt: now,
UpdatedAt: now,
}
+ fileSize, err := s.svc.fileManager.PutFile(
+ ctx,
+ file,
+ req.File,
+ map[string]string{
+ "type": "trust-center-nda",
+ "trust-center-id": req.TrustCenterID.String(),
+ "organization-id": trustCenter.OrganizationID.String(),
+ },
+ )
+ if err != nil {
+ return fmt.Errorf("cannot upload file to S3: %w", err)
+ }
+
+ file.FileSize = fileSize
+
if err := file.Insert(ctx, conn, scope); err != nil {
return fmt.Errorf("cannot insert file: %w", err)
}
diff --git a/pkg/server/api/console/v1/base_resolvers.go b/pkg/server/api/console/v1/base_resolvers.go
index 0f11be47b..639f22395 100644
--- a/pkg/server/api/console/v1/base_resolvers.go
+++ b/pkg/server/api/console/v1/base_resolvers.go
@@ -8,7 +8,6 @@ package console_v1
import (
"context"
"errors"
- "fmt"
"slices"
"strings"
@@ -332,15 +331,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
return nil, err
}
- var file *coredata.File
- if trustCenter.NonDisclosureAgreementFileID != nil {
- file, err = r.probo.Files.Get(ctx, scope, *trustCenter.NonDisclosureAgreementFileID)
- if err != nil {
- return nil, fmt.Errorf("cannot get NDA file: %w", err)
- }
- }
-
- return types.NewTrustCenter(trustCenter, file), nil
+ return types.NewTrustCenter(trustCenter), nil
}
case coredata.TrustCenterAccessEntityType:
action = probo.ActionTrustCenterAccessGet
diff --git a/pkg/server/api/console/v1/common_third_party_resolvers.go b/pkg/server/api/console/v1/common_third_party_resolvers.go
index fd406cfe1..deb593140 100644
--- a/pkg/server/api/console/v1/common_third_party_resolvers.go
+++ b/pkg/server/api/console/v1/common_third_party_resolvers.go
@@ -8,30 +8,22 @@ package console_v1
import (
"context"
- "go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
"go.probo.inc/probo/pkg/server/api/console/v1/types"
- "go.probo.inc/probo/pkg/server/gqlutils"
)
-// LogoURL is the resolver for the logoUrl field.
-func (r *commonThirdPartyResolver) LogoURL(ctx context.Context, obj *types.CommonThirdParty) (*string, error) {
+// Logo is the resolver for the logo field.
+func (r *commonThirdPartyResolver) Logo(ctx context.Context, obj *types.CommonThirdParty) (*types.File, error) {
if _, err := r.authorize(ctx, obj.ID, probo.ActionCommonThirdPartyGet); err != nil {
return nil, err
}
- if obj.LogoFileID == nil {
+ if obj.Logo == nil {
return nil, nil
}
- logoURL, err := r.thirdParty.GenerateLogoURL(ctx, *obj.LogoFileID)
- if err != nil {
- r.logger.ErrorCtx(ctx, "cannot generate common third party logo URL", log.Error(err))
- return nil, gqlutils.Internal(ctx)
- }
-
- return logoURL, nil
+ return r.loadFile(ctx, obj.Logo.ID)
}
// CommonThirdParty returns schema.CommonThirdPartyResolver implementation.
diff --git a/pkg/server/api/console/v1/electronic_signature_resolvers.go b/pkg/server/api/console/v1/electronic_signature_resolvers.go
index 21efc3b5b..a1f58de39 100644
--- a/pkg/server/api/console/v1/electronic_signature_resolvers.go
+++ b/pkg/server/api/console/v1/electronic_signature_resolvers.go
@@ -8,34 +8,23 @@ package console_v1
import (
"context"
"fmt"
- "time"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
"go.probo.inc/probo/pkg/server/api/console/v1/types"
)
-// CertificateFileURL is the resolver for the certificateFileUrl field.
-func (r *electronicSignatureResolver) CertificateFileURL(ctx context.Context, obj *types.ElectronicSignature) (*string, error) {
+// Certificate is the resolver for the certificate field.
+func (r *electronicSignatureResolver) Certificate(ctx context.Context, obj *types.ElectronicSignature) (*types.File, error) {
if _, err := r.authorize(ctx, obj.ID, probo.ActionElectronicSignatureGet); err != nil {
return nil, err
}
- signature, err := r.esign.GetSignatureByID(ctx, obj.ID)
- if err != nil {
- return nil, fmt.Errorf("cannot load signature: %w", err)
- }
-
- if signature.CertificateFileID == nil {
+ if obj.Certificate == nil {
return nil, nil
}
- url, err := r.esign.GenerateCertificateFileURL(ctx, *signature.CertificateFileID, 1*time.Hour)
- if err != nil {
- return nil, fmt.Errorf("cannot generate certificate file URL: %w", err)
- }
-
- return &url, nil
+ return r.loadFile(ctx, obj.Certificate.ID)
}
// Events is the resolver for the events field.
diff --git a/pkg/server/api/console/v1/file_loader.go b/pkg/server/api/console/v1/file_loader.go
new file mode 100644
index 000000000..89a3c41b0
--- /dev/null
+++ b/pkg/server/api/console/v1/file_loader.go
@@ -0,0 +1,44 @@
+// Copyright (c) 2026 Probo Inc .
+//
+// 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 console_v1
+
+import (
+ "context"
+ "errors"
+
+ "github.com/vikstrous/dataloadgen"
+ "go.gearno.de/kit/log"
+ "go.probo.inc/probo/pkg/gid"
+ "go.probo.inc/probo/pkg/server/api/console/v1/dataloader"
+ "go.probo.inc/probo/pkg/server/api/console/v1/types"
+ "go.probo.inc/probo/pkg/server/gqlutils"
+)
+
+func (r *Resolver) loadFile(ctx context.Context, fileID gid.GID) (*types.File, error) {
+ loaders := dataloader.FromContext(ctx)
+
+ file, err := loaders.File.Load(ctx, fileID)
+ if err != nil {
+ if errors.Is(err, dataloadgen.ErrNotFound) {
+ return nil, gqlutils.NotFound(ctx, err)
+ }
+
+ r.logger.ErrorCtx(ctx, "cannot load file", log.Error(err))
+
+ return nil, gqlutils.Internal(ctx)
+ }
+
+ return types.NewFile(file, r.baseURL), nil
+}
diff --git a/pkg/server/api/console/v1/file_resolvers.go b/pkg/server/api/console/v1/file_resolvers.go
deleted file mode 100644
index 14c61c747..000000000
--- a/pkg/server/api/console/v1/file_resolvers.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package console_v1
-
-// This file will be automatically regenerated based on the schema, any resolver
-// implementations
-// will be copied through when generating and any unknown code will be moved to the end.
-// Code generated by github.com/99designs/gqlgen version v0.17.90
-
-import (
- "context"
- "time"
-
- "go.gearno.de/kit/log"
- "go.probo.inc/probo/pkg/probo"
- "go.probo.inc/probo/pkg/server/api/console/v1/schema"
- "go.probo.inc/probo/pkg/server/api/console/v1/types"
- "go.probo.inc/probo/pkg/server/gqlutils"
-)
-
-// DownloadURL is the resolver for the downloadUrl field.
-func (r *fileResolver) DownloadURL(ctx context.Context, obj *types.File) (string, error) {
- scope, err := r.authorize(ctx, obj.ID, probo.ActionFileGet)
- if err != nil {
- return "", err
- }
-
- downloadUrl, err := r.probo.Files.GenerateFileURL(ctx, scope, obj.ID, 60*time.Second)
- if err != nil {
- r.logger.ErrorCtx(ctx, "cannot generate download URL", log.Error(err))
- return "", gqlutils.Internal(ctx)
- }
-
- return downloadUrl, nil
-}
-
-// File returns schema.FileResolver implementation.
-func (r *Resolver) File() schema.FileResolver { return &fileResolver{r} }
-
-type fileResolver struct{ *Resolver }
diff --git a/pkg/server/api/console/v1/framework_resolvers.go b/pkg/server/api/console/v1/framework_resolvers.go
index 5aaa85b7a..af83fc825 100644
--- a/pkg/server/api/console/v1/framework_resolvers.go
+++ b/pkg/server/api/console/v1/framework_resolvers.go
@@ -9,7 +9,6 @@ import (
"context"
"encoding/json"
"errors"
- "time"
"github.com/vikstrous/dataloadgen"
"go.gearno.de/kit/log"
@@ -81,24 +80,30 @@ func (r *frameworkResolver) Controls(ctx context.Context, obj *types.Framework,
return types.NewControlConnection(page, r, obj.ID, controlFilter), nil
}
-// LightLogoURL is the resolver for the lightLogoURL field.
-func (r *frameworkResolver) LightLogoURL(ctx context.Context, obj *types.Framework) (*string, error) {
- scope, err := r.authorize(ctx, obj.ID, probo.ActionFrameworkGet)
- if err != nil {
+// LightLogo is the resolver for the lightLogo field.
+func (r *frameworkResolver) LightLogo(ctx context.Context, obj *types.Framework) (*types.File, error) {
+ if _, err := r.authorize(ctx, obj.ID, probo.ActionFrameworkGet); err != nil {
return nil, err
}
- return r.probo.Frameworks.GenerateLightLogoURL(ctx, scope, obj.ID, 1*time.Hour)
+ if obj.LightLogo == nil {
+ return nil, nil
+ }
+
+ return r.loadFile(ctx, obj.LightLogo.ID)
}
-// DarkLogoURL is the resolver for the darkLogoURL field.
-func (r *frameworkResolver) DarkLogoURL(ctx context.Context, obj *types.Framework) (*string, error) {
- scope, err := r.authorize(ctx, obj.ID, probo.ActionFrameworkGet)
- if err != nil {
+// DarkLogo is the resolver for the darkLogo field.
+func (r *frameworkResolver) DarkLogo(ctx context.Context, obj *types.Framework) (*types.File, error) {
+ if _, err := r.authorize(ctx, obj.ID, probo.ActionFrameworkGet); err != nil {
return nil, err
}
- return r.probo.Frameworks.GenerateDarkLogoURL(ctx, scope, obj.ID, 1*time.Hour)
+ if obj.DarkLogo == nil {
+ return nil, nil
+ }
+
+ return r.loadFile(ctx, obj.DarkLogo.ID)
}
// Permission is the resolver for the permission field.
diff --git a/pkg/server/api/console/v1/graphql/common_third_party.graphql b/pkg/server/api/console/v1/graphql/common_third_party.graphql
index 86dc793e5..185e10963 100644
--- a/pkg/server/api/console/v1/graphql/common_third_party.graphql
+++ b/pkg/server/api/console/v1/graphql/common_third_party.graphql
@@ -30,5 +30,5 @@ type CommonThirdParty
trustPageUrl: String
statusPageUrl: String
termsOfServiceUrl: String
- logoUrl: String @goField(forceResolver: true)
+ logo: File @goField(forceResolver: true)
}
diff --git a/pkg/server/api/console/v1/graphql/electronic_signature.graphql b/pkg/server/api/console/v1/graphql/electronic_signature.graphql
index 41108262d..90dbde33f 100644
--- a/pkg/server/api/console/v1/graphql/electronic_signature.graphql
+++ b/pkg/server/api/console/v1/graphql/electronic_signature.graphql
@@ -129,7 +129,7 @@ type ElectronicSignature implements Node {
consentText: String!
lastError: String
signedAt: Datetime
- certificateFileUrl: String @goField(forceResolver: true)
+ certificate: File @goField(forceResolver: true)
events: [ElectronicSignatureEvent!]! @goField(forceResolver: true)
createdAt: Datetime!
updatedAt: Datetime!
diff --git a/pkg/server/api/console/v1/graphql/file.graphql b/pkg/server/api/console/v1/graphql/file.graphql
index ef51af51c..aa9313ab0 100644
--- a/pkg/server/api/console/v1/graphql/file.graphql
+++ b/pkg/server/api/console/v1/graphql/file.graphql
@@ -3,7 +3,7 @@ type File {
mimeType: String!
fileName: String!
size: BigInt!
- downloadUrl: String! @goField(forceResolver: true)
+ downloadUrl: String!
createdAt: Datetime!
updatedAt: Datetime!
}
diff --git a/pkg/server/api/console/v1/graphql/framework.graphql b/pkg/server/api/console/v1/graphql/framework.graphql
index 68d0a8672..3c506cf68 100644
--- a/pkg/server/api/console/v1/graphql/framework.graphql
+++ b/pkg/server/api/console/v1/graphql/framework.graphql
@@ -29,8 +29,8 @@ type Framework implements Node {
orderBy: ControlOrder
filter: ControlFilter
): ControlConnection! @goField(forceResolver: true)
- lightLogoURL: String @goField(forceResolver: true)
- darkLogoURL: String @goField(forceResolver: true)
+ lightLogo: File @goField(forceResolver: true)
+ darkLogo: File @goField(forceResolver: true)
createdAt: Datetime!
updatedAt: Datetime!
diff --git a/pkg/server/api/console/v1/graphql/organization.graphql b/pkg/server/api/console/v1/graphql/organization.graphql
index 4ba0fd45c..3d9dfe2a2 100644
--- a/pkg/server/api/console/v1/graphql/organization.graphql
+++ b/pkg/server/api/console/v1/graphql/organization.graphql
@@ -90,8 +90,8 @@ type UpdateOrganizationContextPayload {
type Organization implements Node {
id: ID!
name: String!
- logoUrl: String @goField(forceResolver: true)
- horizontalLogoUrl: String @goField(forceResolver: true)
+ logo: File @goField(forceResolver: true)
+ horizontalLogo: File @goField(forceResolver: true)
description: String
websiteUrl: String
diff --git a/pkg/server/api/console/v1/graphql/third_party.graphql b/pkg/server/api/console/v1/graphql/third_party.graphql
index 5590ab95f..971b87a9e 100644
--- a/pkg/server/api/console/v1/graphql/third_party.graphql
+++ b/pkg/server/api/console/v1/graphql/third_party.graphql
@@ -342,9 +342,7 @@ type ThirdPartyBusinessAssociateAgreement implements Node {
thirdParty: ThirdParty! @goField(forceResolver: true)
validFrom: Datetime
validUntil: Datetime
- fileName: String!
- fileUrl: String! @goField(forceResolver: true)
- fileSize: BigInt!
+ file: File! @goField(forceResolver: true)
createdAt: Datetime!
updatedAt: Datetime!
@@ -380,9 +378,7 @@ type ThirdPartyDataPrivacyAgreement implements Node {
thirdParty: ThirdParty! @goField(forceResolver: true)
validFrom: Datetime
validUntil: Datetime
- fileName: String!
- fileUrl: String! @goField(forceResolver: true)
- fileSize: BigInt!
+ file: File! @goField(forceResolver: true)
createdAt: Datetime!
updatedAt: Datetime!
diff --git a/pkg/server/api/console/v1/graphql/trust_center.graphql b/pkg/server/api/console/v1/graphql/trust_center.graphql
index ba0d6110b..fd66895be 100644
--- a/pkg/server/api/console/v1/graphql/trust_center.graphql
+++ b/pkg/server/api/console/v1/graphql/trust_center.graphql
@@ -249,10 +249,9 @@ type TrustCenter implements Node
id: ID!
active: Boolean!
searchEngineIndexing: SearchEngineIndexing!
- logoFileUrl: String @goField(forceResolver: true)
- darkLogoFileUrl: String @goField(forceResolver: true)
- ndaFileName: String
- ndaFileUrl: String @goField(forceResolver: true)
+ logo: File @goField(forceResolver: true)
+ darkLogo: File @goField(forceResolver: true)
+ nda: File @goField(forceResolver: true)
createdAt: Datetime!
updatedAt: Datetime!
organization: Organization! @goField(forceResolver: true)
@@ -368,7 +367,7 @@ type TrustCenterReference implements Node {
name: String!
description: String
websiteUrl: String!
- logoUrl: String! @goField(forceResolver: true)
+ logo: File! @goField(forceResolver: true)
rank: Int!
createdAt: Datetime!
updatedAt: Datetime!
@@ -443,7 +442,7 @@ type TrustCenterFile implements Node {
id: ID!
name: String!
category: String!
- fileUrl: String! @goField(forceResolver: true)
+ file: File! @goField(forceResolver: true)
trustCenterVisibility: TrustCenterVisibility!
createdAt: Datetime!
updatedAt: Datetime!
diff --git a/pkg/server/api/console/v1/organization_resolvers.go b/pkg/server/api/console/v1/organization_resolvers.go
index d48dbedd6..f9471a930 100644
--- a/pkg/server/api/console/v1/organization_resolvers.go
+++ b/pkg/server/api/console/v1/organization_resolvers.go
@@ -9,7 +9,6 @@ import (
"context"
"errors"
"fmt"
- "time"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/agentrun"
@@ -58,36 +57,30 @@ func (r *mutationResolver) UpdateOrganizationContext(ctx context.Context, input
}, nil
}
-// LogoURL is the resolver for the logoUrl field.
-func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
- scope, err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGetLogoUrl)
- if err != nil {
+// Logo is the resolver for the logo field.
+func (r *organizationResolver) Logo(ctx context.Context, obj *types.Organization) (*types.File, error) {
+ if _, err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGetLogoUrl); err != nil {
return nil, err
}
- logoURL, err := r.probo.Organizations.GenerateLogoURL(ctx, scope, obj.ID, 1*time.Hour)
- if err != nil {
- r.logger.ErrorCtx(ctx, "cannot generate logo url", log.Error(err))
- return nil, gqlutils.Internal(ctx)
+ if obj.Logo == nil {
+ return nil, nil
}
- return logoURL, nil
+ return r.loadFile(ctx, obj.Logo.ID)
}
-// HorizontalLogoURL is the resolver for the horizontalLogoUrl field.
-func (r *organizationResolver) HorizontalLogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
- scope, err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGetHorizontalLogoUrl)
- if err != nil {
+// HorizontalLogo is the resolver for the horizontalLogo field.
+func (r *organizationResolver) HorizontalLogo(ctx context.Context, obj *types.Organization) (*types.File, error) {
+ if _, err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGetHorizontalLogoUrl); err != nil {
return nil, err
}
- horizontalLogoURL, err := r.probo.Organizations.GenerateHorizontalLogoURL(ctx, scope, obj.ID, 1*time.Hour)
- if err != nil {
- r.logger.ErrorCtx(ctx, "cannot generate horizontal logo url", log.Error(err))
- return nil, gqlutils.Internal(ctx)
+ if obj.HorizontalLogo == nil {
+ return nil, nil
}
- return horizontalLogoURL, nil
+ return r.loadFile(ctx, obj.HorizontalLogo.ID)
}
// Context is the resolver for the context field.
@@ -1175,16 +1168,7 @@ func (r *organizationResolver) TrustCenter(ctx context.Context, obj *types.Organ
return nil, gqlutils.Internal(ctx)
}
- var file *coredata.File
- if trustCenter.NonDisclosureAgreementFileID != nil {
- file, err = r.probo.Files.Get(ctx, scope, *trustCenter.NonDisclosureAgreementFileID)
- if err != nil {
- r.logger.ErrorCtx(ctx, "cannot get NDA file", log.Error(err))
- return nil, gqlutils.Internal(ctx)
- }
- }
-
- return types.NewTrustCenter(trustCenter, file), nil
+ return types.NewTrustCenter(trustCenter), nil
}
// CustomDomain is the resolver for the customDomain field.
diff --git a/pkg/server/api/console/v1/third_party_resolvers.go b/pkg/server/api/console/v1/third_party_resolvers.go
index 546ecae26..1cd22d1a6 100644
--- a/pkg/server/api/console/v1/third_party_resolvers.go
+++ b/pkg/server/api/console/v1/third_party_resolvers.go
@@ -9,7 +9,6 @@ import (
"context"
"errors"
"fmt"
- "time"
pgx "github.com/jackc/pgx/v5"
"github.com/vikstrous/dataloadgen"
@@ -359,7 +358,7 @@ func (r *mutationResolver) UploadThirdPartyBusinessAssociateAgreement(ctx contex
return nil, err
}
- thirdPartyBusinessAssociateAgreement, file, err := r.probo.ThirdPartyBusinessAssociateAgreements.Upload(
+ thirdPartyBusinessAssociateAgreement, _, err := r.probo.ThirdPartyBusinessAssociateAgreements.Upload(
ctx, scope,
input.ThirdPartyID,
&probo.ThirdPartyBusinessAssociateAgreementCreateRequest{
@@ -380,7 +379,7 @@ func (r *mutationResolver) UploadThirdPartyBusinessAssociateAgreement(ctx contex
}
return &types.UploadThirdPartyBusinessAssociateAgreementPayload{
- ThirdPartyBusinessAssociateAgreement: types.NewThirdPartyBusinessAssociateAgreement(thirdPartyBusinessAssociateAgreement, file),
+ ThirdPartyBusinessAssociateAgreement: types.NewThirdPartyBusinessAssociateAgreement(thirdPartyBusinessAssociateAgreement),
}, nil
}
@@ -391,7 +390,7 @@ func (r *mutationResolver) UpdateThirdPartyBusinessAssociateAgreement(ctx contex
return nil, err
}
- thirdPartyBusinessAssociateAgreement, file, err := r.probo.ThirdPartyBusinessAssociateAgreements.Update(
+ thirdPartyBusinessAssociateAgreement, _, err := r.probo.ThirdPartyBusinessAssociateAgreements.Update(
ctx, scope,
input.ThirdPartyID,
&probo.ThirdPartyBusinessAssociateAgreementUpdateRequest{
@@ -410,7 +409,7 @@ func (r *mutationResolver) UpdateThirdPartyBusinessAssociateAgreement(ctx contex
}
return &types.UpdateThirdPartyBusinessAssociateAgreementPayload{
- ThirdPartyBusinessAssociateAgreement: types.NewThirdPartyBusinessAssociateAgreement(thirdPartyBusinessAssociateAgreement, file),
+ ThirdPartyBusinessAssociateAgreement: types.NewThirdPartyBusinessAssociateAgreement(thirdPartyBusinessAssociateAgreement),
}, nil
}
@@ -438,7 +437,7 @@ func (r *mutationResolver) UploadThirdPartyDataPrivacyAgreement(ctx context.Cont
return nil, err
}
- thirdPartyDataPrivacyAgreement, file, err := r.probo.ThirdPartyDataPrivacyAgreements.Upload(
+ thirdPartyDataPrivacyAgreement, _, err := r.probo.ThirdPartyDataPrivacyAgreements.Upload(
ctx, scope,
input.ThirdPartyID,
&probo.ThirdPartyDataPrivacyAgreementCreateRequest{
@@ -459,7 +458,7 @@ func (r *mutationResolver) UploadThirdPartyDataPrivacyAgreement(ctx context.Cont
}
return &types.UploadThirdPartyDataPrivacyAgreementPayload{
- ThirdPartyDataPrivacyAgreement: types.NewThirdPartyDataPrivacyAgreement(thirdPartyDataPrivacyAgreement, file),
+ ThirdPartyDataPrivacyAgreement: types.NewThirdPartyDataPrivacyAgreement(thirdPartyDataPrivacyAgreement),
}, nil
}
@@ -470,7 +469,7 @@ func (r *mutationResolver) UpdateThirdPartyDataPrivacyAgreement(ctx context.Cont
return nil, err
}
- thirdPartyDataPrivacyAgreement, file, err := r.probo.ThirdPartyDataPrivacyAgreements.Update(
+ thirdPartyDataPrivacyAgreement, _, err := r.probo.ThirdPartyDataPrivacyAgreements.Update(
ctx, scope,
input.ThirdPartyID,
&probo.ThirdPartyDataPrivacyAgreementUpdateRequest{
@@ -489,7 +488,7 @@ func (r *mutationResolver) UpdateThirdPartyDataPrivacyAgreement(ctx context.Cont
}
return &types.UpdateThirdPartyDataPrivacyAgreementPayload{
- ThirdPartyDataPrivacyAgreement: types.NewThirdPartyDataPrivacyAgreement(thirdPartyDataPrivacyAgreement, file),
+ ThirdPartyDataPrivacyAgreement: types.NewThirdPartyDataPrivacyAgreement(thirdPartyDataPrivacyAgreement),
}, nil
}
@@ -667,7 +666,7 @@ func (r *thirdPartyResolver) BusinessAssociateAgreement(ctx context.Context, obj
return nil, err
}
- thirdPartyBusinessAssociateAgreement, file, err := r.probo.ThirdPartyBusinessAssociateAgreements.GetByThirdPartyID(ctx, scope, obj.ID)
+ thirdPartyBusinessAssociateAgreement, _, err := r.probo.ThirdPartyBusinessAssociateAgreements.GetByThirdPartyID(ctx, scope, obj.ID)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
@@ -678,7 +677,7 @@ func (r *thirdPartyResolver) BusinessAssociateAgreement(ctx context.Context, obj
return nil, gqlutils.Internal(ctx)
}
- return types.NewThirdPartyBusinessAssociateAgreement(thirdPartyBusinessAssociateAgreement, file), nil
+ return types.NewThirdPartyBusinessAssociateAgreement(thirdPartyBusinessAssociateAgreement), nil
}
// DataPrivacyAgreement is the resolver for the dataPrivacyAgreement field.
@@ -688,7 +687,7 @@ func (r *thirdPartyResolver) DataPrivacyAgreement(ctx context.Context, obj *type
return nil, err
}
- thirdPartyDataPrivacyAgreement, file, err := r.probo.ThirdPartyDataPrivacyAgreements.GetByThirdPartyID(ctx, scope, obj.ID)
+ thirdPartyDataPrivacyAgreement, _, err := r.probo.ThirdPartyDataPrivacyAgreements.GetByThirdPartyID(ctx, scope, obj.ID)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
@@ -699,7 +698,7 @@ func (r *thirdPartyResolver) DataPrivacyAgreement(ctx context.Context, obj *type
return nil, gqlutils.Internal(ctx)
}
- return types.NewThirdPartyDataPrivacyAgreement(thirdPartyDataPrivacyAgreement, file), nil
+ return types.NewThirdPartyDataPrivacyAgreement(thirdPartyDataPrivacyAgreement), nil
}
// Contacts is the resolver for the contacts field.
@@ -994,20 +993,13 @@ func (r *thirdPartyBusinessAssociateAgreementResolver) ThirdParty(ctx context.Co
return types.NewThirdParty(thirdParty), nil
}
-// FileURL is the resolver for the fileUrl field.
-func (r *thirdPartyBusinessAssociateAgreementResolver) FileURL(ctx context.Context, obj *types.ThirdPartyBusinessAssociateAgreement) (string, error) {
- scope, err := r.authorize(ctx, obj.ID, probo.ActionFileGet)
- if err != nil {
- return "", err
+// File is the resolver for the file field.
+func (r *thirdPartyBusinessAssociateAgreementResolver) File(ctx context.Context, obj *types.ThirdPartyBusinessAssociateAgreement) (*types.File, error) {
+ if _, err := r.authorize(ctx, obj.ID, probo.ActionFileGet); err != nil {
+ return nil, err
}
- fileURL, err := r.probo.ThirdPartyBusinessAssociateAgreements.GenerateFileURL(ctx, scope, obj.ID, 1*time.Hour)
- if err != nil {
- r.logger.ErrorCtx(ctx, "cannot generate file URL", log.Error(err))
- return "", gqlutils.Internal(ctx)
- }
-
- return fileURL, nil
+ return r.loadFile(ctx, obj.File.ID)
}
// Permission is the resolver for the permission field.
@@ -1185,20 +1177,13 @@ func (r *thirdPartyDataPrivacyAgreementResolver) ThirdParty(ctx context.Context,
return types.NewThirdParty(thirdParty), nil
}
-// FileURL is the resolver for the fileUrl field.
-func (r *thirdPartyDataPrivacyAgreementResolver) FileURL(ctx context.Context, obj *types.ThirdPartyDataPrivacyAgreement) (string, error) {
- scope, err := r.authorize(ctx, obj.ID, probo.ActionFileGet)
- if err != nil {
- return "", err
+// File is the resolver for the file field.
+func (r *thirdPartyDataPrivacyAgreementResolver) File(ctx context.Context, obj *types.ThirdPartyDataPrivacyAgreement) (*types.File, error) {
+ if _, err := r.authorize(ctx, obj.ID, probo.ActionFileGet); err != nil {
+ return nil, err
}
- fileURL, err := r.probo.ThirdPartyDataPrivacyAgreements.GenerateFileURL(ctx, scope, obj.ID, 1*time.Hour)
- if err != nil {
- r.logger.ErrorCtx(ctx, "cannot generate file URL", log.Error(err))
- return "", gqlutils.Internal(ctx)
- }
-
- return fileURL, nil
+ return r.loadFile(ctx, obj.File.ID)
}
// Permission is the resolver for the permission field.
diff --git a/pkg/server/api/console/v1/trust_center_resolvers.go b/pkg/server/api/console/v1/trust_center_resolvers.go
index da12687d2..6a4db6dd6 100644
--- a/pkg/server/api/console/v1/trust_center_resolvers.go
+++ b/pkg/server/api/console/v1/trust_center_resolvers.go
@@ -9,7 +9,6 @@ import (
"context"
"errors"
"fmt"
- "time"
"github.com/vikstrous/dataloadgen"
"go.gearno.de/kit/log"
@@ -63,7 +62,7 @@ func (r *mutationResolver) UpdateTrustCenter(ctx context.Context, input types.Up
return nil, err
}
- trustCenter, file, err := r.probo.TrustCenters.Update(
+ trustCenter, _, err := r.probo.TrustCenters.Update(
ctx, scope,
&probo.UpdateTrustCenterRequest{
ID: input.TrustCenterID,
@@ -82,7 +81,7 @@ func (r *mutationResolver) UpdateTrustCenter(ctx context.Context, input types.Up
}
return &types.UpdateTrustCenterPayload{
- TrustCenter: types.NewTrustCenter(trustCenter, file),
+ TrustCenter: types.NewTrustCenter(trustCenter),
}, nil
}
@@ -93,7 +92,7 @@ func (r *mutationResolver) UploadTrustCenterNda(ctx context.Context, input types
return nil, err
}
- trustCenter, file, err := r.probo.TrustCenters.UploadNDA(
+ trustCenter, _, err := r.probo.TrustCenters.UploadNDA(
ctx, scope,
&probo.UploadTrustCenterNDARequest{
TrustCenterID: input.TrustCenterID,
@@ -112,7 +111,7 @@ func (r *mutationResolver) UploadTrustCenterNda(ctx context.Context, input types
}
return &types.UploadTrustCenterNDAPayload{
- TrustCenter: types.NewTrustCenter(trustCenter, file),
+ TrustCenter: types.NewTrustCenter(trustCenter),
}, nil
}
@@ -123,14 +122,14 @@ func (r *mutationResolver) DeleteTrustCenterNda(ctx context.Context, input types
return nil, err
}
- trustCenter, file, err := r.probo.TrustCenters.DeleteNDA(ctx, scope, input.TrustCenterID)
+ trustCenter, _, err := r.probo.TrustCenters.DeleteNDA(ctx, scope, input.TrustCenterID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot delete trust center NDA", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return &types.DeleteTrustCenterNDAPayload{
- TrustCenter: types.NewTrustCenter(trustCenter, file),
+ TrustCenter: types.NewTrustCenter(trustCenter),
}, nil
}
@@ -179,7 +178,7 @@ func (r *mutationResolver) UpdateTrustCenterBrand(ctx context.Context, input typ
}
}
- trustCenter, file, err := r.probo.TrustCenters.UpdateTrustCenterBrand(ctx, scope, req)
+ trustCenter, _, err := r.probo.TrustCenters.UpdateTrustCenterBrand(ctx, scope, req)
if err != nil {
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
@@ -191,7 +190,7 @@ func (r *mutationResolver) UpdateTrustCenterBrand(ctx context.Context, input typ
}
return &types.UpdateTrustCenterBrandPayload{
- TrustCenter: types.NewTrustCenter(trustCenter, file),
+ TrustCenter: types.NewTrustCenter(trustCenter),
}, nil
}
@@ -689,59 +688,45 @@ func (r *mutationResolver) DeleteCustomDomain(ctx context.Context, input types.D
}, nil
}
-// LogoFileURL is the resolver for the logoFileUrl field.
-func (r *trustCenterResolver) LogoFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
- scope, err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterGet)
- if err != nil {
+// Logo is the resolver for the logo field.
+func (r *trustCenterResolver) Logo(ctx context.Context, obj *types.TrustCenter) (*types.File, error) {
+ if _, err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterGet); err != nil {
return nil, err
}
- logoURL, err := r.probo.TrustCenters.GenerateLogoURL(ctx, scope, obj.ID, 1*time.Hour)
- if err != nil {
- r.logger.ErrorCtx(ctx, "cannot generate logo url", log.Error(err))
- return nil, gqlutils.Internal(ctx)
+ if obj.Logo == nil {
+ return nil, nil
}
- return logoURL, nil
+ return r.loadFile(ctx, obj.Logo.ID)
}
-// DarkLogoFileURL is the resolver for the darkLogoFileUrl field.
-func (r *trustCenterResolver) DarkLogoFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
- scope, err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterGet)
- if err != nil {
+// DarkLogo is the resolver for the darkLogo field.
+func (r *trustCenterResolver) DarkLogo(ctx context.Context, obj *types.TrustCenter) (*types.File, error) {
+ if _, err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterGet); err != nil {
return nil, err
}
- logoURL, err := r.probo.TrustCenters.GenerateDarkLogoURL(ctx, scope, obj.ID, 1*time.Hour)
- if err != nil {
- r.logger.ErrorCtx(ctx, "cannot generate logo url", log.Error(err))
- return nil, gqlutils.Internal(ctx)
+ if obj.DarkLogo == nil {
+ return nil, nil
}
- return logoURL, nil
+ return r.loadFile(ctx, obj.DarkLogo.ID)
}
-// NdaFileURL is the resolver for the ndaFileUrl field.
-func (r *trustCenterResolver) NdaFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
+// Nda is the resolver for the nda field.
+func (r *trustCenterResolver) Nda(ctx context.Context, obj *types.TrustCenter) (*types.File, error) {
hasPermission, err := r.Resolver.Permission(ctx, obj, probo.ActionTrustCenterGetNda)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot authorize", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
- if !hasPermission {
+ if !hasPermission || obj.Nda == nil {
return nil, nil
}
- scope := coredata.NewScopeFromObjectID(obj.ID)
-
- fileURL, err := r.probo.TrustCenters.GenerateNDAFileURL(ctx, scope, obj.ID, 15*time.Minute)
- if err != nil {
- r.logger.ErrorCtx(ctx, "cannot generate NDA file URL", log.Error(err))
- return nil, gqlutils.Internal(ctx)
- }
-
- return fileURL, nil
+ return r.loadFile(ctx, obj.Nda.ID)
}
// Organization is the resolver for the organization field.
@@ -1143,20 +1128,13 @@ func (r *trustCenterDocumentAccessConnectionResolver) TotalCount(ctx context.Con
return count, nil
}
-// FileURL is the resolver for the fileUrl field.
-func (r *trustCenterFileResolver) FileURL(ctx context.Context, obj *types.TrustCenterFile) (string, error) {
- scope, err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterFileGetFileUrl)
- if err != nil {
- return "", err
+// File is the resolver for the file field.
+func (r *trustCenterFileResolver) File(ctx context.Context, obj *types.TrustCenterFile) (*types.File, error) {
+ if _, err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterFileGetFileUrl); err != nil {
+ return nil, err
}
- fileURL, err := r.probo.TrustCenterFiles.GenerateFileURL(ctx, scope, obj.ID, 1*time.Hour)
- if err != nil {
- r.logger.ErrorCtx(ctx, "cannot generate file URL", log.Error(err))
- return "", gqlutils.Internal(ctx)
- }
-
- return fileURL, nil
+ return r.loadFile(ctx, obj.File.ID)
}
// Organization is the resolver for the organization field.
@@ -1207,20 +1185,13 @@ func (r *trustCenterFileConnectionResolver) TotalCount(ctx context.Context, obj
return count, nil
}
-// LogoURL is the resolver for the logoUrl field.
-func (r *trustCenterReferenceResolver) LogoURL(ctx context.Context, obj *types.TrustCenterReference) (string, error) {
- scope, err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterReferenceGetLogoUrl)
- if err != nil {
- return "", err
+// Logo is the resolver for the logo field.
+func (r *trustCenterReferenceResolver) Logo(ctx context.Context, obj *types.TrustCenterReference) (*types.File, error) {
+ if _, err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterReferenceGetLogoUrl); err != nil {
+ return nil, err
}
- fileURL, err := r.probo.TrustCenterReferences.GenerateLogoURL(ctx, scope, obj.ID)
- if err != nil {
- r.logger.ErrorCtx(ctx, "cannot generate logo URL", log.Error(err))
- return "", gqlutils.Internal(ctx)
- }
-
- return fileURL, nil
+ return r.loadFile(ctx, obj.Logo.ID)
}
// Permission is the resolver for the permission field.
diff --git a/pkg/server/api/console/v1/types/common_third_party.go b/pkg/server/api/console/v1/types/common_third_party.go
index 439a4458c..05fc7cb51 100644
--- a/pkg/server/api/console/v1/types/common_third_party.go
+++ b/pkg/server/api/console/v1/types/common_third_party.go
@@ -34,13 +34,13 @@ type CommonThirdParty struct {
TrustPageURL *string `json:"trustPageUrl,omitempty"`
StatusPageURL *string `json:"statusPageUrl,omitempty"`
TermsOfServiceURL *string `json:"termsOfServiceUrl,omitempty"`
- LogoFileID *gid.GID `json:"logoFileId,omitempty"`
+ Logo *File `json:"logo,omitempty"`
}
func (CommonThirdParty) IsTrackerPatternThirdPartyLink() {}
func NewCommonThirdParty(c *coredata.CommonThirdParty) *CommonThirdParty {
- return &CommonThirdParty{
+ party := &CommonThirdParty{
ID: c.ID,
Name: c.Name,
Category: c.Category,
@@ -55,6 +55,11 @@ func NewCommonThirdParty(c *coredata.CommonThirdParty) *CommonThirdParty {
TrustPageURL: c.TrustPageURL,
StatusPageURL: c.StatusPageURL,
TermsOfServiceURL: c.TermsOfServiceURL,
- LogoFileID: c.LogoFileID,
}
+
+ if c.LogoFileID != nil {
+ party.Logo = &File{ID: *c.LogoFileID}
+ }
+
+ return party
}
diff --git a/pkg/server/api/console/v1/types/electronic_signature.go b/pkg/server/api/console/v1/types/electronic_signature.go
index 4e751cd16..759f8365c 100644
--- a/pkg/server/api/console/v1/types/electronic_signature.go
+++ b/pkg/server/api/console/v1/types/electronic_signature.go
@@ -19,7 +19,7 @@ import (
)
func NewElectronicSignature(es *coredata.ElectronicSignature) *ElectronicSignature {
- return &ElectronicSignature{
+ signature := &ElectronicSignature{
ID: es.ID,
Status: es.Status,
DocumentType: es.DocumentType,
@@ -29,6 +29,12 @@ func NewElectronicSignature(es *coredata.ElectronicSignature) *ElectronicSignatu
CreatedAt: es.CreatedAt,
UpdatedAt: es.UpdatedAt,
}
+
+ if es.CertificateFileID != nil {
+ signature.Certificate = &File{ID: *es.CertificateFileID}
+ }
+
+ return signature
}
func NewElectronicSignatureEvent(ev *coredata.ElectronicSignatureEvent) *ElectronicSignatureEvent {
diff --git a/pkg/server/api/console/v1/types/file.go b/pkg/server/api/console/v1/types/file.go
index 3dd2e25bf..44cdb8020 100644
--- a/pkg/server/api/console/v1/types/file.go
+++ b/pkg/server/api/console/v1/types/file.go
@@ -17,17 +17,11 @@ package types
import (
"go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/coredata"
+ "go.probo.inc/probo/pkg/filemanager"
)
func NewFile(r *coredata.File, base *baseurl.BaseURL) *File {
- var path string
- if r.Visibility == coredata.FileVisibilityPublic {
- path = "/api/files/v1/public/" + r.ID.String()
- } else {
- path = "/api/files/v1/" + r.ID.String()
- }
-
- url := base.WithPath(path).MustString()
+ url := base.WithPath(filemanager.DownloadAPIPath(r)).MustString()
return &File{
ID: r.ID,
diff --git a/pkg/server/api/console/v1/types/framework.go b/pkg/server/api/console/v1/types/framework.go
index ab718e7aa..4665a02bb 100644
--- a/pkg/server/api/console/v1/types/framework.go
+++ b/pkg/server/api/console/v1/types/framework.go
@@ -61,7 +61,7 @@ func NewFrameworkEdge(f *coredata.Framework, orderBy coredata.FrameworkOrderFiel
}
func NewFramework(f *coredata.Framework) *Framework {
- return &Framework{
+ framework := &Framework{
ID: f.ID,
Name: f.Name,
Organization: &Organization{
@@ -71,4 +71,14 @@ func NewFramework(f *coredata.Framework) *Framework {
CreatedAt: f.CreatedAt,
UpdatedAt: f.UpdatedAt,
}
+
+ if f.LightLogoFileID != nil {
+ framework.LightLogo = &File{ID: *f.LightLogoFileID}
+ }
+
+ if f.DarkLogoFileID != nil {
+ framework.DarkLogo = &File{ID: *f.DarkLogoFileID}
+ }
+
+ return framework
}
diff --git a/pkg/server/api/console/v1/types/organization.go b/pkg/server/api/console/v1/types/organization.go
index 78f4dbcd5..c58fa665c 100644
--- a/pkg/server/api/console/v1/types/organization.go
+++ b/pkg/server/api/console/v1/types/organization.go
@@ -34,6 +34,14 @@ func NewOrganization(o *coredata.Organization) *Organization {
UpdatedAt: o.UpdatedAt,
}
+ if o.LogoFileID != nil {
+ org.Logo = &File{ID: *o.LogoFileID}
+ }
+
+ if o.HorizontalLogoFileID != nil {
+ org.HorizontalLogo = &File{ID: *o.HorizontalLogoFileID}
+ }
+
if o.CustomDomainID != nil {
org.CustomDomain = &CustomDomain{
ID: *o.CustomDomainID,
diff --git a/pkg/server/api/console/v1/types/third_party_business_associate_agreement.go b/pkg/server/api/console/v1/types/third_party_business_associate_agreement.go
index 8e7f4ed3f..59126dfa8 100644
--- a/pkg/server/api/console/v1/types/third_party_business_associate_agreement.go
+++ b/pkg/server/api/console/v1/types/third_party_business_associate_agreement.go
@@ -18,7 +18,7 @@ import (
"go.probo.inc/probo/pkg/coredata"
)
-func NewThirdPartyBusinessAssociateAgreement(v *coredata.ThirdPartyBusinessAssociateAgreement, file *coredata.File) *ThirdPartyBusinessAssociateAgreement {
+func NewThirdPartyBusinessAssociateAgreement(v *coredata.ThirdPartyBusinessAssociateAgreement) *ThirdPartyBusinessAssociateAgreement {
return &ThirdPartyBusinessAssociateAgreement{
ID: v.ID,
ThirdParty: &ThirdParty{
@@ -26,8 +26,7 @@ func NewThirdPartyBusinessAssociateAgreement(v *coredata.ThirdPartyBusinessAssoc
},
ValidFrom: v.ValidFrom,
ValidUntil: v.ValidUntil,
- FileName: file.FileName,
- FileSize: file.FileSize,
+ File: &File{ID: v.FileID},
CreatedAt: v.CreatedAt,
UpdatedAt: v.UpdatedAt,
}
diff --git a/pkg/server/api/console/v1/types/third_party_data_privacy_agreement.go b/pkg/server/api/console/v1/types/third_party_data_privacy_agreement.go
index 97eef67f8..509857656 100644
--- a/pkg/server/api/console/v1/types/third_party_data_privacy_agreement.go
+++ b/pkg/server/api/console/v1/types/third_party_data_privacy_agreement.go
@@ -18,7 +18,7 @@ import (
"go.probo.inc/probo/pkg/coredata"
)
-func NewThirdPartyDataPrivacyAgreement(v *coredata.ThirdPartyDataPrivacyAgreement, file *coredata.File) *ThirdPartyDataPrivacyAgreement {
+func NewThirdPartyDataPrivacyAgreement(v *coredata.ThirdPartyDataPrivacyAgreement) *ThirdPartyDataPrivacyAgreement {
return &ThirdPartyDataPrivacyAgreement{
ID: v.ID,
ThirdParty: &ThirdParty{
@@ -26,8 +26,7 @@ func NewThirdPartyDataPrivacyAgreement(v *coredata.ThirdPartyDataPrivacyAgreemen
},
ValidFrom: v.ValidFrom,
ValidUntil: v.ValidUntil,
- FileName: file.FileName,
- FileSize: file.FileSize,
+ File: &File{ID: v.FileID},
CreatedAt: v.CreatedAt,
UpdatedAt: v.UpdatedAt,
}
diff --git a/pkg/server/api/console/v1/types/trust_center.go b/pkg/server/api/console/v1/types/trust_center.go
index f22b35ec6..83139eac3 100644
--- a/pkg/server/api/console/v1/types/trust_center.go
+++ b/pkg/server/api/console/v1/types/trust_center.go
@@ -25,10 +25,9 @@ type TrustCenter struct {
ID gid.GID `json:"id"`
Active bool `json:"active"`
SearchEngineIndexing coredata.SearchEngineIndexing `json:"searchEngineIndexing"`
- LogoFileURL *string `json:"logoFileUrl,omitempty"`
- DarkLogoFileURL *string `json:"darkLogoFileUrl,omitempty"`
- NdaFileName *string `json:"ndaFileName,omitempty"`
- NdaFileURL *string `json:"ndaFileUrl,omitempty"`
+ Logo *File `json:"logo,omitempty"`
+ DarkLogo *File `json:"darkLogo,omitempty"`
+ Nda *File `json:"nda,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Organization *Organization `json:"organization"`
@@ -43,21 +42,29 @@ type TrustCenter struct {
func (TrustCenter) IsNode() {}
func (t TrustCenter) GetID() gid.GID { return t.ID }
-func NewTrustCenter(tc *coredata.TrustCenter, file *coredata.File) *TrustCenter {
- var ndaFileName *string
- if file != nil {
- ndaFileName = &file.FileName
- }
-
- return &TrustCenter{
+func NewTrustCenter(tc *coredata.TrustCenter) *TrustCenter {
+ trustCenter := &TrustCenter{
ID: tc.ID,
Organization: &Organization{
ID: tc.OrganizationID,
},
Active: tc.Active,
SearchEngineIndexing: tc.SearchEngineIndexing,
- NdaFileName: ndaFileName,
CreatedAt: tc.CreatedAt,
UpdatedAt: tc.UpdatedAt,
}
+
+ if tc.LogoFileID != nil {
+ trustCenter.Logo = &File{ID: *tc.LogoFileID}
+ }
+
+ if tc.DarkLogoFileID != nil {
+ trustCenter.DarkLogo = &File{ID: *tc.DarkLogoFileID}
+ }
+
+ if tc.NonDisclosureAgreementFileID != nil {
+ trustCenter.Nda = &File{ID: *tc.NonDisclosureAgreementFileID}
+ }
+
+ return trustCenter
}
diff --git a/pkg/server/api/console/v1/types/trust_center_file.go b/pkg/server/api/console/v1/types/trust_center_file.go
index 92f96391f..313b5cc0c 100644
--- a/pkg/server/api/console/v1/types/trust_center_file.go
+++ b/pkg/server/api/console/v1/types/trust_center_file.go
@@ -34,6 +34,7 @@ func NewTrustCenterFile(tcf *coredata.TrustCenterFile) *TrustCenterFile {
ID: tcf.ID,
Name: tcf.Name,
Category: tcf.Category,
+ File: &File{ID: tcf.FileID},
TrustCenterVisibility: tcf.TrustCenterVisibility,
CreatedAt: tcf.CreatedAt,
UpdatedAt: tcf.UpdatedAt,
diff --git a/pkg/server/api/console/v1/types/trust_center_reference.go b/pkg/server/api/console/v1/types/trust_center_reference.go
index 428589161..ba846ade9 100644
--- a/pkg/server/api/console/v1/types/trust_center_reference.go
+++ b/pkg/server/api/console/v1/types/trust_center_reference.go
@@ -35,6 +35,7 @@ func NewTrustCenterReference(tcc *coredata.TrustCenterReference) *TrustCenterRef
Name: tcc.Name,
Description: tcc.Description,
WebsiteURL: tcc.WebsiteURL,
+ Logo: &File{ID: tcc.LogoFileID},
Rank: tcc.Rank,
CreatedAt: tcc.CreatedAt,
UpdatedAt: tcc.UpdatedAt,