Migrate all callers to unified filemanager.Service
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
This commit is contained in:
@@ -464,7 +464,7 @@ func (s *Service) GenerateCertificateFileURL(
|
||||
return "", err
|
||||
}
|
||||
|
||||
url, err := s.fileManager.GenerateFileURL(ctx, &file, expiresIn)
|
||||
url, err := s.fileManager.GeneratePresignedFileURL(ctx, &file, expiresIn)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot generate certificate file URL: %w", err)
|
||||
}
|
||||
@@ -501,7 +501,7 @@ func (s *Service) GenerateSignatureFileURL(
|
||||
return "", err
|
||||
}
|
||||
|
||||
url, err := s.fileManager.GenerateFileURL(ctx, &file, expiresIn)
|
||||
url, err := s.fileManager.GeneratePresignedFileURL(ctx, &file, expiresIn)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot generate signature file URL: %w", err)
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ func (s *CompliancePageService) GenerateLogoURL(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignedURL, err := s.fm.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.fm.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
|
||||
@@ -1410,7 +1410,7 @@ func (s OrganizationService) GenerateLogoURL(
|
||||
return nil, fmt.Errorf("cannot generate logo URL: %w", err)
|
||||
}
|
||||
|
||||
presignedURL, err := s.fm.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.fm.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
@@ -1456,7 +1456,7 @@ func (s OrganizationService) GenerateHorizontalLogoURL(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
presignedURL, err := s.fm.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.fm.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ func (s FileService) GenerateFileURL(
|
||||
return "", fmt.Errorf("cannot get file: %w", err)
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
|
||||
@@ -866,7 +866,7 @@ func (s FrameworkService) GenerateLightLogoURL(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
@@ -908,7 +908,7 @@ func (s FrameworkService) GenerateDarkLogoURL(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"go.gearno.de/crypto/uuid"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/filemanager"
|
||||
"go.probo.inc/probo/pkg/filevalidation"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/validator"
|
||||
@@ -295,7 +296,7 @@ func (s OrganizationService) Update(
|
||||
}
|
||||
}
|
||||
|
||||
fileSize, err := s.svc.fileManager.GetFileSize(req.File.Content)
|
||||
fileSize, err := filemanager.GetFileSize(req.File.Content)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get file size: %w", err)
|
||||
}
|
||||
@@ -359,7 +360,7 @@ func (s OrganizationService) Update(
|
||||
}
|
||||
}
|
||||
|
||||
fileSize, err := s.svc.fileManager.GetFileSize(req.HorizontalLogoFile.Content)
|
||||
fileSize, err := filemanager.GetFileSize(req.HorizontalLogoFile.Content)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get file size: %w", err)
|
||||
}
|
||||
@@ -450,7 +451,7 @@ func (s OrganizationService) GenerateLogoURL(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
@@ -492,7 +493,7 @@ func (s OrganizationService) GenerateHorizontalLogoURL(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/crypto/cipher"
|
||||
"go.probo.inc/probo/pkg/esign"
|
||||
"go.probo.inc/probo/pkg/file"
|
||||
"go.probo.inc/probo/pkg/filemanager"
|
||||
"go.probo.inc/probo/pkg/filevalidation"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
@@ -80,7 +79,6 @@ type (
|
||||
html2pdfConverter *html2pdf.Converter
|
||||
acmeService *certmanager.ACMEService
|
||||
fileManager *filemanager.Service
|
||||
file *file.Service
|
||||
logger *log.Logger
|
||||
slack *slack.Service
|
||||
esign *esign.Service
|
||||
@@ -145,7 +143,6 @@ func NewService(
|
||||
esignService *esign.Service,
|
||||
connectorRegistry *connector.ConnectorRegistry,
|
||||
invitationTokenValidity time.Duration,
|
||||
fileService *file.Service,
|
||||
) (*Service, error) {
|
||||
if bucket == "" {
|
||||
return nil, fmt.Errorf("bucket is required")
|
||||
@@ -165,7 +162,6 @@ func NewService(
|
||||
html2pdfConverter: html2pdfConverter,
|
||||
acmeService: acmeService,
|
||||
fileManager: fileManagerService,
|
||||
file: fileService,
|
||||
logger: logger,
|
||||
slack: slackService,
|
||||
esign: esignService,
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"go.gearno.de/crypto/uuid"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/filemanager"
|
||||
"go.probo.inc/probo/pkg/filevalidation"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
@@ -160,7 +161,7 @@ func (s TrustCenterFileService) Create(
|
||||
filename := req.File.Filename
|
||||
contentType := req.File.ContentType
|
||||
|
||||
fileSize, err := s.svc.fileManager.GetFileSize(req.File.Content)
|
||||
fileSize, err := filemanager.GetFileSize(req.File.Content)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get file size: %w", err)
|
||||
}
|
||||
@@ -313,7 +314,7 @@ func (s TrustCenterFileService) GenerateFileURL(
|
||||
return "", err
|
||||
}
|
||||
|
||||
fileURL, err := s.svc.fileManager.GenerateFileURL(ctx, storedFile, duration)
|
||||
fileURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, storedFile, duration)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
|
||||
@@ -305,7 +305,7 @@ func (s TrustCenterReferenceService) GenerateLogoURL(
|
||||
return "", fmt.Errorf("cannot load trust center reference: %w", err)
|
||||
}
|
||||
|
||||
return s.svc.file.GenerateFileURL(ctx, reference.LogoFileID)
|
||||
return s.svc.fileManager.GenerateFileURL(ctx, reference.LogoFileID)
|
||||
}
|
||||
|
||||
func (s TrustCenterReferenceService) uploadLogoFile(
|
||||
|
||||
@@ -500,7 +500,7 @@ func (s TrustCenterService) GenerateNDAFileURL(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
@@ -546,7 +546,7 @@ func (s TrustCenterService) GenerateLogoURL(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
@@ -592,7 +592,7 @@ func (s TrustCenterService) GenerateDarkLogoURL(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ import (
|
||||
pemutil "go.probo.inc/probo/pkg/crypto/pem"
|
||||
"go.probo.inc/probo/pkg/esign"
|
||||
"go.probo.inc/probo/pkg/evidencedescriber"
|
||||
"go.probo.inc/probo/pkg/file"
|
||||
"go.probo.inc/probo/pkg/filemanager"
|
||||
"go.probo.inc/probo/pkg/geoloc"
|
||||
"go.probo.inc/probo/pkg/html2pdf"
|
||||
@@ -327,7 +326,7 @@ func (impl *Implm) Run(
|
||||
return err
|
||||
}
|
||||
|
||||
fileManagerService := filemanager.NewService(s3Client)
|
||||
fileManagerService := filemanager.NewService(pgClient, baseURL, s3Client)
|
||||
|
||||
var (
|
||||
samlCert *x509.Certificate
|
||||
@@ -529,8 +528,6 @@ func (impl *Implm) Run(
|
||||
|
||||
cookieBannerService := cookiebanner.NewService(pgClient, impl.cfg.Branding)
|
||||
|
||||
fileService := file.NewService(pgClient, baseURL, fileManagerService)
|
||||
|
||||
proboService, err := probo.NewService(
|
||||
ctx,
|
||||
encryptionKey,
|
||||
@@ -554,7 +551,6 @@ func (impl *Implm) Run(
|
||||
esignService,
|
||||
defaultConnectorRegistry,
|
||||
time.Duration(impl.cfg.Auth.InvitationConfirmationTokenValidity)*time.Second,
|
||||
fileService,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create probo service: %w", err)
|
||||
@@ -572,7 +568,6 @@ func (impl *Implm) Run(
|
||||
fileManagerService,
|
||||
l,
|
||||
slackService,
|
||||
fileService,
|
||||
)
|
||||
|
||||
accessReviewService := accessreview.NewService(
|
||||
@@ -587,7 +582,7 @@ func (impl *Implm) Run(
|
||||
|
||||
iamService.Authorizer.RegisterPolicySet(agentrun.PolicySet())
|
||||
|
||||
thirdPartyService := thirdparty.NewService(pgClient, fileService, thirdPartyVetter)
|
||||
thirdPartyService := thirdparty.NewService(pgClient, fileManagerService, thirdPartyVetter)
|
||||
riskManagementService := riskmanagement.NewService(pgClient)
|
||||
|
||||
serverHandler, err := server.NewServer(
|
||||
@@ -595,7 +590,7 @@ func (impl *Implm) Run(
|
||||
AllowedOrigins: impl.cfg.Api.Cors.AllowedOrigins,
|
||||
ExtraHeaderFields: impl.cfg.Api.ExtraHeaderFields,
|
||||
Probo: proboService,
|
||||
File: fileService,
|
||||
File: fileManagerService,
|
||||
IAM: iamService,
|
||||
Trust: trustService,
|
||||
ESign: esignService,
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/connector/provider"
|
||||
"go.probo.inc/probo/pkg/cookiebanner"
|
||||
"go.probo.inc/probo/pkg/esign"
|
||||
"go.probo.inc/probo/pkg/file"
|
||||
"go.probo.inc/probo/pkg/filemanager"
|
||||
"go.probo.inc/probo/pkg/geoloc"
|
||||
"go.probo.inc/probo/pkg/iam"
|
||||
"go.probo.inc/probo/pkg/mailman"
|
||||
@@ -56,7 +56,7 @@ type (
|
||||
BaseURL *baseurl.BaseURL
|
||||
AllowedOrigins []string
|
||||
Probo *probo.Service
|
||||
File *file.Service
|
||||
File *filemanager.Service
|
||||
IAM *iam.Service
|
||||
Trust *trust.Service
|
||||
ESign *esign.Service
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"go.gearno.de/kit/log"
|
||||
"go.probo.inc/probo/pkg/brand"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/file"
|
||||
"go.probo.inc/probo/pkg/filemanager"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/iam"
|
||||
"go.probo.inc/probo/pkg/probo"
|
||||
@@ -38,14 +38,14 @@ const presignedURLExpiry = 1 * time.Hour
|
||||
|
||||
type Handler struct {
|
||||
logger *log.Logger
|
||||
fileSvc *file.Service
|
||||
fileSvc *filemanager.Service
|
||||
probo *probo.Service
|
||||
iamSvc *iam.Service
|
||||
}
|
||||
|
||||
func NewMux(
|
||||
logger *log.Logger,
|
||||
fileSvc *file.Service,
|
||||
fileSvc *filemanager.Service,
|
||||
proboSvc *probo.Service,
|
||||
iamSvc *iam.Service,
|
||||
cookieConfig securecookie.Config,
|
||||
@@ -94,7 +94,7 @@ func (h *Handler) handleGetPublicFile(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
presignedURL, err := h.fileSvc.GeneratePublicPresignedURL(r.Context(), fileID, presignedURLExpiry)
|
||||
presignedURL, err := h.fileSvc.GeneratePublicPresignedFileURL(r.Context(), fileID, presignedURLExpiry)
|
||||
if err != nil {
|
||||
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||
jsonutil.RenderNotFound(w, fmt.Errorf("file not found"))
|
||||
@@ -157,7 +157,7 @@ func (h *Handler) handleGetFile(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
presignedURL, err := h.fileSvc.GeneratePresignedURL(ctx, f, presignedURLExpiry)
|
||||
presignedURL, err := h.fileSvc.GeneratePresignedFileURL(ctx, f, presignedURLExpiry)
|
||||
if err != nil {
|
||||
h.logger.ErrorCtx(ctx, "cannot generate file URL", log.Error(err), log.String("file_id", fileIDStr))
|
||||
jsonutil.RenderInternalServerError(w)
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/connector/provider"
|
||||
"go.probo.inc/probo/pkg/cookiebanner"
|
||||
"go.probo.inc/probo/pkg/esign"
|
||||
"go.probo.inc/probo/pkg/file"
|
||||
"go.probo.inc/probo/pkg/filemanager"
|
||||
"go.probo.inc/probo/pkg/geoloc"
|
||||
"go.probo.inc/probo/pkg/iam"
|
||||
"go.probo.inc/probo/pkg/iam/oauth2server"
|
||||
@@ -55,7 +55,7 @@ type Config struct {
|
||||
AllowedOrigins []string
|
||||
ExtraHeaderFields map[string]string
|
||||
Probo *probo.Service
|
||||
File *file.Service
|
||||
File *filemanager.Service
|
||||
IAM *iam.Service
|
||||
Trust *trust.Service
|
||||
ESign *esign.Service
|
||||
|
||||
6
pkg/thirdparty/service.go
vendored
6
pkg/thirdparty/service.go
vendored
@@ -20,18 +20,18 @@ import (
|
||||
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/file"
|
||||
"go.probo.inc/probo/pkg/filemanager"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
pg *pg.Client
|
||||
file *file.Service
|
||||
file *filemanager.Service
|
||||
vetter Vetter
|
||||
vettingEnabled bool
|
||||
}
|
||||
|
||||
func NewService(pgClient *pg.Client, fileSvc *file.Service, vetter Vetter) *Service {
|
||||
func NewService(pgClient *pg.Client, fileSvc *filemanager.Service, vetter Vetter) *Service {
|
||||
_, disabled := vetter.(DisabledVetter)
|
||||
|
||||
return &Service{
|
||||
|
||||
@@ -85,7 +85,7 @@ func (s FrameworkService) GenerateLightLogoURL(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
@@ -128,7 +128,7 @@ func (s FrameworkService) GenerateDarkLogoURL(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"go.probo.inc/probo/packages/emails"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/esign"
|
||||
"go.probo.inc/probo/pkg/file"
|
||||
"go.probo.inc/probo/pkg/filemanager"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/html2pdf"
|
||||
@@ -47,7 +46,6 @@ type (
|
||||
esign *esign.Service
|
||||
html2pdfConverter *html2pdf.Converter
|
||||
fileManager *filemanager.Service
|
||||
file *file.Service
|
||||
logger *log.Logger
|
||||
slack *slack.Service
|
||||
TrustCenters *TrustCenterService
|
||||
@@ -77,7 +75,6 @@ func NewService(
|
||||
fileManagerService *filemanager.Service,
|
||||
logger *log.Logger,
|
||||
slack *slack.Service,
|
||||
fileService *file.Service,
|
||||
) *Service {
|
||||
svc := &Service{
|
||||
pg: pgClient,
|
||||
@@ -89,7 +86,6 @@ func NewService(
|
||||
esign: esignSvc,
|
||||
html2pdfConverter: html2pdfConverter,
|
||||
fileManager: fileManagerService,
|
||||
file: fileService,
|
||||
logger: logger,
|
||||
slack: slack,
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func (s TrustCenterReferenceService) GenerateLogoURL(
|
||||
return "", fmt.Errorf("cannot load trust center reference: %w", err)
|
||||
}
|
||||
|
||||
return s.svc.file.GenerateFileURL(ctx, reference.LogoFileID)
|
||||
return s.svc.fileManager.GenerateFileURL(ctx, reference.LogoFileID)
|
||||
}
|
||||
|
||||
func (s TrustCenterReferenceService) Get(
|
||||
|
||||
@@ -148,7 +148,7 @@ func (s TrustCenterService) GenerateNDAFileURL(
|
||||
return "", err
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
@@ -195,7 +195,7 @@ func (s TrustCenterService) GenerateLogoURL(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
@@ -242,7 +242,7 @@ func (s TrustCenterService) GenerateDarkLogoURL(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
presignedURL, err := s.svc.fileManager.GenerateFileURL(ctx, file, expiresIn)
|
||||
presignedURL, err := s.svc.fileManager.GeneratePresignedFileURL(ctx, file, expiresIn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot generate file URL: %w", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user