Add document viewer with proper 404 handling for trust center
Move document download/view to a dedicated viewer page with PDF preview, access request flow, and a proper 404 error boundary when documents are not found. The backend now returns NOT_FOUND instead of INTERNAL for missing documents and reports. Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
@@ -874,7 +874,7 @@ type RecordSigningEventPayload {
|
||||
|
||||
type Query {
|
||||
viewer: Identity
|
||||
node(id: ID!): Node!
|
||||
node(id: ID!): Node
|
||||
currentTrustCenter: TrustCenter
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,9 @@ func (r *auditResolver) Report(ctx context.Context, obj *types.Audit) (*types.Re
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
report, err := trustService.Reports.Get(ctx, *audit.ReportID)
|
||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||
|
||||
report, err := trustService.Reports.Get(ctx, trustCenter.OrganizationID, *audit.ReportID)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot load report", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
@@ -91,7 +93,7 @@ func (r *documentResolver) IsUserAuthorized(ctx context.Context, obj *types.Docu
|
||||
trustService := r.TrustService(ctx, obj.ID.TenantID())
|
||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||
|
||||
document, err := trustService.Documents.Get(ctx, obj.ID)
|
||||
document, err := trustService.Documents.Get(ctx, trustCenter.OrganizationID, obj.ID)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot load document", log.Error(err))
|
||||
return false, gqlutils.Internal(ctx)
|
||||
@@ -355,7 +357,7 @@ func (r *mutationResolver) ExportDocumentPDF(ctx context.Context, input types.Ex
|
||||
trustService := r.TrustService(ctx, input.DocumentID.TenantID())
|
||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||
|
||||
document, err := trustService.Documents.Get(ctx, input.DocumentID)
|
||||
document, err := trustService.Documents.Get(ctx, trustCenter.OrganizationID, input.DocumentID)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot load document", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
@@ -462,8 +464,11 @@ func (r *mutationResolver) ExportTrustCenterFile(ctx context.Context, input type
|
||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||
trustService := r.TrustService(ctx, trustCenter.ID.TenantID())
|
||||
|
||||
trustCenterFile, err := trustService.TrustCenterFiles.Get(ctx, input.TrustCenterFileID)
|
||||
trustCenterFile, err := trustService.TrustCenterFiles.Get(ctx, trustCenter.OrganizationID, input.TrustCenterFileID)
|
||||
if err != nil {
|
||||
if errors.Is(err, trust.ErrTrustCenterFileNotFound) || errors.Is(err, trust.ErrTrustCenterFileNotVisible) {
|
||||
return nil, gqlutils.NotFoundf(ctx, "trust center file %q not found", input.TrustCenterFileID)
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot load trust center file", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
@@ -514,7 +519,7 @@ func (r *mutationResolver) RequestDocumentAccess(ctx context.Context, input type
|
||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||
trustService := r.TrustService(ctx, trustCenter.ID.TenantID())
|
||||
|
||||
document, err := trustService.Documents.Get(ctx, input.DocumentID)
|
||||
document, err := trustService.Documents.Get(ctx, trustCenter.OrganizationID, input.DocumentID)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot load document", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
@@ -597,8 +602,11 @@ func (r *mutationResolver) RequestTrustCenterFileAccess(ctx context.Context, inp
|
||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||
trustService := r.TrustService(ctx, trustCenter.ID.TenantID())
|
||||
|
||||
trustCenterFile, err := trustService.TrustCenterFiles.Get(ctx, input.TrustCenterFileID)
|
||||
trustCenterFile, err := trustService.TrustCenterFiles.Get(ctx, trustCenter.OrganizationID, input.TrustCenterFileID)
|
||||
if err != nil {
|
||||
if errors.Is(err, trust.ErrTrustCenterFileNotFound) || errors.Is(err, trust.ErrTrustCenterFileNotVisible) {
|
||||
return nil, gqlutils.NotFoundf(ctx, "trust center file %q not found", input.TrustCenterFileID)
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot load trust center file", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
@@ -852,8 +860,13 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
|
||||
return types.NewOrganization(organization), nil
|
||||
|
||||
case coredata.DocumentEntityType:
|
||||
document, err := trustService.Documents.Get(ctx, id)
|
||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||
|
||||
document, err := trustService.Documents.Get(ctx, trustCenter.OrganizationID, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, trust.ErrDocumentNotFound) || errors.Is(err, trust.ErrDocumentNotVisible) || errors.Is(err, coredata.ErrResourceNotFound) {
|
||||
return nil, gqlutils.NotFoundf(ctx, "node %q not found", id)
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot get document", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
@@ -868,8 +881,13 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
|
||||
return types.NewFramework(framework), nil
|
||||
|
||||
case coredata.ReportEntityType:
|
||||
report, err := trustService.Reports.Get(ctx, id)
|
||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||
|
||||
report, err := trustService.Reports.Get(ctx, trustCenter.OrganizationID, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, trust.ErrReportNotFound) || errors.Is(err, coredata.ErrResourceNotFound) {
|
||||
return nil, gqlutils.NotFoundf(ctx, "node %q not found", id)
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot get report", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
@@ -907,6 +925,20 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
|
||||
}
|
||||
return types.NewTrustCenterReference(reference), nil
|
||||
|
||||
case coredata.TrustCenterFileEntityType:
|
||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||
|
||||
trustCenterFile, err := trustService.TrustCenterFiles.Get(ctx, trustCenter.OrganizationID, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, trust.ErrTrustCenterFileNotFound) || errors.Is(err, trust.ErrTrustCenterFileNotVisible) {
|
||||
return nil, gqlutils.NotFoundf(ctx, "node %q not found", id)
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot get trust center file", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return types.NewTrustCenterFile(trustCenterFile), nil
|
||||
|
||||
default:
|
||||
return nil, gqlutils.NotFoundf(ctx, "node %q not found", id)
|
||||
}
|
||||
@@ -1251,8 +1283,11 @@ func (r *trustCenterFileResolver) IsUserAuthorized(ctx context.Context, obj *typ
|
||||
|
||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||
|
||||
trustCenterFile, err := trustService.TrustCenterFiles.Get(ctx, obj.ID)
|
||||
trustCenterFile, err := trustService.TrustCenterFiles.Get(ctx, trustCenter.OrganizationID, obj.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, trust.ErrTrustCenterFileNotFound) || errors.Is(err, trust.ErrTrustCenterFileNotVisible) {
|
||||
return false, gqlutils.NotFoundf(ctx, "trust center file %q not found", obj.ID)
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot load trust center file", log.Error(err))
|
||||
return false, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ func (s *DocumentService) ExportPDFWithoutWatermark(
|
||||
|
||||
func (s DocumentService) Get(
|
||||
ctx context.Context,
|
||||
organizationID gid.GID,
|
||||
documentID gid.GID,
|
||||
) (*coredata.Document, error) {
|
||||
document := &coredata.Document{}
|
||||
@@ -110,6 +111,14 @@ func (s DocumentService) Get(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if document.OrganizationID != organizationID {
|
||||
return nil, ErrDocumentNotFound
|
||||
}
|
||||
|
||||
if document.TrustCenterVisibility == coredata.TrustCenterVisibilityNone {
|
||||
return nil, ErrDocumentNotVisible
|
||||
}
|
||||
|
||||
return document, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -23,5 +23,10 @@ var (
|
||||
ErrUserNotFound = errors.New("user not found")
|
||||
ErrUserInactive = errors.New("user inactive")
|
||||
ErrDocumentAccessNotFound = errors.New("document access not found")
|
||||
ErrNDAFileNotFound = errors.New("NDA file not found")
|
||||
ErrNDAFileNotFound = errors.New("NDA file not found")
|
||||
ErrDocumentNotFound = errors.New("document not found")
|
||||
ErrDocumentNotVisible = errors.New("document not visible")
|
||||
ErrReportNotFound = errors.New("report not found")
|
||||
ErrTrustCenterFileNotFound = errors.New("trust center file not found")
|
||||
ErrTrustCenterFileNotVisible = errors.New("trust center file not visible")
|
||||
)
|
||||
|
||||
@@ -33,6 +33,23 @@ type ReportService struct {
|
||||
}
|
||||
|
||||
func (s ReportService) Get(
|
||||
ctx context.Context,
|
||||
organizationID gid.GID,
|
||||
reportID gid.GID,
|
||||
) (*coredata.Report, error) {
|
||||
report, err := s.loadByID(ctx, reportID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if report.OrganizationID != organizationID {
|
||||
return nil, ErrReportNotFound
|
||||
}
|
||||
|
||||
return report, nil
|
||||
}
|
||||
|
||||
func (s ReportService) loadByID(
|
||||
ctx context.Context,
|
||||
reportID gid.GID,
|
||||
) (*coredata.Report, error) {
|
||||
@@ -62,7 +79,7 @@ func (s ReportService) GenerateDownloadURL(
|
||||
reportID gid.GID,
|
||||
expiresIn time.Duration,
|
||||
) (*string, error) {
|
||||
report, err := s.Get(ctx, reportID)
|
||||
report, err := s.loadByID(ctx, reportID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get report: %w", err)
|
||||
}
|
||||
@@ -114,7 +131,7 @@ func (s ReportService) exportPDFData(
|
||||
ctx context.Context,
|
||||
reportID gid.GID,
|
||||
) ([]byte, error) {
|
||||
report, err := s.Get(ctx, reportID)
|
||||
report, err := s.loadByID(ctx, reportID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get report: %w", err)
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ type TrustCenterFileService struct {
|
||||
|
||||
func (s *TrustCenterFileService) Get(
|
||||
ctx context.Context,
|
||||
organizationID gid.GID,
|
||||
trustCenterFileID gid.GID,
|
||||
) (*coredata.TrustCenterFile, error) {
|
||||
trustCenterFile := &coredata.TrustCenterFile{}
|
||||
@@ -54,6 +55,14 @@ func (s *TrustCenterFileService) Get(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if trustCenterFile.OrganizationID != organizationID {
|
||||
return nil, ErrTrustCenterFileNotFound
|
||||
}
|
||||
|
||||
if trustCenterFile.TrustCenterVisibility == coredata.TrustCenterVisibilityNone {
|
||||
return nil, ErrTrustCenterFileNotVisible
|
||||
}
|
||||
|
||||
return trustCenterFile, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user