You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
auth2/cmd/microauth2sqld/db/user.go

161 lines
4.0 KiB
Go

package db
import (
"context"
"time"
"github.com/google/uuid"
"github.com/uptrace/bun"
"jochum.dev/jo-micro/auth2/internal/ibun"
)
type User struct {
bun.BaseModel `bun:"users,alias:u"`
ID uuid.UUID `bun:"id,pk,type:uuid,default:uuid_generate_v4()" json:"id" yaml:"id"`
Username string `bun:"username" json:"username" yaml:"username"`
Password string `bun:"password" json:"-" yaml:"-"`
Email string `bun:"email" json:"email" yaml:"email"`
Roles []string `bun:",array,scanonly" json:"roles" yaml:"roles"`
// Timestamps
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at" yaml:"created_at"`
UpdatedAt bun.NullTime `bun:"updated_at" json:"updated_at" yaml:"updated_at"`
// SoftDelete
DeletedAt bun.NullTime `bun:"deleted_at,soft_delete,nullzero" json:"deleted_at" yaml:"deleted_at"`
}
func UserList(ctx context.Context, limit, offset uint64) ([]User, error) {
// Get the data from the db.
var users []User
err := ibun.Bun.NewSelect().
Model(&users).
ColumnExpr("u.*").
ColumnExpr("array(SELECT r.name FROM users_roles AS ur LEFT JOIN roles AS r ON ur.role_id = r.id WHERE ur.user_id = u.id) AS roles").
Limit(int(limit)).
Offset(int(offset)).Scan(ctx)
if err != nil {
return nil, err
}
return users, nil
}
func UserDetail(ctx context.Context, id string) (*User, error) {
user := User{}
err := ibun.Bun.NewSelect().
Model(&user).
ColumnExpr("u.*").
ColumnExpr("array(SELECT r.name FROM users_roles AS ur LEFT JOIN roles AS r ON ur.role_id = r.id WHERE ur.user_id = u.id) AS roles").
Limit(1).
Where("id = ?", id).
Scan(ctx)
if err != nil {
return nil, err
}
return &user, nil
}
func UserDelete(ctx context.Context, id string) error {
user := User{}
_, err := ibun.Bun.NewDelete().Model(&user).Where("id = ?", id).Exec(ctx)
return err
}
func UserUpdateRoles(ctx context.Context, id string, roles []string) (*User, error) {
// Check if all new roles exists
rolesIds := make([]string, len(roles))
for idx, role := range roles {
id, err := RoleGetId(ctx, role)
if err != nil {
return nil, err
}
rolesIds[idx] = id
}
// Delete all current roles
_, err := ibun.Bun.NewDelete().Table("users_roles").Where("user_id = ?", id).Exec(ctx)
if err != nil {
return nil, err
}
// Exit out if user wants to delete all roles
if len(roles) < 1 {
return UserDetail(ctx, id)
}
// Reassign roles
for _, roleId := range rolesIds {
values := map[string]interface{}{
"user_id": id,
"role_id": roleId,
}
_, err = ibun.Bun.NewInsert().Model(&values).TableExpr("users_roles").Exec(ctx)
if err != nil {
return nil, err
}
}
return UserDetail(ctx, id)
}
func UserFindByUsername(ctx context.Context, username string) (*User, error) {
user := User{}
err := ibun.Bun.NewSelect().
Model(&user).
ColumnExpr("u.*").
ColumnExpr("array(SELECT r.name FROM users_roles AS ur LEFT JOIN roles AS r ON ur.role_id = r.id WHERE ur.user_id = u.id) AS roles").
Limit(1).
Where("u.username = ?", username).
Scan(ctx)
if err != nil {
return nil, err
}
return &user, nil
}
func UserFindById(ctx context.Context, id string) (*User, error) {
user := User{}
err := ibun.Bun.NewSelect().
Model(&user).
ColumnExpr("u.*").
ColumnExpr("array(SELECT r.name FROM users_roles AS ur LEFT JOIN roles AS r ON ur.role_id = r.id WHERE ur.user_id = u.id) AS roles").
Limit(1).
Where("u.id = ?", id).
Scan(ctx)
if err != nil {
return nil, err
}
return &user, nil
}
func UserCreate(ctx context.Context, username, password, email string, roles []string) (*User, error) {
// Create the user
user := User{}
user.Username = username
user.Password = password
user.Email = email
_, err := ibun.Bun.NewInsert().Model(&user).Exec(ctx, &user)
if err != nil {
return nil, err
}
// Create roles
_, err = UserUpdateRoles(ctx, user.ID.String(), roles)
if err != nil {
if len(user.ID.String()) > 0 {
UserDelete(ctx, user.ID.String())
}
return nil, err
}
return &user, nil
}