ExpressJwt is not a function - javascript

I'm trying to write user authorization middleware. I use this function to validate and verify authorization later on.
I have done yarn add express-jwt.
auth.js code:
const SECRET = 'secret-message';
const jwt = require('jsonwebtoken');
const expressJwt = require('express-jwt');
const compose = require('composable-middleware');
function sign(user) {
return jwt.sign({
_id: user._id,
}, SECRET, {
expiresIn: 60 * 60
});
}
function sendUnauthorized(req, res) {
console.log(req.headers.authorization);
console.log(req.user);
res.status(401).json ({ message: 'Unathorized' });
};
const validateJwt = expressJwt({
secret: SECRET,
fail: sendUnauthorized,
getToken(req) {
if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
return req.headers.authorization.split(' ')[1];
} else if (req.query && req.query.access_token) {
return req.query.access_token;
}
return null;
}
});
And the error is:
const validateJwt = expressJwt({
^
TypeError: expressJwt is not a function
I'm stuck on this error and can't go any further. I really need some advice.

As the error says, expressJwt is not a function. The logical next step would then be to check what it is instead, and at the same time to recheck your assumption of it being a function (why do you think that?) and looking for sources for that, for example by checking the docs of the package.
You will find that a) it's an object with { expressjwt: <some function here> }, and b) that the docs show an example that uses destructuring (var { expressjwt: jwt } = require('express-jwt')) which you don't do.
Both of these findings should point you to the fact that your assumption of the module's default export being a function is wrong and it's instead an object with property expressjwt which is the function you are looking for, so you could fix your code by using destructuring on the import as follows:
const { expressjwt: expressJwt } = require('express-jwt');
(Alternatively, using expressJwt.expressjwt(...) would have worked too, of course, but I think it looks quite ugly and is unnecessarily verbose.)

Related

Cannot Get Prop Of NextRequest

I'm trying to MiddleWare With Next.js's Middleware and JWT.
When I console.log cookies and typeof cookies variable im getting on console:
{
token: 'token='myToken'; Path=/'
}
object
Here is my code:
import { NextRequest, NextResponse } from "next/server";
import { verify } from "jsonwebtoken";
const SECRET = process.env.SECRET;
export function middleware(req, res) {
const cookies = req.cookies;
const url = req.url;
if (url.includes("/admin")) {
console.log(cookies)
console.log(typeof cookies)
}
return NextResponse.next();
}
But when i try to get token prop like cookies.token, i got undefined
Any idea of what's going on?
Funny Answer:
I just need to use get method for get specified prop
const cookies = req.cookies.get('token');

TypeError: Cannot set property 'user' of undefined<br> at [file path] sqlite3

I am receiving an undefined error when attempting to set a session for the user upon validation of credentials on login. I am trying to use express-session to create the session for the user but do not have it directly imported into the file (I was guided to not do so) but am unsure how to resolve this error given. Any help and insight would be much appreciated!
End point:
router.post("/login", async (req, res, next) => {
try {
const { username, password } = req.body
// * checks for record existence in db, assigns record to var for access
const user = await users_access.findByFilter({ username })
if (!user) {
return res.status(401).json({ message: 'invalid crededentials' });
}
// * compares the entered password to the hash on record
const passwordValid = await secure.compare(password, user.password)
// * handling invalid responses + creating session
if (!passwordValid) {
return res.status(401).json({ message: 'invalid credentials' });
}
req.session.user = user
res.json({ message: `welcome, ${user.username}!`})
} catch(error) {
next(error)
}
});
application model:
// * add users to the datbase
// * inserts argument into user table in db access
// * returns a user found by id
const add = async (user) => {
const [id] = await database_access("users")
.insert(user)
return findById(id)
}
// * find user record with username and password
const find = () => {
return database_access("users").select("id", "username")
}
// * find user by filter
const findByFilter = (filter) => {
return database_access("users")
.select("id", "username", "password")
.where(filter)
.first()
}
// * find user with id
const findById = (id) => {
return database_access("users")
.select("id", "username")
.where({ id }) // desctructuring id from the request
.first()
}
module.exports = {
add,
find,
findByFilter,
findById
}
if you need to see any additional code to assess I am happy to provide but believe this is the source of issue per the error response. Thank you in advanced!
so I guess you are using the express-session module in your entry file for the server, app.js, server.js, index.js however you call it.
this login handler require to be used in a context where the session is available.
I think what you want is not a unit test for this particular router, but an integration test, to test this router in the context of your app.
This is all I can see from the information you provided. If this was not helpful enough, maybe you can show us your servers main file. and how this router is used.

Sequlize beforeCreated hook with a condition

In my user model I've define a lifecycle hook for encrypt the password with bycrypt.
beforeCreate: function(acc, next) {
const salt = bcrypt.genSaltSync(10);
const hash = bcrypt.hashSync(acc.password, salt);
acc.password = hash;
}
This works perfectly. But now I implement Oauth google login to the project. In that case I want to bypass this hook.
if (acc.password) {
encrypt();
} else {
skip();
}
I tried this
hooks: {
beforeCreate: function(acc, next) {
if (acc.password) {
const salt = bcrypt.genSaltSync(10);
const hash = bcrypt.hashSync(acc.password, salt);
acc.password = hash;
} else {
return next
}
}
}
But this seems not work.
How do I skip the hook when req.body doesn't provide the password property.
You need to call next as a method like so: next().

Resolving a "TypeError: Cannot read property 'data' of undefined" in Cloud Functions

Sorry if this seems like a really basic question, the concept of cloud functions is extremely new to me and i'm still highly in the learning process.
However, whilst trying to execute this cloud function i get the following error
TypeError: Cannot read property 'data' of undefined
Full log can be seen here
For reference as well, I didnt make this function, im just trying to get it working, i used this video.
The actual cloud function:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const firestore = admin.firestore();
const settings = { timestampInSnapshots: true };
firestore.settings(settings);
const stripe = require('stripe')(functions.config().stripe.token);
exports.addStripeSource =
functions.firestore.document('cards/{userid}/tokens/{tokenid}')
.onCreate(async (tokenSnap, context) => {
var customer;
const data = tokenSnap.after.data();
if (data === null) {
return null
}
const token = data.tokenId;
const snapchat = await
firestore.collection('cards').doc(context.params.userId).get();
const customerId = snapshot.data().custId;
const customerEmail = snpashot.data().email;
if (customerId === 'new') {
customer = await stripe.customers.create({
email: customerEmail,
source: token
});
firestore.collection('cards').doc(context.params.userId).update({
custId: customer.id
});
}
else {
customer = await stripe.customers.retrieve(customerId)
}
const customerSource = customer.sources.data[0];
return firestore.collection('cards').doc(context.params.userId).collection('sources').doc(customerSource.card.fingerprint).set(customersource, { merge: true });})
The dart code im using for writing a payment service:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class PaymentService {
addCard(token) {
FirebaseAuth.instance.currentUser().then((user) {
print("Found User");
Firestore.instance
.collection('cards')
.document(user.uid)
.collection('tokens')
.add({'tokenId': token}).then((val) {
print('saved');
});
});
}
}
And finally, what executes when i push the button:
StripeSource.addSource().then((String token) {
print("Stripe!");
PaymentService().addCard(token);
});
As you can see the code is clearly being triggered, but i guess there is some sort of error with the data var, JavaScript is brand new to me so im sure its some sort of very dumb syntax issue.
From the log image attached the error is context is not defined
functions.firestore.document('cards/{userid}/tokens/{tokenid}')
.onCreate(async (tokenSnap, conetxt) => {
In the above function, you have passed parameter as conetxt and later in the function context is used, because of which it is giving undefined error.
Change the parameter name conetxt to context.
As your provided log output explains : you need to define a reference for your firestore.document function :
functions.firestore.document('cards/{userid}/tokens/{tokenid}')
modify it to :
functions.firestore.documentReference(){
}

How to get data passed to mongoose schema constructor

I am testing my application and need to verify that mongoose schema constructor is called with correct data.
let's say I do this:
const UserData = new User(user)
console.log(UserData.contructor.args)
I would expect log of the user object.
Probably the data is passed to constructor of mongoose schema?
Can some one please advise me how to access it?
Here is specific case I am trying to solve.
export const signup = async (req, res, next) => {
try {
//if user object is missing return error
if (!req.body.user)
return next(boom.unauthorized('No user data received.'))
//get user data
const user = req.body.user,
{ auth: { local: { password, password_2 } } } = user
//check if both passwords match
if (password !== password_2)
return next(boom.unauthorized('Passwords do not match.'))
//check if password is valid
if (!Password.validate(password)) {
const errorData = Password.validate(password, { list: true })
return next(boom.notAcceptable('Invalid password.', errorData))
}
//creates new mongo user
const UserData = new User(user)
//sets user password hash
UserData.setPassword(password)
//saves user to database
await UserData.save()
//returns new users authorization data
return res.json({ user: UserData.toAuthJSON() })
} catch(err) {
//if mongo validation error return callback with error
if(err.name === 'ValidationError') {
return next(boom.unauthorized(err.message))
}
// all other server errors
return next(boom.badImplementation('Something went wrong', err))
}
}
And part of test:
describe('Success', () => {
it('Should create new instance of User with request data', async () => {
const req = { body },
res = {},
local = { password: '1aaaBB', password_2: '1aaaBB'},
constructorStub = sandbox.stub(User.prototype, 'constructor')
req.body.user.auth.local = {...local}
await signup(req, res, next)
expect(constructorStub.calledOnceWith({...req.body.user})).to.be.true
})
})
EDIT: I can verify that is is called with expect(constructorStub.calledOnce).to.be.true
Just can't get to verify data passed.
Edit: After talking for some time sounds like what you need is to validate that you are creating a new user correctly.
My suggestion here is to create a new function createUserFromRequest that would take in request and return a new User.
You can then test this function easily as it's pure (no side effects, just input and output).
At this point, most of the logic in your handler is in this function so it would be probably not worth testing the handler itself, but you could still do it, for example by mocking the function above.
Example:
function createUserFromRequest(request) {
//get user data
const user = req.body.user,
{ auth: { local: { password, password_2 } } } = user
//check if both passwords match
if (password !== password_2)
return next(boom.unauthorized('Passwords do not match.'))
//check if password is valid
if (!Password.validate(password)) {
const errorData = Password.validate(password, { list: true })
return next(boom.notAcceptable('Invalid password.', errorData))
}
//creates new mongo user
const UserData = new User(user)
//sets user password hash
UserData.setPassword(password)
return UserData;
}
Please note: stubs and mocking are usually a code smell: there could either be a better way of testing, or it could be a sign of a need to refactor the code into something more easily testable. They usually point to tightly coupled or cluttered code.
Check out this great article on that topic: https://medium.com/javascript-scene/mocking-is-a-code-smell-944a70c90a6a

Categories

Resources