I am using below dependencies in my flutter web app with firebaseAuth and firestore:
firebase_core: ^1.7.0
firebase_auth: ^3.1.3
cloud_firestore: ^2.5.3
Below are the script versions on web/index.html:
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-firestore.js"></script>
I want to navigate the screen to screen after user login with the credentials. I am tiring below method but its not working. Unable to use then FirebaseAuth.instance.currentUser!.then((user) { and .getDocuments() .where('uid', isEqualTo: user.uid).getDocuments() How to solve this.
Actually, I want to open the admin screen after get the user role saved in firestore user data. So in this case, User id of current user which is logged in should be match to uid field in a document stored in firestore. And then it should be match the role with the role field. For reference please find the images.
I am trying below code:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:webfire/admin_screen.dart';
import 'package:webfire/home_screen.dart';
import 'package:flutter/widgets.dart';
class UserManagement {
signOut() {
FirebaseAuth.instance.signOut();
}
//FirebaseFirestore firestore = FirebaseFirestore.instance;
authorizeAdmin(BuildContext context) {
FirebaseAuth.instance.currentUser!.then((user) {
FirebaseFirestore.instance
.collection('users')
.where('uid', isEqualTo: user.uid)
.getDocuments()
.then((docs) {
if (docs.documents[0].exists) {
if (docs.documents[0].data['role'] == 'admin') {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => const AdminScreen()));
} else if (docs.documents[0].data['role'] == 'user') {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => const HomeScreen()));
}
}
});
});
}
}
Below is Cloud Firestore data Image:
I am using email and password authentication. User id and the uid in firestore are same. you can find below image.
FirebaseAuth.instance.currentUser is no longer Future<User> it's direct User? object
After where condition use .get() function to get Snapshot
Related
I followed some tutos and I add user on firestore successly but I can't print this user on the profile page when the current user is logging because I'm having a error too in my front end.
This is my entire frontend with this error:
The method '[]' can't be unconditionally invoked because the receiver can be 'null'. Try making the call conditional (using '?.') or adding a null check to the target ('!')."
I tried ? and ! but with not success.
hope you help me !
FutureBuilder(
future: FirebaseFirestore.instance
.collection('users')
.doc('uid')
.get(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Text(snapshot.data['displayName'],
);
} else {
return Text("Loading...");
and my backend if needed
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
Future userSetup(String displayName) async {
CollectionReference users = FirebaseFirestore.instance.collection('Users');
FirebaseAuth auth = FirebaseAuth.instance;
String uid = auth.currentUser!.uid.toString();
await users.doc(uid).set({'displayName': displayName, 'uid': uid });
final result = await users.doc(uid).get();
final data = result.data() as Map<String, dynamic>;
return data['displayName'];
}
I have implemented Google sign in to my mobile application, however, it asked me once for my e-mail and password. When I run the app again it skips the login screen and automatically navigates to the home screen.
I tried:
Deleting the app on the menu.
Clearing the cache on settings. (I guess I couldn't do it properly not for sure)
Even deleted the profile which automatically logs in. (still holds this profile as user idk how...)
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import './components/google_sign_in.dart';
import 'components/body.dart';
import 'package:firebase_auth/firebase_auth.dart';
import '../home/home_screen.dart';
class SignInScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: ChangeNotifierProvider(
create: (context) => GoogleSignInProvider(),
child: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
final provider = Provider.of<GoogleSignInProvider>(context);
if (provider.isSigningIn) {
return buildLodading();
} else if (snapshot.hasData) {
print("data: ${snapshot.data}");
return HomeScreen();
} else {
return Body();
}
})));
}
Widget buildLodading() => Center(child: CircularProgressIndicator());
}
Body() = The login screen.
The program always returns true on snapshot.hasData so that it doesn't go in else.
What you're describing is the expected behavior. When you restart the app, Firebase implicitly tries to restore the user credentials, so that the user doesn't have to sign in each time they start the app.
If you want the user to explicitly require the user to provide their sign-in credentials each time they start the app, sign any existing user out when the app starts.
For example:
void main() {
WidgetsFlutterBinding.ensureInitialized();
final Future<FirebaseApp> _initialization = Firebase.initializeApp();
FirebaseAuth.instance.signOut();
runApp(App());
}
I am using StreamBuilder inside the home property of MaterialApp() widget in the main.dart file in order to navigate between the WelcomeScreen (containing login and signup buttons) and the DashboardScreen with the help of the authStateChanges() provided by firebase_auth package. But whenever I am logging in or signing up it stays on that screen only, until I manually Hot Reload the app. I have to hot reload the app in order to get from loginscreen to dashboard. The firebase auth is working correctly. I am able to see the user signed up in the firebase console. But the screen is not changing automatically. Also, there is no Navigator.push() method after the login or signup code.
main.dart:
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:banquet_owner_app/screens/welcome_screen.dart';
import 'package:banquet_owner_app/screens/dashboard.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, userSnapshot) {
if (userSnapshot.hasData) {
return Dashboard();
}
return WelcomeScreen();
},
),
);
}
}
you need to get the state of the stream ,then check if it has data
here is how to go about it
home: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, userSnapshot) {
if (userSnapshot.connectionState == ConnectionState.waiting) {
//loading screen
}
if (userSnapshot.connectionState == ConnectionState.done) {
//state is loaded check if snapshot has data
if (userSnapshot.hasData) {
return Dashboard();
}else{
return WelcomeScreen();
}
},
Here is my code, slightly adapted from the example in flutter documentation:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
#override
Widget build(BuildContext context) {
CollectionReference items = FirebaseFirestore.instance.collection('item');
return FutureBuilder<DocumentSnapshot>(
future: items.doc(itemId).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data = snapshot.data.data();
return data['out_of_stock_location_ids'];// ${data['last_name']}");
}
return Text("loading");
},
);
}
The code "FirebaseFirestore" is giving an error as it's not recognized as part of library that I'm imported. The import 'package:firebase_core/firebase_core.dart'; is grayed out, possibly inappropriately so. I can't find where on the internet I can find why this is occurring or what to do about it.
If you are using cloud_firestore: 0.14.0 version and above you need to use FirebaseFirestore & doc() then if cloud_firestore: 0.13.7+1 and below you need to use Firestore & document().
The documentation you mentioned is updated and I believe you are using now the lower version of cloud_firestore. If you want to use the higher or latest version of cloud_firestore you must change the version of your firestore in pubspec.yaml then visit the changelog of firestore in pub.dev to see the every changes and update of firestore.
I'm not sure but you probably didn't initialize firebase in your main method you had to use firebase core for initialization
import core to main.dart
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
It appears that the documentation is outdated. I had to change FirebaseFirestore to Firestore and doc to document. I'm not sure how people are supposed to know to do that.
In my AuthProvider class where I handle my sign in, sign, out authentications, I created 2 functions that returns a Future String like so
Future<String> currentUser() async {
FirebaseUser user = await _auth.currentUser();
return user.uid;
}
Future<String> getCurrentUserEmail() async {
FirebaseUser user = await _auth.currentUser();
final String email = user.email.toString();
// print(email);
return email;
}
In my menu screen, I want to display my current signed in user email in a text field and I am calling it as below.
UserAccountsDrawerHeader(
accountName: Text('Brad Pitt'),
accountEmail: Text(
'${AuthProvider.of(context).auth.getCurrentUserEmail()}'),
I have tried using both the currenUser() and getCurrentUserEmail() to try to display the loggedIn user's email but I keep getting a "Instance of Future" displayed.
Is there something I'm overlooking here? I've tried every possible hack I can think of.
Thanks.
Since your getCurrentUserEmail returns a Future, you'll need to use a FutureBuilder to use it in your build method.
accountEmail: FutureBuilder<String>(
future: AuthProvider.of(context).auth.getCurrentUserEmail(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data)
}
else {
return Text("Loading user data...")
}
}
)
The best thing to do is to upgrade to firebase_auth:0.18.0, after upgrade you can get the currentUser synchronously!
dependencies:
flutter:
sdk: flutter
firebase_core : ^0.5.0
firebase_auth : ^0.18.0
initialize Firebase:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
Then in UsersAccountDrawerHeader:
UserAccountsDrawerHeader(
accountName: Text('Brad Pitt'),
accountEmail: Text('${auth.instance.currentUser.email}'),
Also check:
Undefined class 'FirebaseUser'
No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp() in Flutter and Firebase
Retrieving user email, null safety supported.
var currentUser = FirebaseAuth.instance.currentUser;
Text('admin email: ${FirebaseAuth.instance.currentUser!.email}'),
You need to add ~await~ in front of the function as it's a function that returns a ~Future~
await AuthProvider.of(context).auth.getCurrentUserEmail()
After initilizing your Firebase in your main
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
Now in the Text widget to display the current user's email use
Text('${FirebaseAuth.instance.currentUser!.email}',),