diff --git a/backend/app/api/handlers/v1/v1_ctrl_items_attachments.go b/backend/app/api/handlers/v1/v1_ctrl_items_attachments.go index 9f3c74a..033f683 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_items_attachments.go +++ b/backend/app/api/handlers/v1/v1_ctrl_items_attachments.go @@ -2,10 +2,7 @@ package v1 import ( "errors" - "fmt" "net/http" - "path/filepath" - "strings" "github.com/hay-kot/homebox/backend/internal/core/services" "github.com/hay-kot/homebox/backend/internal/data/ent/attachment" @@ -95,41 +92,6 @@ func (ctrl *V1Controller) HandleItemAttachmentCreate() server.HandlerFunc { } } -// HandleItemAttachmentGet godocs -// @Summary retrieves an attachment for an item -// @Tags Items Attachments -// @Produce application/octet-stream -// @Param id path string true "Item ID" -// @Param token query string true "Attachment token" -// @Success 200 -// @Router /v1/items/{id}/attachments/download [GET] -// @Security Bearer -func (ctrl *V1Controller) HandleItemAttachmentDownload() server.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) error { - token := server.GetParam(r, "token", "") - - doc, err := ctrl.svc.Items.AttachmentPath(r.Context(), token) - - if err != nil { - log.Err(err).Msg("failed to get attachment") - return validate.NewRequestError(err, http.StatusInternalServerError) - } - - ext := filepath.Ext(doc.Path) - - title := doc.Title - - if !strings.HasSuffix(doc.Title, ext) { - title = doc.Title + ext - } - - w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", title)) - w.Header().Set("Content-Type", "application/octet-stream") - http.ServeFile(w, r, doc.Path) - return nil - } -} - // HandleItemAttachmentGet godocs // @Summary retrieves an attachment for an item // @Tags Items Attachments @@ -182,7 +144,7 @@ func (ctrl *V1Controller) handleItemAttachmentsHandler(w http.ResponseWriter, r ctx := services.NewContext(r.Context()) switch r.Method { case http.MethodGet: - doc, err := ctrl.svc.Items.AttachmentPathV2(r.Context(), attachmentID) + doc, err := ctrl.svc.Items.AttachmentPath(r.Context(), attachmentID) if err != nil { log.Err(err).Msg("failed to get attachment path") return validate.NewRequestError(err, http.StatusInternalServerError) diff --git a/backend/app/api/routes.go b/backend/app/api/routes.go index 9049bb5..e5a7948 100644 --- a/backend/app/api/routes.go +++ b/backend/app/api/routes.go @@ -65,10 +65,6 @@ func (a *app) mountRoutes(repos *repo.AllRepos) { a.server.Post(v1Base("/users/register"), v1Ctrl.HandleUserRegistration()) a.server.Post(v1Base("/users/login"), v1Ctrl.HandleAuthLogin()) - // Attachment download URl needs a `token` query param to be passed in the request. - // and also needs to be outside of the `auth` middleware. - a.server.Get(v1Base("/items/{id}/attachments/download"), v1Ctrl.HandleItemAttachmentDownload()) - userMW := []server.Middleware{ a.mwAuthToken, a.mwRoles(RoleModeOr, authroles.RoleUser.String()), diff --git a/backend/internal/core/services/all.go b/backend/internal/core/services/all.go index 25e406e..43deb52 100644 --- a/backend/internal/core/services/all.go +++ b/backend/internal/core/services/all.go @@ -38,7 +38,6 @@ func New(repos *repo.AllRepos, opts ...OptionsFunc) *AllServices { Group: &GroupService{repos}, Items: &ItemService{ repo: repos, - at: attachmentTokens{}, autoIncrementAssetID: options.autoIncrementAssetID, }, } diff --git a/backend/internal/core/services/service_items.go b/backend/internal/core/services/service_items.go index 5055c67..df37e67 100644 --- a/backend/internal/core/services/service_items.go +++ b/backend/internal/core/services/service_items.go @@ -18,9 +18,6 @@ type ItemService struct { repo *repo.AllRepos filepath string - // at is a map of tokens to attachment IDs. This is used to store the attachment ID - // for issued URLs - at attachmentTokens autoIncrementAssetID bool } diff --git a/backend/internal/core/services/service_items_attachments.go b/backend/internal/core/services/service_items_attachments.go index f395b8e..4a7b197 100644 --- a/backend/internal/core/services/service_items_attachments.go +++ b/backend/internal/core/services/service_items_attachments.go @@ -4,80 +4,15 @@ import ( "context" "io" "os" - "time" "github.com/google/uuid" "github.com/hay-kot/homebox/backend/internal/data/ent" "github.com/hay-kot/homebox/backend/internal/data/ent/attachment" "github.com/hay-kot/homebox/backend/internal/data/repo" - "github.com/hay-kot/homebox/backend/pkgs/hasher" "github.com/rs/zerolog/log" ) -// TODO: this isn't a scalable solution, tokens should be stored in the database -type attachmentTokens map[string]uuid.UUID - -func (at attachmentTokens) Add(token string, id uuid.UUID) { - at[token] = id - - log.Debug().Str("token", token).Str("uuid", id.String()).Msg("added token") - - go func() { - ch := time.After(1 * time.Minute) - <-ch - at.Delete(token) - log.Debug().Str("token", token).Msg("deleted token") - }() -} - -func (at attachmentTokens) Get(token string) (uuid.UUID, bool) { - id, ok := at[token] - return id, ok -} - -func (at attachmentTokens) Delete(token string) { - delete(at, token) -} - -func (svc *ItemService) AttachmentToken(ctx Context, itemId, attachmentId uuid.UUID) (string, error) { - _, err := svc.repo.Items.GetOneByGroup(ctx, ctx.GID, itemId) - if err != nil { - return "", err - } - - token := hasher.GenerateToken() - - // Ensure that the file exists - attachment, err := svc.repo.Attachments.Get(ctx, attachmentId) - if err != nil { - return "", err - } - - if _, err := os.Stat(attachment.Edges.Document.Path); os.IsNotExist(err) { - _ = svc.AttachmentDelete(ctx, ctx.GID, itemId, attachmentId) - return "", ErrNotFound - } - - svc.at.Add(token.Raw, attachmentId) - - return token.Raw, nil -} - -func (svc *ItemService) AttachmentPathV2(ctx context.Context, attachmentId uuid.UUID) (*ent.Document, error) { - attachment, err := svc.repo.Attachments.Get(ctx, attachmentId) - if err != nil { - return nil, err - } - - return attachment.Edges.Document, nil -} - -func (svc *ItemService) AttachmentPath(ctx context.Context, token string) (*ent.Document, error) { - attachmentId, ok := svc.at.Get(token) - if !ok { - return nil, ErrNotFound - } - +func (svc *ItemService) AttachmentPath(ctx context.Context, attachmentId uuid.UUID) (*ent.Document, error) { attachment, err := svc.repo.Attachments.Get(ctx, attachmentId) if err != nil { return nil, err