Skip to content

Commit 0cf4c86

Browse files
committed
[#11] Make ApiToken JsonSerializable and equatable
1 parent 60be60d commit 0cf4c86

File tree

5 files changed

+79
-4
lines changed

5 files changed

+79
-4
lines changed

ios/Podfile.lock

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ PODS:
22
- Flutter (1.0.0)
33
- flutter_config (0.0.1):
44
- Flutter
5+
- flutter_secure_storage (6.0.0):
6+
- Flutter
57
- integration_test (0.0.1):
68
- Flutter
79
- package_info_plus (0.4.5):
@@ -12,6 +14,7 @@ PODS:
1214
DEPENDENCIES:
1315
- Flutter (from `Flutter`)
1416
- flutter_config (from `.symlinks/plugins/flutter_config/ios`)
17+
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
1518
- integration_test (from `.symlinks/plugins/integration_test/ios`)
1619
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
1720
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
@@ -21,6 +24,8 @@ EXTERNAL SOURCES:
2124
:path: Flutter
2225
flutter_config:
2326
:path: ".symlinks/plugins/flutter_config/ios"
27+
flutter_secure_storage:
28+
:path: ".symlinks/plugins/flutter_secure_storage/ios"
2429
integration_test:
2530
:path: ".symlinks/plugins/integration_test/ios"
2631
package_info_plus:
@@ -31,6 +36,7 @@ EXTERNAL SOURCES:
3136
SPEC CHECKSUMS:
3237
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
3338
flutter_config: 2226c1df19c78fe34a05eb7f1363445f18e76fc1
39+
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
3440
integration_test: 13825b8a9334a850581300559b8839134b124670
3541
package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7
3642
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6

lib/model/api_token.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import 'package:json_annotation/json_annotation.dart';
2+
import 'package:survey_flutter/model/response/login_response.dart';
3+
import 'package:survey_flutter/storage/secure_storage.dart';
4+
5+
part 'api_token.g.dart';
6+
7+
@JsonSerializable()
8+
class ApiToken extends SecureStorageModel {
9+
@JsonKey(name: 'access_token')
10+
final String accessToken;
11+
@JsonKey(name: 'refresh_token')
12+
final String refreshToken;
13+
@JsonKey(name: 'token_type')
14+
final String tokenType;
15+
16+
ApiToken({
17+
required this.accessToken,
18+
required this.refreshToken,
19+
required this.tokenType,
20+
});
21+
22+
factory ApiToken.fromJson(Map<String, dynamic> json) =>
23+
_$ApiTokenFromJson(json);
24+
25+
Map<String, dynamic> toJson() => _$ApiTokenToJson(this);
26+
27+
static ApiToken from(LoginResponse loginResponse) => ApiToken(
28+
accessToken: loginResponse.accessToken,
29+
refreshToken: loginResponse.refreshToken,
30+
tokenType: loginResponse.tokenType,
31+
);
32+
33+
@override
34+
bool operator ==(Object other) =>
35+
other is ApiToken &&
36+
accessToken == other.accessToken &&
37+
refreshToken == other.refreshToken &&
38+
tokenType == other.tokenType;
39+
40+
@override
41+
int get hashCode => (accessToken + refreshToken + tokenType).hashCode;
42+
}

lib/repositories/authentication_repository.dart

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@ import 'package:survey_flutter/api/authentication_api_service.dart';
33
import 'package:survey_flutter/api/exception/network_exceptions.dart';
44
import 'package:survey_flutter/di/provider/dio_provider.dart';
55
import 'package:survey_flutter/env.dart';
6+
import 'package:survey_flutter/model/api_token.dart';
67
import 'package:survey_flutter/model/login_model.dart';
78
import 'package:survey_flutter/model/request/login_request.dart';
9+
import 'package:survey_flutter/storage/secure_storage.dart';
10+
import 'package:survey_flutter/storage/secure_storage_impl.dart';
811

912
const String _grantType = "password";
1013

1114
final authenticationRepositoryProvider =
12-
Provider<AuthenticationRepository>((_) {
15+
Provider<AuthenticationRepository>((ref) {
1316
return AuthenticationRepositoryImpl(
1417
AuthenticationApiService(DioProvider().getDio()),
18+
ref.watch(secureStorageProvider),
1519
);
1620
});
1721

@@ -24,8 +28,12 @@ abstract class AuthenticationRepository {
2428

2529
class AuthenticationRepositoryImpl extends AuthenticationRepository {
2630
final AuthenticationApiService _authenticationApiService;
31+
final SecureStorage _secureStorage;
2732

28-
AuthenticationRepositoryImpl(this._authenticationApiService);
33+
AuthenticationRepositoryImpl(
34+
this._authenticationApiService,
35+
this._secureStorage,
36+
);
2937

3038
@override
3139
Future<LoginModel> login({
@@ -40,6 +48,10 @@ class AuthenticationRepositoryImpl extends AuthenticationRepository {
4048
clientSecret: Env.clientSecret,
4149
grantType: _grantType,
4250
));
51+
await _secureStorage.save(
52+
value: ApiToken.from(response),
53+
key: SecureStorageKey.apiToken,
54+
);
4355
return response.toLoginModel();
4456
} catch (exception) {
4557
throw NetworkExceptions.fromDioException(exception);

test/api/repositories/authentication_repository_test.dart

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import 'package:flutter_config/flutter_config.dart';
22
import 'package:flutter_test/flutter_test.dart';
33
import 'package:mockito/mockito.dart';
4-
import 'package:survey_flutter/repositories/authentication_repository.dart';
54
import 'package:survey_flutter/api/exception/network_exceptions.dart';
5+
import 'package:survey_flutter/model/api_token.dart';
66
import 'package:survey_flutter/model/response/login_response.dart';
7+
import 'package:survey_flutter/repositories/authentication_repository.dart';
8+
import 'package:survey_flutter/storage/secure_storage.dart';
79

810
import '../../mocks/generate_mocks.mocks.dart';
911

1012
void main() {
1113
group('AuthenticationRepositoryTest', () {
1214
late MockAuthenticationApiService mockAuthApiService;
15+
late MockSecureStorage mockSecureStorage;
1316
late AuthenticationRepositoryImpl authRepository;
1417

1518
const email = "email";
@@ -24,7 +27,11 @@ void main() {
2427

2528
setUp(() {
2629
mockAuthApiService = MockAuthenticationApiService();
27-
authRepository = AuthenticationRepositoryImpl(mockAuthApiService);
30+
mockSecureStorage = MockSecureStorage();
31+
authRepository = AuthenticationRepositoryImpl(
32+
mockAuthApiService,
33+
mockSecureStorage,
34+
);
2835
});
2936

3037
test('When login successfully, it returns correct model', () async {
@@ -37,6 +44,12 @@ void main() {
3744
await authRepository.login(email: email, password: password);
3845

3946
expect(result, loginResponse.toLoginModel());
47+
verify(
48+
mockSecureStorage.save(
49+
value: ApiToken.from(loginResponse),
50+
key: SecureStorageKey.apiToken,
51+
),
52+
).called(1);
4053
});
4154

4255
test('When login fail, it returns failed exception', () async {

test/mocks/generate_mocks.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'package:mockito/annotations.dart';
33
import 'package:survey_flutter/api/authentication_api_service.dart';
44
import 'package:survey_flutter/api/survey_api_service.dart';
55
import 'package:survey_flutter/repositories/authentication_repository.dart';
6+
import 'package:survey_flutter/storage/secure_storage.dart';
67
import 'package:survey_flutter/usecases/login_use_case.dart';
78
import 'package:survey_flutter/utils/internet_connection_manager.dart';
89
import 'package:survey_flutter/repositories/survey_repository.dart';
@@ -16,6 +17,7 @@ import '../utils/async_listener.dart';
1617
DioError,
1718
InternetConnectionManager,
1819
LoginUseCase,
20+
SecureStorage,
1921
SurveyRepository,
2022
SurveyApiService,
2123
])

0 commit comments

Comments
 (0)