Parse CLP / ACL causing issues with beforeSave trigger - security

thanks for stopping by.
I have a class, let's call Class1, that I use to give users of my app discounts / coupons. When a user finishes the registration process, I create an object and store the pointer to it on the user.
I want to give this class CLP permissions so that the public can create, but not write to this object. Let it only be something that I use internally.
My problem is that the class has several arrays that can't be undefined, or other cloud functions will end up throwing errors trying to read those values. I set up a beforeSave() trigger for the class, and use the master key, but the object isn't being saved so my entire user save at the end of registration isn't working. How do I fix this while keeping my object secure and making sure users can't steal all of my app's services for free?
Here is my beforeSave trigger:
Parse.Cloud.beforeSave("Class1", function(request, response)
{
Parse.Cloud.useMasterKey();
var emptyArray = [];
class1 = request.object;
if( class1.isNew() )
{
class1.set("array1", emptyArray);
class1.set("array2", emptyArray);
class1.set("array3", emptyArray);
}
response.success();
});

So I guess you can't use the master key to override CLP / ACL stuff in a beforeSave trigger... though it makes sense, as that would entirely defeat the point.
However, if you give public create access, you can populate any initial data, you just can't update it without update access. So, the obvious answer was to just set these parameters on the client side when I created the object and before I saved it.

Related

GetStream.io - Non authenticated user activity

I'm using GetStream's Laravel integration (github.com/GetStream/stream-laravel) but noticed that 'actor' is just a swappable Model. I'm trying to allow logged in users to post, but I want to allow "anonymous" (unauthenticated) users to like the post using UserAgent/fingerprint/ip/session etc.
Has anybody done something similar or know of a method to hot swap the actors or allow the actor_id in specific situations to use another model?
You should be able to use the ActivityTrait (https://github.com/GetStream/stream-laravel/blob/master/src/GetStream/StreamLaravel/Eloquent/ActivityTrait.php) without using the activityActor method, which is called here: https://github.com/GetStream/stream-laravel/blob/master/src/GetStream/StreamLaravel/Eloquent/ActivityTrait.php#L130.
For example:
class Model
{
use ActivityTrait {activityActor as traitActivityActor;}
public function activityActor()
{
if (/* check if authenticated user */) {
return $this->traitActivityActor(); // Reusing the same method.
}
return /* some other logic to return identifier for anonymous user */;
}
}
There are other places to hook into and adjust the functionality by this package. But I think in your case this might be the easiest for this model.
I hope this help you in the right direction.

wit.ai runActions how to handle context in follow-up message

I'm using node-wit to develop a chatbot application.
This is working fine mostly, but I've run into a problem with the use of the context.
I'm using the runActions api :
this.witClient.runActions(customer._key, messageText, witContext).then((newContext => {}
)).catch(reject);
I have defined a number of actions, which set the context.
This is working fine, as long the context is taking place over one message.
For example, if I were to call an action called addProduct :
addProduct({sessionId, context, text, entities}) {
return new Promise((resolve, reject) => {
context.product = `myNewProduct';
resolve(context);
});
},
It will then show a message using the 'product' context key.
However, when I try to use it over 2 messages, it seems to have lost the context ( for example, when asking a multiple choice question, and then handling that response ).
If I understand how it's working correctly, then node-wit doesn't keep the context beyond messages ( I assumed this at first because I'm passing a session key ).
A solution I see is to store the resulting context ( newContext in this case) in a session/user specific way, and then restore it and pass it again when the user is sending his new message.
Meaning, something like this :
witContext = getContextFromSession();
this.witClient.runActions(customer._key, messageText, witContext).then((newContext => { setContextInSession(newContext) }
)).catch(reject);
Would this be the correct way of handling it ?
Off course you have to store your context state, you decide how to store it. But, take into account what is the most efficient way if you're gonna have a lot of users, and your reasources available.
As you can see in the official example for nodeJs, there's a method named findOrCreateSession on https://github.com/wit-ai/node-wit/blob/master/examples/messenger.js they get the session before the wit actions are called.
In my particular case, I am storing it in the database, so I get the session before the action is called, so I can send the context, then in the actions I query the session again to modify the resulting context and store it again, try the best implementation for your needs.

How to think asynchronously with nodejs?

I just started developing nodejs. I'm confused to use async model. I believe there is a way to turn most of SYNC use cases into ASYNC way. Example, by SYNC, we load some data and wait until it returns then show them to user; by ASYNC, we load data and return, just tell the user data will be presented later. I can understand why ASYNC is used in this scenario.
But here I have a use case. I'm building an web app, allowing user to place a order (buying something). Before saving the order data into db, I want to put some user data together with order data (I'm using document NoSql db by the way). So I think by SYNC, after I get order data, I make a SYNC call to database and wait for its returned user data. After I get returned data, integrate them together and ingest into db.
I think there might be an issue if I make ASYNC call to db to query user data because user data may be returned after I save data to db. And that's not what I want.
So in this case, how can I do this thing ASYNCHRONOUSLY?
Couple of things here. First, if your application already has the user data (the user is already logged in), then this information should be stored in session so you don't have to access the DB. If you are allowing the user to register at the time of purchase, you would simply want to pass a callback function that handles saving the order into your call that saves the user data. Without knowing specifically what your code looks like, something like this is what you would be looking for.
function saveOrder(userData, orderData, callback) {
// save the user data to the DB
db.save(userData, function(rec) {
// if you need to add the user ID or something to the order...
orderData.userId = rec.id; // this would be dependent on your DB of choice
// save the order data to the DB
db.save(orderData, callback);
});
}
Sync code goes something like this. step by step - one after other. There can be ifs and loops (for) etc. all of us get it.
fetchUserDataFromDB();
integrateOrderDataAndUserData();
updateOrderData();
Think of async programming with nodejs as event driven. Like UI programming - code (function) is executed when an event occurs. E.g. On click event - framework calls back registered clickHandler.
nodejs async programming can also be thought on these lines. When db query (async) execution completes, your callback is called. When order data is updated, your callback is called. The above code goes something like this:
function nodejsOrderHandler(req,res)
{
var orderData;
db.queryAsync(..., onqueryasync);
function onqueryasync(userdata)
{
// integrate user data with order data
db.update(updateParams, onorderudpate);
}
function onorderupdate(e, r)
{
// handler error
write response.
}
}
javascript closure provides the way to keep state in variables across functions.
There is certainly much more to async programming and there are helper modules that help with basic constructs like chain, parallel, join etc as you write more involved async code. but this probably gives you a quick idea.

Bigbluebutton ending a meeting

I have implemented a function from the client part that calls the following function in the bigbluebutton-apps participant service
public void modEndMeeting(String roomName){
roomsManager.removeRoom(roomName);
}
Which calls a function that does the following
Gson gson = new Gson();
messagingService.send(MessagingConstants.SYSTEM_CHANNEL, gson.toJson(map));
And on the bigbluebutton-web part the following code is ran
listener.userLeft(meetingId, internalUserId);
And all that code does is place the meeting on the garbage collection list and does not end it right away.
The correct way to do it is to call the function end defined in ApiController.groovy.
I can do that buy generating an HTTP request. and sending the correct parameter. But I do not want to follow that approach
Is there any way that i can connect or return an instance of from which i can call the function end defined in ApiController.groovy that has an instance of a class called meetingService that actually owns the meeting ?
I have tried to make meetingService a singleton but that did not work.
I have also made the list that owns in the meeting of meetingService static. That also did not work
Here is a brief structure of meetingService
private final ConcurrentMap<String, Meeting> meetings;
This is a list that houses the meetings
Any ideas or suggestions ??
And http request would be the only way to close a meeting from the APIcontroller.
An other way would be to expensive. And it would decreasing the timer from 60 000 to like 1000 in the ExpiredMeetingCleanupTimer.java class
Or you can place a listener in the Apicontroller.groovy and send a redis message.
The thing to do would be to mark the meeting as closed on the red5 part and kicking anyone trying to join it, until the web part does the trick and ends the meeting.

Persistent Sessions in Meteor

So, one of the more confusing aspects I've been observing with Meteor is that Sessions get cleared every refresh. Since it isn't a persistent store, where would I put things like userid, or where people are in my application's state machine?
What are the patterns for those scenarios?
Actually what you could do is create a "subclass" of Session that stores the value in Amplify's local storage when set() is called. You would automatically inherit all the reactive properties of Session. Here is the code, it worked for me:
SessionAmplify = _.extend({}, Session, {
keys: _.object(_.map(amplify.store(), function(value, key) {
return [key, JSON.stringify(value)]
})),
set: function (key, value) {
Session.set.apply(this, arguments);
amplify.store(key, value);
},
});
Just replace all your Session.set/get calls with SessionAmplify.set/get calls. When set() is called, the parent Session method is called, as well as amplify.store(). When the "subclass" is first created, it loads everything that is in amplify's store inside its keys, so that they can be retrieved right away with get().
You can test a working variation of the Leaderboard example here: https://github.com/sebastienbarre/meteor-leaderboard
Well, for a start I would be using meteors built in Auth to store userID. They are using local storage by default there I think, but AFAIK there's no easy way to hook into that.
However, I would have thought if you want stuff to survive across refreshes you should either store it in mongo or use the URL to indicate where they are in the 'state machine'. You can use the bootstrap router (for example) to use pushState to change the URL.

Resources