Codigo HTML de inicio de sesion, auth.js - html

var auth=firebase.auth();
async function signup_P(email, password) {
var userCredential= await auth.createUserWithEmailAndPassword(email, password);
credentials.email=userCredential.user.email;
credentials.uid=userCredential.user.uid;
console.log("user created! "+JSON.stringify(credentials));
}
async function signin_P(email, password) {
var userCredential= await auth.signInWithEmailAndPassword(email, password);
credentials.email=userCredential.user.email;
credentials.uid=userCredential.user.uid;
console.log("user in! "+JSON.stringify(credentials));
}

Related

How to send a header to a MERN api

I am creating a MERN application and I have a problem, in the back end I have the protected routes through a function called verifytoken that looks for the token as a header, on the other hand, in the front I receive a token that I keep in the local storage, how can I send the local storage as a header when calling that API?
I attach my code
frontend function that receives the token and stores it in localstorage
`import axios from "axios";
const jwtString = 'jwtlibraryyt'
export const loginUser = async (userObj) => {
const response = await axios.post(`http://localhost:3001/login`, userObj);
const { user, token} = response.data;
const {_id, ...userStored} = user;
localStorage.setItem(jwtString, token );
return response;
}`
frontend function that tries to call the protected route and send the local storage as a header
`const Books=()=> {
const [books, setBooks] = useState([]);
useEffect(() => {
getBooks();
},[])
async function getBooks(){
if(!localStorage.getItem("jwtlibraryyt")){
}
else{
const response = await axios.get('http://localhost:3001/books',{ headers: { token:localStorage.getItem('jwtlibraryyt') }});
setBooks(response.data);
}
}`
protected backend path
`router.get('/books', UserController.verifyToken,BookController.allBooks)`
verifytoken function found in the backend
`UserMethods.verifyToken = async (req, res, next) => {
let token = req.headers["token"];
if (!token) return res.status(403).json({ message: "Dame un token" });
try {
const decoded = jwt.verify(token, SECRET='elbicho');
req.currentUserId = decoded._id;
const user = await Users.findById(req.currentUserId, { password: 0 });
if (!user) return res.status(404).json({ message: "No se encontro el usuario" });
next();
} catch (error) {
return res.status(401).json({ message: "Usted no tiene autorizacion" });
}
};`

Where to place code to show data from MySQL to Handlebars?

Goal:
I am aiming to teach myself how to use Node JS, MySQL and express.
I'm struggling to understand where to place my code for loading MySQL data into HTML.
Let me show you the whole code.
app.js
var express = require('express');
var mysql = require('mysql');
var dotenv = require('dotenv');
var path = require('path');
var cookieParser = require('cookie-parser');
dotenv.config({path: './.env'});
var app = express();
// Connection to MySQL
var db = mysql.createConnection({
host: process.env.DATABASE_HOST,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE
});
db.connect(function(error) {
if(error) {
console.log(error);
}
else{
console.log("Connected");
}
});
// Parse URL-Encoded bodies
app.use(express.urlencoded({extended: false}));
// Parse JSON bodies
app.use(express.json());
// Initialize a cookie
app.use(cookieParser());
// View engine to control HTML
app.set('view engine', 'hbs');
// Public dir
var publicDir = path.join(__dirname, './public');
app.use(express.static(publicDir));
// Define routes
app.use('/', require('./routes/pages'));
app.use('/auth', require('./routes/auth'));
app.listen(3000, function() {
console.log("Server is running on port 3000");
});
routes/pages.js
var express = require('express');
var authController = require('../controllers/auth');
var router = express.Router();
// Home
router.get("/", authController.isLoggedIn, function(req,res) {
res.render("index", {
user: req.user
});
});
// Register
router.get("/register", function(req, res) {
res.render("register");
});
// Login
router.get("/login", function(req, res) {
res.render("login");
});
// Profile
router.get('/profile', authController.isLoggedIn, function(req, res) {
if(req.user) {
res.render('profile', {
user: req.user
});
}
else {
res.redirect('login');
}
});
// Forum
router.get('/forums', authController.isLoggedIn, function(req, res) {
if(req.user) {
res.render('forums');
} else {
res.redirect('login');
}
});
// English Division //
// Premier League
router.get('/Leagues/EnglishDivision', authController.isLoggedIn, function(req, res) {
if(req.user) {
res.render('PremierLeague');
} else {
res.redirect('../../login');
}
});
module.exports = router;
routes/auth.js
var express = require('express');
var authController = require('../controllers/auth');
var router = express.Router();
// Register
router.post("/register", authController.register);
// Login
router.post("/login", authController.login);
// Logout
router.get('/logout', authController.logout);
module.exports = router;
controllers/auth.js
var mysql = require('mysql');
var jwt = require('jsonwebtoken');
var bcrypt = require('bcryptjs');
var {promisify} = require('util');
// Connection to MySQL
var db = mysql.createConnection({
host: process.env.DATABASE_HOST,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE
});
// Register function
exports.register = function(req, res) {
console.log(req.body);
var {name, email, password, passwordConfirm} = req.body;
db.query("SELECT email FROM users WHERE email = ?", [email], function(error, result) {
if(error){
console.log(error);
}
if(result.length > 0) {
return res.render('register', {
message: 'That email is already in use'
})
} else if(password !== passwordConfirm) {
return res.render('register', {
message: 'Passwords do not match'
});
}
let hashedPassword = bcrypt.hashSync(password, 8);
console.log(hashedPassword);
// Insert user details into MySQL
db.query('INSERT INTO users set ?', {name: name, email: email, password: hashedPassword, dateJoined: new Date()}, function(error, result) {
if(error) {
console.log(error);
} else {
console.log(result);
return res.render('register', {
message: 'User registered'
});
}
});
});
}
// Login function
exports.login = function(req, res) {
try {
var {email, password} = req.body;
if(!email || !password) {
return res.status(400).render('login', {
message: 'Please provide an email and password'
});
}
db.query('SELECT * FROM users WHERE email = ?', [email], async function(error, result) {
console.log(result);
if(!result.length > 0 || !(await bcrypt.compare(password, result[0].password))) {
res.status(401).render('login', {
message: 'The email or password is incorrect'
});
}
else {
var id = result[0].id;
// Create a token
var token = jwt.sign({id}, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRES_IN
});
console.log("The token is " + token);
// Create a cookie
var cookieOptions = {
expires: new Date(
Date.now() + process.env.JWT_COOKIE_EXPIRES * 24 * 60 * 60 * 1000
),
httpOnly: true
}
// Set up a cookie
res.cookie('jwt', token, cookieOptions);
res.status(200).redirect("/");
}
});
} catch (error) {
console.log(error);
}
}
// Check if logged in
exports.isLoggedIn = async function(req, res, next) {
console.log(req.cookies);
if(req.cookies.jwt){
try {
// Verify the token
var decoded = await promisify(jwt.verify)(req.cookies.jwt, process.env.JWT_SECRET);
console.log(decoded);
// Check if user exist
db.query("SELECT id, name, email, password, date_format(datejoined, '%d/%m/%Y') as dateJoined FROM users WHERE id = ?", [decoded.id], function(error, result) {
console.log(result);
// If no result
if(!result) {
return next();
}
req.user = result[0];
return next();
});
}
catch (e) {
console.log(e);
return next();
}
} else{
next();
}
}
// Logout function
exports.logout = async function(req, res) {
res.clearCookie('jwt');
res.status(200).redirect('/');
}
Question
In my .hbs file called PremierLeague I'd like to load MySQL data in HTML format. Where in the code below I need to start?
Desired goal:
This is when the user clicks into view premier league
Foreach record in MySQL I'd like to add a new card for each record. I know how to use HandleBars {{some.data}}.
I just don't get where I code the query?
Does it needs to be in a controller or can it be in in the router.get(...?
Also how do I use {{#foreach}} correctly ?
You don't need any other specific controller, the right place to code the query is actually the route itself.
But before entering the core of your question, let's talk a while about your code.
I can see you are performing connection to database more than once, you could add database dedicated controller, something like:
controllers/db.js
var mysql = require('mysql');
var dotenv = require('dotenv');
dotenv.config({path: './.env'});
// Connection to MySQL
var db = mysql.createConnection({
host: process.env.DATABASE_HOST,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE
});
function connect(done) {
db.connect(done);
}
module.exports = { db: db, connect: connect };
this let you access to the database instance from every file with just one line:
var db = require('./controllers/db').db;
than you could use the connect function in your app:
app.js
var express = require('express');
var db = require(./controllers/db);
var path = require('path');
var cookieParser = require('cookie-parser');
// set up your server
var app = express();
// Parse URL-Encoded bodies
app.use(express.urlencoded({extended: false}));
// Parse JSON bodies
app.use(express.json());
// Initialize a cookie
app.use(cookieParser());
// View engine to control HTML
app.set('view engine', 'hbs');
// Public dir
var publicDir = path.join(__dirname, './public');
app.use(express.static(publicDir));
// Define routes
app.use('/', require('./routes/pages'));
app.use('/auth', require('./routes/auth'));
// finally run your server only if you can connect to the database
db.connect(function(error) {
if(error) return console.log("Error connecting to the database:", error);
app.listen(3000, function() {
console.log("Server is running on port 3000");
});
});
you could also simplify you controllers/auth.js removing database connection stuff and using only the line to require your database controller.
Finally you can code your query:
routes/pages.js
var express = require('express');
var authController = require('../controllers/auth');
var db = require('../controllers/db').db;
var router = express.Router();
// Omissis... other routes
// Premier League
router.get('/Leagues/EnglishDivision', authController.isLoggedIn, function(req, res) {
// a good practice is first to handle possible exit cases to reduce nesting levels
if(! req.user) return res.redirect('../../login');
// this is actually the right place to perform queries
db.query('SELECT ...', [...], function(error, results) {
// once again first possible exit cases
if(error) return res.status(500).end(error.message)
res.render('PremierLeague', { results: results });
});
});
module.exports = router;
Last in your PremierLeague.hbs file you can handle the results in a #foreach directive.
Just pass your data when you render the view
router.get('/Leagues/EnglishDivision', authController.isLoggedIn, function(req, res) {
if(req.user) {
connection.query('SELECT * FROM EnglishDivision',function (err,results) {
if (err) throw err;
res.render('PremierLeague',{data: results});
});
} else {
res.redirect('../../login');
}
});
then in the .hbs file
{{#each data}}
<div class="card">
<h3>{{this.someData}}</h3>
<h2>{{this.someData}}</h2>
</div>
{{/each}}

Nods.js router throws "SyntaxError: await is only valid in async function"

I have a Nodejs structure that separates the router and the controller.
And I try to use Async-Await inside the controller but I get SyntaxError: await is only valid in async function.
Is my syntax wrong?
Why do I get SyntaxError: await is only valid in async function for Await?
routes
const express = require('express');
const router = express.Router();
const authController = require('../controller/auth_controller');
router.post('/login', authController.login);
module.exports = router;
controller
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const User = require('../model/index');
const { jwtSign } = require('../mixin/jwt');
exports.login = async (req, res, next) => {
const { email, password } = req.body;
const secretKey = req.app.get('jwt-secret');
let sql = `SELECT * FROM user WHERE email = ?`;
try {
User.query(sql, [email], (err, result) => {
...
else {
const token = await jwtSign(secretKey, result[0].userId, email);
...
}
});
} catch (error) {
console.log(error);
}
};
mixin/jwtSign
const jwt = require('jsonwebtoken');
exports.jwtSign = async (secretKey, userId, email) => {
const token = jwt.sign(
{
userId: userId,
email: email
},
secretKey
);
return token;
};
You have to replace:
User.query(sql, [email], (err, result) => {
With:
User.query(sql, [email], async (err, result) => {
To make it an async function.

mysql insertion query and check by postman

I'm stuck in this problem, before postman told me that it lacked the default value and now...
when I run the insert tells me that one of the columns, in this case the column full_name, is not defined
I restarted the database and changed the restrictions for the NN fields
'use strict';
const bcrypt = require('bcrypt');
const Joi = require('joi');
const uuidV4 = require('uuid/v4');
const sendgridMail = require('#sendgrid/mail');
const mysqlPool = require('../../../ddbb/mysql-pool');
sendgridMail.setApiKey(process.env.SENDGRID_API_KEY);
async function validateSchema(payload) {
/**
* rellenar campos obligatorios: nombre, email, contraseña
* nombre String con 3 caracteres mínimos y un máximo de 50
* correo electrónico válido
* contraseña letras mayúsculas, minúscula y número. Mínimo 3 caracteres y máximo 30, usando regular expression
*/
const schema = {
full_name: Joi.string()
.min(3)
.max(50)
.required(),
email: Joi.string()
.email({ minDomainAtoms: 2 })
.required(),
password: Joi.string()
.regex(/^[a-zA-Z0-9]{3,30}$/)
.required(),
};
return Joi.validate(payload, schema);
}
/**
* creo perfil de usuario e inserto uuid y name en tabla users
* #param {number} uuid
* #return {String} name
*/
async function createUserProfile(uuid, name) {
const fullName = full_name;
const verificationCode = uuid;
const sqlQuery = `INSERT INTO users SET ?`;
const connection = await mysqlPool.getConnection();
await connection.query(sqlQuery,{
uuid: verificationCode,
full_name: fullName
});
connection.release();
return fullName;
}
/**
* creo un codigo de verificacion de usuario e inserto
* #param {String} uuid
* #return {String} verificationCode
*/
async function addVerificationCode (uuid){
const verificationCode = uuidV4();
const now = new Date();
const createdAt = now
.toISOString()
.substring(0, 19)
.replace('T', ' ');
const sqlQuery = 'INSERT INTO users_activation SET ?';
const connection = await mysqlPool.getConnection();
await connection.query(sqlQuery, {
users_uuid:uuid,
verification_code: verificationCode,
created_at: createdAt,
});
connection.release();
return verificationCode;
}
/**
* utilizo sendgrid para verificacion del email
* #param {String} userEmail
* #param {String} verificationCode
*/
async function sendEmailRegistration(userEmail, verificationCode) {
const linkActivacion = `${
process.env.API_BASE_URL
}/account/activate?verification_code=${verificationCode}`;
const msg = {
to: userEmail,
from: {
email: 'rebook#yopmail.com',
name: 'reBook',
},
subject: 'Welcome to reBook',
text: 'Where books take on a new life!',
html: `To confirm the account activate it here`,
};
const data = await sendgridMail.send(msg);
return data;
}
async function createAccount(req, res, next) {
const accountData = req.body;
try {
await validateSchema(accountData);
}catch (e) {
return res.status(400).send(e);
}
/**
* inserto usuario en ddbb:
* 3.hash de la password para almacenamiento seguro
*/
const now = new Date();
const securePassword = await bcrypt.hash(accountData.password, 10);
const uuid = uuidV4();
const connection = await mysqlPool.getConnection();
const sqlInsercion = `INSERT INTO users SET ?`;
try {
const result = await connection.query(sqlInsercion, {
uuid: uuid,
email: accountData.email,
password: securePassword,
});
connection.release();
const verificationCode = await addVerificationCode(uuid);
await sendEmailRegistration(accountData.email, verificationCode);
await createUserProfile(uuid, accountData.name);
return res.status(201).send();
} catch (e) {
if(connection){
connection.release();
}
return res.status(500).send(e.message);
}
}
module.exports = createAccount;
This is the json I introduce by postman.
{
"full_name":"Arturo",
"email":"arturos2006#yopmail.com",
"password":"1234567"
}
,and answers me that the full_name field is not defined

If I console.log my results it shows up, but if I return it it doesn't

My return result doesn't make it all the way back to API endpoint.
Do you see what I'm doing wrong?
app.js
const express = require('express');
const app = express();
app.use(express.static('client'));
var GetContracts = require('./contractsService');
app.get('/contracts', async (req, res) => {
var results = await GetContracts.get();
console.log(results);
res.send(results);
});
module.exports = app;
contractsService.js
var mysql = require('mysql');
const config = require('./config')
var con = mysql.createConnection({
host: config.HOST,
user: config.USER,
password: config.PASSWORD,
database: config.DATABASE
});
exports.get = function () {
con.connect(function (err) {
if (err) {
throw new Error('Error by Rodney')
};
con.query("SELECT * FROM " + config.DATABASE + ".Contracts", function (err, result, fields) {
if (err) {
throw new Error('Error by Rodney')
};
return result;
//console.log(result); //works
});
});
}
query method accepts error-first callback that isn't affected by returned value. GetContracts.get doesn't return a promise, and awaiting won't do anything.
It should be promisified in order to be used in promise control flow:
exports.get = function () {
return new Promise((resolve, reject) => {
con.connect(function (err) {
if (err) {
reject(new Error('Error by Rodney'))
};
con.query("SELECT * FROM " + config.DATABASE + ".Contracts", function (err, result, fields) {
if (err) {
reject(new Error('Error by Rodney'));
} else
resolve(result);
});
});
});
}
Or preferably, use existing promise-based MySQL library like promise-mysql, something like:
var mysql = require('promise-mysql');
const conPromise = mysql.createConnection({
host: config.HOST,
user: config.USER,
password: config.PASSWORD,
database: config.DATABASE
});
exports.get = async () => {
const con = await conPromise;
const result = await con.query("SELECT * FROM " + config.DATABASE + ".Contracts");
return result;
};