backup
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
const express = require("express");
|
||||
const cors = require('cors');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const passport = require('passport');
|
||||
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
@@ -14,14 +16,39 @@ if(process.env.NODE_ENV) {
|
||||
const app = express();
|
||||
const connectDB = require("./db");
|
||||
|
||||
// JSON LIMIT EXPRESS
|
||||
app.use(express.json({ limit: '50mb' }));
|
||||
app.use(express.urlencoded({
|
||||
extended: true,
|
||||
limit: '50mb'
|
||||
}));
|
||||
|
||||
// connect database
|
||||
connectDB();
|
||||
|
||||
// CORS
|
||||
app.use(cookieParser());
|
||||
|
||||
app.use(cors({
|
||||
origin: 'http://localhost:3000',
|
||||
credentials: true, // if using cookies/auth
|
||||
}));
|
||||
|
||||
// ROUTES (NO AUTH)
|
||||
app.use('/user', require('./routes/user'));
|
||||
|
||||
// AUTH
|
||||
checkAuth = passport.authenticate('jwt', { session: false });
|
||||
app.use(checkAuth);
|
||||
|
||||
// ROUTES WITH AUTH
|
||||
/*
|
||||
app.use('/campaign', require('./routes/campaign'));
|
||||
app.use('/maps', require('./routes/map'));
|
||||
app.use('/datagen', require('./routes/datagen'));
|
||||
app.use('/admin', require('./routes/admin'));
|
||||
*/
|
||||
|
||||
app.get("/api/test", (req, res) => {
|
||||
console.log("Hey");
|
||||
res.json({"message": "Hello from backend!"});
|
||||
|
||||
16
backend/src/models/User.js
Normal file
16
backend/src/models/User.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const mongoose = require("mongoose");
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
const UserSchema = new Schema({
|
||||
name: {type: String, required: true},
|
||||
username: { type: String, required: true, unique: true },
|
||||
email: { type: String, required: true, unique: true },
|
||||
password: { type: String },
|
||||
date: { type: Date, default: Date.now},
|
||||
admin: {type: Boolean, default: false},
|
||||
image: { type: String },
|
||||
setupCode: { type: String },
|
||||
settings: { type: Object }
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('User', UserSchema);
|
||||
175
backend/src/routes/user.js
Normal file
175
backend/src/routes/user.js
Normal file
@@ -0,0 +1,175 @@
|
||||
const express = require('express')
|
||||
const router = express.Router();
|
||||
|
||||
const bcrypt = require('bcryptjs');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const passport = require('passport');
|
||||
const secret = require('../services/keys').secret;
|
||||
const rateLimitMiddleware = require("../services/rate-limiter");
|
||||
const crypto = require("crypto");
|
||||
|
||||
const { isAdmin } = require('../services/middleware');
|
||||
|
||||
const User = require("../models/User");
|
||||
|
||||
const upload = require("../services/storage");
|
||||
|
||||
|
||||
|
||||
// Admin registers new user
|
||||
router.post('/register', isAdmin, async (req, res) => {
|
||||
try {
|
||||
let setupCode = crypto.randomBytes(64).toString('base64url');
|
||||
|
||||
let user = new User({
|
||||
admin: false,
|
||||
name: crypto.randomBytes(16).toString('base64url'),
|
||||
username: crypto.randomBytes(16).toString('base64url'),
|
||||
email: crypto.randomBytes(16).toString('base64url'),
|
||||
setupCode
|
||||
});
|
||||
|
||||
await user.save();
|
||||
res.json({ status: "ok", code: setupCode });
|
||||
} catch (err) {
|
||||
res.json({ status: "error", msg: "internal" });
|
||||
}
|
||||
});
|
||||
|
||||
// User gets if setup account exists given the query code
|
||||
router.get('/verify-setup', async (req, res) => {
|
||||
try {
|
||||
const user = await User.findOne({ setupCode: req.query.code });
|
||||
if (user) {
|
||||
res.json({ status: "ok", code: req.query.code });
|
||||
} else {
|
||||
res.json({ status: "error", msg: "not-exists" });
|
||||
}
|
||||
} catch (err) {
|
||||
res.json({ status: "error", msg: "internal" });
|
||||
}
|
||||
});
|
||||
|
||||
// User posts the parameters of his new account given by admin
|
||||
router.post('/setup', rateLimitMiddleware, async (req, res) => {
|
||||
const { name, username, email, password } = req.body;
|
||||
const setupCode = req.query.code;
|
||||
|
||||
if (!(name && username && email && password && setupCode)) {
|
||||
return res.json({ status: "error", msg: "params" });
|
||||
}
|
||||
|
||||
try {
|
||||
const user = await User.findOne({ setupCode });
|
||||
if (!user) {
|
||||
return res.json({ status: "error", msg: "not-found" });
|
||||
}
|
||||
|
||||
const sameUser = await User.findOne({ email });
|
||||
if (sameUser) {
|
||||
return res.json({ status: "error", msg: "already-email" });
|
||||
}
|
||||
|
||||
const salt = await bcrypt.genSalt(10);
|
||||
user.password = await bcrypt.hash(password, salt);
|
||||
user.username = username;
|
||||
user.email = email;
|
||||
user.setupCode = undefined;
|
||||
|
||||
await user.save();
|
||||
res.json({ status: "ok" });
|
||||
} catch (err) {
|
||||
res.json({ status: "error", msg: "internal" });
|
||||
}
|
||||
});
|
||||
|
||||
// Login post
|
||||
router.post('/login', rateLimitMiddleware, async (req, res) => {
|
||||
const { username, password } = req.body;
|
||||
|
||||
if (!(username && password)) {
|
||||
return res.json({ status: "error", msg: "params" });
|
||||
}
|
||||
|
||||
try {
|
||||
const user = await User.findOne({ username });
|
||||
if (!user) {
|
||||
return res.json({ status: "error", msg: "wrong" });
|
||||
}
|
||||
|
||||
const isMatch = await bcrypt.compare(password, user.password);
|
||||
if (!isMatch) {
|
||||
return res.json({ status: "error", msg: "wrong" });
|
||||
}
|
||||
|
||||
const payload = {
|
||||
_id: user._id,
|
||||
username: user.username,
|
||||
name: user.name,
|
||||
email: user.email,
|
||||
admin: user.admin,
|
||||
settings: user.settings
|
||||
};
|
||||
|
||||
const token = await new Promise((resolve, reject) => {
|
||||
jwt.sign(payload, secret, { expiresIn: 172800 }, (err, token) => {
|
||||
if (err) reject(err);
|
||||
else resolve(token);
|
||||
});
|
||||
});
|
||||
|
||||
res.json({ status: "ok", token, msg: "success" });
|
||||
} catch (err) {
|
||||
res.json({ status: "error", msg: "internal" });
|
||||
}
|
||||
});
|
||||
|
||||
// Upload avatar post
|
||||
router.post("/upload-avatar", upload.single("image"), passport.authenticate('jwt', {session: false}), async (req, res) => {
|
||||
try {
|
||||
const imageName = req.file.filename;
|
||||
await User.updateOne(req.user, { image: imageName });
|
||||
res.json({ status: "ok", msg: "uploaded" });
|
||||
} catch (err) {
|
||||
res.json({ status: "error", msg: "internal" });
|
||||
}
|
||||
});
|
||||
|
||||
router.get("/retrieve-avatar", async (req, res) => {
|
||||
try {
|
||||
const data = await User.findOne({ username: req.query.username });
|
||||
res.json({ status: "ok", image: data.image });
|
||||
} catch (err) {
|
||||
res.json({ status: "error" });
|
||||
}
|
||||
});
|
||||
|
||||
router.get("/has-admin", async (req, res) => {
|
||||
try {
|
||||
const data = await User.findOne({ admin: true });
|
||||
if (data) res.json({ status: "ok" });
|
||||
else res.json({ status: "init" });
|
||||
} catch (err) {
|
||||
res.json({ status: "error" });
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/update-settings", passport.authenticate('jwt', {session: false}), async (req, res) => {
|
||||
try {
|
||||
await User.updateOne(req.user, { settings: req.body.settings });
|
||||
res.json({ status: "ok", settings: req.body.settings });
|
||||
} catch (err) {
|
||||
res.json({ status: "error", msg: "internal" });
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/get-settings', passport.authenticate('jwt', {session: false}), async (req, res) => {
|
||||
try {
|
||||
const data = await User.findOne(req.user);
|
||||
res.json({ status: "ok", settings: data.settings });
|
||||
} catch (err) {
|
||||
res.json({ status: "error", msg: "internal" });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
5
backend/src/services/keys.js
Normal file
5
backend/src/services/keys.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const fs = require('fs');
|
||||
|
||||
module.exports = {
|
||||
secret: "putyoursecrethere"
|
||||
}
|
||||
17
backend/src/services/middleware.js
Normal file
17
backend/src/services/middleware.js
Normal file
@@ -0,0 +1,17 @@
|
||||
const User = require("../models/User");
|
||||
|
||||
async function isAdmin(req, res, next) {
|
||||
try {
|
||||
const user = await User.findOne(req.user).lean();
|
||||
if (user && user.admin) {
|
||||
return next();
|
||||
}
|
||||
res.json({ status: "error", msg: "unauthorized" });
|
||||
} catch (err) {
|
||||
res.json({ status: "error", msg: err.message });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isAdmin
|
||||
}
|
||||
11
backend/src/services/rate-limiter.js
Normal file
11
backend/src/services/rate-limiter.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const setRateLimit = require("express-rate-limit");
|
||||
|
||||
// Rate limit middleware
|
||||
const rateLimitMiddleware = setRateLimit({
|
||||
windowMs: 60 * 60 * 1000,
|
||||
max: 150,
|
||||
message: "Has fet masses peticions de login en una hora (ets un robot???)",
|
||||
headers: true,
|
||||
});
|
||||
|
||||
module.exports = rateLimitMiddleware;
|
||||
14
backend/src/services/storage.js
Normal file
14
backend/src/services/storage.js
Normal file
@@ -0,0 +1,14 @@
|
||||
const multer = require('multer');
|
||||
|
||||
var storage = multer.diskStorage({
|
||||
destination: function (req, file, cb) {
|
||||
cb(null, 'uploads')
|
||||
},
|
||||
filename: function (req, file, cb) {
|
||||
cb(null, file.fieldname + '-' + Date.now())
|
||||
}
|
||||
});
|
||||
|
||||
var upload = multer({storage: storage});
|
||||
module.exports = upload;
|
||||
|
||||
Reference in New Issue
Block a user