@@ -32,17 +32,6 @@ class _SignInCodeEntry extends _CodeEntryBase {
3232 _SignInCodeEntry (super .code, super .expiresAt);
3333}
3434
35- /// {@template link_code_entry}
36- /// Stores a verification code for linking an email to an existing user.
37- /// {@endtemplate}
38- class _LinkCodeEntry extends _CodeEntryBase {
39- /// {@macro link_code_entry}
40- _LinkCodeEntry (super .code, super .expiresAt, this .emailToLink);
41-
42- /// The email address this link code is intended to verify.
43- final String emailToLink;
44- }
45-
4635/// {@template verification_code_storage_service}
4736/// Defines the interface for a service that manages verification codes
4837/// for different authentication flows (sign-in and account linking).
@@ -69,36 +58,6 @@ abstract class VerificationCodeStorageService {
6958 /// Throws [OperationFailedException] if clearing fails.
7059 Future <void > clearSignInCode (String email);
7160
72- // --- For Linking an Email to an Existing Authenticated (Anonymous) User ---
73-
74- /// Generates, stores, and returns a verification code for linking
75- /// [emailToLink] to the account of [userId] .
76- /// The [userId] is that of the currently authenticated anonymous user.
77- /// Codes are typically 6 digits.
78- /// Throws [OperationFailedException] on storage failure.
79- /// Throws [ConflictException] if [emailToLink] is already actively pending
80- /// for linking by another user, or if this [userId] already has an active
81- /// link code pending.
82- Future <String > generateAndStoreLinkCode ({
83- required String userId,
84- required String emailToLink,
85- });
86-
87- /// Validates the [linkCode] provided by the user with [userId] who is
88- /// attempting to link an email.
89- /// Returns the "emailToLink" if the code is valid and matches the one
90- /// stored for this [userId] . Returns `null` if invalid or expired.
91- /// Throws [OperationFailedException] on validation failure if an unexpected
92- /// error occurs during the check.
93- Future <String ?> validateAndRetrieveLinkedEmail ({
94- required String userId,
95- required String linkCode,
96- });
97-
98- /// Clears any pending link-code data associated with [userId] .
99- /// Throws [OperationFailedException] if clearing fails.
100- Future <void > clearLinkCode (String userId);
101-
10261 // --- General ---
10362
10463 /// Periodically cleans up expired codes of all types.
@@ -144,10 +103,6 @@ class InMemoryVerificationCodeStorageService
144103 @visibleForTesting
145104 final Map <String , _SignInCodeEntry > signInCodesStore = {};
146105
147- /// Store for account linking codes: Key is userId.
148- @visibleForTesting
149- final Map <String , _LinkCodeEntry > linkCodesStore = {};
150-
151106 Timer ? _cleanupTimer;
152107 bool _isDisposed = false ;
153108 final Random _random = Random ();
@@ -196,71 +151,6 @@ class InMemoryVerificationCodeStorageService
196151 );
197152 }
198153
199- @override
200- Future <String > generateAndStoreLinkCode ({
201- required String userId,
202- required String emailToLink,
203- }) async {
204- if (_isDisposed) {
205- throw const OperationFailedException ('Service is disposed.' );
206- }
207- await Future <void >.delayed (Duration .zero); // Simulate async
208-
209- // Check if this userId already has a pending link code
210- if (linkCodesStore.containsKey (userId) &&
211- ! linkCodesStore[userId]! .isExpired) {
212- throw const ConflictException (
213- 'User already has an active email linking process pending.' ,
214- );
215- }
216- // Check if emailToLink is already pending for another user
217- final isEmailPendingForOther = linkCodesStore.values.any (
218- (entry) =>
219- entry.emailToLink == emailToLink &&
220- ! entry.isExpired &&
221- linkCodesStore.keys.firstWhere ((id) => linkCodesStore[id] == entry) !=
222- userId,
223- );
224- if (isEmailPendingForOther) {
225- throw const ConflictException (
226- 'Email is already pending verification for another account linking process.' ,
227- );
228- }
229-
230- final code = _generateNumericCode ();
231- final expiresAt = DateTime .now ().add (codeExpiryDuration);
232- linkCodesStore[userId] = _LinkCodeEntry (code, expiresAt, emailToLink);
233- print (
234- '[InMemoryVerificationCodeStorageService] Stored link code for user $userId , email $emailToLink (expires: $expiresAt )' ,
235- );
236- return code;
237- }
238-
239- @override
240- Future <String ?> validateAndRetrieveLinkedEmail ({
241- required String userId,
242- required String linkCode,
243- }) async {
244- if (_isDisposed) return null ;
245- await Future <void >.delayed (Duration .zero); // Simulate async
246- final entry = linkCodesStore[userId];
247- if (entry == null || entry.isExpired || entry.code != linkCode) {
248- return null ;
249- }
250- return entry
251- .emailToLink; // Return the email associated with this valid code
252- }
253-
254- @override
255- Future <void > clearLinkCode (String userId) async {
256- if (_isDisposed) return ;
257- await Future <void >.delayed (Duration .zero); // Simulate async
258- linkCodesStore.remove (userId);
259- print (
260- '[InMemoryVerificationCodeStorageService] Cleared link code for user $userId ' ,
261- );
262- }
263-
264154 @override
265155 Future <void > cleanupExpiredCodes () async {
266156 if (_isDisposed) return ;
@@ -275,14 +165,6 @@ class InMemoryVerificationCodeStorageService
275165 return false ;
276166 });
277167
278- linkCodesStore.removeWhere ((key, entry) {
279- if (entry.isExpired) {
280- cleanedCount++ ;
281- return true ;
282- }
283- return false ;
284- });
285-
286168 if (cleanedCount > 0 ) {
287169 print (
288170 '[InMemoryVerificationCodeStorageService] Cleaned up $cleanedCount expired codes.' ,
@@ -296,7 +178,6 @@ class InMemoryVerificationCodeStorageService
296178 _isDisposed = true ;
297179 _cleanupTimer? .cancel ();
298180 signInCodesStore.clear ();
299- linkCodesStore.clear ();
300181 print ('[InMemoryVerificationCodeStorageService] Disposed.' );
301182 }
302183 }
0 commit comments