Adopt File type for trust logos and MCP
Trust GraphQL and MCP still exposed presigned URL strings for trust-center logos while console and connect already serve stable File.downloadUrl paths. Phase 1 migrates the seven public logo fields on trust GraphQL and the trust-center file references on MCP to the shared File type; trust GraphQL NDA stays on fileUrl for a follow-up. Trust resolvers load public files through filemanager and map them with types.NewFile. The trust app Relay queries and components now read logo.downloadUrl. MCP specification, resolvers, and helpers are updated in sync, including NDA on MCP where callers already have file access. filemanager is split into focused files and its URL surface is narrowed to GenerateFileURL(file) for stable app URLs and GeneratePresignedURL for S3 redirects. GetPublicFile remains the DB entry point when only a file ID is known. Add trust and MCP e2e coverage for public logo download URLs. Signed-off-by: Ludovic Vielle <ludovic@probo.com>
This commit is contained in:
@@ -66,8 +66,12 @@ const auditRowFragment = graphql`
|
||||
framework {
|
||||
id
|
||||
name
|
||||
lightLogoURL
|
||||
darkLogoURL
|
||||
lightLogo {
|
||||
downloadUrl
|
||||
}
|
||||
darkLogo {
|
||||
downloadUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -176,8 +180,8 @@ export function AuditRowAvatar(props: { audit: AuditRowFragment$key }) {
|
||||
<div className="flex flex-col gap-2 items-center w-19">
|
||||
<FrameworkLogo
|
||||
className="size-19"
|
||||
lightLogoURL={audit.framework.lightLogoURL}
|
||||
darkLogoURL={audit.framework.darkLogoURL}
|
||||
lightLogoURL={audit.framework.lightLogo?.downloadUrl}
|
||||
darkLogoURL={audit.framework.darkLogo?.downloadUrl}
|
||||
name={audit.framework.name}
|
||||
/>
|
||||
<div className="txt-primary text-sm max-w-19 overflow-hidden min-w-0 whitespace-nowrap text-ellipsis">
|
||||
@@ -215,8 +219,8 @@ function AuditDialog(
|
||||
<DialogContent className="p-4 lg:p-8 space-y-6">
|
||||
<FrameworkLogo
|
||||
className="size-24 mx-auto"
|
||||
lightLogoURL={audit.framework.lightLogoURL}
|
||||
darkLogoURL={audit.framework.darkLogoURL}
|
||||
lightLogoURL={audit.framework.lightLogo?.downloadUrl}
|
||||
darkLogoURL={audit.framework.darkLogo?.downloadUrl}
|
||||
name={audit.framework.name}
|
||||
/>
|
||||
<h2 className="text-xl font-semibold mb-1">{audit.framework.name}</h2>
|
||||
|
||||
@@ -23,8 +23,12 @@ const frameworkFragment = graphql`
|
||||
# eslint-disable-next-line relay/unused-fields
|
||||
id
|
||||
name
|
||||
lightLogoURL
|
||||
darkLogoURL
|
||||
lightLogo {
|
||||
downloadUrl
|
||||
}
|
||||
darkLogo {
|
||||
downloadUrl
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -35,8 +39,8 @@ export function FrameworkBadge(props: { framework: FrameworkBadgeFragment$key })
|
||||
<div className="flex flex-col gap-2 items-center w-19">
|
||||
<FrameworkLogo
|
||||
className="size-19"
|
||||
lightLogoURL={framework.lightLogoURL}
|
||||
darkLogoURL={framework.darkLogoURL}
|
||||
lightLogoURL={framework.lightLogo?.downloadUrl}
|
||||
darkLogoURL={framework.darkLogo?.downloadUrl}
|
||||
name={framework.name}
|
||||
/>
|
||||
<div className="txt-primary text-xs max-w-19 min-w-0 text-center">
|
||||
|
||||
@@ -85,7 +85,9 @@ export function OrganizationSidebar({
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
const logoFileUrl = theme === "dark" ? (trustCenter?.darkLogoFileUrl ?? trustCenter?.logoFileUrl) : trustCenter?.logoFileUrl;
|
||||
const logoFileUrl = theme === "dark"
|
||||
? (trustCenter?.darkLogo?.downloadUrl ?? trustCenter?.logo?.downloadUrl)
|
||||
: trustCenter?.logo?.downloadUrl;
|
||||
|
||||
const [requestAllAccesses, isRequestingAccess]
|
||||
= useMutation<OrganizationSidebar_requestAllAccessesMutation>(
|
||||
|
||||
@@ -38,8 +38,8 @@ export function MainLayout(props: Props) {
|
||||
|
||||
useFavicon(
|
||||
theme === "dark"
|
||||
? (trustCenter?.darkLogoFileUrl ?? trustCenter?.logoFileUrl)
|
||||
: trustCenter?.logoFileUrl,
|
||||
? (trustCenter?.darkLogo?.downloadUrl ?? trustCenter?.logo?.downloadUrl)
|
||||
: trustCenter?.logo?.downloadUrl,
|
||||
);
|
||||
useRequestAccessCallback();
|
||||
|
||||
|
||||
@@ -47,8 +47,12 @@ import type { DocumentPageRequestTrustCenterFileAccessMutation } from "./__gener
|
||||
export const documentPageQuery = graphql`
|
||||
query DocumentPageQuery($id: ID!) {
|
||||
currentTrustCenter {
|
||||
logoFileUrl
|
||||
darkLogoFileUrl
|
||||
logo {
|
||||
downloadUrl
|
||||
}
|
||||
darkLogo {
|
||||
downloadUrl
|
||||
}
|
||||
}
|
||||
node(id: $id) @required(action: THROW) {
|
||||
__typename
|
||||
@@ -230,8 +234,8 @@ export function DocumentPage({ queryRef }: Props) {
|
||||
const nodeId = getNodeId(node);
|
||||
|
||||
const logoFileUrl = theme === "dark"
|
||||
? (trustCenter?.darkLogoFileUrl ?? trustCenter?.logoFileUrl)
|
||||
: trustCenter?.logoFileUrl;
|
||||
? (trustCenter?.darkLogo?.downloadUrl ?? trustCenter?.logo?.downloadUrl)
|
||||
: trustCenter?.logo?.downloadUrl;
|
||||
|
||||
const [exportDocument, isExportingDocument]
|
||||
= useMutation<DocumentPageExportDocumentMutation>(exportDocumentMutation);
|
||||
|
||||
@@ -46,7 +46,9 @@ const overviewFragment = graphql`
|
||||
node {
|
||||
id
|
||||
name
|
||||
logoUrl
|
||||
logo {
|
||||
downloadUrl
|
||||
}
|
||||
websiteUrl
|
||||
}
|
||||
}
|
||||
@@ -223,7 +225,7 @@ function Subprocessors({
|
||||
|
||||
type Reference = {
|
||||
name: string;
|
||||
logoUrl: string;
|
||||
logo: { downloadUrl: string } | null;
|
||||
websiteUrl: string;
|
||||
id: string;
|
||||
};
|
||||
@@ -248,7 +250,7 @@ function References({ references }: { references: Reference[] }) {
|
||||
className="flex flex-col justify-center items-center gap-2"
|
||||
>
|
||||
<img
|
||||
src={reference.logoUrl}
|
||||
src={reference.logo?.downloadUrl}
|
||||
alt={reference.name}
|
||||
className="rounded-2xl size-12 block"
|
||||
/>
|
||||
|
||||
@@ -23,8 +23,12 @@ import type { AuthLayoutQuery } from "./__generated__/AuthLayoutQuery.graphql";
|
||||
export const authLayoutQuery = graphql`
|
||||
query AuthLayoutQuery {
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
logoFileUrl
|
||||
darkLogoFileUrl
|
||||
logo {
|
||||
downloadUrl
|
||||
}
|
||||
darkLogo {
|
||||
downloadUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -36,8 +40,8 @@ export function AuthLayout(props: { queryRef: PreloadedQuery<AuthLayoutQuery> })
|
||||
const theme = useSystemTheme();
|
||||
|
||||
const logoFileUrl = theme === "dark"
|
||||
? compliancePage.darkLogoFileUrl ?? compliancePage.logoFileUrl
|
||||
: compliancePage.logoFileUrl;
|
||||
? compliancePage.darkLogo?.downloadUrl ?? compliancePage.logo?.downloadUrl
|
||||
: compliancePage.logo?.downloadUrl;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen text-txt-primary bg-level-0 flex flex-col items-center justify-center">
|
||||
|
||||
@@ -31,8 +31,12 @@ export const currentTrustGraphQuery = graphql`
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
logoFileUrl
|
||||
darkLogoFileUrl
|
||||
logo {
|
||||
downloadUrl
|
||||
}
|
||||
darkLogo {
|
||||
downloadUrl
|
||||
}
|
||||
nonDisclosureAgreement {
|
||||
fileName
|
||||
fileUrl
|
||||
|
||||
Reference in New Issue
Block a user