I am building an Expo App for IOS Phone. I have added login page which provides reset password mechanism. I have used Node.js program to reset the password and the new resetted password is saved as hash password using bcrypt (ex: $2b$05$cMUtC/1WHxzGNqDTJcCBJOf9i7D6ad57jKyYqChLF0Vvji1A2mzIq for Test123456) inside Mysql database. This is working well and good. Below is the node.js program:
users.js:
var express = require('express');
var router = express.Router();
var connection = require('../database.js');
var nodemailer = require('nodemailer');
var bcrypt = require('bcrypt');
var randtoken = require('rand-token');
//send email
function sendEmail(email, token) {
var email = email;
var token = token;
var mail = nodemailer.createTransport({
service: 'gmail',
auth: {
user: '*******#gmail.com', // Your email id
pass: '*******' // Your password
}
});
var mailOptions = {
from: 'abc#tech.com',
to: email,
subject: 'Reset Password Link - Tutsmake.com',
html: '<p>You requested for reset password, kindly use this link to reset
your password</p>'
};
mail.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(1)
} else {
console.log(0)
}
});
}
/* home page */
router.get('/', function(req, res, next) {
res.render('index', {
title: 'Forget Password Page'
});
});
/* send reset password link in email */
router.post('/reset-password-email', function(req, res, next) {
var email = req.body.email;
connection.query('SELECT * FROM JTGDB.UserInfo WHERE email ="' + email + '"',
function(err, result) {
if (err) throw err;
var type = ''
var msg = ''
console.log(result[0]);
if (result[0].Email.length > 0) {
var token = randtoken.generate(20);
var sent = sendEmail(email, token);
if (sent != '0') {
var data = {
token: token
}
connection.query('UPDATE JTGDB.UserInfo SET ? WHERE email ="' + email + '"', data,
function(err, result) {
if(err) throw err
})
type = 'success';
msg = 'The reset password link has been sent to your email address';
} else {
type = 'error';
msg = 'Something goes to wrong. Please try again';
}
} else {
console.log('2');
type = 'error';
msg = 'The Email is not registered with us';
}
req.flash(type, msg);
res.redirect('/');
});
})
/* reset page */
router.get('/reset-password', function(req, res, next) {
res.render('reset-password', {
title: 'Reset Password Page',
token: req.query.token
});
});
/* update password to database */
router.post('/update-password', function(req, res, next) {
var token = req.body.token;
var password = req.body.password;
connection.query('SELECT * FROM JTGDB.UserInfo WHERE token ="' + token + '"',
function(err, result) {
if (err) throw err;
var type
var msg
if (result.length > 0) {
var saltRounds = 5;
bcrypt.genSalt(saltRounds, function(err, salt) {
bcrypt.hash(password, salt, function(err, hash) {
var data = {
password: hash
}
connection.query('UPDATE JTGDB.UserInfo SET ? WHERE email ="' + result[0].Email +
'"', data, function(err, result) {
if(err) throw err
});
});
});
type = 'success';
msg = 'Your password has been updated successfully';
} else {
console.log('2');
type = 'success';
msg = 'Invalid link; please try again';
}
req.flash(type, msg);
res.redirect('/');
});
})
module.exports = router;
But in Expo App, I want to hash the password that we enter in the login page and compare with the database hash password and then let the user to log into the App.
I have added a post request in app.js to get password from expo app and convert to hash code and compare it with database password to let user log in.Below is the app.js code .
app.js:
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var flash = require('express-flash');
var session = require('express-session');
var bodyParser = require('body-parser');
const createError = require('http-errors');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var bcrypt = require('bcrypt');
var app = express();
/* hash password from database to expo App */
app.post('/hash-password', function(req, res, next) {
const password = req.body.password;
console.log('Password is '+password)
var saltRounds = 5;
//var hash = bcrypt.hash(password, saltRounds);
bcrypt.genSalt(saltRounds, function(err, salt) {
bcrypt.hash(password, salt, function(err, hash) {
var data = {
password: hash
}
console.log(data);
})
})
})
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
secret: '********',
resave: false,
saveUninitialized: true,
cookie: { maxAge: 60000 }
}))
app.use(flash());
app.use('/', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err :
{};
// render the error page
res.status(err.status || 500);
res.render('error');
});
app.listen(4000, function () {
console.log('Node app is running on port 4000');
});
module.exports = app;
I checked the code by sending password from postman ,but I am getting the below error:
Related
I'm trying to test a OAuth2 passport setup and I found this package.
https://www.npmjs.com/package/oauth2-mock-server
I'm trying to return a profile object using it but with no success.
Has anyone used this package ?
How would I pass back a profile object ?
My mock setup:
const { OAuth2Server } = require("oauth2-mock-server");
const request = require("request");
async function startServer() {
let server = new OAuth2Server();
await server.issuer.keys.generate("RS256");
await server.start(3003, "localhost");
server.service.once("beforeResponse", (tokenEndpointResponse, req) => {
console.log("tokenEndpointResponse = ", tokenEndpointResponse);
tokenEndpointResponse.body = {
...tokenEndpointResponse.body,
scope: { profile: { id: "xxx" } },
};
});
server.service.once(
"beforeAuthorizeRedirect",
(authorizeRedirectUri, req) => {
console.log("THIS WAS TRIGGERED >>>> = ", authorizeRedirectUri);
}
);
}
startServer();
My OAuth2Strategy
const strategy = new OAuth2Strategy(
{
state: true,
authorizationURL: `${process.env.MOCK_AUTH_SERVER_URL}/authorize`,
tokenURL: `${process.env.MOCK_AUTH_SERVER_URL}/token`,
clientID: "xxx",
clientSecret: "xxx",
callbackURL: `${process.env.SERVER_URL}/callback`,
passReqToCallback: true,
},
async (accessToken, refershToken, profile, done) => {
console.log("profile = ", profile);
if (profile) {
return done(null, profile);
}
}
);
I keep getting back a string for profile but wanted the profile object ??
I've created an Ionic chat app with firebase cloud functions. The push notifications are working with Android but not ios.
async getIosToken(token: string, userId: string): Promise<void> {
if (!FCM.hasPermission()) {
FCM.requestPushPermission()
.then(async (hasPerm) => {
if (hasPerm) {
const iosToken = await FCM.getAPNSToken();
if (iosToken === token) {
return;
} else {
this.saveToken(iosToken, userId);
}
}
});
} else {
const iosToken = await FCM.getAPNSToken();
if (iosToken === token) {
return;
} else {
this.saveToken(iosToken, userId);
}
}
}
saveToken(token: string, userId: string): void {
this.userSvc.saveTokenToFirestore(token, userId)
.then(() => {
this.storageSvc.setDeviceToken(token);
});
}
The iOS token is being saved to firebase...although it never prompted the user for request permissions.
I console logged the firebase cloud function and I can see the APNs token.
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();
exports.newChatNotification = functions.firestore
.document(`chat/{id}/messages/{doc}`)
.onWrite(async event => {
const message = event.after.data();
let data: any;
let device: any;
const db = admin.firestore();
console.log('message', message);
console.log('db', db);
if (message) { data = message; }
const receivingUserId = data ? data.receivingUserId : '';
const content = data ? data.content : '';
const sendingUserId = data ? data.sendingUserId : '';
console.log('payload', receivingUserId, sendingUserId);
const payload = {
notification: {
title: 'New message',
body: `${content}`,
click_action: 'FCM_PLUGIN_ACTIVITY'
},
data: {
page: 'tabs/travel-buddies',
}
};
console.log('payload2', payload);
const devicesRef = (await db.collection('devices').doc(`${receivingUserId}`).get()).data();
if (devicesRef) { device = devicesRef; }
const token = device ? device.token : '';
console.log('devicesRef', devicesRef, token);
return admin.messaging().sendToDevice(token, payload);
});
Here's the firebase cloud function console
I'm not sure how to troubleshoot why ios is not receiving a push notification because there aren't any errors and I'm getting the APNs token.
I've also tried updating the build system per Google searches online:
Any help would be greatly appreciated.
I'm trying to link a user within 'Pre Signup Trigger' using adminLinkProviderForUser.
I can merge by setting the following in the parameter of adminLinkProviderForUser.
const params = {
DestinationUser: {
ProviderAttributeValue: username,
ProviderName: 'Cognito'
},
SourceUser: {
ProviderAttributeName: 'Cognito_Subject',
ProviderAttributeValue: providerUserId,
ProviderName: 'Google'
},
UserPoolId: userPoolId
}
But, I get an error when I try to merge the Cognito user (email/password) by first creating a Google account as follows.
const params = {
DestinationUser: {
ProviderAttributeValue: username,
ProviderName: 'Google'
},
SourceUser: {
ProviderAttributeName: 'Cognito_Subject',
ProviderAttributeValue: providerUserId,
ProviderName: 'Cognito'
},
UserPoolId: userPoolId
}
If I created a Google account first, is there a way to merge the cognito user (email / password) created later?
All the code currently written in Lambda. (I'm having trouble with the FIXME part.)
'use strict';
const AWS = require('aws-sdk');
const cognitoIdp = new AWS.CognitoIdentityServiceProvider();
const getUserByEmail = async (userPoolId, email) => {
const params = {
UserPoolId: userPoolId,
Filter: `email = "${email}"`
}
return cognitoIdp.listUsers(params).promise()
}
const linkProviderToUser = async (username, baseProviderName, userPoolId, providerUserName, providerName, providerUserId) => {
const params = {
DestinationUser: {
ProviderAttributeValue: username,
ProviderName: baseProviderName
},
SourceUser: {
ProviderAttributeName: providerUserName,
ProviderAttributeValue: providerUserId,
ProviderName: providerName
},
UserPoolId: userPoolId
}
const result = await (new Promise((resolve, reject) => {
cognitoIdp.adminLinkProviderForUser(params, (err, data) => {
if (err) {
reject(err)
return
}
resolve(data)
})
}))
return result
}
exports.handler = async (event, context, callback) => {
console.log(event)
if (event.triggerSource == 'PreSignUp_ExternalProvider') {
const userRs = await getUserByEmail(event.userPoolId, event.request.userAttributes.email)
if (userRs && userRs.Users.length > 0) {
let [ providerName, providerUserId ] = event.userName.split('_') // event userName example: "Facebook_12324325436"
providerName = providerName === 'google' ? 'Google' : providerName
await linkProviderToUser(userRs.Users[0].Username, 'Cognito' ,event.userPoolId, 'Cognito_Subject', providerName, providerUserId)
} else {
console.log('Users Not Found. This process skip.')
}
}
if (event.triggerSource == 'PreSignUp_SignUp') {
const userRs = await getUserByEmail(event.userPoolId, event.request.userAttributes.email)
if (userRs && userRs.Users.length > 0) {
// FIXME: This will be executed if the Cognito user is created later.I want to set parameters appropriately and merge with Google account users.
} else {
console.log('Users Not Found. This process skip.')
}
}
return callback(null, event)
}
According to the AWS documentation for the AdminLinkProviderForUser action, you cannot link a native Cognito email/password user to any existing user. Only federated users from external IdPs can be linked.
Definition for the SourceUser parameter:
An external IdP account for a user who doesn't exist yet in the user
pool. This user must be a federated user (for example, a SAML or
Facebook user), not another native user.
Is that possible to upload any file(doc,pdf,img) in xamarin android using web service in c#. i am using sql server for data connection.
Use MediaFile from the Xamarin.Plugins.Media Library.
public static void upload(MediaFile mediaFile)
{
try
{
StreamContent scontent = new StreamContent(mediaFile.GetStream());
scontent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
FileName = "newimage",
Name = "image"
};
scontent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
var client = new HttpClient();
var multi = new MultipartFormDataContent();
multi.Add(scontent);
client.BaseAddress = new Uri(Constants.API_ROOT_URL);
var result = client.PostAsync("api/photo", multi).Result;
Debug.WriteLine(result.ReasonPhrase);
}
catch (Exception e)
{
Debug.WriteLine(e);
}
}
And node.js code to receive request.
var formidable = require('formidable');
var util = require('util');
var fs = require('fs');
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads');
},
filename: function (req, file, callback) {
console.log(file.fieldname);
callback(null, file.fieldname + '-' + Date.now());
}
});
var upload = multer({ storage: storage }).single('image');
exports.post = function (req, res) {
upload(req, res, function (err) {
console.log(req.file);
if (err) {
console.log("ERROR : "+err);
return res.end("Error uploading file.");
}
console.log("SUCCESS");
res.end("File is uploaded");
});
};
See complete information from below thread
https://forums.xamarin.com/discussion/18649/best-practice-to-upload-image-selected-to-a-web-api
https://forums.xamarin.com/discussion/5033/upload-file-from-device-to-server
I am using SocketIO and redis based on the following code,
var sub = redis.createClient();
var pub = redis.createClient();
sub.subscribe('chat');
io.use(socketHandshake({store: sessionStore, key:'jsessionid', secret:'secret', parser:cookieParser()}));
io.on('connection', function (socket) {
socket.on('chat', function (message) {
// io.emit('chat', "hello world");
pub.publish('chat', "hello world");
});
sub.on('message', function (channel, message) {
io.emit(channel, message);
});
});
This is the base code. I have modified the code so that if any user goes offline, in server side I am storing the messages in RSMQ(Redis Simple Message Queue) and when user comes online, the message is fetched from queue and emits to the user.I have used the following code to achieve this.I have stored the user status in an array.
var fs = require('fs')
, http = require('http')
, socketio = require('socket.io');
var redis = require('redis');
var store = redis.createClient();
var pub = redis.createClient();
var sub = redis.createClient();
RedisSMQ = require("rsmq");
rsmq = new RedisSMQ( {host: "127.0.0.1", port: 6379, ns: "rsmq"} );
var active_users=[];
var inactive_users=[];
var user_status=[];
var channel_users=[];
var users_queue=[];
var socket_ids=[];
var cname,qn;
var clients=[];
var server = http.createServer(function(req, res) {
res.writeHead(200, { 'Content-type': 'text/html'});
res.end(fs.readFileSync(__dirname + '/index.html'));
}).listen(9000, function() {
console.log('Listening at: http://localhost:9000');
});
socketio.listen(server).on('connection', function (socket) {
socket.on('login', function(data){
console.log('a user ' + data.userId + ' connected'+socket.id);
//saving userId to array with socket ID
active_users[socket.id] = data.userId;
socket_ids[data.userId]=socket.id;
clients[socket.id] = socket;
user_status[data.userId]="online";
});
socket.on('message', function (msg) {
console.log('Message Received: ', msg);
socket.broadcast.emit('message', msg);
});
socket.on('json', function (msg) {
if(msg.channel_name=='UserState'){
rsmq.listQueues(function(err,resp){
//console.log("QUEUES LIST"+resp);
});
if(msg.user_state=='active'){
store.hmset("active_users."+msg.sender_id,{"user":"online"});
user_status[msg.sender_id]="online";console.log(user_status);
if(users_queue[msg.sender_id]!=undefined && users_queue[msg.sender_id].length>0){
console.log("USERS QUEUE:"+users_queue[msg.sender_id]['0']);
for(var i=0;i<users_queue[msg.sender_id].length;i++){
cname=users_queue[msg.sender_id][i].split('_')[0];//get channel name from queue name
qn=users_queue[msg.sender_id][i];
rsmq.getQueueAttributes({qname:users_queue[msg.sender_id][i]},function(err,resp){
console.log("RESP:"+resp.msgs);
if(resp.msgs>0){ //if there are messages in queue......
for(var j=0;j<resp.msgs;j++){
rsmq.popMessage({qname:qn},function(err,resp){
console.log(resp);
var sid=socket_ids[msg.sender_id]; console.log("SOCKETID:"+sid); //get socket.id for the user
pub.publish(cname,resp.message);
});
}
}
});
}
}
}
else{
store.hmset("active_users."+msg.sender_id,{"status":"offline"});
user_status[msg.sender_id]="offline";
}
}
if(msg.channel_name=='ShareConversation'){
var channel=msg.conversations_data.conversation_id;//have to change to conversation_id or whatever channel.....
sub.subscribe(channel);
channel_users[channel]=[];
var m=msg.conversations_data.users.split(',');
for(var i=0;i<m.length;i++){
channel_users[channel].push(m[i]);
}
for(var i=0;i<channel_users[channel].length;i++){
var q=channel_users[channel][i].split('#')[0].replace(/(^\s+|\s+$)/g, '');
var queue_name=channel+"_"+q;console.log(queue_name);
var uname=channel_users[channel][i].replace(/(^\s+|\s+$)/g, '');
users_queue[uname]=[];
users_queue[uname].push(queue_name);
rsmq.createQueue({qname:queue_name}, function (err, resp) {
console.log(err);
console.log(queue_name);
if (resp===1) {
console.log("queue created");
}
});
}
}
socket.broadcast.emit('json', msg);
});
sub.on('message', function (channel, message) {
console.log("Message: " + message);
for(var i=0;i<channel_users[channel].length;i++){
var c=channel_users[channel][i].replace(/(^\s+|\s+$)/g, '');console.log("channel_users:"+channel_users[channel][i]);console.log("USER STATE :"+ user_status[c]);
if(user_status[c]=='offline'){
//send notification.........
//put messages in queue.......
var q=channel_users[channel][i].split('#')[0].replace(/(^\s+|\s+$)/g, '');
var queue_name=channel+"_"+q;console.log(queue_name);
rsmq.sendMessage({qname:queue_name, message:message}, function (err, resp) {
console.log(err);
if (resp) {
console.log("Message sent. ID:", resp);
}
});
}
}
socket.emit(channel, message);
});
});
This is my entire code. Here the issue is when the user goes offline, the message gets saved in queue multiple times and when the user comes online, the messages are received multiple times as there are duplicate messages saved in queue. How to overcome this.Please help....