initial commit
2
.env
Normal file
@@ -0,0 +1,2 @@
|
||||
NODE_ENV="development"
|
||||
JWT_SECRET=kj3h45bl2k34jt23498570q9n8098354t7029358tyowie5uthw8475tyq98347ty834irhfoqi34uyt18
|
||||
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
package-lock.json
|
||||
.vscode
|
||||
16
README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# trainer-api
|
||||
|
||||
RESTful web API for the Trainer App.
|
||||
|
||||
## Install
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
## Run
|
||||
```
|
||||
npm start
|
||||
```
|
||||
|
||||
## Documentation
|
||||
http://localhost:4000
|
||||
15
app.js
Normal file
@@ -0,0 +1,15 @@
|
||||
require("dotenv").config();
|
||||
var express = require("express");
|
||||
var app = express();
|
||||
var router = require("./router");
|
||||
var { testConnection } = require("./config/database");
|
||||
var formidable = require("express-formidable");
|
||||
var cors = require("cors");
|
||||
|
||||
|
||||
testConnection();
|
||||
app.use(cors());
|
||||
app.use(formidable());
|
||||
app.use(router);
|
||||
|
||||
module.exports = app;
|
||||
BIN
assets/1589743589738adopt.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
assets/1589743596506amina.jpg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
assets/1589743602933carla.jpg
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
assets/1589743606893flotfyr.jpeg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
assets/1589743612191frida.jpeg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
assets/1589743618350pava.jpeg
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
assets/1589743622345pia.jpg
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
assets/1589743626930polly.jfif
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
assets/1589743632335primula.jfif
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
assets/1589743636008tristan.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
assets/1589743651917kittens.jpg
Normal file
|
After Width: | Height: | Size: 153 KiB |
BIN
assets/1589743660929save.jpg
Normal file
|
After Width: | Height: | Size: 276 KiB |
BIN
assets/1589743668268internat.jpg
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
assets/1589743672248leading.jpg
Normal file
|
After Width: | Height: | Size: 171 KiB |
BIN
assets/1589743676167volunteer.jpg
Normal file
|
After Width: | Height: | Size: 28 KiB |
46
bin/www
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env node
|
||||
require("dotenv").config();
|
||||
var app = require("../app");
|
||||
var http = require("http");
|
||||
|
||||
// Define a port for the server to listen on
|
||||
var port = process.env.PORT || 4000;
|
||||
app.set("port", port);
|
||||
|
||||
// Create a server instance
|
||||
var server = http.createServer(app);
|
||||
|
||||
// Make the server listen on a port
|
||||
server.listen(port);
|
||||
|
||||
// Handle errors and success
|
||||
server.on("error", onError);
|
||||
server.on("listening", onListening);
|
||||
|
||||
function pipeOrPort(address) {
|
||||
return typeof address == "string" ? `pipe ${address}` : `port ${address.port}`;
|
||||
}
|
||||
|
||||
function onError(error) {
|
||||
if (error.syscall != "listen") {
|
||||
throw error;
|
||||
}
|
||||
|
||||
let bind = pipeOrPort(server.address());
|
||||
|
||||
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() {
|
||||
let bind = pipeOrPort(server.address());
|
||||
console.log(`Listening on ${bind}`);
|
||||
}
|
||||
20
config/database.js
Normal file
@@ -0,0 +1,20 @@
|
||||
var { Sequelize } = require("sequelize");
|
||||
var sequelize = new Sequelize({
|
||||
dialect: "sqlite",
|
||||
storage: "./storage/database.sqlite3",
|
||||
logging: false
|
||||
});
|
||||
|
||||
async function testConnection() {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
console.log("Connection established");
|
||||
} catch (error) {
|
||||
console.error("Unable to connect", error);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
testConnection,
|
||||
sequelize
|
||||
};
|
||||
8
config/sqlite.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
development: {
|
||||
force: true,
|
||||
},
|
||||
production: {
|
||||
force: false,
|
||||
},
|
||||
};
|
||||
16
config/winston.js
Normal file
@@ -0,0 +1,16 @@
|
||||
var winston = require("winston");
|
||||
var expressWinston = require("express-winston");
|
||||
|
||||
var requestLogger = expressWinston.logger({
|
||||
transports: [
|
||||
new winston.transports.Console()
|
||||
],
|
||||
format: winston.format.simple(),
|
||||
expressFormat: true,
|
||||
meta: false,
|
||||
colorize: true,
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
requestLogger
|
||||
};
|
||||
74
controllers/about.controller.js
Normal file
@@ -0,0 +1,74 @@
|
||||
var { About } = require("../models/models");
|
||||
|
||||
async function getSingleAbout(req, res, next) {
|
||||
try {
|
||||
let about = await About.findByPk(parseInt(req.params.id));
|
||||
res.json(about);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function getAllAbouts(req, res, next) {
|
||||
try {
|
||||
let about = await About.findAll();
|
||||
res.json(about);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function createSingleAbout(req, res, next) {
|
||||
try {
|
||||
let about = await About.create({
|
||||
title: req.fields.title,
|
||||
content: req.fields.content
|
||||
});
|
||||
res.json(about);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function updateSingleAbout(req, res, next) {
|
||||
try {
|
||||
let about = await About.findByPk(parseInt(req.params.id));
|
||||
|
||||
if(about) {
|
||||
about.title = req.fields.title;
|
||||
about.content = req.fields.content;
|
||||
about.save();
|
||||
res.json(about);
|
||||
} else {
|
||||
res.status(404).end();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteSingleAbout(req, res, next) {
|
||||
try {
|
||||
await About.destroy({
|
||||
where: {
|
||||
id: parseInt(req.params.id)
|
||||
}
|
||||
})
|
||||
res.end();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createSingleAbout,
|
||||
getSingleAbout,
|
||||
getAllAbouts,
|
||||
updateSingleAbout,
|
||||
deleteSingleAbout
|
||||
};
|
||||
76
controllers/adoptsection.controller.js
Normal file
@@ -0,0 +1,76 @@
|
||||
var { Adoptsection, Asset } = require("../models/models");
|
||||
|
||||
async function getSingleAdoptSection(req, res, next) {
|
||||
try {
|
||||
let adoptsection = await Adoptsection.findByPk(parseInt(req.params.id), { include: [ Asset ] });
|
||||
res.json(adoptsection);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function getAllAdoptSections(req, res, next) {
|
||||
try {
|
||||
let adoptsections = await Adoptsection.findAll({ include: [ Asset ] });
|
||||
res.json(adoptsections);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function createSingleAdoptSection(req, res, next) {
|
||||
try {
|
||||
let adoptsection = await Adoptsection.create({
|
||||
title: req.fields.title,
|
||||
content: req.fields.content,
|
||||
assetId: parseInt(req.fields.assetId)
|
||||
});
|
||||
res.json(adoptsection);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function updateSingleAdoptSection(req, res, next) {
|
||||
try {
|
||||
let adoptsection = await Adoptsection.findByPk(parseInt(req.params.id), { include: [ Asset ] });
|
||||
|
||||
if (adoptsection) {
|
||||
adoptsection.title = req.fields.title;
|
||||
adoptsection.content = req.fields.content;
|
||||
adoptsection.assetId = parseInt(req.fields.assetId);
|
||||
adoptsection.save();
|
||||
res.json(adoptsection);
|
||||
} else {
|
||||
res.status(404).end();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteSingleAdoptSection(req, res, next) {
|
||||
try {
|
||||
await Adoptsection.destroy({
|
||||
where: {
|
||||
id: parseInt(req.params.id)
|
||||
}
|
||||
});
|
||||
res.end();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createSingleAdoptSection,
|
||||
getSingleAdoptSection,
|
||||
getAllAdoptSections,
|
||||
updateSingleAdoptSection,
|
||||
deleteSingleAdoptSection
|
||||
};
|
||||
77
controllers/animal.controller.js
Normal file
@@ -0,0 +1,77 @@
|
||||
var { Animal, Asset } = require("../models/models");
|
||||
|
||||
async function getSingleAnimal(req, res, next) {
|
||||
try {
|
||||
let animal = await Animal.findByPk(parseInt(req.params.id), { include: [ Asset ] });
|
||||
res.json(animal);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function getAllAnimals(req, res, next) {
|
||||
try {
|
||||
let animals = await Animal.findAll({ include: [ Asset ] });
|
||||
res.json(animals);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function createSingleAnimal(req, res, next) {
|
||||
try {
|
||||
let animal = await Animal.create({
|
||||
name: req.fields.name,
|
||||
description: req.fields.description,
|
||||
age: req.fields.age,
|
||||
assetId: parseInt(req.fields.assetId)
|
||||
});
|
||||
res.json(animal);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function updateSingleAnimal(req, res, next) {
|
||||
try {
|
||||
let animal = await Animal.findByPk(parseInt(req.params.id), { include: [ Asset ] });
|
||||
|
||||
if (animal) {
|
||||
animal.name = req.fields.name;
|
||||
animal.description = req.fields.description;
|
||||
animal.assetId = parseInt(req.fields.assetId);
|
||||
animal.save();
|
||||
res.json(animal);
|
||||
} else {
|
||||
res.status(404).end();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteSingleAnimal(req, res, next) {
|
||||
try {
|
||||
await Animal.destroy({
|
||||
where: {
|
||||
id: parseInt(req.params.id)
|
||||
}
|
||||
});
|
||||
res.end();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createSingleAnimal,
|
||||
getSingleAnimal,
|
||||
getAllAnimals,
|
||||
updateSingleAnimal,
|
||||
deleteSingleAnimal
|
||||
};
|
||||
41
controllers/asset.controller.js
Normal file
@@ -0,0 +1,41 @@
|
||||
var { Asset } = require("../models/models");
|
||||
var saveFile = require("../services/asset");
|
||||
|
||||
async function createSingleAsset(req, res, next) {
|
||||
try {
|
||||
let file = saveFile(req.files.file);
|
||||
let asset = await Asset.create({
|
||||
url: "http://localhost:4000/file-bucket/" + file
|
||||
});
|
||||
res.json(asset);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function getAllAssets(req, res, next) {
|
||||
try {
|
||||
let assets = await Asset.findAll();
|
||||
res.json(assets);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function getSingleAsset(req, res, next) {
|
||||
try {
|
||||
let asset = await Asset.findByPk(req.params.id);
|
||||
res.json(asset);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createSingleAsset,
|
||||
getAllAssets,
|
||||
getSingleAsset
|
||||
};
|
||||
44
controllers/subscriber.controller.js
Normal file
@@ -0,0 +1,44 @@
|
||||
var { Subscriber } = require("../models/models");
|
||||
|
||||
async function getAllSubscribers(req, res, next) {
|
||||
try {
|
||||
let subscribers = await Subscriber.findAll();
|
||||
res.json(subscribers);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function createSingleSubscriber(req, res, next) {
|
||||
try {
|
||||
let subscriber = await Subscriber.create({
|
||||
name: req.fields.name,
|
||||
email: req.fields.email
|
||||
});
|
||||
res.json(subscriber);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteSingleSubscriber(req, res, next) {
|
||||
try {
|
||||
await Subscriber.destroy({
|
||||
where: {
|
||||
email: req.params.email
|
||||
}
|
||||
});
|
||||
res.end();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createSingleSubscriber,
|
||||
getAllSubscribers,
|
||||
deleteSingleSubscriber
|
||||
};
|
||||
31
controllers/token.controller.js
Normal file
@@ -0,0 +1,31 @@
|
||||
var { User } = require("../models/models");
|
||||
var { compareSync } = require("bcryptjs");
|
||||
var { sign } = require("jsonwebtoken");
|
||||
|
||||
async function createToken(req, res, next) {
|
||||
try {
|
||||
let user = await User.findOne({ where: { username: req.fields.username } });
|
||||
|
||||
if (!user) return res.status(401).end();
|
||||
|
||||
if (!compareSync(req.fields.password, user.password))
|
||||
return res.status(401).end();
|
||||
|
||||
let token = sign({
|
||||
data: user
|
||||
}, process.env.JWT_SECRET, { expiresIn: "1h" });
|
||||
|
||||
res.json({
|
||||
userId: user.id,
|
||||
token,
|
||||
validUntil: Date.now() + (60*60*1000)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createToken
|
||||
};
|
||||
34
controllers/user.controller.js
Normal file
@@ -0,0 +1,34 @@
|
||||
var { User, Class } = require("../models/models");
|
||||
var { hashSync } = require("bcryptjs");
|
||||
|
||||
async function getSingleUser(req, res, next) {
|
||||
try {
|
||||
let user = await User.findByPk(parseInt(req.params.id));
|
||||
if (user) {
|
||||
res.json(user);
|
||||
} else {
|
||||
res.status(404).end();
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function createSingleUser(req, res, next) {
|
||||
try {
|
||||
let user = await User.create({
|
||||
username: req.fields.username,
|
||||
password: hashSync(req.fields.password, 15)
|
||||
});
|
||||
res.json(user);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createSingleUser,
|
||||
getSingleUser
|
||||
};
|
||||
78
controllers/volunteer.controller.js
Normal file
@@ -0,0 +1,78 @@
|
||||
var { Volunteer, Asset } = require("../models/models");
|
||||
|
||||
async function getSingleVolunteer(req, res, next) {
|
||||
try {
|
||||
let volunteer = await Volunteer.findByPk(parseInt(req.params.id), { include: [ Asset ] });
|
||||
res.json(volunteer);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function getAllVolunteers(req, res, next) {
|
||||
try {
|
||||
let volunteers = await Volunteer.findAll({ include: [ Asset ] });
|
||||
res.json(volunteers);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function createSingleVolunteer(req, res, next) {
|
||||
try {
|
||||
let volunteer = await Volunteer.create({
|
||||
title: req.fields.title,
|
||||
content: req.fields.content,
|
||||
extra: req.fields.extra,
|
||||
assetId: parseInt(req.fields.assetId)
|
||||
});
|
||||
res.json(volunteer);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function updateSingleVolunteer(req, res, next) {
|
||||
try {
|
||||
let volunteer = await Volunteer.findByPk(parseInt(req.params.id), { include: [ Asset ] });
|
||||
|
||||
if (volunteer) {
|
||||
volunteer.title = req.fields.title;
|
||||
volunteer.content = req.fields.content;
|
||||
volunteer.extra = req.fields.extra;
|
||||
volunteer.assetId = parseInt(req.fields.assetId);
|
||||
volunteer.save();
|
||||
res.json(volunteer);
|
||||
} else {
|
||||
res.status(404).end();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteSingleVolunteer(req, res, next) {
|
||||
try {
|
||||
await Volunteer.destroy({
|
||||
where: {
|
||||
id: parseInt(req.params.id)
|
||||
}
|
||||
});
|
||||
res.end();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createSingleVolunteer,
|
||||
getSingleVolunteer,
|
||||
getAllVolunteers,
|
||||
updateSingleVolunteer,
|
||||
deleteSingleVolunteer
|
||||
};
|
||||
15
docs/bundle.css
Normal file
34
docs/bundle.css.map
Normal file
9
docs/bundle.js
Normal file
1
docs/bundle.js.map
Normal file
BIN
docs/favicon.ico
Normal file
|
After Width: | Height: | Size: 32 KiB |
16
docs/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<link rel="stylesheet" href="bundle.css">
|
||||
<script defer src="bundle.js"></script>
|
||||
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"
|
||||
integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
|
||||
</head>
|
||||
<body>
|
||||
<noscript>In order to view this documentation page, you have to enable JavaScript in your web browser.</noscript>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
1
docs/insomnia.json
Normal file
BIN
docs/logo.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
1
docs/rest-api.json
Normal file
31
middleware/auth.js
Normal file
@@ -0,0 +1,31 @@
|
||||
var { verify } = require("jsonwebtoken");
|
||||
|
||||
function isAuthorized(req, res, next) {
|
||||
if (!req.headers.authorization)
|
||||
return res.status(401).end();
|
||||
|
||||
if (req.headers.authorization.split(" ")[0] !== "Bearer")
|
||||
return res.status(403).end();
|
||||
|
||||
if (!verify(req.headers.authorization.split(" ")[1], process.env.JWT_SECRET))
|
||||
return res.status(403).end();
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
function isRelevantUser(req, res, next) {
|
||||
let reqId = req.params.id;
|
||||
let token = req.headers.authorization.split(" ")[1];
|
||||
let decodedToken = verify(token, process.env.JWT_SECRET);
|
||||
|
||||
if (decodedToken.data.id !== parseInt(reqId)) return res.status(403).end();
|
||||
|
||||
if (decodedToken.data.exp < Date.now()) return res.status(403).end();
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isAuthorized,
|
||||
isRelevantUser
|
||||
};
|
||||
73
models/models.js
Normal file
@@ -0,0 +1,73 @@
|
||||
var { DataTypes, Model } = require("sequelize");
|
||||
var { sequelize } = require("../config/database");
|
||||
|
||||
class About extends Model {};
|
||||
class Volunteer extends Model {};
|
||||
class Animal extends Model {};
|
||||
class Asset extends Model {};
|
||||
class Subscriber extends Model {};
|
||||
class Adoptsection extends Model {};
|
||||
class User extends Model {};
|
||||
|
||||
User.init({
|
||||
username: DataTypes.TEXT,
|
||||
password: DataTypes.TEXT
|
||||
}, { sequelize, modelName: "user" });
|
||||
|
||||
About.init({
|
||||
title: DataTypes.TEXT,
|
||||
content: DataTypes.TEXT
|
||||
}, { sequelize, modelName: "about" });
|
||||
|
||||
Volunteer.init({
|
||||
title: DataTypes.TEXT,
|
||||
content: DataTypes.TEXT,
|
||||
extra: DataTypes.TEXT
|
||||
}, { sequelize, modelName: "volunteer" });
|
||||
|
||||
Animal.init({
|
||||
name: DataTypes.TEXT,
|
||||
description: DataTypes.TEXT,
|
||||
age: DataTypes.INTEGER
|
||||
}, { sequelize, modelName: "animal" });
|
||||
|
||||
Asset.init({
|
||||
url: DataTypes.TEXT
|
||||
}, { sequelize, modelName: "asset" });
|
||||
|
||||
Subscriber.init({
|
||||
name: DataTypes.TEXT,
|
||||
email: { type: DataTypes.TEXT, unique: true }
|
||||
}, { sequelize, modelName: "subscriber" });
|
||||
|
||||
Adoptsection.init({
|
||||
title: DataTypes.TEXT,
|
||||
content: DataTypes.TEXT
|
||||
}, { sequelize, modelName: "adoptsection" });
|
||||
|
||||
Animal.belongsTo(Asset, { foreignKey: "assetId" });
|
||||
Asset.hasOne(Animal, { foreignKey: "assetId" });
|
||||
|
||||
Volunteer.belongsTo(Asset, { foreignKey: "assetId" });
|
||||
Asset.hasOne(Volunteer, { foreignKey: "assetId" });
|
||||
|
||||
Adoptsection.belongsTo(Asset, { foreignKey: "assetId" });
|
||||
Asset.hasOne(Adoptsection, { foreignKey: "assetId" });
|
||||
|
||||
sequelize.sync({ force: false })
|
||||
.then(function() {
|
||||
console.log("Tabels created");
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
User,
|
||||
About,
|
||||
Volunteer,
|
||||
Animal,
|
||||
Asset,
|
||||
Subscriber,
|
||||
Adoptsection
|
||||
};
|
||||
29
package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "general-purpose-rest-api",
|
||||
"version": "0.0.0",
|
||||
"description": "A general purpose RESTful web-API written with Express and MySQL",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node bin/www",
|
||||
"dev": "nodemon bin/www",
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"docs": "cd ./docs && npx insomnia-documenter --config ./rest-api.json"
|
||||
},
|
||||
"author": "Brian Emilius <be@rts.dk>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bcryptjs": "^2.4.3",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.17.1",
|
||||
"express-formidable": "^1.2.0",
|
||||
"express-winston": "^4.0.2",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"sequelize": "^5.21.3",
|
||||
"sqlite3": "^4.1.1",
|
||||
"winston": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.2"
|
||||
}
|
||||
}
|
||||
22
router.js
Normal file
@@ -0,0 +1,22 @@
|
||||
var router = require("express").Router();
|
||||
var { readdir } = require("fs");
|
||||
var { join } = require("path");
|
||||
var { requestLogger } = require("./config/winston");
|
||||
|
||||
router.use(requestLogger);
|
||||
|
||||
readdir(join(__dirname, "routes"), routesIterator);
|
||||
|
||||
function routesIterator(err, files) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
files.forEach(file => requireRoute(file));
|
||||
}
|
||||
|
||||
function requireRoute(file) {
|
||||
require(join(__dirname, "routes", file))(router);
|
||||
}
|
||||
|
||||
module.exports = router;
|
||||
10
routes/about.route.js
Normal file
@@ -0,0 +1,10 @@
|
||||
var { createSingleAbout, getSingleAbout, getAllAbouts, updateSingleAbout, deleteSingleAbout } = require("../controllers/about.controller");
|
||||
var { isAuthorized } = require("../middleware/auth");
|
||||
|
||||
module.exports = function(router) {
|
||||
router.post("/api/v1/abouts", isAuthorized, createSingleAbout);
|
||||
router.get("/api/v1/abouts/:id", getSingleAbout);
|
||||
router.get("/api/v1/abouts", getAllAbouts);
|
||||
router.put("/api/v1/abouts/:id", isAuthorized, updateSingleAbout);
|
||||
router.delete("/api/v1/abouts/:id", isAuthorized, deleteSingleAbout);
|
||||
};
|
||||
10
routes/adopsection.route.js
Normal file
@@ -0,0 +1,10 @@
|
||||
var { createSingleAdoptSection, getSingleAdoptSection, getAllAdoptSections, updateSingleAdoptSection, deleteSingleAdoptSection } = require("../controllers/adoptsection.controller");
|
||||
var { isAuthorized } = require("../middleware/auth");
|
||||
|
||||
module.exports = function(router) {
|
||||
router.post("/api/v1/adoptsections", isAuthorized, createSingleAdoptSection);
|
||||
router.get("/api/v1/adoptsections/:id", getSingleAdoptSection);
|
||||
router.get("/api/v1/adoptsections", getAllAdoptSections);
|
||||
router.put("/api/v1/adoptsections/:id", isAuthorized, updateSingleAdoptSection);
|
||||
router.delete("/api/v1/adoptsections/:id", isAuthorized, deleteSingleAdoptSection);
|
||||
};
|
||||
10
routes/animal.route.js
Normal file
@@ -0,0 +1,10 @@
|
||||
var { createSingleAnimal, getSingleAnimal, getAllAnimals, updateSingleAnimal, deleteSingleAnimal } = require("../controllers/animal.controller");
|
||||
var { isAuthorized } = require("../middleware/auth");
|
||||
|
||||
module.exports = function(router) {
|
||||
router.post("/api/v1/animals", isAuthorized, createSingleAnimal);
|
||||
router.get("/api/v1/animals/:id", getSingleAnimal);
|
||||
router.get("/api/v1/animals", getAllAnimals);
|
||||
router.put("/api/v1/animals/:id", isAuthorized, updateSingleAnimal);
|
||||
router.delete("/api/v1/animals/:id", isAuthorized, deleteSingleAnimal);
|
||||
};
|
||||
8
routes/asset.route.js
Normal file
@@ -0,0 +1,8 @@
|
||||
var { createSingleAsset, getAllAssets, getSingleAsset } = require("../controllers/asset.controller");
|
||||
var { isAuthorized } = require("../middleware/auth");
|
||||
|
||||
module.exports = function(router) {
|
||||
router.post("/api/v1/assets", isAuthorized, createSingleAsset);
|
||||
router.get("/api/v1/assets", getAllAssets);
|
||||
router.get("/api/v1/assets/:id", getSingleAsset);
|
||||
};
|
||||
5
routes/file-bucket.route.js
Normal file
@@ -0,0 +1,5 @@
|
||||
var { static } = require("express");
|
||||
|
||||
module.exports = function(router) {
|
||||
router.use("/file-bucket", static("assets"));
|
||||
};
|
||||
5
routes/home.route.js
Normal file
@@ -0,0 +1,5 @@
|
||||
var express = require("express");
|
||||
|
||||
module.exports = function(router) {
|
||||
router.use(express.static("docs"));
|
||||
}
|
||||
8
routes/subscriber.route.js
Normal file
@@ -0,0 +1,8 @@
|
||||
var { createSingleSubscriber, getAllSubscribers, deleteSingleSubscriber } = require("../controllers/subscriber.controller");
|
||||
var { isAuthorized } = require("../middleware/auth");
|
||||
|
||||
module.exports = function(router) {
|
||||
router.post("/api/v1/subscribers", createSingleSubscriber);
|
||||
router.get("/api/v1/subscribers", isAuthorized, getAllSubscribers);
|
||||
router.delete("/api/v1/subscribers/:email", deleteSingleSubscriber);
|
||||
};
|
||||
5
routes/token.route.js
Normal file
@@ -0,0 +1,5 @@
|
||||
var { createToken } = require("../controllers/token.controller");
|
||||
|
||||
module.exports = function(router) {
|
||||
router.post("/auth/token", createToken);
|
||||
};
|
||||
6
routes/user.route.js
Normal file
@@ -0,0 +1,6 @@
|
||||
var { createSingleUser, getSingleUser } = require("../controllers/user.controller");
|
||||
|
||||
module.exports = function(router) {
|
||||
router.get("/api/v1/users/:id", getSingleUser);
|
||||
router.post("/api/v1/users", createSingleUser);
|
||||
};
|
||||
10
routes/volunteer.route.js
Normal file
@@ -0,0 +1,10 @@
|
||||
var { createSingleVolunteer, getSingleVolunteer, getAllVolunteers, updateSingleVolunteer, deleteSingleVolunteer } = require("../controllers/volunteer.controller");
|
||||
var { isAuthorized } = require("../middleware/auth");
|
||||
|
||||
module.exports = function(router) {
|
||||
router.post("/api/v1/volunteers", isAuthorized, createSingleVolunteer);
|
||||
router.get("/api/v1/volunteers/:id", getSingleVolunteer);
|
||||
router.get("/api/v1/volunteers", getAllVolunteers);
|
||||
router.put("/api/v1/volunteers/:id", isAuthorized, updateSingleVolunteer);
|
||||
router.delete("/api/v1/volunteers/:id", isAuthorized, deleteSingleVolunteer);
|
||||
};
|
||||
12
services/asset.js
Normal file
@@ -0,0 +1,12 @@
|
||||
var { readFileSync, writeFileSync } = require("fs");
|
||||
var { join } = require("path");
|
||||
|
||||
function saveFile(file) {
|
||||
let tmpFile = readFileSync(file.path);
|
||||
let newFileName = Date.now() + file.name;
|
||||
let newFile = join(__dirname, "..", "assets", newFileName);
|
||||
writeFileSync(newFile, tmpFile);
|
||||
return newFileName;
|
||||
}
|
||||
|
||||
module.exports = saveFile;
|
||||