implement service context

This commit is contained in:
Hayden 2022-09-23 14:47:17 -08:00
parent d19f0e2922
commit 0899217c43
3 changed files with 64 additions and 8 deletions

View file

@ -3,6 +3,7 @@ package services
import (
"context"
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/types"
)
@ -15,6 +16,31 @@ var (
ContextUserToken = &contextKeys{name: "UserToken"}
)
type ServiceContext struct {
context.Context
// UID is a unique identifier for the acting user.
UID uuid.UUID
// GID is a unique identifier for the acting users group.
GID uuid.UUID
// User is the acting user.
User *types.UserOut
}
// UseServiceCtx is a helper function that returns the service context from the context.
// This extracts the users from the context and embeds it into the ServiceContext struct
func NewServiceContext(ctx context.Context) ServiceContext {
user := UseUserCtx(ctx)
return ServiceContext{
Context: ctx,
UID: user.ID,
GID: user.GroupID,
User: user,
}
}
// SetUserCtx is a helper function that sets the ContextUser and ContextUserToken
// values within the context of a web request (or any context).
func SetUserCtx(ctx context.Context, user *types.UserOut, token string) context.Context {

View file

@ -40,12 +40,12 @@ func (at attachmentTokens) Delete(token string) {
delete(at, token)
}
func (svc *ItemService) AttachmentToken(ctx context.Context, gid, itemId, attachmentId uuid.UUID) (string, error) {
func (svc *ItemService) AttachmentToken(ctx ServiceContext, itemId, attachmentId uuid.UUID) (string, error) {
item, err := svc.repo.Items.GetOne(ctx, itemId)
if err != nil {
return "", err
}
if item.Edges.Group.ID != gid {
if item.Edges.Group.ID != ctx.GID {
return "", ErrNotOwner
}
@ -77,25 +77,55 @@ func (svc *ItemService) AttachmentPath(ctx context.Context, token string) (strin
return attachment.Edges.Document.Path, nil
}
func (svc *ItemService) AttachmentUpdate(ctx ServiceContext, itemId uuid.UUID, data *types.ItemAttachmentUpdate) (*types.ItemOut, error) {
// Update Properties
attachment, err := svc.repo.Attachments.Update(ctx, data.ID, attachment.Type(data.Type))
if err != nil {
return nil, err
}
attDoc := attachment.Edges.Document
if data.Title != attachment.Edges.Document.Title {
newPath := pathlib.Safe(svc.attachmentPath(ctx.GID, itemId, data.Title))
// Move File
err = os.Rename(attachment.Edges.Document.Path, newPath)
if err != nil {
return nil, err
}
_, err = svc.repo.Docs.Update(ctx, attDoc.ID, types.DocumentUpdate{
Title: data.Title,
Path: newPath,
})
if err != nil {
return nil, err
}
}
return svc.GetOne(ctx, ctx.GID, itemId)
}
// AttachmentAdd adds an attachment to an item by creating an entry in the Documents table and linking it to the Attachment
// Table and Items table. The file provided via the reader is stored on the file system based on the provided
// relative path during construction of the service.
func (svc *ItemService) AttachmentAdd(ctx context.Context, gid, itemId uuid.UUID, filename string, attachmentType attachment.Type, file io.Reader) (*types.ItemOut, error) {
func (svc *ItemService) AttachmentAdd(ctx ServiceContext, itemId uuid.UUID, filename string, attachmentType attachment.Type, file io.Reader) (*types.ItemOut, error) {
// Get the Item
item, err := svc.repo.Items.GetOne(ctx, itemId)
if err != nil {
return nil, err
}
if item.Edges.Group.ID != gid {
if item.Edges.Group.ID != ctx.GID {
return nil, ErrNotOwner
}
fp := svc.attachmentPath(gid, itemId, filename)
fp := svc.attachmentPath(ctx.GID, itemId, filename)
filename = filepath.Base(fp)
// Create the document
doc, err := svc.repo.Docs.Create(ctx, gid, types.DocumentCreate{
doc, err := svc.repo.Docs.Create(ctx, ctx.GID, types.DocumentCreate{
Title: filename,
Path: fp,
})
@ -126,7 +156,7 @@ func (svc *ItemService) AttachmentAdd(ctx context.Context, gid, itemId uuid.UUID
return nil, err
}
return svc.GetOne(ctx, gid, itemId)
return svc.GetOne(ctx, ctx.GID, itemId)
}
func (svc *ItemService) AttachmentDelete(ctx context.Context, gid, itemId, attachmentId uuid.UUID) error {

View file

@ -125,7 +125,7 @@ func TestItemService_AddAttachment(t *testing.T) {
reader := strings.NewReader(contents)
// Setup
afterAttachment, err := svc.AttachmentAdd(context.Background(), tGroup.ID, itm.ID, "testfile.txt", "attachment", reader)
afterAttachment, err := svc.AttachmentAdd(ServiceContext{Context: context.Background(), GID: tGroup.ID}, itm.ID, "testfile.txt", "attachment", reader)
assert.NoError(t, err)
assert.NotNil(t, afterAttachment)