Compare commits
55 commits
Author | SHA1 | Date | |
---|---|---|---|
|
53cebca836 | ||
|
c121746380 | ||
|
e0468e5805 | ||
|
932b93b9c7 | ||
|
2bba8fb6f4 | ||
|
71b6805621 | ||
|
0134087eee | ||
|
38aff94e26 | ||
|
b2cccada23 | ||
|
f67c8e0167 | ||
|
9dc6c5385f | ||
|
dc27bb9f08 | ||
|
c6b8219d1e | ||
|
b18612205a | ||
|
e00a165ce2 | ||
|
faaee98022 | ||
|
219c2f449c | ||
|
218f5de6a0 | ||
|
338eeb4562 | ||
|
b7f909ba09 | ||
|
a850629661 | ||
|
823e6f0de3 | ||
|
8b8f20a6d1 | ||
|
51e379f104 | ||
|
1406f4645b | ||
|
43a5234ab3 | ||
|
cd11c01c9b | ||
|
3e466925d6 | ||
|
2c03395371 | ||
|
3392600861 | ||
|
a09d88684e | ||
|
e93ad5d7b3 | ||
|
dcc78c725b | ||
|
abffdc9438 | ||
|
6d94b5f60c | ||
|
c9652c1366 | ||
|
2397868a5e | ||
|
a737f48433 | ||
|
56ddad5ae9 | ||
|
defd3cf8a0 | ||
|
745bdab145 | ||
|
90f4f688eb | ||
|
8dab5968c3 | ||
|
ca364f202e | ||
|
e4f06185fe | ||
|
405d908a09 | ||
|
b3dc18e57d | ||
|
4b9bed8926 | ||
|
ddce225376 | ||
|
4c6f670297 | ||
|
60cd0f69cc | ||
|
e738d80579 | ||
|
a8dc7f8323 | ||
|
d07237cc6b | ||
|
1eff672f06 |
43 changed files with 11427 additions and 2 deletions
3
.eslintrc.js
Normal file
3
.eslintrc.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = {
|
||||||
|
"extends": "standard"
|
||||||
|
};
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/node_modules
|
77
README.md
77
README.md
|
@ -1,3 +1,76 @@
|
||||||
# cfa-nimes
|
# Projet WEB CFA Nimes
|
||||||
|
|
||||||
Projet WEB
|
## Introduction
|
||||||
|
|
||||||
|
Le but de ce projet est de créer un mini site administrable permettant de visualiser les végétaux visibles sur le lycée.
|
||||||
|
|
||||||
|
## Front
|
||||||
|
|
||||||
|
Le front, partie visible par les visiteurs, se compose de 2 blocs :
|
||||||
|
|
||||||
|
* Header
|
||||||
|
* Main
|
||||||
|
|
||||||
|
### Header
|
||||||
|
|
||||||
|
Le header contient un logo, un menu ainsi qu'une zone de recherche.
|
||||||
|
|
||||||
|
Le menu contient 2 éléments :
|
||||||
|
|
||||||
|
* Plan
|
||||||
|
* Végétaux
|
||||||
|
|
||||||
|
Le plan renvoie sur la page plan.
|
||||||
|
|
||||||
|
Végétaux contient un sous menu listant les différents types de végétaux.
|
||||||
|
|
||||||
|
### Main
|
||||||
|
|
||||||
|
La zone main contient le contenu de la page courante.
|
||||||
|
|
||||||
|
Le site contient 3 types de pages :
|
||||||
|
|
||||||
|
* Page d'accueil
|
||||||
|
* Page listant l'ensemble des végétaux d'une famille
|
||||||
|
* Plan du lycée
|
||||||
|
|
||||||
|
### Recherche
|
||||||
|
|
||||||
|
Le module de recherche permet de faire une recherche AJAX avec auto complétion.
|
||||||
|
|
||||||
|
Le fait de cliquer sur un résultat de la recherche renvoie sur le plan du lycée.
|
||||||
|
|
||||||
|
Sur le plan des marqueurs sont placés aux endroits ou se trouve le végétal recherché.
|
||||||
|
|
||||||
|
Les détails du végétal sont affichés sur la droite.
|
||||||
|
|
||||||
|
### Plan
|
||||||
|
|
||||||
|
La page plan du lycée affiche une carte du lycée.
|
||||||
|
|
||||||
|
Des zones sont cliquables. Un clic sur une zone permet d'afficher, sur la droite, le détails du végétal choisi, de la même manière que lors d'une recherche.
|
||||||
|
|
||||||
|
## Back
|
||||||
|
|
||||||
|
Le back permet aux utilisateurs enregistrés (liste pré définie) de saisir les informations suivantes :
|
||||||
|
* Type de végétaux (permettant de peupler le menu "Végétal")
|
||||||
|
* Végétaux
|
||||||
|
* Placer des marqueurs sur la carte
|
||||||
|
|
||||||
|
### Type de Végétaux
|
||||||
|
|
||||||
|
L'entité "Type de végétaux" contient simplement un nom.
|
||||||
|
|
||||||
|
### Végétaux
|
||||||
|
|
||||||
|
L'entité "Végétaux" contient :
|
||||||
|
* Un nom
|
||||||
|
* Un "type de Végétaux"
|
||||||
|
* Une photo principale
|
||||||
|
* Une ou plusieurs photos secondaires (?)
|
||||||
|
* Une description
|
||||||
|
* Une position sur la carte
|
||||||
|
|
||||||
|
```
|
||||||
|
DEBUG=cfa-nimes:* npm start
|
||||||
|
```
|
||||||
|
|
53
app.js
Normal file
53
app.js
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
const createError = require('http-errors')
|
||||||
|
const express = require('express')
|
||||||
|
const path = require('path')
|
||||||
|
const cookieParser = require('cookie-parser')
|
||||||
|
const logger = require('morgan')
|
||||||
|
const passport = require('passport')
|
||||||
|
const session = require('express-session')
|
||||||
|
const cors = require('cors')
|
||||||
|
|
||||||
|
const app = express()
|
||||||
|
|
||||||
|
require('./libs/passport')(passport)
|
||||||
|
app.use(session({
|
||||||
|
secret: 'CFA_Nimes',
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: false,
|
||||||
|
cookie: {
|
||||||
|
maxAge: 180000
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
app.use(passport.initialize())
|
||||||
|
app.use(passport.session())
|
||||||
|
|
||||||
|
app.set('views', path.join(__dirname, 'views'))
|
||||||
|
app.set('view engine', 'pug')
|
||||||
|
|
||||||
|
app.use(logger('dev'))
|
||||||
|
app.use(express.json())
|
||||||
|
app.use(express.urlencoded({ extended: false }))
|
||||||
|
app.use(cookieParser())
|
||||||
|
app.use(express.static(path.join(__dirname, 'public')))
|
||||||
|
|
||||||
|
app.use(cors())
|
||||||
|
|
||||||
|
app.use('/', require('./routes/vegetableTypes')(passport))
|
||||||
|
app.use('/', require('./routes/vegetables')(passport))
|
||||||
|
app.use('/', require('./routes/properties')(passport))
|
||||||
|
app.use('/', require('./routes/user')(passport))
|
||||||
|
app.use('/', require('./routes/search')(passport))
|
||||||
|
|
||||||
|
app.use(function (req, res, next) {
|
||||||
|
next(createError(404))
|
||||||
|
})
|
||||||
|
|
||||||
|
app.use(function (err, req, res, next) {
|
||||||
|
res.locals.message = err.message
|
||||||
|
res.locals.error = req.app.get('env') === 'development' ? err : {}
|
||||||
|
|
||||||
|
res.status(err.status || 500)
|
||||||
|
res.render('error')
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = app
|
59
bin/www
Executable file
59
bin/www
Executable file
|
@ -0,0 +1,59 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
var app = require('../app')
|
||||||
|
var debug = require('debug')('cfa-nimes:server')
|
||||||
|
var http = require('http')
|
||||||
|
|
||||||
|
var port = normalizePort(process.env.PORT || '3000')
|
||||||
|
app.set('port', port)
|
||||||
|
|
||||||
|
var server = http.createServer(app)
|
||||||
|
|
||||||
|
server.listen(port)
|
||||||
|
server.on('error', onError)
|
||||||
|
server.on('listening', onListening)
|
||||||
|
|
||||||
|
function normalizePort (val) {
|
||||||
|
var port = parseInt(val, 10)
|
||||||
|
|
||||||
|
if (isNaN(port)) {
|
||||||
|
// named pipe
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
if (port >= 0) {
|
||||||
|
// port number
|
||||||
|
return port
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function onError (error) {
|
||||||
|
if (error.syscall !== 'listen') {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
|
var bind = typeof port === 'string'
|
||||||
|
? 'Pipe ' + port
|
||||||
|
: 'Port ' + port
|
||||||
|
|
||||||
|
switch (error.code) {
|
||||||
|
case 'EACCES':
|
||||||
|
console.error(bind + ' requires elevated privileges')
|
||||||
|
process.exit(1)
|
||||||
|
case 'EADDRINUSE':
|
||||||
|
console.error(bind + ' is already in use')
|
||||||
|
process.exit(1)
|
||||||
|
default:
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onListening () {
|
||||||
|
var addr = server.address()
|
||||||
|
var bind = typeof addr === 'string'
|
||||||
|
? 'pipe ' + addr
|
||||||
|
: 'port ' + addr.port
|
||||||
|
debug('Listening on ' + bind)
|
||||||
|
}
|
23
config/config.json
Normal file
23
config/config.json
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"development": {
|
||||||
|
"username": "cfanimes",
|
||||||
|
"password": "kojee9Mo",
|
||||||
|
"database": "cfa_nimes",
|
||||||
|
"host": "cfanimes.c6flpj4u5fit.eu-west-3.rds.amazonaws.com",
|
||||||
|
"dialect": "mysql"
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"username": "root",
|
||||||
|
"password": null,
|
||||||
|
"database": "database_test",
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"dialect": "mysql"
|
||||||
|
},
|
||||||
|
"production": {
|
||||||
|
"username": "cfanimes",
|
||||||
|
"password": "bdGGcaAoEeDgDkwG",
|
||||||
|
"database": "cfanimes",
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"dialect": "mysql"
|
||||||
|
}
|
||||||
|
}
|
106
libs/aws.js
Normal file
106
libs/aws.js
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
const AWS = require('aws-sdk')
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
class Aws {
|
||||||
|
constructor () {
|
||||||
|
AWS.config.update({
|
||||||
|
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
||||||
|
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_send (params, callback) {
|
||||||
|
fs.readFile(params.path, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const base64data = Buffer.from(data, 'binary')
|
||||||
|
const dest = path.join(process.env.AWS_BASEFOLDER, params.filename)
|
||||||
|
const s3 = new AWS.S3()
|
||||||
|
|
||||||
|
s3.putObject({
|
||||||
|
Bucket: process.env.AWS_BUCKET,
|
||||||
|
Key: dest,
|
||||||
|
Body: base64data,
|
||||||
|
ACL: 'public-read'
|
||||||
|
}, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, res)
|
||||||
|
} else {
|
||||||
|
callback(null, {
|
||||||
|
file: process.env.AWS_URL + dest
|
||||||
|
})
|
||||||
|
fs.unlink(params.path, () => { })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_compress (params, callback) {
|
||||||
|
const newFile = params.path + '.' + params.filename.split('.')[1]
|
||||||
|
|
||||||
|
fs.copyFile(params.path, newFile, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
this._send({
|
||||||
|
path: newFile,
|
||||||
|
// path: file[0].path,
|
||||||
|
filename: params.filename
|
||||||
|
}, (err, res) => {
|
||||||
|
callback(err, res)
|
||||||
|
// fs.unlink(file[0].path, () => { })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload file on s3
|
||||||
|
* @param {Object} params {path: String, filename: String}
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
upload (params, callback) {
|
||||||
|
fs.readFile(params.path, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
this._compress(params, callback)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteObjects (files, callback) {
|
||||||
|
const s3 = new AWS.S3()
|
||||||
|
const basePath = process.env.AWS_URL + process.env.AWS_BASEFOLDER
|
||||||
|
let items = []
|
||||||
|
|
||||||
|
files.forEach((file) => {
|
||||||
|
if (file) {
|
||||||
|
items.push({
|
||||||
|
Key: file.replace(basePath, '')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (items.length > 0) {
|
||||||
|
s3.deleteObjects({
|
||||||
|
Bucket: process.env.AWS_BUCKET,
|
||||||
|
Delete: { // required
|
||||||
|
Objects: items
|
||||||
|
}
|
||||||
|
}, callback)
|
||||||
|
} else {
|
||||||
|
callback(null, {
|
||||||
|
code: 200,
|
||||||
|
res: 'No file deleted'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Aws
|
67
libs/passport.js
Normal file
67
libs/passport.js
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
const BasicAuth = require('passport-http').BasicStrategy
|
||||||
|
const bCrypt = require('bcrypt-nodejs')
|
||||||
|
const users = require('../models').Users
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare bcrypt password
|
||||||
|
* @param {Object} user
|
||||||
|
* @param {String} password
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
let isValidPassword = function (user, password) {
|
||||||
|
return bCrypt.compareSync(password, user.password)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function (passport) {
|
||||||
|
passport.serializeUser(
|
||||||
|
function (user, done) {
|
||||||
|
done(null, user.id)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
passport.deserializeUser(
|
||||||
|
function (id, done) {
|
||||||
|
users.findById(id)
|
||||||
|
.then(user => {
|
||||||
|
if (!user) {
|
||||||
|
done(new Error('No user found'), user)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
done(null, user)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
done(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
passport.use(
|
||||||
|
'basic-auth', new BasicAuth({
|
||||||
|
usernameField: 'email',
|
||||||
|
passwordField: 'password',
|
||||||
|
passReqToCallback: true
|
||||||
|
},
|
||||||
|
function (req, email, password, done) {
|
||||||
|
users.find({
|
||||||
|
where: {
|
||||||
|
email: email
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(user => {
|
||||||
|
if (!user) {
|
||||||
|
done(new Error('No user found'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!isValidPassword(user, password)) {
|
||||||
|
return done(null, false, {
|
||||||
|
message: 'Invalid password'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return done(null, user)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
done(e, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
64
libs/resize.js
Normal file
64
libs/resize.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
const fs = require('fs')
|
||||||
|
const resizeImg = require('resize-img')
|
||||||
|
|
||||||
|
class Resize {
|
||||||
|
constructor (width, heigth) {
|
||||||
|
this.size = {
|
||||||
|
width: 128,
|
||||||
|
heigth: 128
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width && heigth) {
|
||||||
|
this.setSize(width, heigth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_createOutputFilename (input) {
|
||||||
|
return `${input}_${this.size.width}x${this.size.heigth}`
|
||||||
|
}
|
||||||
|
|
||||||
|
_resize (input, output, callback) {
|
||||||
|
fs.readFile(input, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
resizeImg(data, this.size)
|
||||||
|
.then(buf => {
|
||||||
|
fs.writeFile(output, buf, (err) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
callback(null, { input: input, output: output, size: this.size })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(callback)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setSize (width, heigth) {
|
||||||
|
this.size = {
|
||||||
|
width: width,
|
||||||
|
heigth: heigth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createThumbnail (file, callback) {
|
||||||
|
this.setSize(128, 128)
|
||||||
|
this._resize(file, this._createOutputFilename(file), callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
createLargeImage (file, callback) {
|
||||||
|
this.setSize(1200, 900)
|
||||||
|
this._resize(file, this._createOutputFilename(file), callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
resize (file, width, heigth, callback) {
|
||||||
|
this.setSize(width, heigth)
|
||||||
|
this._resize(file, this._createOutputFilename(file), callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Resize
|
229
middleware/Pictures.js
Normal file
229
middleware/Pictures.js
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
const pictures = require('../models').vegetablePictures
|
||||||
|
const multer = require('multer')
|
||||||
|
const Vegetables = require('./Vegetables')
|
||||||
|
const path = require('path')
|
||||||
|
const fs = require('fs')
|
||||||
|
const Aws = require('../libs/aws')
|
||||||
|
const Resize = require('../libs/resize')
|
||||||
|
const uuid = require('uuid/v4')
|
||||||
|
|
||||||
|
class Pictures {
|
||||||
|
constructor () {
|
||||||
|
this._upload = multer({
|
||||||
|
storage: multer.diskStorage({}),
|
||||||
|
fileFilter: function (req, file, cb) {
|
||||||
|
const filetypes = /jpg|jpeg|png|JPG|JPEG|PNG/
|
||||||
|
const mimetype = filetypes.test(file.mimetype)
|
||||||
|
const extname = filetypes.test(path.extname(file.originalname).toLowerCase())
|
||||||
|
|
||||||
|
if (mimetype && extname) {
|
||||||
|
return cb(null, true)
|
||||||
|
}
|
||||||
|
cb(new Error('Error: File upload only supports the following filetypes - ' + filetypes))
|
||||||
|
}
|
||||||
|
}).single('picture')
|
||||||
|
}
|
||||||
|
|
||||||
|
_reOrderPictures (position, vegetableId) {
|
||||||
|
pictures.findAll({
|
||||||
|
where: {
|
||||||
|
vegetableId: vegetableId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(items => {
|
||||||
|
items.forEach((item) => {
|
||||||
|
let itemPosition = item.order
|
||||||
|
if (itemPosition >= position) {
|
||||||
|
item.update({ order: itemPosition - 1 })
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(e)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static getAll (req, callback) {
|
||||||
|
Vegetables.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
pictures.findAndCountAll({
|
||||||
|
where: {
|
||||||
|
vegetableId: req.params.vegetablesId
|
||||||
|
},
|
||||||
|
order: [
|
||||||
|
['order', 'ASC']
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then(items => {
|
||||||
|
if (!items) {
|
||||||
|
callback(new Error('No picture found'), 204)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
callback(null, items)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static getOne (req, callback) {
|
||||||
|
Vegetables.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
pictures.find({
|
||||||
|
where: {
|
||||||
|
id: req.params.pictureId,
|
||||||
|
vegetableId: req.params.vegetablesId
|
||||||
|
},
|
||||||
|
order: [
|
||||||
|
['order', 'ASC']
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then(item => {
|
||||||
|
if (!item) {
|
||||||
|
callback(new Error('Picture not found'), 404)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
callback(null, item)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_createOne (req, callback) {
|
||||||
|
pictures.create({
|
||||||
|
order: req.body.order,
|
||||||
|
url: req.body.url,
|
||||||
|
vegetableId: req.params.vegetablesId
|
||||||
|
})
|
||||||
|
.then(item => {
|
||||||
|
callback(null, item)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.log(e)
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
fs.unlink(req.file.path, () => { })
|
||||||
|
}
|
||||||
|
|
||||||
|
createOne (req, callback) {
|
||||||
|
Vegetables.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
Pictures.getAll(req, (err, items) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const order = items.count + 1
|
||||||
|
|
||||||
|
this._upload(req, req.body, (err) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.file) {
|
||||||
|
const key = uuid()
|
||||||
|
let aws = new Aws()
|
||||||
|
let resize = new Resize()
|
||||||
|
|
||||||
|
resize.createLargeImage(req.file.path, (err, large) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
aws.upload({
|
||||||
|
path: large.output,
|
||||||
|
filename: `picture_${req.params.vegetablesId}_${key}_large.${req.file.originalname.split('.')[req.file.originalname.split('.').length - 1]}`
|
||||||
|
}, (err, res) => {
|
||||||
|
if (err) { callback(err, null) }
|
||||||
|
|
||||||
|
req.body = {
|
||||||
|
order: order,
|
||||||
|
url: res.file
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.unlink(large.output, () => { })
|
||||||
|
|
||||||
|
resize.createThumbnail(req.file.path, (err, file) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
aws.upload({
|
||||||
|
path: file.output,
|
||||||
|
filename: `picture_${req.params.vegetablesId}_${key}_thumb.${req.file.originalname.split('.')[req.file.originalname.split('.').length - 1]}`
|
||||||
|
}, (err, res) => {
|
||||||
|
if (err) { callback(err, null) }
|
||||||
|
|
||||||
|
this._createOne(req, callback)
|
||||||
|
fs.unlink(file.output, () => { })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
callback(new Error('No file sent'), 406)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteOne (req, callback) {
|
||||||
|
Pictures.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const aws = new Aws()
|
||||||
|
|
||||||
|
aws.deleteObjects([item.url, item.url.replace('_large.', '_tumb.')], (err) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
pictures.destroy({
|
||||||
|
where: {
|
||||||
|
id: req.params.pictureId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(deleted => {
|
||||||
|
if (deleted === 0) {
|
||||||
|
callback(new Error('Error when trying to delete item'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, null)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Pictures
|
92
middleware/Properties.js
Normal file
92
middleware/Properties.js
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
const properties = require('../models').properties
|
||||||
|
|
||||||
|
class Properties {
|
||||||
|
static getAll (req, callback) {
|
||||||
|
properties.findAndCountAll({
|
||||||
|
order: [
|
||||||
|
['name', 'ASC']
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then(items => {
|
||||||
|
if (!items) {
|
||||||
|
callback(new Error('No property found'), 204)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
callback(null, items)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
createOne (req, callback) {
|
||||||
|
properties.create(req.body)
|
||||||
|
.then(item => {
|
||||||
|
callback(null, item)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static getOne (req, callback) {
|
||||||
|
properties.findById(
|
||||||
|
req.params.propertyId
|
||||||
|
)
|
||||||
|
.then(item => {
|
||||||
|
if (!item) {
|
||||||
|
callback(new Error('Property not found'), 404)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
callback(null, item)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
patchOne (req, callback) {
|
||||||
|
Properties.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
item.update(req.body)
|
||||||
|
.then(animal => {
|
||||||
|
callback(null, animal)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteOne (req, callback) {
|
||||||
|
Properties.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
properties.destroy({
|
||||||
|
where: {
|
||||||
|
id: req.params.propertyId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(deleted => {
|
||||||
|
if (deleted === 0) {
|
||||||
|
callback(new Error('Error when trying to delete item'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, null)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Properties
|
94
middleware/VegetableProperties.js
Normal file
94
middleware/VegetableProperties.js
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
const Vegetables = require('./Vegetables')
|
||||||
|
const vegetableProperties = require('../models').vegetableProperties
|
||||||
|
|
||||||
|
class VegetableProperties {
|
||||||
|
createOne (req, callback) {
|
||||||
|
Vegetables.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
req.body.vegetableId = req.params.vegetablesId
|
||||||
|
|
||||||
|
vegetableProperties.create(req.body)
|
||||||
|
.then(item => {
|
||||||
|
callback(null, item)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static getOne (req, callback) {
|
||||||
|
Vegetables.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
vegetableProperties.findById(
|
||||||
|
req.params.propertyId,
|
||||||
|
{
|
||||||
|
include: ['Vegetable']
|
||||||
|
})
|
||||||
|
.then(item => {
|
||||||
|
if (!item) {
|
||||||
|
callback(new Error('Item vegetable property not found'), 404)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
callback(null, item)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
patchOne (req, callback) {
|
||||||
|
VegetableProperties.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
delete req.body.vegetableId
|
||||||
|
|
||||||
|
item.update(req.body)
|
||||||
|
.then(animal => {
|
||||||
|
callback(null, animal)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteOne (req, callback) {
|
||||||
|
VegetableProperties.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
vegetableProperties.destroy({
|
||||||
|
where: {
|
||||||
|
id: req.params.propertyId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(deleted => {
|
||||||
|
if (deleted === 0) {
|
||||||
|
callback(new Error('Error when trying to delete item'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, null)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = VegetableProperties
|
146
middleware/VegetableTypes.js
Normal file
146
middleware/VegetableTypes.js
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
const models = require('../models')
|
||||||
|
const vegetableTypes = models.vegetableTypes
|
||||||
|
|
||||||
|
class VegetableTypes {
|
||||||
|
static getAll (req, callback) {
|
||||||
|
vegetableTypes.findAndCountAll({
|
||||||
|
order: [
|
||||||
|
['name', 'ASC']
|
||||||
|
],
|
||||||
|
include: [{
|
||||||
|
model: models.vegetables,
|
||||||
|
as: 'Vegetables',
|
||||||
|
order: [
|
||||||
|
['name', 'ASC']
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
.then(items => {
|
||||||
|
if (!items) {
|
||||||
|
callback(new Error('No vegetable type found'), 204)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = []
|
||||||
|
|
||||||
|
for (let i = 0; i < items.rows.length; i += 1) {
|
||||||
|
let type = items.rows[i].toJSON()
|
||||||
|
let vegetables = []
|
||||||
|
|
||||||
|
for (let j = 0; j < type.Vegetables.length; j += 1) {
|
||||||
|
let k = 0
|
||||||
|
for (k = 0; k < vegetables.length; k += 1) {
|
||||||
|
if (type.Vegetables[j].name.localeCompare(vegetables[k].name) === -1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vegetables.splice(k, 0, type.Vegetables[j])
|
||||||
|
}
|
||||||
|
type.Vegetables = vegetables
|
||||||
|
res.push(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, { count: res.length, rows: res })
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log('ERR:', e)
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
createOne (req, callback) {
|
||||||
|
vegetableTypes.create(req.body)
|
||||||
|
.then(item => {
|
||||||
|
callback(null, item)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static getOne (req, callback) {
|
||||||
|
vegetableTypes.findById(
|
||||||
|
req.params.vegetableTypesId,
|
||||||
|
{
|
||||||
|
include: [{
|
||||||
|
model: models.vegetables,
|
||||||
|
as: 'Vegetables',
|
||||||
|
order: [
|
||||||
|
['name', 'ASC']
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
.then(item => {
|
||||||
|
if (!item) {
|
||||||
|
callback(new Error('Item vegetable type not found'), 404)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let type = item.toJSON()
|
||||||
|
let vegetables = []
|
||||||
|
|
||||||
|
for (let j = 0; j < type.Vegetables.length; j += 1) {
|
||||||
|
let k = 0
|
||||||
|
for (k = 0; k < vegetables.length; k += 1) {
|
||||||
|
if (type.Vegetables[j].name.localeCompare(vegetables[k].name) === -1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vegetables.splice(k, 0, type.Vegetables[j])
|
||||||
|
}
|
||||||
|
type.Vegetables = vegetables
|
||||||
|
|
||||||
|
callback(null, type)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
patchOne (req, callback) {
|
||||||
|
VegetableTypes.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
item.update(req.body)
|
||||||
|
.then(animal => {
|
||||||
|
callback(null, animal)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteOne (req, callback) {
|
||||||
|
VegetableTypes.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
vegetableTypes.destroy({
|
||||||
|
where: {
|
||||||
|
id: req.params.vegetableTypesId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(deleted => {
|
||||||
|
if (deleted === 0) {
|
||||||
|
callback(new Error('Error when trying to delete item'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, null)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = VegetableTypes
|
409
middleware/Vegetables.js
Normal file
409
middleware/Vegetables.js
Normal file
|
@ -0,0 +1,409 @@
|
||||||
|
const vegetables = require('../models').vegetables
|
||||||
|
const models = require('../models')
|
||||||
|
const VegetableTypes = require('./VegetableTypes')
|
||||||
|
const uuid = require('uuid/v4')
|
||||||
|
const multer = require('multer')
|
||||||
|
const path = require('path')
|
||||||
|
const fs = require('fs')
|
||||||
|
const Resize = require('../libs/resize')
|
||||||
|
const Aws = require('../libs/aws')
|
||||||
|
const Op = models.Sequelize.Op
|
||||||
|
|
||||||
|
class Vegetables {
|
||||||
|
constructor () {
|
||||||
|
this._upload = multer({
|
||||||
|
storage: multer.diskStorage({}),
|
||||||
|
fileFilter: function (req, file, cb) {
|
||||||
|
const filetypes = /jpg|jpeg|png|JPG|JPEG|PNG/
|
||||||
|
const mimetype = filetypes.test(file.mimetype)
|
||||||
|
const extname = filetypes.test(path.extname(file.originalname).toLowerCase())
|
||||||
|
|
||||||
|
if (mimetype && extname) {
|
||||||
|
return cb(null, true)
|
||||||
|
}
|
||||||
|
cb(new Error('Error: File upload only supports the following filetypes - ' + filetypes))
|
||||||
|
}
|
||||||
|
}).single('mainPicture')
|
||||||
|
}
|
||||||
|
|
||||||
|
_createItem (req, callback) {
|
||||||
|
let newItem = req.body
|
||||||
|
newItem.vegetableTypeId = req.params.vegetableTypesId
|
||||||
|
|
||||||
|
vegetables.create(newItem)
|
||||||
|
.then(item => {
|
||||||
|
models.properties
|
||||||
|
.findAndCountAll()
|
||||||
|
.then(properties => {
|
||||||
|
if (properties && properties.rows.length > 0) {
|
||||||
|
let saved = 0
|
||||||
|
const _callback = () => {
|
||||||
|
if (properties.count === saved) {
|
||||||
|
callback(null, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
properties.rows.forEach(propperty => {
|
||||||
|
models.vegetableProperties
|
||||||
|
.create({
|
||||||
|
vegetableId: item.id,
|
||||||
|
propertyId: propperty.id
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
saved += 1
|
||||||
|
_callback()
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(e)
|
||||||
|
saved += 1
|
||||||
|
_callback()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
callback(null, item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
item.destroy()
|
||||||
|
callback(e, 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_patchOne (item, values, callback) {
|
||||||
|
item.update(values)
|
||||||
|
.then(item => {
|
||||||
|
callback(null, item)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_deleteOne (item, req, callback) {
|
||||||
|
models.vegetablePictures
|
||||||
|
.destroy({
|
||||||
|
where: {
|
||||||
|
vegetableId: req.params.vegetablesId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
models.vegetableProperties
|
||||||
|
.destroy({
|
||||||
|
where: {
|
||||||
|
vegetableId: req.params.vegetablesId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
vegetables.destroy({
|
||||||
|
where: {
|
||||||
|
id: req.params.vegetablesId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(deleted => {
|
||||||
|
if (deleted === 0) {
|
||||||
|
callback(new Error('Error when trying to delete item'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_deleteMedias (path, callback) {
|
||||||
|
const aws = new Aws()
|
||||||
|
if (!callback) {
|
||||||
|
callback = (e) => {
|
||||||
|
if (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aws.deleteObjects([path, path.replace('_large.', '_thumb.')], callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
static getAll (req, callback) {
|
||||||
|
vegetables.findAndCountAll({
|
||||||
|
where: {
|
||||||
|
vegetableTypeId: req.params.vegetableTypesId
|
||||||
|
},
|
||||||
|
include: ['Type'],
|
||||||
|
order: [
|
||||||
|
['name', 'ASC']
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then(items => {
|
||||||
|
if (!items) {
|
||||||
|
callback(new Error('No vegetable found'), 204)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
callback(null, items)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static searchAll (req, callback) {
|
||||||
|
if (!req.query.q || req.query.q.length < 3) {
|
||||||
|
callback(new Error('Minimum 3 letters'), 406)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
vegetables.findAndCountAll({
|
||||||
|
where: {
|
||||||
|
[Op.or]: {
|
||||||
|
name: {
|
||||||
|
[Op.like]: `%${req.query.q}%`
|
||||||
|
},
|
||||||
|
'$Properties.value$': {
|
||||||
|
[Op.like]: `%${req.query.q}%`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
include: ['Type', 'Properties'],
|
||||||
|
order: [
|
||||||
|
['name', 'ASC']
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then(items => {
|
||||||
|
if (!items) {
|
||||||
|
callback(new Error('No vegetable found'), 204)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let vegetables = []
|
||||||
|
|
||||||
|
for (let j = 0; j < items.rows.length; j += 1) {
|
||||||
|
const item = items.rows[j].toJSON()
|
||||||
|
let k = 0
|
||||||
|
for (k = 0; k < vegetables.length; k += 1) {
|
||||||
|
if (item.name.localeCompare(vegetables[k].name) === -1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vegetables.splice(k, 0, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, { count: vegetables.length, rows: vegetables })
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log('ERR:', e)
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
createOne (req, callback) {
|
||||||
|
VegetableTypes.getOne(req, (err, universe) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, universe)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
this._upload(req, req.body, (err) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.file) {
|
||||||
|
let uploaded = 0
|
||||||
|
let aws = new Aws()
|
||||||
|
let thumb = new Resize()
|
||||||
|
let large = new Resize()
|
||||||
|
const key = uuid()
|
||||||
|
let _create = () => {
|
||||||
|
if (uploaded === 2) {
|
||||||
|
this._createItem(req, callback)
|
||||||
|
fs.unlink(req.file.path, () => { })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
large.createLargeImage(req.file.path, (err, file) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
aws.upload({
|
||||||
|
path: file.output,
|
||||||
|
filename: `main_${key}_large.${req.file.originalname.split('.')[req.file.originalname.split('.').length - 1]}`
|
||||||
|
}, (err, res) => {
|
||||||
|
if (!err) {
|
||||||
|
req.body.mainPicture = res.file
|
||||||
|
uploaded += 1
|
||||||
|
_create()
|
||||||
|
fs.unlink(file.output, () => { })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
thumb.createThumbnail(req.file.path, (err, file) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
aws.upload({
|
||||||
|
path: file.output,
|
||||||
|
filename: `main_${key}_thumb.${req.file.originalname.split('.')[req.file.originalname.split('.').length - 1]}`
|
||||||
|
}, (err, res) => {
|
||||||
|
if (!err) {
|
||||||
|
uploaded += 1
|
||||||
|
_create()
|
||||||
|
fs.unlink(file.output, () => { })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this._createItem(req, callback)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static getOne (req, callback) {
|
||||||
|
vegetables.find({
|
||||||
|
where: {
|
||||||
|
vegetableTypeId: req.params.vegetableTypesId,
|
||||||
|
id: req.params.vegetablesId
|
||||||
|
},
|
||||||
|
include: [
|
||||||
|
'Type',
|
||||||
|
'Pictures',
|
||||||
|
{
|
||||||
|
model: models.vegetableProperties,
|
||||||
|
as: 'Properties',
|
||||||
|
include: ['Property']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then(item => {
|
||||||
|
if (!item) {
|
||||||
|
callback(new Error('Vegetable not found'), 404)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
callback(null, item)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
callback(e, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
patchOne (req, callback) {
|
||||||
|
Vegetables.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
this._upload(req, req.body, (err) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let values = req.body
|
||||||
|
|
||||||
|
if (req.file) {
|
||||||
|
let uploaded = 0
|
||||||
|
let aws = new Aws()
|
||||||
|
let thumb = new Resize()
|
||||||
|
let large = new Resize()
|
||||||
|
const key = uuid()
|
||||||
|
|
||||||
|
if (item.mainPicture !== null && item.mainPicture !== '') {
|
||||||
|
this._deleteMedias(item.mainPicture)
|
||||||
|
}
|
||||||
|
|
||||||
|
let _patch = () => {
|
||||||
|
if (uploaded === 2) {
|
||||||
|
this._patchOne(item, values, callback)
|
||||||
|
fs.unlink(req.file.path, () => { })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
large.createLargeImage(req.file.path, (err, file) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
aws.upload({
|
||||||
|
path: file.output,
|
||||||
|
filename: `main_${key}_large.${req.file.originalname.split('.')[req.file.originalname.split('.').length - 1]}`
|
||||||
|
}, (err, res) => {
|
||||||
|
if (!err) {
|
||||||
|
values.mainPicture = res.file
|
||||||
|
uploaded += 1
|
||||||
|
_patch()
|
||||||
|
fs.unlink(file.output, () => { })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
thumb.createThumbnail(req.file.path, (err, file) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
aws.upload({
|
||||||
|
path: file.output,
|
||||||
|
filename: `main_${key}_thumb.${req.file.originalname.split('.')[req.file.originalname.split('.').length - 1]}`
|
||||||
|
}, (err, res) => {
|
||||||
|
if (!err) {
|
||||||
|
uploaded += 1
|
||||||
|
_patch()
|
||||||
|
fs.unlink(file.output, () => { })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this._patchOne(item, values, callback)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteOne (req, callback) {
|
||||||
|
Vegetables.getOne(req, (err, item) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, item)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.mainPicture !== null && item.mainPicture !== '') {
|
||||||
|
if (!callback) {
|
||||||
|
callback = (e) => {
|
||||||
|
if (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._deleteMedias(item.mainPicture, (e, res) => {
|
||||||
|
if (e) {
|
||||||
|
callback(e, null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
this._deleteOne(item, req, callback)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this._deleteOne(item, req, callback)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Vegetables
|
35
migrations/20180907180037-create-users.js
Normal file
35
migrations/20180907180037-create-users.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.createTable('Users', {
|
||||||
|
id: {
|
||||||
|
allowNull: false,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
firstName: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
lastName: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.dropTable('Users')
|
||||||
|
}
|
||||||
|
}
|
26
migrations/20180907185114-create-vegetables-types.js
Normal file
26
migrations/20180907185114-create-vegetables-types.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.createTable('vegetableTypes', {
|
||||||
|
id: {
|
||||||
|
allowNull: false,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.dropTable('vegetableTypes')
|
||||||
|
}
|
||||||
|
}
|
42
migrations/20180907185312-create-vegetables.js
Normal file
42
migrations/20180907185312-create-vegetables.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.createTable('vegetables', {
|
||||||
|
id: {
|
||||||
|
allowNull: false,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
mainPicture: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: Sequelize.TEXT
|
||||||
|
},
|
||||||
|
lat: {
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
lng: {
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
vegetableTypeId: {
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
references: { model: 'vegetableTypes', key: 'id' }
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.dropTable('vegetables')
|
||||||
|
}
|
||||||
|
}
|
33
migrations/20180907185320-create-vegetables_pictures.js
Normal file
33
migrations/20180907185320-create-vegetables_pictures.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.createTable('vegetablePictures', {
|
||||||
|
id: {
|
||||||
|
allowNull: false,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
vegetableId: {
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
references: { model: 'vegetables', key: 'id' }
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.dropTable('vegetablePictures')
|
||||||
|
}
|
||||||
|
}
|
27
migrations/20181002071412-create-properties.js
Normal file
27
migrations/20181002071412-create-properties.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
'use strict';
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.createTable('properties', {
|
||||||
|
id: {
|
||||||
|
allowNull: false,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.dropTable('properties');
|
||||||
|
}
|
||||||
|
};
|
32
migrations/20181002073641-create-vegetable-properties.js
Normal file
32
migrations/20181002073641-create-vegetable-properties.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.createTable('vegetableProperties', {
|
||||||
|
id: {
|
||||||
|
allowNull: false,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
vegetableId: {
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
propertyId: {
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Sequelize.TEXT
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.dropTable('vegetableProperties')
|
||||||
|
}
|
||||||
|
}
|
35
models/index.js
Normal file
35
models/index.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
const Sequelize = require('sequelize')
|
||||||
|
const basename = path.basename(__filename)
|
||||||
|
const env = process.env.NODE_ENV || 'development'
|
||||||
|
const config = require(path.join(__dirname, '/../config/config.json'))[env]
|
||||||
|
const db = {}
|
||||||
|
|
||||||
|
let sequelize
|
||||||
|
if (config.use_env_variable) {
|
||||||
|
sequelize = new Sequelize(process.env[config.use_env_variable], config)
|
||||||
|
} else {
|
||||||
|
sequelize = new Sequelize(config.database, config.username, config.password, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
fs
|
||||||
|
.readdirSync(__dirname)
|
||||||
|
.filter(file => {
|
||||||
|
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js')
|
||||||
|
})
|
||||||
|
.forEach(file => {
|
||||||
|
const model = sequelize['import'](path.join(__dirname, file))
|
||||||
|
db[model.name] = model
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.keys(db).forEach(modelName => {
|
||||||
|
if (db[modelName].associate) {
|
||||||
|
db[modelName].associate(db)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
db.sequelize = sequelize
|
||||||
|
db.Sequelize = Sequelize
|
||||||
|
|
||||||
|
module.exports = db
|
9
models/properties.js
Normal file
9
models/properties.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
module.exports = (sequelize, DataTypes) => {
|
||||||
|
const Properties = sequelize.define('properties', {
|
||||||
|
name: DataTypes.STRING
|
||||||
|
}, {})
|
||||||
|
Properties.associate = function (models) {
|
||||||
|
// associations can be defined here
|
||||||
|
}
|
||||||
|
return Properties
|
||||||
|
}
|
11
models/users.js
Normal file
11
models/users.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
module.exports = (sequelize, DataTypes) => {
|
||||||
|
const Users = sequelize.define('Users', {
|
||||||
|
firstName: DataTypes.STRING,
|
||||||
|
lastName: DataTypes.STRING,
|
||||||
|
email: DataTypes.STRING,
|
||||||
|
password: DataTypes.STRING
|
||||||
|
}, {})
|
||||||
|
Users.associate = function (models) {
|
||||||
|
}
|
||||||
|
return Users
|
||||||
|
}
|
27
models/vegetable_properties.js
Normal file
27
models/vegetable_properties.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
module.exports = (sequelize, DataTypes) => {
|
||||||
|
const vegetableProperties = sequelize.define('vegetableProperties', {
|
||||||
|
vegetableId: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
references: 'vegetables',
|
||||||
|
referencesKey: 'id'
|
||||||
|
},
|
||||||
|
propertyId: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
references: 'properties',
|
||||||
|
referencesKey: 'id'
|
||||||
|
},
|
||||||
|
value: DataTypes.TEXT
|
||||||
|
}, {})
|
||||||
|
vegetableProperties.associate = function (models) {
|
||||||
|
vegetableProperties.hasOne(models.vegetables, {
|
||||||
|
as: 'Vegetable',
|
||||||
|
foreignKey: 'id'
|
||||||
|
})
|
||||||
|
vegetableProperties.belongsTo(models.properties, {
|
||||||
|
as: 'Property',
|
||||||
|
foreignKey: 'propertyId',
|
||||||
|
targetKey: 'id'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return vegetableProperties
|
||||||
|
}
|
31
models/vegetables.js
Normal file
31
models/vegetables.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
module.exports = (sequelize, DataTypes) => {
|
||||||
|
const vegetables = sequelize.define('vegetables', {
|
||||||
|
name: DataTypes.STRING,
|
||||||
|
mainPicture: DataTypes.STRING,
|
||||||
|
description: DataTypes.TEXT,
|
||||||
|
lat: DataTypes.INTEGER,
|
||||||
|
lng: DataTypes.INTEGER,
|
||||||
|
vegetableTypeId: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
references: 'vegetableTypes',
|
||||||
|
referencesKey: 'id'
|
||||||
|
}
|
||||||
|
}, {})
|
||||||
|
vegetables.associate = function (models) {
|
||||||
|
vegetables.belongsTo(models.vegetableTypes, {
|
||||||
|
as: 'Type',
|
||||||
|
foreignKey: 'vegetableTypeId'
|
||||||
|
})
|
||||||
|
vegetables.hasMany(models.vegetablePictures, {
|
||||||
|
as: 'Pictures',
|
||||||
|
foreignKey: 'vegetableId',
|
||||||
|
onDelete: 'cascade'
|
||||||
|
})
|
||||||
|
vegetables.hasMany(models.vegetableProperties, {
|
||||||
|
as: 'Properties',
|
||||||
|
foreignKey: 'vegetableId',
|
||||||
|
onDelete: 'cascade'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return vegetables
|
||||||
|
}
|
18
models/vegetables_pictures.js
Normal file
18
models/vegetables_pictures.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
module.exports = (sequelize, DataTypes) => {
|
||||||
|
const vegetablePictures = sequelize.define('vegetablePictures', {
|
||||||
|
url: DataTypes.STRING,
|
||||||
|
order: DataTypes.INTEGER,
|
||||||
|
vegetableId: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
references: 'vegetables',
|
||||||
|
referencesKey: 'id'
|
||||||
|
}
|
||||||
|
}, {})
|
||||||
|
vegetablePictures.associate = function(models) {
|
||||||
|
vegetablePictures.hasOne(models.vegetables, {
|
||||||
|
as: 'Vegetables',
|
||||||
|
foreignKey: 'id'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return vegetablePictures
|
||||||
|
}
|
13
models/vegetables_types.js
Normal file
13
models/vegetables_types.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
module.exports = (sequelize, DataTypes) => {
|
||||||
|
const vegetableTypes = sequelize.define('vegetableTypes', {
|
||||||
|
name: DataTypes.STRING
|
||||||
|
}, {})
|
||||||
|
vegetableTypes.associate = function (models) {
|
||||||
|
vegetableTypes.hasMany(models.vegetables, {
|
||||||
|
as: 'Vegetables',
|
||||||
|
onDelete: 'cascade',
|
||||||
|
foreignKey: 'vegetableTypeId'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return vegetableTypes
|
||||||
|
}
|
9172
package-lock.json
generated
Normal file
9172
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
40
package.json
Normal file
40
package.json
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"name": "cfa-nimes",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"start": "nodejs ./bin/www",
|
||||||
|
"dev": "DEBUG=myapp:* nodemon"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"aws-sdk": "^2.311.0",
|
||||||
|
"bcrypt-nodejs": "0.0.3",
|
||||||
|
"cookie-parser": "~1.4.3",
|
||||||
|
"cors": "^2.8.4",
|
||||||
|
"debug": "~2.6.9",
|
||||||
|
"express": "~4.16.0",
|
||||||
|
"express-session": "^1.15.6",
|
||||||
|
"http-errors": "~1.6.2",
|
||||||
|
"imagemin": "^6.0.0",
|
||||||
|
"imagemin-jpegtran": "^5.0.2",
|
||||||
|
"imagemin-pngquant": "^6.0.0",
|
||||||
|
"morgan": "~1.9.0",
|
||||||
|
"multer": "^1.3.1",
|
||||||
|
"mysql2": "^1.6.1",
|
||||||
|
"passport": "^0.4.0",
|
||||||
|
"passport-http": "^0.3.0",
|
||||||
|
"pug": "2.0.0-beta11",
|
||||||
|
"resize-img": "^1.1.2",
|
||||||
|
"sequelize": "^4.38.0",
|
||||||
|
"uuid": "^3.3.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^5.5.0",
|
||||||
|
"eslint-config-standard": "^12.0.0",
|
||||||
|
"eslint-plugin-import": "^2.14.0",
|
||||||
|
"eslint-plugin-node": "^7.0.1",
|
||||||
|
"eslint-plugin-promise": "^4.0.1",
|
||||||
|
"eslint-plugin-standard": "^4.0.0",
|
||||||
|
"gulp": "^4.0.0"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/40676339_1228322073974201_6754233297305337856_n.jpg
Normal file
BIN
public/40676339_1228322073974201_6754233297305337856_n.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
BIN
public/40684029_340720676473669_8185729820999548928_n.jpg
Normal file
BIN
public/40684029_340720676473669_8185729820999548928_n.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
public/40875936_1833802126696967_5201800299966103552_n.jpg
Normal file
BIN
public/40875936_1833802126696967_5201800299966103552_n.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
8
public/stylesheets/style.css
Normal file
8
public/stylesheets/style.css
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
body {
|
||||||
|
padding: 50px;
|
||||||
|
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #00B7FF;
|
||||||
|
}
|
75
routes/properties.js
Normal file
75
routes/properties.js
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
const express = require('express')
|
||||||
|
const router = express.Router()
|
||||||
|
const Properties = require('../middleware/Properties')
|
||||||
|
|
||||||
|
module.exports = function (passport) {
|
||||||
|
const basePath = '/api/properties/'
|
||||||
|
const itemPath = basePath + ':propertyId'
|
||||||
|
|
||||||
|
router.route(basePath)
|
||||||
|
.get(
|
||||||
|
function (req, res) {
|
||||||
|
Properties.getAll(req, function (err, items) {
|
||||||
|
if (err) {
|
||||||
|
res.status(items || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(items)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.post(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const property = new Properties()
|
||||||
|
property.createOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(201).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
router.route(itemPath)
|
||||||
|
.get(
|
||||||
|
function (req, res) {
|
||||||
|
Properties.getOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.patch(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const property = new Properties()
|
||||||
|
property.patchOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.delete(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const property = new Properties()
|
||||||
|
property.deleteOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return router
|
||||||
|
}
|
22
routes/search.js
Normal file
22
routes/search.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
const express = require('express')
|
||||||
|
const router = express.Router()
|
||||||
|
const Vegetables = require('../middleware/Vegetables')
|
||||||
|
|
||||||
|
module.exports = function () {
|
||||||
|
const basePath = '/api/search/vegetables'
|
||||||
|
|
||||||
|
router.route(basePath)
|
||||||
|
.get(
|
||||||
|
function (req, res) {
|
||||||
|
Vegetables.searchAll(req, function (err, items) {
|
||||||
|
if (err) {
|
||||||
|
res.status(items || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(items)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return router
|
||||||
|
}
|
22
routes/user.js
Normal file
22
routes/user.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
const express = require('express')
|
||||||
|
const router = express.Router()
|
||||||
|
|
||||||
|
module.exports = function (passport) {
|
||||||
|
router.route('/api/login/')
|
||||||
|
.post(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
res.status(200).send(req.user)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
router.route('/api/me/')
|
||||||
|
.get(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
res.status(200).send(req.user)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return router
|
||||||
|
}
|
75
routes/vegetableTypes.js
Normal file
75
routes/vegetableTypes.js
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
const express = require('express')
|
||||||
|
const router = express.Router()
|
||||||
|
const VegetableTypes = require('../middleware/VegetableTypes')
|
||||||
|
|
||||||
|
module.exports = function (passport) {
|
||||||
|
const basePath = '/api/types/'
|
||||||
|
const itemPath = basePath + ':vegetableTypesId'
|
||||||
|
|
||||||
|
router.route(basePath)
|
||||||
|
.get(
|
||||||
|
function (req, res) {
|
||||||
|
VegetableTypes.getAll(req, function (err, items) {
|
||||||
|
if (err) {
|
||||||
|
res.status(items || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(items)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.post(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const vegetableTypes = new VegetableTypes()
|
||||||
|
vegetableTypes.createOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(201).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
router.route(itemPath)
|
||||||
|
.get(
|
||||||
|
function (req, res) {
|
||||||
|
VegetableTypes.getOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.patch(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const vegetableTypes = new VegetableTypes()
|
||||||
|
vegetableTypes.patchOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.delete(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const vegetableTypes = new VegetableTypes()
|
||||||
|
vegetableTypes.deleteOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return router
|
||||||
|
}
|
204
routes/vegetables.js
Normal file
204
routes/vegetables.js
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
const express = require('express')
|
||||||
|
const router = express.Router()
|
||||||
|
const Vegetables = require('../middleware/Vegetables')
|
||||||
|
const Pictures = require('../middleware/Pictures')
|
||||||
|
const Properties = require('../middleware/VegetableProperties')
|
||||||
|
|
||||||
|
module.exports = function (passport) {
|
||||||
|
const basePath = '/api/types/:vegetableTypesId/vegetables'
|
||||||
|
const itemPath = basePath + '/:vegetablesId'
|
||||||
|
const picturesPath = itemPath + '/pictures'
|
||||||
|
const picturePath = picturesPath + '/:pictureId'
|
||||||
|
const propertiesPath = itemPath + '/properties'
|
||||||
|
const propertyPath = propertiesPath + '/:propertyId'
|
||||||
|
|
||||||
|
/* Vegetables */
|
||||||
|
router.route(basePath)
|
||||||
|
.get(
|
||||||
|
function (req, res) {
|
||||||
|
Vegetables.getAll(req, function (err, items) {
|
||||||
|
if (err) {
|
||||||
|
res.status(items || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(items)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.post(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const vegetable = new Vegetables()
|
||||||
|
vegetable.createOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(201).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Vegetable */
|
||||||
|
router.route(itemPath)
|
||||||
|
.get(
|
||||||
|
function (req, res) {
|
||||||
|
Vegetables.getOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.patch(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const vegetable = new Vegetables()
|
||||||
|
vegetable.patchOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.delete(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const vegetable = new Vegetables()
|
||||||
|
vegetable.deleteOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Pictures */
|
||||||
|
router.route(picturesPath)
|
||||||
|
.get(
|
||||||
|
function (req, res) {
|
||||||
|
Pictures.getAll(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.post(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const picture = new Pictures()
|
||||||
|
picture.createOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(201).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Picture */
|
||||||
|
router.route(picturePath)
|
||||||
|
.get(
|
||||||
|
function (req, res) {
|
||||||
|
Pictures.getOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.delete(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const picture = new Pictures()
|
||||||
|
picture.deleteOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Properties */
|
||||||
|
router.route(propertiesPath)
|
||||||
|
.get(
|
||||||
|
function (req, res) {
|
||||||
|
Properties.getAll(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.post(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const property = new Properties()
|
||||||
|
property.createOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(201).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Property */
|
||||||
|
router.route(propertyPath)
|
||||||
|
.get(
|
||||||
|
function (req, res) {
|
||||||
|
Properties.getOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.patch(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const property = new Properties()
|
||||||
|
property.patchOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.delete(
|
||||||
|
passport.authenticate(['basic-auth']),
|
||||||
|
function (req, res) {
|
||||||
|
const property = new Properties()
|
||||||
|
property.deleteOne(req, function (err, item) {
|
||||||
|
if (err) {
|
||||||
|
res.status(item || 500).send(err.message)
|
||||||
|
} else {
|
||||||
|
res.status(200).json(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return router
|
||||||
|
}
|
8
run.sh
Executable file
8
run.sh
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
AWS_ACCESS_KEY_ID=AKIAJ67E5YL5KLB7MYQQ \
|
||||||
|
AWS_SECRET_ACCESS_KEY=XxvqJkzH4d8JnAk01/X2uHEHvXgq4shxa4uFqy4M \
|
||||||
|
AWS_BUCKET=cfa-nimes \
|
||||||
|
AWS_BASEFOLDER= \
|
||||||
|
AWS_URL=https://s3.eu-west-3.amazonaws.com/cfa-nimes/ \
|
||||||
|
npm run dev
|
23
seeders/20180907191459-createUsers.js
Normal file
23
seeders/20180907191459-createUsers.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.bulkInsert('Users', [
|
||||||
|
{
|
||||||
|
firstName: 'Damien',
|
||||||
|
lastName: 'Broqua',
|
||||||
|
email: 'contact@darkou.fr',
|
||||||
|
password: '$2a$10$J4M5xlpdvtEGBY6BQhYhHe9Kz1lr9zt6oJB9Wz8qgFaTXdg4w9RvO', // cfanimes
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
firstName: 'Sharlotte',
|
||||||
|
lastName: 'Demerson',
|
||||||
|
email: 'charlotte.cecile@live.fr',
|
||||||
|
password: '$2a$10$J4M5xlpdvtEGBY6BQhYhHe9Kz1lr9zt6oJB9Wz8qgFaTXdg4w9RvO', // cfanimes
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date()
|
||||||
|
}
|
||||||
|
], {})
|
||||||
|
}
|
||||||
|
}
|
6
views/error.pug
Normal file
6
views/error.pug
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
extends layout
|
||||||
|
|
||||||
|
block content
|
||||||
|
h1= message
|
||||||
|
h2= error.status
|
||||||
|
pre #{error.stack}
|
5
views/index.pug
Normal file
5
views/index.pug
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
extends layout
|
||||||
|
|
||||||
|
block content
|
||||||
|
h1= title
|
||||||
|
p Welcome to #{title}
|
7
views/layout.pug
Normal file
7
views/layout.pug
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
doctype html
|
||||||
|
html
|
||||||
|
head
|
||||||
|
title= title
|
||||||
|
link(rel='stylesheet', href='/stylesheets/style.css')
|
||||||
|
body
|
||||||
|
block content
|
Loading…
Reference in a new issue