Problem authenticating with mocha, chai and supertest - mocha.js

I add the userRecord to the database in the before function but when I try to authenticate using supertest it gives me bad combo.
I am using sails for the backend, the code is as follows
var request = require('supertest');
let should = chai.should();
require('../../boostrap.test.js');
describe('The bookedservices Controller', function() {
let userRecord,
studioRecord,
serviceRecord,
timingRecord,
bookedServiceRecord,
authenticatedUser,
authenticatedStudio,
session = null;
before(async function() {
// beforeEach(async function(done) {
userRecord = await User.create({
emailAddress: 'xx#gmail.com',
password: 'xxisnotgood123',
fullName: 'siddhant',
location: 'vellore',
image: 'not a pipi pic',
mobile: '9681901311',
description: 'words cant describe me'
}).fetch();
creditRecord = await Credits.create({
expirydate: '2019-05-25T03:23:55.016Z',
creditsPresent: 30,
passType: '1 month',
userId: userRecord.id
}).fetch();
studioRecord = await Studios.create({
emailAddress: 'yy#gmail.com',
password: 'yyisnotgood123',
fullName: 'siddhant',
location: 'vellore',
image: 'not a lili pic',
mobile: '9681901311',
description: 'words cant describe me'
}).fetch();
serviceRecord = await Services.create({
serviceName: 'zumba',
price: 1500,
creditCost: 3,
studioId: studioRecord.id
}).fetch();
timingRecord = await Timings.create({
eventInTime: '2019-05-11T03:23:55.016Z',
eventOutTime: '2019-05-13T00:00:02.001Z',
numberOfSlotsAvailable: 3,
serviceId: serviceRecord.id
}).fetch();
bookedServiceRecord = await BookedServices.create({
isComplete: 'false',
bookingDate: '2019-05-13T03:23:55.016Z',
timingId: timingRecord.id,
userId: userRecord.id,
studioId: studioRecord.id,
serviceId: serviceRecord.id
}).fetch();
authenticatedUser = await request.agent(sails.hooks.http.app);
authenticatedUser
.post('/api/v1/users/entrance/login')
.set('Accept', 'application/json')
.send({ emailAddress: 'xx#gmail.com', password: 'xxisnotgood123' })
.end((err, res) => {
if (err) {
throw err;
} else {
console.log(res);
session = res.header['Sails.sid'];
}
});
// authenticatedStudio = await request.agent(sails.hooks.http.app);
// authenticatedStudio
// .post('/api/v1/studios/login')
// .set('Accept', 'application/json')
// .send({ emailAddress: 'yy#gmail.com', password: 'yyisnotgood123' });
// done();
});
it('all the records have been added', function(done) {
userRecord.should.have.property('id');
console.log('OUTPUT: userRecord', userRecord);
studioRecord.should.have.property('id');
// console.log('OUTPUT: studioRecord', studioRecord);
serviceRecord.should.have.property('id');
// console.log('OUTPUT: serviceRecord', serviceRecord);
timingRecord.should.have.property('id');
// console.log('OUTPUT: timingRecord', timingRecord);
bookedServiceRecord.should.have.property('id');
// console.log('OUTPUT: bookedServiceRecord', bookedServiceRecord);
done();
});
it('should post and return a bookedService model document', function(done) {
timingRecordId = timingRecord.id;
// console.log(`/api/v1/timings/${timingRecordId}/bookedservices`);
authenticatedUser
.post(`/api/v1/timings/${timingRecordId}/bookedservices`)
.set('Accept', 'application/json')
.set('Cookie', session)
.send({ isComplete: false, bookedDate: '2019-05-13T00:10:02.001Z' })
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, result) {
if (err) {
done(err);
} else {
result.body.should.be.an('object');
result.body.should.have.property('bookedServiceDoc');
result.body.should.have.property('message');
createdPostId = result.body.bookedServiceDoc.should.have.property(
'id'
);
console.log(result.body);
done();
}
});
});
The error is like this
<- POST /api/v1/users/entrance/login (36ms 401)
| bad combo
| The provided email and password combination does not match any user in the database.
Edit-1:- I narrowed it down to that it is not that the user does not exist but it throws this error due to not maching the password, I am using the template that comes with user authentication and it uses the helpers.password for confirming the password. It is throwing error there.
But where is this helper in the project?
Thank you for your help

For anyone in the future, this is how I changed it.
The problem is not hashing when I add it directly but when I verify it sails hashes the incoming password, thus resulting in mismatch of passwords
let hashedPasswordUser = await sails.helpers.passwords.hashPassword(
'xxisnotgood123',
12
);
userRecord = await User.create({
emailAddress: 'xx#gmail.com',
password: hashedPasswordUser,
fullName: 'siddhant',
location: 'vellore',
image: 'not a cipdsai pic',
mobile: '9681901311',
description: 'words cant describe me'
}).fetch();

Related

#sidebase/nuxt-auth refresh token issue with laravel passport

I'm using nuxt 3 with #sidebase/nuxt-auth for my PKCE OAUTH2 authentication flow with my Laravel API which uses Laravel passport. I am done with the implementation of the authentication flow from the Laravel side, and done with the nuxt side, getting the token and saving it.
Then I have created a custom interceptor with ofetch, in order to send the access_token that I fetch from the session at every request.
but when the access token is expired, it is not getting refreshed automatically.
am i missing some configuration? or refresh token is a custom logic i have to write?
I've tried the JWT callback in the #sidebase/nuxt-auth but it didn't work.
This is my current auth configuration:
import {NuxtAuthHandler} from '#auth'
import useCustomFetch from "~/composables/useCustomFetch";
export default NuxtAuthHandler({
providers: [
{
id: 'passport',
name: 'Passport',
type: 'oauth',
version: '2.0',
authorization: {
url: "https://example.com/oauth/authorize",
params: {
scope: '',
prompt: 'front',
},
},
clientSecret: 'awd',
clientId: "96695f40-1578-4b7c-974b-181e0344dcac",
token: 'https://example.com/api/v1/oauth/token',
userinfo: 'https://example.com/api/v1/user',
checks: ['pkce'],
profile(profile: { success: { user: any } }) {
const data = profile.success.user
return {
id: data.id,
name: data.first_name + " " + data.last_name,
email: data.email,
};
},
}
],
cookies: {
},
callbacks: {
async jwt({token, account, user}) {
if (account && user) {
return {
access_token: account.access_token,
refresh_token: account.refresh_token,
accessTokenExpires: account.expires_at,
user
}
}
// #ts-ignore
if (Date.now() < token.accessTokenExpires * 1000) {
return token
}
return await refreshAccessToken(token);
},
async session({session, token}) {
// #ts-ignore
session.user = token.user
// #ts-ignore
session.access_token = token.access_token
// #ts-ignore
session.error = token.error
return session
},
},
events: {
async signOut() {
try {
await useCustomFetch('/oauth/tokens/revoke', {
method: 'POST'
})
} catch (e) {
console.log(e);
}
},
}
})
async function refreshAccessToken(token: any) {
try {
const url = "https://example.com/api/v1/oauth/token";
// #ts-ignore
const refreshedToken: AuthResponse = await $fetch(url, {
headers: {
"Content-Type": "application/json",
},
method: "POST",
body: {
grant_type: 'refresh_token',
refresh_token: token.refresh_token,
client_id: "96695f40-1578-4b7c-974b-181e0344dcac"
}
});
token.access_token = refreshedToken.access_token;
token.accessTokenExpires = Date.now() + refreshedToken.expires_at * 1000;
token.refresh_token = refreshedToken.refresh_token;
return {
...token
}
} catch (error) {
console.log(error)
return {
...token,
error: "RefreshAccessTokenError",
}
}
}
interface AuthResponse {
access_token: string,
refresh_token: string,
token_type: string,
expires_at: number,
}

Post Error with Apollo Client While Creating a New User

I am running into a POST http://localhost:4000/ 400 (Bad Request) Error.
I am trying to create a new user with the following frontend.
const REGISTER_USER = gql`
mutation Mutation(
$createUser: CreateUserInput!
) {
createUser(createUserInput: $createUserInput){
email
name
token
password
}
}
`
const Register = () => {
const context = useContext(AuthContext)
let navigate = useNavigate()
const [errors, setErrors] = useState([])
function registerUserCallback() {
console.log("Callback hit")
registerUser()
}
const {onChange, onSubmit, values} = useForm(registerUserCallback, {
name: '',
email: '',
password:'',
confirmPassword: '',
})
const [registerUser, {loading}] = useMutation(REGISTER_USER, {
update(proxy, {data: {registerUser: userData}}) {
context.login(userData)
navigate('/Dashboard')
},
onError({graphQLErrors}) {
setErrors(graphQLErrors)
console.log("Error: " + graphQLErrors)
console.log(graphQLErrors)
},
variables: {createUserInput: values}
})
However, the grapQLErrors is not even being console.logged for some reason. When I run the Mutation via Apollo Studio it works. Any information would be great!
Edit: Network Tab Screenshot:
Adding Code for my httpLink:
import { ApolloClient, InMemoryCache, createHttpLink } from "#apollo/client";
import { setContext } from "#apollo/client/link/context";
const httpLink = createHttpLink({
uri: 'http://localhost:4000'
})
const authLink = setContext((_, {headers}) => {
return {
headers: {
...headers,
authorization: localStorage.getItem('token') || ""
}
}
})
export const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
});
Edit: createUser Mutation seems to be the issue. This is the Network response error: ["GraphQLError: Unknown argument "createUserInput" on field "Mutation.createUser".","
#Mutation((returns) => User)
async createUser(#Arg('data') data:CreateUserInput, #Ctx() ctx: Context) {
const oldUser = await ctx.prisma.user.findFirst({ where: { email: data.email}})
if(oldUser) {
throw new ApolloError('A user is already registered with the email' + data.email, 'USER_ALREADY_EXISTS')
}
var encryptedPassword = await bcrypt.hash(data.password, 10)
const newUser = await ctx.prisma.user.create({
data: {
name: data.name,
email: data.email,
password: encryptedPassword
}
})
return {token: jwt.sign(newUser, 'supersecret')}
}
Here is a screen shot of my Preview in my Network...I really don't get it.
export class CreateUserInput {
#Field((type) => String)
name: string
#Field((type) => String)
email: string
#Field((type) => String)
password: string

Formik setStatus not updating - formik.status undefined

I am trying to manually set the status on my formik instance upon receiving an error response from server:
const formik = useFormik({
initialValues: {
email: "",
password: "",
},
onSubmit: async ({ email, password }, { setStatus }) => {
try {
const response = await loginUser({
variables: {
email,
password,
},
});
} catch (error) {
await setStatus({ email: error.message, password: error.message });
console.log(formik.status);
}
formik.resetForm();
},
validationSchema: Yup.object().shape({
email: Yup.string(),
password: Yup.string(),
}),
});
Logging status prints undefined.
Why is status not being set?
Figured it out.
Using resetForm clears both form status and errors.
To get around this I have manually cleared both fields instead:
initialValues={{
email: "",
password: "",
}}
onSubmit={async ({ email, password }, { setStatus, setFieldValue }) => {
try {
const response = await loginUser({
variables: {
email,
password,
},
});
} catch (error) {
setStatus({
email: "Shit",
});
setFieldValue("email", "");
setFieldValue("password", "");
}
}}
validationSchema={Yup.object().shape({
email: Yup.string(),
password: Yup.string(),
})}

Lambda function – GET doesn't return anything

I am completely new to The Serverless Framework and AWS lambda.
When making a GET request to http://localhost:3000/user/1e89a3f0-d170-11e9-94bd-91e9ae84f3e9 I would expect a response being send back to the browser with a valid JSON object matching the Key. Like the only getting logged out to the console. And not empty document.
Am I returning incorrectly? I am having difficulties debugging this, I don’t now if the problem is with my lambda function, or what it is.
Thank you.
console.log statement
{
email: 'i#am.com',
password: '$argon2i$v=19$m=4096,t=3,p=1$IIICgcMqbUA7wFpEMqb/GA$ENScjko+Y8pruQsTiE6qN81QAJfAPX/T116RQZqe347Y1p0rez4KhKaEulMeabKKiu8',
id: '1e89a3f0-d170-11e9-94bd-91e9ae84f3e9'
}
Here is the get handler in question.
users/get.js
const AWS = require("aws-sdk");
const dynamoDb = new AWS.DynamoDB.DocumentClient({
region: "localhost",
endpoint: "http://localhost:8000"
});
module.exports.get = async event => {
const params = {
TableName: process.env.DYNAMODB_TABLE,
Key: {
id: event.pathParameters.id
}
};
dynamoDb.get(params, (error, result) => {
if (error) {
console.error(error);
return;
}
console.log(result.Item); // logs successfully to the console.
return {
// doesn't return a response.
statusCode: 200,
body: JSON.stringify(result.Item)
};
});
};
serverless.yml
# EXCERPT
functions:
get:
handler: users/get.get
events:
- http:
method: get
path: user/{id}
cors: true
resources:
Resources:
UsersDynamoDbTable:
Type: "AWS::DynamoDB::Table"
DeletionPolicy: Retain
Properties:
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:provider.environment.DYNAMODB_TABLE}
custom:
dynamodb:
stages:
- dev
start:
port: 8000
inMemory: true
sharedDb: true
noStart: true
You should either use the callback argument to return a response:
module.exports.get = (event, context, callback) => {
const params = {
TableName: process.env.DYNAMODB_TABLE,
Key: {
id: event.pathParameters.id,
},
};
dynamoDb.get(params, (error, result) => {
if (error) {
console.error(error);
callback({
statusCode: 500,
body: 'Unable to get item',
});
}
console.log(result.Item);
callback(null, {
statusCode: 200,
body: JSON.stringify(result.Item),
});
});
};
Or use promises:
module.exports.get = async event => {
try {
const params = {
TableName: process.env.DYNAMODB_TABLE,
Key: {
id: event.pathParameters.id,
},
};
const result = await dynamoDb.get(params).promise();
console.log(result.Item);
return {
statusCode: 200,
body: JSON.stringify(result.Item),
};
} catch (error) {
console.error(error);
return {
statusCode: 500,
body: 'Unable to get item',
};
}
};

How to access the context in GraphQL from your resolvers

I just want to send the request to all my resolvers through the context field, but when I access it from one of my resolvers, it returns null.
app.use('/graphql', graphqlHTTP(async (request, response, graphQLParams) => ({
schema: schema,
context:{token_1:null,test:request},
graphiql:true
})));
These are part of my schema. Firstly I Login to set the token ,but when I want to access the context.token_1 from the other resolver (BuyItems), it returns null.
BuyItems :{
type: UserType,
args: {
name: {type: GraphQLString},
points: {type: GraphQLInt}
},
resolve(parent,args,context){
console.log(context.token_1)
return UserModel.findOneAndUpdate({name:args.name},{points:args.points})
}
},
Login: {
type: AuthType,
args: {
email: {type:GraphQLString},
password: {type:GraphQLString}
},
async resolve(parent,args,context){
const user = await UserModel.findOne({ email: args.email });
if (!user) {
throw new Error('User does not exist on login!');
}
const isEqual = await bcrypt.compare(args.password, user.password);
if (!isEqual) {
throw new Error('Password is incorrect!');
}
const token = jwt.sign(
{ userId: user.id, email: user.email },
'somesupersecretkey',
{ expiresIn: '1h' }
);
context.token_1 = token;
return {tokenExpiration: 1, userId: user.id, token:token}
}
}

Resources