Socket.IO: How to emit an event to all (authenticated) users? - javascript

Here's the server code:
io.set('authorization', socketioJwt.authorize({
secret: jwtSecret,
handshake: true
}));
app.post('/login', function (req, res)
{
if((req.body.username === "test") && (req.body.password === "test"))
{
var token = jwt.sign({ username: req.body.username, password: req.body.password}, jwtSecret, { expiresInMinutes: 60*24*7 });
res.json({ token: token });
console.log(req.body.username + " logged in");
}
else
{
res.status(401).send('Wrong user or password');
}
});
io.on('connection', function(socket)
{
// test event
socket.on('ping', function (data)
{
io.emit("pong", data)
});
});
And here the client:
var server = $("#server-input").val();
var obj = { username: $("#login-input").val(), password: $("#password-input").val() };
$.post(server + "/login", obj)
.done( function(response)
{
connect_socket(response.token);
});
function connect_socket(token)
{
socket = io(server, {query: 'token=' + token});
socket.on("connect", function()
{
socket.emit("ping", {hi:"there"});
socket.on("pong", function(data)
{
console.log(data);
});
});
}
Now, when one user connects, the ping gets send and is received. When the same user connects a second time, the pong will be received on both instances, but when another user connects the pong will only be reveiced by that user. User a and b don't see eachother.
How can I fix this? Could this be a problem with the authentication?

Related

I'm building an E-commerce website, in this process, I'm facing a problem that how to send users input data from javascript to the backend

I'm building an E-commerce website, in this process, I'm facing a problem that how to send users input data from javascript to the backend.
For the backend, I'm using node.js (express).
if I get the solution for this problem, then I can store the data in the database
.mb-3
label.form-label(for='username') User name
input#username.form-control(type='text' aria-describedby='emailHelp')
.mb-3
label.form-label(for='Email') Email
input#email.form-control(type='Email')
.mb-3
label.form-label(for='mobilenumber') Enter number
input#mobilenumber.form-control(type='number')
.mb-3
label.form-label(for='password') Enter New Password
input#password.form-control(type='password')
.mb-3
label.form-label(for='confirmpassword') Confirm Password
input#confirmpassword.form-control(type='password')
.form-check.login-checkbox-container
input.bg-danger.border-danger#t-and-c-checkbox.form-check-input(type='checkbox' checked)
label.form-check-label.m-0(for='exampleCheck1') Agree To Our
a.text-danger Terms And Conditions
.form-check.login-checkbox-container
input.border-danger.form-check-input#upcoming-notification(type='checkbox')
label.form-check-label.m-0(for='exampleCheck1') recieve upcomimg offers and events mails
button.btn.btn-success#new-user-submit-btn(type='button') Submit
button.btn.btn-outline-primary#signups-login-btn(type='button') Login
Any solution for this problem
Use Ajax to send a User input data in Node server
I am give example of code to send a user input data to node server.
use Jquery and Mongodb and nodejs.
It is a simple Login page to Authentication.
Client Code:
<script>
function login() {
var name = $("#name").val();
var password = $('#password').val();
if (name !== '' && password !== '') {
$.ajax({
url: "http://localhost:3000/login",
type: 'POST',
crossDomain: true,
dataType: 'json',
data: {
name: String(name),
password: password
},
success: function(response) {
console.log(response.msg)
if (response.msg == 'verified') {
window.location.href = response.link;
} else {
alert(response.msg)
}
},
error: function(error) {
console.log(error);
}
});
} else {
alert('Please Enter UserName Password')
}
}
</script>
Server code
var app = require('express')();
var bodyParser = require('body-parser');
var http = require('http').Server(app);
var port = 3000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017";
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
})
app.post('/login', function(req, res) {
var data = req.body;
var name = data.name;
var password = data.password;
MongoClient.connect(url, function(err, db) {
if (err) throw err;
let dbo = db.db('demo-mrracer');
var query = { name: name }
dbo.collection('user_details').find(query).toArray(function(err1, result) {
if (err1) throw err1;
if (result.length > 0) {
var d = result[0].password;
if (d == password) {
console.log('user verified..');
db.close();
} else {
db.close();
res.send({ msg: 'Username or Password incorrect' })
}
} else {
db.close();
res.send({ msg: 'Please Register..' })
}
})
})
})
app.listen(port, function() {
console.log(`${port} Running Successfully..`)
})
That's it.

Unable to use the Request Body from POST

I'm trying to develop api with node.js express api for my angular web front end.This code worked when I used the params (http://localhost:5000/login/admin/00606006350066500673 ).
But I don't know why I'm getting an error while using the Request raw body data ({ strUserID: "admin" , strUserPwd: "00606006350066500673"})
router.post('/login', function (req, res, next) {
let User = {
strUserID : req.body.strUserID,
strUserPwd : req.body.strUserPwd };
function getUserPwd(strUID){
var sqlConfig = {
user: 'sa',
password: 'XXXXX',
server: 'XXXXXXXXXXXXXX.us-east-2.rds.amazonaws.com',
database: 'XXXXX'
};
sql.connect(sqlConfig, function () {
var request = new sql.Request();
var strquery = "select fUserPwd from tblUser where fUserID ='"+User.strUserID+"'"
request.query(strquery, function (err, recordset) {
return(recordset);
});
sql.close();
});
}
if ( User.strUserPwd == getUserPwd(User.strUserID)) {
let token = jwt.sign(User, global.config.secretKey, {
algorithm: global.config.algorithm,
expiresIn: '15m'
});
console.log("Token Generated : "+ token + User );
res.status(200).json({
token , User
});
}
else {
res.status(401).json({
message: 'Login Failed'
});
}
});

socket.io - Client connects to two sockets by same server

I am trying to build socket connections between React client-side and Node.js server-side. But the server will host two sockets. Here is the server-side code
var app = express();
var server = http.createServer(app);
var io = require('socket.io')(2893, {
path: "/ws",
resource: "/ws",
transports: ['websocket'],
pingTimeout: 5000
});
var redis = require('redis');
const subscriber = redis.createClient();
require('./server/route')(app, io);
require('./server/lib/subscriber')(require('socket.io').listen(server), subscriber);
The first socket connection is ok, but I wonder why the second one is not working (which is attached with listen(server). Here is subscriber module I wrote:
module.exports = (io, subscriber) => {
io.sockets.on('connection', (socket) => {
console.log(socket);
socket.on('room', (room) => {
socket.join(room);
});
});
subscriber.on('pmessage', (pattern, channel, message) => {
const msg = JSON.parse(message);
const idCallcenter = msg.idCallcenter;
return io.to(idCallcenter).emit('message', { type: channel, message: msg });
});
subscriber.psubscribe('*');
};
And the client-side React module
var socketOption = { path: "/ws", transports: ['websocket'] };
var socket = io("http://localhost:2893", socketOption);
var socket2 = io.connect("http://localhost:4004");
export default function (user) {
debugger
socket.user = user;
contact(socket);
notify(socket);
socket.on('connect', function () {
debug('socket connect', socket.id);
store.dispatch(connectNetworkSuccess());
socket.emit('user-online', {
idUser: user._id,
idCallcenter: user.idCallcenter,
email: user.email
});
});
socket2.on('connect', () => {
debug('Socket connected');
socket2.emit('room', user.idCallcenter);
});
socket2.on('message', (data) => {
debugger
debug('Socket message');
debug(data);
const type = data.type;
const message = data.message;
if (type === 'recordFetched') {
}
});
socket.emit('user-online', {
idUser: user._id,
idCallcenter: user.idCallcenter,
email: user.email
});
socket.on('disconnect', function (reason) {
debug('socket disconnect', reason);
store.dispatch(connectNetworkFailed());
});
}
The first socket (in port 2893) runs normally. Meanwhile, socket2 (in port 4004) does not connect. It does not jump into connection callback of both server and client sides. What did I do wrong here?
I solved the case myself. The working code on client side is:
export default function (user) {
debugger
var socketOption = { path: "/ws", transports: ['websocket'] };
var socket = env === "local" ? io("http://localhost:2893", socketOption) : io(window.location.origin, socketOption);
var socket2 = io.connect();
socket.user = user;
contact(socket);
notify(socket);
socket.on('connect', function () {
debug('socket connect', socket.id);
store.dispatch(connectNetworkSuccess());
socket.emit('user-online', {
idUser: user._id,
idCallcenter: user.idCallcenter,
email: user.email
});
});
socket2.on('connect', () => {
console.log('Socket connected');
socket2.emit('room', user.idCallcenter);
});
socket2.on('message', (data) => {
debugger
console.log('Socket message', data);
const type = data.type;
const message = data.message;
if (type === 'recordFetched') {
}
});
socket.emit('user-online', {
idUser: user._id,
idCallcenter: user.idCallcenter,
email: user.email
});
socket.on('disconnect', function (reason) {
debug('socket disconnect', reason);
store.dispatch(connectNetworkFailed());
});
}
The server did jump into connection callback, but not room callback. I suppose it is because the connect callback of client side was defined after the connection is made, so that it couldn't jump into it. This is my possibility. Am I right?

Nodejs only specific logged users can get message

when users online and don't close our clients such as browser tab or android application, i can send message to each specific user by
socket.broadcast.to(socketId)
.emit('new message', {
username: data.fromUsername,
money : 'Hurrraaa'
});
when users close clients as mobile application this event don't trigger but i can send any message to broadcast as:
socket.broadcast.emit('new message', "hooooorrrrraaaaa");
my users don't use client application any time, but i need to send message to some specific user and notify user until opening application and see message, users should be on'time in my application to get every message which i want to send from server like with Chat messengers which don't need users currently are using application such as WhatsApp, how can i resolve this problem?
then problem is send message to some specific users when they are istalled application and logged ti sever, but not using now and application waiting to receive message such as broadcast or special message to himself
this code is my simplified server:
var socket = require('socket.io'),
express = require('express'),
app = express(),
server = require('http').createServer(app),
io = socket.listen(server),
port = process.env.PORT || 3000,
mysql = require('mysql'),
uuid = require('node-uuid'),
datetime = require('node-datetime'),
moment = require('moment'),
bcrypt = require('bcrypt'),
async = require('async'),
request = require('request'),
redis = require("redis"),
redisClient = redis.createClient(),
forever = require('forever'),
log = require('log4node');
var io_redis = require('socket.io-redis');
io.adapter(io_redis({host: 'localhost', port: 6379}));
require('sticky-socket-cluster/replace-console')();
var options = {
workers : require('os').cpus().length,
first_port : 8000,
proxy_port : 3000,
session_hash: function (req, res) {
return req.connection.remoteAddress;
},
no_sockets: false
};
require('sticky-socket-cluster')(options, start);
function start(port) {
io.sockets.on('connection', function (socket) {
socket.on('new message', function (data) {
socket.broadcast.emit('new message', "hooooorrrrraaaaa");
});
socket.on('login', function (data) {
log.info(JSON.stringify(data))
login(data.username, data.password, function (success, value) {
if (success) {
redisClient.exists(data.username, function (err, doesExist) {
if (err) return;
if (!doesExist) {
redisClient.set(data.username, socket.id, function (err, res) {
redisClient.set(data.username, socket.id);
});
}
else {
redisClient.del(data.username);
redisClient.set(data.username, socket.id, function (err, res) {
redisClient.set(data.username, socket.id);
});
}
});
socket.emit('login', {
result : true,
id : value.id,
registeredMobileNumber: value.registeredMobileNumber
});
} else {
socket.emit('login', {result: false});
}
});
});
socket.on('userConnected', function (username) {
redisClient.exists(username, function (err, doesExist) {
if (err) return;
if (!doesExist) {
redisClient.set(username, socket.id, function (err, res) {
redisClient.set(username, socket.id);
});
}
else {
redisClient.del(username);
redisClient.set(username, socket.id, function (err, res) {
redisClient.set(username, socket.id);
});
}
});
});
socket.on('disconnectUser', function (data) {
redisClient.exists(data.username, function (err, doesExist) {
if (err) return;
if (doesExist) {
redisClient.del(data.username);
}
});
});
server.listen(port, function () {
console.log('Express and socket.io listening on port ' + port);
});
}
You can use socket.on('disconnect', function() {});
When a User disconnects , save the users user_id.
Subsequent message on the user_id would be saved in the server.
When the client reconnects again get the time of the latest message and then push the message after that time (saved in the server) to the client.

Express js routing error ("Cannot GET /")

I am having a hard time wondering why, when i access my HTTP server http://localhost:8000/, i get a "Cannot GET /" message. I use express js for routing server side and angular at client-side.
I have read that this error is there because i haven't set a route for "/" path, but i don't want to route anything there, just want to let my angular handle "/".
FYI, my express server is in a different path than the angular app.
MY node code:
var bcrypt = require('bcryptjs');
var bodyParser = require('body-parser');
var cors = require('cors');
var express = require('express');
var jwt = require('jwt-simple');
var moment = require('moment');
var mongoose = require('mongoose');
var path = require('path');
var request = require('request');
var compress = require('compression');
var config = require('./config');
var User = mongoose.model('User', new mongoose.Schema({
instagramId: { type: String, index: true },
email: { type: String, unique: true, lowercase: true },
password: { type: String, select: false },
username: String,
fullName: String,
picture: String,
accessToken: String
}));
mongoose.connect(config.db);
var app = express();
app.set('port', process.env.PORT || 8000);
app.use(compress());
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public'), { maxAge: 2628000000 }));
/*
|--------------------------------------------------------------------------
| Login Required Middleware
|--------------------------------------------------------------------------
*/
function isAuthenticated(req, res, next) {
if (!(req.headers && req.headers.authorization)) {
return res.status(400).send({ message: 'You did not provide a JSON Web Token in the Authorization header.' });
}
var header = req.headers.authorization.split(' ');
var token = header[1];
var payload = jwt.decode(token, config.tokenSecret);
var now = moment().unix();
if (now > payload.exp) {
return res.status(401).send({ message: 'Token has expired.' });
}
User.findById(payload.sub, function(err, user) {
if (!user) {
return res.status(400).send({ message: 'User no longer exists.' });
}
req.user = user;
next();
})
}
/*
|--------------------------------------------------------------------------
| Generate JSON Web Token
|--------------------------------------------------------------------------
*/
function createToken(user) {
var payload = {
exp: moment().add(14, 'days').unix(),
iat: moment().unix(),
sub: user._id
};
return jwt.encode(payload, config.tokenSecret);
}
/*
|--------------------------------------------------------------------------
| Sign in with Email
|--------------------------------------------------------------------------
*/
app.post('/auth/login', function(req, res) {
User.findOne({ email: req.body.email }, '+password', function(err, user) {
if (!user) {
return res.status(401).send({ message: { email: 'Incorrect email' } });
}
bcrypt.compare(req.body.password, user.password, function(err, isMatch) {
if (!isMatch) {
return res.status(401).send({ message: { password: 'Incorrect password' } });
}
user = user.toObject();
delete user.password;
var token = createToken(user);
res.send({ token: token, user: user });
});
});
});
/*
|--------------------------------------------------------------------------
| Create Email and Password Account
|--------------------------------------------------------------------------
*/
app.post('/auth/signup', function(req, res) {
User.findOne({ email: req.body.email }, function(err, existingUser) {
if (existingUser) {
return res.status(409).send({ message: 'Email is already taken.' });
}
var user = new User({
email: req.body.email,
password: req.body.password
});
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(user.password, salt, function(err, hash) {
user.password = hash;
user.save(function() {
var token = createToken(user);
res.send({ token: token, user: user });
});
});
});
});
});
/*
|--------------------------------------------------------------------------
| Sign in with Instagram
|--------------------------------------------------------------------------
*/
app.post('/auth/instagram', function(req, res) {
var accessTokenUrl = 'https://api.instagram.com/oauth/access_token';
var params = {
client_id: req.body.clientId,
redirect_uri: req.body.redirectUri,
client_secret: config.clientSecret,
code: req.body.code,
grant_type: 'authorization_code'
};
// Step 1. Exchange authorization code for access token.
request.post({ url: accessTokenUrl, form: params, json: true }, function(error, response, body) {
// Step 2a. Link user accounts.
if (req.headers.authorization) {
User.findOne({ instagramId: body.user.id }, function(err, existingUser) {
var token = req.headers.authorization.split(' ')[1];
var payload = jwt.decode(token, config.tokenSecret);
User.findById(payload.sub, '+password', function(err, localUser) {
if (!localUser) {
return res.status(400).send({ message: 'User not found.' });
}
// Merge two accounts. Instagram account takes precedence. Email account is deleted.
if (existingUser) {
existingUser.email = localUser.email;
existingUser.password = localUser.password;
localUser.remove();
existingUser.save(function() {
var token = createToken(existingUser);
return res.send({ token: token, user: existingUser });
});
} else {
// Link current email account with the Instagram profile information.
localUser.instagramId = body.user.id;
localUser.username = body.user.username;
localUser.fullName = body.user.full_name;
localUser.picture = body.user.profile_picture;
localUser.accessToken = body.access_token;
localUser.save(function() {
var token = createToken(localUser);
res.send({ token: token, user: localUser });
});
}
});
});
} else {
// Step 2b. Create a new user account or return an existing one.
User.findOne({ instagramId: body.user.id }, function(err, existingUser) {
if (existingUser) {
var token = createToken(existingUser);
return res.send({ token: token, user: existingUser });
}
var user = new User({
instagramId: body.user.id,
username: body.user.username,
fullName: body.user.full_name,
picture: body.user.profile_picture,
accessToken: body.access_token
});
user.save(function() {
var token = createToken(user);
res.send({ token: token, user: user });
});
});
}
});
});
app.get('/api/feed', isAuthenticated, function(req, res) {
var feedUrl = 'https://api.instagram.com/v1/users/self/feed';
var params = { access_token: req.user.accessToken };
request.get({ url: feedUrl, qs: params, json: true }, function(error, response, body) {
if (!error && response.statusCode == 200) {
res.send(body.data);
}
});
});
app.get('/api/media/:id', isAuthenticated, function(req, res) {
var mediaUrl = 'https://api.instagram.com/v1/media/' + req.params.id;
var params = { access_token: req.user.accessToken };
request.get({ url: mediaUrl, qs: params, json: true }, function(error, response, body) {
if (!error && response.statusCode == 200) {
res.send(body.data);
}
});
});
app.post('/api/like', isAuthenticated, function(req, res) {
var mediaId = req.body.mediaId;
var accessToken = { access_token: req.user.accessToken };
var likeUrl = 'https://api.instagram.com/v1/media/' + mediaId + '/likes';
request.post({ url: likeUrl, form: accessToken, json: true }, function(error, response, body) {
if (response.statusCode !== 200) {
return res.status(response.statusCode).send({
code: response.statusCode,
message: body.meta.error_message
});
}
res.status(200).end();
});
});
app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
In that case, then you should catch all the routes in / to angular.
Put this code at the very last of your route definitions before error handlers.
app.get('*', function (req, res) {
res.sendFile('/path/to/angular/index.html');
});
As you are using Angular for your web app, you would want your express server to serve all the files related to the front-end so when you land on the link "http://localhost:8000/", Express would serve the related files back. This folder would include .js, .css and .html files as well as all the other resources (images, videos etc.) so you can link them in your markup. (eg link href="/logo.png").
You can serve these files using Express by telling express to use the Static Middleware.
Using the Middleware, you would tell Express to serve the contents of a specific folder as static resources. Putting your Angular App in the folder would then let Angular handle the routes.
var publicFolder = path.join(__dirname, '../client')
app.use(express.static(publicFolder);
You would register other endpoints to create an API for your web app. So express server would be able to provide data to the Angular app through those endpoints.

Categories

Resources