diff --git a/pkg/coredata/file.go b/pkg/coredata/file.go index 3713dd873..ad2c181d5 100644 --- a/pkg/coredata/file.go +++ b/pkg/coredata/file.go @@ -30,16 +30,17 @@ import ( type ( File struct { - ID gid.GID `db:"id"` - OrganizationID gid.GID `db:"organization_id"` - BucketName string `db:"bucket_name"` - MimeType string `db:"mime_type"` - FileName string `db:"file_name"` - FileKey string `db:"file_key"` - FileSize int64 `db:"file_size"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` - DeletedAt *time.Time `db:"deleted_at"` + ID gid.GID `db:"id"` + OrganizationID gid.GID `db:"organization_id"` + BucketName string `db:"bucket_name"` + MimeType string `db:"mime_type"` + FileName string `db:"file_name"` + FileKey string `db:"file_key"` + FileSize int64 `db:"file_size"` + Visibility FileVisibility `db:"visibility"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` + DeletedAt *time.Time `db:"deleted_at"` } Files []*File @@ -93,6 +94,7 @@ SELECT file_name, file_key, file_size, + visibility, created_at, updated_at, deleted_at @@ -145,6 +147,7 @@ INSERT INTO file_name, file_key, file_size, + visibility, created_at, updated_at, deleted_at @@ -158,6 +161,7 @@ VALUES ( @file_name, @file_key, @file_size, + @visibility, @created_at, @updated_at, @deleted_at @@ -173,6 +177,7 @@ VALUES ( "file_name": f.FileName, "file_key": f.FileKey, "file_size": f.FileSize, + "visibility": f.Visibility, "created_at": f.CreatedAt, "updated_at": f.UpdatedAt, "deleted_at": f.DeletedAt, @@ -192,6 +197,55 @@ VALUES ( return nil } +func (f *File) LoadPublicByID( + ctx context.Context, + conn pg.Conn, + fileID gid.GID, +) error { + q := ` +SELECT + id, + organization_id, + bucket_name, + mime_type, + file_name, + file_key, + file_size, + visibility, + created_at, + updated_at, + deleted_at +FROM + files +WHERE + id = @file_id + AND visibility = 'PUBLIC' + AND deleted_at IS NULL +LIMIT 1; +` + + args := pgx.StrictNamedArgs{"file_id": fileID} + + rows, err := conn.Query(ctx, q, args) + if err != nil { + return fmt.Errorf("cannot query file: %w", err) + } + defer rows.Close() + + file, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[File]) + if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + return ErrResourceNotFound + } + + return fmt.Errorf("cannot collect file: %w", err) + } + + *f = file + + return nil +} + func (f File) SoftDelete(ctx context.Context, conn pg.Conn, scope Scoper) error { q := ` UPDATE files diff --git a/pkg/coredata/file_visibility.go b/pkg/coredata/file_visibility.go new file mode 100644 index 000000000..aba204f5e --- /dev/null +++ b/pkg/coredata/file_visibility.go @@ -0,0 +1,57 @@ +// 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 coredata + +import ( + "database/sql/driver" + "fmt" +) + +type FileVisibility string + +const ( + FileVisibilityPrivate FileVisibility = "PRIVATE" + FileVisibilityPublic FileVisibility = "PUBLIC" +) + +func (fv FileVisibility) String() string { + return string(fv) +} + +func (fv *FileVisibility) Scan(value any) error { + var s string + switch v := value.(type) { + case string: + s = v + case []byte: + s = string(v) + default: + return fmt.Errorf("unsupported type for FileVisibility: %T", value) + } + + switch s { + case "PRIVATE": + *fv = FileVisibilityPrivate + case "PUBLIC": + *fv = FileVisibilityPublic + default: + return fmt.Errorf("invalid FileVisibility value: %q", s) + } + return nil +} + +func (fv FileVisibility) Value() (driver.Value, error) { + return fv.String(), nil +} diff --git a/pkg/coredata/migrations/20260318T120000Z.sql b/pkg/coredata/migrations/20260318T120000Z.sql new file mode 100644 index 000000000..0f045ff00 --- /dev/null +++ b/pkg/coredata/migrations/20260318T120000Z.sql @@ -0,0 +1,41 @@ +-- 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. + +ALTER TABLE files ADD COLUMN visibility TEXT NOT NULL DEFAULT 'PRIVATE'; + +-- Backfill trust center logos to PUBLIC +UPDATE files SET visibility = 'PUBLIC' +WHERE id IN ( + SELECT logo_file_id FROM trust_centers WHERE logo_file_id IS NOT NULL + UNION + SELECT dark_logo_file_id FROM trust_centers WHERE dark_logo_file_id IS NOT NULL +); + +-- Backfill organization logos to PUBLIC +UPDATE files SET visibility = 'PUBLIC' +WHERE id IN ( + SELECT logo_file_id FROM organizations WHERE logo_file_id IS NOT NULL + UNION + SELECT horizontal_logo_file_id FROM organizations WHERE horizontal_logo_file_id IS NOT NULL +); + +-- Backfill framework logos to PUBLIC +UPDATE files SET visibility = 'PUBLIC' +WHERE id IN ( + SELECT light_logo_file_id FROM frameworks WHERE light_logo_file_id IS NOT NULL + UNION + SELECT dark_logo_file_id FROM frameworks WHERE dark_logo_file_id IS NOT NULL +); + +ALTER TABLE files ALTER COLUMN visibility DROP DEFAULT; diff --git a/pkg/esign/completion_certificate_worker.go b/pkg/esign/completion_certificate_worker.go index ddf826ad8..ab6f76d5b 100644 --- a/pkg/esign/completion_certificate_worker.go +++ b/pkg/esign/completion_certificate_worker.go @@ -271,6 +271,7 @@ func (w *CompletionCertificateWorker) generateCertificate( MimeType: "application/pdf", FileName: certificateFilename, FileKey: uuid.MustNewV4().String(), + Visibility: coredata.FileVisibilityPrivate, CreatedAt: time.Now(), UpdatedAt: time.Now(), } diff --git a/pkg/esign/service.go b/pkg/esign/service.go index 2437a6779..104e5e0bc 100644 --- a/pkg/esign/service.go +++ b/pkg/esign/service.go @@ -209,6 +209,7 @@ func (s *Service) createStampedDocument( MimeType: "application/pdf", FileName: originalFile.FileName, FileKey: uuid.MustNewV4().String(), + Visibility: coredata.FileVisibilityPrivate, CreatedAt: now, UpdatedAt: now, } diff --git a/pkg/file/service.go b/pkg/file/service.go new file mode 100644 index 000000000..7f1845484 --- /dev/null +++ b/pkg/file/service.go @@ -0,0 +1,67 @@ +// 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 file + +import ( + "context" + "fmt" + "time" + + "go.gearno.de/kit/pg" + "go.probo.inc/probo/pkg/coredata" + "go.probo.inc/probo/pkg/filemanager" + "go.probo.inc/probo/pkg/gid" +) + +type Service struct { + pg *pg.Client + fileManager *filemanager.Service +} + +func NewService(pgClient *pg.Client, fileManager *filemanager.Service) *Service { + return &Service{ + pg: pgClient, + fileManager: fileManager, + } +} + +func (s *Service) GetPublicFileURL( + ctx context.Context, + fileID gid.GID, + expiresIn time.Duration, +) (string, error) { + file := &coredata.File{} + + err := s.pg.WithConn( + ctx, + func(conn pg.Conn) error { + if err := file.LoadPublicByID(ctx, conn, fileID); err != nil { + return fmt.Errorf("cannot load public file: %w", err) + } + + return nil + }, + ) + if err != nil { + return "", err + } + + presignedURL, err := s.fileManager.GenerateFileUrl(ctx, file, expiresIn) + if err != nil { + return "", fmt.Errorf("cannot generate file URL: %w", err) + } + + return presignedURL, nil +} diff --git a/pkg/iam/organization_service.go b/pkg/iam/organization_service.go index 4e2627917..2a87061f9 100644 --- a/pkg/iam/organization_service.go +++ b/pkg/iam/organization_service.go @@ -521,6 +521,7 @@ func (s *OrganizationService) CreateOrganization( FileName: filename, FileKey: objectKey.String(), FileSize: req.LogoFile.Size, + Visibility: coredata.FileVisibilityPublic, CreatedAt: now, UpdatedAt: now, } @@ -558,6 +559,7 @@ func (s *OrganizationService) CreateOrganization( FileName: filename, FileKey: objectKey.String(), FileSize: req.HorizontalLogoFile.Size, + Visibility: coredata.FileVisibilityPublic, CreatedAt: now, UpdatedAt: now, } @@ -698,6 +700,7 @@ func (s *OrganizationService) UpdateOrganization(ctx context.Context, organizati FileName: filename, FileKey: objectKey.String(), FileSize: (*req.LogoFile).Size, + Visibility: coredata.FileVisibilityPublic, CreatedAt: now, UpdatedAt: now, } @@ -735,6 +738,7 @@ func (s *OrganizationService) UpdateOrganization(ctx context.Context, organizati FileName: filename, FileKey: objectKey.String(), FileSize: (*req.HorizontalLogoFile).Size, + Visibility: coredata.FileVisibilityPublic, CreatedAt: now, UpdatedAt: now, } diff --git a/pkg/probo/document_service.go b/pkg/probo/document_service.go index 39b9cef0a..d42af78c4 100644 --- a/pkg/probo/document_service.go +++ b/pkg/probo/document_service.go @@ -1767,6 +1767,7 @@ func (s *DocumentService) BuildAndUploadExport(ctx context.Context, exportJobID FileName: fmt.Sprintf("Documents Export %s.zip", now.Format("2006-01-02")), FileKey: uuid.String(), FileSize: fileInfo.Size(), + Visibility: coredata.FileVisibilityPrivate, CreatedAt: now, UpdatedAt: now, } diff --git a/pkg/probo/file_service.go b/pkg/probo/file_service.go index f568b6b88..bbf74fbc4 100644 --- a/pkg/probo/file_service.go +++ b/pkg/probo/file_service.go @@ -142,6 +142,7 @@ func (s FileService) UploadAndSaveFile( FileName: req.Filename, FileKey: objectKey.String(), FileSize: *headOutput.ContentLength, + Visibility: coredata.FileVisibilityPrivate, CreatedAt: now, UpdatedAt: now, } diff --git a/pkg/probo/framework_service.go b/pkg/probo/framework_service.go index 50b4aefa8..a3e26b11e 100644 --- a/pkg/probo/framework_service.go +++ b/pkg/probo/framework_service.go @@ -534,6 +534,7 @@ func (s FrameworkService) Import( MimeType: contentType, FileName: filename, FileKey: objectKey.String(), + Visibility: coredata.FileVisibilityPublic, CreatedAt: now, UpdatedAt: now, } @@ -761,6 +762,7 @@ func (s *FrameworkService) BuildAndUploadExport(ctx context.Context, exportJobID FileName: fmt.Sprintf("Framework Export %s.zip", now.Format("2006-01-02")), FileKey: uuid.String(), FileSize: fileInfo.Size(), + Visibility: coredata.FileVisibilityPrivate, CreatedAt: now, UpdatedAt: now, } diff --git a/pkg/probo/organization_service.go b/pkg/probo/organization_service.go index 19ceb62b7..ed8145340 100644 --- a/pkg/probo/organization_service.go +++ b/pkg/probo/organization_service.go @@ -257,6 +257,7 @@ func (s OrganizationService) Update( MimeType: contentType, FileName: filename, FileKey: objectKey.String(), + Visibility: coredata.FileVisibilityPublic, CreatedAt: now, UpdatedAt: now, } @@ -317,6 +318,7 @@ func (s OrganizationService) Update( MimeType: contentType, FileName: filename, FileKey: objectKey.String(), + Visibility: coredata.FileVisibilityPublic, CreatedAt: now, UpdatedAt: now, } diff --git a/pkg/probo/trust_center_file_service.go b/pkg/probo/trust_center_file_service.go index 693e81024..324c56f06 100644 --- a/pkg/probo/trust_center_file_service.go +++ b/pkg/probo/trust_center_file_service.go @@ -396,6 +396,7 @@ func (s TrustCenterFileService) uploadFile( FileName: filename, FileKey: objectKey.String(), FileSize: fileSize, + Visibility: coredata.FileVisibilityPrivate, CreatedAt: now, UpdatedAt: now, } diff --git a/pkg/probo/trust_center_reference_service.go b/pkg/probo/trust_center_reference_service.go index 6c7e587ba..7cdf30801 100644 --- a/pkg/probo/trust_center_reference_service.go +++ b/pkg/probo/trust_center_reference_service.go @@ -416,6 +416,7 @@ func (s TrustCenterReferenceService) uploadLogoFile( FileName: filename, FileKey: objectKey.String(), FileSize: fileSize, + Visibility: coredata.FileVisibilityPublic, CreatedAt: now, UpdatedAt: now, } diff --git a/pkg/probo/trust_center_service.go b/pkg/probo/trust_center_service.go index 3d57597c9..a8bd3c85f 100644 --- a/pkg/probo/trust_center_service.go +++ b/pkg/probo/trust_center_service.go @@ -262,6 +262,7 @@ func (s TrustCenterService) UploadNDA( FileName: req.FileName, FileKey: objectKey.String(), FileSize: *headOutput.ContentLength, + Visibility: coredata.FileVisibilityPrivate, CreatedAt: now, UpdatedAt: now, } @@ -441,6 +442,7 @@ func (s TrustCenterService) uploadFile( FileName: fileUpload.Filename, FileKey: objectKey.String(), FileSize: *headOutput.ContentLength, + Visibility: coredata.FileVisibilityPublic, CreatedAt: now, UpdatedAt: now, } diff --git a/pkg/probo/vendor_business_associate_agreement_service.go b/pkg/probo/vendor_business_associate_agreement_service.go index 9b9833878..9b115be53 100644 --- a/pkg/probo/vendor_business_associate_agreement_service.go +++ b/pkg/probo/vendor_business_associate_agreement_service.go @@ -159,6 +159,7 @@ func (s VendorBusinessAssociateAgreementService) Upload( FileName: req.FileName, FileKey: objectKey.String(), FileSize: *headOutput.ContentLength, + Visibility: coredata.FileVisibilityPrivate, CreatedAt: now, UpdatedAt: now, } diff --git a/pkg/probo/vendor_data_privacy_agreement_service.go b/pkg/probo/vendor_data_privacy_agreement_service.go index 815f0016c..c683b85ac 100644 --- a/pkg/probo/vendor_data_privacy_agreement_service.go +++ b/pkg/probo/vendor_data_privacy_agreement_service.go @@ -157,6 +157,7 @@ func (s VendorDataPrivacyAgreementService) Upload( FileName: req.FileName, FileKey: objectKey.String(), FileSize: *headOutput.ContentLength, + Visibility: coredata.FileVisibilityPrivate, CreatedAt: now, UpdatedAt: now, } diff --git a/pkg/probod/probod.go b/pkg/probod/probod.go index 8e63a551a..7c4a238ca 100644 --- a/pkg/probod/probod.go +++ b/pkg/probod/probod.go @@ -57,6 +57,7 @@ import ( "go.probo.inc/probo/pkg/mailer" "go.probo.inc/probo/pkg/mailman" "go.probo.inc/probo/pkg/probo" + "go.probo.inc/probo/pkg/file" "go.probo.inc/probo/pkg/securecookie" "go.probo.inc/probo/pkg/server" "go.probo.inc/probo/pkg/slack" @@ -473,11 +474,14 @@ func (impl *Implm) Run( slackService, ) + fileService := file.NewService(pgClient, fileManagerService) + serverHandler, err := server.NewServer( server.Config{ AllowedOrigins: impl.cfg.Api.Cors.AllowedOrigins, ExtraHeaderFields: impl.cfg.Api.ExtraHeaderFields, Probo: proboService, + File: fileService, IAM: iamService, Trust: trustService, ESign: esignService, diff --git a/pkg/server/api/api.go b/pkg/server/api/api.go index 89939c97e..7a302a343 100644 --- a/pkg/server/api/api.go +++ b/pkg/server/api/api.go @@ -29,9 +29,11 @@ import ( "go.probo.inc/probo/pkg/iam" "go.probo.inc/probo/pkg/mailman" "go.probo.inc/probo/pkg/probo" + "go.probo.inc/probo/pkg/file" "go.probo.inc/probo/pkg/securecookie" connect_v1 "go.probo.inc/probo/pkg/server/api/connect/v1" console_v1 "go.probo.inc/probo/pkg/server/api/console/v1" + files_v1 "go.probo.inc/probo/pkg/server/api/files/v1" mcp_v1 "go.probo.inc/probo/pkg/server/api/mcp/v1" slack_v1 "go.probo.inc/probo/pkg/server/api/slack/v1" trust_v1 "go.probo.inc/probo/pkg/server/api/trust/v1" @@ -44,6 +46,7 @@ type ( BaseURL *baseurl.BaseURL AllowedOrigins []string Probo *probo.Service + File *file.Service IAM *iam.Service Trust *trust.Service ESign *esign.Service @@ -66,6 +69,7 @@ type ( cfg Config compliancePageHandler http.Handler consoleHandler http.Handler + filesHandler http.Handler mcpHandler http.Handler slackHandler http.Handler connectHandler http.Handler @@ -139,6 +143,10 @@ func NewServer(cfg Config) (*Server, error) { cfg.BaseURL, cfg.CustomDomainCname, ), + filesHandler: files_v1.NewMux( + cfg.Logger.Named("files.v1"), + cfg.File, + ), mcpHandler: mcp_v1.NewMux( cfg.Logger.Named("mcp.v1"), cfg.Probo, @@ -191,6 +199,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { router.Mount("/console/v1", http.StripPrefix("/console/v1", s.consoleHandler)) router.Mount("/connect/v1", http.StripPrefix("/connect/v1", s.connectHandler)) + router.Mount("/files/v1", http.StripPrefix("/files/v1", s.filesHandler)) router.Mount("/trust/v1", http.StripPrefix("/trust/v1", s.compliancePageHandler)) router.Mount("/mcp/v1", http.StripPrefix("/mcp/v1", s.mcpHandler)) router.Mount("/slack/v1", http.StripPrefix("/slack/v1", s.slackHandler)) diff --git a/pkg/server/api/files/v1/handler.go b/pkg/server/api/files/v1/handler.go new file mode 100644 index 000000000..08d24fc19 --- /dev/null +++ b/pkg/server/api/files/v1/handler.go @@ -0,0 +1,76 @@ +// 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 files_v1 + +import ( + "errors" + "net/http" + "time" + + "github.com/go-chi/chi/v5" + "go.gearno.de/kit/log" + "go.probo.inc/probo/pkg/coredata" + "go.probo.inc/probo/pkg/gid" + "go.probo.inc/probo/pkg/file" +) + +const presignedURLExpiry = 1 * time.Hour + +type Handler struct { + logger *log.Logger + fileSvc *file.Service +} + +func NewMux(logger *log.Logger, fileSvc *file.Service) *chi.Mux { + h := &Handler{ + logger: logger, + fileSvc: fileSvc, + } + + r := chi.NewRouter() + + r.Get("/{fileID}", h.handleGetPublicFile) + + return r +} + +func (h *Handler) handleGetPublicFile(w http.ResponseWriter, r *http.Request) { + fileIDStr := chi.URLParam(r, "fileID") + + fileID, err := gid.ParseGID(fileIDStr) + if err != nil { + http.NotFound(w, r) + return + } + + presignedURL, err := h.fileSvc.GetPublicFileURL(r.Context(), fileID, presignedURLExpiry) + if err != nil { + if errors.Is(err, coredata.ErrResourceNotFound) { + http.NotFound(w, r) + return + } + + h.logger.ErrorCtx( + r.Context(), + "cannot get public file URL", + log.Error(err), + log.String("file_id", fileIDStr), + ) + http.Error(w, "internal server error", http.StatusInternalServerError) + return + } + + http.Redirect(w, r, presignedURL, http.StatusTemporaryRedirect) +} diff --git a/pkg/server/server.go b/pkg/server/server.go index 2d0ab3851..3aa156e27 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -28,6 +28,7 @@ import ( "go.probo.inc/probo/pkg/iam" "go.probo.inc/probo/pkg/mailman" "go.probo.inc/probo/pkg/probo" + "go.probo.inc/probo/pkg/file" "go.probo.inc/probo/pkg/securecookie" "go.probo.inc/probo/pkg/server/api" "go.probo.inc/probo/pkg/server/api/compliancepage" @@ -43,6 +44,7 @@ type Config struct { AllowedOrigins []string ExtraHeaderFields map[string]string Probo *probo.Service + File *file.Service IAM *iam.Service Trust *trust.Service ESign *esign.Service @@ -72,6 +74,7 @@ func NewServer(cfg Config) (*Server, error) { BaseURL: cfg.BaseURL, AllowedOrigins: cfg.AllowedOrigins, Probo: cfg.Probo, + File: cfg.File, IAM: cfg.IAM, Trust: cfg.Trust, ESign: cfg.ESign,