I'm developing nodejs application with users registration using sails.
I have an /signup method, which is looking for existing user, if user not found, it will create new user in db.
As you know in sails model (waterline) available few methods : beforeCreate, afterCreate. In beforeCreate I need also register user in a few other services(it takes +-2 seconds), after that I can set received data to user object.
The problem is if user clicks few times on "register" button (or just send the same request 2+ times in a row), it will create 2 objects in db ( or another services ). I have a similar with some other methods like this.
I was trying to set unique field in user model. Also maybe is good idea to implement police, witch can check user + reqest url and put this data into redis. If the second request arrives , check if it exists in Redis. Any other ideas?
Related
I am implementing the stripe api in my node application. The problem i am having is that if i click the submit button very fast multiple times, the api is called multiple times and the stripe customer suddenly has multiple subscriptions and charges.
The scenario is when a user has a stripe customer account without a subscription since they have previously unsubscribed. Now they would like to resubscribe with a new plan since the old one is deleted.
The logic of my code is as follows:
1. Submit form
2. I retrieve the user from my mongo db
3. I retrieve the customer from stripe using a stored customer id (api call)
4. I create a customer subscription (api call)
5. I update the stripe customer object with their credit card (api call)
6. Respond back to user
All of the above is done using async waterfall, each subsequent asynchronous call is in a separate function
What I want:
Between steps 3 and 4 i want to retrieve the customer and check if he or she is already subscribed and prevent 4 and 5 from occurring if the user already has an active subscription.
The Issue:
I am testing the scenario where the user clicks the submit button multiple times and ends up being charged for several subscriptions. I believe that it has to do with how node sends several requests at once due to its asynchronous nature and me wanting to check make an api call to check if something is set takes too long and node doesn't wait when it sends all of the requests.
How do i go about solving this.
Note: Of course i have the front end handling this to prevent user from submitting the form multiple times but this is not ideal and don't want this to be my only line of defense.
Thanks
use a powerful rate limiter library
https://github.com/jhurliman/node-rate-limiter
var RateLimiter = require('limiter').RateLimiter;
// Allow 1 requests per minute
var limiterPayments = new RateLimiter(1, 'minute');
exports.payWithStripe = function(req,res){
limiterPayments.removeTokens(1,function(err,remainingRequests){
if (err){
return res.sendStatus(429);
} else {
// continue with stripe payment
}
}
This will throttle per session (per user browser)
One way is to keep a cache (in Redis or similar) of recent transactions, indexed by a hash derived from key transaction values (e.g. customer id, date, time, amount.)
Before submitting the subscription request to stripe, compare the current transaction to the cache. If you get a hit, you can either show an error, automatically ignore the transaction, or let the user choose whether to proceed.
Disable the button in your frontend using javascript as soon as it's clicked the first time.
Stripe has built in functionality to help you prevent this. https://stripe.com/docs/api/idempotent_requests
You need to generate a unique string and send it along with the stripe request.
Putting it in the HTML in a hidden form, a la your CORS token, then reading it out and putting it in the Stripe call will prevent double click / retries.
I'm interfacing my App with Moodle and I'm successfully calling mod_scorm_get_scorm_sco_tracks and mod_scorm_get_scorm_attempt_count via Ajax (XMLHttpRequest) for a given user (userid).
Now I want my App to push some SCORM tracks back to Moodle.
So I'm trying to use mod_scorm_insert_scorm_tracks but with no success.
The problem is that this method does not take an userid parameter, so I don't understand how to use it (and if I try to add userid to input params I get an invalid parameter exception).
I had kind of success (no error message) by sending this:
scoid=206&attempt=2&tracks[0][element]=cmi.completion_status&tracks[0][value]=completed&tracks[1][element]=cmi.interactions.0.id&tracks[1][value]=multiplechoice_page_1_1&tracks[2][element]=cmi.interactions.0.learner_response&tracks[2][value]=White&tracks[3][element]=cmi.interactions.0.result&tracks[3][value]=correct&tracks[4][element]=cmi.interactions.0.description&tracks[4][value]=Which%20color%20was%20Garibaldi's%20white%20horse%3F&tracks[5][element]=cmi.interactions.1.id&tracks[5][value]=hotobject_page_2_1&tracks[6][element]=cmi.interactions.1.learner_response&tracks[6][value]=butterfly&tracks[7][element]=cmi.interactions.1.result&tracks[7][value]=incorrect&tracks[8][element]=cmi.interactions.1.description&tracks[8][value]=Where%20is%20the%20fish%3F&tracks[9][element]=cmi.score.max&tracks[9][value]=2&tracks[10][element]=cmi.score.raw&tracks[10][value]=1&tracks[11][element]=cmi.score.scaled&tracks[11][value]=0.5&tracks[12][element]=cmi.session_time&tracks[12][value]=PT0H0M15S&tracks[13][element]=timemodified&tracks[13][value]=1480947821&tracks[14][element]=userid&tracks[14][value]=26&tracks[15][element]=scoid&tracks[15][value]=206&wstoken=69f2471506c4c49ff47cd0de0c4c9f01&wsfunction=mod_scorm_insert_scorm_tracks&moodlewsrestformat=json
However, since I cannot specify the user those data belongs to, my user's attempts does not update (as predictable).
This is the response from Moodle:
{"trackids":[44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59],"warnings":[]}
I've tried inserting the userid info into traks (tracks[14][element]=userid&tracks[14][value]=26) but still no luck.
So, the questions are:
Which user are those tracks inserted to considering that I'm calling it from an external app, so there's no logged in user in Moodle?
How can I specify that those tracks are for a give userid?
the user identity comes from the HTTP Context of a full login into Moodle: you can't provide SCORM tracking info on behalf of any user but the actual logged-in user.
More at:
https://github.com/moodle/moodle/blob/d33c67bc4744f901bf389607cfbbb683ef1c7d80/mod/scorm/classes/external.php#L451
https://github.com/moodle/moodle/blob/0b8e0c374f89ca20e5b9e7c9370761810811edc6/lib/externallib.php#L481
HTH,
Matteo
I have created a chat message functionality. The message stores the userid of sender and receiver. How can I get other details of the user just based on the userid?
Is creating a Meteor method the best way or I have to create publish/subscribe pattern for it.
I want to avoid sending all users data to client side.
I tried creating a meteor method but I don't think its the best approach.
Meteor.methods({
getUserInfoById: function (usrId) {
//console.log("BEGIN");
//console.log(usrId);
var user = Meteor.users.findOne(usrId);
//console.log(user);
//console.log("END");
return user;
}
});
Create a publisher (and also a subscriber) for the data about other users that you want a given user to see. You can restrict the fields returned using the {fields: ...} qualifier in the query.
This is a very common pattern. Using a method for this is an anti-pattern due to the extra round-trip delay for something you're likely to show quite often, i.e. another user's username or avatar.
So I'm trying to make a notification system similar to Facebook's system. I have a cron job running in the background and when it feels the need to send out a notification to an user it uses the PHP (REST) SDK to send a push to Firebase. On the dashboard I have an 'on' callback that fetches all incoming notifications for the user and shows a notification for each incoming new notification
var push_ref = firebase_ref.on('child_added', function(push) {
new PNotify({
title: 'Notification',
text: push.val().message,
...
});
});
However, when I reload the page all previously sent notifications pops up simultaneously and fills the screen with notification boxes. I don't wanna delete the sent push notifications because later on I'm gonna make a system to fetch them and put them in a dropdown box (similar to the notification dropdown on Facebook).
My question is;
How can I keep all sent notifications but at the same time disable that Firebase returns all notifications when the client goes online again?
UPDATE:
Looked through their documentation again and saw that their retrieving data types are very different. It says under "child_Added" that it "is triggered once for each existing child and then again every time a new child is added to the specified path". This is why it is triggered once I reload the page with all the existing children.
Can you see any other types that might work for me, because I haven't found any.
You could have the client update each message on receipt to acknowledge that it was shown (set acknowledged = true or whatever). Then use the acknowledged field to filter the UI treatment to only highlighting unacknowledged messages.
This assumes the messages are user-specific, or your data structure will require a message/user mapping to hold the acknowledgements.
If the user is reading from a public stream of messages, you could save a user-specific lastReadDate or something that filters out the old messages.
I am using SignalR for notifications in my web site but i couldn't find a way to send notifications according to the page/content.
Let me explain in details.
Assume that, there is a page for showing a record from database (for example a blog post).
So there is only one page for showing posts as it should be.
And every post has a like counter which i want to update via signalr notifications, if another user clicks like button. Until here, it is very easy to accomplish.
This page contains a javascript code block like below
var notify = $.connection.notificationHub;
notify.client.updatePostLikeCount = function (likeCount) {
$("#likeCount").text(likeCount);
};
And this function triggered from server-side like below (it is in another class instead of Hub class)
var context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
context.Clients.User(user.Id).updatePostLikeCount(likeCount);
But a user might open more than one post; so if a notification is sent from server-side all opened tabs receive this notification and update its counter.
I looked for .Caller method but it is not available in IHubContext interface which GetHubContext() returns and couldn't find another way.
To summarize, i want to send notifications to users who had opened the post which user liked.
EDIT: After sending question i got an idea. Continue sending notification as being and filtering according to the content at client side. It is not very good but i think it will work with charms.