Add Apple Login => Works only on iPhone for now, will be adding rest later.
This commit is contained in:
@@ -1444,6 +1444,8 @@ PODS:
|
|||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- sign_in_with_apple (0.0.1):
|
||||||
|
- Flutter
|
||||||
- url_launcher_ios (0.0.1):
|
- url_launcher_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
|
||||||
@@ -1461,6 +1463,7 @@ DEPENDENCIES:
|
|||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
|
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
@@ -1520,6 +1523,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
|
sign_in_with_apple:
|
||||||
|
:path: ".symlinks/plugins/sign_in_with_apple/ios"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
|
|
||||||
@@ -1564,6 +1569,7 @@ SPEC CHECKSUMS:
|
|||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
RecaptchaInterop: 11e0b637842dfb48308d242afc3f448062325aba
|
RecaptchaInterop: 11e0b637842dfb48308d242afc3f448062325aba
|
||||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||||
|
sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
|
||||||
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||||
|
|
||||||
PODFILE CHECKSUM: 53a6aebc29ccee84c41f92f409fc20cd4ca011f1
|
PODFILE CHECKSUM: 53a6aebc29ccee84c41f92f409fc20cd4ca011f1
|
||||||
|
|||||||
@@ -340,14 +340,10 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
@@ -376,14 +372,10 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Copy Pods Resources";
|
name = "[CP] Copy Pods Resources";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||||
|
|||||||
@@ -62,5 +62,16 @@
|
|||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>CFBundleURLTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleURLName</key>
|
||||||
|
<string>Apple Sign-In</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:firebase_auth/firebase_auth.dart' as firebase_auth;
|
|||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import '../models/user.dart';
|
import '../models/user.dart';
|
||||||
import '../services/auth_service.dart';
|
import '../services/auth_service.dart';
|
||||||
|
import '../services/error_service.dart';
|
||||||
|
|
||||||
/// Repository for authentication operations and user data management.
|
/// Repository for authentication operations and user data management.
|
||||||
///
|
///
|
||||||
@@ -16,14 +17,15 @@ class AuthRepository {
|
|||||||
/// Firestore instance for user data operations.
|
/// Firestore instance for user data operations.
|
||||||
final FirebaseFirestore _firestore;
|
final FirebaseFirestore _firestore;
|
||||||
|
|
||||||
|
/// Error service for logging authentication errors.
|
||||||
|
final _errorService = ErrorService();
|
||||||
|
|
||||||
/// Creates a new [AuthRepository] with optional service dependencies.
|
/// Creates a new [AuthRepository] with optional service dependencies.
|
||||||
///
|
///
|
||||||
/// If [authService] or [firestore] are not provided, default instances will be used.
|
/// If [authService] or [firestore] are not provided, default instances will be used.
|
||||||
AuthRepository({
|
AuthRepository({AuthService? authService, FirebaseFirestore? firestore})
|
||||||
AuthService? authService,
|
: _authService = authService ?? AuthService(),
|
||||||
FirebaseFirestore? firestore,
|
_firestore = firestore ?? FirebaseFirestore.instance;
|
||||||
}) : _authService = authService ?? AuthService(),
|
|
||||||
_firestore = firestore ?? FirebaseFirestore.instance;
|
|
||||||
|
|
||||||
/// Stream of authentication state changes.
|
/// Stream of authentication state changes.
|
||||||
///
|
///
|
||||||
@@ -57,7 +59,7 @@ class AuthRepository {
|
|||||||
);
|
);
|
||||||
return await getUserFromFirestore(firebaseUser.user!.uid);
|
return await getUserFromFirestore(firebaseUser.user!.uid);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw Exception('Sign-in error: $e');
|
_errorService.showError(message: 'Utilisateur ou mot de passe incorrect');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,9 +97,8 @@ class AuthRepository {
|
|||||||
|
|
||||||
await _firestore.collection('users').doc(user.id).set(user.toMap());
|
await _firestore.collection('users').doc(user.id).set(user.toMap());
|
||||||
return user;
|
return user;
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw Exception('Registration error: $e');
|
_errorService.showError(message: 'Erreur lors de la création du compte');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,8 +134,9 @@ class AuthRepository {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw Exception('Google sign-in error: $e');
|
_errorService.showError(message: 'Erreur lors de la connexion Google');
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signs in a user using Apple authentication.
|
/// Signs in a user using Apple authentication.
|
||||||
@@ -148,8 +150,8 @@ class AuthRepository {
|
|||||||
try {
|
try {
|
||||||
final firebaseUser = await _authService.signInWithApple();
|
final firebaseUser = await _authService.signInWithApple();
|
||||||
|
|
||||||
if (firebaseUser?.user != null) {
|
if (firebaseUser.user != null) {
|
||||||
final existingUser = await getUserFromFirestore(firebaseUser!.user!.uid);
|
final existingUser = await getUserFromFirestore(firebaseUser.user!.uid);
|
||||||
|
|
||||||
if (existingUser != null) {
|
if (existingUser != null) {
|
||||||
return existingUser;
|
return existingUser;
|
||||||
@@ -167,8 +169,9 @@ class AuthRepository {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw Exception('Apple sign-in error: $e');
|
_errorService.showError(message: 'Erreur lors de la connexion Apple');
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signs out the current user.
|
/// Signs out the current user.
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
|
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
|
||||||
import 'package:travel_mate/services/error_service.dart';
|
import 'package:travel_mate/services/error_service.dart';
|
||||||
|
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
|
||||||
|
|
||||||
/// Service for handling Firebase authentication operations.
|
/// Service for handling Firebase authentication operations.
|
||||||
///
|
///
|
||||||
@@ -178,8 +179,83 @@ class AuthService {
|
|||||||
|
|
||||||
/// Signs in a user using Apple authentication.
|
/// Signs in a user using Apple authentication.
|
||||||
///
|
///
|
||||||
/// This method is currently a placeholder for future Apple authentication support.
|
/// Handles the complete Apple Sign-In flow including platform initialization
|
||||||
Future signInWithApple() async {
|
/// and credential exchange with Firebase. Supports both iOS and Android platforms.
|
||||||
// TODO: Implement Apple sign-in
|
///
|
||||||
|
/// Returns a [UserCredential] containing the authenticated user's information.
|
||||||
|
/// Throws various exceptions if authentication fails or platform is not supported.
|
||||||
|
Future<UserCredential> signInWithApple() async {
|
||||||
|
try {
|
||||||
|
await ensureInitialized();
|
||||||
|
|
||||||
|
// Check if Apple Sign-In is available on this platform
|
||||||
|
final bool isAvailable = await SignInWithApple.isAvailable();
|
||||||
|
if (!isAvailable) {
|
||||||
|
throw FirebaseAuthException(
|
||||||
|
code: 'ERROR_APPLE_SIGNIN_NOT_AVAILABLE',
|
||||||
|
message: 'Apple Sign-In is not available on this platform',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request Apple ID credential with platform-specific configuration
|
||||||
|
final AuthorizationCredentialAppleID credential =
|
||||||
|
await SignInWithApple.getAppleIDCredential(
|
||||||
|
scopes: [
|
||||||
|
AppleIDAuthorizationScopes.email,
|
||||||
|
AppleIDAuthorizationScopes.fullName,
|
||||||
|
],
|
||||||
|
// Configuration for Android/Web
|
||||||
|
webAuthenticationOptions: WebAuthenticationOptions(
|
||||||
|
clientId: 'be.devdayronvl.TravelMate',
|
||||||
|
redirectUri: Uri.parse(
|
||||||
|
'https://your-project-id.firebaseapp.com/__/auth/handler',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create OAuth credential for Firebase
|
||||||
|
final OAuthCredential oauthCredential = OAuthProvider("apple.com")
|
||||||
|
.credential(
|
||||||
|
idToken: credential.identityToken,
|
||||||
|
accessToken: credential.authorizationCode,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Sign in with Firebase
|
||||||
|
UserCredential userCredential = await firebaseAuth.signInWithCredential(
|
||||||
|
oauthCredential,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update display name if it's the first sign-in and we have name info
|
||||||
|
if (userCredential.additionalUserInfo?.isNewUser == true &&
|
||||||
|
credential.givenName != null &&
|
||||||
|
credential.familyName != null) {
|
||||||
|
final String displayName =
|
||||||
|
'${credential.givenName} ${credential.familyName}';
|
||||||
|
await userCredential.user?.updateDisplayName(displayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return userCredential;
|
||||||
|
} on SignInWithAppleException catch (e) {
|
||||||
|
_errorService.logError('Apple Sign-In error: $e', StackTrace.current);
|
||||||
|
throw FirebaseAuthException(
|
||||||
|
code: 'ERROR_APPLE_SIGNIN_FAILED',
|
||||||
|
message: 'Apple Sign-In failed: ${e.toString()}',
|
||||||
|
);
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
_errorService.logError(
|
||||||
|
'Firebase error during Apple Sign-In: $e',
|
||||||
|
StackTrace.current,
|
||||||
|
);
|
||||||
|
rethrow;
|
||||||
|
} catch (e) {
|
||||||
|
_errorService.logError(
|
||||||
|
'Unknown error during Apple Sign-In: $e',
|
||||||
|
StackTrace.current,
|
||||||
|
);
|
||||||
|
throw FirebaseAuthException(
|
||||||
|
code: 'ERROR_APPLE_SIGNIN_UNKNOWN',
|
||||||
|
message: 'Unknown error during Apple Sign-In: $e',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
pubspec.lock
24
pubspec.lock
@@ -944,6 +944,30 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.1"
|
version: "2.4.1"
|
||||||
|
sign_in_with_apple:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: sign_in_with_apple
|
||||||
|
sha256: "8bd875c8e8748272749eb6d25b896f768e7e9d60988446d543fe85a37a2392b8"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.1"
|
||||||
|
sign_in_with_apple_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sign_in_with_apple_platform_interface
|
||||||
|
sha256: "981bca52cf3bb9c3ad7ef44aace2d543e5c468bb713fd8dda4275ff76dfa6659"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
|
sign_in_with_apple_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sign_in_with_apple_web
|
||||||
|
sha256: f316400827f52cafcf50d00e1a2e8a0abc534ca1264e856a81c5f06bd5b10fed
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.0"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ dependencies:
|
|||||||
intl: ^0.20.2
|
intl: ^0.20.2
|
||||||
firebase_storage: ^13.0.3
|
firebase_storage: ^13.0.3
|
||||||
url_launcher: ^6.3.2
|
url_launcher: ^6.3.2
|
||||||
|
sign_in_with_apple: ^7.0.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_launcher_icons: ^0.13.1
|
flutter_launcher_icons: ^0.13.1
|
||||||
|
|||||||
Reference in New Issue
Block a user