I am trying to get a REST API to return currentSession() from AWS Amplify and Cognito. The SignIn function works and i get a CognitoUser object returned, however, the getSession() function returns "No current user"
const Amplify = require('aws-amplify');
const express = require('express');
const router = express.Router();
Amplify.default.configure({
Auth: {
region: 'REGION',
userPoolId: 'USERPOOLID',
userPoolWebClientId: 'WEBCLIENTID',
authenticationFlowType: 'AUTHTYPE',
}
})
router.post('/', (req, res) => {
async function signIn(username, password) {
try {
Amplify.Auth.signIn(username, password)
.then(() => getSession())
.catch(err => console.log(err));
} catch (error) {
res.json(error);
}
}
async function getSession() {
try {
Amplify.Auth.currentSession()
.then(data => console.log(data))
.catch(err => console.log(err));
} catch (error) {
res.json('error');
}
}
signIn(req.body.u, req.body.p);
});
Help!
Related
I'm trying to make a POST request to my database. However, when I use Postman to test if the request is being made, it's giving me back an error,
Cannot POST /api/grocery
I'm using Model, View, Controller for my project. This is my index file
const express = require('express')
const app = express()
const port = 3000
const groceryController = require('./Controller/controllerGrocery.js')
app.use(express.urlencoded({extended: true}));
app.post('api/grocery', (req, res) => {
groceryController.addGrocery(req, res)
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
This is my controller file
const models = require('../Model/modelGrocery.js')
const addGrocery = (req, res) => {
const addGrocery = (err) => {
if (err) {
res.status(500).send()
} else {
res.status(201).end();
}
}
models.addGrocery(req.body, addGrocery)
}
module.exports = {
addGrocery: addGrocery
}
This is my model file that I'm connecting to the database
var db = require('../../DB/db.js');
const getGrocery = (doNext) => {
//query the database
db.find()
.then(result => doNext(null, result))
.catch(err => doNext(err))
//callback
}
const addGrocery = (grocery, callback) => {
db.insertOne({
item: grocery.item,
quantity: grocery.quantity
})
.catch(err => callback(err))
}
module.exports = {
addGrocery: addGrocery
}
Change API Path from api/grocery to /api/grocery
app.post('/api/grocery', (req, res) => {
groceryController.addGrocery(req, res)
})
I am trying to run a integration test for one of the express routes in the application.
The routed is a protected route allows user to create supplier when user is authenticated.
I am trying to login user before making a request to the 'api/v1/supplier' (protected route) route but not able to login user before calling the Login API give 500 error back, the Login API is working as expected when tested separately.
Here is the test that I am trying. request help!
process.env.NODE_ENV = 'development';
const expect = require('chai').expect;
const request = require('supertest');
const app = require('../../../app.js');
const conn = require('../../../db/index.js');
describe('POST /api/v1/supplier ', () => {
let token = '';
before(done => {
conn
.connect()
.then(done())
.catch(err => done(err));
});
after(done => {
conn
.close()
.then(done())
.catch(err => done(err));
});
it('Error, on unauthorized POST Supplier request', done => {
request(app)
.post('/api/v1/users/login')
.send({ email: 'sgrmhdk00#gmail.com', password: '12345678' })
.end(function(err, res) {
token = res.body.token;
});
request(app)
.post('/api/v1/supplier')
.set('Authorization', 'Bearer' + token)
.send({ supplierID: '1234567' })
.then(res => {
const body = res.body;
expect(body).to.contain.property('status');
expect(body).to.contain.property('error');
done();
})
.catch(err => done(err));
});
});
db/index.js
const dotenv = require('dotenv');
const mongoose = require('mongoose');
const DB_URI = 'mongodb://localhost:27017/myapp';
function connect() {
return new Promise((resolve, reject) => {
dotenv.config({ path: './config.env' });
const setDatabase = () => {
if (process.env.NODE_ENV === 'development') {
const DB = process.env.DATABASE;
return DB;
} else {
const DB = process.env.DATABASE_PRODUCTION.replace(
'<PASSWORD>',
process.env.DATABASE_PASSWORD
);
return DB;
}
};
const DB = setDatabase();
mongoose
.connect(DB, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false
})
.then(() => console.log('DB connection successful!'));
});
}
function close() {
return mongoose.disconnect();
}
module.exports = { connect, close };
You need to call you API with token, but the two calls are asynchronous, you need call the second method inside the end of the first:
it('Error, on unauthorized POST Supplier request', done => {
request(app)
.post('/api/v1/users/login')
.send({ email: 'sgrmhdk00#gmail.com', password: '12345678' })
.end(function(err, res) {
if(err){
done(err)
return
}
token = res.body.token;
request(app)
.post('/api/v1/supplier')
.set('Authorization', 'Bearer' + token)
.send({ supplierID: '1234567' })
.then(res => {
const body = res.body;
expect(body).to.contain.property('status');
expect(body).to.contain.property('error');
done();
})
.catch(err => done(err));
});
});
So i want to fetch from db using asyncdata and axios, Here's the code, The problem is that no request is sent, And i'm wondering if someone can help me catch the error.
async asyncData({ $axios, store }) {
try {
let profile = await $axios.$get('/profile', store.state.auth.id)
return { profile }
} catch (error) {
console.log(error.message)
}
},
router.get('/profile', async (req, res) => {
const { userId } = req.body
try {
const profileUser = await User.findById(userId)
res.send(profileUser)
} catch (e) {
console.log(e)
res.status(400).json(e.message)
}
})
You may need to modify your route to the following, if you want to pass the id as parameter
router.get('/profile/:id', async (req, res) => {
const { userId } = req.params.id;
try {
const profileUser = await User.findById(userId)
res.send(profileUser)
} catch (e) {
console.log(e)
res.status(400).json(e.message)
}
})
and add profile id as route parameter
async asyncData({ $axios, store }) {
try {
let profile = await $axios.get('/profile/{profile_id_here}')
return { profile }
} catch (error) {
console.log(error.message)
}
}
Otherwise, if you want to get the id of the authenticated user (may be resolved from a Bearer token), it needs to be set to the request object in you authentication middleware.
In your authentication middleware,
const user = await _authService.validateFromToken(bearerToken);
if (user) {
req.user = user;
}
then you can access authenticated user as,
router.get('/profile', async (req, res) => {
const { userId } = req.user._id;
try {
const profileUser = await User.findById(userId)
res.send(profileUser)
} catch (e) {
console.log(e)
res.status(400).json(e.message)
}
})
I have an issue with function which update password. What I would like to have is a function which will update logged user data.
export const updateMe = async (req, res, next) => {
if (!req) {
res.status(400).end()
}
try {
const updatedDoc = await User.findById(req.user._id, function(err, doc) {
if (err) return next(err)
doc.password = req.body.password
doc.save()
})
.lean()
.exec()
res.status(200).json({ data: updatedDoc })
} catch (e) {
console.log(e)
res.status(400).end()
}
}
I have written middleware which will hash password before it will be saved.
userSchema.pre('save', function(next) {
if (!this.isModified('password')) {
return next()
}
bcrypt.hash(this.password, 8, (err, hash) => {
if (err) {
return next(err)
}
this.password = hash
next()
})
})
I do not know why error is always reciving with message "doc.save() is not a funcition"
You are mixing promise and await code, also doc.save() returns a promise so you need to await it.
( I assume you are already setting req.user._id in a middleware, and it is not null.)
So your method must be like this if async/await is used:
export const updateMe = async (req, res, next) => {
if (!req.body.password) {
return res.status(400).send("Password is required");
}
try {
let updatedDoc = await User.findById(req.user._id);
updatedDoc.password = req.body.password;
updatedDoc = await updatedDoc.save();
res.status(200).json({ data: updatedDoc });
} catch (e) {
console.log(e);
res.status(400);
}
};
I'm using the best practice MongoDB with Lambda example from here https://docs.atlas.mongodb.com/best-practices-connecting-to-aws-lambda/
I need to publish to SNS but are unable to due to the callbackWaitsForEmptyEventLoop = false, if I uncomment this, it works fine but then my Lambda function just times out and never receive the success callback.
"use strict";
const MongoClient = require('mongodb').MongoClient;
const MONGODB_URI = process.env.MONGODB_URI; // or Atlas connection string
const AWS = require('aws-sdk');
const SNS_TOPICARN = process.env.SNS_TOPICARN;
const sns = new AWS.SNS({ apiVersion: '2010-03-31' });
let cachedDb = null;
function connectToDatabase(uri) {
console.log('=> connect to database');
if (cachedDb) {
console.log('=> using cached database instance');
return Promise.resolve(cachedDb);
}
return MongoClient.connect(uri)
.then(db => {
cachedDb = db;
return cachedDb;
});
}
function queryDatabase(db) {
console.log('=> query database');
return db.collection('items').find({}).toArray()
.then((data) => { return { statusCode: 200, data: data }; })
.catch(err => {
console.log('=> an error occurred: ', err);
return { statusCode: 500, data: null };
});
}
exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
console.log('event: ', event);
connectToDatabase(MONGODB_URI)
.then(db => queryDatabase(db))
.then(result => {
console.log('=> returning result: ', result);
var params = {
Message: result.data,
Subject: 'Devices Lost Connection',
TopicArn: SNS_TOPICARN
};
sns.publish(params, function (err, data) {
if (err) console.log(err, err.stack);
else console.log(data);
});
callback(null, result);
})
.catch(err => {
console.log('=> an error occurred: ', err);
callback(err);
});
};
Problem solved, will leave it here if someone else has the same issue:
I need to do the handler callback in the callback of the second function:
sns.publish(params, function (err, data) {
if (err) console.log(err, err.stack);
else console.log(data);
callback(null, result);
});