commit
6d35b93d9b
@ -0,0 +1,5 @@ |
||||
module.exports = app => { |
||||
app.get('/ani', (req, res) => res.send("This is the Natsuki Anime Database API! We're currently at v1, so direct your queries to /ani/v1/.")); |
||||
|
||||
require('./v1/index')(app); |
||||
}; |
@ -0,0 +1,3 @@ |
||||
module.exports = app => { |
||||
app.use('/ani/v1', require('./router')(app)); |
||||
}; |
@ -0,0 +1,15 @@ |
||||
const fs = require('fs'); |
||||
const {Router} = require("express"); |
||||
|
||||
const router = Router(); |
||||
|
||||
module.exports = app => { |
||||
router |
||||
.use((req, res, next) => {console.log(`[ANI/v1] ${req.path} | [${req.method}]`); next()}) |
||||
.get('/', (req, res) => res.send("This is the Natsuki Anime DB API v1 head."))
|
||||
|
||||
fs.readdirSync('./ani/v1/routes').filter(file => file.endsWith('.js')) |
||||
.forEach(route => require(`./routes/${route}`)(app, router)); //execute all router functions
|
||||
|
||||
return router; |
||||
}; |
@ -0,0 +1,77 @@ |
||||
const {hashSync, compareSync} = require('bcrypt'); |
||||
const {sign} = require('jsonwebtoken'); |
||||
|
||||
module.exports = (app, router) => { |
||||
const Users = app.db.models.ani.users; |
||||
|
||||
router.get('/user', (req, res) => res.send("/user: /user/:id required.")); |
||||
|
||||
router.route('/user/:id') |
||||
.get(async (req, res) => { |
||||
if (!req.params.id) {return res.status(400).send("Missing ID!");} |
||||
const user = await Users.findOne({id: req.params.id.toLowerCase()}); |
||||
if (!user) {return res.status(404).send("That user doesn't exist!");} |
||||
return res.json({name: user.name, discord: user.discord, id: user.id, permissions: user.permissions}); |
||||
}) |
||||
.post(async (req, res) => { //TODO validate Discord ID
|
||||
try { |
||||
if (!req.params.id) {return res.status(400).send("Missing ID!");} |
||||
if (await Users.findOne({id: req.params.id.toLowerCase()})) {return res.status(400).send("That user already exists!");} |
||||
if (!req.body) {return res.status(400).send("Missing body!");} |
||||
if ( |
||||
!req.body.name || !req.body.discord || !req.body.permissions || !Array.isArray(req.body.permissions) |
||||
|| !req.body.name.match(/^[\w_ ]+$/gm) || req.body.name.length > 20 |
||||
|| !req.params.id.toLowerCase().match(/^[\w_]+$/gm) || req.params.id.toLowerCase().length > 15 |
||||
|| !req.body.password || req.body.password.length > 30 |
||||
) {return res.status(400).send("Malformed body or missing body data. Make sure you have all the required parameters, and you don't have illegal characters present.");} |
||||
|
||||
const newUser = new Users({ |
||||
id: req.params.id.toLowerCase(),
|
||||
name: req.body.name, |
||||
permissions: req.body.permissions, |
||||
discord: req.body.discord, |
||||
password: hashSync(req.body.password, 8) |
||||
}); |
||||
return newUser.save() |
||||
.then(() => res.json({ |
||||
message: "Successfully added user.",
|
||||
name: newUser.name,
|
||||
discord: newUser.discord,
|
||||
id: newUser.id,
|
||||
permissions: newUser.permissions,
|
||||
accessToken: sign({id: newUser.id}, app.auth.jwt_secret, {expiresIn: "15d"}) |
||||
})) |
||||
.catch(e => {console.error("Error trying to add new user", e); res.status(500).send("Something went wrong.");}); |
||||
} |
||||
catch (e) {console.error("Error trying to add new user", e); res.status(500).send("Something went wrong.");} |
||||
}) |
||||
.put(app.auth.token, async (req, res) => { |
||||
|
||||
}); |
||||
|
||||
router.route('/user/:id/auth') |
||||
.post(async (req, res) => { |
||||
if (!req.params.id) {return res.status(400).send("Missing ID!");} |
||||
const user = await Users.findOne({id: req.params.id.toLowerCase()}); |
||||
if (!user) {return res.status(404).send("That user doesn't exist!");} |
||||
if (!req.body.password || !compareSync(req.body.password, user.password)) {return res.status(401).json({accessToken: null, message: "Invalid or missing password!"});} |
||||
return res.json({ |
||||
message: "Successfully authenticated.",
|
||||
name: user.name,
|
||||
discord: user.discord,
|
||||
id: user.id,
|
||||
permissions: user.permissions,
|
||||
accessToken: sign({id: user.id}, app.auth.jwt_secret, {expiresIn: "15d"}) |
||||
}); |
||||
}) |
||||
.get(app.auth.token, (req, res) => { |
||||
if (!req.user) {return res.status(401).send("You have not been authenticated, and will not be able to access any sensitive routes.");} |
||||
return res.json({ |
||||
message: "You are authenticated, and your token is valid.",
|
||||
name: req.user.name,
|
||||
discord: req.user.discord,
|
||||
id: req.user.id,
|
||||
permissions: req.user.permissions |
||||
}); |
||||
}); |
||||
}; |
@ -0,0 +1,17 @@ |
||||
const {verify} = require("jsonwebtoken"); |
||||
|
||||
module.exports = app => { |
||||
const Users = app.db.models.ani.users |
||||
return (req, res, next) => { |
||||
if (req.headers && req.headers.authorization && req.headers.authorization.split(" ")[0] === "JWT") { |
||||
verify(req.headers.authorization.split(' ')[1], app.auth.jwt_secret, (e, d) => { |
||||
if (e) {req.user = undefined; return next();} |
||||
Users.findOne({id: d.id}) |
||||
.exec((err, user) => { |
||||
if (err) {res.status(500).send("Something went trying to authorize you!");} |
||||
else {req.user = user; next();} |
||||
}); |
||||
}); |
||||
} |
||||
}; |
||||
}; |
@ -0,0 +1,41 @@ |
||||
const express = require('express'); |
||||
const bodyParser = require('body-parser'); |
||||
const cors = require('cors'); |
||||
const helmet = require('helmet'); |
||||
const {set, createConnection} = require('mongoose'); |
||||
|
||||
const app = express(); |
||||
set('strictQuery', false); |
||||
|
||||
app.use(helmet()); |
||||
app.use(bodyParser.json()); |
||||
app.use(cors()); |
||||
app.use(express.urlencoded({extended: true})); |
||||
|
||||
app.get('/', (req, res) => res.send("You've reached the Natsuki API! This 200 status indicates we're online, and currently on v1. Natsuki bot-related queries live at /v1/, ani database queries live at /ani/v1/.")); |
||||
|
||||
app.auth = {}; |
||||
app.auth.jwt_secret = require('../auth.json').jwt_secret; |
||||
|
||||
let server; |
||||
const anidb = createConnection(`mongodb://127.0.0.1:27017/natsuki-anime-api`, { |
||||
useNewUrlParser: true, dbName: 'natsuki-anime-api', useUnifiedTopology: true |
||||
}); |
||||
const botdb = createConnection(`mongodb://127.0.0.1:27017/natsuki-api`, { |
||||
useNewUrlParser: true, dbName: 'natsuki-api', useUnifiedTopology: true |
||||
}); |
||||
console.log("Connected to Mongo Databases"); |
||||
server = app.listen(4062, async () => { |
||||
console.log(`API online at port ${server.address().port}`); |
||||
|
||||
app.db = {}; //set db connections into app object
|
||||
app.db.ani = anidb; |
||||
app.db.bot = botdb; |
||||
|
||||
require('../db/build')(app); //place all models in memory to prevent double-compiling
|
||||
|
||||
app.auth.token = require('./baseAuthorize')(app); //jwt token validation
|
||||
|
||||
require('./v1/index')(app); //initialize bot API branch
|
||||
require('./ani/index')(app); //initialize ani API branch
|
||||
}); |
@ -0,0 +1,3 @@ |
||||
module.exports = (app) => { |
||||
app.get('/v1', (req, res) => res.send("This is the Natsuki API v1 head.")); |
||||
}; |
Loading…
Reference in new issue