We take the signup values from the form(at the signup component) and send them to both my controller and store them in the context, use that information in the context to make the signup process and then redirect them to another page.
//signup-card component
import React, { useState } from 'react';
import { Space, Button, Form, Input, Checkbox } from 'antd';
import { signupFunc, loginFunc } from '../services/auth';
import { useContextInfo } from '../hooks/context';
const layout = {
labelCol: { span: 8 },
wrapperCol: { span: 16 },
};
const tailLayout = {
wrapperCol: { offset: 8, span: 16 },
};
const SignupCard = ({ history }) => {
//const [form] = Form.useForm();
const { signup } = useContextInfo();
const [error, setError] = useState(null);
async function onFinish(values) { //traemos valores del form despues de dar SUBMIT
try {
await signupFunc(values)//hacemos signup con los servicios
console.log('Success:', values);
const { data } = await loginFunc(values);//hacemos login justo
signup(data);//usamos la data del context para hacer signhup
history.push("/MainHub")// redirigimos al MainHub
}
catch (e) {
console.log(e);
setError(e.response.data.message)
} finally {
}
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
return (
<Form
{...layout}
name="basic"
initialValues={{ remember: true }}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
>
<Form.Item
label="name"
name="name"
rules={[{ required: true, message: 'Please input your name' }]}
>
<Input />
</Form.Item>
<Form.Item
label="email"
email="email"
rules={[{ required: true, message: 'Please input your email!' }]}
>
<Input />
</Form.Item>
<Form.Item
label="Password"
name="password"
rules={[{ required: true, message: 'Please input your password!' }]}
>
<Input.Password />
</Form.Item>
<Form.Item {...tailLayout} name="remember" valuePropName="checked">
<Checkbox>Remember me</Checkbox>
</Form.Item>
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
)
}
export default SignupCard;
Here's my controller
//Auth controller
const bcrypt = require('bcrypt')
User = require('../models/User') //asking for a model
passport = require('../config/passport')
//SIGN UP CONTROL-------------------------------------------------------------------
exports.signupProcessUser = async (req, res) => {
try {
const { email, password, name } = req.body
if (!email || !password) {
return res.status(403).json({ message: "Please provide an email and a password" })
//validates data being written or not ^
}
const user = await User.findOne({
email,
})
if (user) {
return res.status(401).json({ message: 'user already exists' })
}
const salt = bcrypt.genSaltSync(12)//HASHING PASSWORD LENGTH
const hashPass = bcrypt.hashSync(password, salt)
const newUser = await User.create({
email,
password: hashPass,
name,
})
if (newUser) res.status(201).json(newUser)
//if the user is geniune,we're good to go
} catch (e) {
console.log(e)
res.status(401).json({ message: e })
} finally {
console.log('CONTROLLER signupProcessUser')
}
}
//LOGIN CONTROL-------------------------------------------------------
exports.loginProcess = async (req, res, next) => {
passport.authenticate('local', (err, user, failureDetails) => {
if (err) {
return res.status(500).json({ message: err })
}
if (!user) {
return res.status(401).json({ message: 'no user with that credentials' })
}
req.login(user, (err) => {
if (err) {
return res.status(500).json({ message: err })
}
user.password = null
res.status(200).json(user)
})
})(req, res, next)
}
//---logout---
exports.logout = (req, res) => {
req.session.destroy()
req.logout()
res.status(200).json({ message: 'logged out' })
}
exports.currentUser = (req, res) => {
// console.log('currentUser', req.user);
res.json(req.user || null);
};
//VIEW PROFILE-----------------------------
exports.profileView = async (req, res) => {
try {
const id = req.session.passport.user
const user = Await.User.findById(id)
res.send('profile', user)
} catch (e) {
console.error(e)
res.status(401).json({ message: e })
}
}
//EDIT PROFILE------------------------------
exports.editProfile = async (req, res) => {
try {
//traemos la info del form
const { email, password, name } = req.body
//obtenemos el USER ID
const userId = req.session.passport.user
//actualizamos el email
if (email) {
const user = Await.User.findByIdAndUpdate(
userId,
{
email,
},
{
new: true
}
)
res.status(202).json(user)
}
//Actualizamos el nombre
if (name) {
const user = await User.findByIdAndUpdate(
userId,
{
name: name,
},
{
new: true,
}
)
res.status(202).json(user)
}
//Update PASSWORD
if (password) {
const salt = bcrypt.genSaltSync(12)
const hashPass = bcrypt.hashSync(password, salt)
const user = Await.User.findByIdAndUpdate(
userId,
{
password: hashPass,
},
{
new: true,
}
)
res.status(202).json(user)
}
} catch (e) {
console.log(e.message)
res.status(500).json({ message: e.message })
} finally {
console.log('CONTROLLER Route edit')
}
}
//DELETE profile
exports.deleteProfile = async (req, res) => {
const userId = req.session.passport.user
const user = await User.findById(userId)
let userDeleted = await User.deleteOne({
_id: userId,
})
res.status(200).json({ message: 'Profile deleted' })
}
exports.currentUser = (req, res) => {
res.json(req.user || null)
}
Here's my context file
import React, { useState, createContext, useContext, useEffect } from 'react';
import { currentUserFunc } from '../services/auth';
export const AppContext = createContext();
export const AppCtxProvider = (props) => {
const [user, setUser] = useState(null)
const [userUpdate, setUsrUpdate] = useState(false)
useEffect(() => {
async function getSessionData() {
const { data } = await currentUserFunc()
login(data)
}
getSessionData()
setUsrUpdate(false)
}, [userUpdate])
const login = (userInf) => {
setUser(userInf)
}
const signup = (userInf) => {
setUser(userInf)
}
const logout = () => {
setUser(null)
}
const value = { user, login, logout, signup, setUsrUpdate }
return <AppContext.Provider {...props} value={value} />
}
export const useContextInfo = () => useContext(AppContext)
I already checked up the routes with postman and they work as they should,I can signup the user ,log it in and out, but I can't do that from the browser,I get a 401 error, so, it's either a problem within the controller or the data within the context is not being accepted, but I have no clue why.
here are my router and services(frontend)
//router
import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import Home from './components/home/Home';
import NotFound from './components/404/NotFound.js';
import MainHub from './pages/MainHub';
import LoginPage from './pages/LoginPage';
import LoginCard from './components/LogCard';
import SignupCard from './components/SignCard';
const Router = () => (
<BrowserRouter>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/signup" component={SignupCard} />
<Route exact path="/MainHub" component={MainHub} />
<Route exact path="/login" component={LoginCard} />
<Route component={NotFound} />
</Switch>
</BrowserRouter>
);
export default Router;
//services
import axios from 'axios';
let baseURL;
process.env.NODE_ENV === 'production'
? (baseURL = 'here should be your production endpoint')
: (baseURL = 'http://localhost:3001');
const authService = axios.create({ withCredentials: true, baseURL });
export const signupFunc = (userInf) => authService.post('/signup', userInf);
export const loginFunc = (userInf) => authService.post('/login', userInf);
export const currentUserFunc = () => authService.get('/current-user')
export const logoutFunc = () => authService.get('/logout')
export const deleteFunc = () => authService.get('/deleteProfile')
export const editProfFunc = (userInf) => authService.put('./editProfile', userInf)
Here´s my app.js file
//App.js wirth configured CORS
require('dotenv').config();
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const express = require('express');
const mongoose = require('mongoose');
const logger = require('morgan');
const path = require('path');
const cors = require('cors');
const session = require('express-session');
const passport = require('./config/passport');
mongoose
.connect(process.env.DB, { useNewUrlParser: true, useUnifiedTopology: true })
.then((x) => console.log(`Connected to Mongo! Database name: "${x.connections[0].name}"`))
.catch((err) => console.error('Error connecting to mongo', err));
const app_name = require('./package.json').name;
const debug = require('debug')(`${app_name}:${path.basename(__filename).split('.')[0]}`);
const app = express();
app.use(
cors({
credentials: true,
origin: [
'http://localhost:3001',
'http://localhost:3000',
'http://localhost:3000/current-user',
process.env.FRONTENDPOINT,
"*"]
})
);
app.use(
session({
resave: false,
saveUninitialized: true,
secret: process.env.SECRET,
cookie: { maxAge: 1000 * 60 * 60 }
})
);
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(logger('dev'));
const index = require('./routes/index');
const auth = require('./routes/auth');
app.use('/', index);
app.use('/', auth);
// Uncomment this line for production
// app.get('/*', (req, res) => res.sendFile(__dirname + '/public/index.html'));
module.exports = app;