Issue in loopback's upsertWithWhere() - loopbackjs

I'm using loopback3.x. Why upsertWithWhere function always updates the same instance? Only one instance is there for all the time when updateWithWhere function executes.
app.models.oneTimePassword.upsertWithWhere({
where: {
userId: user.id
}
}, {
userId: user.id,
otp: otp,
updatedAt: updatedAt,
type: 'email'
}, (err, res) => {
if (!err) {
callback(null, {
status: "OK",
message: "email sent"
});
} else {
callback(err);
}
});

app.models.oneTimePassword.upsertWithWhere(
{
userId: user.id
},
{
userId: user.id,
otp: otp,
updatedAt: updatedAt,
type: 'email'
},
(err, res) => {
if (!err) {
callback(null, {
status: "OK",
message: "email sent"
});
} else {
callback(err);
});
Try this, The first argument of upsertWithWhere should be where therefore, you don't need to add where: {} check out this official documentation

Related

How to implement auth guard for graphql subscriptions (passportjs + cookies)

How I can pass user to the request?
Is there any possible way to implement something like SubscriptionAuthGuard?
without the subscription, everything works fine
Code:
GraphQLModule.forRoot({
installSubscriptionHandlers: true,
subscriptions: {
'subscriptions-transport-ws': {
onConnect: (connectionParams, webSocket) =>
new Promise((resolve) => {
passportInit(webSocket.upgradeReq, {} as any, () => {
resolve(webSocket.upgradeReq);
});
}),
},
},
context: ({ req }) => ({ req }),
}),
Error:
TypeError: Cannot set property 'authInfo' of undefined
This worked for me, I'm using JWT and bearer tokens.
GraphQL.module:
'subscriptions-transport-ws': {
path: '/graphql',
onConnect: (connectionParams) => {
return {
req: {
headers: { authorization: connectionParams.Authorization },
},
};
},
},
Guard:
#Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
async canActivate(context: ExecutionContext): Promise<boolean> {
try {
return (await super.canActivate(context)) as boolean;
} catch (e) {
throw new AuthenticationError(generalErrorMessages.invalidToken);
}
}
getRequest(context: ExecutionContext): Request {
const ctx = GqlExecutionContext.create(context);
return ctx.getContext().req;
}
}

for some reason my put route is not working in sequelize

this is my call
$.ajax({
url: "/api/user_data",
method: "PUT",
data: {
id: data.id,
level: newLevel,
point: addPoints
},
error: function(req, err) {
console.log(err)
}
}).then(result => {
console.log("user info updated");
console.log(result);
// window.location.replace("/members");
});
this is my route
app.put("/api/user_data", function(req, res) {
db.User.update(
{
points: req.body.points,
level: req.body.level,
},
{
where: {
id: req.body.id,
},
}
).then(function(result) {
res.json(result);
});
});
I am also getting an error saying "can't set headers after they are sent".
I had { force: true } set before and it was not working. When I set force: false the level would update but only after I logged out then logged back in. I'm not sure why that was happening at all but any help would be much appreciated.

AWS SES send email lambda not sending every time

I want to send emails using the ses from aws from lambda. The problem is that the email is only sent some times using the same code. We don't get errors.
Here's the code:
const AWS = require('aws-sdk');
var ses = new AWS.SES();
exports.handler = async (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
await new Promise((resolve, reject) => {
var params = {
Destination: {
ToAddresses: [myEmail]
},
Message: {
Body: {
Text: { Data: "Test"
}
},
Subject: { Data: "Test Email"
}
},
Source: "sourceMail"
};
ses.sendEmail(params, function (err, data) {
if (err) {
console.log(err);
context.fail(err);
} else {
console.log(data);
context.succeed(event);
}
callback(null, {err: err, data: data});
});
});
}
I would be careful with using callbackWaitsForEmptyEventLoop as it can lead to unexpected results (If this is false, any outstanding events continue to run during the next invocation.).
Can you try using this simplified version:
const AWS = require('aws-sdk');
var ses = new AWS.SES();
exports.handler = async (event, context, callback) => {
const params = {
Destination: {
ToAddresses: [myEmail],
},
Message: {
Body: {
Text: { Data: 'Test' },
},
Subject: { Data: 'Test Email' },
},
Source: 'sourceMail',
};
await ses.sendEmail(params).promise();
return event;
};

How to res.send something in loopback-next

I have a function that has a callback as shown below, and I want to return account that is returned in the callback as a response to the request for the function. How could I res.send the account (since I cannot return values from a callback function)
#get('/payments/retrieve-stripe/{id}', {
responses: {
'200': {
description: 'User model instance',
content: {'application/json': {schema: {'x-ts-type': User}}},
},
},
})
async retrieveStripe(#param.path.number('id') id: number,
#requestBody() req: any): Promise<any> {
if (!req.stripeAccountId) {
throw new HttpErrors.NotFound('No Stripe Account');
}
else {
stripe.accounts.retrieve(
req.stripeAccountId,
async function(err: any, account: any) {
//console.log(err)
console.log(account)
return account
})
}
}
If you're stuck using a callback any any point in your code you're going to use manual promises (or maybe some promise wrapping library).
Instead of using async and return, use resolve() which functionally can return from any point in your function, regardless of scope.
#get('/payments/retrieve-stripe/{id}', {
responses: {
'200': {
description: 'User model instance',
content: {'application/json': {schema: {'x-ts-type': User}}},
},
},
})
retrieveStripe(#param.path.number('id') id: number, #requestBody() req: any): Promise<any> {
return new Promise((resolve, reject) => {
if (!req.stripeAccountId) {
throw new HttpErrors.NotFound('No Stripe Account');
}
else {
stripe.accounts.retrieve(req.stripeAccountId, function(err: any, account: any) {
resolve(account);
})
}
});
}

How to return a callback's function return value

I'm using loopback-next along with the stripe api. In the stripe API, I call retrieve account as follows, in a payments.controller.ts file:
#post('/payments/retrieve-stripe/{id}', {
responses: {
'200': {
description: 'User model instance',
content: {'application/json': {schema: {'x-ts-type': User}}},
},
},
})
async retrieveStripe(#param.path.number('id') id: number,
#requestBody() req: any): Promise<any> {
console.log(req);
if (!req.stripeAccountId) {
throw new HttpErrors.NotFound('No Stripe Account');
}
else {
return await stripe.accounts.retrieve(
req.stripeAccountId,
function(err: any, account: any) {
return err ? err : account
})
}
}
However, when I try return account, nothing is returned in the JSON body. If i try, response.json on the front end, it said that the JSON unexpectedly finished, meaning there is nothing in the body. How would I be able to successfully return account in the above function inside of a controller function?
This was the same problem I had for trying to return a string as well. I'm not sure what to do.
EDIT: I learned that you cannot return variables in a callback and that is the issue.
You have to require type definitions (#types/stripe) to use its library in promise style. After that you can use in following way:-
#post('/payments/retrieve-stripe/{id}', {
responses: {
'200': {
description: 'User model instance',
content: { 'application/json': { schema: { type: 'object' } } },
},
},
})
async retrieveStripe(#param.path.number('id') id: number,
#requestBody() req: any): Promise<any> {
console.log(req);
if (!req.stripeAccountId) {
throw new HttpErrors.NotFound('No Stripe Account');
} else {
return await stripe.accounts.retrieve(req.stripeAccountId).then((res: any) => {
return res;
}).catch((err: any) => {
console.debug(err);
throw new HttpErrors.InternalServerError('Something went wrong!')
});
}
}
For more details https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/stripe/stripe-tests.ts