"on HttpException catch (error)" desn't work in flutter - flutter

I made this code to handle error from the server Firebase with flutter :
This is the main function :
try {
if (_authMode == AuthMode.Login) {
print("log in");
await Provider.of<Auth>(context, listen: false)
.signIn(_authData['email'], _authData['password']);
} else {
await Provider.of<Auth>(context, listen: false)
.signUp(_authData['email'], _authData['password']);
}
} on HttpException catch (error) {
print("Check error");
if (error.toString().contains("EMAIL_EXISTS")) {
_ServerError =
"The email address is already in use by another account.";
}
if (error.toString().contains("TOO_MANY_ATTEMPTS_TRY_LATER")) {
_ServerError =
"We have blocked all requests from this device due to unusual activity.\n Try again later.";
} else {
_ServerError = "Something wrong. \n Try again later!";
}
} catch (error) {
print(error.toString() );
}
This is the called function :
Future<void> signIn(String? email, String? password) async {
const _url =
"https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=APICODE";
_authentication(_url, email, password);}
Future<void> _authentication(
String _url, String? email, String? password) async {
try {
final _response = await http.post(Uri.parse(_url),
body: json.encode({
'email': email,
'password': password,
'returnSecureToken': true
}));
final _responseData = json.decode(_response.body);
if (_responseData['error'] != null) {
throw HttpException(_responseData['error']['message']);
}
} catch (error) {
throw error;
}}
But the problem is when the called function throw the HttpException error, I don't get it in the main function because the Catch doesn't work because I don't get the message "check error" in the panel ?!
this is the panel :
Can you help me please ?

The problem is I forgot to add return to called function :
Future<void> signIn(String? email, String? password) async {
const _url =
"https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=APICODE";
return _authentication(_url, email, password);
}

Related

Flutter Firebase Error - Ignoring header X-Firebase-Locale because its value was null

My app was working fine few days ago, when i try to Login or signup i am getting this error now. I have tried all the solutions found in the internet. I am facing this issue only in android, IOS is working fine.
Below is my code.
Login and Register functions.
Future signIn(String email, String password) async {
if (_formKey.currentState!.validate()) {
try {
await _auth.signInWithEmailAndPassword(email: email, password: password).then((value) {
MySharedPreferences.instance
.setBooleanValue("loggedin", true);
Get.to(() => const MobileNumberScreen());
});
} on FirebaseAuthException catch (error) {
switch (error.code) {
//error information
}
// print("Login Error:: " + error.toString());
}
setState(() {
_autoValidate = AutovalidateMode.always;
});
}
}
Future signUp(String email, String password) async {
if (_formkey.currentState!.validate()) {
try {
await _auth.createUserWithEmailAndPassword(email: email, password: password).then((value) => addUser());
} on FirebaseAuthException catch (error) {
print('Error:$error');
switch (error.code) {
//error information
}
setState(() {
_autoValidate = AutovalidateMode.always;
});
print("Registration Error" + error.code);
}
}
}
Can someone please help me on this.

error : display a red line under this statement _userFromFirebaseUser(userCredential.user);

hi every one I'm trying making my app with flutter . it is contains a sign up page so I write the code and I'm retrieving an information from the firebase after I upload it .
the below code is the sign up code
UserModel? _userFromFirebaseUser(User userCredential) {
return userCredential != null
? UserModel(
id: userCredential.uid,
bannerImageUrl: '',
name: '',
email: '',
profileImageUrl: '')
: null;
}
Stream<UserModel?> get userCredential {
return auth
.authStateChanges()
.map((userCredential) => _userFromFirebaseUser(userCredential!));
}
Future SignUp(email, password) async {
var formdata = formstate.currentState;
if (formdata!.validate()) {
print("valid");
formdata.save();
try {
UserCredential userCredential =
(await auth.createUserWithEmailAndPassword(
email: myemail!, password: mypassword!));
FirebaseFirestore.instance
.collection('Users')
.doc(userCredential.user!.uid)
.set({'name': email, 'email': email});
_userFromFirebaseUser(userCredential.user);
return userCredential;
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
Navigator.of(context).pop();
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
Navigator.of(context).pop();
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
} else {}
}
and the red line appears on this line _userFromFirebaseUser(userCredential.user); as it is appears in the picture . please help me
userCredential.user is User? not User
change the method parameter
UserModel? _userFromFirebaseUser(User? userCredential) {
return ....
}

Strange error using Flutter app + Deno + MongoDB backend

I want to write a simple registration function and this is my code:
auth_screen.dart:
Future<void> _submit() async {
if (!_formKey.currentState!.validate()) {
// Invalid!
return;
}
_formKey.currentState!.save();
setState(() {
_isLoading = true;
});
try {
if (_authMode == AuthMode.Login) {
// Log user in
await Provider.of<Auth>(context, listen: false).login(
_authData['email'] as String,
_authData['password'] as String,
);
} else {
// Sign user up
await Provider.of<Auth>(context, listen: false).signup(
_authData['email'] as String,
_authData['password'] as String,
);
}
} on HttpException catch (error) {
var errorMessage = 'Authentication failed';
print("this is the auth data");
print(_authData);
if (error.toString().contains('EMAIL_EXISTS')) {
errorMessage = 'This email address is already in use.';
} else if (error.toString().contains('INVALID_EMAIL')) {
errorMessage = 'This is not a valid email address';
} else if (error.toString().contains('WEAK_PASSWORD')) {
errorMessage = 'This password is too weak.';
} else if (error.toString().contains('EMAIL_NOT_FOUND')) {
errorMessage = 'Could not find a user with that email.';
} else if (error.toString().contains('INVALID_PASSWORD')) {
errorMessage = 'Invalid password.';
}
_showErrorDialog(errorMessage);
} catch (error) {
var errorMessage = 'Could not authenticate you. Please try again later.' +
error.toString();
_showErrorDialog(errorMessage);
}
setState(() {
_isLoading = false;
});
}
auth.dart:
Future<void> signup(String email, String password) async {
return _authenticate(email, password, 'register');
}
Future<void> _authenticate(
String email, String password, String urlSegment) async {
final url = Uri.parse('http://10.0.2.2:8000/api/$urlSegment');
// final url = Uri.http('http://localhost:8000/api/', 'urlSegment');
try {
final response = await http.post(
url,
body: json.encode(
{
'email': email,
'password': password,
//'returnSecureToken': true,
},
),
);
final responseData = json.decode(response.body);
if (responseData['error'] != null) {
throw HttpException(responseData['error']['message']);
}
_token = responseData['idToken'];
_userId = responseData['localId'];
_expiryDate = DateTime.now().add(
Duration(
seconds: int.parse(
responseData['expiresIn'],
),
),
);
_autoLogout();
notifyListeners();
final prefs = await SharedPreferences.getInstance();
final userData = json.encode(
{
'token': _token,
'userId': _userId,
'expiryDate': _expiryDate!.toIso8601String(),
},
);
prefs.setString('userData', userData);
} catch (error) {
throw error;
}
}
This is the backend(Deno) part of the project:
auth_controller.ts:
async register(ctx: RouterContext) {
const { email, password } = await ctx.request.body().value;
let user = await User.findOne({ email });
if (user) {
ctx.response.status = 422;
ctx.response.body = { message: "Email is already exist" };
return;
}
const hashedPassword = hashSync(password);
user = new User({ email, password: hashedPassword });
await user.save();
ctx.response.status = 201;
ctx.response.body = {
id: user.id,
name: user.name,
email: user.email
};
}
And this is the user.ts class:
export default class User extends BaseModel {
public id: string = "";
public name: string = "";
public email: string = "";
public password: string = "";
constructor({ id = "", name = "", email = "", password = "" }) {
super();
this.id = id;
this.name = name;
this.email = email;
this.password = password;
}
static async findOne(params: object): Promise<User | null> {
const user = await userCollection.findOne(params);
if (!user) {
return null;
}
return new User(User.prepare(user));
}
async save() {
const _id = await userCollection.insertOne(this);
this.id = _id;
return this;
}
}
I get this error message when I want to test the application on Android emulator:
type 'Null' is not a subtype of type 'String'
When I try the backend server using Postman and send post request to http://0.0.0.0:8000/api/register address. I get correct response and it works, but I don't know why do I get Null response using the Flutter app?
I tried to print the variables in both front and backend side of the application and it seems they all are good and correct but I can not understand why do I get this error message?!
probably you got a null value in your map in this part since map return a null value when can't find a key, check if the Map value is not null
try {
if (_authMode == AuthMode.Login) {
// Log user in
await Provider.of<Auth>(context, listen: false).login(
_authData['email'] as String, // can return a null value
_authData['password'] as String, // can return a null value
);
} else {
// Sign user up
await Provider.of<Auth>(context, listen: false).signup(
_authData['email'] as String, // can return a null value
_authData['password'] as String, // can return a null value
);
}
}
Seems you're getting a null as a response value instead of a String.
EDIT:
Future<void> signup(String email, String password) async {
return _authenticate(email, password, 'register');
}
Check email and password are not null. And getting the correct values.
Actually the problem was from these two lines of code:
_token = responseData['idToken'];
_userId = responseData['localId'];
Because it wasn't passing these data in response from the backend side.

Flutter | Getting Firebase Email Link Login Data

I have difficulty implementing the Email Link login with Firebase.
I send the email link using:
_firebaseAuth.sendSignInLinkToEmail(
email: email,
actionCodeSettings: ActionCodeSettings(
url: 'https://subdomain.example.com/user-auth', //<subdomain.example.com> = my real domain
handleCodeInApp: true,
androidInstallApp: true,
androidPackageName: 'com.example.app',
),
);
Email is sent and when clicking I open the link using the DynamicLink package:
void _handleDynamicLinks() {
FirebaseDynamicLinks.instance.onLink(onSuccess: _onSuccess);
}
Future<dynamic> _onSuccess(PendingDynamicLinkData data) async {
print('---onLink---');
// How to pass signIn link to `isSignInWithEmailLink` and `signInWithEmailLink` ???
// data.link returns `https://subdomain.example.com/user-auth` which is not the complete link
}
Every method I call on PendingDynamicLinkData data doesn't return the full dynamic link and isSignInWithEmailLink returns false!
Try this in your _handleDynamicLink function.
try {
FirebaseDynamicLinks.instance.onLink.listen((dynamicLink) {
final Uri? deepLink = dynamicLink.link;
if (deepLink != null) {
emailLinkService.handleLink(deepLink, _emailController.text);
FirebaseDynamicLinks.instance.onLink.listen((dynamicLink) {
final Uri? deepLink = dynamicLink.link;
emailLinkService.handleLink(deepLink!, _emailController.text);
}, onError: (e) async {
print(e.message);
});
}
}, onError: (e) async {
print(e.message);
});
final PendingDynamicLinkData? data =
await FirebaseDynamicLinks.instance.getInitialLink();
final Uri? deepLink = data?.link;
print('deepLink :: $deepLink');
} catch (e) {
// you can print this error as well
}
And check if your url is the same as here:
And also add the Dynamic link as your custom Authorised domain like this:
Here is the handleLink method:
class EmailLinkService {
final FirebaseAuth _auth = FirebaseAuth.instance;
Future<void> signInWithEmailAndLink(
{required String userEmail}) async {
var _userEmail = userEmail;
var acs = ActionCodeSettings(
url: Constants.firebaseProjectURL,
handleCodeInApp: true,
iOSBundleId: 'com.example....',
androidPackageName: 'com.example....',
try {
return await _auth
.sendSignInLinkToEmail(email: _userEmail, actionCodeSettings: acs);
} on FirebaseAuthException catch (e) {
}
void handleLink(Uri link, userEmail) async {
if (link != null) {
final UserCredential user =
await FirebaseAuth.instance.signInWithEmailLink(
email: userEmail,
emailLink: link.toString(),
);
} else {
print(" link is null");
}
}
}

How to catch exception in flutter?

This is my exception class. Exception class has been implemented by the abstract exception class of flutter. Am I missing something?
class FetchDataException implements Exception {
final _message;
FetchDataException([this._message]);
String toString() {
if (_message == null) return "Exception";
return "Exception: $_message";
}
}
void loginUser(String email, String password) {
_data
.userLogin(email, password)
.then((user) => _view.onLoginComplete(user))
.catchError((onError) => {
print('error caught');
_view.onLoginError();
});
}
Future < User > userLogin(email, password) async {
Map body = {
'username': email,
'password': password
};
http.Response response = await http.post(apiUrl, body: body);
final responseBody = json.decode(response.body);
final statusCode = response.statusCode;
if (statusCode != HTTP_200_OK || responseBody == null) {
throw new FetchDataException(
"An error occured : [Status Code : $statusCode]");
}
return new User.fromMap(responseBody);
}
CatchError doesn't catch the error when the status is not 200. In short error caught is not printed.
Try
void loginUser(String email, String password) async {
try {
var user = await _data
.userLogin(email, password);
_view.onLoginComplete(user);
});
} on FetchDataException catch(e) {
print('error caught: $e');
_view.onLoginError();
}
}
catchError is sometimes a bit tricky to get right.
With async/await you can use try/catch like with sync code and it is usually much easier to get right.
Let's say this is your function which throws an exception:
Future<void> foo() async {
throw Exception('FooException');
}
You can either use try-catch block or catchError on the Future since both do the same thing.
Using try-catch
try {
await foo();
} on Exception catch (e) {
print(e); // Only catches an exception of type `Exception`.
} catch (e) {
print(e); // Catches all types of `Exception` and `Error`.
}
Use catchError
await foo().catchError(print);
I was trying to find this answer when got to this page, hope it helps: https://stackoverflow.com/a/57736915/12647239
Basicly i was just trying to catch an error message from a method, but i was calling
throw Exception("message")
And in "catchError" i was getting "Exception: message" instead of "message".
catchError(
(error) => print(error)
);
fixed with the return in the above reference
Future < User > userLogin(email, password) async { try {
Map body = {
'username': email,
'password': password
};
http.Response response = await http.post(apiUrl, body: body);
final responseBody = json.decode(response.body);
final statusCode = response.statusCode;
if (statusCode != HTTP_200_OK || responseBody == null) {
throw new FetchDataException(
"An error occured : [Status Code : $statusCode]");
}
return new User.fromMap(responseBody); }
catch (e){
print(e.toString());
}