homebox/backend/internal/repo/repo_users.go
Hayden a6d2fd45df
feat: change password (#35)
* refactor: implement factories for testing

* add additional factories

* change protection for dropFields

* prevent timed attacks on login

* use switch instead of else-if

* API implementation for changing password

* add change-password dialog
2022-10-09 09:23:21 -08:00

127 lines
3.1 KiB
Go

package repo
import (
"context"
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/ent"
"github.com/hay-kot/homebox/backend/ent/user"
)
type UserRepository struct {
db *ent.Client
}
type (
// UserCreate is the Data object contain the requirements of creating a user
// in the database. It should to create users from an API unless the user has
// rights to create SuperUsers. For regular user in data use the UserIn struct.
UserCreate struct {
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"password"`
IsSuperuser bool `json:"isSuperuser"`
GroupID uuid.UUID `json:"groupID"`
}
UserUpdate struct {
Name string `json:"name"`
Email string `json:"email"`
}
UserOut struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
IsSuperuser bool `json:"isSuperuser"`
GroupID uuid.UUID `json:"groupId"`
GroupName string `json:"groupName"`
PasswordHash string `json:"-"`
}
)
var (
mapUserOutErr = mapTErrFunc(mapUserOut)
mapUsersOutErr = mapTEachErrFunc(mapUserOut)
)
func mapUserOut(user *ent.User) UserOut {
return UserOut{
ID: user.ID,
Name: user.Name,
Email: user.Email,
IsSuperuser: user.IsSuperuser,
GroupID: user.Edges.Group.ID,
GroupName: user.Edges.Group.Name,
PasswordHash: user.Password,
}
}
func (e *UserRepository) GetOneId(ctx context.Context, id uuid.UUID) (UserOut, error) {
return mapUserOutErr(e.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().
Where(user.Email(email)).
WithGroup().
Only(ctx),
)
}
func (e *UserRepository) GetAll(ctx context.Context) ([]UserOut, error) {
return mapUsersOutErr(e.db.User.Query().WithGroup().All(ctx))
}
func (e *UserRepository) Create(ctx context.Context, usr UserCreate) (UserOut, error) {
entUser, err := e.db.User.
Create().
SetName(usr.Name).
SetEmail(usr.Email).
SetPassword(usr.Password).
SetIsSuperuser(usr.IsSuperuser).
SetGroupID(usr.GroupID).
Save(ctx)
if err != nil {
return UserOut{}, err
}
return e.GetOneId(ctx, entUser.ID)
}
func (e *UserRepository) Update(ctx context.Context, ID uuid.UUID, data UserUpdate) error {
q := e.db.User.Update().
Where(user.ID(ID)).
SetName(data.Name).
SetEmail(data.Email)
_, err := q.Save(ctx)
return err
}
func (e *UserRepository) Delete(ctx context.Context, id uuid.UUID) error {
_, err := e.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)
return err
}
func (e *UserRepository) GetSuperusers(ctx context.Context) ([]*ent.User, error) {
users, err := e.db.User.Query().Where(user.IsSuperuser(true)).All(ctx)
if err != nil {
return nil, err
}
return users, nil
}
func (r *UserRepository) ChangePassword(ctx context.Context, UID uuid.UUID, pw string) error {
return r.db.User.UpdateOneID(UID).SetPassword(pw).Exec(ctx)
}