cleanup temporary token implementation

This commit is contained in:
Hayden 2022-12-03 10:50:47 -09:00
parent 9178da7f0b
commit 1c28db89a0
No known key found for this signature in database
GPG key ID: 17CF79474E257545
5 changed files with 2 additions and 113 deletions

View file

@ -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)

View file

@ -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()),

View file

@ -38,7 +38,6 @@ func New(repos *repo.AllRepos, opts ...OptionsFunc) *AllServices {
Group: &GroupService{repos},
Items: &ItemService{
repo: repos,
at: attachmentTokens{},
autoIncrementAssetID: options.autoIncrementAssetID,
},
}

View file

@ -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
}

View file

@ -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