Skip to content

Commit 549c493

Browse files
committed
refactor: enforce domain validation and VO construction at system boundaries
1 parent 43098a4 commit 549c493

File tree

13 files changed

+120
-118
lines changed

13 files changed

+120
-118
lines changed

internal/db/device_repository.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,15 @@ func (r *DeviceRepository) FindById(ctx context.Context, id device.DeviceID, use
9898
return nil, fmt.Errorf("find device by id failed: %w", err)
9999
}
100100

101-
return device.RehydrateDevice(deviceID, userID, name, deviceType, status, metadata, createdAt, updatedAt)
101+
return device.RehydrateDevice(
102+
device.DeviceID(deviceID),
103+
user.UserID(userID),
104+
name,
105+
deviceType,
106+
status,
107+
metadata,
108+
createdAt,
109+
updatedAt,
110+
)
111+
102112
}

internal/db/token_repository.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func (r *TokenRepository) FindValidTokenByHash(ctx context.Context, hash []byte,
9797
return nil, fmt.Errorf("failed to find token: %w", err)
9898
}
9999

100-
return token.RehydrateToken(id, dbHash, userID, dbScope, revoked, expiresAt, lastUsedAt, createdAt), nil
100+
return token.RehydrateToken(token.TokenID(id), dbHash, userID, dbScope, revoked, expiresAt, lastUsedAt, createdAt), nil
101101
}
102102

103103
func (r *TokenRepository) Revoke(ctx context.Context, scope string, hash []byte) error {

internal/db/user_repository.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func (r *UserRepository) Create(ctx context.Context, u *user.User) error {
5555
return nil
5656
}
5757

58-
func (r *UserRepository) FindByEmail(ctx context.Context, email string) (*user.User, error) {
58+
func (r *UserRepository) FindByEmail(ctx context.Context, email user.Email) (*user.User, error) {
5959
var (
6060
id uuid.UUID
6161
emailStr string
@@ -70,7 +70,7 @@ func (r *UserRepository) FindByEmail(ctx context.Context, email string) (*user.U
7070
WHERE users.email = $1
7171
`
7272

73-
err := r.db.QueryRow(ctx, query, email).Scan(
73+
err := r.db.QueryRow(ctx, query, email.String()).Scan(
7474
&id,
7575
&emailStr,
7676
&usernameStr,
@@ -87,5 +87,5 @@ func (r *UserRepository) FindByEmail(ctx context.Context, email string) (*user.U
8787
return nil, fmt.Errorf("failed to find user: %w", err)
8888
}
8989

90-
return user.RehydrateUser(id, emailStr, usernameStr, passwordHash, createdAt, updatedAt)
90+
return user.RehydrateUser(user.UserID(id), emailStr, usernameStr, passwordHash, createdAt, updatedAt)
9191
}

internal/domain/auth/service.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,17 @@ func NewService(userService *user.Service, tokenService *token.Service) *Service
1919
}
2020
}
2121

22-
func (s *Service) Register(ctx context.Context, username, email, password string) (*user.User, error) {
22+
func (s *Service) Register(
23+
ctx context.Context,
24+
username user.Username,
25+
email user.Email,
26+
password user.Password,
27+
) (*user.User, error) {
2328
return s.user.RegisterUser(ctx, username, email, password)
2429
}
2530

26-
func (s *Service) Login(ctx context.Context, email, password string) (string, *token.Token, error) {
27-
u, err := s.user.AuthenticateUser(ctx, email, password)
31+
func (s *Service) Login(ctx context.Context, email user.Email, rawPassword string) (string, *token.Token, error) {
32+
u, err := s.user.AuthenticateUser(ctx, email, rawPassword)
2833
if err != nil {
2934
return "", nil, err
3035
}

internal/domain/device/device.go

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
"time"
77

8-
"github.com/google/uuid"
98
"github.com/raphico/go-device-telemetry-api/internal/domain/user"
109
)
1110

@@ -20,38 +19,29 @@ type Device struct {
2019
UpdatedAt time.Time
2120
}
2221

23-
func NewDevice(userId user.UserID, name, status, deviceType string, metadata map[string]any) (*Device, error) {
24-
n, err := NewName(name)
25-
if err != nil {
26-
return nil, err
27-
}
28-
29-
s, err := NewStatus(status)
30-
if err != nil {
31-
return nil, err
32-
}
33-
34-
dt, err := NewDeviceType(deviceType)
35-
if err != nil {
36-
return nil, err
37-
}
38-
22+
func NewDevice(
23+
userId user.UserID,
24+
name Name,
25+
status Status,
26+
deviceType DeviceType,
27+
metadata map[string]any,
28+
) *Device {
3929
if metadata == nil {
4030
metadata = make(map[string]any)
4131
}
4232

4333
return &Device{
4434
UserID: userId,
45-
Name: n,
46-
Status: s,
47-
DeviceType: dt,
35+
Name: name,
36+
Status: status,
37+
DeviceType: deviceType,
4838
Metadata: metadata,
49-
}, nil
39+
}
5040
}
5141

5242
func RehydrateDevice(
53-
id uuid.UUID,
54-
userID uuid.UUID,
43+
id DeviceID,
44+
userID user.UserID,
5545
name string,
5646
deviceType string,
5747
status string,
@@ -85,8 +75,8 @@ func RehydrateDevice(
8575
}
8676

8777
return &Device{
88-
ID: DeviceID(id),
89-
UserID: user.UserID(userID),
78+
ID: id,
79+
UserID: userID,
9080
Name: n,
9181
Status: s,
9282
DeviceType: dt,

internal/domain/device/service.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,18 @@ func NewService(repo Repository) *Service {
1919
func (s *Service) CreateDevice(
2020
ctx context.Context,
2121
userId user.UserID,
22-
name,
23-
status,
24-
deviceType string,
22+
name Name,
23+
status Status,
24+
deviceType DeviceType,
2525
metadata map[string]any,
2626
) (*Device, error) {
27-
device, err := NewDevice(userId, name, status, deviceType, metadata)
28-
if err != nil {
29-
return nil, err
30-
}
27+
dev := NewDevice(userId, name, status, deviceType, metadata)
3128

32-
if err = s.repo.Create(ctx, device); err != nil {
29+
if err := s.repo.Create(ctx, dev); err != nil {
3330
return nil, err
3431
}
3532

36-
return device, nil
33+
return dev, nil
3734
}
3835

3936
func (s *Service) GetDevice(ctx context.Context, id DeviceID, userId user.UserID) (*Device, error) {

internal/domain/token/token.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func HashPlaintext(plaintext string) []byte {
5050
}
5151

5252
func RehydrateToken(
53-
id uuid.UUID,
53+
id TokenID,
5454
hash []byte,
5555
userID user.UserID,
5656
scope string,
@@ -60,7 +60,7 @@ func RehydrateToken(
6060
createdAt time.Time,
6161
) *Token {
6262
return &Token{
63-
ID: TokenID(id),
63+
ID: id,
6464
Hash: hash,
6565
UserID: userID,
6666
Scope: scope,

internal/domain/user/password.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,15 @@ func validatePassword(pw string) error {
3131

3232
var (
3333
hasMinLen = len(pw) >= 8
34-
hasUpper bool
35-
hasLower bool
34+
hasLetter bool
3635
hasDigit bool
3736
hasSpecial bool
3837
)
3938

4039
for _, c := range pw {
4140
switch {
42-
case unicode.IsUpper(c):
43-
hasUpper = true
44-
case unicode.IsLower(c):
45-
hasLower = true
41+
case unicode.IsLetter(c):
42+
hasLetter = true
4643
case unicode.IsDigit(c):
4744
hasDigit = true
4845
case unicode.IsSymbol(c) || unicode.IsPunct(c):
@@ -53,7 +50,7 @@ func validatePassword(pw string) error {
5350
if !hasMinLen {
5451
return ErrPasswordTooShort
5552
}
56-
if !hasUpper || !hasLower || !hasDigit || !hasSpecial {
53+
if !hasLetter || !hasDigit || !hasSpecial {
5754
return ErrPasswordTooWeak
5855
}
5956

internal/domain/user/repository.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ import "context"
44

55
type Repository interface {
66
Create(ctx context.Context, u *User) error
7-
FindByEmail(ctx context.Context, email string) (*User, error)
7+
FindByEmail(ctx context.Context, email Email) (*User, error)
88
}

internal/domain/user/service.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ func NewService(repo Repository) *Service {
1414
}
1515
}
1616

17-
func (s *Service) RegisterUser(ctx context.Context, username, email, password string) (*User, error) {
18-
user, err := NewUser(email, username, password)
19-
if err != nil {
20-
return nil, err
21-
}
17+
func (s *Service) RegisterUser(
18+
ctx context.Context,
19+
username Username,
20+
email Email,
21+
password Password,
22+
) (*User, error) {
23+
user := NewUser(email, username, password)
2224

2325
if err := s.repo.Create(ctx, user); err != nil {
2426
return nil, err
@@ -27,13 +29,13 @@ func (s *Service) RegisterUser(ctx context.Context, username, email, password st
2729
return user, nil
2830
}
2931

30-
func (s *Service) AuthenticateUser(ctx context.Context, email, password string) (*User, error) {
32+
func (s *Service) AuthenticateUser(ctx context.Context, email Email, rawPassword string) (*User, error) {
3133
user, err := s.repo.FindByEmail(ctx, email)
3234
if err != nil {
3335
return nil, ErrInvalidCredentials
3436
}
3537

36-
if matches := user.Password.Matches(password); !matches {
38+
if matches := user.Password.Matches(rawPassword); !matches {
3739
return nil, ErrInvalidCredentials
3840
}
3941

0 commit comments

Comments
 (0)