Admin-stored API key with env fallback; scan drive/mail/IMAP uploads. Fail-open if VT down, 422 on malware; migration for virus_scan_status.
105 lines
3.2 KiB
Go
105 lines
3.2 KiB
Go
package drive
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/ultisuite/ulti-backend/internal/filescan"
|
|
"github.com/ultisuite/ulti-backend/internal/nextcloud"
|
|
)
|
|
|
|
func (s *Service) UploadPublicShare(ctx context.Context, token, filePath, password string, body io.Reader, contentType string) error {
|
|
perms, err := s.GetPublicSharePermissions(ctx, token, password)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !nextcloud.PublicShareCanCreate(perms) && !nextcloud.PublicShareCanUpdate(perms) {
|
|
return ErrForbidden
|
|
}
|
|
reader := body
|
|
if s.scanner != nil {
|
|
data, _, err := s.scanner.ScanReader(ctx, filePath, body, -1)
|
|
if err != nil {
|
|
if errors.Is(err, filescan.ErrMalicious) {
|
|
return ErrMalware
|
|
}
|
|
return err
|
|
}
|
|
reader = bytes.NewReader(data)
|
|
}
|
|
if err := mapPublicShareError(s.nc.UploadPublicShare(ctx, token, filePath, password, reader, contentType)); err != nil {
|
|
return err
|
|
}
|
|
s.recordPublicShareAccess(ctx, token)
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) CreatePublicShareFolder(ctx context.Context, token, folderPath, password string) error {
|
|
if err := s.requirePublicSharePerm(ctx, token, password, nextcloud.PublicShareCanCreate); err != nil {
|
|
return err
|
|
}
|
|
return mapPublicShareError(s.nc.CreatePublicShareFolder(ctx, token, folderPath, password))
|
|
}
|
|
|
|
func (s *Service) DeletePublicShareItem(ctx context.Context, token, filePath, password string) error {
|
|
if err := s.requirePublicSharePerm(ctx, token, password, nextcloud.PublicShareCanDelete); err != nil {
|
|
return err
|
|
}
|
|
return mapPublicShareError(s.nc.DeletePublicShare(ctx, token, filePath, password))
|
|
}
|
|
|
|
func (s *Service) RenamePublicShareItem(ctx context.Context, token, filePath, newName, password string) error {
|
|
if strings.Contains(newName, "/") {
|
|
return ErrInvalid
|
|
}
|
|
if err := s.requirePublicSharePathPerm(ctx, token, filePath, password, nextcloud.PublicShareCanUpdate); err != nil {
|
|
return err
|
|
}
|
|
filePath = nextcloud.NormalizeClientPath(filePath)
|
|
dir := path.Dir("/" + strings.TrimPrefix(filePath, "/"))
|
|
destination := path.Join(dir, newName)
|
|
return mapPublicShareError(s.nc.MovePublicShare(ctx, token, filePath, destination, password))
|
|
}
|
|
|
|
func (s *Service) GetPublicSharePermissions(ctx context.Context, token, password string) (int, error) {
|
|
perms, err := s.nc.GetPublicSharePermissions(ctx, token, password)
|
|
if err != nil {
|
|
return 0, mapPublicShareError(err)
|
|
}
|
|
return perms, nil
|
|
}
|
|
|
|
func (s *Service) GetPublicSharePathPermissions(ctx context.Context, token, path, password string) (int, error) {
|
|
perms, err := s.nc.GetPublicSharePathPermissions(ctx, token, path, password)
|
|
if err != nil {
|
|
return 0, mapPublicShareError(err)
|
|
}
|
|
return perms, nil
|
|
}
|
|
|
|
func (s *Service) requirePublicSharePerm(ctx context.Context, token, password string, check func(int) bool) error {
|
|
perms, err := s.GetPublicSharePermissions(ctx, token, password)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !check(perms) {
|
|
return ErrForbidden
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) requirePublicSharePathPerm(ctx context.Context, token, path, password string, check func(int) bool) error {
|
|
perms, err := s.GetPublicSharePathPermissions(ctx, token, path, password)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !check(perms) {
|
|
return ErrForbidden
|
|
}
|
|
return nil
|
|
}
|