User input from form not posting to database? (axios ,mongodb, vue) - javascript

I am new to vue and I'm trying to post data from user input to my mongodb. I am using axios to retrieve and post data.
While the data from the db does show up on my page, I cannot get the form input to post. I'm not even getting any sort of error message, it is just not posting. I look forward to your response to let me know what I am doing wrong.
Here is my AddUser.vue page, from the client
<template>
<div>
<h1>Registration</h1>
<p>First name: </p>
<b-form-input v-model="firstname">
</b-form-input>
<p>Last name: </p>
<b-form-input v-model="lastname">
</b-form-input>
<p>Email: </p>
<b-form-input v-model="email">
</b-form-input>
<p>Password: </p>
<b-form-input v-model="password">
</b-form-input>
<br>
<button v-on:click="submitNew">Submit</button>
</div>
</template>
<script>
import UserService from "../UserService";
export default {
name: "UserEdit",
data(){
return {
editUsers: this.$route.query.user,
editStatus: "",
user: {}
}
},
methods: {
submitNew(){
try{
this.user = UserService.addUsers;
} catch (err) {
this.error = err.message;
}
this.cancel();
}
},
watch :{
$route: "updateRouter"
}
}
</script>
Here is my UserService.vue, from the client
import axios from "axios";
const mongoURL = "http://localhost:5000/api/posts";
class UserService{
static getUsers(){
return new Promise(async (resolve,reject)=> {
try{
const res = await axios.get(mongoURL);
const users = res.data;
resolve(
users.map((users) =>({
...users,
}))
);
} catch (err) {
reject (err);
}
});
}
static addUsers(user){
return axios.post(mongoURL, {
user
})
}
export default UserService;
Here is my model for Users.js, from the server
const mongoose = require('mongoose');
const User = mongoose.model("User",{
firstname: {
type: String,
required: true,
trim: true
},
lastname: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
trim: true
},
password: {
type: String,
required: true
}
})
module.exports = User;
Here is my posts.js, from the server
const express = require("express"),
mongoose = require("mongoose"),
User = require("../models/Users.js"),
router = express.Router();
router.get("/", async (req,res)=>{
try {
const user = await User.find({});
res.send(user);
} catch (error){
res.status(500).send(error);
}
});
router.post("/", async(req,res)=>{
console.log(req.body["user"]);
const user = new User(req.body["user"])
console.log(user);
try{
await user.save
console.log(user)
} catch(err){
res.status(550).send(err);
}
})
module.exports = router;

<template>
<div>
<h1>Registration</h1>
<p>First name: </p>
<b-form-input v-model="user.firstname">
</b-form-input>
<p>Last name: </p>
<b-form-input v-model="user.lastname">
</b-form-input>
<p>Email: </p>
<b-form-input v-model="user.email">
</b-form-input>
<p>Password: </p>
<b-form-input v-model="user.password">
</b-form-input>
<br>
<button v-on:click="submitNew">Submit</button>
</div>
</template>
<script>
import UserService from "../UserService";
export default {
name: "UserEdit",
data() {
return {
editUsers: this.$route.query.user,
editStatus: "",
user: {}
}
},
methods: {
submitNew() {
try {
this.user = UserService.addUsers(this.user);
} catch (err) {
this.error = err.message;
}
this.cancel();
}
},
watch: {
$route: "updateRouter"
}
}
</script>

Related

Nodemailer Nextjs Typescript form not sending emails

I am working on a personal project with Next.js Typescript and Nodemailer. It is my first time using Nodemailer. I am having issues making it work. I am following this tutorial. This is my code below as it is on the tutorial.
Nodemailer.ts: here I had to replace the type APIResponse for any due to the code gave me errors, and VSCode suggested me to create that function at the bottom of the file. Also, the location of this file is /pages/api/nodemailer.ts
import { NextApiHandler, NextApiRequest } from "next";
import nodemailer from "nodemailer";
type Fields = {
name: string;
message: string;
email: string;
};
const transporter = nodemailer.createTransport({
service: 'hotmail',
auth: {
user: process.env.NEXT_PUBLIC_EMAIL_ADDRESS,
pass: process.env.NEXT_PUBLIC_PASSWORD,
},
});
export const config = {
api: {
bodyParser: false,
},
};
const handler: NextApiHandler<any> = async(req, res) => {
if (req.method !== "POST") {
return res.status(404).send({ error: "Begone." });
}
res.setHeader("Content-Type", "application/json")
try {
const { fields } = await formidablePromise(req, {});
const { name, email, message } = fields;
if (!name || !name.trim()) {
throw new Error("Please provide a valid name.");
}
if (!email || !email.trim()) {
throw new Error("Please provide a valid email address.");
}
if (!message || !message.trim()) {
throw new Error("Please provide a valid email message.");
}
await transporter.sendMail({
to: 'info#someemail.com.au',
from: 'info#someemail.com.au',
replyTo: email,
subject: `Hello from ${name}`,
text: message,
html: `<p>${message.replace(/(?:\r\n|\r|\n)/g, "<br>")}</p>`,
});
res.status(200).json({});
} catch (error) {
res.status(500).json({ error: error });
}
}
export default handler;
function formidablePromise(req: NextApiRequest, arg1: {}): { fields: any; } | PromiseLike<{ fields: any; }> {
throw new Error("Function not implemented.");
}
Form.tsx: It is in /components/Form.tsx
import { FaFacebook, FaTwitter } from 'react-icons/fa';
import React, { ChangeEvent, FormEvent, useRef, useState } from 'react';
import styles from './Form.module.css';
export interface FormProps {
result: boolean
isChecked: boolean
callTime: {time: string, isChecked: boolean}[]
loading: boolean
}
const Form: React.FC<FormProps> = () => {
const [loading, setLoading] = useState<boolean>(false)
const [name, setName] = useState<string>("");
const [email, setEmail] = useState<string>("");
const [mobile, setMobile] = useState<string | number | any>("");
const [message, setMessage] = useState<string>("");
console.log('NAme:', name, ', email', email, ', mobile', mobile, ', message', message);
async function sendEmail(event: FormEvent) {
event.preventDefault();
setLoading(true);
try {
const formData = new FormData();
if (!name.trim()) {
throw new Error("Please provide a valid name.");
}
if (!email.trim()) {
throw new Error("Please provide a valid email address.");
}
if (!mobile.trim()) {
throw new Error("Please provide a valid mobile number.");
}
if (!message.trim()) {
throw new Error("Please provide a valid message.");
}
formData.append("name", name);
formData.append("email", email);
formData.append("mobile", mobile);
formData.append("message", message);
console.log('form data', formData);
const response = await fetch("/api/nodemailer", {
method: "POST",
body: formData,
});
const responseData = await response.json();
console.log('form responseData', responseData);
if (responseData.error) {
throw new Error(responseData.error);
}
console.log("Thanks, we will be in touch soon!");
setName("");
setEmail("");
setMobile("");
setMessage("");
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
console.log('send email', sendEmail);
return (
<>
<div className={styles.wrapper}>
<form
onSubmit={sendEmail}
className={styles.formContainer}>
<h3>Get <span>in</span> touch</h3>
<label>Full Name<span className={styles.required}>*</span></label>
<input
type="text"
name="name"
required
value={name}
onChange={({ target }: ChangeEvent) => setName(( target as HTMLInputElement ).value)}
/>
<div className={styles.twoInputs}>
<div className={styles.innerInputs}>
<label>Email</label>
<input
type="email"
name="email"
pattern=".+#.+\..+"
value={email}
onChange={({ target }: ChangeEvent) => setEmail(( target as HTMLInputElement ).value)}
/>
</div>
<div className={styles.innerInputs}>
<label>Mobile<span className={styles.required}>*</span></label>
<input
type="tel"
name="tel"
required
value={mobile}
onChange={({ target }: ChangeEvent) => setMobile((target as HTMLInputElement ).value)} />
</div>
</div>
<label>Message<span className={styles.required}>*</span></label>
<textarea
name="message"
rows={6}
required
value={message}
maxLength={1000}
onChange={({ target }: ChangeEvent) => setMessage(( target as HTMLInputElement ).value)}
/>
<input type="submit" value="Send" />
<small><span className={styles.required}>*</span>Required</small>
</form>
</div>
</>
)
}
export default Form;
At the moment I having an error 500 on the browser network, but when I opened the link the error references to the 404 of the Nodemailer.ts handler "Begone."
Any help would be much appreacciate it.
UPDATE after Anton answer
First, you need install #types/nodemailer as a devDependencies.
In the Form.tsx you are trying to send a regular object (class) instead of JSON. You must serialize the data with JSON.stringify() and you can also add a headers here. To simplify, you can directly put the values (states) to JSON.stringify(). And remove all formData.
Form.tsx
const response = await fetch('/api/nodemailer', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, email, mobile, message }), // Serialize JSON
});
I removed the formidablePromise() function because we recive and handling all data from the handler function and req.body.
nodemailer.ts
import { NextApiResponse, NextApiRequest } from 'next';
import nodemailer from 'nodemailer';
type Fields = {
name: string;
message: string;
mobile: string;
email: string;
};
type Response = {
error?: string;
status?: string;
message?: string;
};
const transporter = nodemailer.createTransport({
service: 'hotmail',
auth: {
user: process.env.NEXT_PUBLIC_EMAIL_ADDRESS,
pass: process.env.NEXT_PUBLIC_PASSWORD,
},
});
//export const config = {
// api: {
// bodyParser: false,
// },
//};
const handler = async (req: NextApiRequest, res: NextApiResponse<Response>) => {
const { name, email, message } = req.body as Fields;
if (req.method !== 'POST') {
return res.status(404).send({ status: 'fail', error: 'Begone.' });
}
try {
if (!name || !name.trim()) {
throw new Error('Please provide a valid name.');
}
if (!email || !email.trim()) {
throw new Error('Please provide a valid email address.');
}
if (!message || !message.trim()) {
throw new Error('Please provide a valid email message.');
}
await transporter.sendMail({
to: 'info#someemail.com.au',
from: 'info#someemail.com.au',
replyTo: email,
subject: `Hello from ${name}`,
text: message,
html: `<p>${message.replace(/(?:\r\n|\r|\n)/g, '<br>')}</p>`,
});
res.status(200).send({ status: 'done', message: 'message has been sent' });
} catch (error) {
res.status(500).send({ status: 'fail', error: `${error}` });
}
};
export default handler;
This works with my nodemailer Gmail options.
With export const config = {api: {bodyParser: false}}
Without
Credentials issue: Error: Missing credentials for "LOGIN" / "PLAIN"
I had LOGIN instead of PLAIN because I have other values in my .env, you need to check your .env. If it is fine, in the second step, create a app passwords, because you can't to use the same password as for login in.
How to set app passwords Gmail, Hotmail
Also, you can find an answer about Missing credentials for "PLAIN" here

NextAuth throwing CLIENT_FETCH_ERROR error in session callback

Having some trouble with setting up nextauth v4. Getting this error:
Client fetch error, Unexpected end of JSON input {error: {…}, path:
'session', message: 'JSON.parse: unexpected end of data at line 1
column 1 of the JSON data'}.
To fix it they say you have to add the url path to a .env file when deploying. I’m working on localhost so this shouldn't be a problem, but after adding it, still the same error.
When I comment out the async session callback in [...nextauth] file, the error doesn’t pop up and the session is “authenticated” but doesn’t persist. I’ve been staring it at this for a good while now and could use some help!
[...nextauth].js
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { PrismaClient } from "#prisma/client";
const prisma = new PrismaClient();
export default NextAuth({
providers: [
CredentialsProvider({
async authorize(credentials, res) {
//find existing user
const user = await prisma.user.findUnique({
where: {
email: credentials.email,
},
});
if (
credentials.email === user.email &&
credentials.password === user.password
) {
return user;
} else {
return res.status(409).send({ message: "No user with that email." });
}
},
}),
],
callbacks: {
async jwt({ token, user }) {
if (user) {
token.id = user.id;
return token;
}
},
//commenting this function and no error shows up
async session({ session, token }) {
if (token) {
session.id = token.id;
return session;
}
},
},
secret: "mysecret",
jwt: {
secret: "mysecret",
encryption: true,
},
session: {
strategy: "jwt",
maxAge: 1 * 24 * 60 * 60,
},
});
auth-form
import { signIn, useSession } from "next-auth/react";
export default function AuthForm() {
const { data: session } = useSession();
const handleSubmit = async (userData) => {
const { error, ok, url } = await signIn("credentials", {
redirect: false,
email: userData.email,
password: userData.password,
callbackUrl: "/profiel",
});
if (ok) {
router.push(url);
} else {
alert(error);
}
};
return (
<Form onSubmit={handleSubmit}>
<Field id="email" />
<Field id="password" />
<button type="submit">{isRegistered ? "Sign in" : "Register"}</button>
</Form>
);
}
_app.js
import { SessionProvider } from "next-auth/react";
function MyApp({ Component, pageProps: { session, ...pageProps } }) {
return (
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
);
}
The session and jwt callbacks need to return a session and jwt object respectively. You need to move the return statements in each function after the if block.
callbacks: {
async jwt({ token, user }) {
if (user) {
token.id = user.id;
}
return token;
},
async session({ session, token }) {
if (token) {
session.id = token.id;
}
return session;
}
}

How to display server-side validation messages in the client side via react-query?

Here is the Express route for the signup API call, It works as expected on the server-side but I want to display these same validation messages in real-time when the user will put their credentials on the React client
app.post("/signup", async (req, res) => {
try {
// Validate data before submission
const { error } = registerValidation(
req.body.username,
req.body.firstname,
req.body.lastname,
req.body.email,
req.body.password
);
if (error) return res.status(400).send(error.details[0].message);
// Checking if username already exists
const usernameExist = await database.query(
"SELECT username FROM users WHERE username=$1",
[req.body.username]
);
if (usernameExist.rows[0])
return res.status(400).send("Username already taken!");
// Checking if email already exists
const emailExist = await database.query(
"SELECT email FROM users WHERE email=$1",
[req.body.email]
);
if (emailExist.rows[0])
return res.status(400).send("Email already exists!");
// Hash the password
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(req.body.password, salt);
// Save the New User
const newUser = await database.query(
"INSERT INTO users(username, firstname, lastname, email, password) VALUES($1, $2, $3, $4, $5) RETURNING *",
[
req.body.username,
req.body.firstname,
req.body.lastname,
req.body.email,
hashedPassword,
]
);
res.json(newUser.rows[0]);
} catch (err) {
console.error(err.message);
}
});
And here is my fetch POST request for signup.
export const signUp = async (formData) => {
try {
const res = await fetch(`${API_URL}/signup`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(formData),
});
if (!res.ok) {
const errMsg = await res.text();
throw new Error(errMsg);
}
await res.json();
} catch (err) {
console.error(err.message);
}
};
And here is the signup form using react-hook-form and react-query, the error message is displayed on the console but wanted to display it on screen in real-time while the user typing in the form without the need to submit the form to display those messages.
import React from "react";
import { useForm } from "react-hook-form";
import { joiResolver } from "#hookform/resolvers/joi";
import Joi from "joi";
import { useMutation } from "react-query";
import { useHistory } from "react-router-dom";
import { signUp } from "../API/API";
// Signup Form Validation
const schema = Joi.object({
username: Joi.string().min(3).required(),
firstname: Joi.string().min(3).required(),
lastname: Joi.string().min(3).required(),
email: Joi.string()
.min(6)
.required()
.email({ tlds: { allow: false } }),
password: Joi.string().min(6).required(),
});
const SignupForm = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({ resolver: joiResolver(schema) });
const mutation = useMutation(signUp);
const history = useHistory();
// To submit data on server
const onSubmit = async (data) => {
// const res = await mutation.mutate(data);
// console.log(res);
await mutation.mutate(data);
history.push("/");
};
console.log(errors);
return (
<div>
<h3>Sign up</h3>
<form onSubmit={handleSubmit(onSubmit)}>
<input
type="text"
name="username"
placeholder="Username"
{...register("username", { required: true, min: 3 })}
/>
<p>{errors.username?.message}</p>
<br />
<input
type="text"
name="firstname"
placeholder="First Name"
{...register("firstname", { required: true, min: 3 })}
/>
<p>{errors.firstname?.message}</p>
<br />
<input
type="text"
name="lastname"
placeholder="Last Name"
{...register("lastname", { required: true, min: 3 })}
/>
<p>{errors.lastname?.message}</p>
<br />
<input
type="email"
name="email"
placeholder="Email"
{...register("email", {
required: true,
min: 6,
pattern: /^\S+#\S+$/i,
})}
/>
<p>{errors.email?.message}</p>
<br />
<input
type="password"
name="password"
placeholder="Password"
{...register("password", { required: true, min: 6 })}
/>
<p>{errors.password?.message}</p>
<br />
<button type="submit">Sign up</button>
</form>
</div>
);
};
export default SignupForm;
Please check with your syntax and all but did you check onError property?.
const { mutate } = useMutation(signUp, {
onSuccess: () => {
alert("successful");
},
onError: () => {
setStatus("there is an error");
},
});

Can't upload picture to MongoDb from React frontend

I'm creating a tinder clone, I can create a user fine however I cant upload a picture. The error I get is ValidationError: User validation failed: pictures: Cast to embedded failed for value "'picture'" at path "pictures". I'm not sure what I'm doing wrong. The post request seems to fire as excepted with the payload however its when I login when I get the error. So I'm sure this has something to do with initial creation of the account.
create account front and back
import React, { useState } from "react";
import {useHistory } from "react-router-dom";
import axios from "axios";
const CreateAccount = () => {
const api = "http://localhost:5000/user/create-account";
const history = useHistory();
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [emailAddress, setEmailAddress] = useState("");
const [password, setPassword] = useState("");
const [gender, setGender] = useState("Male");
const [sexualPreference, setSexualPreference] = useState("Straight");
const [age, setAge] = useState("");
const [description, setDescription] = useState("");
const [picture, setPicture] = useState("");
const account = {
firstName: firstName,
lastName: lastName,
emailAddress: emailAddress,
password: password,
gender: gender,
sexualPreference: sexualPreference,
age: age,
description: description,
pictures: picture
};
console.log(account.gender);
console.log(account.sexualPreference);
console.log(account.pictures)
const submit = () => {
axios
.post(api, account)
.then((res) => {
console.log(res.data);
history.push({
pathname: "/",
});
})
.catch((err) => console.log(err));
};
const handleSubmit = (event) => {
event.preventDefault();
submit();
};
return (
<div>
<div>
<h1>Create account</h1>
</div>
<form onSubmit={handleSubmit} encType="multipart/form-data">
<p>First Name</p>
<input
id="firstName"
name="firstName"
type="firstName"
onChange={(e) => setFirstName(e.target.value)}
></input>
<p>Last Name</p>
<input
id="lastName"
name="lastName"
type="lastName"
onChange={(e) => setLastName(e.target.value)}
></input>
<p>Email Address</p>
<input
id="emailAddress"
name="emailAddress"
type="emailAddress"
onChange={(e) => setEmailAddress(e.target.value)}
></input>
<p>Password</p>
<input
id="password"
name="password"
type="password"
onChange={(e) => setPassword(e.target.value)}
></input>
<p>Gender</p>
<select
id="gender"
name="gender"
type="gender"
onChange={(e) => setGender(e.target.value)}
>
<option value="Male">Male</option>
<option value="Female">Female</option>
</select>
<p>Sexual Preference</p>
<select
id="sexualPreference"
name="sexualPreference"
type="sexualPreference"
onChange={(e) => setSexualPreference(e.target.value)}
>
<option value="Straight" >Straight</option>
<option value="Gay" >Gay</option>
<option value="Lesbian" >Lesbian</option>
<option value="Bisexual" >Bisexual</option>
</select>
<p>Age</p>
<input
id="age"
name="age"
type="age"
onChange={(e) => setAge(e.target.value)}
></input>
<p>Description</p>
<input
id="description"
name="description"
type="description"
onChange={(e) => setDescription(e.target.value)}
></input>
<input
type="file"
name="file"
id="picture"
onChange={(e) => setPicture(e.target.id)}
></input>
<button type="submit">Submit</button>
</form>
</div>
);
};
export default CreateAccount;
router.post( "/user/create-account", [
check("firstName")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "firstName"'),
check("lastName")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "username"'),
check("emailAddress")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "emailAddress"'),
check("password")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "password"'),
check("gender")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "gender"'),
check("sexualPreference")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "sexualPreference"'),
check("age")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "age"'),
check("description")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "description"'),
check("pictures")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "pictures"'),
],
asyncHandler(async (req, res, next) => {
// Attempt to get the validation result from the Request object.
const errors = validationResult(req);
// If there are validation errors...
if (!errors.isEmpty()) {
// Use the Array `map()` method to get a list of error messages.
const errorMessages = errors.array().map((error) => error.msg);
// Return the validation errors to the client.
return res.status(400).json({ errors: errorMessages });
}
//new user request body using mongo model from schema
const postUser = new User({
firstName: req.body.firstName,
lastName: req.body.lastName,
emailAddress: req.body.emailAddress,
password: req.body.password,
gender: req.body.gender,
sexualPreference: req.body.sexualPreference,
age: req.body.age,
description: req.body.description,
pictures: req.body.pictures
});
const userEmail = await User.findOne({
emailAddress: postUser.emailAddress,
});
if (postUser.emailAddress === userEmail) {
console.log("User with this email already exists");
return res.status(500).end();
} else if (postUser) {
//if true salts the password with bcryptjs
let salt = await bcryptjs.genSalt(10);
const hashPass = await bcryptjs.hash(postUser.password, salt);
console.log(hashPass);
postUser.password = hashPass;
postUser.save();
res.json({ postUser });
return res.status(201).end();
} else {
res.status(400).send({ error: "Error: Account not created" }).end();
}
})
);
mongoDb Schema
const mongoose = require('mongoose');
const userSchema = mongoose.Schema( {
firstName:{
type: String,
required: true
},
lastName: {
type: String,
require: true
},
emailAddress: {
type: String,
require: true
},
password:{
type: String,
required: true
},
gender:{
type: String,
required: true
},
sexualPreference: {
type: String,
required: true
},
age: {
type: Number,
required: true
},
description: {
type: String,
required: true
},
pictures: {
type: [{
picURL: String,
}],
},
matches: {
type: [{
Object
}],
},
})
module.exports = mongoose.model('User', userSchema);
login backend and frontend
router.post( "/login", asyncHandler(async (req, res, next) => {
const userBody = req.body;
const user = await User.findOne({ emailAddress: req.body.emailAddress });
if (userBody && user) {
console.log(user);
const authenticated = bcryptjs.compare(userBody.password, user.password);
console.log(authenticated);
if (authenticated) {
console.log("match");
const accessToken = jwt.sign(user.toJSON(), process.env.ACCESS_TOKEN_SECRET, { expiresIn: 86400 });
res.cookie("token", accessToken, { httpOnly: false, maxAge: 86400 });
res.setHeader('Authorization', 'Bearer '+ accessToken);
res.json({
user: user,
accessToken: accessToken,
})
.send()
} else {
res.status(403).send({ error: "Login failed: Please try again" }).end();
}
} else {
res.status(403).send({ error: "Login failed: Please try again" }).end();
}
})
);
import React, { useState} from "react";
import { useHistory } from "react-router";
import axios from "axios";
import { Link } from "react-router-dom";
const api = 'http://localhost:5000';
export default function Login () {
const history = useHistory();
const [ email, setEmail ] = useState("");
const [ pass, setPassword ] = useState("");
const submit = () => {
axios.post(`${api}/login`, { emailAddress: email, password: pass }, {withCredentials: true, credentials: 'include'})
.then(res => {
localStorage.setItem('jwt', res.data.accessToken);
history.push({
pathname: `/user/account/${res.data.user._id}`
});
})
.catch(err => console.log(err));
}
const handleSubmit = (event) => {
event.preventDefault();
submit()
}
return (
<div>
<h1>Login</h1>
<form onSubmit={handleSubmit}>
<input
id="emailAddress"
name="emailAddress"
type="text"
placeholder="emailAddress"
onChange={(e) => setEmail(e.target.value)}
/>
<input
id="password"
name="password"
type="password"
placeholder="Password"
onChange={(e) => setPassword(e.target.value)}
/>
<button type="submit">Submit</button>
<button >Cancel</button>
</form>
<p>Don't have a user account?
<Link to="/user/create-account" >Click here</Link>
to sign up!
</p>
</div>
);
}
first of all you can't upload image like this because you send regular http request if you want to send iamge you need to follow this steps
in the frontend you need to send the request with form data for more info read this blog from mdn what is formData mdn you can do something like that with axios append all of the req body to the formData and add it to the axios add multipart/form-data header
axios({
method: "post",
url: "myurl",
data: bodyFormData,
headers: { "Content-Type": "multipart/form-data" },
})
.then(function (response) {
// handle success
})
.catch(function (response) {
//handle error
});
in the server you need to upload-files-or-images-to-server-using-nodejs

how to get token (at login) in nuxt App using my own backend api?

I'm working on a project with an other person.
I'm doing the backend part and he's doing the frontend part.
Our users can register and login but we can't get the token that I generate in my back api.
I tried to found some sources to do that but nothing seems to be appropriate to our situation
How can we do that?
Thanks :)
Front:
<form #submit.prevent="login" method="post">
<div class="group_field">
<input id="email" v-model="email" type="email" name="email" required>
<label for="email">Email</label>
</div>
<div class="group_field">
<input id="password" v-model="pswd" type="password" name="password" required>
<label for="password">Password</label>
</div>
<button type="submit">
Login
</button>
<small>Pas de compte ? <nuxt-link to="/register">S'inscrire</nuxt-link></small>
</form>
<script>
export default {
data () {
return {
email: '',
pswd: '',
token: '',
error: null
}
},
methods: {
async login () {
try {
await this.$axios.post('http://localhost:3080/login', {
email: this.email,
pswd: this.pswd,
token: this.token
})
this.$router.push('/')
} catch (e) {
this.error = e.response.data.message
}
}
}
}
</script>
Back :
index.js :
router.route('/login')
.post(logger, userController.logUser);
users.js :
export const logUser = async (req, res) => {
if (!req.body.email || !req.body.pswd) return throwBadRequest('Missing parameters', res);
if (!await utils.validateEmail(req.body.email)) return throwBadRequest('Wrong email format', res);
if (!await utils.validatePassword(req.body.pswd)) return throwBadRequest('Wrong password formatmust be: at least 3 char long with 1 uppercase 1 lowercase and 1 number', res);
await UserModel.fetchUser(req.body.email, req.body.pswd, (err, result) => {
if (err) return throwIntServerError(err, res);
req.token = { token: result };
return sendOKWithData({ auth: true, token: result }, res);
});
}
userModel.js :
UserSchema.statics.fetchUser = async function (userEmail, userPswd, cb) {
await this.findOne({ userEmail }, async (err, user) => {
if (err) return cb(err);
if(!user) return cb(new Error('user Not Found'));
const isValid = await bcrypt.compare(userPswd, user.userPswd);
if(isValid === true) {
let token = jwt.sign({ userEmail: userEmail, userPswd: userPswd }, secret, {expiresIn: 86400});
return cb(null, token);
} else {
return null;
}
});
}
I personally use Nuxt auth to login and register users. It is convenient because the main configuration is set in nuxt.config.js. Using axios we have dedicated functions built into Nuxt Auth. Maybe I didn't help centrally with the problem, but maybe I pointed out an additional way out.

Categories

Resources