102 lines
2.4 KiB
Go
102 lines
2.4 KiB
Go
package testkit
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"galaxy/authsession/internal/domain/common"
|
|
"galaxy/authsession/internal/ports"
|
|
)
|
|
|
|
// SequenceIDGenerator is a deterministic IDGenerator double that consumes
|
|
// queued identifiers before falling back to monotonic generated ids.
|
|
type SequenceIDGenerator struct {
|
|
mu sync.Mutex
|
|
|
|
// ChallengeIDs stores queued challenge identifiers returned by
|
|
// NewChallengeID before generated ids are used.
|
|
ChallengeIDs []common.ChallengeID
|
|
|
|
// DeviceSessionIDs stores queued device-session identifiers returned by
|
|
// NewDeviceSessionID before generated ids are used.
|
|
DeviceSessionIDs []common.DeviceSessionID
|
|
|
|
// ChallengeErr is returned directly from NewChallengeID when set.
|
|
ChallengeErr error
|
|
|
|
// DeviceSessionErr is returned directly from NewDeviceSessionID when set.
|
|
DeviceSessionErr error
|
|
|
|
ChallengePrefix string
|
|
DeviceSessionPrefix string
|
|
nextChallengeNumber int
|
|
nextSessionNumber int
|
|
}
|
|
|
|
// NewChallengeID returns the next deterministic challenge identifier.
|
|
func (g *SequenceIDGenerator) NewChallengeID() (common.ChallengeID, error) {
|
|
if g.ChallengeErr != nil {
|
|
return "", g.ChallengeErr
|
|
}
|
|
|
|
g.mu.Lock()
|
|
defer g.mu.Unlock()
|
|
|
|
if len(g.ChallengeIDs) > 0 {
|
|
id := g.ChallengeIDs[0]
|
|
g.ChallengeIDs = g.ChallengeIDs[1:]
|
|
if err := id.Validate(); err != nil {
|
|
return "", err
|
|
}
|
|
return id, nil
|
|
}
|
|
|
|
g.nextChallengeNumber++
|
|
prefix := g.ChallengePrefix
|
|
if prefix == "" {
|
|
prefix = "challenge-"
|
|
}
|
|
|
|
id := common.ChallengeID(fmt.Sprintf("%s%d", prefix, g.nextChallengeNumber))
|
|
if err := id.Validate(); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return id, nil
|
|
}
|
|
|
|
// NewDeviceSessionID returns the next deterministic device-session
|
|
// identifier.
|
|
func (g *SequenceIDGenerator) NewDeviceSessionID() (common.DeviceSessionID, error) {
|
|
if g.DeviceSessionErr != nil {
|
|
return "", g.DeviceSessionErr
|
|
}
|
|
|
|
g.mu.Lock()
|
|
defer g.mu.Unlock()
|
|
|
|
if len(g.DeviceSessionIDs) > 0 {
|
|
id := g.DeviceSessionIDs[0]
|
|
g.DeviceSessionIDs = g.DeviceSessionIDs[1:]
|
|
if err := id.Validate(); err != nil {
|
|
return "", err
|
|
}
|
|
return id, nil
|
|
}
|
|
|
|
g.nextSessionNumber++
|
|
prefix := g.DeviceSessionPrefix
|
|
if prefix == "" {
|
|
prefix = "device-session-"
|
|
}
|
|
|
|
id := common.DeviceSessionID(fmt.Sprintf("%s%d", prefix, g.nextSessionNumber))
|
|
if err := id.Validate(); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return id, nil
|
|
}
|
|
|
|
var _ ports.IDGenerator = (*SequenceIDGenerator)(nil)
|