package rpc import ( "context" "sync" "telesrv/internal/domain" ) type captureAuthService struct { bindTempCalls int bindTempLayer int bindTempHook func(domain.TempAuthKeyBinding) error bindTempResult domain.TempAuthKeyBindingResult resolvedAuthKeyID [8]byte hasResolved bool resolveCount int userID int64 userIDCount int signInUser domain.User signUpPhone string signUpHash string signUpFirstName string signUpLastName string signUpAuth domain.Authorization signUpUser domain.User acceptedAuth domain.Authorization acceptedUserID int64 authorizations []domain.Authorization authorizationLookups int authorizationLists int authKeyClientInfos map[[8]byte]domain.AuthKeyClientInfo authKeyInfoLookups int loggedOutAuthKeyID [8]byte pendingPasswordUserID int64 pendingPassword bool completedPasswordKey [8]byte completedPasswordUser int64 completePasswordCount int codeDelivery domain.AuthCodeDelivery signInCount int signInPhone string signInHash string signInCode string signInWithEmailCount int signInWithEmailPhone string signInWithEmailHash string signInWithEmailCode string resetAvailable bool } func (s *captureAuthService) LoginEmailResetAvailable() bool { return s.resetAvailable } type blockingUserAuthService struct { userID int64 started chan struct{} release chan struct{} once sync.Once mu sync.Mutex count int } func (s *blockingUserAuthService) UserIDCount() int { s.mu.Lock() defer s.mu.Unlock() return s.count } func (s *blockingUserAuthService) BindTempAuthKey(context.Context, int64, domain.TempAuthKeyBinding) (domain.TempAuthKeyBindingResult, error) { return domain.TempAuthKeyBindingResult{}, nil } func (s *blockingUserAuthService) ResolveAuthKey(context.Context, [8]byte) ([8]byte, bool, error) { return [8]byte{}, false, nil } func (s *blockingUserAuthService) UserID(ctx context.Context, _ [8]byte) (int64, bool, error) { s.mu.Lock() s.count++ s.mu.Unlock() s.once.Do(func() { close(s.started) }) select { case <-s.release: return s.userID, s.userID != 0, nil case <-ctx.Done(): return 0, false, ctx.Err() } } func (s *blockingUserAuthService) SendCode(context.Context, string) (string, error) { return "", nil } func (s *blockingUserAuthService) CodeDelivery(context.Context, string) (domain.AuthCodeDelivery, bool, error) { return domain.AuthCodeDelivery{Kind: domain.AuthCodeDeliveryPhone, Length: devCodeLength}, true, nil } func (s *blockingUserAuthService) ResendCode(context.Context, string, string) (string, error) { return "", nil } func (s *blockingUserAuthService) CancelCode(context.Context, string, string) error { return nil } func (s *blockingUserAuthService) SignIn(context.Context, domain.Authorization, string, string, string) (domain.User, domain.Message, bool, error) { return domain.User{}, domain.Message{}, false, nil } func (s *blockingUserAuthService) SignInWithEmail(context.Context, domain.Authorization, string, string, string) (domain.User, domain.Message, bool, error) { return domain.User{}, domain.Message{}, false, nil } func (s *blockingUserAuthService) BindVerifiedLogin(_ context.Context, _ domain.Authorization, userID int64) (domain.User, error) { return domain.User{ID: userID}, nil } func (s *blockingUserAuthService) SignUp(context.Context, domain.Authorization, string, string, string, string) (domain.User, domain.Message, error) { return domain.User{}, domain.Message{}, nil } func (s *blockingUserAuthService) AcceptLoginToken(context.Context, domain.Authorization, int64) (domain.Authorization, error) { return domain.Authorization{}, nil } func (s *blockingUserAuthService) SignInBot(context.Context, domain.Authorization, string) (domain.User, error) { return domain.User{}, domain.ErrBotTokenInvalid } func (s *blockingUserAuthService) LogOut(context.Context, [8]byte) error { return nil } func (s *blockingUserAuthService) Authorization(context.Context, [8]byte) (domain.Authorization, bool, error) { return domain.Authorization{}, false, nil } func (s *blockingUserAuthService) AuthKeyClientInfo(context.Context, [8]byte) (domain.AuthKeyClientInfo, bool, error) { return domain.AuthKeyClientInfo{}, false, nil } func (s *blockingUserAuthService) UpdateAuthKeyClientInfo(context.Context, [8]byte, domain.AuthKeyClientInfo) error { return nil } func (s *blockingUserAuthService) ListAuthorizations(context.Context, int64) ([]domain.Authorization, error) { return nil, nil } func (s *blockingUserAuthService) ResetAuthorization(context.Context, int64, int64) (domain.Authorization, bool, error) { return domain.Authorization{}, false, nil } func (s *blockingUserAuthService) ResetAuthorizations(context.Context, int64, [8]byte) ([]domain.Authorization, error) { return nil, nil } func (s *blockingUserAuthService) PendingPasswordUserID(context.Context, [8]byte) (int64, bool, error) { return 0, false, nil } func (s *blockingUserAuthService) CompletePasswordSignIn(context.Context, [8]byte, int64) error { return nil } func (s *captureAuthService) BindTempAuthKey(ctx context.Context, _ int64, binding domain.TempAuthKeyBinding) (domain.TempAuthKeyBindingResult, error) { s.bindTempCalls++ s.bindTempLayer = LayerFrom(ctx) if s.bindTempHook != nil { if err := s.bindTempHook(binding); err != nil { return domain.TempAuthKeyBindingResult{}, err } } if s.bindTempResult != (domain.TempAuthKeyBindingResult{}) { return s.bindTempResult, nil } permID := authKeyIDFromInt64(binding.PermAuthKeyID) if info, ok := s.authKeyClientInfos[permID]; ok { return domain.TempAuthKeyBindingResult{ Layer: info.Layer, LayerObservationID: info.LayerObservationID, }, nil } return domain.TempAuthKeyBindingResult{}, nil } func (s *captureAuthService) ResolveAuthKey(context.Context, [8]byte) ([8]byte, bool, error) { s.resolveCount++ return s.resolvedAuthKeyID, s.hasResolved, nil } func (s *captureAuthService) UserID(context.Context, [8]byte) (int64, bool, error) { s.userIDCount++ return s.userID, s.userID != 0, nil } func (s *captureAuthService) SendCode(context.Context, string) (string, error) { return "", nil } func (s *captureAuthService) CodeDelivery(context.Context, string) (domain.AuthCodeDelivery, bool, error) { if s.codeDelivery.Kind != "" { return s.codeDelivery, true, nil } return domain.AuthCodeDelivery{Kind: domain.AuthCodeDeliveryPhone, Length: devCodeLength}, true, nil } func (s *captureAuthService) ResendCode(context.Context, string, string) (string, error) { return "", nil } func (s *captureAuthService) CancelCode(context.Context, string, string) error { return nil } func (s *captureAuthService) SignIn(_ context.Context, _ domain.Authorization, phone, hash, code string) (domain.User, domain.Message, bool, error) { s.signInCount++ s.signInPhone = phone s.signInHash = hash s.signInCode = code if s.signInUser.ID != 0 { return s.signInUser, domain.Message{}, false, nil } return domain.User{}, domain.Message{}, false, nil } func (s *captureAuthService) SignInWithEmail(_ context.Context, _ domain.Authorization, phone, hash, code string) (domain.User, domain.Message, bool, error) { s.signInWithEmailCount++ s.signInWithEmailPhone = phone s.signInWithEmailHash = hash s.signInWithEmailCode = code if s.signInUser.ID != 0 { return s.signInUser, domain.Message{}, false, nil } return domain.User{}, domain.Message{}, false, nil } func (s *captureAuthService) BindVerifiedLogin(_ context.Context, _ domain.Authorization, userID int64) (domain.User, error) { if s.signInUser.ID != 0 { return s.signInUser, nil } return domain.User{ID: userID}, nil } func (s *captureAuthService) SignUp(_ context.Context, a domain.Authorization, phone, hash, first, last string) (domain.User, domain.Message, error) { s.signUpAuth = a s.signUpPhone = phone s.signUpHash = hash s.signUpFirstName = first s.signUpLastName = last if s.signUpUser.ID != 0 { return s.signUpUser, domain.Message{}, nil } return domain.User{}, domain.Message{}, nil } func (s *captureAuthService) AcceptLoginToken(_ context.Context, a domain.Authorization, userID int64) (domain.Authorization, error) { a.UserID = userID if a.Hash == 0 { a.Hash = 77 } s.acceptedAuth = a s.acceptedUserID = userID return a, nil } func (s *captureAuthService) SignInBot(context.Context, domain.Authorization, string) (domain.User, error) { if s.signInUser.ID != 0 { return s.signInUser, nil } return domain.User{}, domain.ErrBotTokenInvalid } func (s *captureAuthService) LogOut(_ context.Context, authKeyID [8]byte) error { s.loggedOutAuthKeyID = authKeyID return nil } func (s *captureAuthService) Authorization(_ context.Context, authKeyID [8]byte) (domain.Authorization, bool, error) { s.authorizationLookups++ for _, item := range s.authorizations { if item.AuthKeyID == authKeyID { return item, true, nil } } return domain.Authorization{}, false, nil } func (s *captureAuthService) AuthKeyClientInfo(_ context.Context, authKeyID [8]byte) (domain.AuthKeyClientInfo, bool, error) { s.authKeyInfoLookups++ info, ok := s.authKeyClientInfos[authKeyID] return info, ok, nil } func (s *captureAuthService) UpdateAuthKeyClientInfo(_ context.Context, authKeyID [8]byte, info domain.AuthKeyClientInfo) error { if s.authKeyClientInfos == nil { s.authKeyClientInfos = make(map[[8]byte]domain.AuthKeyClientInfo) } current := s.authKeyClientInfos[authKeyID] if info.Layer > 0 { current.Layer = info.Layer } if info.DeviceModel != "" { current.DeviceModel = info.DeviceModel } if info.Platform != "" { current.Platform = info.Platform } if info.SystemVersion != "" { current.SystemVersion = info.SystemVersion } if info.APIID != 0 { current.APIID = info.APIID } if info.AppVersion != "" { current.AppVersion = info.AppVersion } if info.IP != "" { current.IP = info.IP } s.authKeyClientInfos[authKeyID] = current for i := range s.authorizations { if s.authorizations[i].AuthKeyID != authKeyID { continue } if info.DeviceModel != "" { s.authorizations[i].DeviceModel = info.DeviceModel } if info.Platform != "" { s.authorizations[i].Platform = info.Platform } if info.SystemVersion != "" { s.authorizations[i].SystemVersion = info.SystemVersion } if info.APIID != 0 { s.authorizations[i].APIID = info.APIID } if info.AppVersion != "" { s.authorizations[i].AppVersion = info.AppVersion } if info.IP != "" { s.authorizations[i].IP = info.IP } } return nil } func (s *captureAuthService) ListAuthorizations(context.Context, int64) ([]domain.Authorization, error) { s.authorizationLists++ return append([]domain.Authorization(nil), s.authorizations...), nil } func (s *captureAuthService) ResetAuthorization(context.Context, int64, int64) (domain.Authorization, bool, error) { return domain.Authorization{}, false, nil } func (s *captureAuthService) ResetAuthorizations(context.Context, int64, [8]byte) ([]domain.Authorization, error) { return nil, nil } func (s *captureAuthService) PendingPasswordUserID(context.Context, [8]byte) (int64, bool, error) { return s.pendingPasswordUserID, s.pendingPassword, nil } func (s *captureAuthService) CompletePasswordSignIn(_ context.Context, authKeyID [8]byte, userID int64) error { s.completedPasswordKey = authKeyID s.completedPasswordUser = userID s.completePasswordCount++ return nil }