What is the best way to handle real time chat & messaging system? - angularjs

I am using node.js for backend and angular for frontend...
I thought to use socket.io but I am not sure how how to handle comunication between users...
For example how can I push message message to specific user after message is saved to database?
ex.
router.post('/message', function(req, res) {
Message.create({
text: req.body.text,
fromUser: req.fromToken.id,
toUser: req.body.toUser
}, function(err,message) {
//FROM HERE WHAT IS THE BEST WAY TO PUSH MESSAGE TO USER
})
});

Related

Approving or disapproving requests in one flutter app from another flutter app

So, I have created two applications, user and admin, using flutter. And both of them are in a single firebase project.
The Applications are investment-related. What I want to do is, Suppose a user sends an investment request from the user app. Another user in the admin app should be able to approve or disapprove the request and then the request status should be visible in the user app. Is there any way to do it?
What I tried: I created a new field in Firebase Realtime Database named Request Status. Then I passed a String Approved into it through the Admin app but it didn't work.
...
final investmentRequestsRef = database.child("Investment Requests");
...
void addData(String requestStatus) {
investmentRequestRef.set({
"Request Status": requestStatus,
});
}
...
Code of button that updates the status:
ElevatedButton(
...
onPressed: () {
addData("Approved");
},
...
)
What happens in realtime database when I do the method
You should try something like this...
DatabaseReference ref = FirebaseDatabase.instance.ref("Investment Requests/${requestID}");
await ref.update({
"Request Status": requestStatus,
});
This should work... I haven't seen your full code so I can't add anything else without more details about your code.
Use this official link of FlutterFire for reference.

Issue with watch request on gmail api

I am using the below code to send a watch request to gmail. But it is sending push notifications for every action on the mailbox. I need google to send notifications if there is a new email received only. Otherwise I don't want google to send notifications. I am using google-api nodejs client. Can anyone please assist me on this?
watch (cb) {
const params = {
userId: 'me',
resource: {
labelIds: ['INBOX'],
labelFilterAction: 'include',
topicName: configure.Google.TopicName
}
};
this.gmail.users.watch(params, cb);
}
You can do labelIds: ['UNREAD']
When you go to request history.list with the historyId, there is an option to limit the messages returned to messagesAdded, though you will continue to get extraneous push notifications.
labelIds expects the id of the label, not the display name of it.

Apply Socket.io in social network

I am building a social network application like facebook twitter. In this application one user have many followers. I need to apply socket.io when I give a status then It's only published on group of followers those who follow this specific user only. I've implemented socket.io in my application but now It's working all of the browser newsfeed but I want to apply socket only those who follow me.
I applied socket following way,
At client,
socket.emit('load-post', timelinePost);
socket.on('post-received', function(timelinePosts) {
$rootScope.timelinePosts = timelinePosts;
});
Server,
var io = require('socket.io')(server);
io.on('connection', function(socket) {
console.log('new connection made!');
// Broadcast the post
socket.on('load-post', function(data) {
socket.emit('post-received', data);
});
socket.on('disconnect', function() {
console.log('disconnected!');
});
});
News feed functions where I want to apply socket,
getNewsFeedServices.getStatusPosts().then(function(successMessage) {
$rootScope.posts = successMessage.data;
}, function(errorMessage) {
console.log(errorMessage);
});
This function load all the news feed informations of user followers and bring out all followers posts and then It's load individual accounts holder. But I want to apply here socket when user post a status then only followers get this status. How can I do this, any Ideas?
consider creating a Room for every online person, and then join the new and old active sockets (owned by followers) to that room.

How do I send user specific data with socket.io and laravel?

I am not sure how to word this question right, but here I go. I have laravel, angular, node w/socket.io and I am also using JWT for authentication. My end goal is to be able to send real time update notifications to specific users. For the life of me, I cannot seem to get how the workflow would be.
My initial though was to send the jwt within the handshake and then use then in node to do http requests to get data, and then return said data. In another words, when a specific event is fired, node will already have the token, send request to laravel for specific information.
Can someone please explain to me how sending user specific data via socket.io in this architecture?
I found this great article : https://www.ukietech.com/blog/programming/step-by-step-instruction-of-setting-up-real-time-secure-broadcasting-with-laravel-5-1-socket-io-and-redis/
This set me on the right track.
First I need to pass in my JWT into the socket:
var socket = io('http://192.168.10.10:3000', {query: "Authorization="+$rootScope.$storage.satellizer_token});
Next I actually verify the token.. again. I know this may be overkill, but I want to know that what hits the socket is legit.
io.use(function(socket, next){
if (socket.handshake.query.Authorization) {
var config = {
url:'http://192.168.10.10/api/auth',
headers:{
Authorization:'Bearer '+socket.handshake.query.Authorization
}
};
request.get(config,function(error,response,body){
socket.userId = JSON.parse(body).id;
next();
});
}
// call next() with an Error if you need to reject the connection.
next(new Error('Authentication error'));
});
The request in this block of code returns a user object based on the authenticated token. Refer to JWTAuth for more.
Then on connection I will assign the user to a unique channel.
io.on('connection',function(socket){
socket.join('userNotifications.'+socket.userId);
console.log('user joined room: userNotifications.'+socket.userId);
});
Then broadcast the event:
notifications.on('pmessage', function(subscribed, channel, message) {
var m = JSON.parse(message);
io.emit(channel+":"+m.event, message);
});
Back on the client side I listen for the channel. the var user is the user id.
socket.on('userNotifications.'+ user+':App\\Events\\notifications', function(message){
console.log(message);
});

MEANJS: Security in SocketIO

Situation
I'm using the library SocketIO in my MEAN.JS application.
in NodeJS server controller:
var socketio = req.app.get('socketio');
socketio.sockets.emit('article.created.'+req.user._id, data);
in AngularJS client controller:
//Creating listener
Socket.on('article.created.'+Authentication.user._id, callback);
//Destroy Listener
$scope.$on('$destroy',function(){
Socket.removeListener('article.created.'+Authentication.user._id, callback);
});
Okey. Works well...
Problem
If a person (hacker or another) get the id of the user, he can create in another application a listener in the same channel and he can watch all the data that is sends to the user; for example all the notificacions...
How can I do the same thing but with more security?
Thanks!
Some time ago I stumbled upon the very same issue. Here's my solution (with minor modifications - used in production).
We will use Socket.IO namespaces to create private room for each user. Then we can emit messages (server-side) to specific rooms. In our case - only so specific user can receive them.
But to create private room for each connected user, we have to verify their identify first. We'll use simple piece of authentication middleware for that, supported by Socket.IO since its 1.0 release.
1. Authentication middleware
Since its 1.0 release, Socket.IO supports middleware. We'll use it to:
Verify connecting user identify, using JSON Web Token (see jwt-simple) he sent us as query parameter. (Note that this is just an example, there are many other ways to do this.)
Save his user id (read from the token) within socket.io connection instance, for later usage (in step 2).
Server-side code example:
var io = socketio.listen(server); // initialize the listener
io.use(function(socket, next) {
var handshake = socket.request;
var decoded;
try {
decoded = jwt.decode(handshake.query().accessToken, tokenSecret);
} catch (err) {
console.error(err);
next(new Error('Invalid token!'));
}
if (decoded) {
// everything went fine - save userId as property of given connection instance
socket.userId = decoded.userId; // save user id we just got from the token, to be used later
next();
} else {
// invalid token - terminate the connection
next(new Error('Invalid token!'));
}
});
Here's example on how to provide token when initializing the connection, client-side:
socket = io("http://stackoverflow.com/", {
query: 'accessToken=' + accessToken
});
2. Namespacing
Socket.io namespaces provide us with ability to create private room for each connected user. Then we can emit messages into specific room (so only users within it will receive them, as opposed to every connected client).
In previous step we made sure that:
Only authenticated users can connect to our Socket.IO interface.
For each connected client, we saved user id as property of socket.io connection instance (socket.userId).
All that's left to do is joining proper room upon each connection, with name equal to user id of freshly connected client.
io.on('connection', function(socket){
socket.join(socket.userId); // "userId" saved during authentication
// ...
});
Now, we can emit targeted messages that only this user will receive:
io.in(req.user._id).emit('article.created', data); // we can safely drop req.user._id from event name itself

Resources