To implement password reset request in loopback (send email to the user with reset link), we need to handle the event resetPasswordRequest.
This is a possible implementation below
Client.on('resetPasswordRequest', function(info) {
var options = {
type: 'email',
to: info.email,
from: '....',
...
};
Client.email.send(options, function(err, res) {
if (err) console.log(err);
});
});
With this approach, if an error occurs it is simply logged to the console. Throwing an error that won't be handled doesn't feel like a better solution either.
Why is it not mentioned in the docs to use an afterRemoteHook to add this logic or even create a new custom endpoint ? Both solutions seem better at handling errors.
I think your code is based on example application, isn't it? If so, this approach is used by developer of example application but is not required implementation. You may use any other appropriate solution and one is that what you've mentioned in your question.
As for emitting event - it has it's advantage. You emit event and immediately send response to request. So client app will not wait until email sending part will send email - this can take from seconds to tens of seconds.
You may implement email sending log and make another request to it while user is waiting for password reset email thus notify him if any error will occur.
From the other hand this is only example but not required implementation for using in production.
Related
I would like to implement a system that allows users to add each other as friends and share data between them. I have gotten the authentication done and currently researching ways to do this real time. This project of mine is purely a learning experience so I am looking for many ways to perform this task to grow my knowledge.
I have experience using Websockets on a previous project and it was easy to use. Websockets seems like the best solution to my problem as it allows the user to send and receive invites through the open socket. However I have also learnt that the downside would be a long open socket connection that might be potentially performance taxing(?) Since I'm only sending/receiving information only when an invite is sent/received, websockets might be overutilized for a simple function.
At the same time I would like to learn about new technologies and I found out about Server Sent Events that would be less performance heavy(?) Using SSE would be much efficient as it only sends HTTP requests to the clients/server whenever the user send the invite.
Please correct me if I'm wrong for what I typed out above as this is what I gathered through my reading online. So now I'm having a hard time understanding whether SSE is better than websocket for my project. If there are other technologies please do let me know too! Thank you
how you doing ?
The best advise would be always to use websocket in this context, cuz your project can grow and need some feature that would be better using websocket
But you got another options, one of the is Firebase, Yes, FIREBASE!
You can do a nice reactive application with firebase, becouse the its observers update data in realtime, just like the websockets do.
But here go some cons and pros.
Websocket: Can make your project escalable, its more complete, you can use it in any context, BUT: is hard to implement and takes more time to be learned and understood.
Firebase, Easy and fast to implement, you can do a chat in 20 minuts, and surelly would help you with your problem, There is Firestore and Reatime database.. even the firestore updates in realtime.. BUT: Firebase costs in a big project can be expensive, i dont think is a good option for a big project.
Thats it.. the better options to do a real time data application to me.
A little bit more about. Firebase vs Websocket
https://ably.com/compare/firebase-vs-socketio
to send a friend invitation, you just send an API request. WebSocket is used for real time communication. From react.js, get the email and send the email to the server
export const sendFriendInvitation = async (data) => {
try {
return axios.post("/friend-invitation", data);
} catch (exception) {
console.error(error)
}
};
On node.js side, write a controller to control this request:
const invitationRequest = async (req, res) => {
// get the email
const { targetMail } = req.body;
// write code to handle that same person is not sending req to himself
// get the details of user who sent the email
const targetUser = await User.findOne({
mail: targetMail.toLowerCase(),
});
if (!targetUser) {
return res
.status(404)
.send("send error message");
}
// you should have Invitations model
// check if invitation already sent.
// check if the user we would like to invite is our friend
// now create a new invitation
// if invitation has been successfully created, update the user's friend
return res.status(201).send("Invitation has been sent");
};
I found similar questions but not found any good answer so I am posting it again and with more specific environment.
I am using Node.js + Express to build REST APi for my React Native app.
I am using pattern Router->Controller->Service->Database and I am not sure if I am supposed to throw specific errors from my services.
Example:
I am validating registration request.
Field validations are hapenning inside Controller (I am using ajv JSON schema validator).
Now I need to validate if user/email already exists
Am I supposed to do this from controller by calling for example service.emailExists(data.email) before calling service.createUser(data)??
Or I can let database fall on CREATE duplicate, return false from service.createUser(data) and inform user from controller that Email exists. If I do so, I am not able to inform user if there is Unspecified error inside service, because it will always return as Email exists error, even something else happens.
You can use try...catch, or if...else to handle the possibilities of errors.
This is how it worked for me. Service using express and sequelize
const { Keluhan } = require('../../models');
var getAllKeluhan = () => {
return Keluhan.findAll()
.then(data => {
if (data) {
return {
code: 200,
message: "Data Found!",
result: data
};
} else {
return {
code: 404,
message: "Data not Found!"
}
}
})
.catch(err => {
throw err;
})
}
module.exports = getAllKeluhan;
This kind of typical problem can be solved in different ways. i provide below few.
A general way of handling it to fail in Database layer and there will be a cascading of failure from database layer to service layer and then controller layer. In this case it is assumed that there is no graceful failure and in this case, people just broadcast a generic failure. All the errors and exceptions are reported in a log.
The another approach is to make a failure at the service layer itself if the email id already exists in the cache without connecting to database. It seems to be a good approach as long as there is a good synchronization between database and the cache layer.
Another approach would be a proactive failure where once the user enters the email id and makes a tab out in UI, you can connect to database to validate through a service.
Sometimes, it is also thought that let the user enters everything in the UI screen and let us validate at the end.
As far as design is concerned, I think approach should be given by the functional team who propose the idea. Technically, all the approaches are possible.
The most important thing here is to grab the error or exception in the controller and propagate as a bad request. It means user should be notified whether email id already exists or not.
Finally, you can think of the design like Fail-Safe or Fail-Fast as per your requirements.
We need to update the client side UI to indicate that a message fails to deliver. How do I have Socket.IO JS client call a custom callback directly when the message fails to deliver? For example, something like:
socket.emit("event", data).onError(myCallback);
I know Socket.IO provides the Ack mechanism to confirm delivery success. Therefore, one can set up a timer with a handler which calls the failure callback, if the ack is not called after a certain amount of time. But this doesn't seem to be the best way to do.
Also there is the error event provided by Socket.IO, but it doesn't come with info regarding which emit caused the error.
Unfortunately there's no way to get errors from callbacks, the only way is to indeed create your own timeout:
var timeoutId = setTimeout(timeoutErrorFn, 500);
var acknCallbackFn = function(err, userData){
clearTimeout(timeoutId)
//manage UserData
}
socket.emit('getUserData', acknCallbackFn);
Source of the code
And there's another issue about this, open
So for the time being you have to stick with your manual setTimeout.
The fact that I haven't found an existing answer for this makes me think I'm asking the wrong question. Please feel free to (gently or otherwise) push me onto a better path if necessary.
We use a dedicated auth server, the purpose of which is to (1) given login credentials, return a JWT with a near-term exp or (2) given a JWT, according to a set of rules, issue a new JWT. A refresh, essentially.
That all works ace, until it's hacked. But for now, it's ace.
When it comes to socket.io connections to non-auth servers, however, we're shooting more than a bit from the hip. I wonder if somebody would be so kind as to evaluate this process. (I'm happy to post more code; you tell me if it's relevant).
1) initial socket.io connection results in a challenge:
this.socket.emit('authenticate'); // the challenge
this.authTimeout = setTimeout(() => {
this.socket.disconnect('unauthorized', errors);
}, TIME_TO_AUTHENTICATE); // the response kills this!
this.socket.on('authenticate', token => {
clearTimeout(this.authTimeout);
this._authenticate(token)
})
2) subsequent messages must contain a "payload" message in the form:
payload = {token: 'foo', message: 'bar'}, which token would be accepted if valid or returned if invalid.
In addition, the resource server sends its own periodic heartbeat, which must be acknowledged by heartbeat {token}.
My question, thus is: this seems too easy; am I cutting corners somewhere? Could you defeat this feeble fortification?
Just to be clear, we're looking to roll our own module here. I'm happy to look at anything existing; just haven't found anything I could begin to convince the bosses is fully baked for our needs.
Many thanks in advance.
I cannot fully analyse the method or ensure it doesn't have flaws, however I'd like to point out some things that came up to mind:
Apart from disconnecting the user in case of timeout on authentication challenge, you must ensure that the server does not send any non-public message to this user until after the authorization challenge is actually fulfilled successfully. Otherwise, there is a period until timeout where the user could receive a message without being authenticated.
I assume that you are also disconnecting the socket if token is invalid (or someway preventing non-public message to be sent).
This article is about authenticating socket.io communications using JWT. It is from 2014 so it might be a little bit out of date but I think that the core concept is still valid.
Associated with the article, there is a tool built specifically to authenticate socket.io connections using jwt. Even if you don't want to use it, you might want to explore its code looking for "inspiration". You can find it here: socketio-jwt.
You can see that this tool is able to use two different approaches:
An approach pretty similar to yours:
from socketio-jwt/blob/master/lib/index.js
if(options.required){
var auth_timeout = setTimeout(function () {
socket.disconnect('unauthorized');
}, options.timeout || 5000);
}
socket.on('authenticate', function (data) {
// ...
// Token validation
// Emit "authenticated" event if token is valid, the server can use
// this event as a point to send messages, once token is valid
});
A "One roundtrip" approach that basically uses query strings during handshake. And whose main drawback is that the token is exposed in the URL, so it might be logged, or getting exposed.
I'm using socket stream to send the data to the logged in user by using the following code
var ss = require('socketstream');
....
....
ss.api.publish.user('userId', content);
but the ss.api.publish is undefined is what the error i'm receiving.
Where am i going wrong.
Please advice.
The API for a publish to a user is:
Sending to Users
Once a user has been authenticated (which basically means their session now includes a value for req.session.userId), you can message the user directly by passing the userId (or an array of IDs) to the first argument of ss.publish.user as so:
// in a /server/rpc file
ss.publish.user('fred', 'specialOffer', 'Here is a special offer just for you!');
Important: When a user signs out of your app, you should call req.session.setUserId(null, cb) to prevent the browser from receiving future events addressed to that userId. Note: This command only affects the current session. If the user is logged in via other devices/sessions these will be unaffected.
The above is taken from the original document describing the socketstream pub/sub api.
as you can see, you need to supply one more argument than you thought. That is, becasue on the client side you need to subscribe to a message channel in order to get the message. In the above example, you need to do this in your client side code:
ss.event.on('specialOffer', function(message){
alert(message);
});