Loopback 4 - POST request dtasource template - loopback

I am having issue to declare POST operation in Loopback 4 datasource file.
My template is as follows:
{
"template": {
"method": "POST",
"url": "https://reqres.in/api/login"
},
"functions": {
"login": []
}
}
My service interface
login(email: string, password: string): Promise<any>;
My Controller
#post('/loginTest')
async testingLogin(
#requestBody({
content: {
'application/json': {
schema: getModelSchemaRef(TestModel, {
title: 'Post',
}),
},
},
})
testModel: TestModel, )
: Promise<any> {
// TEST MODEL CONTAIN JSON OBJECT {email: "" , password: ""}
console.log("Test Model Representation: ", testModel)
try {
var response = await this.loginService.login(testModel.email, testModel.password);
} catch (error) {
console.log("error", error)
}
console.log("Fake POST response", response)
return response;
};
I am using this fake API : https://reqres.in/api/login
I am getting following error:
Test Model Representation: { email: 'string', password: 'string' }
error Error: {"error":"Missing email or username"}
at callback (D:\loginApp\node_modules\loopback-connector-rest\lib\rest-builder.js:541:21)
at D:\loginApp\node_modules\loopback-datasource-juggler\lib\observer.js:269:22
at doNotify (D:\loginApp\node_modules\loopback-datasource-juggler\lib\observer.js:157:49)
at RestConnector.ObserverMixin._notifyBaseObservers (D:\loginApp\node_modules\loopback-datasource-juggler\lib\observer.js:180:5) {
statusCode: 400,
message: '{"error":"Missing email or username"}'
}
Fake POST response undefined
It look like my email and password is not passed ? Thanks for any help.

The login function you defined in the datasource file should match with the service interface. That means it would be something like:
"functions": {
"login": ["email", "password"]
}

Related

Cannot get a response from PostgreSQL server

I freely admit that I am completely new to next-auth and the documentation for Credentials is understandably very light. I have got the email link process to work perfectly and will be moving users across top this.
Unfortunately, I have a lot of user data that will require credentials to login and, after spending a few days getting nowhere, I just want to get some idea of what I am doing wrong! This is my [...nextauth].js file:
import NextAuth from "next-auth";
import Providers from "next-auth/providers";
import axios from 'axios'
const options = {
providers: [
Providers.Email({
server: {
host: process.env.EMAIL_SERVER_HOST,
port: process.env.EMAIL_SERVER_PORT,
auth: {
user: process.env.EMAIL_SERVER_USER,
pass: process.env.EMAIL_SERVER_PASSWORD
}
},
from: process.env.EMAIL_FROM
}),
Providers.Credentials({
credentials: {
mem_num: { label: "Membership Number", type: "text", placeholder: "12345" },
password: { label: "Password", type: "text" }
},
authorize: async (credentials) => {
console.log("credentials: ", credentials)
try {
const data = {
mem_num: credentials.mem_num,
password: credentials.password
}
const user = await login(data)
if (user) {
console.log('user:', user)
return user
}
} catch (error) {
if (error.response) {
console.log(error.response)
Promise.reject(new Error('Invalid Number and Password combination'))
}
}
}
})
],
site: process.env.NEXTAUTH_URL || "http://localhost:3000",
database: process.env.DATABASE_URL,
session: {
// Use JSON Web Tokens for session instead of database sessions.
// This option can be used with or without a database for users/accounts.
// Note: `jwt` is automatically set to `true` if no database is specified.
jwt: true,
},
}
const login = async data => {
var config = {
headers: {
'Content-Type': "application/json; charset=utf-8",
'corsOrigin': '*',
"Access-Control-Allow-Origin": "*"
}
};
const url = process.env.DATABASE_URL;
const result = await axios.post(url, data, config);
console.log('result', result);
return result;
};
export default (req, res) => NextAuth(req, res, options);

Axios in Nuxt.js is not catch error properly

As I mentioned above my Axios on Nuxt.js is not catch error properly
I need to know the error, so I can prompt to let the user know their input is not correct but it only console.log the error code status not the message from my API
this is my code
await axios
.post(
"API LINK",
{
email: user.email,
password: "123456",
name: user.name,
dob: user.dob ?? null,
gender: user.gender ?? null,
profileImage: imageUrl ?? user.profileImage,
userType: user.userType
}
)
.then(res => {
console.log("success");
console.log(res);
})
.catch(err => {
console.log('fail');
console.log(err)
})
This is what log on a chrome console
error
add.vue?104b:181 Error: Request failed with status code 400
at createError (createError.js?2d83:16)
at settle (settle.js?467f:17)
at XMLHttpRequest.handleLoad (xhr.js?b50d:61)
But what I expect from the console.log(err) is
(This is response from postman)
{
"message": "Error creating new user.",
"error": {
"code": "auth/invalid-password",
"message": "The password must be a string with at least 6 characters."
}
}
I have no idea what is happening.
Try this
console.log(err.response)
To make the code cleaner you can destructure the argument:
.catch(({ response }) => {
console.log('fail');
console.log(response)
})
If you want to use some other property name instead of response you can do it like this:
.catch(({ response: err }) => {
console.log('fail');
console.log(err)
})
The problem is when the console.log tries to output the error, the string representation is printed, not the object structure, so you do not see the .response property.
Here you can read about https://github.com/axios/axios/issues/960
This is working with a try / catch structure, which is the preferred way
try {
await axios.post("API LINK", {
email: user.email,
password: "123456",
name: user.name,
dob: user.dob ?? null,
gender: user.gender ?? null,
profileImage: imageUrl ?? user.profileImage,
userType: user.userType,
})
console.log("success", res)
} catch ({ response }) {
console.log("fail", response)
}

mongoose When I Use update it updates Nothing with status 200(success)

I use update Query for push some data in array in Mongodb and I use mongoose in nodeJs.Pplease anyone can help out from this.
Model Schema :
var mongoose = require('mongoose')
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt')
var schema = new Schema({
email: { type: String, require: true },
username: { type: String, require: true },
password: { type: String, require: true },
creation_dt: { type: String, require: true },
tasks : []
});
module.exports = mongoose.model('User',schema)
So I use this schema and I want to push data in tasks array and here is my route code for pushing data.
Route For Update Data in Tasks:
router.post("/newTask", isValidUser, (req, res) => {
addToDataBase(req, res);
});
async function addToDataBase(req, res) {
var dataa = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime,
};
var usr = new User(req.user);
usr.update({ email: req.user.email }, { $push: { tasks: dataa } });
console.log(req.user.email);
try {
doc = await usr.save();
return res.status(201).json(doc);
} catch (err) {
return res.status(501).json(err);
}
}
Here I create a async function and call that function in route but when I post data using postman it response with status code 200(success) but it updates nothing in my database.
Output screenshot:
as you can see in this image task : [].. it updates nothing in that array but status is success
I don't know why is this happening.
You can achieve this task easier using findOneAndUpdate method.
router.put("/users", isValidUser, async (req, res) => {
var data = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime,
};
try {
const user = await User.findOneAndUpdate(
{ email: req.user.email },
{
$push: {
tasks: data,
},
},
{ new: true }
);
if (!user) {
return res.status(404).send("User with email not found");
}
res.send(user);
} catch (err) {
console.log(err);
res.status(500).send("Something went wrong");
}
});
Also I strongly suggest using raw / JSON data for request body, that's how most ui libraries (reactjs, angular) send data.
To be able to parse json data, you need to add the following line to your main file before using routes.
app.use(express.json());
TEST
Existing user:
{
"tasks": [],
"_id": "5e8b349dc285884b64b6b167",
"email": "test#gmail.com",
"username": "Kirtan",
"password": "123213",
"creation_dt": "2020-04-06T14:21:40",
"__v": 0
}
Request body:
{
"pName": "pName 1",
"pTitle": "pTitle 1",
"pStartTime": "pStartTime 1",
"pEndTime": "pEndTime 1",
"pSessionTime": "pSessionTime 1"
}
Response:
{
"tasks": [
{
"pName": "pName 1",
"pTitle": "pTitle 1",
"pStartTime": "pStartTime 1",
"pEndTime": "pEndTime 1",
"pSessionTime": "pSessionTime 1"
}
],
"_id": "5e8b349dc285884b64b6b167",
"email": "test#gmail.com",
"username": "Kirtan",
"password": "123213",
"creation_dt": "2020-04-06T14:21:40",
"__v": 0
}
Also as a side note, you had better to create unique indexes on username and email fields. This can be done applying unique: true option in the schema, but better to create these unique indexes at mongodb shell like this:
db.users.createIndex( { "email": 1 }, { unique: true } );
db.users.createIndex( { "username": 1 }, { unique: true } );
It's been awhile since I've done mongoose, but I'm pretty sure <model>.update() also actively updates the record in Mongo.
You use .update() when you want to update an existing record in Mongo, but you are instantiating a new User model (i.e. creating a new user)
try the following code instead for a NEW USER:
router.post('/newTask', isValidUser, (req, res) => {
addToDataBase(req,res)
})
async function addToDataBase(req, res) {
var dataa = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime
}
// email field is already in `req.user`
var usr = new User({ ...req.user, tasks: [dataa] });
console.log(req.user.email);
try {
await usr.save();
return res.status(201).json(doc);
}
catch (err) {
return res.status(501).json(err);
}
}
Now, if you wanted to update an existing record :
router.post('/newTask', isValidUser, (req, res) => {
addToDataBase(req,res)
})
async function addToDataBase(req, res) {
var dataa = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime
}
try {
await usr. updateOne({ email : req.user.email}, { $push: { tasks: dataa } });
return res.status(201).json(doc);
}
catch (err) {
return res.status(501).json(err);
}
}
For more info read: https://mongoosejs.com/docs/documents.html

Unable to update Data

Am trying to update the json data through an api call.
I was able to GET the data without any issues, as am not passing any Options in the request.
For UPDATE,
//saga.js
export function* BlurideaTitler(opt) {
const id = opt.id; // 4
const updatedTitle = opt.newTitle; // "title changed"
let options = {
crossDomain: true,
method: 'PUT',
json: true,
headers: {'Content-Type': 'application/json'},
body: {
title: updatedTitle
}
};
const requestURL = `http://localhost:3000/ideas/${id}`;
try {
yield call(request, requestURL, options);
} catch (err) {
console.log(err);
}
}
// request.js
export default function request(url, options) {
return fetch(url, options)
.then(checkStatus)
.then(parseJSON);
}
//db.json
JSON am trying to update.,
{
"ideas": [
{
"id": 4,
"title": "My fourth Idea",
"body": "Description of my fourth idea",
"created_date": "14-Apr-2019"
}
]
}
This is supposed to update the value of title. But it throws error'Bad request' . Can someone please let me know what am missing here.

Sengrid template substitution tags not replaced when sending email in Meteor app

In Meteor application that incorporates Sendgrid transaction email templates for user invitations and notifications, I can't manage to replace substitution tags. Templated email is received, but without any difference.
Email.send({
from: "hello#domain.com",
to:email,
subject: "Subject",
sub: {
"{name}":post.createdBy,
"{title}":post.title,
},
headers: {
"X-SMTPAPI": {
"filters": {
"templates": {
"settings": {
"enable": 1,
"template_id": "xxxx"
}
}
}
},
"Content-Type" : "text/html"
}
});
I'm not using API directly, but rather Meteor Email package, but don't see that possible issue:
Meteor.startup(function () {
process.env.MAIL_URL = 'smtp://username:password#smtp.sendgrid.net:587';
});
This is my shortened email template:
Hey {name},
your post {title} has a new comment.
You need to put the subs in the X-SMTPAPI header as well. The X-SMTPAPI header itself should also contain valid JSON in a string.
Try this:
var xsmtpapi = {
"filters": {
"templates": {
"settings": {
"enable": 1,
"template_id": "xxxx"
}
}
},
"sub": {
"{name}": post.createdBy,
"{title}": post.title
}
}
Email.send({
from: "hello#domain.com",
to:email,
subject: "Subject",
sub: {
"{name}":post.createdBy,
"{title}":post.title,
},
headers: {
"X-SMTPAPI": JSON.stringify(xsmtpapi),
"Content-Type" : "text/html"
}
});
What I ended up doing was using smtpapi-nodejs NPM package.
The simple example would be:
var nodemailer = require('nodemailer');
var smtpapi = require('smtpapi');
var header = new smtpapi();
header.setFilters({
"templates": {
"settings": {
"enable": 1,
"template_id": xxx-template-id-xxx
}
}
});
header.addSubstitution('-name-', post.createdBy);
header.addSubstitution(-title-', post.title);
var headers = { 'x-smtpapi': header.jsonString() };
// Use nodemailer to send the email
var settings = {
host: "smtp.sendgrid.net",
port: parseInt(587, 10),
requiresAuth: true,
auth: {
user: "sendgrid_username",
pass: "sendgrid_password"
}
};
var smtpTransport = nodemailer.createTransport(settings);
var mailOptions = {
from: "Fred Foo <foo#blurdybloop.com>",
to: "bar#blurdybloop.com",
subject: "Hello",
text: "Hello world",
html: "<b>Hello world</b>",
headers: headers
}
smtpTransport.sendMail(mailOptions, function(error, response) {
smtpTransport.close();
if (error) {
console.log(error);
} else {
console.log("Message sent: " + response.message);
}
});