Files
silo-server/internal/auth/account_provisioner.go
T

100 lines
2.1 KiB
Go

package auth
import (
"context"
"fmt"
"strings"
"github.com/Silo-Server/silo-server/internal/models"
"github.com/Silo-Server/silo-server/internal/userstore"
)
type AccountUserRepository interface {
Create(ctx context.Context, input models.CreateUserInput) (*models.User, error)
Delete(ctx context.Context, id int) error
}
type DefaultProfileOptions struct {
Enabled bool
Name string
}
type CreateAccountInput struct {
User models.CreateUserInput
DefaultProfile DefaultProfileOptions
}
type AccountProvisioner struct {
users AccountUserRepository
storeProvider userstore.UserStoreProvider
}
func NewAccountProvisioner(
users AccountUserRepository,
storeProvider userstore.UserStoreProvider,
) *AccountProvisioner {
return &AccountProvisioner{
users: users,
storeProvider: storeProvider,
}
}
func (p *AccountProvisioner) CreateAccount(
ctx context.Context,
input CreateAccountInput,
) (*models.User, error) {
user, err := p.users.Create(ctx, input.User)
if err != nil {
return nil, err
}
if !input.DefaultProfile.Enabled {
return user, nil
}
if err := p.createDefaultProfile(ctx, user.ID, input); err != nil {
if deleteErr := p.users.Delete(ctx, user.ID); deleteErr != nil {
return nil, fmt.Errorf(
"create default profile: %w (cleanup user: %v)",
err,
deleteErr,
)
}
return nil, fmt.Errorf("create default profile: %w", err)
}
return user, nil
}
func (p *AccountProvisioner) createDefaultProfile(
ctx context.Context,
userID int,
input CreateAccountInput,
) error {
if p.storeProvider == nil {
return fmt.Errorf("user store provider unavailable")
}
store, err := p.storeProvider.ForUser(ctx, userID)
if err != nil {
return fmt.Errorf("open user store: %w", err)
}
name := strings.TrimSpace(input.DefaultProfile.Name)
if name == "" {
name = strings.TrimSpace(input.User.Username)
}
if name == "" {
return fmt.Errorf("default profile name is required")
}
if err := store.CreateProfile(ctx, userstore.Profile{
Name: name,
ShowForcedSubtitles: true,
}); err != nil {
return fmt.Errorf("store profile: %w", err)
}
return nil
}