forked from mirrors/homebox
setup location repository
This commit is contained in:
parent
630fe83de5
commit
9583847f94
11 changed files with 267 additions and 25 deletions
|
@ -12,8 +12,23 @@ import (
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var testEntClient *ent.Client
|
var (
|
||||||
var testRepos *AllRepos
|
testEntClient *ent.Client
|
||||||
|
testRepos *AllRepos
|
||||||
|
testUser *ent.User
|
||||||
|
testGroup *ent.Group
|
||||||
|
)
|
||||||
|
|
||||||
|
func bootstrap() {
|
||||||
|
ctx := context.Background()
|
||||||
|
testGroup, _ = testRepos.Groups.Create(ctx, "test-group")
|
||||||
|
testUser, _ = testRepos.Users.Create(ctx, UserFactory())
|
||||||
|
|
||||||
|
if testGroup == nil || testUser == nil {
|
||||||
|
log.Fatal("Failed to bootstrap test data")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
rand.Seed(int64(time.Now().Unix()))
|
rand.Seed(int64(time.Now().Unix()))
|
||||||
|
@ -29,10 +44,9 @@ func TestMain(m *testing.M) {
|
||||||
|
|
||||||
testEntClient = client
|
testEntClient = client
|
||||||
testRepos = EntAllRepos(testEntClient)
|
testRepos = EntAllRepos(testEntClient)
|
||||||
|
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
m.Run()
|
bootstrap()
|
||||||
|
|
||||||
os.Exit(m.Run())
|
os.Exit(m.Run())
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,18 +12,9 @@ type EntGroupRepository struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *EntGroupRepository) Create(ctx context.Context, name string) (*ent.Group, error) {
|
func (r *EntGroupRepository) Create(ctx context.Context, name string) (*ent.Group, error) {
|
||||||
dbGroup, err := r.db.Group.Create().SetName(name).Save(ctx)
|
return r.db.Group.Create().SetName(name).Save(ctx)
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return dbGroup, err
|
|
||||||
}
|
|
||||||
return dbGroup, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *EntGroupRepository) GetOneId(ctx context.Context, id uuid.UUID) (*ent.Group, error) {
|
func (r *EntGroupRepository) GetOneId(ctx context.Context, id uuid.UUID) (*ent.Group, error) {
|
||||||
dbGroup, err := r.db.Group.Get(ctx, id)
|
return r.db.Group.Get(ctx, id)
|
||||||
if err != nil {
|
|
||||||
return dbGroup, err
|
|
||||||
}
|
|
||||||
return dbGroup, nil
|
|
||||||
}
|
}
|
||||||
|
|
20
backend/internal/repo/repo_group_test.go
Normal file
20
backend/internal/repo/repo_group_test.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Group_Create(t *testing.T) {
|
||||||
|
g, err := testRepos.Groups.Create(context.Background(), "test")
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "test", g.Name)
|
||||||
|
|
||||||
|
// Get by ID
|
||||||
|
foundGroup, err := testRepos.Groups.GetOneId(context.Background(), g.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, g.ID, foundGroup.ID)
|
||||||
|
}
|
47
backend/internal/repo/repo_locations.go
Normal file
47
backend/internal/repo/repo_locations.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/hay-kot/content/backend/ent"
|
||||||
|
"github.com/hay-kot/content/backend/ent/group"
|
||||||
|
"github.com/hay-kot/content/backend/ent/location"
|
||||||
|
"github.com/hay-kot/content/backend/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EntLocationRepository struct {
|
||||||
|
db *ent.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *EntLocationRepository) Get(ctx context.Context, ID uuid.UUID) (*ent.Location, error) {
|
||||||
|
return r.db.Location.Get(ctx, ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *EntLocationRepository) GetAll(ctx context.Context, groupId uuid.UUID) ([]*ent.Location, error) {
|
||||||
|
return r.db.Location.Query().
|
||||||
|
Where(location.HasGroupWith(group.ID(groupId))).
|
||||||
|
All(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *EntLocationRepository) Create(ctx context.Context, groupdId uuid.UUID, data types.LocationCreate) (*ent.Location, error) {
|
||||||
|
location, err := r.db.Location.Create().
|
||||||
|
SetName(data.Name).
|
||||||
|
SetDescription(data.Description).
|
||||||
|
SetGroupID(groupdId).
|
||||||
|
Save(ctx)
|
||||||
|
|
||||||
|
location.Edges.Group = &ent.Group{ID: groupdId} // bootstrap group ID
|
||||||
|
return location, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *EntLocationRepository) Update(ctx context.Context, data types.LocationUpdate) (*ent.Location, error) {
|
||||||
|
return r.db.Location.UpdateOneID(data.ID).
|
||||||
|
SetName(data.Name).
|
||||||
|
SetDescription(data.Description).
|
||||||
|
Save(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *EntLocationRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
||||||
|
return r.db.Location.DeleteOneID(id).Exec(ctx)
|
||||||
|
}
|
100
backend/internal/repo/repo_locations_test.go
Normal file
100
backend/internal/repo/repo_locations_test.go
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hay-kot/content/backend/ent"
|
||||||
|
"github.com/hay-kot/content/backend/internal/types"
|
||||||
|
"github.com/hay-kot/content/backend/pkgs/faker"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
var fk = faker.NewFaker()
|
||||||
|
|
||||||
|
func locationFactory() types.LocationCreate {
|
||||||
|
return types.LocationCreate{
|
||||||
|
Name: fk.RandomString(10),
|
||||||
|
Description: fk.RandomString(100),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Locations_Get(t *testing.T) {
|
||||||
|
loc, err := testRepos.Locations.Create(context.Background(), testGroup.ID, locationFactory())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Get by ID
|
||||||
|
foundLoc, err := testRepos.Locations.Get(context.Background(), loc.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, loc.ID, foundLoc.ID)
|
||||||
|
|
||||||
|
testRepos.Locations.Delete(context.Background(), loc.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Locations_GetAll(t *testing.T) {
|
||||||
|
created := make([]*ent.Location, 6)
|
||||||
|
|
||||||
|
for i := 0; i < 6; i++ {
|
||||||
|
result, err := testRepos.Locations.Create(context.Background(), testGroup.ID, types.LocationCreate{
|
||||||
|
Name: fk.RandomString(10),
|
||||||
|
Description: fk.RandomString(100),
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
created[i] = result
|
||||||
|
}
|
||||||
|
|
||||||
|
locations, err := testRepos.Locations.GetAll(context.Background(), testGroup.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 6, len(locations))
|
||||||
|
|
||||||
|
for _, loc := range created {
|
||||||
|
testRepos.Locations.Delete(context.Background(), loc.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Locations_Create(t *testing.T) {
|
||||||
|
loc, err := testRepos.Locations.Create(context.Background(), testGroup.ID, locationFactory())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Get by ID
|
||||||
|
foundLoc, err := testRepos.Locations.Get(context.Background(), loc.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, loc.ID, foundLoc.ID)
|
||||||
|
|
||||||
|
testRepos.Locations.Delete(context.Background(), loc.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Locations_Update(t *testing.T) {
|
||||||
|
loc, err := testRepos.Locations.Create(context.Background(), testGroup.ID, locationFactory())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
updateData := types.LocationUpdate{
|
||||||
|
ID: loc.ID,
|
||||||
|
Name: fk.RandomString(10),
|
||||||
|
Description: fk.RandomString(100),
|
||||||
|
}
|
||||||
|
|
||||||
|
update, err := testRepos.Locations.Update(context.Background(), updateData)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
foundLoc, err := testRepos.Locations.Get(context.Background(), loc.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, update.ID, foundLoc.ID)
|
||||||
|
assert.Equal(t, update.Name, foundLoc.Name)
|
||||||
|
assert.Equal(t, update.Description, foundLoc.Description)
|
||||||
|
|
||||||
|
testRepos.Locations.Delete(context.Background(), loc.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Locations_Delete(t *testing.T) {
|
||||||
|
loc, err := testRepos.Locations.Create(context.Background(), testGroup.ID, locationFactory())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = testRepos.Locations.Delete(context.Background(), loc.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = testRepos.Locations.Get(context.Background(), loc.ID)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
|
@ -16,7 +16,8 @@ func Test_EntAuthTokenRepo_CreateToken(t *testing.T) {
|
||||||
|
|
||||||
user := UserFactory()
|
user := UserFactory()
|
||||||
|
|
||||||
userOut, _ := testRepos.Users.Create(ctx, user)
|
userOut, err := testRepos.Users.Create(ctx, user)
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
expiresAt := time.Now().Add(time.Hour)
|
expiresAt := time.Now().Add(time.Hour)
|
||||||
|
|
||||||
|
@ -33,8 +34,8 @@ func Test_EntAuthTokenRepo_CreateToken(t *testing.T) {
|
||||||
assert.Equal(expiresAt, token.ExpiresAt)
|
assert.Equal(expiresAt, token.ExpiresAt)
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
err = testRepos.Users.Delete(ctx, userOut.ID)
|
testRepos.Users.Delete(ctx, userOut.ID)
|
||||||
_, err = testRepos.AuthTokens.DeleteAll(ctx)
|
testRepos.AuthTokens.DeleteAll(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_EntAuthTokenRepo_GetUserByToken(t *testing.T) {
|
func Test_EntAuthTokenRepo_GetUserByToken(t *testing.T) {
|
||||||
|
@ -53,6 +54,8 @@ func Test_EntAuthTokenRepo_GetUserByToken(t *testing.T) {
|
||||||
UserID: userOut.ID,
|
UserID: userOut.ID,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
// Get User from token
|
// Get User from token
|
||||||
foundUser, err := testRepos.AuthTokens.GetUserFromToken(ctx, token.TokenHash)
|
foundUser, err := testRepos.AuthTokens.GetUserFromToken(ctx, token.TokenHash)
|
||||||
|
|
||||||
|
@ -62,8 +65,8 @@ func Test_EntAuthTokenRepo_GetUserByToken(t *testing.T) {
|
||||||
assert.Equal(userOut.Email, foundUser.Email)
|
assert.Equal(userOut.Email, foundUser.Email)
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
err = testRepos.Users.Delete(ctx, userOut.ID)
|
testRepos.Users.Delete(ctx, userOut.ID)
|
||||||
_, err = testRepos.AuthTokens.DeleteAll(ctx)
|
testRepos.AuthTokens.DeleteAll(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_EntAuthTokenRepo_PurgeExpiredTokens(t *testing.T) {
|
func Test_EntAuthTokenRepo_PurgeExpiredTokens(t *testing.T) {
|
||||||
|
@ -105,6 +108,6 @@ func Test_EntAuthTokenRepo_PurgeExpiredTokens(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
err = testRepos.Users.Delete(ctx, userOut.ID)
|
testRepos.Users.Delete(ctx, userOut.ID)
|
||||||
_, err = testRepos.AuthTokens.DeleteAll(ctx)
|
testRepos.AuthTokens.DeleteAll(ctx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ func (e *EntUserRepository) GetOneEmail(ctx context.Context, email string) (*ent
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EntUserRepository) GetAll(ctx context.Context) ([]*ent.User, error) {
|
func (e *EntUserRepository) GetAll(ctx context.Context) ([]*ent.User, error) {
|
||||||
users, err := e.db.User.Query().All(ctx)
|
users, err := e.db.User.Query().WithGroup().All(ctx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -13,11 +13,13 @@ import (
|
||||||
|
|
||||||
func UserFactory() types.UserCreate {
|
func UserFactory() types.UserCreate {
|
||||||
f := faker.NewFaker()
|
f := faker.NewFaker()
|
||||||
|
|
||||||
return types.UserCreate{
|
return types.UserCreate{
|
||||||
Name: f.RandomString(10),
|
Name: f.RandomString(10),
|
||||||
Email: f.RandomEmail(),
|
Email: f.RandomEmail(),
|
||||||
Password: f.RandomString(10),
|
Password: f.RandomString(10),
|
||||||
IsSuperuser: f.RandomBool(),
|
IsSuperuser: f.RandomBool(),
|
||||||
|
GroupID: testGroup.ID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,12 +79,19 @@ func Test_EntUserRepo_GetAll(t *testing.T) {
|
||||||
// Validate
|
// Validate
|
||||||
allUsers, err := testRepos.Users.GetAll(ctx)
|
allUsers, err := testRepos.Users.GetAll(ctx)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, len(created), len(allUsers))
|
assert.Equal(t, len(created), len(allUsers))
|
||||||
|
|
||||||
for _, usr := range created {
|
for _, usr := range created {
|
||||||
fmt.Printf("%+v\n", usr)
|
fmt.Printf("%+v\n", usr)
|
||||||
assert.Contains(t, allUsers, usr)
|
for _, usr2 := range allUsers {
|
||||||
|
if usr.ID == usr2.ID {
|
||||||
|
assert.Equal(t, usr.Email, usr2.Email)
|
||||||
|
|
||||||
|
// Check groups are loaded
|
||||||
|
assert.NotNil(t, usr2.Edges.Group)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, usr := range created {
|
for _, usr := range created {
|
||||||
|
|
|
@ -7,6 +7,7 @@ type AllRepos struct {
|
||||||
Users *EntUserRepository
|
Users *EntUserRepository
|
||||||
AuthTokens *EntTokenRepository
|
AuthTokens *EntTokenRepository
|
||||||
Groups *EntGroupRepository
|
Groups *EntGroupRepository
|
||||||
|
Locations *EntLocationRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func EntAllRepos(db *ent.Client) *AllRepos {
|
func EntAllRepos(db *ent.Client) *AllRepos {
|
||||||
|
@ -14,5 +15,6 @@ func EntAllRepos(db *ent.Client) *AllRepos {
|
||||||
Users: &EntUserRepository{db},
|
Users: &EntUserRepository{db},
|
||||||
AuthTokens: &EntTokenRepository{db},
|
AuthTokens: &EntTokenRepository{db},
|
||||||
Groups: &EntGroupRepository{db},
|
Groups: &EntGroupRepository{db},
|
||||||
|
Locations: &EntLocationRepository{db},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
29
backend/internal/services/service_locations.go
Normal file
29
backend/internal/services/service_locations.go
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/hay-kot/content/backend/ent"
|
||||||
|
"github.com/hay-kot/content/backend/internal/repo"
|
||||||
|
"github.com/hay-kot/content/backend/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LocationService struct {
|
||||||
|
repos *repo.AllRepos
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToLocationOut(location *ent.Location, err error) (*types.LocationOut, error) {
|
||||||
|
return &types.LocationOut{
|
||||||
|
ID: location.ID,
|
||||||
|
GroupID: location.Edges.Group.ID,
|
||||||
|
Name: location.Name,
|
||||||
|
Description: location.Description,
|
||||||
|
CreatedAt: location.CreatedAt,
|
||||||
|
UpdatedAt: location.UpdatedAt,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svc *LocationService) GetAll(ctx context.Context, groupId uuid.UUID) ([]*types.LocationOut, error) {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
27
backend/internal/types/location_types.go
Normal file
27
backend/internal/types/location_types.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LocationCreate struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LocationUpdate struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LocationOut struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
GroupID uuid.UUID `json:"groupId"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
|
}
|
Loading…
Reference in a new issue