I am facing issue in storing uid in database - flutter

This is error
error getting token java.util.concurrent.ExecutionException:
com.google.firebase.internal.api.FirebaseNoSignedInUserException:
Please sign in before trying to get a token. W/NetworkRequest(10820):
no auth token for request W/NetworkRequest(10820): No App Check token
for request. E/flutter (10820):
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled
Exception: Null check operator used on a null value E/flutter (10820):
#0 _signupState.build. (package:ecommerce/Auth/signup.dart:161:28) E/flutter (10820):
E/flutter (10820):
I think error is in uid because when use id it signup successfully. If my code is wrong then please tell how I can store.
This is my code
final uid =auth.currentUser!.uid ;
auth.createUserWithEmailAndPassword(email: emailcontroller.text.toString(), password: passcontroller.text.toString()).then((signin){
ref.doc(uid).set({
"id":uid,
"name":namecontroller.text.toString(),
"email":emailcontroller.text.toString(),
"password":passcontroller.text.toString(),
"phone":phonecontroller.text.toString(),
"imageurl":url1.toString()
})

You are using uid before signUp in App. Try this code:
var uid;
await auth.createUserWithEmailAndPassword(email: emailcontroller.text.toString(), password: passcontroller.text.toString()).then((signin){
uid =auth.currentUser!.uid ;
ref.doc(uid).set({
"id":uid,
"name":namecontroller.text.toString(),
"email":emailcontroller.text.toString(),
"password":passcontroller.text.toString(),
"phone":phonecontroller.text.toString(),
"imageurl":url1.toString()
})

Related

Unhandled Exception: NoSuchMethodError: Class 'FirebaseAuthException' has no instance getter '_message'

Help me pls.
I have this error.
10Q
Unhandled Exception: NoSuchMethodError: Class 'FirebaseAuthException' has no instance getter '_message'.
E/flutter ( 5700): Receiver: Instance of 'FirebaseAuthException'
E/flutter ( 5700): Tried calling: _message
await _auth
.signInWithEmailAndPassword(
email: _emailTextEditingController.text.trim(),
password: _passwordTextEditingController.text.trim(),
)
.then((authUser) {
setState(() {
firebaseUser = authUser.user;
});
}).catchError((error) {
showDialog(
context: context,
builder: (c) {
return ErrorAlertDialog(
message: error._message == '[firebase_auth/user-not-found] There is no user record corresponding to this identifier. The user may have been deleted.'
? 'Email or password incorrect' : 'Error',
);
});
});
error._message == '[firebase_auth/user-not-found] There is no user record corresponding to this identifier. The user may have been deleted.'
? 'Email or password incorrect' : 'Error',
You are being told that there is no getter named _message for FirebaseAuthException. If you go to the code for that class, or the documentation (here) and look at the methods you have available to you,
_message is not one.
There is one there (getErrorCode) that you should be able to compare with much easier.
I think that the _message was called on null, I am not sure about this.

Flutter Futures: How can I make this StompClient connection awaitable with Futures?

I am using StompClient to connect to my gameservers websocket endpoint. For the sake of using FutureBuilder of Flutter I'd like to have async/await features with this client.
Therefore I wrapped the StompClient in the following way:
class CombatClient {
late StompClient _client;
Future<bool> connect() async {
_client = StompClient(
config: StompConfig.SockJS(
url: '${ServerGlobals.backendHost}/connect',
onConnect: (frame) async {
_client.subscribe(destination: "/gameserver/foo", callback: (data) => {print("foo: ${data.body}")});
},
),
);
_client.activate();
return await Future.doWhile(() => _client.connected);
}
}
In my main logic I am using the whole like this:
final combatClient = CombatClient();
await combatClient.connect();
However this does not work because of the following error:
E/flutter (23147): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Null' is not a subtype of type 'FutureOr<bool>'
E/flutter (23147): #0 CombatClient.connect (package:app/combat/websocket/combat_client.dart:19:12)
E/flutter (23147): <asynchronous suspension>
E/flutter (23147): #1 _DebugCombatPageState.build.<anonymous closure> (package:app/debug/debug_combat_page.dart:61:27)
E/flutter (23147): <asynchronous suspension>
E/flutter (23147):
Regardless of the error I'd just love to know what the proper approach is. I always struggle when it comes to Futures etc. I can't find the right API usage to make my connection to the game server awaitable.
Quoted from #pskink
simply use Completer class instead of return await Future.doWhile(... - the docs say: "A way to produce Future objects and to complete them later with a value or error"

Null check operator error in Flutter application

I am developing a Flutter app that implements OpenID authentication. I am getting the following error in one of the flutter libraries I am using (library https://pub.dev/packages/openid_client). The error is as follows:
E/flutter (14084): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled ExceptionNull check operator used on a null value
E/flutter (14084): #0 new Flow._
package:solidauth/…/src/openid.dart:344
E/flutter (14084): #1 new Flow.authorizationCode
package:solidauth/…/src/openid.dart:361
E/flutter (14084): #2 new Authenticator
package:solidauth/openid/openid_client_io.dart:23
E/flutter (14084): #3 AppLogin.authenticate1
package:solidauth/main.dart:873
E/flutter (14084): <asynchronous suspension>
E/flutter (14084): #4 AppLogin.build.<anonymous closure>
package:solidauth/main.dart:574
E/flutter (14084): <asynchronous suspension>
The piece of code that I am getting the error is the following:
class Authenticator {
final Flow flow;
final Function(String url) urlLancher;
final int port;
Authenticator(Client? client,
{this.port = 3000,
this.urlLancher = _runBrowser,
Iterable<String> scopes = const [],
Uri? redirectUri})
: flow = redirectUri == null
? Flow.authorizationCodeWithPKCE(client)
: Flow.authorizationCode(client)
..scopes.addAll(scopes)
..redirectUri = redirectUri ?? Uri.parse('http://localhost:$port/');
... some other functions ...
}
The error is coming from the above class constructor when I call it like the following. But I don't see any obvious errors in there. Not sure what I am doing wrong here.
// create an authenticator
var authenticator = new Authenticator(client,
scopes: scopes,
port: 4000,
urlLancher: urlLauncher,
redirectUri: Uri.parse(redirUrl));
I think the issue comes from this line in the class Flow because the client is null, so the null check ! will throw that error.
Flow._(this.type, this.responseType, this.client, {String? state})
: state = state ?? _randomString(20) {
var scopes = client!.issuer!.metadata.scopesSupported; <-- This line
for (var s in const ['openid', 'profile', 'email']) {
if (scopes!.contains(s)) {
this.scopes.add(s);
break;
}
}

How to handle the authentication token and and GraphQL client with Riverpod?

We are using GraphQL to connect our backend with our mobil application. We are using Riverpod to, among other things, handle global state, dependency injection, etc.
We are using a provider to handle the GraphQL cliente without any authentication header at first while the user is not authentication (this will handle unauthenticated request like login or registering), after the user is authenticated, a token provider who provides the token is updated and it must update the client provider who is user for every repository on the application:
final StateProvider<String> tokenProvider =
StateProvider<String>((_) => '', name: "Token Provider");
final graphQLClientProvider = Provider<GraphQLClient>(
(ref) {
final String token = ref.watch(tokenProvider).state;
final Link _link = HttpLink(
'http://192.168.1.36:1337/graphql',
defaultHeaders: {
if (token != '') 'Authorization': 'Bearer $token',
});
return GraphQLClient(
cache: GraphQLCache(),
link: _link,
);
},
name: "GraphQL Client Provider",
);
There is too problems here:
After updating the token, the client is changed, and from this, the function who updates the token does not finish in a proper way:
[ +141 ms] E/flutter ( 8361): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Bad state: Tried to use AuthNotifier after `dispose` was called.
[ ] E/flutter ( 8361):
[ ] E/flutter ( 8361): Consider checking `mounted`.
[ ] E/flutter ( 8361):
[ ] E/flutter ( 8361): #0 StateNotifier._debugIsMounted.<anonymous closure> (package:state_notifier/state_notifier.dart:128:9)
[ ] E/flutter ( 8361): #1 StateNotifier._debugIsMounted (package:state_notifier/state_notifier.dart:135:6)
[ ] E/flutter ( 8361): #2 StateNotifier.state= (package:state_notifier/state_notifier.dart:155:12)
[ ] E/flutter ( 8361): #3 AuthNotifier.signIn (package:thesis_cancer/features/auth/application/auth.notifier.dart:84:7)
[ ] E/flutter ( 8361): <asynchronous suspension>
[ ] E/flutter ( 8361): #4 _LoginCardState._submit (package:flutter_login/src/widgets/auth_card.dart:503:15)
[ ] E/flutter ( 8361): <asynchronous suspension>
[ ] E/flutter ( 8361):
It means when the token is updated, the authentication notifier who receives the repository with depends on the provided client is updated/changes (following the chain):
final authRepositoryProvider = Provider<AuthRepository>(
(ref) => GraphQLAuthRepository(client: ref.read(graphQLClientProvider)),
name: 'Auth Repository Provider',
);
final authNotifierProvider = StateNotifierProvider<AuthNotifier, AuthState>(
(ref) => AuthNotifier(
authRepository: ref.watch(authRepositoryProvider),
dataStore: ref.watch(dataStoreRepositoryProvider),
profileRepository: ref.watch(profileRepositoryProvider),
tokenController: ref.watch(tokenProvider.notifier),
userController: ref.watch(userEntityProvider.notifier),
),
name: "Authentication Notifier Provider",
);
The notification function who breaks at the conditional(if):
Future<String?> signIn({
required String username,
required String password,
}) async {
try {
final Map<String, dynamic> rawUser = await authRepository.signIn(
identifier: username, password: password) as Map<String, dynamic>;
final User sessionUser = User.fromJson(rawUser);
if (sessionUser.confirmed != false) {
tokenController.state = sessionUser.token!; <-- Bug begins here
}
await dataStore.writeUserProfile(sessionUser);
userController.state = sessionUser;
state = const AuthState.loggedIn();
} on LogInFailureByBadRequest {
return "E-posta veya şifre geçersiz.";
} on LogInFailure catch (error) {
return error.toString();
}
}
While the client appears to be changed when the token is updated, the client itself does not reflect the change (it does not include the authentication header with the token) and thus breaks the GraphQL client:
Following the comments on the issue we opened, we added the ProviderReference to our notifier (following this question) but it does not work:
AuthNotifier(
this._ref, {
required this.authRepository,
required this.profileRepository,
required this.dataStore,
required this.tokenController,
required this.userController,
}) : super(const AuthState.loading());
final ProviderReference _ref;
final ProfileRepository profileRepository;
final AuthRepository authRepository;
final DataStoreRepository dataStore;
final StateController<User?> userController;
final StateController<String> tokenController;
At this point, we don't understand what's the problem here.
UPDATE
We removed this changes both in the StateNotifier and its provider.
Getting the client at repository by read does not avoid the error:
What's the proper way to handle the authorization token and the GraphQL client with Riverpod?
Thank you.
The problem is the authRepositoryProvider:
final authRepositoryProvider = Provider<AuthRepository>(
(ref) => GraphQLAuthRepository(client: ref.read(graphQLClientProvider)),
name: 'Auth Repository Provider',
);
In this fragment, the authRepositoryProvider is using a GraphQLClient without token. When the token is updated, the graphQLClientProvider state is well updated, but the authRepositoryProvider isn't because you are using ref.read avoiding the rebuild of the authRepositoryProvider state. This implies that the authRepositoryProvider knows a disposed (and unmounted) state of graphQLClientProvider and that's why the error message.
There are 2 solutions:
Using ref.watch:
final authRepositoryProvider = Provider<AuthRepository>(
(ref) => GraphQLAuthRepository(client: ref.watch(graphQLClientProvider)),
name: 'Auth Repository Provider',
);
Passing the ref.read as parameter:
final authRepositoryProvider = Provider<AuthRepository>(
(ref) => GraphQLAuthRepository(client: ref.read),
name: 'Auth Repository Provider',
);
class AuthRepository {
AuthRepository(this.read)
final Reader read;
GraphQLClient get client => read(graphQLClientProvider);
}
Be care about using read and watch, the first one does not react to the changes but could be used anywhere, while the second one reacts to a provider's state update but only can be used in another provider constructor or in a widget that provides access to a watch or ref.watch depending on the version of Riverpod.
In addition, there is another problem in your code:
final User sessionUser = User.fromJson(rawUser);
if (sessionUser.confirmed != false) {
// In this moment, the token is updated,
// then the QrahpQLClient is updated,
// then the AuthNotifier is recreated,
// i.e the current is disposed
// and now becomes the previous
tokenController.state = sessionUser.token!; <-- Bug begins here
}
await dataStore.writeUserProfile(sessionUser);
userController.state = sessionUser;
// In this moment you are updating the state of a disposed notifier
state = const AuthState.loggedIn();
To provide a solution it is necessary to define which elements will make rebuild the AuthNotifer.state instead of recreating the notifier.
You must consider access to another notifiers bases on the ref.read and manually create the subscriptions in the StateController constructor.
In the future, when riverpod 1.0 will be released, this issue will be easy with ref.listen but now you need to rewrite your code. You can take inspiration in the bloc-to-bloc communication gide: https://bloclibrary.dev/#/architecture?id=bloc-to-bloc-communication
i think the error is in your AuthNotifier:
if (sessionUser.confirmed != false) {
tokenController.state = sessionUser.token!; <-- you are updating a dependencie of your actual AuthNotifier object
}
await dataStore.writeUserProfile(sessionUser); <-- during the await a new object is created and the actual instance is disposed so this line will throw

Flutter Problem in FireAuth Email Verification

I tried to make email verification and the problem is that the app registered the user without sending the email
this is my Function code
Future<String> registerUsingEmailAndPassword(String email, String password) async {
UserCredential userCredential = await firebaseAuth.createUserWithEmailAndPassword(email: email, password: password);
User user = userCredential.user;
if(!user.emailVerified){
await user.sendEmailVerification();
print(user.email);
}
return user.uid;
}
and this is my log
W/System ( 3599): Ignoring header X-Firebase-Locale because its value was null.
W/System ( 3599): Ignoring header X-Firebase-Locale because its value was null.
D/FirebaseAuth( 3599): Notifying id token listeners about user ( Q8d7R7mE9dOv5lAbkZH2UCiwmKA2 ).
D/FirebaseAuth( 3599): Notifying auth state listeners about user ( Q8d7R7mE9dOv5lAbkZH2UCiwmKA2 ).
W/System ( 3599): Ignoring header X-Firebase-Locale because its value was null.
I/flutter ( 3599): wasee.2132254#gmail.com
EDIT
when I check my email I found the messages, so, wanna do something like waiting screen that waiting for the user verification and then resumes the registration process
any idea?
I think you could check if Firebase User user.isEmailVerified is true