Skip to content

Commit

Permalink
FEAT: add mock user functionality (#25)
Browse files Browse the repository at this point in the history
* initiate the routing operation

* feat(auth): launch social auth

* feat: complete the oauth log in flow

* feat: use go_router for navigation

* fix: go router doesn't work

* feat: add transition to the sign up screen

* feat: add the new routes

* refactor: use go router instead or navigator

* feat: separate the local and remote repository for the auth

* same as before

* feat: mock the user authentication process

* fix: not using go_route in settings

* feat: add temporarly log out functionality
  • Loading branch information
Ahmed-Aladdiin authored Oct 30, 2024
1 parent 23dee9d commit 9b055c7
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 71 deletions.
5 changes: 4 additions & 1 deletion lib/.env_example
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ RECAPTCHA_SITE_KEY={reCAPTCHA_SITE_KEY}

# Social auth URL
GOOGLE_AUTH_URL=/auth/google
GITHUB_AUTH_URL=/auth/github
GITHUB_AUTH_URL=/auth/github

# mocking
USE_MOCK_DATA=true
5 changes: 5 additions & 0 deletions lib/core/mock/constants_mock.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// ignore_for_file: non_constant_identifier_names

import 'package:flutter_dotenv/flutter_dotenv.dart';

final USE_MOCK_DATA = (dotenv.env['USE_MOCK_DATA'] ?? 'false') == 'true';
1 change: 1 addition & 0 deletions lib/core/mock/token_mock.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const tokenMock = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoiNjEwZjQwZjYwZjYwZjYwZjYwZjYwZjYwIn0sImlhdCI6MTYzMTQwNjQwN30.7';
21 changes: 21 additions & 0 deletions lib/core/mock/user_mock.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:telware_cross_platform/core/models/user_model.dart';

const UserModel userMock = UserModel(
username: 'mock.user',
screenName: 'Mocka Mocka',
email: '[email protected]',
status: 'verified',
bio: 'I am a mocking user',
maxFileSize: 30,
automaticDownloadEnable: true,
lastSeenPrivacy: 'recently',
readReceiptsEnablePrivacy: 'enable',
storiesPrivacy: 'private',
picturePrivacy: 'global',
invitePermissionsPrivacy: 'enable',
phone: '+01100663311',
photo:
'https://static1.cbrimages.com/wordpress/wp-content/uploads/2023/05/jujutsu-kaisen-gojo-223.jpg',
);

const userMockPassword = 'qwerty99';
12 changes: 1 addition & 11 deletions lib/features/auth/repository/auth_local_repository.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:hive/hive.dart';
import 'package:telware_cross_platform/core/models/user_model.dart';
import 'package:telware_cross_platform/core/providers/token_provider.dart';
import 'package:telware_cross_platform/core/providers/user_provider.dart';

part 'auth_local_repository.g.dart';

Expand All @@ -18,46 +16,38 @@ AuthLocalRepository authLocalRepository(AuthLocalRepositoryRef ref) {
class AuthLocalRepository {
final Box<String> _tokenBox;
final Box<UserModel> _userBox;
final ProviderRef<AuthLocalRepository> _ref;

AuthLocalRepository({
required Box<String> tokenBox,
required Box<UserModel> userBox,
required ProviderRef<AuthLocalRepository> ref,
}) : _tokenBox = tokenBox,
_userBox = userBox,
_ref = ref;
_userBox = userBox;

void setToken(String token) async {
await _tokenBox.put('token', token);
_ref.read(tokenProvider.notifier).update((_) => token);
}

String? getToken() {
String? token = _tokenBox.get('token');
_ref.read(tokenProvider.notifier).update((_) => token);
return token;
}

Future<void> deleteToken() async {
await _tokenBox.delete('token');
_ref.read(tokenProvider.notifier).update((_) => null);
}

// todo: create the user setting and getting methods
void setUser(UserModel user) async {
await _userBox.put('user', user);
_ref.read(userProvider.notifier).update((_) => user);
}

UserModel? getMe() {
UserModel? user = _userBox.get('user');
_ref.read(userProvider.notifier).update((_) => user);
return user;
}

Future<void> deleteUser() async {
await _userBox.delete('user');
_ref.read(userProvider.notifier).update((_) => null);
}
}
41 changes: 17 additions & 24 deletions lib/features/auth/repository/auth_remote_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import 'package:telware_cross_platform/core/models/app_error.dart';
import 'package:flutter/foundation.dart';
import 'package:telware_cross_platform/features/auth/models/auth_response_model.dart';

import 'package:telware_cross_platform/features/auth/repository/auth_local_repository.dart';

part 'auth_remote_repository.g.dart';

@Riverpod(keepAlive: true)
Expand All @@ -19,14 +17,12 @@ AuthRemoteRepository authRemoteRepository(AuthRemoteRepositoryRef ref) {
}

class AuthRemoteRepository {
final ProviderRef<AuthRemoteRepository> _ref;
final Dio _dio;

AuthRemoteRepository({
required ProviderRef<AuthRemoteRepository> ref,
required Dio dio,
}) : _ref = ref,
_dio = dio;
}) : _dio = dio;

Future<AppError?> signUp({
required String email,
Expand Down Expand Up @@ -57,30 +53,28 @@ class AuthRemoteRepository {
return null;
}

Future<AppError?> verifyEmail(
// todo: make sure of what does get from the back-end
Future<Either<AppError, AuthResponseModel>> verifyEmail(
{required String email, required String code}) async {
try {
final response = await _dio.post('/auth/verify',
data: {'email': email, 'verificationCode': code});

if (response.statusCode! >= 400) {
final String message = response.data?['message'] ?? 'Unexpected Error';
return AppError(message);
return Left(AppError(message));
}
final AuthResponseModel verificationResponse = AuthResponseModel.fromMap(
(response.data['data']) as Map<String, dynamic>);

_ref.read(authLocalRepositoryProvider).setUser(verificationResponse.user);
_ref
.read(authLocalRepositoryProvider)
.setToken(verificationResponse.token);
return Right(verificationResponse);
} on DioException catch (dioException) {
return handleDioException(dioException);
return Left(handleDioException(dioException));
} catch (error) {
debugPrint('Verify Email error:\n${error.toString()}');
return AppError("Couldn't verify email now. Please, try again later.");
return Left(
AppError("Couldn't verify email now. Please, try again later."));
}
return null;
}

Future<AppError?> sendConfirmationCode({required String email}) async {
Expand All @@ -101,7 +95,7 @@ class AuthRemoteRepository {
return null;
}

Future<Either<AppError,UserModel>> getMe(String sessionId) async {
Future<Either<AppError, UserModel>> getMe(String sessionId) async {
try {
final response = await _dio.get(
'/users/me',
Expand All @@ -121,11 +115,12 @@ class AuthRemoteRepository {
return Left(handleDioException(dioException));
} catch (error) {
debugPrint('Get user error:\n${error.toString()}');
return Left(AppError('Failed to connect, check your internet connection.'));
return Left(
AppError('Failed to connect, check your internet connection.'));
}
}

Future<AppError?> logIn({
Future<Either<AppError, AuthResponseModel>> logIn({
required String email,
required String password,
}) async {
Expand All @@ -141,24 +136,22 @@ class AuthRemoteRepository {
if (response.statusCode! > 200 || response.statusCode! < 200) {
final String message = response.data?['message'] ?? 'Unexpected Error';
if (response.statusCode == 403) {
return AppError(message, code: 403);
return Left(AppError(message, code: 403));
}
return AppError(message);
return Left(AppError(message));
}

// todo(ahmed): check response body from the back side
final AuthResponseModel logInResponse = AuthResponseModel.fromMap(
(response.data['data']) as Map<String, dynamic>);

_ref.read(authLocalRepositoryProvider).setUser(logInResponse.user);
_ref.read(authLocalRepositoryProvider).setToken(logInResponse.token);
return Right(logInResponse);
} on DioException catch (dioException) {
return handleDioException(dioException);
return Left(handleDioException(dioException));
} catch (e) {
debugPrint('Log in error:\n${e.toString()}');
return AppError('Couldn\'t log in now. Please, try again later.');
return Left(AppError('Couldn\'t log in now. Please, try again later.'));
}
return null;
}

Future<AppError?> logOut(
Expand Down
7 changes: 2 additions & 5 deletions lib/features/auth/view/screens/log_in_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,8 @@ class _LogInScreenState extends ConsumerState<LogInScreen> {
if (someNotFilled) {
vibrate();
} else {
// ref.read(authViewModelProvider.notifier).login(
// email: emailController.text, password: passwordController.text);

// todo(ahmed): navigate to home screen
context.go(Routes.home);
ref.read(authViewModelProvider.notifier).login(
email: emailController.text, password: passwordController.text);
}
}

Expand Down
Loading

0 comments on commit 9b055c7

Please sign in to comment.