I'm trying to save an user on the Parse User table using
user.save(null,{
success: function(savedUser){
alert("We saved parseID");
},
error: function(error){
alert('Error'+JSON.stringify(error));
}
})
Unfortunately the error is thrown which contains the object I'm trying to save:
{"username":"ffsdfsd","password":"gdfgfdd","createAt":2016-09-21T13:13:18.965Z", "updatedAt":"2016-09-21T13:13:18.965Z","ACL":{"*":{"read":true},"2FUmrere":{"read":true,"write":true}},"sessionToken":"fdgfdgdgdgdf","objectId":"3ffd3f"}
Any idea? Is it something related to the ACL setting (only read permission)?
if the user that you are trying to save is not the logged in user then this is an ACL issue. When a new user is being created in the database the default ACL is public read but the write permissions are granted only to the user.
If you still want to save new data on this user without changing the default ACL you need to create a cloud code function and in the cloud code function you need to write the following code:
user.save(null,{
sessionToken: request.user.get("sessionToken")
}).then(function(user){
// user saved
},function(error){
// error handling
});
please notice that in my code i sent the logged in user session token (this is required in parse-server) and also i use Promises which is the best practice.
Related
My question probably not limited to firebase database only, but my problem happened while i working on the Angular Project that using Firebase Database so i will tag Firebase & Angular as well.
According to the Firebase Real Time Database documentation, most of the ThenableReference is returning a Promise.
When i write a basic function like pushing new object to DB or updating an existing object in DB, it will return me a Promise, so i can use then to perform next action after done the action with DB.
When there is an error (Permission Denied for example), i can make it display on the screen like this:
But my problem is, I can't figure out how to write the error into DB to log it down.
Below is my code:
this.clientService.createClient(this.client).then(data=>{ //when successfully Push object to DB
this.loggerService.log('success','createClient', this.client, {id:data['key'],msg:'Successfully Create the Client'}, 'add-client') //Log the result into DB
this.router.navigate(['search-results',data.key,'client-details']) //route user to another page
this.toastrService.success('','Successfully Create the Client') //display a successful Pop Up message
},error=>{
console.log(error) //this is working
let msg = error.toString()
this.loggerService.log('error','createClient', this.client, msg, 'add-client') //this is not working
this.toastrService.error(error,'Failed to create the Client') //this is working like the attached photo
});
Below is my loggerService.log code:
log(status,action,req,res:Object,site){
let object = {
dtcreate: Date.now(),
uid:this.currentUser.uid,
userEmail:this.currentUser.email,
action:action,
req:req,
res:res,
site:site,
status:status
}
return this.logRef.push(object)
}
Edited:
Below is the error for the console.log(error), this is what i wish to log into my DB (Error: PERMISSION_DENIED: Permission denied).
Error: PERMISSION_DENIED: Permission denied
at vendor.js:88796
at exceptionGuard (vendor.js:76410)
at Repo.push../node_modules/#firebase/database/dist/index.cjs.js.Repo.callOnCompleteCallback (vendor.js:88787)
at vendor.js:88564
at vendor.js:87739
at PersistentConnection.push../node_modules/#firebase/database/dist/index.cjs.js.PersistentConnection.onDataMessage_ (vendor.js:87772)
at Connection.push../node_modules/#firebase/database/dist/index.cjs.js.Connection.onDataMessage_ (vendor.js:87057)
at Connection.push../node_modules/#firebase/database/dist/index.cjs.js.Connection.onPrimaryMessageReceived_ (vendor.js:87051)
at WebSocketConnection.onMessage (vendor.js:86952)
at WebSocketConnection.push../node_modules/#firebase/database/dist/index.cjs.js.WebSocketConnection.appendFrame_ (vendor.js:86557)
Thanks in advance!
I am trying to create a function that, when a device is registered in the app, will attach this device uid to the uid of the signed-in user who registered the device (this is in another firestore collection that is automatically created when a user registers).
Here is my code:
exports.addDeviceToUser = functions.firestore.document('device-names/{device}').onUpdate((change, context) => {
const currentUser = admin.auth().currentUser;
const deviceName = context.params.device;
var usersRef = db.collection('users');
var queryRef = usersRef.where('uid', '==', currentUser.uid);
if (authVar.exists) {
return queryRef.update({sensors: deviceName}).then((writeResult => {
return console.log('Device attached');
}));
} else {return console.log('Device attachment failed, user not signed in');}
});
I am consistently getting this error: "TypeError: Cannot read property 'uid' of undefined." Obviously I am not able to access the auth information of the current user. Why?
The Admin SDK doesn't have a sense of current user. When you say admin.auth(), you're getting back an Auth object. As you can see from the API docs, there is no currentUser property on it. Only the Firebase client SDK has a sense of current user, because you use that to get the user logged in.
If you need the client app to tell Cloud Functions code work with the user's identity, you have to send it an ID token from the client, and verify it on the server. Then the server can know who the end user is, and perform actions on their behalf. Typically you do this with an HTTP type trigger. Callable functions transmit this data automatically between the client and server, but you can do it manually yourself using code that works like this sample.
Right now, Firestore triggers don't have immediate access to the end user that made a change in the database. However, if you use the Auth UID of the user as the key of the document, and protect that document with security rules, you can at least infer the UID of the user based on the changes they make to the document by pulling it out of the id of the document that changed.
Because, by design, Cloud Functions executes on the back end and do not hold any information on which user was authenticated when adding/modifying the data in the database.
When writing the data in the 'device-names/{device}' document (from your app), you could include an extra piece of data which is the uid of the current user.
I'm having trouble interacting with my Parse data in node.js. I'm able to login successfully, but Parse.User.current() returns null. After running the below code, I'd like to query data that has ACL read/write only for that user. Currently, that query returns empty, but if I change that data to public read/write, I can see the results of the query output in the terminal.
Here is my node.js code:
Prompt.get([{
name: 'username',
required: true}, {
name: 'password',
hidden: true}], function (err, result) {
if (err) {
console.log('Error: ' + err);
} else {
Parse.User.logIn(result.username, result.password, {
success: function(user) {
console.log('LOGGED IN');
console.log(user);
console.log(Parse.Session.current());
console.log(Parse.User.current());
... (query happens below this)
And my console output:
prompt: username: pablo
prompt: password:
LOGGED IN
ParseUser { _objCount: 0, className: '_User', id: 'EXyg99egkv' }
ParsePromise {
_resolved: false,
_rejected: true,
_resolvedCallbacks: [],
_rejectedCallbacks: [],
_error: 'There is no current user.' }
null
Thanks in advance.
Is this not a usecase for Parse.User.become()? From the parse docs:
If you’ve created your own authentication routines, or otherwise
logged in a user on the server side, you can now pass the session
token to the client and use the become method. This method will ensure
the session token is valid before setting the current user.
Parse.User.become("session-token-here").then(function (user) {
// The current user is now set to user.
}, function (error) {
// The token could not be validated.
});
I had similar problems and found this Parse blog that explains the issue:
Also in Cloud Code, the concept of a method that returns the current user makes sense, as it does in JavaScript on a web page, because there’s only one active request and only one user. However in a context like node.js, there can’t be a global current user, which requires explicit passing of the session token. Version 1.6 and higher of the Parse JavaScript SDK already requires this, so if you’re at that version, you’re safe in your library usage.
You can execute queries with user credentials in a node.js environment like this:
query.find({ sessionToken: request.user.getSessionToken() }).then(function(data) {
// do stuff with data
}, function(error) {
// do stuff with error
});
If you wish to validate that token before using it, here's an explanation of how you could go about doing that:
one way would be to query for an object known to be only readable by the user. You could have a class that stores such objects, and have each one of them use an ACL that restricts read permissions to the user itself. If running a find query over this class returns 0 objects with a given sessionToken, you know it's not valid. You can take it a step further and also compare the user object id to make sure it belongs to the right user.
Session tokens cannot be queried even with the master key.
I'm using cloud function to fetch user's sessionToken. The documentation says, this method only returns correct value when a user object is fetched with the master key. However, even if I use the master key, I still get the undefined result. What's wrong with my code?
Parse.Cloud.define("hello", function(request, response) {
Parse.Cloud.useMasterKey();
Parse.Promise.as().then(function(){
var query = new Parse.Query(Parse.User);
return query.first({useMasterKey:true});
}).then(function(user){
return user.fetch({useMasterKey:true});
}).then(function(user){
response.success(user.getSessionToken());
});
});
That won't work because the user is not logged in when you fetch him via cloud code. For getSessionToken to work you need to already have a logged in user. Because, otherwise how would CloudCode know which session of your user you want to get? (if he is logged in multiple devices) Also your code is returning the first user in the database, is that realy what you want?
Either way, you need to log the user in via cloud code and then return the session token. However I had some trouble doing that without the password (just by calling user.logIn(), it should work so give it a try) so the only solution I found was to change the password of the user and then log him in. Why do you need to fetch the user's session token? If you don't mind changing the user's password you can do something like:
var password; //create new random passowrd
query.first({useMasterKey: true}).then(function(user){
user.set("password", password);
return user.save();
}).then(function(user){
return Parse.User.logIn(user.get("username"), password);
}).then(function(user){
return user.getSessionToken();
});
I am using the google sign-in button everything looks to be working fine, But where i have issues is the callbacks from the response, How to get the sign-in details to feed into my DB.
i used the example code on https://developers.google.com/+/web/signin/add-button (STEP:5)
function signinCallback(authResult) {
if (authResult['status']['signed_in']) {
// Update the app to reflect a signed in user
// Hide the sign-in button now that the user is authorized, for example:
document.getElementById('signinButton').setAttribute('style', 'display: none');
} else {
// Update the app to reflect a signed out user
// Possible error values:
// "user_signed_out" - User is signed-out
// "access_denied" - User denied access to your app
// "immediate_failed" - Could not automatically log in the user
console.log('Sign-in state: ' + authResult['error']);
}
}
This is the error i am getting Uncaught ReferenceError: ext is not defined Sign-in state: user_signed_out
I keep getting the exact same problem. Its tempting to ditch the google sign in and just use your own.... or facebook. To fix this you can revoke access to your application and then sign in again. I did this by...
if (AccessToken){
var revokeUrl = 'https://accounts.google.com/o/oauth2/revoke?token=' + AccessToken;
// Perform an asynchronous GET request.
$http.jsonp(revokeUrl).
success(function(data, status, headers, config) {
console.log(data)
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log(data)
});
}
Notice that it seems there are two callbacks, first one comes back and says it worked! Then the other comes back saying:
error: "user_signed_out".
I have not found a way around this other than the way i just explained.
ANSWER
My problem was solved as soon as i realized the following...
I was not using a sub domain....
testsite.com
however when i changed it to www.testsite.com it worked perfectly and flawlessly.
Please make sure that you guys have the proper sub domain.