57 lines
1.5 KiB
Go
57 lines
1.5 KiB
Go
package usecase
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/emil28092005/SciMesh/users/internal/domain"
|
|
)
|
|
|
|
const (
|
|
// minPasswordLen is a floor, not a policy engine — enough to reject the
|
|
// obviously weak without pretending to measure real strength.
|
|
minPasswordLen = 8
|
|
// maxPasswordLen is bcrypt's hard input limit: it ignores bytes past 72, so
|
|
// accepting a longer password would silently hash only its prefix.
|
|
maxPasswordLen = 72
|
|
)
|
|
|
|
// Register creates a new account: it validates the password, hashes it, builds
|
|
// the domain user, and persists it.
|
|
type Register struct {
|
|
users UserRepository
|
|
hasher PasswordHasher
|
|
clk Clock
|
|
}
|
|
|
|
func NewRegister(users UserRepository, hasher PasswordHasher, clk Clock) *Register {
|
|
return &Register{users: users, hasher: hasher, clk: clk}
|
|
}
|
|
|
|
// Execute registers email/password and returns the persisted user. The returned
|
|
// user carries no plaintext password, only its hash.
|
|
func (r *Register) Execute(ctx context.Context, email, password string) (*domain.User, error) {
|
|
if len(password) < minPasswordLen {
|
|
return nil, ErrPasswordTooShort
|
|
}
|
|
if len(password) > maxPasswordLen {
|
|
return nil, ErrPasswordTooLong
|
|
}
|
|
|
|
hash, err := r.hasher.Hash(password)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// NewUser normalises the email and enforces its shape; it returns a domain
|
|
// validation error the transport layer maps to 400.
|
|
u, err := domain.NewUser(email, hash, r.clk.Now())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := r.users.Insert(ctx, u); err != nil {
|
|
return nil, err
|
|
}
|
|
return u, nil
|
|
}
|