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

@ -21,7 +21,7 @@ var (
tClient *ent.Client
tRepos *repo.AllRepos
tUser repo.UserOut
tGroup *ent.Group
tGroup repo.Group
tSvc *AllServices
)
@ -31,7 +31,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)
}
@ -62,7 +62,7 @@ func TestMain(m *testing.M) {
}
tClient = client
tRepos = repo.EntAllRepos(tClient, os.TempDir()+"/homebox")
tRepos = repo.New(tClient, os.TempDir()+"/homebox")
tSvc = NewServices(tRepos)
defer client.Close()

View file

@ -24,20 +24,16 @@ type UserService struct {
type (
UserRegistration struct {
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"password"`
GroupName string `json:"groupName"`
GroupToken string `json:"token"`
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"password"`
GroupName string `json:"groupName"`
}
UserAuthTokenDetail struct {
Raw string `json:"raw"`
ExpiresAt time.Time `json:"expiresAt"`
}
UserAuthTokenCreate struct {
TokenHash []byte `json:"token"`
UserID uuid.UUID `json:"userId"`
ExpiresAt time.Time `json:"expiresAt"`
}
LoginForm struct {
Username string `json:"username"`
Password string `json:"password"`
@ -51,11 +47,28 @@ func (svc *UserService) RegisterUser(ctx context.Context, data UserRegistration)
Str("name", data.Name).
Str("email", data.Email).
Str("groupName", data.GroupName).
Str("groupToken", data.GroupToken).
Msg("Registering new user")
group, err := svc.repos.Groups.Create(ctx, data.GroupName)
if err != nil {
return repo.UserOut{}, err
var (
err error
group repo.Group
token repo.GroupInvitation
)
if data.GroupToken == "" {
group, err = svc.repos.Groups.GroupCreate(ctx, data.GroupName)
if err != nil {
log.Err(err).Msg("Failed to create group")
return repo.UserOut{}, err
}
} else {
token, err = svc.repos.Groups.InvitationGet(ctx, hasher.HashToken(data.GroupToken))
if err != nil {
log.Err(err).Msg("Failed to get invitation token")
return repo.UserOut{}, err
}
group = token.Group
}
hashed, _ := hasher.HashPassword(data.Password)
@ -86,6 +99,15 @@ func (svc *UserService) RegisterUser(ctx context.Context, data UserRegistration)
}
}
// Decrement the invitation token if it was used
if token.ID != uuid.Nil {
err = svc.repos.Groups.InvitationUpdate(ctx, token.ID, token.Uses-1)
if err != nil {
log.Err(err).Msg("Failed to update invitation token")
return repo.UserOut{}, err
}
}
return usr, nil
}
@ -155,3 +177,18 @@ func (svc *UserService) RenewToken(ctx context.Context, token string) (UserAuthT
func (svc *UserService) DeleteSelf(ctx context.Context, ID uuid.UUID) error {
return svc.repos.Users.Delete(ctx, ID)
}
func (svc *UserService) NewInvitation(ctx Context, uses int, expiresAt time.Time) (string, error) {
token := hasher.GenerateToken()
_, err := svc.repos.Groups.InvitationCreate(ctx, ctx.GID, repo.GroupInvitationCreate{
Token: token.Hash,
Uses: uses,
ExpiresAt: expiresAt,
})
if err != nil {
return "", err
}
return token.Raw, nil
}