This is my first time playing around with security roles in Parse and I believe what I'm trying to do is fairly simple. I want to create a new security Role after I signup a new user using the afterSave trigger in CloudCode.
I've verified that this is being called and the roleName is correct, but nothing is being saved in the data browser. I feel like I'm missing something pretty basic here for this not to be working - is there a setting somewhere I need to turn on?
Parse.Cloud.afterSave(Parse.User, function(request, response) {
var user = request.object;
if (user.existed()) { return; }
var acl = new Parse.ACL();
acl.setPublicReadAccess(false);
acl.setPublicWriteAccess(false);
var roleName = user.get("email");
Parse.Cloud.useMasterKey();
var companyRole = new Parse.Role(roleName, acl);
console.log("Role = " + companyRole);
companyRole.save();
});
Found the solution. In Parse, you the name for a Role can only contains letters, numbers, and underscore. I was trying to set the role name as an email address, which contains '#' and '.'
I did a replace on these characters before I saved the name and worked perfectly. I wish Parse would've thrown an error if trying to save with invalid characters but problem solved now.
Related
I have a Friends table that contains userIds for a user list of friends. The user column is a pointer to the User table and the friendId does the same.
I'm attempting to find all of the users that equal the "friendId" for a particular user and send notifications to those users.
I've added a "user" column to my Installations table which is a pointer to "User" so that I can find my installations for specific users and send a push notification.
The issue I am having is I an unable to link those queries together to get send my push notifications to my list of friends.
Any suggestions are helpful.
My current cloud code
Parse.Cloud.define("pushCheckIn", function(request, response) {
// Find users near with pending messages
var friendList = Parse.Object.extend("Friends");
var username = request.params.username;
var location = request.params.location;
var userQuery = new Parse.Query(friendList);
userQuery.equalTo("friendId", Parse.User);
// Find devices associated with these users
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.matchesQuery("user", userQuery);
var alertMsg = username + " checked-in at " + location;
Parse.Push.send({
where: pushQuery,
data: {
alert: alertMsg,
sound: "beep-shinymetal.caf",
title: alertMsg
}
}, {
success: function() {
response.success(alertMsg);
// Push was successful
},
error: function(error) {
response.error("push failed");
}
});
});
Your description of your tables is complicated and I don't fully understand, however I think that new Parse.Query(friendList); should rather be new Parse.Query("Friends"); and userQuery.equalTo("friendId", Parse.User); doesn't make sense at all, if it is string you should use userQuery.equalTo("friendId", yourFriendIdString);
If you try to explain your tables better, I can try to give you better advice :)
The Installations table can not be queried directly without using the master key. To query the installations table, use
Parse.Cloud.useMasterKey();
before executing the query
I am using Parse as a service for my app, specifically the JavaScript SDK.
In my app I have a class that represents a user post in my app containing images and text.
For some reason occasionally when a new object is created by the user, the objectId assigned by parse sometimes causes errors with that particular post.
I get this in the console:
t.Error {code: 105, message: "invalid field name: 3qUHMBPCBs"}
the field name is the objectId assigned automatically by Parse when the user uploads their post.
Second time this has happened. I noticed when I removed that post, the error disappeared but, obviously I can't keep deferring to that method.
Updated, code used for the user post below
so, essentially theres functionality that allows a user to post an update to parse. When the user submits, this function is performed and an object is generated by Parse.
var sendThis = $('#resultImage').attr('src');
var parseFile = new Parse.File("mypic.jpg", {
base64: sendThis
});
var val = document.getElementById('statusupdateform').value;
var statusupdate = $('#statusupdateform').val();
var currentUser = Parse.User.current();
parseFile.save().then(function() {
var nameCurrent = currentUser.getUsername();
var cigarWall = new Parse.Object("cigarwall");
cigarWall.set("appuser", nameCurrent);
cigarWall.set("statusupdate", statusupdate);
cigarWall.set("imagefile", parseFile);
cigarWall.save({
success: function() {
$('#uploadBtn').removeClass('tapActive');
var postupdate = cigarWall.get('statusupdate');
//$('#fileselect').attr('data-change', 'false');
$('#statusInnerWrapper').removeClass('slideLeft');
location.reload();
},
error: function() {
alert("upload failed. please try again!");
}
});
});
I Had a bad line of code in my Query function for one of the Parse classes. I Was unnecessarily querying against the objectId column.
I'm trying to return a list a users who are not already in a friends join table on Parse.com but it seems that trying to match a pointer record with a users objectId will not work.
We could break this out into separate calls but that would be poor performance.
Has anyone solved this yet?
//Get users current friends
var myfriends = new Parse.Query("UserFriend");
myfriends.equalTo("myUserId",user);
//get users who are not already friends
var userQuery = new Parse.Query(Parse.User);
userQuery.doesNotMatchKeyInQuery("objectId", "theirUserId", myfriends);
userQuery.find().then(function(newfriends){
//do stuff with newfriends
//New friends should not include existing friends but it does..
});
Big thanks to anyone who can help.
I haven't tested this, but give it a shot.. From my comment: "have a query for Parse.User that matches key in query for user friends, against a user query that does not match that query". This might suffer the same problem.
var friendsQuery = new Parse.Query(Parse.User);
var myfriends = new Parse.Query("UserFriend");
myfriends.equalTo("myUserId",user);
friendsQuery.matchesKeyInQuery("objectId", "theirUserId", myfriends);
var userQuery = new Parse.Query(Parse.User);
userQuery.doesNotMatchQuery("objectId", friendsQuery);
//Assuming Cloud Code...
userQuery.find({ useMasterKey: true }).then(function(newfriends){
//do stuff with newfriends
});
I couldn't get this to work either.. Instead I used doesNotMatchQuery which worked find with pointers.
I had a similar problem and discovered you can't compare an objectId to a pointer object. So in the case above:
userQuery.doesNotMatchKeyInQuery("objectId", "theirUserId", myfriends);
theirUserId would need to be a string key containing the the actual alphanumeric Id, not a pointer.
This is a running issue in Parse Server
https://github.com/parse-community/parse-server/issues/4346
So I am building an app, and in this app users will be able to go to each others' profile, and essentially like their profile. I am calling these likes compliments. This requires the current user to be able to access the selected users information to update the compliment count. So in order to implement this I am using Parse.com's cloud code.
My code looks like:
Parse.Cloud.define("complimentCounter", function(request, response) {
Parse.Cloud.useMasterKey();
var User = Parse.Object.extend("User");
var user = new User();
var user.id = request.params.userId;
var increment = request.params.increment;
user.increment = ("complimentsValue", increment);
user.save(null, {
success: function(user) {
response.success(true);
},
error: function(user, error) {
response.error("Could not compliment.");
}
});
});
However when I run it I get the error "Unexpected token . in main.js:8", and when I take that "." out it only returns the error of the function and not the success. Can someone please guide me in the right direction, and let me know what the issue is here? Thanks!
The increment() function is documented here.
The correct way to call it is:
// increment by 1
user.increment("keyName");
// increment by a number in a variable (yes you can use negative numbers too)
var increaseAmount = -5;
user.increment("keyName", increaseAmount);
You're reading a value, which seems to mean you want to increase the count by more than one, so the 2nd syntax is what you want.
Unfortunately you're calling it incorrectly, just take the = out of your line so it reads as follows:
user.increment("complimentsValue", increment);
I have been trying to automate Lotus Notes mail fillup from a browser interface.
After refering to Richard Schwartz's answer, i came up with this piece of code using the Lotus.NotesSession class.
function SendScriptMail() {
var mToMail = document.getElementById('txtMailId').value
var mSub = document.getElementById('txtSubject').value
var mMsg = document.getElementById('txtContent').value
var Password = "yyy"
alert("1");
var MailFileServer = "xxx.com"
var MailFile = "C:\Program Files\IBM\Lotus\Notes\mail\user.nsf"
alert("2")
var Session;
var Maildb;
var UI;
var NewMail;
var From = "user#xxx.com"
try {
alert("3")
// Create the Activex object for NotesSession
Session = new ActiveXObject("Lotus.NotesSession");
alert("4")
if (Session == null) {
throw ("NoSession");
} else {
Session.Initialize(Password);
// Get mail database
Maildb = Session.GetDatabase(MailFileServer, MailFile);
alert("5")
if (Maildb == null) {
throw ("NoMaildb");
} else {
NewMail = MailDB.CreateDocument();
if (MailDoc == null) {
throw ('NoMailDoc');
} else {
// Populate the fields
NewMail.AppendItemValue("Form", "Memo")
NewMail.AppendItemValue("SendTo", mToMail)
NewMail.AppendItemValue("From", From)
NewMail.AppendItemValue("Subject", mSub)
NewMail.AppendItemValue("Body", mMsg)
NewMail.Save(True, False)
NewMail.Send(False)
}
}
}
} catch (err) {
// feel free to improve error handling...
alert('Error while sending mail');
}
}
But now, alerts 1,2,3 are being trigerrd, and then the counter moves to the catch block. The lotus notes session is not being started.
In a powershell script that I was previously looking at there was a code regsvr32 "$NotesInstallDir\nlsxbe.dll" /s that was used before the Session = new ActiveXObject("Lotus.NotesSession");. Is there something similar in javascript too, if so how do i invoke that dll.
I think I've realised where I am going wrong. According to me, upto alert("5") things are good. But since Lotus.NotesSession doesn't have a CreateDocument() method, it is throwing the error. I am not sure how to create the document and populate the values though.
Since you've chosen to use the Notes.NotesUIWorkspace class, you are working with the Notes client front-end. It's running, and your users see what's happening on the screen. Are you aware that there's a set of back-end classes (rooted in Lotus.NotesSession) instead of Notes.NotesSession and Notes.NotesUIWorkspace) that work directly with Notes database data, without causing the Notes client to grab focus and display everything that you're doing?
Working with the front-end means that in some cases (depending on the version of Notes that you are working with) you're not going to be working directly with the field names that are standard in Notes messages as stored and as seen in the back-end. You're going to be working with names used as temporary inputs in the form that is used to view and edit the message. You can see these names by using Domino Designer to view the Memo form.
Instead of using 'SendTo', try using:
MailDoc.Fieldsettext('EnterSendTo', mToMail)
Regarding the Body field, there's no temporary field involved, however you haven't really explained the difficulty you are having. Do you not know how to display the interface that you want in the browser? Do you not know how to combine different inputs into a single FieldSetText call? Or are you just dissatisfied with the fact that FieldSetText can't do any fancy formatting? In the latter case, to get more formatting capability you may want to switch to using the back-end classes, which give you access to the NotesRichTextItem class, which has more formatting capabilities.