Skip to content

Commit 038443c

Browse files
committed
feat: An in-memory implementation of the HtAuthClient interface. This class simulates authentication flows, manages user and token states in memory, and throws appropriate HtHttpException subtypes, without any dependency on HtHttpClient.
1 parent d3b75b3 commit 038443c

File tree

1 file changed

+110
-3
lines changed

1 file changed

+110
-3
lines changed

lib/src/ht_auth_inmemory.dart

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,114 @@
1+
import 'dart:async';
2+
3+
import 'package:ht_auth_client/ht_auth_client.dart';
4+
import 'package:ht_shared/ht_shared.dart';
5+
import 'package:uuid/uuid.dart';
6+
17
/// {@template ht_auth_inmemory}
2-
/// A Very Good Project created by Very Good CLI.
8+
/// An in-memory implementation of the [HtAuthClient] interface for
9+
/// demonstration and testing purposes.
10+
///
11+
/// This client simulates authentication flows without requiring a backend,
12+
/// managing user and token states purely in memory.
313
/// {@endtemplate}
4-
class HtAuthInmemory {
14+
class HtAuthInmemory implements HtAuthClient {
515
/// {@macro ht_auth_inmemory}
6-
const HtAuthInmemory();
16+
HtAuthInmemory({
17+
this.initialUser,
18+
this.initialToken,
19+
}) {
20+
_currentUser = initialUser;
21+
_currentToken = initialToken;
22+
if (_currentUser != null) {
23+
_authStateController.add(_currentUser);
24+
}
25+
}
26+
27+
final Uuid _uuid = const Uuid();
28+
29+
/// The initial user to set for demonstration purposes.
30+
final User? initialUser;
31+
32+
/// The initial token to set for demonstration purposes.
33+
final String? initialToken;
34+
35+
final StreamController<User?> _authStateController =
36+
StreamController<User?>.broadcast();
37+
38+
User? _currentUser;
39+
String? _currentToken;
40+
final Map<String, String> _pendingCodes = {};
41+
42+
@override
43+
Stream<User?> get authStateChanges => _authStateController.stream;
44+
45+
/// Returns the current authentication token.
46+
///
47+
/// This is a custom getter for the in-memory client to allow the
48+
/// repository to retrieve the token after successful authentication.
49+
String? get currentToken => _currentToken;
50+
51+
@override
52+
Future<User?> getCurrentUser() async {
53+
return _currentUser;
54+
}
55+
56+
@override
57+
Future<void> requestSignInCode(String email) async {
58+
if (!email.contains('@') || !email.contains('.')) {
59+
throw const InvalidInputException('Invalid email format.');
60+
}
61+
// Simulate sending a code
62+
_pendingCodes[email] = '123456'; // Hardcoded for demo
63+
await Future<void>.delayed(const Duration(milliseconds: 500));
64+
}
65+
66+
@override
67+
Future<AuthSuccessResponse> verifySignInCode(String email, String code)
68+
async {
69+
if (!email.contains('@') || !email.contains('.')) {
70+
throw const InvalidInputException('Invalid email format.');
71+
}
72+
if (code != _pendingCodes[email]) {
73+
throw const AuthenticationException('Invalid or expired code.');
74+
}
75+
76+
// Simulate user creation/login
77+
final user = User(
78+
id: _uuid.v4(),
79+
email: email,
80+
role: UserRole.standardUser,
81+
);
82+
_currentUser = user;
83+
_currentToken = _uuid.v4(); // Generate a new token
84+
_authStateController.add(_currentUser);
85+
_pendingCodes.remove(email); // Clear pending code after successful verification
86+
87+
await Future<void>.delayed(const Duration(milliseconds: 500));
88+
return AuthSuccessResponse(user: user, token: _currentToken!);
89+
}
90+
91+
@override
92+
Future<AuthSuccessResponse> signInAnonymously() async {
93+
final user = User(
94+
id: _uuid.v4(),
95+
role: UserRole.guestUser,
96+
);
97+
_currentUser = user;
98+
_currentToken = _uuid.v4(); // Generate a new token
99+
_authStateController.add(_currentUser);
100+
101+
await Future<void>.delayed(const Duration(milliseconds: 500));
102+
return AuthSuccessResponse(user: user, token: _currentToken!);
103+
}
104+
105+
@override
106+
Future<void> signOut() async {
107+
_currentUser = null;
108+
_currentToken = null;
109+
_authStateController.add(null);
110+
_pendingCodes.clear(); // Clear all pending codes on sign out
111+
112+
await Future<void>.delayed(const Duration(milliseconds: 500));
113+
}
7114
}

0 commit comments

Comments
 (0)