hosted parse Cloud code find(...) does not retrieve sessionToken - parse-platform

I am migrating Parse.com cloud code to hosted parse-server. Mongodb is already migrated.
The code is supposed to retrieve a user's sessionToken according to its google plus id. The find operation succeeds and a user is returned but the user does not have any sessionToken.
EDIT regarding mongodb:
Checking mongo db directly - the _User table record holds a _session_token value. In the _Session table I could not find that _session_token. Also I could not find any entry for that _User (I concatenated _User$ when searching).
The code is (more or less) so:
Parse.Cloud.define("getParseUserSessionToken", function(request, response) {
var googlePlusId = ...;
// here we're doing some code to get the google id
// assume it is set
var googleIdQuery = new Parse.Query(Parse.User);
googleIdQuery.equalTo(GOOGLE_PLUS_ID_FIELD_KEY, googlePlusId);
searchUserQuery.find({
useMasterKey: true
}).
then(function(users) {
if (users && users.length > 0) {
var user = users[0]; //user exist
var token = user.getSessionToken();
if (token) {
//user exist, return sessionToken
// ....
} else {
// CODE REACHES HERE AS THERE'S NO TOKEN
// return error: "no token"
}
}
}
As you can see I pass userMasterKey: true to find()
With a debugger I can see that I get a user with data, but without a token. I tried several things but nothing works.
Any idea what am I missing?

Related

Roles added to the user does give false in IsInRole

I am trying to use [Authorize(Roles = "Administrator")]
But I always get "Access denied".
To test if i added the roles correct i added the following code in my controller:
var test=User.IsInRole("Administrator");
var user = await userManager.GetUserAsync(User);
var roles =await userManager.GetRolesAsync(user);
rolesOfUser = roles.ToList();
Have I added the role wrong?
Why does IsInRole always return false? is suggesting that the user is not signin or completed all authentication process. If the is the case how do i do that?
Seeding data:
public async Task SeedAsync()
{
context.Database.EnsureCreated();
if (await roleManager.RoleExistsAsync("Administrator") == false)
{
await roleManager.CreateAsync(new IdentityRole("Administrator"));
}
var user = await userManager.FindByEmailAsync("Jakob.Madsen#********.com");
if (user == null)
{
user = new IdentityUser()
{
UserName = "Jakob.Madsen#*********.com",
PhoneNumber = "*********",
Email = "Jakob.Madsen#*********.com",
};
var result = await userManager.CreateAsync(user, "*********");
if (result == IdentityResult.Success)
{
userManager.AddToRoleAsync(user, "Administrator").Wait();
}
else
{
throw new InvalidOperationException("Could not create Administrator");
}
}
var resultRoles = await userManager.GetRolesAsync(user);
if (resultRoles.Contains("Administrator") == false)
{
userManager.AddToRoleAsync(user, "Administrator").Wait();
}
}
Update:
I follow this ASP .Net Core Identity Role Claims not adding to User as suggested.
And it now works.
The IsInRole method and [Authorize(Roles="Administrator")] attribute check whether an identity that this claims principal possesses contains a claim of type ClaimsIdentity.RoleClaimType(http://schemas.microsoft.com/ws/2008/06/identity/claims/role) where the value of the claim is equal to the value specified by the role parameter.
So to summarize, if you call IsInRole, by default the assumption is that your claims representing roles have the type mentioned above – otherwise the role check will not succeed. You can confirm that by listing the claims :
var claims = User.Claims.ToList();
You haven't provide how you seed the roles , but you can find a lot of code samples :
ASP.NET Core 2.0: Getting Started With Identity And Role Management
.NET Core 2.1 Use Role Management
Also don't forget to logout and login again to see the desired behavior .

Parse Cloud Right Query to retrieve Friendslist and not (like Instagram)

I have the class "Users" the default of Parse Dashboad. I have also the class "Friends", where I store the friendships between users like this:
There are two columns, "toUser" and "fromUser", which are showing who of the two users sent the friend request. These two columns are Pointers(Pointer<_User>) to the Users Class.
My concept is to retrieve two lists:
1. Friendlist for the logged in user
2. Userlist of users (who are not friends with the logged in user)
What would be the appropriate queries for that?
The first one logically should not scan all the class Users because it may slow down the perfomance of the app which is using Ionic 3 and Angular 4
Thank you
you don't need another class to do so all you need is a relation column in the default user class
to add new friend you just need the following code
var friendtoadd
//this is the friend object from parse user class you want to add you can get it by anyway you want
var currentUser = Parse.User.current();
var relation = currentUser.relation("friends");
relation.add(friendtoadd)
currentUser.save();
to retrieve array of friends of logged in user you can use the following code
var currentUser = Parse.User.current();
var friendRelation = currentUser.relation('friends');
var env = this
friendRelation.query().find({
success: function(users) {
for (var i = 0; i< users.length; i++) {
var object = users[i];
env.friends.push(object)
console.log(env.friends)
}
}
});
// you should define friends = []; in the class
if I understood your question right you want to find the friend requests you sent, or the ones you received. because I don't see where you made a relation between the user and his friends.
this is the code if you want to do this using cloud code:
First I validated the parameters of the friendRequest being saved :
Parse.Cloud.beforeSave("Friends", function(request, response){
var friendRequest = request.object;
if (!friendRequest.has("toUser") || !friendRequest.has("fromUser")) {
response.error("Invalid parameters");
return;
}
response.success();
});
then I created two cloud functions, one for retrieving the sentRequests:
Parse.Cloud.define("getSentRequests", function(request, response){
var query = new Parse.Query("Friends");
query.equalTo("fromUser", request.user);
if (!request.master) {
query.find({ sessionToken: request.user.getSessionToken() }).then(function(friends){
response.success(friends);
});
}else{
query.find({useMasterKey:true}).then(function(friends){
response.success(friends);
});
}
});
and you can call this either from a logged in user or using the masterKey if you want, and the other query is for the recievedRequests:
Parse.Cloud.define("getRecievedRequests", function(request, response){
var query = new Parse.Query("Friends");
query.equalTo("toUser", request.user);
if (!request.master) {
query.find({ sessionToken: request.user.getSessionToken() }).then(function(users){
response.success(users);
});
}else{
query.find({useMasterKey:true}).then(function(users){
response.success(users);
});
}
});

Why Parse server is creating new object instead of updating?

I am running parse server in NodeJS environment with express.
Generally, Parse automatically figures out which data has changed so only “dirty” fields will be sent to the Parse Cloud. So, I don’t need to worry about squashing data that I didn’t intend to update.
But why this following code is saving new data every time instead of updating the existing document data with name "Some Name".
// Parse code
Parse.initialize(keys.parseAppID);
Parse.serverURL = keys.parseServerURL;
var GameScore = Parse.Object.extend("GameScore");
var gameScore = new GameScore();
let data = {
playerName: "Some Name",
score: 2918,
cheatMode: true
};
gameScore.save(data, {
success: (gameScore) => {
// let q = new Parse.Query("GameScore");
// q.get(gameScore.id)
console.log("ID: " + gameScore.id)
},
error: function (gameScore, error) {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and message.
alert('Failed to create new object, with error code: ' + error.message);
}
});
// End of Parse code
The problem is that you're executing the query to find which object you want to update, but then you're not using the results when you go to save data.
query.first({ // This will result in just one object returned
success: (result) => {
// Check to make sure a result exists
if (result) {
result.save(data, {
// Rest of code
Note: You're treating playerName as a unique key. If multiple users can have the same playerName attribute, then there will be bugs. You can use id instead which is guaranteed to be unique. If you use id instead, you can utilize Parse.Query.get
Edit:
Since you want to update an existing object, you must specify its id.
var GameScore = Parse.Object.extend("GameScore");
var gameScore = new GameScore();
gameScore.id = "ID"; // This id should be the id of the object you want to update

How do you update objects in a Parse.com database using Xamarin?

I have an online Parse.com database and I can create objects and query them but not update. In the Xamarin section of the Parse.com documentation it only tells you how to update an object directly after you've created it which I don't want to do. I tried adapting what the documentation says for other platforms but it hasn't worked, I have also tried querying the database and entering the new field values directly after that but it treats them as separate functions. Does anyone have any help?
Parse.com documentation:
// Create the object.
var gameScore = new ParseObject("GameScore")
{
{ "score", 1337 },
{ "playerName", "Sean Plott" },
{ "cheatMode", false },
{ "skills", new List<string> { "pwnage", "flying" } },
};
await gameScore.SaveAsync();
// Now let's update it with some new data. In this case, only cheatMode
// and score will get sent to the cloud. playerName hasn't changed.
gameScore["cheatMode"] = true;
gameScore["score"] = 1338;
await gameScore.SaveAsync();
What I tried most recently:
ParseQuery<ParseObject> query = ParseObject.GetQuery("cust_tbl");
IEnumerable<ParseObject> customers = await query.FindAsync();
customers["user"] = admin;
record["score"] = 1338;
await record;
In your example, you are getting an list (IEnumerable) of objects instead of single object. Instead, try something like this:
ParseQuery<ParseObject> query = ParseObject.GetQuery("cust_tbl");
// you need to keep track of the ObjectID assigned when you first saved,
// otherwise you will have to query by some unique field like email or username
ParseObject customer = await query.GetAsync(objectId);
customer["user"] = admin;
customer["score"] = 1338;
await customer.SaveAsync();

Find objects not in a relation

I have a custom object Team in Parse with a relation field for the default User object. What I would like to do is retrieve all User objects which are not related to any Team object. Can anyone point me in the right direction on how to do this using the JavaScript SDK? I've been going over the documentation for the Query object but I can't find anything.
Perhaps another type of relation, or placing the relation at another place is a better solution. What I want to accomplish is the following: Each user is allowed to be in one team and one team only. In addition I need to be able to query the following information from Parse:
I want to retrieve the User objects of all the users assigned to a team
I want to retrieve the User objects of all the users who are not assigned to any team
I have tried using a join table with both the user and team object ids. Then I tried to following query to get all users not assigned to a team:
var teammember = Parse.Object.extend('TeamMember'),
query = new Parse.Query("User");
var innerQuery = new Parse.Query("TeamMember");
query.doesNotMatchQuery('user', innerQuery);
query.find({
success: function(results) {
response.success(results);
},
error : function(error) {
response.error(error);
}
})
But this just gets me the following response: error: "{"code":102,"message":"bad type for $notInQuery"}".
I like the Relation type as I can add or remove multiple members at once with a single call to the REST API. I also have no problems retrieving the information on team members when using the Relation type to connect the users to the teams. It is just getting the users which are not assigned to any team that is giving me problems.
It doesn't sound like you need a relation at all. Instead, add a Pointer column to User that points to Team. It ensures that a User can only belong to one team, and your other requirements can be captured as follows.
// All users assigned to a team
query = new Parse.Query('User');
query.exists('team');
// All users assigned to a specific team
query = new Parse.Query('User');
query.equalTo('team', specificTeam);
// All unassigned users
query = new Parse.Query('User');
query.doesNotExist('team');
Update: If you need to support multiple teams per User in the future, then I would suggest creating a Parse table called Membership with two columns: a Pointer to User and a Pointer to Team. This essentially gives you more control than relying on Parse relations, but it gets a little more complicated.
_ = require('underscore'); // Or lodash
// All users assigned to a team
query = new Parse.Query('Membership');
query.find().then(function (results) {
// http://underscorejs.org/#uniq
users = _.uniq(results, false, function (user) { return user.id; });
});
// All users assigned to a specific team
query = new Parse.Query('Membership');
query.equalTo('team', specificTeam);
// All unassigned users
var assignedUsers = []
var unassignedUsers = []
memberQuery = new Parse.Query('Membership');
userQuery = new Parse.Query('User');
memberQuery.find().then(function (memberResults) {
// http://underscorejs.org/#map
var ids = _.map(memberResults, function (user) { return user.id; });
// http://underscore.js.org/#uniq
assignedUsers = _.uniq(ids);
userQuery.find();
}).then(function (userResults) {
var users = _.map(userResults, function (user) { return user.id; });
// http://underscorejs.org/#difference
unassignedUsers = _.difference(users, assignedUsers);
});
To add and remove Users to/from Teams, you would create Membership objects and save API calls with Parse.Object.saveAll() and Parse.Object.destroyAll().
I ran into trouble with the answer provided by Seth. When retrieving the users not assigned to a team the difference between the two arrays would be incorrect. I am assuming this is due to the assignedUsers having object of type Membership and userResults being of type User. This would make it impossible for underscore to make a proper match.
I would up using this as my Cloud Code:
Parse.Cloud.define("getTeamlessUsers", function(request, response) {
var _ = require("underscore"),
assignedUsers = [],
companyUsers = [],
memberQuery = new Parse.Query("TeamMembers"),
userQuery = new Parse.Query("User"),
index,
ubound;
memberQuery.find().then(function(memberResults) {
// Make sure each User ID will appear just once
memberResults = _.unique(memberResults, false, function(item) { return item.get('user').id; });
// Loop over the unique team members and push the User ID into the array
for (index = 0, ubound = memberResults.length; index < ubound; index++) {
var user = memberResults[index].get("user");
assignedUsers.push(user.id);
}
// Get al the users
return userQuery.find();
}).then(function(userResults) {
// Loop over all the users and push the ID into the array
for (index = 0, ubound = userResults.length; index < ubound; index++) {
companyUsers.push(userResults[index].id);
}
// Create an array of user IDs which are not present in the assignedUsers array
var result = _.difference(companyUsers, assignedUsers);
// Return the IDs of user not assigned to any team
response.success(result);
}).fail(function(error) {
response.error(error);
});
});

Resources