I'm trying to write data to the realtime database by first logging in users always using firebase (google_auth).
But there is something wrong with my rules ... if I set write and read "true" they obviously go, the same if I just use "auth! = Null" but when I use these rules:
{
"rules": {
"users": {
"$uid": {
".read": "auth! = null && auth.uid == $ uid",
".write": "auth! = null && auth.uid == $ uid"
}
}
}
}
No longer goes. So I assume the problem is that auth.uid is not the same as uid. I am attaching the code used for authentication and data submission.
Login / registration:
Future <UserCredential> signInWithGoogle () async {
final GoogleSignInAccount? userGoogle = await GoogleSignIn (). signIn ();
final GoogleSignInAuthentication? Google user data =
await userGoogle? .authentication;
final credentialsGoogle = GoogleAuthProvider.credential (
accessToken: Google User data? .accessToken,
idToken: Google User data? .idToken,
);
return await FirebaseAuth.instance.signInWithCredential (Google credentials);
}
Data sending:
DatabaseReference ref = FirebaseDatabase.instance.ref ();
await ref.set ({
"users": {
"$uid": {
"name": "John",
}
}
});
uid is fetched like this:
checkLogin () {
FirebaseAuth.instance.authStateChanges (). Listen ((User? User) {
if (user! = null) {
username = user.displayName;
uid = user.uid;
}
});
}
i think it's because of wrong spacing.. edited the rules. Try this please
{
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
}
Related
I try to make some unit tests on a login funtion in flutter and I have an error that I can't fix.
This is the test:
test('Register (success)', () async {
var auth = AuthService();
var result = await auth.login("test", "123456");
var json = jsonDecode(result.toString());
expect(json['success'], true);
});
This is the function called by the test:
login(name, password) async {
if (name.toString().isEmpty || password.toString().isEmpty) {
return "Error: empty field";
}
return await dio.post('https://itsmilife.herokuapp.com/authenticate',
data: {"name": name, "password": password},
options: Options(contentType: Headers.formUrlEncodedContentType))
}
This is the function that sent the informations:
authenticate: function(req, res) {
User.findOne({
name: req.body.name
}, function (err, user) {
if (err) throw err
if (!user) {
res.status(403).send({success: false, msg: 'Authentication Failed, User not found'})
} else {
user.comparePassword(req.body.password, function (err, isMatch) {
if (isMatch && !err) {
var token = jwt.encode(user, config.secret)
res.json({success: true, token: token, user: user})
}
else {
return res.status(403).send({success: false, msg: 'Authentication failed wrong password'})
}
})
}
})
},
I have the error when I launch the test:
NoSuchMethodError: The method '[]' was called on null.
Receiver: null
Tried calling: []("success")
dart:core Object.noSuchMethod
test\widget_test.dart 24:16 main.<fn>
I don't understand how to fix the probleme.
Try something like this:
Future<bool> login(name, password) async {
if (name.toString().isEmpty || password.toString().isEmpty) {
return false;
}
var responseFromServer = await dio.post(
'https://itsmilife.herokuapp.com/authenticate',
data: {"name": name, "password": password},
options: Options(contentType: Headers.formUrlEncodedContentType));
if (responseFromServer == null || responseFromServer.statusCode != 200) {
return false;
}
return true;
}
Also, make your test like:
test('Register (success)', () async {
var auth = AuthService();
var result = await auth.login("test", "123456");
expect(result, true);
});
I wanted to know if it's possible that a newly authenticated user can insert only their information to the realtime database.
The flow would be something like:
User authenticates via my app where he has to input
Email
Username
...
The user is authenticated (via Firebase Authentication) and has a uid
User writes a new DB entry in the /users/{uid} field of his/her. However, they are not allowed to set the balances field below.
Email
Username
...
He/She should only be able to write and read his/her own /users/{uid} object.
I've tried these rules so far, but none of them lets me create a new /users/{uid}
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
"balances": {
".write": false
},
"userName": {
".write": "$uid === auth.uid",
},
"email": {
".write": "$uid === auth.uid",
},
"phoneNumber": {
".write": "$uid === auth.uid",
}
}
}
}
}
The code I want to insert:
// ...
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
if let error = error {
self.error = error.localizedDescription
return
}
if let authResult = authResult {
// Auth successful
User.firebaseUser = authResult.user
print("Firebace UserId: \(authResult.user.uid)")
let ref: DatabaseReference! = Database.database().reference()
ref.child("users").child(authResult.user.uid).setValue([
"userName": self.userName,
"email": self.email
])
// ...
}
}
My Swift error message:
2022-05-26 16:55:55.043864+0200 Project[15240:1265346] 9.0.0 - [FirebaseDatabase][I-RDB038012] setValue: or removeValue: at /users/EZ2bNl3rMANtLtn1G9Wfqi0Ivjl1 failed: permission_denied
Thank you in advance!
Future login() async
{
insert (
<String, dynamic> {
"username": useremail.text,
"password": password.text
}
);
x = await result.data.toString();
if(x == null) {
_showInSnackBar("somthing went wrong");
}
if(x != null)
{
_showInSnackBar("success");
}
}
I have a weird situation on my project. I have 2 entities: children and users. Users create children, so on children, I have a reference to their owners and on users I have a list of the children they have created.
When I add a new child to firebase, the user owner of that child has his list of children updated to add that new child.
The thing is: on the staging environment everything works as it should be. But on the production environment, the child is added to the children, but not to the list of children on users.
Both databases have the same rules.
I've got to this project when it was already partially developed, so I can't even find where specifically the user should be updated. It seems to me that when you update a child, the users entity is automagically updated (using breakpoints I could verify it actually happens on the same step). I'm kind of new to Firebase so I am really lost here.
Can anyone try to help me?
Here are the database rules:
{"rules": {
"children": {
"$uid": {
".validate": "newData.hasChildren(['first_name'])",
"date_of_birth": {
".validate": "newData.isString() && newData.val().matches(/^(19|20)\\d\\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/)"
},
"first_name": {
".validate": "newData.isString() && newData.val().length > 0"
},
"users": {
"$key2": {
".validate": "root.child('users').child($key2).val() != null && newData.isString() && newData.val() == 'parent'"
},
".validate": "newData.hasChildren()"
},
"$other": {
".validate": "false"
},
".read": "data.child('users').child(auth.uid).val() != null",
".write": "data.child('users').child(auth.uid).val() == 'parent' || newData.child('users').child(auth.uid).val() == 'parent'"
}
},
"users": {
".indexOn": [
"email"
],
"$uid": {
".validate": "newData.hasChildren()",
"email": {
".validate": "newData.isString() && newData.val() == auth.token.email"
},
"first_name": {
".validate": "newData.isString()"
},
"is_subscribed": {
".validate": "newData.isBoolean()"
},
"children": {
"$key5": {
".validate": "root.child('children').child($key5).val() != null && newData.isString() && newData.val() == 'parent'"
},
".validate": "newData.hasChildren()"
},
"$other": {
".validate": "false"
},
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
}
and the code that adds children to it.
var entityDatabase: DatabaseReference = Database.database().reference().child(“children”).child(did)
entityDatabase.keepSynced(true)
var firstName: String?
var users: [String: String] = [:]
var params: [String: Any] {
var strings: [String: String] = [:]
strings["first_name"] = firstName
let keysToRemove = strings.keys.filter { strings[$0] == "" }
for key in keysToRemove {
strings.removeValue(forKey: key)
}
var dict: [String: Any] = strings
dict["users"] = users
return dict
}
guard let user = Firebase.Auth.auth().currentUser else {
return
}
guard firstName?.isEmpty == false else {
return
}
users[user.uid] = "parent"
entityDatabase.updateChildValues(params) { [weak self] (error, _) in
self?.observe()
guard error == nil else {
return
}
switch self?.updatedImage {
case let image?:
self?.save(image: image, completion: completion)
case nil:
}
}
I am trying to use passportjs with facebook and on sails js.in the middleware, this is my implementation
var verifyHandler = function (token, tokenSecret, profile, done) {
process.nextTick(function () {
//check if the user exist or not
var uid=profile.id;
User.findOne({uid:profile.id}).done(function(err,user){
if(user)
{
console.log('found');
//done(null,user);
}
else
{
console.log('user does not exists');
}
});
};
The weird thing is that it is not able to search through the model.Where Am I doing it wrongly?
I have finally figured it out and I hope it will assist anyone having the same issue with MySQL.
1. Within your user model, the uid datatype should be a STRING not an INTEGER.Please make sure you have effect the same changes on the database table structure to VARCHAR.
2.Change middleware.js verifyHandler to this(omitting parseInt)
var passport = require('passport')
, GitHubStrategy = require('passport-github').Strategy
, FacebookStrategy = require('passport-facebook').Strategy
, GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
var verifyHandler = function (token, tokenSecret, profile, done) {
process.nextTick(function () {
User.findOne({uid: profile.id}).done(function (err, user) {
if (user) {
return done(null, user);
} else {
var data = {
provider: profile.provider,
uid: profile.id,
name: profile.displayName
};
if(profile.emails && profile.emails[0] && profile.emails[0].value) {
data.email = profile.emails[0].value;
}
if(profile.name && profile.name.givenName) {
data.firstname = profile.name.givenName;
}
if(profile.name && profile.name.familyName) {
data.lastname = profile.name.familyName;
}
User.create(data).done(function (err, user) {
return done(err, user);
});
}
});
});
};
passport.serializeUser(function (user, done) {
done(null, user.uid);
});
passport.deserializeUser(function (uid, done) {
User.findOne({uid:uid}).done(function (err, user) {
done(err, user)
});
});
module.exports = {
// Init custom express middleware
express: {
customMiddleware: function (app) {
passport.use(new FacebookStrategy({
clientID: "****",
clientSecret: "********",
callbackURL: "http://localhost:1337/auth/facebook/callback"
},
verifyHandler
));
app.use(passport.initialize());
app.use(passport.session());
}
}
};
Hope this helps someone out.Cheers!