feat(server/auth): Register 加 inviteCode + ReferralHook(注册后 best-effort 归因)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -132,12 +132,22 @@ type Service struct {
|
||||
now func() time.Time
|
||||
devReg DeviceRegistrar // nil until wired; registration is best-effort
|
||||
sessions SessionStore // nil until wired; session recording is best-effort
|
||||
referral ReferralHook // nil until wired; referral attribution is best-effort
|
||||
}
|
||||
|
||||
// SetDeviceRegistrar / SetSessionStore wire collaborators after construction
|
||||
// (main keeps auth, devices and sessions decoupled). Call once during startup.
|
||||
// ReferralHook is invoked after a successful registration to attribute the new
|
||||
// account to the invite code it registered with (best-effort; implemented by
|
||||
// reward.Service). Defined consumer-side to avoid an import cycle.
|
||||
type ReferralHook interface {
|
||||
OnRegister(ctx context.Context, inviteeID int64, inviteCode, deviceUUID string)
|
||||
}
|
||||
|
||||
// SetDeviceRegistrar / SetSessionStore / SetReferralHook wire collaborators
|
||||
// after construction (main keeps auth, devices, sessions and reward decoupled).
|
||||
// Call once during startup.
|
||||
func (s *Service) SetDeviceRegistrar(r DeviceRegistrar) { s.devReg = r }
|
||||
func (s *Service) SetSessionStore(st SessionStore) { s.sessions = st }
|
||||
func (s *Service) SetReferralHook(h ReferralHook) { s.referral = h }
|
||||
|
||||
// recordLogin registers the device and binds a session to the freshly-issued
|
||||
// refresh JTI. Best-effort: a registrar/session error (device cap, transient DB)
|
||||
@@ -267,7 +277,7 @@ func (s *Service) SendCode(ctx context.Context, rawEmail, ip string) (retryAfter
|
||||
|
||||
// Register verifies the code (one-time), creates the account plus a 7-day PRO
|
||||
// trial in a single transaction, and returns a fresh token pair.
|
||||
func (s *Service) Register(ctx context.Context, rawEmail, code, password, ip string, device DeviceMeta) (*TokenPair, *apierr.Error) {
|
||||
func (s *Service) Register(ctx context.Context, rawEmail, code, password, ip string, device DeviceMeta, inviteCode string) (*TokenPair, *apierr.Error) {
|
||||
email := NormalizeEmail(rawEmail)
|
||||
if !ValidEmail(email) || len(password) < 8 || len(code) != 6 {
|
||||
return nil, ErrInvalidRequest
|
||||
@@ -301,6 +311,9 @@ func (s *Service) Register(ctx context.Context, rawEmail, code, password, ip str
|
||||
return nil, ErrInternal
|
||||
}
|
||||
s.recordLogin(ctx, user.ID, jti, ip, device)
|
||||
if s.referral != nil {
|
||||
s.referral.OnRegister(ctx, user.ID, inviteCode, device.DeviceID) // best-effort
|
||||
}
|
||||
return pair, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user