fix: inaccruate 401 & sql busy error (#679)

* fix inaccruate 401 error on SQL db error

* init golangci-lint config

* linter autofix

* testify auto fixes

* fix sqlite busy errors

* fix naming

* more linter errors

* fix rest of linter issues

Former-commit-id: e8449b3a7363a6cfd5bc6151609e6d2d94b4f7d8
This commit is contained in:
Hayden 2024-01-04 11:55:26 -06:00 committed by GitHub
parent 5e83b28ff5
commit 03df23d97c
62 changed files with 389 additions and 292 deletions

View file

@ -1,3 +1,4 @@
// Package migrations provides a way to embed the migrations into the binary.
package migrations
import (

View file

@ -54,7 +54,7 @@ func TestMain(m *testing.M) {
tClient = client
tRepos = New(tClient, tbus, os.TempDir())
defer client.Close()
defer func() { _ = client.Close() }()
bootstrap()

View file

@ -11,6 +11,7 @@ import (
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/data/ent"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func useDocs(t *testing.T, num int) []DocumentOut {
@ -25,7 +26,7 @@ func useDocs(t *testing.T, num int) []DocumentOut {
Content: bytes.NewReader([]byte(fk.Str(10))),
})
assert.NoError(t, err)
require.NoError(t, err)
assert.NotNil(t, doc)
results = append(results, doc)
ids = append(ids, doc.ID)
@ -80,31 +81,31 @@ func TestDocumentRepository_CreateUpdateDelete(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
// Create Document
got, err := r.Create(tt.args.ctx, tt.args.gid, tt.args.doc)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, tt.title, got.Title)
assert.Equal(t, fmt.Sprintf("%s/%s/documents", temp, tt.args.gid), filepath.Dir(got.Path))
ensureRead := func() {
// Read Document
bts, err := os.ReadFile(got.Path)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, tt.content, string(bts))
}
ensureRead()
// Update Document
got, err = r.Rename(tt.args.ctx, got.ID, "__"+tt.title+"__")
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, "__"+tt.title+"__", got.Title)
ensureRead()
// Delete Document
err = r.Delete(tt.args.ctx, got.ID)
assert.NoError(t, err)
require.NoError(t, err)
_, err = os.Stat(got.Path)
assert.Error(t, err)
require.Error(t, err)
})
}
}

View file

@ -5,29 +5,30 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_Group_Create(t *testing.T) {
g, err := tRepos.Groups.GroupCreate(context.Background(), "test")
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, "test", g.Name)
// Get by ID
foundGroup, err := tRepos.Groups.GroupByID(context.Background(), g.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, g.ID, foundGroup.ID)
}
func Test_Group_Update(t *testing.T) {
g, err := tRepos.Groups.GroupCreate(context.Background(), "test")
assert.NoError(t, err)
require.NoError(t, err)
g, err = tRepos.Groups.GroupUpdate(context.Background(), g.ID, GroupUpdate{
Name: "test2",
Currency: "eur",
})
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, "test2", g.Name)
assert.Equal(t, "EUR", g.Currency)
}
@ -38,7 +39,7 @@ func Test_Group_GroupStatistics(t *testing.T) {
stats, err := tRepos.Groups.StatsGroup(context.Background(), tGroup.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, 20, stats.TotalItems)
assert.Equal(t, 20, stats.TotalLabels)
assert.Equal(t, 1, stats.TotalUsers)

View file

@ -51,31 +51,31 @@ func ToItemAttachment(attachment *ent.Attachment) ItemAttachment {
}
}
func (r *AttachmentRepo) Create(ctx context.Context, itemId, docId uuid.UUID, typ attachment.Type) (*ent.Attachment, error) {
func (r *AttachmentRepo) Create(ctx context.Context, itemID, docID uuid.UUID, typ attachment.Type) (*ent.Attachment, error) {
bldr := r.db.Attachment.Create().
SetType(typ).
SetDocumentID(docId).
SetItemID(itemId)
SetDocumentID(docID).
SetItemID(itemID)
// Autoset primary to true if this is the first attachment
// that is of type photo
if typ == attachment.TypePhoto {
cnt, err := r.db.Attachment.Query().
Where(
attachment.HasItemWith(item.ID(itemId)),
attachment.TypeEQ(typ),
).
Count(ctx)
if err != nil {
return nil, err
}
// Autoset primary to true if this is the first attachment
// that is of type photo
if typ == attachment.TypePhoto {
cnt, err := r.db.Attachment.Query().
Where(
attachment.HasItemWith(item.ID(itemID)),
attachment.TypeEQ(typ),
).
Count(ctx)
if err != nil {
return nil, err
}
if cnt == 0 {
bldr = bldr.SetPrimary(true)
}
}
if cnt == 0 {
bldr = bldr.SetPrimary(true)
}
}
return bldr.Save(ctx)
return bldr.Save(ctx)
}
func (r *AttachmentRepo) Get(ctx context.Context, id uuid.UUID) (*ent.Attachment, error) {
@ -87,11 +87,11 @@ func (r *AttachmentRepo) Get(ctx context.Context, id uuid.UUID) (*ent.Attachment
Only(ctx)
}
func (r *AttachmentRepo) Update(ctx context.Context, itemId uuid.UUID, data *ItemAttachmentUpdate) (*ent.Attachment, error) {
func (r *AttachmentRepo) Update(ctx context.Context, itemID uuid.UUID, data *ItemAttachmentUpdate) (*ent.Attachment, error) {
// TODO: execute within Tx
typ := attachment.Type(data.Type)
bldr := r.db.Attachment.UpdateOneID(itemId).
bldr := r.db.Attachment.UpdateOneID(itemID).
SetType(typ)
// Primary only applies to photos
@ -109,7 +109,7 @@ func (r *AttachmentRepo) Update(ctx context.Context, itemId uuid.UUID, data *Ite
// Ensure all other attachments are not primary
err = r.db.Attachment.Update().
Where(
attachment.HasItemWith(item.ID(itemId)),
attachment.HasItemWith(item.ID(itemID)),
attachment.IDNEQ(itm.ID),
).
SetPrimary(false).

View file

@ -8,6 +8,7 @@ import (
"github.com/hay-kot/homebox/backend/internal/data/ent"
"github.com/hay-kot/homebox/backend/internal/data/ent/attachment"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAttachmentRepo_Create(t *testing.T) {
@ -23,8 +24,8 @@ func TestAttachmentRepo_Create(t *testing.T) {
type args struct {
ctx context.Context
itemId uuid.UUID
docId uuid.UUID
itemID uuid.UUID
docID uuid.UUID
typ attachment.Type
}
tests := []struct {
@ -37,8 +38,8 @@ func TestAttachmentRepo_Create(t *testing.T) {
name: "create attachment",
args: args{
ctx: context.Background(),
itemId: item.ID,
docId: doc.ID,
itemID: item.ID,
docID: doc.ID,
typ: attachment.TypePhoto,
},
want: &ent.Attachment{
@ -49,8 +50,8 @@ func TestAttachmentRepo_Create(t *testing.T) {
name: "create attachment with invalid item id",
args: args{
ctx: context.Background(),
itemId: uuid.New(),
docId: doc.ID,
itemID: uuid.New(),
docID: doc.ID,
typ: "blarg",
},
wantErr: true,
@ -58,7 +59,7 @@ func TestAttachmentRepo_Create(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tRepos.Attachments.Create(tt.args.ctx, tt.args.itemId, tt.args.docId, tt.args.typ)
got, err := tRepos.Attachments.Create(tt.args.ctx, tt.args.itemID, tt.args.docID, tt.args.typ)
if (err != nil) != tt.wantErr {
t.Errorf("AttachmentRepo.Create() error = %v, wantErr %v", err, tt.wantErr)
return
@ -71,9 +72,9 @@ func TestAttachmentRepo_Create(t *testing.T) {
assert.Equal(t, tt.want.Type, got.Type)
withItems, err := tRepos.Attachments.Get(tt.args.ctx, got.ID)
assert.NoError(t, err)
assert.Equal(t, tt.args.itemId, withItems.Edges.Item.ID)
assert.Equal(t, tt.args.docId, withItems.Edges.Document.ID)
require.NoError(t, err)
assert.Equal(t, tt.args.itemID, withItems.Edges.Item.ID)
assert.Equal(t, tt.args.docID, withItems.Edges.Document.ID)
ids = append(ids, got.ID)
})
@ -96,7 +97,7 @@ func useAttachments(t *testing.T, n int) []*ent.Attachment {
attachments := make([]*ent.Attachment, n)
for i := 0; i < n; i++ {
attachment, err := tRepos.Attachments.Create(context.Background(), item.ID, doc.ID, attachment.TypePhoto)
assert.NoError(t, err)
require.NoError(t, err)
attachments[i] = attachment
ids = append(ids, attachment.ID)
@ -114,10 +115,10 @@ func TestAttachmentRepo_Update(t *testing.T) {
Type: string(typ),
})
assert.NoError(t, err)
require.NoError(t, err)
updated, err := tRepos.Attachments.Get(context.Background(), entity.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, typ, updated.Type)
})
}
@ -127,8 +128,8 @@ func TestAttachmentRepo_Delete(t *testing.T) {
entity := useAttachments(t, 1)[0]
err := tRepos.Attachments.Delete(context.Background(), entity.ID)
assert.NoError(t, err)
require.NoError(t, err)
_, err = tRepos.Attachments.Get(context.Background(), entity.ID)
assert.Error(t, err)
require.Error(t, err)
}

View file

@ -55,8 +55,8 @@ type (
ItemCreate struct {
ImportRef string `json:"-"`
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"`
Name string `json:"name" validate:"required,min=1,max=255"`
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"`
Name string `json:"name" validate:"required,min=1,max=255"`
Description string `json:"description" validate:"max=1000"`
AssetID AssetID `json:"-"`
@ -66,7 +66,7 @@ type (
}
ItemUpdate struct {
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable,x-omitempty"`
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable,x-omitempty"`
ID uuid.UUID `json:"id"`
AssetID AssetID `json:"assetId"`
Name string `json:"name"`
@ -108,7 +108,7 @@ type (
ItemPatch struct {
ID uuid.UUID `json:"id"`
Quantity *int `json:"quantity,omitempty" extensions:"x-nullable,x-omitempty"`
ImportRef *string `json:"-,omitempty" extensions:"x-nullable,x-omitempty"`
ImportRef *string `json:"-,omitempty" extensions:"x-nullable,x-omitempty"`
}
ItemSummary struct {
@ -276,9 +276,9 @@ func mapItemOut(item *ent.Item) ItemOut {
}
}
func (r *ItemsRepository) publishMutationEvent(GID uuid.UUID) {
if r.bus != nil {
r.bus.Publish(eventbus.EventItemMutation, eventbus.GroupMutationEvent{GID: GID})
func (e *ItemsRepository) publishMutationEvent(GID uuid.UUID) {
if e.bus != nil {
e.bus.Publish(eventbus.EventItemMutation, eventbus.GroupMutationEvent{GID: GID})
}
}

View file

@ -22,7 +22,7 @@ func useItems(t *testing.T, len int) []ItemOut {
t.Helper()
location, err := tRepos.Locations.Create(context.Background(), tGroup.ID, locationFactory())
assert.NoError(t, err)
require.NoError(t, err)
items := make([]ItemOut, len)
for i := 0; i < len; i++ {
@ -30,7 +30,7 @@ func useItems(t *testing.T, len int) []ItemOut {
itm.LocationID = location.ID
item, err := tRepos.Items.Create(context.Background(), tGroup.ID, itm)
assert.NoError(t, err)
require.NoError(t, err)
items[i] = item
}
@ -61,23 +61,22 @@ func TestItemsRepository_RecursiveRelationships(t *testing.T) {
// Append Parent ID
_, err := tRepos.Items.UpdateByGroup(context.Background(), tGroup.ID, update)
assert.NoError(t, err)
require.NoError(t, err)
// Check Parent ID
updated, err := tRepos.Items.GetOne(context.Background(), child.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, parent.ID, updated.Parent.ID)
// Remove Parent ID
update.ParentID = uuid.Nil
_, err = tRepos.Items.UpdateByGroup(context.Background(), tGroup.ID, update)
assert.NoError(t, err)
require.NoError(t, err)
// Check Parent ID
updated, err = tRepos.Items.GetOne(context.Background(), child.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Nil(t, updated.Parent)
}
}
@ -86,7 +85,7 @@ func TestItemsRepository_GetOne(t *testing.T) {
for _, item := range entity {
result, err := tRepos.Items.GetOne(context.Background(), item.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, item.ID, result.ID)
}
}
@ -96,9 +95,9 @@ func TestItemsRepository_GetAll(t *testing.T) {
expected := useItems(t, length)
results, err := tRepos.Items.GetAll(context.Background(), tGroup.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, length, len(results))
assert.Len(t, results, length)
for _, item := range results {
for _, expectedItem := range expected {
@ -113,23 +112,23 @@ func TestItemsRepository_GetAll(t *testing.T) {
func TestItemsRepository_Create(t *testing.T) {
location, err := tRepos.Locations.Create(context.Background(), tGroup.ID, locationFactory())
assert.NoError(t, err)
require.NoError(t, err)
itm := itemFactory()
itm.LocationID = location.ID
result, err := tRepos.Items.Create(context.Background(), tGroup.ID, itm)
assert.NoError(t, err)
require.NoError(t, err)
assert.NotEmpty(t, result.ID)
// Cleanup - Also deletes item
err = tRepos.Locations.delete(context.Background(), location.ID)
assert.NoError(t, err)
require.NoError(t, err)
}
func TestItemsRepository_Create_Location(t *testing.T) {
location, err := tRepos.Locations.Create(context.Background(), tGroup.ID, locationFactory())
assert.NoError(t, err)
require.NoError(t, err)
assert.NotEmpty(t, location.ID)
item := itemFactory()
@ -137,18 +136,18 @@ func TestItemsRepository_Create_Location(t *testing.T) {
// Create Resource
result, err := tRepos.Items.Create(context.Background(), tGroup.ID, item)
assert.NoError(t, err)
require.NoError(t, err)
assert.NotEmpty(t, result.ID)
// Get Resource
foundItem, err := tRepos.Items.GetOne(context.Background(), result.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, result.ID, foundItem.ID)
assert.Equal(t, location.ID, foundItem.Location.ID)
// Cleanup - Also deletes item
err = tRepos.Locations.delete(context.Background(), location.ID)
assert.NoError(t, err)
require.NoError(t, err)
}
func TestItemsRepository_Delete(t *testing.T) {
@ -156,11 +155,11 @@ func TestItemsRepository_Delete(t *testing.T) {
for _, item := range entities {
err := tRepos.Items.Delete(context.Background(), item.ID)
assert.NoError(t, err)
require.NoError(t, err)
}
results, err := tRepos.Items.GetAll(context.Background(), tGroup.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Empty(t, results)
}
@ -213,7 +212,7 @@ func TestItemsRepository_Update_Labels(t *testing.T) {
}
updated, err := tRepos.Items.UpdateByGroup(context.Background(), tGroup.ID, updateData)
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, tt.want, len(updated.Labels))
for _, label := range updated.Labels {
@ -250,10 +249,10 @@ func TestItemsRepository_Update(t *testing.T) {
}
updatedEntity, err := tRepos.Items.UpdateByGroup(context.Background(), tGroup.ID, updateData)
assert.NoError(t, err)
require.NoError(t, err)
got, err := tRepos.Items.GetOne(context.Background(), updatedEntity.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, updateData.ID, got.ID)
assert.Equal(t, updateData.Name, got.Name)
@ -263,10 +262,10 @@ func TestItemsRepository_Update(t *testing.T) {
assert.Equal(t, updateData.Manufacturer, got.Manufacturer)
// assert.Equal(t, updateData.PurchaseTime, got.PurchaseTime)
assert.Equal(t, updateData.PurchaseFrom, got.PurchaseFrom)
assert.Equal(t, updateData.PurchasePrice, got.PurchasePrice)
assert.InDelta(t, updateData.PurchasePrice, got.PurchasePrice, 0.01)
// assert.Equal(t, updateData.SoldTime, got.SoldTime)
assert.Equal(t, updateData.SoldTo, got.SoldTo)
assert.Equal(t, updateData.SoldPrice, got.SoldPrice)
assert.InDelta(t, updateData.SoldPrice, got.SoldPrice, 0.01)
assert.Equal(t, updateData.SoldNotes, got.SoldNotes)
assert.Equal(t, updateData.Notes, got.Notes)
// assert.Equal(t, updateData.WarrantyExpires, got.WarrantyExpires)
@ -275,15 +274,15 @@ func TestItemsRepository_Update(t *testing.T) {
}
func TestItemRepository_GetAllCustomFields(t *testing.T) {
const FIELDS_COUNT = 5
const FieldsCount = 5
entity := useItems(t, 1)[0]
fields := make([]ItemField, FIELDS_COUNT)
names := make([]string, FIELDS_COUNT)
values := make([]string, FIELDS_COUNT)
fields := make([]ItemField, FieldsCount)
names := make([]string, FieldsCount)
values := make([]string, FieldsCount)
for i := 0; i < FIELDS_COUNT; i++ {
for i := 0; i < FieldsCount; i++ {
name := fk.Str(10)
fields[i] = ItemField{
Name: name,
@ -306,7 +305,7 @@ func TestItemRepository_GetAllCustomFields(t *testing.T) {
// Test getting all fields
{
results, err := tRepos.Items.GetAllCustomFieldNames(context.Background(), tGroup.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.ElementsMatch(t, names, results)
}
@ -314,7 +313,7 @@ func TestItemRepository_GetAllCustomFields(t *testing.T) {
{
results, err := tRepos.Items.GetAllCustomFieldValues(context.Background(), tUser.GroupID, names[0])
assert.NoError(t, err)
require.NoError(t, err)
assert.ElementsMatch(t, values[:1], results)
}
}

View file

@ -19,14 +19,14 @@ type LabelRepository struct {
type (
LabelCreate struct {
Name string `json:"name" validate:"required,min=1,max=255"`
Name string `json:"name" validate:"required,min=1,max=255"`
Description string `json:"description" validate:"max=255"`
Color string `json:"color"`
}
LabelUpdate struct {
ID uuid.UUID `json:"id"`
Name string `json:"name" validate:"required,min=1,max=255"`
Name string `json:"name" validate:"required,min=1,max=255"`
Description string `json:"description" validate:"max=255"`
Color string `json:"color"`
}
@ -87,28 +87,28 @@ func (r *LabelRepository) GetOneByGroup(ctx context.Context, gid, ld uuid.UUID)
return r.getOne(ctx, label.ID(ld), label.HasGroupWith(group.ID(gid)))
}
func (r *LabelRepository) GetAll(ctx context.Context, groupId uuid.UUID) ([]LabelSummary, error) {
func (r *LabelRepository) GetAll(ctx context.Context, groupID uuid.UUID) ([]LabelSummary, error) {
return mapLabelsOut(r.db.Label.Query().
Where(label.HasGroupWith(group.ID(groupId))).
Where(label.HasGroupWith(group.ID(groupID))).
Order(ent.Asc(label.FieldName)).
WithGroup().
All(ctx),
)
}
func (r *LabelRepository) Create(ctx context.Context, groupdId uuid.UUID, data LabelCreate) (LabelOut, error) {
func (r *LabelRepository) Create(ctx context.Context, groupID uuid.UUID, data LabelCreate) (LabelOut, error) {
label, err := r.db.Label.Create().
SetName(data.Name).
SetDescription(data.Description).
SetColor(data.Color).
SetGroupID(groupdId).
SetGroupID(groupID).
Save(ctx)
if err != nil {
return LabelOut{}, err
}
label.Edges.Group = &ent.Group{ID: groupdId} // bootstrap group ID
r.publishMutationEvent(groupdId)
label.Edges.Group = &ent.Group{ID: groupID} // bootstrap group ID
r.publishMutationEvent(groupID)
return mapLabelOut(label), err
}

View file

@ -5,6 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func labelFactory() LabelCreate {
@ -22,7 +23,7 @@ func useLabels(t *testing.T, len int) []LabelOut {
itm := labelFactory()
item, err := tRepos.Labels.Create(context.Background(), tGroup.ID, itm)
assert.NoError(t, err)
require.NoError(t, err)
labels[i] = item
}
@ -41,7 +42,7 @@ func TestLabelRepository_Get(t *testing.T) {
// Get by ID
foundLoc, err := tRepos.Labels.GetOne(context.Background(), label.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, label.ID, foundLoc.ID)
}
@ -49,26 +50,26 @@ func TestLabelRepositoryGetAll(t *testing.T) {
useLabels(t, 10)
all, err := tRepos.Labels.GetAll(context.Background(), tGroup.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, all, 10)
}
func TestLabelRepository_Create(t *testing.T) {
loc, err := tRepos.Labels.Create(context.Background(), tGroup.ID, labelFactory())
assert.NoError(t, err)
require.NoError(t, err)
// Get by ID
foundLoc, err := tRepos.Labels.GetOne(context.Background(), loc.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, loc.ID, foundLoc.ID)
err = tRepos.Labels.delete(context.Background(), loc.ID)
assert.NoError(t, err)
require.NoError(t, err)
}
func TestLabelRepository_Update(t *testing.T) {
loc, err := tRepos.Labels.Create(context.Background(), tGroup.ID, labelFactory())
assert.NoError(t, err)
require.NoError(t, err)
updateData := LabelUpdate{
ID: loc.ID,
@ -77,26 +78,26 @@ func TestLabelRepository_Update(t *testing.T) {
}
update, err := tRepos.Labels.UpdateByGroup(context.Background(), tGroup.ID, updateData)
assert.NoError(t, err)
require.NoError(t, err)
foundLoc, err := tRepos.Labels.GetOne(context.Background(), loc.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, update.ID, foundLoc.ID)
assert.Equal(t, update.Name, foundLoc.Name)
assert.Equal(t, update.Description, foundLoc.Description)
err = tRepos.Labels.delete(context.Background(), loc.ID)
assert.NoError(t, err)
require.NoError(t, err)
}
func TestLabelRepository_Delete(t *testing.T) {
loc, err := tRepos.Labels.Create(context.Background(), tGroup.ID, labelFactory())
assert.NoError(t, err)
require.NoError(t, err)
err = tRepos.Labels.delete(context.Background(), loc.ID)
assert.NoError(t, err)
require.NoError(t, err)
_, err = tRepos.Labels.GetOne(context.Background(), loc.ID)
assert.Error(t, err)
require.Error(t, err)
}

View file

@ -21,12 +21,12 @@ type LocationRepository struct {
type (
LocationCreate struct {
Name string `json:"name"`
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"`
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"`
Description string `json:"description"`
}
LocationUpdate struct {
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"`
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"`
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
@ -99,7 +99,7 @@ type LocationQuery struct {
FilterChildren bool `json:"filterChildren" schema:"filterChildren"`
}
// GetALlWithCount returns all locations with item count field populated
// GetAll returns all locations with item count field populated
func (r *LocationRepository) GetAll(ctx context.Context, GID uuid.UUID, filter LocationQuery) ([]LocationOutCount, error) {
query := `--sql
SELECT
@ -135,7 +135,7 @@ func (r *LocationRepository) GetAll(ctx context.Context, GID uuid.UUID, filter L
if err != nil {
return nil, err
}
defer rows.Close()
defer func() { _ = rows.Close() }()
list := []LocationOutCount{}
for rows.Next() {
@ -265,7 +265,7 @@ type LocationPath struct {
Name string `json:"name"`
}
func (lr *LocationRepository) PathForLoc(ctx context.Context, GID, locID uuid.UUID) ([]LocationPath, error) {
func (r *LocationRepository) PathForLoc(ctx context.Context, GID, locID uuid.UUID) ([]LocationPath, error) {
query := `WITH RECURSIVE location_path AS (
SELECT id, name, location_children
FROM locations
@ -282,11 +282,11 @@ func (lr *LocationRepository) PathForLoc(ctx context.Context, GID, locID uuid.UU
SELECT id, name
FROM location_path`
rows, err := lr.db.Sql().QueryContext(ctx, query, locID, GID)
rows, err := r.db.Sql().QueryContext(ctx, query, locID, GID)
if err != nil {
return nil, err
}
defer rows.Close()
defer func() { _ = rows.Close() }()
var locations []LocationPath
@ -311,7 +311,7 @@ func (lr *LocationRepository) PathForLoc(ctx context.Context, GID, locID uuid.UU
return locations, nil
}
func (lr *LocationRepository) Tree(ctx context.Context, GID uuid.UUID, tq TreeQuery) ([]TreeItem, error) {
func (r *LocationRepository) Tree(ctx context.Context, GID uuid.UUID, tq TreeQuery) ([]TreeItem, error) {
query := `
WITH recursive location_tree(id, NAME, parent_id, level, node_type) AS
(
@ -393,11 +393,11 @@ func (lr *LocationRepository) Tree(ctx context.Context, GID uuid.UUID, tq TreeQu
query = strings.ReplaceAll(query, "{{ WITH_ITEMS_FROM }}", "")
}
rows, err := lr.db.Sql().QueryContext(ctx, query, GID)
rows, err := r.db.Sql().QueryContext(ctx, query, GID)
if err != nil {
return nil, err
}
defer rows.Close()
defer func() { _ = rows.Close() }()
var locations []FlatTreeItem
for rows.Next() {

View file

@ -8,6 +8,7 @@ import (
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/data/ent"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func locationFactory() LocationCreate {
@ -24,7 +25,7 @@ func useLocations(t *testing.T, len int) []LocationOut {
for i := 0; i < len; i++ {
loc, err := tRepos.Locations.Create(context.Background(), tGroup.ID, locationFactory())
assert.NoError(t, err)
require.NoError(t, err)
out[i] = loc
}
@ -42,15 +43,15 @@ func useLocations(t *testing.T, len int) []LocationOut {
func TestLocationRepository_Get(t *testing.T) {
loc, err := tRepos.Locations.Create(context.Background(), tGroup.ID, locationFactory())
assert.NoError(t, err)
require.NoError(t, err)
// Get by ID
foundLoc, err := tRepos.Locations.Get(context.Background(), loc.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, loc.ID, foundLoc.ID)
err = tRepos.Locations.delete(context.Background(), loc.ID)
assert.NoError(t, err)
require.NoError(t, err)
}
func TestLocationRepositoryGetAllWithCount(t *testing.T) {
@ -63,10 +64,10 @@ func TestLocationRepositoryGetAllWithCount(t *testing.T) {
LocationID: result.ID,
})
assert.NoError(t, err)
require.NoError(t, err)
results, err := tRepos.Locations.GetAll(context.Background(), tGroup.ID, LocationQuery{})
assert.NoError(t, err)
require.NoError(t, err)
for _, loc := range results {
if loc.ID == result.ID {
@ -80,11 +81,11 @@ func TestLocationRepository_Create(t *testing.T) {
// Get by ID
foundLoc, err := tRepos.Locations.Get(context.Background(), loc.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, loc.ID, foundLoc.ID)
err = tRepos.Locations.delete(context.Background(), loc.ID)
assert.NoError(t, err)
require.NoError(t, err)
}
func TestLocationRepository_Update(t *testing.T) {
@ -97,27 +98,27 @@ func TestLocationRepository_Update(t *testing.T) {
}
update, err := tRepos.Locations.UpdateByGroup(context.Background(), tGroup.ID, updateData.ID, updateData)
assert.NoError(t, err)
require.NoError(t, err)
foundLoc, err := tRepos.Locations.Get(context.Background(), loc.ID)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, update.ID, foundLoc.ID)
assert.Equal(t, update.Name, foundLoc.Name)
assert.Equal(t, update.Description, foundLoc.Description)
err = tRepos.Locations.delete(context.Background(), loc.ID)
assert.NoError(t, err)
require.NoError(t, err)
}
func TestLocationRepository_Delete(t *testing.T) {
loc := useLocations(t, 1)[0]
err := tRepos.Locations.delete(context.Background(), loc.ID)
assert.NoError(t, err)
require.NoError(t, err)
_, err = tRepos.Locations.Get(context.Background(), loc.ID)
assert.Error(t, err)
require.Error(t, err)
}
func TestItemRepository_TreeQuery(t *testing.T) {
@ -130,18 +131,18 @@ func TestItemRepository_TreeQuery(t *testing.T) {
Name: locs[0].Name,
Description: locs[0].Description,
})
assert.NoError(t, err)
require.NoError(t, err)
locations, err := tRepos.Locations.Tree(context.Background(), tGroup.ID, TreeQuery{WithItems: true})
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, 2, len(locations))
assert.Len(t, locations, 2)
// Check roots
for _, loc := range locations {
if loc.ID == locs[1].ID {
assert.Equal(t, 1, len(loc.Children))
assert.Len(t, loc.Children, 1)
}
}
}
@ -157,15 +158,15 @@ func TestLocationRepository_PathForLoc(t *testing.T) {
Name: locs[i].Name,
Description: locs[i].Description,
})
assert.NoError(t, err)
require.NoError(t, err)
}
last := locs[0]
path, err := tRepos.Locations.PathForLoc(context.Background(), tGroup.ID, last.ID)
assert.NoError(t, err)
assert.Equal(t, 3, len(path))
require.NoError(t, err)
assert.Len(t, path, 3)
// Check path and order
for i, loc := range path {

View file

@ -23,7 +23,7 @@ type MaintenanceEntryRepository struct {
type MaintenanceEntryCreate struct {
CompletedDate types.Date `json:"completedDate"`
ScheduledDate types.Date `json:"scheduledDate"`
Name string `json:"name" validate:"required"`
Name string `json:"name" validate:"required"`
Description string `json:"description"`
Cost float64 `json:"cost,string"`
}
@ -152,7 +152,6 @@ func (r *MaintenanceEntryRepository) GetLog(ctx context.Context, groupID, itemID
maintenanceentry.DateNotNil(),
maintenanceentry.DateNEQ(time.Time{}),
))
} else if query.Scheduled {
q = q.Where(maintenanceentry.And(
maintenanceentry.Or(

View file

@ -7,6 +7,7 @@ import (
"github.com/hay-kot/homebox/backend/internal/data/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// get the previous month from the current month, accounts for errors when run
@ -67,7 +68,7 @@ func TestMaintenanceEntryRepository_GetLog(t *testing.T) {
}
assert.Equal(t, item.ID, log.ItemID)
assert.Equal(t, 10, len(log.Entries))
assert.Len(t, log.Entries, 10)
// Calculate the average cost
var total float64
@ -76,11 +77,11 @@ func TestMaintenanceEntryRepository_GetLog(t *testing.T) {
total += entry.Cost
}
assert.Equal(t, total, log.CostTotal, "total cost should be equal to the sum of all entries")
assert.Equal(t, total/2, log.CostAverage, "average cost should be the average of the two months")
assert.InDelta(t, total, log.CostTotal, .001, "total cost should be equal to the sum of all entries")
assert.InDelta(t, total/2, log.CostAverage, 001, "average cost should be the average of the two months")
for _, entry := range log.Entries {
err := tRepos.MaintEntry.Delete(context.Background(), entry.ID)
assert.NoError(t, err)
require.NoError(t, err)
}
}

View file

@ -35,15 +35,15 @@ func NewNotifierRepository(db *ent.Client) *NotifierRepository {
type (
NotifierCreate struct {
Name string `json:"name" validate:"required,min=1,max=255"`
Name string `json:"name" validate:"required,min=1,max=255"`
IsActive bool `json:"isActive"`
URL string `json:"url" validate:"required,shoutrrr"`
URL string `json:"url" validate:"required,shoutrrr"`
}
NotifierUpdate struct {
Name string `json:"name" validate:"required,min=1,max=255"`
Name string `json:"name" validate:"required,min=1,max=255"`
IsActive bool `json:"isActive"`
URL *string `json:"url" validate:"omitempty,shoutrrr" extensions:"x-nullable" `
URL *string `json:"url" validate:"omitempty,shoutrrr" extensions:"x-nullable"`
}
NotifierOut struct {

View file

@ -71,7 +71,7 @@ func (r *TokenRepository) GetRoles(ctx context.Context, token string) (*set.Set[
return &roleSet, nil
}
// Creates a token for a user
// CreateToken Creates a token for a user
func (r *TokenRepository) CreateToken(ctx context.Context, createToken UserAuthTokenCreate, roles ...authroles.Role) (UserAuthToken, error) {
dbToken, err := r.db.AuthTokens.Create().
SetToken(createToken.TokenHash).

View file

@ -7,15 +7,15 @@ import (
"github.com/hay-kot/homebox/backend/pkgs/hasher"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAuthTokenRepo_CreateToken(t *testing.T) {
asrt := assert.New(t)
ctx := context.Background()
user := userFactory()
userOut, err := tRepos.Users.Create(ctx, user)
asrt.NoError(err)
require.NoError(t, err)
expiresAt := time.Now().Add(time.Hour)
@ -27,23 +27,22 @@ func TestAuthTokenRepo_CreateToken(t *testing.T) {
UserID: userOut.ID,
})
asrt.NoError(err)
asrt.Equal(userOut.ID, token.UserID)
asrt.Equal(expiresAt, token.ExpiresAt)
require.NoError(t, err)
assert.Equal(t, userOut.ID, token.UserID)
assert.Equal(t, expiresAt, token.ExpiresAt)
// Cleanup
asrt.NoError(tRepos.Users.Delete(ctx, userOut.ID))
require.NoError(t, tRepos.Users.Delete(ctx, userOut.ID))
_, err = tRepos.AuthTokens.DeleteAll(ctx)
asrt.NoError(err)
require.NoError(t, err)
}
func TestAuthTokenRepo_DeleteToken(t *testing.T) {
asrt := assert.New(t)
ctx := context.Background()
user := userFactory()
userOut, err := tRepos.Users.Create(ctx, user)
asrt.NoError(err)
require.NoError(t, err)
expiresAt := time.Now().Add(time.Hour)
@ -54,15 +53,14 @@ func TestAuthTokenRepo_DeleteToken(t *testing.T) {
ExpiresAt: expiresAt,
UserID: userOut.ID,
})
asrt.NoError(err)
require.NoError(t, err)
// Delete token
err = tRepos.AuthTokens.DeleteToken(ctx, []byte(generatedToken.Raw))
asrt.NoError(err)
require.NoError(t, err)
}
func TestAuthTokenRepo_GetUserByToken(t *testing.T) {
assert := assert.New(t)
ctx := context.Background()
user := userFactory()
@ -77,24 +75,23 @@ func TestAuthTokenRepo_GetUserByToken(t *testing.T) {
UserID: userOut.ID,
})
assert.NoError(err)
require.NoError(t, err)
// Get User from token
foundUser, err := tRepos.AuthTokens.GetUserFromToken(ctx, token.TokenHash)
assert.NoError(err)
assert.Equal(userOut.ID, foundUser.ID)
assert.Equal(userOut.Name, foundUser.Name)
assert.Equal(userOut.Email, foundUser.Email)
require.NoError(t, err)
assert.Equal(t, userOut.ID, foundUser.ID)
assert.Equal(t, userOut.Name, foundUser.Name)
assert.Equal(t, userOut.Email, foundUser.Email)
// Cleanup
assert.NoError(tRepos.Users.Delete(ctx, userOut.ID))
require.NoError(t, tRepos.Users.Delete(ctx, userOut.ID))
_, err = tRepos.AuthTokens.DeleteAll(ctx)
assert.NoError(err)
require.NoError(t, err)
}
func TestAuthTokenRepo_PurgeExpiredTokens(t *testing.T) {
assert := assert.New(t)
ctx := context.Background()
user := userFactory()
@ -112,27 +109,26 @@ func TestAuthTokenRepo_PurgeExpiredTokens(t *testing.T) {
UserID: userOut.ID,
})
assert.NoError(err)
assert.NotNil(createdToken)
require.NoError(t, err)
assert.NotNil(t, createdToken)
createdTokens = append(createdTokens, createdToken)
}
// Purge expired tokens
tokensDeleted, err := tRepos.AuthTokens.PurgeExpiredTokens(ctx)
assert.NoError(err)
assert.Equal(5, tokensDeleted)
require.NoError(t, err)
assert.Equal(t, 5, tokensDeleted)
// Check if tokens are deleted
for _, token := range createdTokens {
_, err := tRepos.AuthTokens.GetUserFromToken(ctx, token.TokenHash)
assert.Error(err)
require.Error(t, err)
}
// Cleanup
assert.NoError(tRepos.Users.Delete(ctx, userOut.ID))
require.NoError(t, tRepos.Users.Delete(ctx, userOut.ID))
_, err = tRepos.AuthTokens.DeleteAll(ctx)
assert.NoError(err)
require.NoError(t, err)
}

View file

@ -60,32 +60,32 @@ func mapUserOut(user *ent.User) UserOut {
}
}
func (e *UserRepository) GetOneId(ctx context.Context, id uuid.UUID) (UserOut, error) {
return mapUserOutErr(e.db.User.Query().
Where(user.ID(id)).
func (r *UserRepository) GetOneID(ctx context.Context, ID uuid.UUID) (UserOut, error) {
return mapUserOutErr(r.db.User.Query().
Where(user.ID(ID)).
WithGroup().
Only(ctx))
}
func (e *UserRepository) GetOneEmail(ctx context.Context, email string) (UserOut, error) {
return mapUserOutErr(e.db.User.Query().
func (r *UserRepository) GetOneEmail(ctx context.Context, email string) (UserOut, error) {
return mapUserOutErr(r.db.User.Query().
Where(user.EmailEqualFold(email)).
WithGroup().
Only(ctx),
)
}
func (e *UserRepository) GetAll(ctx context.Context) ([]UserOut, error) {
return mapUsersOutErr(e.db.User.Query().WithGroup().All(ctx))
func (r *UserRepository) GetAll(ctx context.Context) ([]UserOut, error) {
return mapUsersOutErr(r.db.User.Query().WithGroup().All(ctx))
}
func (e *UserRepository) Create(ctx context.Context, usr UserCreate) (UserOut, error) {
func (r *UserRepository) Create(ctx context.Context, usr UserCreate) (UserOut, error) {
role := user.RoleUser
if usr.IsOwner {
role = user.RoleOwner
}
entUser, err := e.db.User.
entUser, err := r.db.User.
Create().
SetName(usr.Name).
SetEmail(usr.Email).
@ -98,11 +98,11 @@ func (e *UserRepository) Create(ctx context.Context, usr UserCreate) (UserOut, e
return UserOut{}, err
}
return e.GetOneId(ctx, entUser.ID)
return r.GetOneID(ctx, entUser.ID)
}
func (e *UserRepository) Update(ctx context.Context, ID uuid.UUID, data UserUpdate) error {
q := e.db.User.Update().
func (r *UserRepository) Update(ctx context.Context, ID uuid.UUID, data UserUpdate) error {
q := r.db.User.Update().
Where(user.ID(ID)).
SetName(data.Name).
SetEmail(data.Email)
@ -111,18 +111,18 @@ func (e *UserRepository) Update(ctx context.Context, ID uuid.UUID, data UserUpda
return err
}
func (e *UserRepository) Delete(ctx context.Context, id uuid.UUID) error {
_, err := e.db.User.Delete().Where(user.ID(id)).Exec(ctx)
func (r *UserRepository) Delete(ctx context.Context, id uuid.UUID) error {
_, err := r.db.User.Delete().Where(user.ID(id)).Exec(ctx)
return err
}
func (e *UserRepository) DeleteAll(ctx context.Context) error {
_, err := e.db.User.Delete().Exec(ctx)
func (r *UserRepository) DeleteAll(ctx context.Context) error {
_, err := r.db.User.Delete().Exec(ctx)
return err
}
func (e *UserRepository) GetSuperusers(ctx context.Context) ([]*ent.User, error) {
users, err := e.db.User.Query().Where(user.IsSuperuser(true)).All(ctx)
func (r *UserRepository) GetSuperusers(ctx context.Context) ([]*ent.User, error) {
users, err := r.db.User.Query().Where(user.IsSuperuser(true)).All(ctx)
if err != nil {
return nil, err
}

View file

@ -5,6 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func userFactory() UserCreate {
@ -23,18 +24,18 @@ func TestUserRepo_GetOneEmail(t *testing.T) {
ctx := context.Background()
_, err := tRepos.Users.Create(ctx, user)
assert.NoError(err)
require.NoError(t, err)
foundUser, err := tRepos.Users.GetOneEmail(ctx, user.Email)
assert.NotNil(foundUser)
assert.Nil(err)
require.NoError(t, err)
assert.Equal(user.Email, foundUser.Email)
assert.Equal(user.Name, foundUser.Name)
// Cleanup
err = tRepos.Users.DeleteAll(ctx)
assert.NoError(err)
require.NoError(t, err)
}
func TestUserRepo_GetOneId(t *testing.T) {
@ -43,16 +44,16 @@ func TestUserRepo_GetOneId(t *testing.T) {
ctx := context.Background()
userOut, _ := tRepos.Users.Create(ctx, user)
foundUser, err := tRepos.Users.GetOneId(ctx, userOut.ID)
foundUser, err := tRepos.Users.GetOneID(ctx, userOut.ID)
assert.NotNil(foundUser)
assert.Nil(err)
require.NoError(t, err)
assert.Equal(user.Email, foundUser.Email)
assert.Equal(user.Name, foundUser.Name)
// Cleanup
err = tRepos.Users.DeleteAll(ctx)
assert.NoError(err)
require.NoError(t, err)
}
func TestUserRepo_GetAll(t *testing.T) {
@ -76,7 +77,7 @@ func TestUserRepo_GetAll(t *testing.T) {
// Validate
allUsers, err := tRepos.Users.GetAll(ctx)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, len(created), len(allUsers))
for _, usr := range created {
@ -96,12 +97,12 @@ func TestUserRepo_GetAll(t *testing.T) {
// Cleanup
err = tRepos.Users.DeleteAll(ctx)
assert.NoError(t, err)
require.NoError(t, err)
}
func TestUserRepo_Update(t *testing.T) {
user, err := tRepos.Users.Create(context.Background(), userFactory())
assert.NoError(t, err)
require.NoError(t, err)
updateData := UserUpdate{
Name: fk.Str(10),
@ -110,11 +111,11 @@ func TestUserRepo_Update(t *testing.T) {
// Update
err = tRepos.Users.Update(context.Background(), user.ID, updateData)
assert.NoError(t, err)
require.NoError(t, err)
// Validate
updated, err := tRepos.Users.GetOneId(context.Background(), user.ID)
assert.NoError(t, err)
updated, err := tRepos.Users.GetOneID(context.Background(), user.ID)
require.NoError(t, err)
assert.NotEqual(t, user.Name, updated.Name)
assert.NotEqual(t, user.Email, updated.Email)
}
@ -131,12 +132,12 @@ func TestUserRepo_Delete(t *testing.T) {
ctx := context.Background()
allUsers, _ := tRepos.Users.GetAll(ctx)
assert.Greater(t, len(allUsers), 0)
assert.NotEmpty(t, allUsers)
err := tRepos.Users.DeleteAll(ctx)
assert.NoError(t, err)
require.NoError(t, err)
allUsers, _ = tRepos.Users.GetAll(ctx)
assert.Equal(t, len(allUsers), 0)
assert.Empty(t, allUsers)
}
func TestUserRepo_GetSuperusers(t *testing.T) {
@ -160,7 +161,7 @@ func TestUserRepo_GetSuperusers(t *testing.T) {
ctx := context.Background()
superUsers, err := tRepos.Users.GetSuperusers(ctx)
assert.NoError(t, err)
require.NoError(t, err)
for _, usr := range superUsers {
assert.True(t, usr.IsSuperuser)
@ -168,5 +169,5 @@ func TestUserRepo_GetSuperusers(t *testing.T) {
// Cleanup
err = tRepos.Users.DeleteAll(ctx)
assert.NoError(t, err)
require.NoError(t, err)
}

View file

@ -1,3 +1,4 @@
// Package repo provides the data access layer for the application.
package repo
import (

View file

@ -1,3 +1,4 @@
// Package types provides custom types for the application.
package types
import (