Last active
August 2, 2019 14:07
-
-
Save Gabson1/07d7cf52b0069d2ea89b29f608c2b976 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { version } from '../../package.json'; | |
import { Router } from 'express'; | |
import jwt from 'jsonwebtoken' | |
import config from '../config.json'; | |
import passport from 'passport' | |
export default ({ config, db }) => { | |
let api = Router(); | |
api.get('/', (req, res) => { | |
res.json({ version }); | |
}); | |
// LOGIN ROUTE | |
api.post('/login', (req, res) => { | |
if (!req.body.email || !req.body.password) { | |
res.status(422).json({ message: "missing parameter" }); | |
return | |
} | |
db.query('SELECT * FROM users WHERE email = ?', [req.body.email], (err, rows) => { | |
let user = null | |
if (err) {res.status(500) | |
return; | |
} | |
if (rows && rows[0]) { | |
user = rows[0] | |
} | |
if (!user) { | |
res.status(401).json({ | |
message: "no such user found" | |
}); | |
return | |
} else if (user.password === req.body.password) { | |
var payload = { | |
email: req.body.email | |
}; | |
var token = jwt.sign(payload, config.secret); | |
res.json({ | |
message: "ok", | |
token: token | |
}); | |
} else { | |
res.status(401).json({ | |
message: "passwords did not match" | |
}); | |
} | |
}) | |
}); | |
// SIGNUP ROUTE | |
api.post('/signup', (req, res) => { | |
if (!req.body.email || !req.body.password || !req.body.username) { | |
res.status(422).json({ | |
message: "missing parameter" | |
}); | |
return | |
} | |
const user = { | |
username: req.body.username, | |
email: req.body.email, | |
password: req.body.password | |
} | |
// check if user already exists | |
db.query('SELECT * FROM users WHERE email = ?', [user.email], (err, rows) => { | |
if (rows && rows.length > 0) { | |
res.status(401).json({ | |
message: "E-Mail already exist" | |
}); | |
return | |
} | |
// usually this would be a database call: | |
db.query('INSERT INTO users SET ?', user, (err, results) => { | |
if (err) { | |
res.status(500) | |
return; | |
} | |
if (user) { | |
var payload = { email: user.email }; | |
var token = jwt.sign(payload, config.secret); | |
res.json({ | |
message: "ok", | |
token: token | |
}); | |
} else { | |
res.status(500) | |
} | |
}) | |
}) | |
}); | |
// Recipe ROUTE - UNPROTECTED | |
api.get('/recipesall', (req, res) => { | |
db.query('SELECT * FROM recipes', (err, rows) => { | |
res.json({ | |
recipes: rows | |
}); | |
}) | |
}); | |
// Profile ROUTE - PROTECTED | |
api.get('/recipes', passport.authenticate('jwt', { | |
session: false | |
}), (req, res) => { | |
db.query('SELECT * FROM recipes', (err, rows) => { | |
res.json({ | |
recipes: rows | |
}); | |
}) | |
}); | |
// Profile ROUTE - PROTECTED | |
api.get('/recipes', (req, res) => { | |
const user_id = req.user.user_id; | |
db.query('SELECT * FROM recipes WHERE user_id = ?', [user_id], (err, rows) => { | |
res.json({ | |
recipes: rows | |
}); | |
}) | |
}); | |
// // Profile CREATE ROUTE - PROTECTED | |
api.post('/recipe', passport.authenticate('jwt', {session: false}), (req, res) => { | |
console.log(req.user.user_id) | |
const data = { | |
user_id: req.user.id, | |
recipe_name: req.body.name, | |
recipe_meal: req.body.meal, | |
recipe_author: req.body.author, | |
recipe_description: req.body.description, | |
recipe_ingredients: req.body.ingredients, | |
recipe_preparation: req.body.preparation | |
} | |
console.log(req.user) | |
console.log(req.body) | |
db.query('INSERT INTO recipes SET ?', [data], (err, result) => { | |
console.log(data) | |
if (err) { | |
console.log("Err", err) | |
result.status(500) | |
return; | |
} | |
db.query('SELECT * FROM recipes WHERE user_id = ? ', [req.user.user_id], (err, rows) => { | |
if (err) { | |
res.status(500) | |
return; | |
} | |
res.json({recipes: rows}); | |
}) | |
}) | |
}); | |
// // Profile DELETE ROUTE - PROTECTED | |
api.delete('/recipe', passport.authenticate('jwt', {session: false}), (req, res) => { | |
const recipe_id = req.body.recipe_id | |
console.log(req.body) | |
console.log(recipe_id) | |
db.query('DELETE FROM recipes WHERE recipe_id = ?', [req.body.recipe_id], (err, results) => { | |
if (err) { | |
console.log("Err:", err) | |
res.status(500) | |
return; | |
} | |
db.query('SELECT * FROM recipes', (err, rows) => { | |
if (err) { | |
res.status(500) | |
return; | |
} | |
res.json({recipes: rows}); | |
}) | |
}) | |
}); | |
return api; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import express from 'express'; | |
import cors from 'cors'; | |
import morgan from 'morgan'; | |
import bodyParser from 'body-parser'; | |
import initializeDb from './db'; | |
import api from './api'; | |
import config from './config.json'; | |
import passport from 'passport' | |
import { ExtractJwt, Strategy } from 'passport-jwt' | |
let app = express(); | |
const port = process.env.PORT || config.port | |
// logger | |
app.use(morgan('dev')); | |
// 3rd party middleware | |
app.use(cors()); | |
// parse post requests | |
app.use(bodyParser.urlencoded({ extended: false })) | |
app.use(bodyParser.json()); | |
// connect to db | |
initializeDb( db => { | |
// auth | |
var jwtOptions = {} | |
jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken(); | |
jwtOptions.secretOrKey = config.secret; | |
passport.use(new Strategy(jwtOptions, function(jwt_payload, next) { | |
console.log('payload received', jwt_payload); | |
db.query('SELECT * FROM users WHERE email = ?', [jwt_payload.email], (err, rows) => { | |
let user = null | |
if (rows && rows[0]) { | |
user = rows[0] | |
} | |
if (user) { | |
next(null, user); | |
} else { | |
next(null, false); | |
} | |
}) | |
})); | |
app.use(passport.initialize()); | |
// api router | |
app.use('/api', api({ config, db })); | |
app.listen(port, () => { | |
console.log(`Started on port ${port}`); | |
}); | |
}); | |
export default app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CREATE DATABASE IF NOT EXISTS veganLearn; | |
USE veganLearn; | |
SET NAMES utf8mb4; | |
# Dump of table users | |
# ------------------------------------------------------------ | |
DROP TABLE IF EXISTS `users`; | |
CREATE TABLE `users` ( | |
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, | |
`username` varchar(300) CHARACTER SET utf8mb4 NOT NULL DEFAULT '', | |
`email` varchar(300) CHARACTER SET utf8mb4 NOT NULL DEFAULT '', | |
`password` varchar(300) CHARACTER SET utf8mb4 NOT NULL DEFAULT '', | |
PRIMARY KEY (`id`) | |
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | |
INSERT INTO `users` (`id`, `username`, `email`, `password`) VALUES | |
(1, 'Name1', 'Name1@gmail.me', 'Gabriel'), | |
(2, 'Name2', 'Name2@gmail.me', 'Gabriel'), | |
(3, 'Name3', 'Name3@gmail.me', 'Gabriel'), | |
(4, 'Name4', 'Name4@gmail.me', 'Gabriel'), | |
(5, 'Name5', 'Name5@gmail.me', 'Gabriel'), | |
(6, 'Name6', 'Name6@gmail.me', 'Gabriel'), | |
(7, 'Name7', 'Name7@gmail.me', 'Gabriel'), | |
(8, 'Name8', 'Name8@gmail.me', 'Gabriel'), | |
(9, 'Name9', 'Name9@gmail.me', 'Gabriel'); | |
# Dump of table recipes | |
# ------------------------------------------------------------ | |
DROP TABLE IF EXISTS `recipes`; | |
CREATE TABLE `recipes` ( | |
`recipe_id` int(11) unsigned NOT NULL AUTO_INCREMENT, | |
`user_id` int(10) unsigned NOT NULL, | |
`recipe_name` varchar(100) NOT NULL DEFAULT '', | |
`recipe_meal` varchar(100) NOT NULL DEFAULT '', | |
`recipe_author` varchar(100) NOT NULL DEFAULT '', | |
`recipe_description` varchar(100) NOT NULL DEFAULT '', | |
`recipe_ingredients` varchar(100) NOT NULL DEFAULT '', | |
`recipe_preparation` varchar(100) NOT NULL DEFAULT '', | |
PRIMARY KEY (`id`), | |
KEY `recipe_user` (`user_id`), | |
CONSTRAINT `recipe_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) | |
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; | |
INSERT INTO `recipes` (`recipe_id`, `user_id`, `recipe_name`, `recipe_meal`, `recipe_author`, `recipe_description`, `recipe_ingredients`, `recipe_preparation`) VALUES | |
(1, '1', 'Name1', 'dinner', 'Gabriel', 'This is the description', 'These are the ingredients', 'This is the preparation method'), | |
(2, '1', 'Name2', 'dinner', 'Gabriel', 'This is the description', 'These are the ingredients', 'This is the preparation method'), | |
(3, '1', 'Name3', 'dinner', 'Gabriel', 'This is the description', 'These are the ingredients', 'This is the preparation method'), | |
(4, '1', 'Name4', 'dinner', 'Gabriel', 'This is the description', 'These are the ingredients', 'This is the preparation method'), | |
(5, '1', 'Name5', 'dinner', 'Gabriel', 'This is the description', 'These are the ingredients', 'This is the preparation method'), | |
(6, '1', 'Name6', 'dinner', 'Gabriel', 'This is the description', 'These are the ingredients', 'This is the preparation method'), | |
(7, '1', 'Name7', 'dinner', 'Gabriel', 'This is the description', 'These are the ingredients', 'This is the preparation method'), | |
(8, '1', 'Name8', 'dinner', 'Gabriel', 'This is the description', 'These are the ingredients', 'This is the preparation method'), | |
(9, '1', 'Name9', 'dinner', 'Gabriel', 'This is the description', 'These are the ingredients', 'This is the preparation method'); | |
# Dump of table learn | |
# ------------------------------------------------------------ | |
DROP TABLE IF EXISTS `learn`; | |
CREATE TABLE `learn` ( | |
`id` int(24) unsigned NOT NULL AUTO_INCREMENT, | |
`learn_image` int(10) DEFAULT NULL, | |
`learn_url_name` varchar(100) DEFAULT NULL, | |
`learn_name` varchar(100) NOT NULL DEFAULT '', | |
`lean_cuisine` varchar(100) NOT NULL DEFAULT '', | |
`learn_type` varchar(10) NOT NULL DEFAULT '', | |
`learn_description` varchar(100) NOT NULL DEFAULT '', | |
PRIMARY KEY (`id`) | |
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import axios from "axios"; | |
import TextField from "@material-ui/core/TextField"; | |
import Button from "@material-ui/core/Button"; | |
import RecipeCard from "../components/Cards/RecipeCard"; | |
import "../index.css"; | |
export default class Profile extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
recipes: "", | |
recipe_id: "", | |
name: "", | |
author: "", | |
meal: "", | |
description: "", | |
ingredients: "", | |
preparation: "" | |
}; | |
console.log(this.state); | |
} | |
//PROTECTED get all recipes from user | |
componentDidMount() { | |
const jwt = localStorage.getItem("jwt"); | |
console.log(jwt); | |
if (jwt) { | |
axios({ | |
method: "get", | |
url: "http://localhost:4000/api/recipes", | |
headers: { | |
Authorization: "Bearer " + jwt | |
} | |
}).then(response => { | |
console.log(response); | |
this.setState({ data: response.data.recipes }); | |
}); | |
} | |
} | |
handleCreate(event) { | |
const jwt = localStorage.getItem("jwt"); | |
console.log(jwt); | |
axios({ | |
method: "post", | |
data: { | |
name: this.state.name, | |
meal: this.state.meal, | |
author: this.state.author, | |
description: this.state.description, | |
ingredients: this.state.ingredients, | |
preparation: this.state.preparation | |
}, | |
url: "http://localhost:4000/api/recipe", | |
headers: { | |
Authorization: "Bearer " + jwt | |
} | |
}) | |
.then(response => { | |
console.log(response); | |
if (response.status === 200) { | |
console.log("Post Success"); | |
window.location.reload(); | |
} | |
this.setState({ recipe: response.data.recipe }); | |
}) | |
.catch((error, res) => { | |
if (error.response.status === 401) { | |
console.log("Error:", error); | |
alert("Failed"); | |
} | |
}); | |
} | |
handleDelete(recipe) { | |
const jwt = localStorage.getItem("jwt"); | |
console.log(jwt); | |
axios({ | |
method: "delete", | |
data: { | |
recipe_id: this.state.recipe_id | |
}, | |
url: "http://localhost:4000/api/recipe", | |
headers: { | |
Authorization: "Bearer " + jwt | |
} | |
}) | |
.then(response => { | |
console.log(response); | |
if (response.status === 200) { | |
console.log("Delete Success"); | |
window.location.reload(); | |
} | |
this.setState({ recipe: response.data.recipe }); | |
}) | |
.catch((error, res) => { | |
if (error.response.status === 401) { | |
console.log("Error:", error); | |
alert("Failed"); | |
} | |
}); | |
} | |
render() { | |
return ( | |
<div className="container-recipe"> | |
<div className="newRecipe-wrapper"> | |
<div className="newRecipe"> | |
<TextField | |
className="input" | |
helperText="Enter the name of your recipe" | |
label="name" | |
onChange={event => this.setState({ name: event.target.value })} | |
/> | |
<br /> | |
<TextField | |
className="input" | |
helperText="Enter the mealtype" | |
label="meal" | |
onChange={event => this.setState({ meal: event.target.value })} | |
/> | |
<br /> | |
<TextField | |
className="input" | |
helperText="Enter your name" | |
label="Author" | |
onChange={event => this.setState({ author: event.target.value })} | |
/> | |
<br /> | |
<TextField | |
className="input" | |
helperText="Enter a short description of your recipe" | |
label="description" | |
onChange={event => | |
this.setState({ description: event.target.value }) | |
} | |
/> | |
<br /> | |
<TextField | |
className="input" | |
helperText="Enter the ingredients" | |
label="ingredients" | |
onChange={event => | |
this.setState({ ingredients: event.target.value }) | |
} | |
/> | |
<br /> | |
<TextField | |
className="input" | |
helperText="Enter the preparation method" | |
label="preparation" | |
onChange={event => | |
this.setState({ preparation: event.target.value }) | |
} | |
/> | |
<br /> | |
</div> | |
<div className="button-wrapper"> | |
<Button | |
className="button" | |
variant="contained" | |
color="primary" | |
onClick={event => this.handleCreate(event)} | |
> | |
Submit Recipe | |
</Button> | |
</div> | |
</div> | |
<div className="recipeWrapper"> | |
{this.state.data && | |
this.state.data.map((data, key) => { | |
return ( | |
<RecipeCard | |
className="recipeCard" | |
name={data.recipe_name} | |
author={data.recipe_author} | |
meal={data.recipe_meal} | |
description={data.recipe_description} | |
ingredients={data.recipe_ingredients} | |
preparation={data.recipe_preparation} | |
handleDelete={this.handleDelete.bind(this)} | |
/> | |
); | |
})} | |
</div> | |
</div> | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import Button from '@material-ui/core/Button'; | |
import { Typography } from '@material-ui/core'; | |
export default class RecipeCard extends React.Component { | |
handleUpdate(){ | |
if(this.props.handleUpdate){ | |
this.props.handleUpdate(this.props.recipe) | |
} | |
} | |
handleDelete(){ | |
if(this.props.handleDelete){ | |
this.props.handleDelete(this.props.recipe) | |
} | |
} | |
render(){ | |
return( | |
<div onClick={this.props.onClick} className={this.props.className}> | |
<Typography variant="h5" gutterBottom> Name: {this.props.name} </Typography> | |
<Typography variant="body1" gutterBottom> Author: {this.props.author} </Typography> | |
<Typography variant="body1" gutterBottom> Meal: {this.props.meal} </Typography> | |
<Typography variant="body1" gutterBottom> Description: {this.props.description} </Typography> | |
<Typography variant="body1" gutterBottom> Ingredients: {this.props.ingredients} </Typography> | |
<Typography variant="body1" gutterBottom> Preparation: {this.props.preparation} </Typography> | |
<img src={this.props.image} alt={this.props.alt}/> | |
<Button color="primary" variant="contained" onClick={(event) => this.handleDelete(event)}>Delete</Button> | |
</div> | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment