diff --git a/bu_passport/android/app/build.gradle b/bu_passport/android/app/build.gradle index ef3cfb2..5dd9ce6 100644 --- a/bu_passport/android/app/build.gradle +++ b/bu_passport/android/app/build.gradle @@ -2,6 +2,7 @@ plugins { id "com.android.application" id "kotlin-android" id "dev.flutter.flutter-gradle-plugin" + id 'com.google.gms.google-services' } def localProperties = new Properties() @@ -45,12 +46,14 @@ android { applicationId "com.example.bu_passport" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion flutter.minSdkVersion targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName multiDexEnabled true - minSdkVersion 20 + minSdkVersion 23 + manifestPlaceholders += [ + 'appAuthRedirectScheme': 'com.example.bu_passport' + ] } buildTypes { @@ -68,4 +71,5 @@ flutter { dependencies { implementation 'androidx.multidex:multidex:2.0.1' + implementation platform('com.google.firebase:firebase-bom:33.4.0') } diff --git a/bu_passport/android/build.gradle b/bu_passport/android/build.gradle index bc157bd..008c4f7 100644 --- a/bu_passport/android/build.gradle +++ b/bu_passport/android/build.gradle @@ -1,3 +1,8 @@ +plugins { + // Add the dependency for the Google services Gradle plugin + id 'com.google.gms.google-services' version '4.4.2' apply false +} + allprojects { repositories { google() diff --git a/bu_passport/android/google-services.json b/bu_passport/android/google-services.json new file mode 100644 index 0000000..893ae4e --- /dev/null +++ b/bu_passport/android/google-services.json @@ -0,0 +1,55 @@ +{ + "project_info": { + "project_number": "429645705382", + "firebase_url": "https://se-bu-passport-default-rtdb.firebaseio.com", + "project_id": "se-bu-passport", + "storage_bucket": "se-bu-passport.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:429645705382:android:9f0f8af5edb9341147c467", + "android_client_info": { + "package_name": "com.example.bu_passport" + } + }, + "oauth_client": [ + { + "client_id": "429645705382-eaea9sqfmj8st3mn8o2t9jgnbacih67m.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.example.bu_passport", + "certificate_hash": "d20f358562edf29f6d34f9d5ab57697734bc4157" + } + }, + { + "client_id": "429645705382-qdv5dcrft8ifi50gs2d1e7psu7e22nfq.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCoIG5QDtwfePSWyYQWOBZQgMLy3RPetc4" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "429645705382-qdv5dcrft8ifi50gs2d1e7psu7e22nfq.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "429645705382-1j4106od8lrq0ceoetqln2c928v18850.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.example.buPassport.RunnerTests" + } + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/bu_passport/android/gradle/wrapper/gradle-wrapper.properties b/bu_passport/android/gradle/wrapper/gradle-wrapper.properties index e1ca574..6cb8454 100644 --- a/bu_passport/android/gradle/wrapper/gradle-wrapper.properties +++ b/bu_passport/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-all.zip diff --git a/bu_passport/firebase.json b/bu_passport/firebase.json new file mode 100644 index 0000000..0bf5976 --- /dev/null +++ b/bu_passport/firebase.json @@ -0,0 +1 @@ +{"flutter":{"platforms":{"android":{"default":{"projectId":"crypto-monolith-417321","appId":"1:368645643837:android:9762661e16a81671965454","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"crypto-monolith-417321","appId":"1:368645643837:ios:259eeb31aac82760965454","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"macos":{"default":{"projectId":"crypto-monolith-417321","appId":"1:368645643837:ios:259eeb31aac82760965454","uploadDebugSymbols":false,"fileOutput":"macos/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"crypto-monolith-417321","configurations":{"android":"1:368645643837:android:9762661e16a81671965454","ios":"1:368645643837:ios:259eeb31aac82760965454","macos":"1:368645643837:ios:259eeb31aac82760965454","web":"1:368645643837:web:0c7de7191eb84a8a965454","windows":"1:368645643837:web:c8ea8678917e5ca3965454"}}}}}} \ No newline at end of file diff --git a/bu_passport/ios/Flutter/Flutter.podspec b/bu_passport/ios/Flutter/Flutter.podspec deleted file mode 100644 index 98e1633..0000000 --- a/bu_passport/ios/Flutter/Flutter.podspec +++ /dev/null @@ -1,18 +0,0 @@ -# -# This podspec is NOT to be published. It is only used as a local source! -# This is a generated file; do not edit or check into version control. -# - -Pod::Spec.new do |s| - s.name = 'Flutter' - s.version = '1.0.0' - s.summary = 'A UI toolkit for beautiful and fast apps.' - s.homepage = 'https://flutter.dev' - s.license = { :type => 'BSD' } - s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } - s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } - s.ios.deployment_target = '12.0' - # Framework linking is handled by Flutter tooling, not CocoaPods. - # Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs. - s.vendored_frameworks = 'path/to/nothing' -end diff --git a/bu_passport/ios/Flutter/Generated.xcconfig b/bu_passport/ios/Flutter/Generated.xcconfig index 9309e6d..fd56f3d 100644 --- a/bu_passport/ios/Flutter/Generated.xcconfig +++ b/bu_passport/ios/Flutter/Generated.xcconfig @@ -1,15 +1,14 @@ // This is a generated file; do not edit or check into version control. -FLUTTER_ROOT=/Users/saisriram/development/flutter -FLUTTER_APPLICATION_PATH=/Users/saisriram/Desktop/BUPassport/se-bu-passport-arts/bu_passport +FLUTTER_ROOT=C:\Users\franj\flutter\flutter_windows_3.24.3-stable\flutter +FLUTTER_APPLICATION_PATH=C:\Users\franj\se-bu-passport-arts\bu_passport COCOAPODS_PARALLEL_CODE_SIGN=true -FLUTTER_TARGET=/Users/saisriram/Desktop/BUPassport/se-bu-passport-arts/bu_passport/lib/main.dart +FLUTTER_TARGET=lib\main.dart FLUTTER_BUILD_DIR=build FLUTTER_BUILD_NAME=1.0.0 FLUTTER_BUILD_NUMBER=1 EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 arm64 EXCLUDED_ARCHS[sdk=iphoneos*]=armv7 -DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC8wNDgxN2M5OWM5ZmQ0OTU2ZjI3NTA1MjA0ZjdlMzQ0MzM1ODEwYWVkLw== DART_OBFUSCATION=false TRACK_WIDGET_CREATION=true TREE_SHAKE_ICONS=false -PACKAGE_CONFIG=/Users/saisriram/Desktop/BUPassport/se-bu-passport-arts/bu_passport/.dart_tool/package_config.json +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/bu_passport/ios/Flutter/flutter_export_environment.sh b/bu_passport/ios/Flutter/flutter_export_environment.sh index b1b041f..3b69bc7 100755 --- a/bu_passport/ios/Flutter/flutter_export_environment.sh +++ b/bu_passport/ios/Flutter/flutter_export_environment.sh @@ -1,14 +1,13 @@ #!/bin/sh # This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=/Users/saisriram/development/flutter" -export "FLUTTER_APPLICATION_PATH=/Users/saisriram/Desktop/BUPassport/se-bu-passport-arts/bu_passport" +export "FLUTTER_ROOT=C:\Users\franj\flutter\flutter_windows_3.24.3-stable\flutter" +export "FLUTTER_APPLICATION_PATH=C:\Users\franj\se-bu-passport-arts\bu_passport" export "COCOAPODS_PARALLEL_CODE_SIGN=true" -export "FLUTTER_TARGET=/Users/saisriram/Desktop/BUPassport/se-bu-passport-arts/bu_passport/lib/main.dart" +export "FLUTTER_TARGET=lib\main.dart" export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" -export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC8wNDgxN2M5OWM5ZmQ0OTU2ZjI3NTA1MjA0ZjdlMzQ0MzM1ODEwYWVkLw==" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false" -export "PACKAGE_CONFIG=/Users/saisriram/Desktop/BUPassport/se-bu-passport-arts/bu_passport/.dart_tool/package_config.json" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/bu_passport/ios/Runner/GeneratedPluginRegistrant.m b/bu_passport/ios/Runner/GeneratedPluginRegistrant.m index 8eb66a7..2853a60 100644 --- a/bu_passport/ios/Runner/GeneratedPluginRegistrant.m +++ b/bu_passport/ios/Runner/GeneratedPluginRegistrant.m @@ -42,6 +42,12 @@ @import google_maps_flutter_ios; #endif +#if __has_include() +#import +#else +@import google_sign_in_ios; +#endif + #if __has_include() #import #else @@ -69,6 +75,7 @@ + (void)registerWithRegistry:(NSObject*)registry { [FLTFirebaseStoragePlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseStoragePlugin"]]; [GeolocatorPlugin registerWithRegistrar:[registry registrarForPlugin:@"GeolocatorPlugin"]]; [FLTGoogleMapsPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTGoogleMapsPlugin"]]; + [FLTGoogleSignInPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTGoogleSignInPlugin"]]; [FLTImagePickerPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTImagePickerPlugin"]]; [PermissionHandlerPlugin registerWithRegistrar:[registry registrarForPlugin:@"PermissionHandlerPlugin"]]; [URLLauncherPlugin registerWithRegistrar:[registry registrarForPlugin:@"URLLauncherPlugin"]]; diff --git a/bu_passport/ios/Runner/Info.plist b/bu_passport/ios/Runner/Info.plist index 0c64889..d0aace8 100644 --- a/bu_passport/ios/Runner/Info.plist +++ b/bu_passport/ios/Runner/Info.plist @@ -54,5 +54,18 @@ We need your location to check you into events near you. NSLocationAlwaysAndWhenInUseUsageDescription We need your location to provide notifications and information about events near you. + GIDClientID + 429645705382-neovegus18m295gn11dpo2g6mi85tv3j.apps.googleusercontent.com + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLSchemes + + com.googleusercontent.apps.429645705382-neovegus18m295gn11dpo2g6mi85tv3j + + + diff --git a/bu_passport/lib/classes/user.dart b/bu_passport/lib/classes/user.dart index 2953645..97fadc5 100644 --- a/bu_passport/lib/classes/user.dart +++ b/bu_passport/lib/classes/user.dart @@ -9,6 +9,7 @@ class Users { final int userPoints; final String userProfileURL; final Map userSavedEvents; + final bool admin; Users({ required this.firstName, @@ -21,5 +22,6 @@ class Users { required this.userSavedEvents, required this.userPoints, required this.userProfileURL, + required this.admin, }); } diff --git a/bu_passport/lib/pages/login_page.dart b/bu_passport/lib/pages/login_page.dart index 3efd246..2c8d80d 100644 --- a/bu_passport/lib/pages/login_page.dart +++ b/bu_passport/lib/pages/login_page.dart @@ -1,23 +1,124 @@ import 'package:bu_passport/pages/signup_page.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; +import 'package:google_sign_in/google_sign_in.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; class LoginPage extends StatefulWidget { const LoginPage({Key? key}) : super(key: key); + @override State createState() => _LoginPageState(); } class _LoginPageState extends State { - TextEditingController _emailController = TextEditingController(); - TextEditingController _passwordController = TextEditingController(); String? _errorMessage; + static bool newUser = false; + static bool BUemail = true; + + // Navigate to the signup page + void _navigateToSignUp() { + if (mounted) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const SignUpPage(), + ), + ); + } + } + + // Navigate to the home page + void _navigateToHome() { + if (mounted) { + Navigator.pushNamed(context, '/home'); + } + } + + Future _signInWithGoogle() async { + try { + final GoogleSignIn googleSignIn = GoogleSignIn( + hostedDomain: 'bu.edu', + ); + final GoogleSignInAccount? googleUser = await googleSignIn.signIn(); + if (googleUser == null) { + return null; // The user canceled the sign-in + } + + final GoogleSignInAuthentication googleAuth = await googleUser.authentication; + final AuthCredential credential = GoogleAuthProvider.credential( + accessToken: googleAuth.accessToken, + idToken: googleAuth.idToken, + ); + + final UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(credential); + final User? user = userCredential.user; + + if (user != null) { + if (user.email != null && !user.email!.contains("bu.edu")) { + BUemail = false; + await user.delete(); + setState(() { + _errorMessage = 'Please sign in with a BU email address.'; + }); + return null; + } else { + BUemail = true; + } + // Check if the user document exists in Firestore + final userDoc = FirebaseFirestore.instance.collection('users').doc(user.uid); + final docSnapshot = await userDoc.get(); + + if (!docSnapshot.exists) { + // Create a new user document + await userDoc.set({ + 'userUID': user.uid, + 'userEmail': user.email, + 'firstName': userCredential.additionalUserInfo?.profile?['given_name'], + 'lastName': userCredential.additionalUserInfo?.profile?['family_name'], + 'userProfileURL': user.photoURL, + 'userPoints': 0, + 'userSavedEvents': {}, + // Additional fields to be filled by the user + 'userBUID': '', + 'userSchool': '', + 'userYear': 0, + 'admin': false, + }); + // Set newUser flag + newUser = true; + } else { + // Check if additional fields are set + final data = docSnapshot.data(); + + if (data != null && (data['userBUID'] == '' || data['userSchool'] == '' || data['userYear'] == 0)) { + newUser = true; + } + } + } else { + setState(() { + _errorMessage = 'Sign in failed. Please sign in with a BU email address.'; + }); + return null; + } + + return user; + } catch (e) { + if (_errorMessage != null) { + setState(() { + _errorMessage = 'Please sign in with a BU email address. Error: $e'; + }); + } else if (mounted) { + setState(() { + _errorMessage = 'Google Sign-In failed. Please try again. Error: $e'; + }); + } + return null; + } + } @override Widget build(BuildContext context) { - double screenWidth = MediaQuery.of(context).size.width; - double screenHeight = MediaQuery.of(context).size.height; - double sizedBoxHeight = (MediaQuery.of(context).size.height * 0.05); double edgeInsets = (MediaQuery.of(context).size.width * 0.02); @@ -32,82 +133,49 @@ class _LoginPageState extends State { "assets/images/onboarding/BU art logo.png", fit: BoxFit.contain, ), - TextField( - controller: _emailController, - decoration: const InputDecoration( - labelText: 'Email', - ), - ), SizedBox(height: sizedBoxHeight), - TextField( - controller: _passwordController, - decoration: const InputDecoration( - labelText: 'Password', + GestureDetector( + onTap: () async { + User? user = await _signInWithGoogle(); + if (user != null) { + if (newUser) { + debugPrint("navigate to signup"); + _navigateToSignUp(); + } else { + debugPrint("navigate to home"); + _navigateToHome(); + } + } + }, + child: Container( + width: 244.14, + height: 43.89, + decoration: BoxDecoration( + color: const Color(0xFFCC0000), + borderRadius: BorderRadius.circular(66.75), + ), + child: const Center( + child: Text( + 'Sign In with BU Gmail', + style: TextStyle( + color: Colors.white, + fontSize: 16, + ), + ), + ), ), - obscureText: true, ), - if (_errorMessage != null) + SizedBox(height: sizedBoxHeight), + if (_errorMessage != null || !BUemail) Text( - _errorMessage!, - style: TextStyle(color: Colors.red), + 'Please sign in with a BU email address.', + style: const TextStyle(color: Color(0xFFCC0000)), ), SizedBox(height: sizedBoxHeight), - ElevatedButton( - onPressed: () async { - // Reset error message - setState(() { - _errorMessage = null; - }); - String email = _emailController.text; - String password = _passwordController.text; - try { - await FirebaseAuth.instance.signInWithEmailAndPassword( - email: email, - password: password, - ); - // Navigate to home page - Navigator.pushNamed(context, '/home'); - } catch (e) { - // Handle login errors - print('Login error: $e'); - setState(() { - _errorMessage = - 'Login failed. Please check your email and password.'; - }); - } - }, - child: const Text('Sign In'), - ), - SizedBox(height: sizedBoxHeight), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text('Don\'t have an account?'), - TextButton( - onPressed: () { - // Navigate to sign up page - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SignUpPage(), - ), - ); - }, - child: const Text('Sign Up'), - ), - ], - ) ], ), ), ), ); } - - @override - void dispose() { - _emailController.dispose(); - _passwordController.dispose(); - super.dispose(); - } -} +} \ No newline at end of file diff --git a/bu_passport/lib/pages/signup_page.dart b/bu_passport/lib/pages/signup_page.dart index 3cbc289..2996230 100644 --- a/bu_passport/lib/pages/signup_page.dart +++ b/bu_passport/lib/pages/signup_page.dart @@ -1,194 +1,163 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; -// SignUpPage allows new users to create an account. class SignUpPage extends StatefulWidget { const SignUpPage({Key? key}) : super(key: key); + @override State createState() => _SignUpPageState(); } -// State class for SignUpPage handling user sign-up logic. class _SignUpPageState extends State { - // Text controllers to manage the input fields for user registration. - TextEditingController _emailController = TextEditingController(); - TextEditingController _passwordController = TextEditingController(); - TextEditingController _firstNameController = TextEditingController(); - TextEditingController _lastNameController = TextEditingController(); - TextEditingController _buIDController = TextEditingController(); - TextEditingController _userSchool = TextEditingController(); - TextEditingController _userYear = TextEditingController(); + final _formKey = GlobalKey(); + final _firstNameController = TextEditingController(); + final _lastNameController = TextEditingController(); + final _userBUIDController = TextEditingController(); + final _userSchoolController = TextEditingController(); + final _userYearController = TextEditingController(); - final db = FirebaseFirestore.instance; // Firestore instance for data storage. + Future _saveUserInfo() async { + if (_formKey.currentState!.validate()) { + final user = FirebaseAuth.instance.currentUser; + if (user != null) { + final userDoc = FirebaseFirestore.instance.collection('users').doc(user.uid); + await userDoc.update({ + 'firstName': _firstNameController.text, + 'lastName': _lastNameController.text, + 'userBUID': _userBUIDController.text, + 'userSchool': _userSchoolController.text, + 'userYear': int.parse(_userYearController.text), + }); + Navigator.pushNamed(context, '/home'); + } + } + } @override Widget build(BuildContext context) { - double screenWidth = MediaQuery.of(context).size.width; - double screenHeight = MediaQuery.of(context).size.height; - - // Variables for consistent spacing and padding in the UI. - double sizedBoxHeight = screenHeight * 0.02; - double edgeInsets = screenWidth * 0.02; - return Scaffold( - appBar: AppBar(), // Simple AppBar for the layout. - body: Center( - child: SingleChildScrollView( - child: Padding( - padding: EdgeInsets.all(edgeInsets), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox(height: sizedBoxHeight), - // Input field for first name. - TextField( - controller: _firstNameController, - decoration: const InputDecoration( - labelText: 'First Name', + appBar: AppBar( + title: const Text('Complete Your Profile', + style: TextStyle( + color: Colors.black, + fontSize: 17, + fontFamily: 'Inter', + fontWeight: FontWeight.w500, + height: 0, + ), + ), + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Form( + key: _formKey, + child: Column( + children: [ + TextFormField( + controller: _firstNameController, + decoration: InputDecoration(labelText: 'First Name'), + style: const TextStyle( + color: Colors.black, + fontSize: 14.93, + fontFamily: 'Inter', + fontWeight: FontWeight.w400, + height: 0, ), - ), - SizedBox(height: sizedBoxHeight), - // Input field for last name. - TextField( - controller: _lastNameController, - decoration: const InputDecoration( - labelText: 'Last Name', + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your first name'; + } + return null; + }, + ), + TextFormField( + controller: _lastNameController, + decoration: InputDecoration(labelText: 'Last Name'), + style: const TextStyle( + color: Colors.black, + fontSize: 14.93, + fontFamily: 'Inter', + fontWeight: FontWeight.w400, + height: 0, ), - ), - SizedBox(height: sizedBoxHeight), - // Input field for email. - TextField( - controller: _emailController, - decoration: const InputDecoration( - labelText: 'Email', + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your last name'; + } + return null; + }, + ), + TextFormField( + controller: _userBUIDController, + decoration: InputDecoration(labelText: 'BUID'), + style: const TextStyle( + color: Colors.black, + fontSize: 14.93, + fontFamily: 'Inter', + fontWeight: FontWeight.w400, + height: 0, ), - ), - SizedBox(height: sizedBoxHeight), - // Input field for university ID. - TextField( - controller: _buIDController, - decoration: const InputDecoration( - labelText: 'BU ID', + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your BUID'; + } + return null; + }, + ), + TextFormField( + controller: _userSchoolController, + decoration: InputDecoration(labelText: 'School'), + style: const TextStyle( + color: Colors.black, + fontSize: 14.93, + fontFamily: 'Inter', + fontWeight: FontWeight.w400, + height: 0, ), - ), - SizedBox(height: sizedBoxHeight), - // Input field for the school within the university. - TextField( - controller: _userSchool, - decoration: const InputDecoration( - labelText: 'School', + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your school'; + } + return null; + }, + ), + TextFormField( + controller: _userYearController, + decoration: InputDecoration(labelText: 'Year'), + style: const TextStyle( + color: Colors.black, + fontSize: 14.93, + fontFamily: 'Inter', + fontWeight: FontWeight.w400, + height: 0, ), - ), - SizedBox(height: sizedBoxHeight), - // Input field for the year in school. - TextField( - controller: _userYear, - decoration: const InputDecoration( - labelText: 'Year', - ), - ), - SizedBox(height: sizedBoxHeight), - // Input field for password, obscured for security. - TextField( - controller: _passwordController, - decoration: const InputDecoration( - labelText: 'Password', + keyboardType: TextInputType.number, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your year'; + } + return null; + }, + ), + SizedBox(height: 20), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFFCC0000), + textStyle: const TextStyle( + color: Color(0xFFFFFFFF), + fontSize: 22.32, + fontFamily: 'Inter', + fontWeight: FontWeight.w500, ), - obscureText: true, ), - SizedBox(height: sizedBoxHeight), - // Button to submit the sign-up form. - ElevatedButton( - onPressed: () async { - String email = _emailController.text; - String password = _passwordController.text; - String firstName = _firstNameController.text; - String lastName = _lastNameController.text; - String buID = _buIDController.text; - String school = _userSchool.text; - String year_text = _userYear.toString().trim(); - - // Check if any of the fields are empty. - if (email.isEmpty || - password.isEmpty || - firstName.isEmpty || - lastName.isEmpty || - buID.isEmpty || - school.isEmpty || - year_text.isEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Please fill out all fields.')), - ); - return; - } - int year = int.parse(year_text); - - try { - // Firebase Auth call to create a new user with email and password. - final userCredential = await FirebaseAuth.instance - .createUserWithEmailAndPassword( - email: email, - password: password, - ); - - // Preparing user data for Firestore. - final user = { - 'firstName': firstName, - 'lastName': lastName, - 'userEmail': userCredential.user!.email, - 'userUID': userCredential.user!.uid, - 'userSchool': school, - 'userYear': year, - 'userBUID': buID, - 'userPoints': 0, - 'userProfileURL': '', - 'userSavedEvents': Map(), - }; - // Saving user data to Firestore. - await db - .collection('users') - .doc(userCredential.user!.uid) - .set(user); - Navigator.pushNamed(context, '/onboarding'); - } catch (e) { - if (e is FirebaseAuthException) { - if (e.code == 'weak-password') { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: - Text('The password provided is too weak.')), - ); - } else if (e.code == 'email-already-in-use') { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'The account already exists for that email.')), - ); - } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Error: ${e.message ?? 'An unknown error occurred.'}')), - ); - } - } else { - // Handle other types of exceptions - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: $e')), - ); - } - } - }, - child: const Text('Sign Up'), - ), - ], - ), + onPressed: _saveUserInfo, + child: Text('Save'), + ), + ], ), ), ), ); } -} +} \ No newline at end of file diff --git a/bu_passport/lib/services/firebase_service.dart b/bu_passport/lib/services/firebase_service.dart index 2ff75cd..ee751f5 100644 --- a/bu_passport/lib/services/firebase_service.dart +++ b/bu_passport/lib/services/firebase_service.dart @@ -83,6 +83,7 @@ class FirebaseService { userPoints: userData['userPoints'], userSavedEvents: Map.from(userData['userSavedEvents'] ?? {}), + admin: userData['admin'], ); return user; } else { @@ -340,6 +341,7 @@ class FirebaseService { Map.from(userData['userSavedEvents'] ?? {}), userPoints: userData['userPoints'], userProfileURL: userData['userProfileURL'], + admin: userData['admin'], ); users.add(user); }); diff --git a/bu_passport/macos/Flutter/GeneratedPluginRegistrant.swift b/bu_passport/macos/Flutter/GeneratedPluginRegistrant.swift index dbd9bdd..5c91395 100644 --- a/bu_passport/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/bu_passport/macos/Flutter/GeneratedPluginRegistrant.swift @@ -11,6 +11,7 @@ import firebase_auth import firebase_core import firebase_storage import geolocator_apple +import google_sign_in_ios import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { @@ -20,5 +21,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseStoragePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseStoragePlugin")) GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) + FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/bu_passport/macos/GoogleService-Info (1).plist b/bu_passport/macos/GoogleService-Info (1).plist new file mode 100644 index 0000000..0ea15da --- /dev/null +++ b/bu_passport/macos/GoogleService-Info (1).plist @@ -0,0 +1,38 @@ + + + + + CLIENT_ID + 429645705382-1j4106od8lrq0ceoetqln2c928v18850.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.429645705382-1j4106od8lrq0ceoetqln2c928v18850 + ANDROID_CLIENT_ID + 429645705382-eaea9sqfmj8st3mn8o2t9jgnbacih67m.apps.googleusercontent.com + API_KEY + AIzaSyDB-0rxfn8BysrqjdSsWddOiJseJlvvIyo + GCM_SENDER_ID + 429645705382 + PLIST_VERSION + 1 + BUNDLE_ID + com.example.buPassport.RunnerTests + PROJECT_ID + se-bu-passport + STORAGE_BUCKET + se-bu-passport.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:429645705382:ios:cd4b6c01aab761b947c467 + DATABASE_URL + https://se-bu-passport-default-rtdb.firebaseio.com + + \ No newline at end of file diff --git a/bu_passport/package-lock.json b/bu_passport/package-lock.json new file mode 100644 index 0000000..f0fb6bc --- /dev/null +++ b/bu_passport/package-lock.json @@ -0,0 +1,693 @@ +{ + "name": "bu_passport", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@clerk/nextjs": "^5.7.3" + } + }, + "node_modules/@clerk/backend": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@clerk/backend/-/backend-1.13.10.tgz", + "integrity": "sha512-1pastJJ+LpEPxKynseJVsZhOwn4bO8Mg+ekCeoDbQC4b4jxSM4kOGriYAXy8xe4q2K+pufe/pTPeKxQT/jkxtg==", + "license": "MIT", + "dependencies": { + "@clerk/shared": "2.9.1", + "@clerk/types": "4.25.1", + "cookie": "0.7.0", + "snakecase-keys": "5.4.4", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=18.17.0" + } + }, + "node_modules/@clerk/clerk-react": { + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/@clerk/clerk-react/-/clerk-react-5.11.1.tgz", + "integrity": "sha512-m7x681y6MasiXsfNaTbo5c8JQKtWlZMbDRKf75Cmoo7naDbccWBZNPY1OYbK0uxpnxY24zi/2xfKWTufW8q5RA==", + "license": "MIT", + "dependencies": { + "@clerk/shared": "2.9.1", + "@clerk/types": "4.25.1", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=18.17.0" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-beta", + "react-dom": ">=18 || >=19.0.0-beta" + } + }, + "node_modules/@clerk/nextjs": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/@clerk/nextjs/-/nextjs-5.7.3.tgz", + "integrity": "sha512-9HwiK43waReG4q9ADbG0k3IzFwV3+pSB8i1p3fieM6wf5iOpbrWQAbNtStx0rRqZ/x9WJTp3xavqStmETgeUqQ==", + "license": "MIT", + "dependencies": { + "@clerk/backend": "1.13.10", + "@clerk/clerk-react": "5.11.1", + "@clerk/shared": "2.9.1", + "@clerk/types": "4.25.1", + "crypto-js": "4.2.0", + "server-only": "0.0.1", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=18.17.0" + }, + "peerDependencies": { + "next": "^13.5.4 || ^14.0.3 || >=15.0.0-rc", + "react": ">=18 || >=19.0.0-beta", + "react-dom": ">=18 || >=19.0.0-beta" + } + }, + "node_modules/@clerk/shared": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-2.9.1.tgz", + "integrity": "sha512-NOO6gLRKvEMmz/3pjDiG/rE7ZSmLbZFaU1yTyx94Wb33v0sAaF4v8uypbXSswgAsPWVKu+fgkWmmbhBJP5Us7A==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@clerk/types": "4.25.1", + "glob-to-regexp": "0.4.1", + "js-cookie": "3.0.5", + "std-env": "^3.7.0", + "swr": "^2.2.0" + }, + "engines": { + "node": ">=18.17.0" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-beta", + "react-dom": ">=18 || >=19.0.0-beta" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@clerk/types": { + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/@clerk/types/-/types-4.25.1.tgz", + "integrity": "sha512-ILvR2YXz6BSGXDoozBAd2BGj8ZF/FQrfWQd0FtLz1JXt1vurkgRncAhEcC427OiXNRnq5R2Pn++urfFEa0PqYA==", + "license": "MIT", + "dependencies": { + "csstype": "3.1.1" + }, + "engines": { + "node": ">=18.17.0" + } + }, + "node_modules/@next/env": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.15.tgz", + "integrity": "sha512-S1qaj25Wru2dUpcIZMjxeMVSwkt8BK4dmWHHiBuRstcIyOsMapqT4A4jSB6onvqeygkSSmOkyny9VVx8JIGamQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.15.tgz", + "integrity": "sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.15.tgz", + "integrity": "sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.15.tgz", + "integrity": "sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.15.tgz", + "integrity": "sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.15.tgz", + "integrity": "sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.15.tgz", + "integrity": "sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.15.tgz", + "integrity": "sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.15.tgz", + "integrity": "sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.15.tgz", + "integrity": "sha512-SzqGbsLsP9OwKNUG9nekShTwhj6JSB9ZLMWQ8g1gG6hdE5gQLncbnbymrwy2yVmH9nikSLYRYxYMFu78Ggp7/g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0", + "peer": true + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "peer": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001669", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", + "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0", + "peer": true + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.0.tgz", + "integrity": "sha512-qCf+V4dtlNhSRXGAZatc1TasyFO6GjohcOul807YOb5ik3+kQSnb4d7iajeCL8QHaJ4uZEjCgiCJerKXwdRVlQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", + "license": "MIT" + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC", + "peer": true + }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT", + "peer": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.15.tgz", + "integrity": "sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@next/env": "14.2.15", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.15", + "@next/swc-darwin-x64": "14.2.15", + "@next/swc-linux-arm64-gnu": "14.2.15", + "@next/swc-linux-arm64-musl": "14.2.15", + "@next/swc-linux-x64-gnu": "14.2.15", + "@next/swc-linux-x64-musl": "14.2.15", + "@next/swc-win32-arm64-msvc": "14.2.15", + "@next/swc-win32-ia32-msvc": "14.2.15", + "@next/swc-win32-x64-msvc": "14.2.15" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC", + "peer": true + }, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/server-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", + "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==", + "license": "MIT" + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/snakecase-keys": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-5.4.4.tgz", + "integrity": "sha512-YTywJG93yxwHLgrYLZjlC75moVEX04LZM4FHfihjHe1FCXm+QaLOFfSf535aXOAd0ArVQMWUAe8ZPm4VtWyXaA==", + "license": "MIT", + "dependencies": { + "map-obj": "^4.1.0", + "snake-case": "^3.0.4", + "type-fest": "^2.5.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "license": "MIT" + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "peer": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "license": "MIT", + "peer": true, + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/swr": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.2.5.tgz", + "integrity": "sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==", + "license": "MIT", + "dependencies": { + "client-only": "^0.0.1", + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + } + } +} diff --git a/bu_passport/package.json b/bu_passport/package.json new file mode 100644 index 0000000..5f56a3d --- /dev/null +++ b/bu_passport/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@clerk/nextjs": "^5.7.3" + } +} diff --git a/bu_passport/pubspec.lock b/bu_passport/pubspec.lock index 957d053..0cb447b 100644 --- a/bu_passport/pubspec.lock +++ b/bu_passport/pubspec.lock @@ -544,6 +544,46 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.6+2" + google_sign_in: + dependency: "direct main" + description: + name: google_sign_in + sha256: "821f354c053d51a2d417b02d42532a19a6ea8057d2f9ebb8863c07d81c98aaf9" + url: "https://pub.dev" + source: hosted + version: "5.4.4" + google_sign_in_android: + dependency: transitive + description: + name: google_sign_in_android + sha256: "0928059d2f0840f63c7b07a30cf73b593ae872cdd0dbd46d1b9ba878d2599c01" + url: "https://pub.dev" + source: hosted + version: "6.1.33" + google_sign_in_ios: + dependency: transitive + description: + name: google_sign_in_ios + sha256: "83f015169102df1ab2905cf8abd8934e28f87db9ace7a5fa676998842fed228a" + url: "https://pub.dev" + source: hosted + version: "5.7.8" + google_sign_in_platform_interface: + dependency: transitive + description: + name: google_sign_in_platform_interface + sha256: "1f6e5787d7a120cc0359ddf315c92309069171306242e181c09472d1b00a2971" + url: "https://pub.dev" + source: hosted + version: "2.4.5" + google_sign_in_web: + dependency: transitive + description: + name: google_sign_in_web + sha256: "75cc41ebc53b1756320ee14d9c3018ad3e6cea298147dbcd86e9d0c8d6720b40" + url: "https://pub.dev" + source: hosted + version: "0.10.2+1" graphs: dependency: transitive description: @@ -692,26 +732,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" lints: dependency: transitive description: @@ -748,18 +788,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.15.0" mime: dependency: transitive description: @@ -1065,26 +1105,26 @@ packages: dependency: "direct dev" description: name: test - sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f + sha256: "7ee44229615f8f642b68120165ae4c2a75fe77ae2065b1e55ae4711f6cf0899e" url: "https://pub.dev" source: hosted - version: "1.24.9" + version: "1.25.7" test_api: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.2" test_core: dependency: transitive description: name: test_core - sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a + sha256: "55ea5a652e38a1dfb32943a7973f3681a60f872f8c3a05a14664ad54ef9c6696" url: "https://pub.dev" source: hosted - version: "0.5.9" + version: "0.6.4" timezone: dependency: "direct main" description: @@ -1201,10 +1241,10 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.5" watcher: dependency: transitive description: @@ -1246,5 +1286,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.3.0 <4.0.0" - flutter: ">=3.19.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.24.0" diff --git a/bu_passport/pubspec.yaml b/bu_passport/pubspec.yaml index 74f1a16..6d9d140 100644 --- a/bu_passport/pubspec.yaml +++ b/bu_passport/pubspec.yaml @@ -48,6 +48,7 @@ dependencies: timezone: ^0.8.0 permission_handler: ^11.3.1 url_launcher: ^6.2.5 + google_sign_in: ^5.2.1 dev_dependencies: flutter_test: