mirror of
https://github.com/get-drexa/drive.git
synced 2026-02-02 08:51:16 +00:00
154 lines
4.0 KiB
Go
154 lines
4.0 KiB
Go
package drive
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/get-drexa/drexa/internal/account"
|
|
"github.com/get-drexa/drexa/internal/httperr"
|
|
"github.com/get-drexa/drexa/internal/organization"
|
|
"github.com/get-drexa/drexa/internal/reqctx"
|
|
"github.com/get-drexa/drexa/internal/user"
|
|
"github.com/get-drexa/drexa/internal/virtualfs"
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/uptrace/bun"
|
|
)
|
|
|
|
type driveInfoResponse struct {
|
|
*Drive
|
|
RootDirID string `json:"rootDirId"`
|
|
}
|
|
|
|
type HTTPHandler struct {
|
|
driveService *Service
|
|
accountService *account.Service
|
|
vfs *virtualfs.VirtualFS
|
|
db *bun.DB
|
|
authMiddleware fiber.Handler
|
|
}
|
|
|
|
func NewHTTPHandler(driveService *Service, accountService *account.Service, vfs *virtualfs.VirtualFS, db *bun.DB, authMiddleware fiber.Handler) *HTTPHandler {
|
|
return &HTTPHandler{
|
|
driveService: driveService,
|
|
accountService: accountService,
|
|
vfs: vfs,
|
|
db: db,
|
|
authMiddleware: authMiddleware,
|
|
}
|
|
}
|
|
|
|
func (h *HTTPHandler) RegisterRoutes(api fiber.Router) *virtualfs.ScopedRouter {
|
|
api.Get("/drives", h.authMiddleware, h.listDrives)
|
|
|
|
drive := api.Group("/drives/:driveID")
|
|
drive.Use(h.authMiddleware)
|
|
drive.Use(h.driveMiddleware)
|
|
|
|
drive.Get("/", h.getDriveInfo)
|
|
|
|
return &virtualfs.ScopedRouter{Router: drive}
|
|
}
|
|
|
|
func (h *HTTPHandler) listDrives(c *fiber.Ctx) error {
|
|
u := reqctx.AuthenticatedUser(c).(*user.User)
|
|
org, ok := reqctx.CurrentOrganization(c).(*organization.Organization)
|
|
if !ok || org == nil {
|
|
return c.SendStatus(fiber.StatusNotFound)
|
|
}
|
|
|
|
acc, err := h.accountService.FindUserAccountInOrg(c.Context(), h.db, org.ID, u.ID)
|
|
if err != nil {
|
|
if errors.Is(err, account.ErrAccountNotFound) {
|
|
return c.SendStatus(fiber.StatusNotFound)
|
|
}
|
|
return httperr.Internal(err)
|
|
}
|
|
if acc.Status != account.StatusActive {
|
|
return c.SendStatus(fiber.StatusNotFound)
|
|
}
|
|
|
|
drives, err := h.driveService.ListAccessibleDrives(c.Context(), h.db, org.ID, acc.ID)
|
|
if err != nil {
|
|
return httperr.Internal(err)
|
|
}
|
|
return c.JSON(drives)
|
|
}
|
|
|
|
func (h *HTTPHandler) getDriveInfo(c *fiber.Ctx) error {
|
|
drive, ok := reqctx.CurrentDrive(c).(*Drive)
|
|
if !ok || drive == nil {
|
|
return c.SendStatus(fiber.StatusNotFound)
|
|
}
|
|
|
|
rootDirID, _ := c.Locals("rootDirId").(string)
|
|
if rootDirID == "" {
|
|
scopeAny := reqctx.VFSAccessScope(c)
|
|
scope, ok := scopeAny.(*virtualfs.Scope)
|
|
if !ok || scope == nil {
|
|
return c.SendStatus(fiber.StatusUnauthorized)
|
|
}
|
|
|
|
root, err := h.vfs.FindNode(c.Context(), h.db, scope.RootNodeID.String(), scope)
|
|
if err != nil {
|
|
if errors.Is(err, virtualfs.ErrNodeNotFound) || errors.Is(err, virtualfs.ErrAccessDenied) {
|
|
return c.SendStatus(fiber.StatusNotFound)
|
|
}
|
|
return httperr.Internal(err)
|
|
}
|
|
rootDirID = root.PublicID
|
|
}
|
|
|
|
return c.JSON(driveInfoResponse{
|
|
Drive: drive,
|
|
RootDirID: rootDirID,
|
|
})
|
|
}
|
|
|
|
func (h *HTTPHandler) driveMiddleware(c *fiber.Ctx) error {
|
|
org, ok := reqctx.CurrentOrganization(c).(*organization.Organization)
|
|
if !ok || org == nil {
|
|
return c.SendStatus(fiber.StatusNotFound)
|
|
}
|
|
|
|
driveID := c.Params("driveID")
|
|
drive, err := h.driveService.DriveByPublicID(c.Context(), h.db, driveID)
|
|
if err != nil {
|
|
if errors.Is(err, ErrDriveNotFound) {
|
|
return c.SendStatus(fiber.StatusNotFound)
|
|
}
|
|
return httperr.Internal(err)
|
|
}
|
|
if drive.OrgID != org.ID {
|
|
return c.SendStatus(fiber.StatusNotFound)
|
|
}
|
|
|
|
acc, ok := reqctx.CurrentAccount(c).(*account.Account)
|
|
if !ok || acc == nil {
|
|
return c.SendStatus(fiber.StatusNotFound)
|
|
}
|
|
|
|
if !h.driveService.CanAccessDrive(drive, acc.OrgID, acc.ID) {
|
|
return c.SendStatus(fiber.StatusNotFound)
|
|
}
|
|
|
|
root, err := h.vfs.FindRootDirectory(c.Context(), h.db, drive.ID)
|
|
if err != nil {
|
|
return httperr.Internal(err)
|
|
}
|
|
|
|
c.Locals("rootDirId", root.PublicID)
|
|
|
|
scope := &virtualfs.Scope{
|
|
DriveID: drive.ID,
|
|
RootNodeID: root.ID,
|
|
AllowedOps: virtualfs.AllAllowedOps,
|
|
AllowedNodes: nil,
|
|
ActorKind: virtualfs.ScopeActorAccount,
|
|
ActorID: acc.ID,
|
|
}
|
|
|
|
reqctx.SetCurrentDrive(c, drive)
|
|
reqctx.SetVFSAccessScope(c, scope)
|
|
|
|
return c.Next()
|
|
}
|