feat: user profiles (#32)

* add user profiles and theme selectors

* lowercase buttons by default

* basic layout

* (wip) init token APIs

* refactor server to support variable options

* fix types

* api refactor / registration tests

* implement UI for url and join

* remove console.logs

* rename repository factory

* fix upload size
This commit is contained in:
Hayden 2022-10-06 18:54:09 -08:00 committed by GitHub
parent 1ca430af21
commit 79f7ad40cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
76 changed files with 5154 additions and 388 deletions

View file

@ -19,7 +19,7 @@ var (
tClient *ent.Client
tRepos *AllRepos
tUser UserOut
tGroup *ent.Group
tGroup Group
)
func bootstrap() {
@ -28,7 +28,7 @@ func bootstrap() {
ctx = context.Background()
)
tGroup, err = tRepos.Groups.Create(ctx, "test-group")
tGroup, err = tRepos.Groups.GroupCreate(ctx, "test-group")
if err != nil {
log.Fatal(err)
}
@ -53,7 +53,7 @@ func TestMain(m *testing.M) {
}
tClient = client
tRepos = EntAllRepos(tClient, os.TempDir())
tRepos = New(tClient, os.TempDir())
defer client.Close()
bootstrap()

View file

@ -2,21 +2,112 @@ package repo
import (
"context"
"time"
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/ent"
"github.com/hay-kot/homebox/backend/ent/groupinvitationtoken"
)
type GroupRepository struct {
db *ent.Client
}
func (r *GroupRepository) Create(ctx context.Context, name string) (*ent.Group, error) {
return r.db.Group.Create().
SetName(name).
Save(ctx)
type (
Group struct {
ID uuid.UUID
Name string
CreatedAt time.Time
UpdatedAt time.Time
Currency string
}
GroupInvitationCreate struct {
Token []byte `json:"-"`
ExpiresAt time.Time `json:"expiresAt"`
Uses int `json:"uses"`
}
GroupInvitation struct {
ID uuid.UUID `json:"id"`
ExpiresAt time.Time `json:"expiresAt"`
Uses int `json:"uses"`
Group Group `json:"group"`
}
)
var (
mapToGroupErr = mapTErrFunc(mapToGroup)
)
func mapToGroup(g *ent.Group) Group {
return Group{
ID: g.ID,
Name: g.Name,
CreatedAt: g.CreatedAt,
UpdatedAt: g.UpdatedAt,
Currency: g.Currency.String(),
}
}
func (r *GroupRepository) GetOneId(ctx context.Context, id uuid.UUID) (*ent.Group, error) {
return r.db.Group.Get(ctx, id)
var (
mapToGroupInvitationErr = mapTErrFunc(mapToGroupInvitation)
)
func mapToGroupInvitation(g *ent.GroupInvitationToken) GroupInvitation {
return GroupInvitation{
ID: g.ID,
ExpiresAt: g.ExpiresAt,
Uses: g.Uses,
Group: mapToGroup(g.Edges.Group),
}
}
func (r *GroupRepository) GroupCreate(ctx context.Context, name string) (Group, error) {
return mapToGroupErr(r.db.Group.Create().
SetName(name).
Save(ctx))
}
func (r *GroupRepository) GroupByID(ctx context.Context, id uuid.UUID) (Group, error) {
return mapToGroupErr(r.db.Group.Get(ctx, id))
}
func (r *GroupRepository) InvitationGet(ctx context.Context, token []byte) (GroupInvitation, error) {
return mapToGroupInvitationErr(r.db.GroupInvitationToken.Query().
Where(groupinvitationtoken.Token(token)).
WithGroup().
Only(ctx))
}
func (r *GroupRepository) InvitationCreate(ctx context.Context, groupID uuid.UUID, invite GroupInvitationCreate) (GroupInvitation, error) {
entity, err := r.db.GroupInvitationToken.Create().
SetGroupID(groupID).
SetToken(invite.Token).
SetExpiresAt(invite.ExpiresAt).
SetUses(invite.Uses).
Save(ctx)
if err != nil {
return GroupInvitation{}, err
}
return r.InvitationGet(ctx, entity.Token)
}
func (r *GroupRepository) InvitationUpdate(ctx context.Context, id uuid.UUID, uses int) error {
_, err := r.db.GroupInvitationToken.UpdateOneID(id).SetUses(uses).Save(ctx)
return err
}
// InvitationPurge removes all expired invitations or those that have been used up.
// It returns the number of deleted invitations.
func (r *GroupRepository) InvitationPurge(ctx context.Context) (amount int, err error) {
q := r.db.GroupInvitationToken.Delete()
q.Where(groupinvitationtoken.Or(
groupinvitationtoken.ExpiresAtLT(time.Now()),
groupinvitationtoken.UsesLTE(0),
))
return q.Exec(ctx)
}

View file

@ -8,13 +8,13 @@ import (
)
func Test_Group_Create(t *testing.T) {
g, err := tRepos.Groups.Create(context.Background(), "test")
g, err := tRepos.Groups.GroupCreate(context.Background(), "test")
assert.NoError(t, err)
assert.Equal(t, "test", g.Name)
// Get by ID
foundGroup, err := tRepos.Groups.GetOneId(context.Background(), g.ID)
foundGroup, err := tRepos.Groups.GroupByID(context.Background(), g.ID)
assert.NoError(t, err)
assert.Equal(t, g.ID, foundGroup.ID)
}

View file

@ -15,7 +15,7 @@ type AllRepos struct {
Attachments *AttachmentRepo
}
func EntAllRepos(db *ent.Client, root string) *AllRepos {
func New(db *ent.Client, root string) *AllRepos {
return &AllRepos{
Users: &UserRepository{db},
AuthTokens: &TokenRepository{db},