Skip to content

Commit

Permalink
Convert refresh return to a TaskEither
Browse files Browse the repository at this point in the history
  • Loading branch information
dhzdhd committed Jun 27, 2023
1 parent 6f969ba commit 1863d0e
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 62 deletions.
27 changes: 15 additions & 12 deletions lib/src/accounts/controllers/auth_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:syncvault/src/accounts/models/auth_provider_model.dart';
import 'package:syncvault/src/accounts/models/folder_info_model.dart';
import 'package:syncvault/src/accounts/services/auth_service.dart';
import 'package:syncvault/src/home/models/error_model.dart';

enum AuthProviderType {
oneDrive,
Expand Down Expand Up @@ -49,16 +50,17 @@ class AuthProviderNotifier extends StateNotifier<List<AuthProviderModel>> {
});
}

Future<void> refresh(AuthProviderModel model) async {
final result = switch (model.provider) {
AuthProviderType.oneDrive => await OneDriveAuth().refresh(model),
AuthProviderType.dropBox => await DropBoxAuth().refresh(model),
};

// Use where
var newState = state;
newState.removeWhere((e) => e == model);
state = [...newState, result];
TaskEither<AppError, ()> refresh(AuthProviderModel model) {
return switch (model.provider) {
AuthProviderType.oneDrive => OneDriveAuth().refresh(model),
AuthProviderType.dropBox => DropBoxAuth().refresh(model),
}
.map(
(r) {
state = [...state.where((e) => e != model), r];
return ();
},
);
}

void signOut(AuthProviderModel model) async {
Expand All @@ -70,8 +72,9 @@ class AuthProviderNotifier extends StateNotifier<List<AuthProviderModel>> {
}

Future<Either<String, FolderInfoModel>> getDriveInfo(
AuthProviderModel authModel) async {
await refresh(authModel);
AuthProviderModel authModel,
) async {
await refresh(authModel).run();

return switch (authModel.provider) {
AuthProviderType.oneDrive =>
Expand Down
4 changes: 2 additions & 2 deletions lib/src/accounts/controllers/folder_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class FolderNotifier extends StateNotifier<List<FolderModel>> {
String folderPath,
String folderName,
) async {
await ref.read(authProvider.notifier).refresh(authModel);
await ref.read(authProvider.notifier).refresh(authModel).run();
final newAuthModel = ref
.read(authProvider)
.where((element) => element.email == authModel.email)
Expand Down Expand Up @@ -110,7 +110,7 @@ class FolderNotifier extends StateNotifier<List<FolderModel>> {
.where((element) => element.email == folderModel.email)
.first;

await ref.read(authProvider.notifier).refresh(oldAuthModel);
await ref.read(authProvider.notifier).refresh(oldAuthModel).run();

final authModel = ref
.read(authProvider)
Expand Down
110 changes: 62 additions & 48 deletions lib/src/accounts/services/auth_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import 'package:syncvault/src/accounts/controllers/auth_controller.dart';
import 'package:syncvault/src/accounts/models/auth_provider_model.dart';
import 'package:syncvault/src/accounts/models/folder_info_model.dart';
import 'package:syncvault/src/accounts/services/drive_service.dart';
import 'package:syncvault/src/home/models/error_model.dart';

final dio = Dio();

abstract interface class AuthService {
Future<Either<String, AuthProviderModel>> signIn();
Future<AuthProviderModel> refresh(AuthProviderModel model);
TaskEither<AppError, AuthProviderModel> refresh(AuthProviderModel model);
Future<Map<String, dynamic>> getUserInfo(String accessToken);
TaskEither<String, FolderInfoModel> getDriveInfo(String accessToken);
}
Expand Down Expand Up @@ -103,35 +104,45 @@ final class DropBoxAuth implements AuthService {
}

@override
Future<AuthProviderModel> refresh(AuthProviderModel model) async {
TaskEither<AppError, AuthProviderModel> refresh(AuthProviderModel model) {
final prev = DateTime.parse(model.createdAt);
final now = DateTime.now();
final diff = prev.add(Duration(seconds: model.expiresIn)).compareTo(now);

if (diff <= 0) {
final options = Options(
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
);
final uri = Uri.https(authHost, '/oauth2/token');
final response = await dio.postUri<Map<String, dynamic>>(
uri,
data: {
'client_id': clientId,
'client_secret': '',
'grant_type': 'refresh_token',
'redirect_uri': callbackUrlScheme,
'refresh_token': model.refreshToken,
},
options: options,
);
return TaskEither.tryCatch(() async {
if (diff <= 0) {
final options = Options(
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
);
final uri = Uri.https(authHost, '/oauth2/token');
final response = await dio.postUri<Map<String, dynamic>>(
uri,
data: {
'client_id': clientId,
'client_secret': '',
'grant_type': 'refresh_token',
'redirect_uri': callbackUrlScheme,
'refresh_token': model.refreshToken,
},
options: options,
);

return model.copyWith(
accessToken: response.data!['access_token'],
expiresIn: response.data!['expires_in'],
);
} else {
return model;
}
return model.copyWith(
accessToken: response.data!['access_token'],
expiresIn: response.data!['expires_in'],
);
} else {
return model;
}
}, (error, stackTrace) {
if (error is DioError) {
return HttpError(
message: error.response.toString(),
stackTrace: error.stackTrace.toString(),
);
}
return GeneralError(message: '', stackTrace: error.toString());
});
}

@override
Expand Down Expand Up @@ -260,23 +271,20 @@ final class OneDriveAuth implements AuthService {
}

@override
Future<AuthProviderModel> refresh(AuthProviderModel model) async {
TaskEither<AppError, AuthProviderModel> refresh(AuthProviderModel model) {
final prev = DateTime.parse(model.createdAt);
final now = DateTime.now();
final diff = prev.add(Duration(seconds: model.expiresIn)).compareTo(now);

print(model);

if (diff <= 0) {
final options = Options(
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
);
final uri = Uri.https(authHost, '/common/oauth2/v2.0/token');
print(uri.toString());
return TaskEither.tryCatch(() async {
if (diff <= 0) {
final options = Options(
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
);
final uri = Uri.https(authHost, '/common/oauth2/v2.0/token');
print(uri.toString());

late final response;
try {
response = await dio.postUri<Map<String, dynamic>>(
final response = await dio.postUri<Map<String, dynamic>>(
uri,
data: {
'client_id': clientId,
Expand All @@ -286,18 +294,24 @@ final class OneDriveAuth implements AuthService {
},
options: options,
);
} on DioError catch (e) {
print(e.response);
}

return model.copyWith(
accessToken: response.data!['access_token'],
expiresIn: response.data!['expires_in'],
refreshToken: response.data!['refresh_token'],
);
} else {
return model;
}
return model.copyWith(
accessToken: response.data!['access_token'],
expiresIn: response.data!['expires_in'],
refreshToken: response.data!['refresh_token'],
);
} else {
return model;
}
}, (error, stackTrace) {
if (error is DioError) {
return HttpError(
message: error.response.toString(),
stackTrace: error.stackTrace.toString(),
);
}
return GeneralError(message: '', stackTrace: error.toString());
});
}

@override
Expand Down
24 changes: 24 additions & 0 deletions lib/src/home/models/error_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
sealed class AppError {
String get message;
String get stackTrace;
}

class HttpError implements AppError {
@override
final String message;

@override
final String stackTrace;

HttpError({required this.message, required this.stackTrace});
}

class GeneralError implements AppError {
@override
final String message;

@override
final String stackTrace;

GeneralError({required this.message, required this.stackTrace});
}

0 comments on commit 1863d0e

Please sign in to comment.