From 488479befaf37f01ed4eb7422971d95f61722a46 Mon Sep 17 00:00:00 2001 From: akhdanre Date: Sun, 4 May 2025 11:40:32 +0700 Subject: [PATCH] feat: google sign in auth service --- lib/data/controllers/user_controller.dart | 7 ++++ lib/data/services/google_auth_service.dart | 35 +++++++++++++++++++ lib/feature/login/bindings/login_binding.dart | 4 ++- .../login/controllers/login_controller.dart | 25 +++++++------ .../profile/binding/profile_binding.dart | 5 ++- .../controller/profile_controller.dart | 23 ++++++++++-- 6 files changed, 82 insertions(+), 17 deletions(-) create mode 100644 lib/data/services/google_auth_service.dart diff --git a/lib/data/controllers/user_controller.dart b/lib/data/controllers/user_controller.dart index 35d5d4b..0ee2a54 100644 --- a/lib/data/controllers/user_controller.dart +++ b/lib/data/controllers/user_controller.dart @@ -39,4 +39,11 @@ class UserController extends GetxController { userImage.value = userEntity.picUrl; email.value = userEntity.email; } + + void clearUser() { + userData = null; + userName.value = ""; + userImage.value = ""; + email.value = ''; + } } diff --git a/lib/data/services/google_auth_service.dart b/lib/data/services/google_auth_service.dart new file mode 100644 index 0000000..9ad6096 --- /dev/null +++ b/lib/data/services/google_auth_service.dart @@ -0,0 +1,35 @@ +import 'package:google_sign_in/google_sign_in.dart'; + +class GoogleAuthService { + final GoogleSignIn _googleSignIn = GoogleSignIn( + scopes: ['email', 'profile', 'openid'], + ); + + Future signIn() async { + try { + return await _googleSignIn.signIn(); + } catch (e) { + rethrow; + } + } + + Future signOut() async { + try { + await _googleSignIn.signOut(); + } catch (e) { + rethrow; + } + } + + Future getIdToken() async { + final account = await _googleSignIn.signIn(); + if (account == null) return null; + + final auth = await account.authentication; + return auth.idToken; + } + + Future isSignedIn() async { + return await _googleSignIn.isSignedIn(); + } +} diff --git a/lib/feature/login/bindings/login_binding.dart b/lib/feature/login/bindings/login_binding.dart index 6c7e36f..9686a88 100644 --- a/lib/feature/login/bindings/login_binding.dart +++ b/lib/feature/login/bindings/login_binding.dart @@ -2,13 +2,15 @@ import 'package:get/get_core/get_core.dart'; import 'package:get/get_instance/get_instance.dart'; import 'package:quiz_app/data/controllers/user_controller.dart'; import 'package:quiz_app/data/services/auth_service.dart'; +import 'package:quiz_app/data/services/google_auth_service.dart'; import 'package:quiz_app/data/services/user_storage_service.dart'; import 'package:quiz_app/feature/login/controllers/login_controller.dart'; class LoginBinding extends Bindings { @override void dependencies() { + Get.lazyPut(() => GoogleAuthService()); Get.lazyPut(() => AuthService()); - Get.lazyPut(() => LoginController(Get.find(), Get.find(), Get.find())); + Get.lazyPut(() => LoginController(Get.find(), Get.find(), Get.find(), Get.find())); } } diff --git a/lib/feature/login/controllers/login_controller.dart b/lib/feature/login/controllers/login_controller.dart index 07f3e2d..2dd8f6b 100644 --- a/lib/feature/login/controllers/login_controller.dart +++ b/lib/feature/login/controllers/login_controller.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:google_sign_in/google_sign_in.dart'; import 'package:quiz_app/app/routes/app_pages.dart'; import 'package:quiz_app/component/global_button.dart'; import 'package:quiz_app/core/utils/logger.dart'; @@ -9,14 +8,21 @@ import 'package:quiz_app/data/entity/user/user_entity.dart'; import 'package:quiz_app/data/models/login/login_request_model.dart'; import 'package:quiz_app/data/models/login/login_response_model.dart'; import 'package:quiz_app/data/services/auth_service.dart'; +import 'package:quiz_app/data/services/google_auth_service.dart'; import 'package:quiz_app/data/services/user_storage_service.dart'; class LoginController extends GetxController { final AuthService _authService; final UserStorageService _userStorageService; final UserController _userController; + final GoogleAuthService _googleAuthService; - LoginController(this._authService, this._userStorageService, this._userController); + LoginController( + this._authService, + this._userStorageService, + this._userController, + this._googleAuthService, + ); final TextEditingController emailController = TextEditingController(); final TextEditingController passwordController = TextEditingController(); @@ -25,10 +31,6 @@ class LoginController extends GetxController { final RxBool isPasswordHidden = true.obs; final RxBool isLoading = false.obs; - final GoogleSignIn _googleSignIn = GoogleSignIn( - scopes: ['email', 'profile', 'openid'], - ); - @override void onInit() { super.onInit(); @@ -81,22 +83,19 @@ class LoginController extends GetxController { /// **🔹 Login via Google** Future loginWithGoogle() async { try { - final GoogleSignInAccount? googleUser = await _googleSignIn.signIn(); - if (googleUser == null) { + final user = await _googleAuthService.signIn(); + if (user == null) { Get.snackbar("Error", "Google Sign-In canceled"); return; } - final GoogleSignInAuthentication googleAuth = await googleUser.authentication; - final idToken = googleAuth.idToken; - + final idToken = await user.authentication.then((auth) => auth.idToken); if (idToken == null || idToken.isEmpty) { - Get.snackbar("Error", "Google sign-in failed. No ID Token received."); + Get.snackbar("Error", "No ID Token received."); return; } final LoginResponseModel response = await _authService.loginWithGoogle(idToken); - final userEntity = _convertLoginResponseToUserEntity(response); await _userStorageService.saveUser(userEntity); diff --git a/lib/feature/profile/binding/profile_binding.dart b/lib/feature/profile/binding/profile_binding.dart index e8d0a25..89e85fd 100644 --- a/lib/feature/profile/binding/profile_binding.dart +++ b/lib/feature/profile/binding/profile_binding.dart @@ -1,9 +1,12 @@ import 'package:get/get.dart'; +import 'package:quiz_app/data/services/google_auth_service.dart'; +import 'package:quiz_app/data/services/user_storage_service.dart'; import 'package:quiz_app/feature/profile/controller/profile_controller.dart'; class ProfileBinding extends Bindings { @override void dependencies() { - Get.lazyPut(() => ProfileController()); + Get.lazyPut(() => GoogleAuthService()); + Get.lazyPut(() => ProfileController(Get.find(), Get.find())); } } diff --git a/lib/feature/profile/controller/profile_controller.dart b/lib/feature/profile/controller/profile_controller.dart index 95a4354..52f29f0 100644 --- a/lib/feature/profile/controller/profile_controller.dart +++ b/lib/feature/profile/controller/profile_controller.dart @@ -1,10 +1,18 @@ import 'package:get/get.dart'; +import 'package:quiz_app/app/routes/app_pages.dart'; import 'package:quiz_app/core/utils/logger.dart'; import 'package:quiz_app/data/controllers/user_controller.dart'; +import 'package:quiz_app/data/services/google_auth_service.dart'; +import 'package:quiz_app/data/services/user_storage_service.dart'; class ProfileController extends GetxController { final UserController _userController = Get.find(); + final UserStorageService _userStorageService; + final GoogleAuthService _googleAuthService; + + ProfileController(this._userStorageService, this._googleAuthService); + Rx get userName => _userController.userName; Rx get email => _userController.email; Rx get userImage => _userController.userImage; @@ -12,8 +20,19 @@ class ProfileController extends GetxController { final totalQuizzes = 12.obs; final avgScore = 85.obs; - void logout() { - logC.i("Logout pressed"); + void logout() async { + try { + await _googleAuthService.signOut(); + + await _userStorageService.clearUser(); + _userController.clearUser(); + _userStorageService.isLogged = false; + + Get.offAllNamed(AppRoutes.loginPage); + } catch (e, stackTrace) { + logC.e("Google Sign-Out Error: $e", stackTrace: stackTrace); + Get.snackbar("Error", "Gagal logout dari Google"); + } } void editProfile() {