mirror of
https://github.com/get-drexa/drive.git
synced 2026-02-02 13:21:17 +00:00
feat: initial sharing impl
This commit is contained in:
@@ -7,4 +7,5 @@ var (
|
||||
ErrParentNotDirectory = errors.New("parent is not a directory")
|
||||
ErrConflict = errors.New("node conflict")
|
||||
ErrContentNotUploaded = errors.New("content has not been uploaded")
|
||||
ErrUnauthorized = errors.New("unauthorized")
|
||||
)
|
||||
|
||||
@@ -4,8 +4,9 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/get-drexa/drexa/internal/account"
|
||||
"github.com/get-drexa/drexa/internal/httperr"
|
||||
"github.com/get-drexa/drexa/internal/reqctx"
|
||||
"github.com/get-drexa/drexa/internal/virtualfs"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
@@ -35,7 +36,7 @@ func NewHTTPHandler(s *Service, db *bun.DB) *HTTPHandler {
|
||||
return &HTTPHandler{service: s, db: db}
|
||||
}
|
||||
|
||||
func (h *HTTPHandler) RegisterRoutes(api fiber.Router) {
|
||||
func (h *HTTPHandler) RegisterRoutes(api *virtualfs.ScopedRouter) {
|
||||
upload := api.Group("/uploads")
|
||||
|
||||
upload.Post("/", h.Create)
|
||||
@@ -59,8 +60,9 @@ func (h *HTTPHandler) RegisterRoutes(api fiber.Router) {
|
||||
// @Failure 409 {object} map[string]string "File with this name already exists"
|
||||
// @Router /accounts/{accountID}/uploads [post]
|
||||
func (h *HTTPHandler) Create(c *fiber.Ctx) error {
|
||||
account := account.CurrentAccount(c)
|
||||
if account == nil {
|
||||
scopeAny := reqctx.VFSAccessScope(c)
|
||||
scope, ok := scopeAny.(*virtualfs.Scope)
|
||||
if !ok || scope == nil {
|
||||
return c.SendStatus(fiber.StatusUnauthorized)
|
||||
}
|
||||
|
||||
@@ -69,11 +71,17 @@ func (h *HTTPHandler) Create(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request"})
|
||||
}
|
||||
|
||||
upload, err := h.service.CreateUpload(c.Context(), h.db, account.ID, CreateUploadOptions{
|
||||
upload, err := h.service.CreateUpload(c.Context(), h.db, CreateUploadOptions{
|
||||
ParentID: req.ParentID,
|
||||
Name: req.Name,
|
||||
})
|
||||
}, scope)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrUnauthorized) {
|
||||
return c.SendStatus(fiber.StatusUnauthorized)
|
||||
}
|
||||
if errors.Is(err, virtualfs.ErrAccessDenied) {
|
||||
return c.SendStatus(fiber.StatusNotFound)
|
||||
}
|
||||
if errors.Is(err, ErrNotFound) {
|
||||
return c.SendStatus(fiber.StatusNotFound)
|
||||
}
|
||||
@@ -107,16 +115,23 @@ func (h *HTTPHandler) Create(c *fiber.Ctx) error {
|
||||
// @Failure 404 {string} string "Upload session not found"
|
||||
// @Router /accounts/{accountID}/uploads/{uploadID}/content [put]
|
||||
func (h *HTTPHandler) ReceiveContent(c *fiber.Ctx) error {
|
||||
account := account.CurrentAccount(c)
|
||||
if account == nil {
|
||||
scopeAny := reqctx.VFSAccessScope(c)
|
||||
scope, ok := scopeAny.(*virtualfs.Scope)
|
||||
if !ok || scope == nil {
|
||||
return c.SendStatus(fiber.StatusUnauthorized)
|
||||
}
|
||||
|
||||
uploadID := c.Params("uploadID")
|
||||
|
||||
err := h.service.ReceiveUpload(c.Context(), h.db, account.ID, uploadID, c.Context().RequestBodyStream())
|
||||
err := h.service.ReceiveUpload(c.Context(), h.db, uploadID, c.Context().RequestBodyStream(), scope)
|
||||
defer c.Context().Request.CloseBodyStream()
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrUnauthorized) {
|
||||
return c.SendStatus(fiber.StatusUnauthorized)
|
||||
}
|
||||
if errors.Is(err, virtualfs.ErrAccessDenied) {
|
||||
return c.SendStatus(fiber.StatusNotFound)
|
||||
}
|
||||
if errors.Is(err, ErrNotFound) {
|
||||
return c.SendStatus(fiber.StatusNotFound)
|
||||
}
|
||||
@@ -142,8 +157,9 @@ func (h *HTTPHandler) ReceiveContent(c *fiber.Ctx) error {
|
||||
// @Failure 404 {string} string "Upload session not found"
|
||||
// @Router /accounts/{accountID}/uploads/{uploadID} [patch]
|
||||
func (h *HTTPHandler) Update(c *fiber.Ctx) error {
|
||||
account := account.CurrentAccount(c)
|
||||
if account == nil {
|
||||
scopeAny := reqctx.VFSAccessScope(c)
|
||||
scope, ok := scopeAny.(*virtualfs.Scope)
|
||||
if !ok || scope == nil {
|
||||
return c.SendStatus(fiber.StatusUnauthorized)
|
||||
}
|
||||
|
||||
@@ -153,8 +169,14 @@ func (h *HTTPHandler) Update(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
if req.Status == StatusCompleted {
|
||||
upload, err := h.service.CompleteUpload(c.Context(), h.db, account.ID, c.Params("uploadID"))
|
||||
upload, err := h.service.CompleteUpload(c.Context(), h.db, c.Params("uploadID"), scope)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrUnauthorized) {
|
||||
return c.SendStatus(fiber.StatusUnauthorized)
|
||||
}
|
||||
if errors.Is(err, virtualfs.ErrAccessDenied) {
|
||||
return c.SendStatus(fiber.StatusNotFound)
|
||||
}
|
||||
if errors.Is(err, ErrNotFound) {
|
||||
return c.SendStatus(fiber.StatusNotFound)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
|
||||
"github.com/get-drexa/drexa/internal/blob"
|
||||
"github.com/get-drexa/drexa/internal/virtualfs"
|
||||
"github.com/google/uuid"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
@@ -35,8 +34,12 @@ type CreateUploadOptions struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (s *Service) CreateUpload(ctx context.Context, db bun.IDB, accountID uuid.UUID, opts CreateUploadOptions) (*Upload, error) {
|
||||
parentNode, err := s.vfs.FindNodeByPublicID(ctx, db, accountID, opts.ParentID)
|
||||
func (s *Service) CreateUpload(ctx context.Context, db bun.IDB, opts CreateUploadOptions, scope *virtualfs.Scope) (*Upload, error) {
|
||||
if scope == nil {
|
||||
return nil, ErrUnauthorized
|
||||
}
|
||||
|
||||
parentNode, err := s.vfs.FindNodeByPublicID(ctx, db, opts.ParentID, scope)
|
||||
if err != nil {
|
||||
if errors.Is(err, virtualfs.ErrNodeNotFound) {
|
||||
return nil, ErrNotFound
|
||||
@@ -48,10 +51,10 @@ func (s *Service) CreateUpload(ctx context.Context, db bun.IDB, accountID uuid.U
|
||||
return nil, ErrParentNotDirectory
|
||||
}
|
||||
|
||||
node, err := s.vfs.CreateFile(ctx, db, accountID, virtualfs.CreateFileOptions{
|
||||
node, err := s.vfs.CreateFile(ctx, db, virtualfs.CreateFileOptions{
|
||||
ParentID: parentNode.ID,
|
||||
Name: opts.Name,
|
||||
})
|
||||
}, scope)
|
||||
if err != nil {
|
||||
if errors.Is(err, virtualfs.ErrNodeConflict) {
|
||||
return nil, ErrConflict
|
||||
@@ -65,7 +68,7 @@ func (s *Service) CreateUpload(ctx context.Context, db bun.IDB, accountID uuid.U
|
||||
Duration: 1 * time.Hour,
|
||||
})
|
||||
if err != nil {
|
||||
_ = s.vfs.PermanentlyDeleteNode(ctx, db, node)
|
||||
_ = s.vfs.PermanentlyDeleteNode(ctx, db, node, scope)
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
@@ -84,7 +87,7 @@ func (s *Service) CreateUpload(ctx context.Context, db bun.IDB, accountID uuid.U
|
||||
return upload, nil
|
||||
}
|
||||
|
||||
func (s *Service) ReceiveUpload(ctx context.Context, db bun.IDB, accountID uuid.UUID, uploadID string, reader io.Reader) error {
|
||||
func (s *Service) ReceiveUpload(ctx context.Context, db bun.IDB, uploadID string, reader io.Reader, scope *virtualfs.Scope) error {
|
||||
fmt.Printf("reader: %v\n", reader)
|
||||
n, ok := s.pendingUploads.Load(uploadID)
|
||||
if !ok {
|
||||
@@ -96,11 +99,15 @@ func (s *Service) ReceiveUpload(ctx context.Context, db bun.IDB, accountID uuid.
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
if upload.TargetNode.AccountID != accountID {
|
||||
if scope == nil {
|
||||
return ErrUnauthorized
|
||||
}
|
||||
|
||||
if upload.TargetNode.AccountID != scope.AccountID {
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
err := s.vfs.WriteFile(ctx, db, upload.TargetNode, virtualfs.FileContentFromReader(reader))
|
||||
err := s.vfs.WriteFile(ctx, db, upload.TargetNode, virtualfs.FileContentFromReader(reader), scope)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -110,7 +117,7 @@ func (s *Service) ReceiveUpload(ctx context.Context, db bun.IDB, accountID uuid.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) CompleteUpload(ctx context.Context, db bun.IDB, accountID uuid.UUID, uploadID string) (*Upload, error) {
|
||||
func (s *Service) CompleteUpload(ctx context.Context, db bun.IDB, uploadID string, scope *virtualfs.Scope) (*Upload, error) {
|
||||
n, ok := s.pendingUploads.Load(uploadID)
|
||||
if !ok {
|
||||
return nil, ErrNotFound
|
||||
@@ -121,7 +128,11 @@ func (s *Service) CompleteUpload(ctx context.Context, db bun.IDB, accountID uuid
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
if upload.TargetNode.AccountID != accountID {
|
||||
if scope == nil {
|
||||
return nil, ErrUnauthorized
|
||||
}
|
||||
|
||||
if upload.TargetNode.AccountID != scope.AccountID {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
@@ -129,7 +140,7 @@ func (s *Service) CompleteUpload(ctx context.Context, db bun.IDB, accountID uuid
|
||||
return upload, nil
|
||||
}
|
||||
|
||||
err := s.vfs.WriteFile(ctx, db, upload.TargetNode, virtualfs.FileContentFromBlobKey(upload.TargetNode.BlobKey))
|
||||
err := s.vfs.WriteFile(ctx, db, upload.TargetNode, virtualfs.FileContentFromBlobKey(upload.TargetNode.BlobKey), scope)
|
||||
if err != nil {
|
||||
if errors.Is(err, blob.ErrNotFound) {
|
||||
return nil, ErrContentNotUploaded
|
||||
|
||||
Reference in New Issue
Block a user