Added File uploads and fetching of said files
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -143,3 +143,4 @@ vite.config.ts.timestamp-*
|
||||
# user files
|
||||
|
||||
/responses
|
||||
/data
|
||||
|
||||
7
.prettierrc
Normal file
7
.prettierrc
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"endOfLine": "lf"
|
||||
}
|
||||
@@ -11,6 +11,8 @@ COPY . .
|
||||
RUN npm prune --production
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine
|
||||
RUN mkdir -p /data
|
||||
RUN chown node /data
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/node_modules node_modules/
|
||||
COPY --from=builder /app/index.js .
|
||||
@@ -18,4 +20,5 @@ COPY --from=builder /app/src src/
|
||||
USER node
|
||||
EXPOSE 12345
|
||||
ENV NODE_ENV=production
|
||||
ENV JEOPARDY_CDN_DATA_PATH=/data
|
||||
CMD [ "node", "."]
|
||||
|
||||
@@ -25,7 +25,7 @@ Ansonsten kann man auch mit `npm run dev` entwickeln.
|
||||
cd /opt/jeopardy/Jeopardy-Server
|
||||
git fetch --tags
|
||||
git checkout <versionsnummer>
|
||||
docker build -t jeopardy .
|
||||
docker build -t jeopardyserver .
|
||||
docker tag jeopardyserver:latest jeopardyserver:<versionsnummer>
|
||||
cd ..
|
||||
docker compose up -d
|
||||
|
||||
32
index.js
32
index.js
@@ -1,25 +1,26 @@
|
||||
import dotenv from "dotenv";
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
import express from "express";
|
||||
import expressWs from "express-ws";
|
||||
import morgan from "morgan";
|
||||
import cookieParser from "cookie-parser";
|
||||
import cors from "cors";
|
||||
import { initWebsocket } from "./src/websocket.js";
|
||||
import { initAuth } from "./src/auth.js";
|
||||
import { close as closeDbConnection, initDbConnection, db } from "./src/db.js";
|
||||
import { initUsers } from "./src/user.js";
|
||||
import express from 'express';
|
||||
import expressWs from 'express-ws';
|
||||
import morgan from 'morgan';
|
||||
import cookieParser from 'cookie-parser';
|
||||
import cors from 'cors';
|
||||
import { initWebsocket } from './src/websocket.js';
|
||||
import { initAuth } from './src/auth.js';
|
||||
import { close as closeDbConnection, initDbConnection, db } from './src/db.js';
|
||||
import { initUsers } from './src/user.js';
|
||||
import { initCdn } from './src/cdn.js';
|
||||
const app = express();
|
||||
const appWs = expressWs(app);
|
||||
const port = 12345;
|
||||
|
||||
process.on('exit', function() {
|
||||
console.log('Shutting down...');
|
||||
console.log('Closing db connection...');
|
||||
closeDbConnection();
|
||||
process.on('exit', function () {
|
||||
console.log('Shutting down...');
|
||||
console.log('Closing db connection...');
|
||||
closeDbConnection();
|
||||
});
|
||||
|
||||
app.use(cors({credentials: true, origin: process.env.JEOPARDY_URL}));
|
||||
app.use(cors({ credentials: true, origin: process.env.JEOPARDY_URL }));
|
||||
app.use(morgan(process.env.production ? 'common' : 'dev'));
|
||||
app.use(express.json());
|
||||
app.use(cookieParser());
|
||||
@@ -29,6 +30,7 @@ await initDbConnection();
|
||||
initAuth(app, db);
|
||||
initUsers(app, db);
|
||||
initWebsocket(app);
|
||||
initCdn(app, db);
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Listening on port ${port}`);
|
||||
|
||||
192
package-lock.json
generated
192
package-lock.json
generated
@@ -17,10 +17,12 @@
|
||||
"express-ws": "^5.0.2",
|
||||
"mongodb": "^6.20.0",
|
||||
"morgan": "^1.10.1",
|
||||
"multer": "^2.0.2",
|
||||
"ws": "^8.18.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.6.0"
|
||||
"@types/node": "^24.6.0",
|
||||
"prettier": "^3.7.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@mongodb-js/saslprep": {
|
||||
@@ -156,6 +158,12 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/append-field": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
|
||||
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/basic-auth": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
|
||||
@@ -203,6 +211,23 @@
|
||||
"node": ">=16.20.1"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/busboy": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
|
||||
"dependencies": {
|
||||
"streamsearch": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
@@ -241,6 +266,21 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
|
||||
"engines": [
|
||||
"node >= 6.0"
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.0.2",
|
||||
"typedarray": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
|
||||
@@ -734,6 +774,27 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.6"
|
||||
},
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
}
|
||||
},
|
||||
"node_modules/mongodb": {
|
||||
"version": "6.20.0",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.20.0.tgz",
|
||||
@@ -839,6 +900,67 @@
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/multer": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz",
|
||||
"integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"append-field": "^1.0.0",
|
||||
"busboy": "^1.6.0",
|
||||
"concat-stream": "^2.0.0",
|
||||
"mkdirp": "^0.5.6",
|
||||
"object-assign": "^4.1.1",
|
||||
"type-is": "^1.6.18",
|
||||
"xtend": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/multer/node_modules/media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/multer/node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/multer/node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/multer/node_modules/type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "~2.1.24"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
|
||||
@@ -918,6 +1040,22 @@
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.7.4",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz",
|
||||
"integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||
@@ -995,6 +1133,20 @@
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/router": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
|
||||
@@ -1170,6 +1322,23 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/streamsearch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
@@ -1205,6 +1374,12 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/typedarray": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.13.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.13.0.tgz",
|
||||
@@ -1220,6 +1395,12 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
@@ -1277,6 +1458,15 @@
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
"express-ws": "^5.0.2",
|
||||
"mongodb": "^6.20.0",
|
||||
"morgan": "^1.10.1",
|
||||
"multer": "^2.0.2",
|
||||
"ws": "^8.18.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.6.0"
|
||||
"@types/node": "^24.6.0",
|
||||
"prettier": "^3.7.4"
|
||||
}
|
||||
}
|
||||
|
||||
50
src/auth.js
50
src/auth.js
@@ -1,4 +1,4 @@
|
||||
import { createUser, generateHash, updateSessionToken } from "./userHelper.js";
|
||||
import { createUser, generateHash, updateSessionToken } from './userHelper.js';
|
||||
|
||||
let db;
|
||||
let users;
|
||||
@@ -19,19 +19,19 @@ async function getUserInfo(req, res) {
|
||||
res.status(200).send({
|
||||
username: req.user.username,
|
||||
role: req.user.role,
|
||||
_id: req.user._id
|
||||
_id: req.user._id,
|
||||
});
|
||||
}
|
||||
|
||||
async function checkSessionToken(req, res, next) {
|
||||
if (req.path.startsWith("/auth/")) {
|
||||
if (req.path.startsWith('/auth/')) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
const token = req.cookies.jeopardytoken;
|
||||
|
||||
let user = await users.findOne({sessiontoken: token});
|
||||
let user = await users.findOne({ sessiontoken: token });
|
||||
|
||||
if (user === null) {
|
||||
res.sendStatus(401);
|
||||
@@ -41,14 +41,14 @@ async function checkSessionToken(req, res, next) {
|
||||
req.user = {
|
||||
role: user.role,
|
||||
username: user.username,
|
||||
_id: user._id
|
||||
}
|
||||
_id: user._id,
|
||||
};
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
function checkAuthorization(role) {
|
||||
return (req, res, next) => {
|
||||
return (req, res, next) => {
|
||||
if (req.user === undefined) {
|
||||
res.status(403).send();
|
||||
return;
|
||||
@@ -59,7 +59,7 @@ function checkAuthorization(role) {
|
||||
} else {
|
||||
res.status(403).send();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function loginUser(req, res) {
|
||||
@@ -79,24 +79,42 @@ async function loginUser(req, res) {
|
||||
if (userobj !== null) {
|
||||
setTokenCookie(res, userobj.sessiontoken);
|
||||
|
||||
res.status(200).send({username: userobj.username, role: userobj.role, _id: userobj._id});
|
||||
res.status(200).send({
|
||||
username: userobj.username,
|
||||
role: userobj.role,
|
||||
_id: userobj._id,
|
||||
});
|
||||
} else {
|
||||
res.sendStatus(403);
|
||||
}
|
||||
}
|
||||
|
||||
export async function authenticateUser(username, password, updateSession = true) {
|
||||
let foundUser = await users.findOne({username});
|
||||
export async function authenticateUser(
|
||||
username,
|
||||
password,
|
||||
updateSession = true,
|
||||
) {
|
||||
let foundUser = await users.findOne({ username });
|
||||
if (foundUser === null) return null;
|
||||
|
||||
const hash = generateHash(password, foundUser.salt, foundUser.iterations);
|
||||
|
||||
if (hash === foundUser.hash) {
|
||||
if (updateSession) {
|
||||
let sessiontoken = await updateSessionToken(users, foundUser._id);
|
||||
return {sessiontoken, username, role: foundUser.role, _id: foundUser._id};
|
||||
let sessiontoken = await updateSessionToken(users, foundUser._id);
|
||||
return {
|
||||
sessiontoken,
|
||||
username,
|
||||
role: foundUser.role,
|
||||
_id: foundUser._id,
|
||||
};
|
||||
} else {
|
||||
return {sessiontoken: foundUser.sessiontoken, username, role: foundUser.role, _id: foundUser._id};
|
||||
return {
|
||||
sessiontoken: foundUser.sessiontoken,
|
||||
username,
|
||||
role: foundUser.role,
|
||||
_id: foundUser._id,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +127,6 @@ function setTokenCookie(res, sessiontoken) {
|
||||
|
||||
res.cookie('jeopardytoken', sessiontoken, {
|
||||
maxAge: 1e3 * 60 * 60 * 24 * 7,
|
||||
path: "/"
|
||||
})
|
||||
path: '/',
|
||||
});
|
||||
}
|
||||
|
||||
91
src/cdn.js
Normal file
91
src/cdn.js
Normal file
@@ -0,0 +1,91 @@
|
||||
import { rmSync } from 'fs';
|
||||
import { copyFile, mkdir } from 'fs/promises';
|
||||
import { Collection, Db, ObjectId } from 'mongodb';
|
||||
import multer from 'multer';
|
||||
|
||||
const dataPath = process.env.JEOPARDY_CDN_DATA_PATH;
|
||||
const upload = multer({ dest: dataPath });
|
||||
|
||||
/**
|
||||
* @type {Collection}
|
||||
*/
|
||||
let ressources;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} app
|
||||
* @param {Db} db
|
||||
*/
|
||||
export function initCdn(app, db) {
|
||||
ressources = db.collection('ressources');
|
||||
app.post('/upload', upload.single('file'), uploadFile);
|
||||
app.get('/cdn/:userid/:resid', fetchFile);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
* @param {import('express').NextFunction} next
|
||||
*/
|
||||
function uploadFile(req, res, next) {
|
||||
console.log(req.file, req.body);
|
||||
|
||||
/**
|
||||
* @type {string | undefined}
|
||||
*/
|
||||
const path = req.body.path;
|
||||
|
||||
if (path !== undefined && path.startsWith('/') && !path.includes('.')) {
|
||||
let destinationPath = `${dataPath}/${req.user._id}${req.body.path}`;
|
||||
mkdir(destinationPath, {
|
||||
recursive: true,
|
||||
})
|
||||
.then(() => {
|
||||
return copyFile(
|
||||
req.file.path,
|
||||
`${destinationPath}/${req.file.filename}`,
|
||||
);
|
||||
})
|
||||
.then(async () => {
|
||||
rmSync(req.file.path);
|
||||
|
||||
await ressources.insertOne({
|
||||
fullpath: destinationPath,
|
||||
path: path,
|
||||
user: req.user._id,
|
||||
mimetype: req.file.mimetype,
|
||||
name: req.file.originalname,
|
||||
filename: req.file.filename,
|
||||
});
|
||||
|
||||
res.sendStatus(200);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
rmSync(req.file.path);
|
||||
res.sendStatus(500);
|
||||
});
|
||||
} else {
|
||||
rmSync(req.file.path);
|
||||
res.sendStatus(400);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async function fetchFile(req, res) {
|
||||
let ressource = await ressources.findOne({
|
||||
user: new ObjectId(req.params.userid),
|
||||
filename: req.params.resid,
|
||||
});
|
||||
|
||||
if (ressource) {
|
||||
res.sendFile(ressource.fullpath + ressource.filename);
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ObjectId } from "mongodb";
|
||||
import { Db, ObjectId } from "mongodb";
|
||||
import { createUser as userHelperCreateUser, generateSessionToken, updatePassword, userExists } from "./userHelper.js";
|
||||
import { isValidRole, roles } from "./roles.js";
|
||||
import { authenticateUser } from "./auth.js";
|
||||
@@ -6,6 +6,11 @@ import { authenticateUser } from "./auth.js";
|
||||
let db;
|
||||
let users;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} app
|
||||
* @param {Db} db
|
||||
*/
|
||||
export function initUsers(app, db) {
|
||||
users = db.collection('users');
|
||||
app.put('/admin/user', createUser);
|
||||
|
||||
Reference in New Issue
Block a user