Added changes I forgot to commit
This commit is contained in:
parent
32c0ffd715
commit
fbb486e697
145
.gitignore
vendored
145
.gitignore
vendored
|
@ -1,145 +0,0 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# vitepress build output
|
||||
**/.vitepress/dist
|
||||
|
||||
# vitepress cache directory
|
||||
**/.vitepress/cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# Vscode files
|
||||
.vscode
|
||||
|
||||
# Data
|
||||
data/*
|
||||
|
||||
# Temporary
|
||||
tests/
|
|
@ -12,7 +12,7 @@ First make sure you have the following dependencies installed:
|
|||
- **Node.js**
|
||||
- **pnpm**
|
||||
|
||||
Then download all needed packages using
|
||||
Then, for each of frontend and backend, download all needed packages using
|
||||
```sh
|
||||
pnpm install
|
||||
```
|
||||
|
@ -28,7 +28,7 @@ node server.js
|
|||
|
||||
## 🔧 Configuration
|
||||
|
||||
All settings are located in [config/config.json](config/config.json). For more explainations and possible values, give a look to the documentation (incomming).
|
||||
All settings are located in [backend/config/config.json](backend/config/config.json). For more explainations and possible values, give a look to the documentation (incomming).
|
||||
|
||||
## 🔗 Documentation
|
||||
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"port": 8000,
|
||||
|
||||
"users": {
|
||||
"admin": {
|
||||
"username": "admin",
|
||||
"password": "admin"
|
||||
}
|
||||
},
|
||||
|
||||
"database": {
|
||||
"type": "sqlite"
|
||||
},
|
||||
|
||||
"auth": {
|
||||
"JWT_secret": "HGF7654EGBNKJNBJH6754356788GJHGY",
|
||||
"tokenExpiry": "1h"
|
||||
}
|
||||
}
|
24
frontend/.gitignore
vendored
Normal file
24
frontend/.gitignore
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
13
frontend/index.html
Normal file
13
frontend/index.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + Preact</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
18
frontend/package.json
Normal file
18
frontend/package.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "wf-radio-frontend",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"preact": "^10.26.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@preact/preset-vite": "^2.10.1",
|
||||
"vite": "^6.3.5"
|
||||
}
|
||||
}
|
1188
frontend/pnpm-lock.yaml
Normal file
1188
frontend/pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
2
frontend/pnpm-workspace.yaml
Normal file
2
frontend/pnpm-workspace.yaml
Normal file
|
@ -0,0 +1,2 @@
|
|||
onlyBuiltDependencies:
|
||||
- esbuild
|
1
frontend/public/vite.svg
Normal file
1
frontend/public/vite.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
43
frontend/src/app.jsx
Normal file
43
frontend/src/app.jsx
Normal file
|
@ -0,0 +1,43 @@
|
|||
import { useState } from 'preact/hooks'
|
||||
import preactLogo from './assets/preact.svg'
|
||||
import viteLogo from '/vite.svg'
|
||||
import './styles/app.css'
|
||||
|
||||
export function App() {
|
||||
const [count, setCount] = useState(0)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<a href="https://vite.dev" target="_blank">
|
||||
<img src={viteLogo} class="logo" alt="Vite logo" />
|
||||
</a>
|
||||
<a href="https://preactjs.com" target="_blank">
|
||||
<img src={preactLogo} class="logo preact" alt="Preact logo" />
|
||||
</a>
|
||||
</div>
|
||||
<h1>Vite + Preact</h1>
|
||||
<div class="card">
|
||||
<button onClick={() => setCount((count) => count + 1)}>
|
||||
count is {count}
|
||||
</button>
|
||||
<p>
|
||||
Edit <code>src/app.jsx</code> and save to test HMR
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
Check out{' '}
|
||||
<a
|
||||
href="https://preactjs.com/guide/v10/getting-started#create-a-vite-powered-preact-app"
|
||||
target="_blank"
|
||||
>
|
||||
create-preact
|
||||
</a>
|
||||
, the official Preact + Vite starter
|
||||
</p>
|
||||
<p class="read-the-docs">
|
||||
Click on the Vite and Preact logos to learn more
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
}
|
1
frontend/src/assets/preact.svg
Normal file
1
frontend/src/assets/preact.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="27.68" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 296"><path fill="#673AB8" d="m128 0l128 73.9v147.8l-128 73.9L0 221.7V73.9z"></path><path fill="#FFF" d="M34.865 220.478c17.016 21.78 71.095 5.185 122.15-34.704c51.055-39.888 80.24-88.345 63.224-110.126c-17.017-21.78-71.095-5.184-122.15 34.704c-51.055 39.89-80.24 88.346-63.224 110.126Zm7.27-5.68c-5.644-7.222-3.178-21.402 7.573-39.253c11.322-18.797 30.541-39.548 54.06-57.923c23.52-18.375 48.303-32.004 69.281-38.442c19.922-6.113 34.277-5.075 39.92 2.148c5.644 7.223 3.178 21.403-7.573 39.254c-11.322 18.797-30.541 39.547-54.06 57.923c-23.52 18.375-48.304 32.004-69.281 38.441c-19.922 6.114-34.277 5.076-39.92-2.147Z"></path><path fill="#FFF" d="M220.239 220.478c17.017-21.78-12.169-70.237-63.224-110.126C105.96 70.464 51.88 53.868 34.865 75.648c-17.017 21.78 12.169 70.238 63.224 110.126c51.055 39.889 105.133 56.485 122.15 34.704Zm-7.27-5.68c-5.643 7.224-19.998 8.262-39.92 2.148c-20.978-6.437-45.761-20.066-69.28-38.441c-23.52-18.376-42.74-39.126-54.06-57.923c-10.752-17.851-13.218-32.03-7.575-39.254c5.644-7.223 19.999-8.261 39.92-2.148c20.978 6.438 45.762 20.067 69.281 38.442c23.52 18.375 42.739 39.126 54.06 57.923c10.752 17.85 13.218 32.03 7.574 39.254Z"></path><path fill="#FFF" d="M127.552 167.667c10.827 0 19.603-8.777 19.603-19.604c0-10.826-8.776-19.603-19.603-19.603c-10.827 0-19.604 8.777-19.604 19.603c0 10.827 8.777 19.604 19.604 19.604Z"></path></svg>
|
After Width: | Height: | Size: 1.6 KiB |
5
frontend/src/main.jsx
Normal file
5
frontend/src/main.jsx
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { render } from 'preact'
|
||||
import './styles/index.css'
|
||||
import { App } from './app.jsx'
|
||||
|
||||
render(<App />, document.getElementById('app'))
|
25
frontend/src/styles/app.css
Normal file
25
frontend/src/styles/app.css
Normal file
|
@ -0,0 +1,25 @@
|
|||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
}
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #646cffaa);
|
||||
}
|
||||
.logo.preact:hover {
|
||||
filter: drop-shadow(0 0 2em #673ab8aa);
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
68
frontend/src/styles/index.css
Normal file
68
frontend/src/styles/index.css
Normal file
|
@ -0,0 +1,68 @@
|
|||
:root {
|
||||
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
7
frontend/vite.config.js
Normal file
7
frontend/vite.config.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import preact from '@preact/preset-vite'
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [preact()],
|
||||
})
|
35
package.json
35
package.json
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"name": "wf-radio",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"start-auto": "pnpx nodemon server.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"packageManager": "pnpm@10.5.2",
|
||||
"dependencies": {
|
||||
"ajv": "^8.17.1",
|
||||
"bcrypt": "^5.1.1",
|
||||
"better-sqlite3": "^11.9.1",
|
||||
"dompurify": "^3.2.4",
|
||||
"express": "^5.1.0",
|
||||
"jsdom": "^26.0.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"marked": "^15.0.7",
|
||||
"mysql": "^2.18.1"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"bcrypt",
|
||||
"better-sqlite3"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.9"
|
||||
}
|
||||
}
|
1884
pnpm-lock.yaml
1884
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
38
server.js
38
server.js
|
@ -1,38 +0,0 @@
|
|||
// --- Imports ---
|
||||
|
||||
const express = require("express");
|
||||
const app = express();
|
||||
const configManager = require("./src/utils/configManager");
|
||||
const { connectDatabase, initDatabase } = require('./src/database/index');
|
||||
|
||||
|
||||
// --- Load configuration ---
|
||||
const config = configManager.loadConfig();
|
||||
|
||||
// --- Body parsing ---
|
||||
app.use(express.json()); // Necessary to parse JSON bodies
|
||||
|
||||
// Database connection
|
||||
(async () => {
|
||||
|
||||
|
||||
// --- Database connection ---
|
||||
await connectDatabase();
|
||||
await initDatabase();
|
||||
|
||||
// --- Routing ---
|
||||
app.use("/", require("./src/routes/index"));
|
||||
app.use("/mods", require("./src/routes/mods"));
|
||||
app.use("/users", require("./src/routes/users"));
|
||||
app.use("/list", require("./src/routes/list"));
|
||||
app.use("/login", require("./src/routes/login"));
|
||||
|
||||
})();
|
||||
|
||||
|
||||
// --- Launch ---
|
||||
|
||||
const port = config.port;
|
||||
app.listen(port, () => {
|
||||
console.log("Server listening on port " + port + "...");
|
||||
})
|
|
@ -1,17 +0,0 @@
|
|||
const handleError = require("../middleware/errors");
|
||||
const authService = require("../services/authService");
|
||||
|
||||
async function login(req, res) {
|
||||
try {
|
||||
const username = req.body.username;
|
||||
const email = req.body.email;
|
||||
const password = req.body.password
|
||||
const token = await authService.login(username, email, password);
|
||||
res.json({ token });
|
||||
} catch (err) {
|
||||
handleError(err, res);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = { login };
|
|
@ -1,14 +0,0 @@
|
|||
const index_service = require("../services/indexService");
|
||||
const handleError = require("../middleware/errors");
|
||||
|
||||
|
||||
async function getVersion(req, res) {
|
||||
try {
|
||||
const query_result = await index_service.getVersion();
|
||||
res.json(query_result);
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getVersion };
|
|
@ -1,68 +0,0 @@
|
|||
const handleError = require("../middleware/errors");
|
||||
const mod_service = require("../services/modService");
|
||||
const { authorizeModModification, authenticateToken } = require("../middleware/auth");
|
||||
|
||||
async function listMods(req, res) {
|
||||
try {
|
||||
// Query
|
||||
const query_result = await mod_service.getAllMods();
|
||||
res.json(query_result);
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
|
||||
async function createMod(req, res) {
|
||||
try {
|
||||
// Authenticate
|
||||
await authenticateToken(req);
|
||||
// Query
|
||||
const mod_data = req.body;
|
||||
const user = req.token_infos.username;
|
||||
const query_result = await mod_service.createMod(mod_data, user);
|
||||
res.json(query_result);
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
|
||||
async function modifyMod(req, res) {
|
||||
try {
|
||||
// Authorize
|
||||
authorizeModModification(req);
|
||||
// Query
|
||||
const mod_data = req.body;
|
||||
const query_result = await mod_service.modifyMod(mod_data);
|
||||
res.json(query_result);
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
|
||||
async function getModByName(req, res) {
|
||||
try {
|
||||
// Query
|
||||
const name = req.params.name
|
||||
const query_result = await mod_service.getModByName(name);
|
||||
res.json(query_result);
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteMod(req, res) {
|
||||
try {
|
||||
// Authorize
|
||||
authorizeModModification(req);
|
||||
// Query
|
||||
const name = req.params.name
|
||||
const query_result = await mod_service.deleteMod(name);
|
||||
res.json(query_result);
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = { listMods, getModByName, createMod, modifyMod, deleteMod };
|
|
@ -1,63 +0,0 @@
|
|||
const handleError = require("../middleware/errors");
|
||||
const user_service = require("../services/userService")
|
||||
const { authorizeUserModification } = require("../middleware/auth");
|
||||
|
||||
|
||||
async function listUsers(req, res) {
|
||||
try {
|
||||
// Query
|
||||
const query_result = await user_service.getAllUsers();
|
||||
res.json(query_result);
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
|
||||
async function getUserByName(req, res) {
|
||||
try {
|
||||
// Query
|
||||
const query_result = await user_service.getUserByName(req.params.name);
|
||||
res.json(query_result);
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
|
||||
async function createUser(req, res) {
|
||||
try {
|
||||
// Query
|
||||
const query_result = await user_service.createUser(req.body);
|
||||
res.json(query_result);
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
|
||||
async function modifyUser(req, res) {
|
||||
try {
|
||||
// Query
|
||||
const diff_data = req.body;
|
||||
const query_result = await user_service.modifyUser(diff_data);
|
||||
res.json(query_result);
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteUser(req, res) {
|
||||
try {
|
||||
// Authenticate
|
||||
await authorizeUserModification(req);
|
||||
// Query
|
||||
const user = req.params.name;
|
||||
const token_user = req.token_infos
|
||||
const query_result = await user_service.deleteUser(user, token_user);
|
||||
return res.json(query_result);
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = { listUsers, getUserByName, createUser, modifyUser, deleteUser };
|
|
@ -1,112 +0,0 @@
|
|||
const MySQLDatabase = require("./mysql");
|
||||
const SQLiteDatabase = require("./sqlite");
|
||||
const { getConfig } = require("../utils/configManager");
|
||||
|
||||
let db;
|
||||
|
||||
async function connectDatabase() {
|
||||
|
||||
// Get config
|
||||
const config = await getConfig();
|
||||
|
||||
// Choose database type
|
||||
if (config.database.type === "mysql") {
|
||||
db = new MySQLDatabase(config.database);
|
||||
} else if (config.database.type === "sqlite") {
|
||||
db = new SQLiteDatabase(config.database);
|
||||
} else {
|
||||
throw new Error("Invalid database type: ", config.database.type);
|
||||
}
|
||||
|
||||
// Connect
|
||||
await db.connect();
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
// Setups the database by creating the tables and the default objects
|
||||
async function initDatabase() {
|
||||
|
||||
if (!db) {
|
||||
throw new Error("Database is not connected");
|
||||
}
|
||||
|
||||
// --- Users ---
|
||||
|
||||
// Uers table
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS Users (
|
||||
username TINYTEXT PRIMARY KEY,
|
||||
display_name TINYTEXT NOT NULL,
|
||||
email TINYTEXT NOT NULL,
|
||||
password TINYTEXT NOT NULL,
|
||||
profile_picture LONGTEXT,
|
||||
role TINYTEXT NOT NULL,
|
||||
settings LONGTEXT
|
||||
);`);
|
||||
|
||||
// --- Mods ---
|
||||
|
||||
// Mods table
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS Mods (
|
||||
name TINYTEXT PRIMARY KEY,
|
||||
display_name TINYTEXT NOT NULL,
|
||||
author TINYTEXT NOT NULL,
|
||||
description TINYTEXT NOT NULL,
|
||||
|
||||
FOREIGN KEY (author) REFERENCES Users(username)
|
||||
);`);
|
||||
|
||||
// Mods complementary infos
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS ModInfos (
|
||||
mod TINYTEXT PRIMARY KEY,
|
||||
full_description TEXT NOT NULL,
|
||||
license TINYTEXT,
|
||||
custom_license TEXT,
|
||||
links TEXT,
|
||||
creation_date TINYTEXT NOT NULL,
|
||||
downloads_count INT NOT NULL,
|
||||
|
||||
FOREIGN KEY (mod) REFERENCES Mods(name)
|
||||
);`);
|
||||
|
||||
// Mods tags
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS ModTags (
|
||||
mod TINYTEXT NOT NULL,
|
||||
tag TINYTEXT NOT NULL,
|
||||
|
||||
FOREIGN KEY (mod) REFERENCES Mods(name)
|
||||
);`);
|
||||
|
||||
// Mods versions
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS ModVersions (
|
||||
mod TINYTEXT NOT NULL,
|
||||
version_number TINYTEXT NOT NULL,
|
||||
channel TINYTEXT NOT NULL,
|
||||
changelog TEXT NOT NULL,
|
||||
release_date TINYTEXT NOT NULL,
|
||||
game_version TINYTEXT NOT NULL,
|
||||
platform TINYTEXT NOT NULL,
|
||||
environment TINYTEXT NOT NULL,
|
||||
url TINYTEXT NOT NULL,
|
||||
|
||||
FOREIGN KEY (mod) REFERENCES Mods(name)
|
||||
);`);
|
||||
|
||||
// User favorites (mods)
|
||||
db.exec(`CREATE TABLE IF NOT EXISTS UserFavoriteMods (
|
||||
username TINYTEXT NOT NULL,
|
||||
mod TINYTEXT NOT NULL,
|
||||
|
||||
FOREIGN KEY (username) REFERENCES Users(username),
|
||||
FOREIGN KEY (mod) REFERENCES Mods(name)
|
||||
);`);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function getDatabase() {
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
module.exports = { getDatabase, connectDatabase, initDatabase };
|
|
@ -1,30 +0,0 @@
|
|||
class MySQLDatabase {
|
||||
constructor(config) {
|
||||
const mysql = require("mysql2/promise");
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
|
||||
async connect() {
|
||||
this.db = await mysql.createConnection({
|
||||
host: this.config.host,
|
||||
user: this.config.user,
|
||||
password: this.config.password,
|
||||
database: this.config.database,
|
||||
});
|
||||
console.log("Connected to MySQL");
|
||||
}
|
||||
|
||||
async close() {
|
||||
await this.db.end();
|
||||
}
|
||||
|
||||
async query(sql, params) {
|
||||
throw new Error("Not implemented"); //TODO
|
||||
const [results] = await this.db.execute(sql, params);
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = MySQLDatabase;
|
|
@ -1,70 +0,0 @@
|
|||
const sqlite = require("better-sqlite3");
|
||||
|
||||
class SQLiteDatabase {
|
||||
|
||||
constructor(config) {
|
||||
this.config = config;
|
||||
this.db = null;
|
||||
}
|
||||
|
||||
async connect() {
|
||||
try {
|
||||
this.db = new sqlite("./data/sqlite.db");
|
||||
// this.db.pragma("journal_mode = WAL");
|
||||
console.log("Connected to SQLite");
|
||||
} catch (err) {
|
||||
console.error("Error connecting to SQLite database: ", err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async close() {
|
||||
if (this.db && this.db.open) {
|
||||
this.db.close();
|
||||
console.debug("Closed database connection");
|
||||
}
|
||||
}
|
||||
|
||||
async query(sql, params = []) {
|
||||
try {
|
||||
if (params.length > 0) {
|
||||
return this.db.prepare(sql).all(params);
|
||||
} else {
|
||||
return this.db.prepare(sql).all();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error executing prepared query:", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async exec(sql) {
|
||||
try {
|
||||
return this.db.exec(sql);
|
||||
} catch (err) {
|
||||
console.error("Error executing statement:", err)}
|
||||
|
||||
}
|
||||
|
||||
async prepare(sql, params = []) {
|
||||
try {
|
||||
if (params.length > 0) {
|
||||
return this.db.prepare(sql).run(params);
|
||||
} else {
|
||||
return this.db.prepare(sql);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error executing prepared statement:", err)}
|
||||
}
|
||||
|
||||
async exists(table, attribute, value) {
|
||||
try {
|
||||
return this.db.prepare(`SELECT COUNT(*) FROM ${table} WHERE ${attribute} = ?`).get(value)['COUNT(*)'] > 0;
|
||||
} catch (err) {
|
||||
console.error("Error checking item existence");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = SQLiteDatabase;
|
|
@ -1,85 +0,0 @@
|
|||
const { getModByName } = require("../services/modService");
|
||||
const { getModpackByName } = require("../services/modpackService");
|
||||
const { getUserByName } = require("../services/userService");
|
||||
const { verifyToken } = require("../utils/crypto");
|
||||
const AppError = require("../utils/appError");
|
||||
|
||||
|
||||
async function authenticateToken(req) {
|
||||
|
||||
const token = req.header("Authorization");
|
||||
|
||||
if (!token) {
|
||||
throw new AppError(401, "Missing authorization header", "Unauthorized");
|
||||
}
|
||||
|
||||
try {
|
||||
req.token_infos = await verifyToken(token);
|
||||
console.debug("Authorizing token from", req.token_infos);
|
||||
} catch (err) {
|
||||
throw new AppError(403, "Forbidden: Error verifying the authorization token");
|
||||
}
|
||||
|
||||
return req.token_infos;
|
||||
}
|
||||
|
||||
|
||||
async function authorizeModModification(req) {
|
||||
|
||||
// Auth token
|
||||
await authenticateToken(req);
|
||||
// Get mod infos
|
||||
if (!req.params || !req.params.name) {
|
||||
throw new AppError(400, "No mod name was scpecified", "Bad request");
|
||||
}
|
||||
const mod_name = req.params.name;
|
||||
const mod = await getModByName(mod_name);
|
||||
if (!mod) {
|
||||
throw new AppError(404, "No mod was found with this name", "Not found");
|
||||
}
|
||||
// Authorize
|
||||
if ( mod.author != req.token_infos.username) {
|
||||
throw new AppError(401, "Mod author differs from current user", "Unauthorized");
|
||||
}
|
||||
}
|
||||
|
||||
async function authorizeModpackModification(req) {
|
||||
|
||||
// Auth token
|
||||
await authenticateToken(req);
|
||||
// Get mod infos
|
||||
if (!req.params || !req.params.name) {
|
||||
throw new AppError(400, "No mod name was scpecified", "Bad request");
|
||||
}
|
||||
const modpack_name = req.params.name;
|
||||
const modpack = await getModpackByName(modpack_name);
|
||||
if (!modpack) {
|
||||
throw new AppError(404, "No mod was found with this name", "Not found");
|
||||
}
|
||||
// Authorize
|
||||
if ( modpack.author != req.token_infos.username) {
|
||||
throw new AppError(401, "Mod author differs from current user", "Unauthorized");
|
||||
}
|
||||
}
|
||||
|
||||
async function authorizeUserModification(req) {
|
||||
|
||||
// Auth token
|
||||
await authenticateToken(req);
|
||||
// Get mod infos
|
||||
if (!req.params || !req.params.name) {
|
||||
throw new AppError(400, "No mod name was scpecified", "Bad request");
|
||||
}
|
||||
const user_name = req.params.name;
|
||||
const user = await getUserByName(user_name);
|
||||
if (!user) {
|
||||
throw new AppError(404, "No user was found with this name", "Not found");
|
||||
}
|
||||
// Authorize
|
||||
if ( user.username != req.token_infos.username) {
|
||||
throw new AppError(401, "User to modify differs from current user", "Unauthorized");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = { authenticateToken, authorizeModModification, authorizeModpackModification, authorizeUserModification };
|
|
@ -1,31 +0,0 @@
|
|||
const AppError = require("../utils/appError");
|
||||
|
||||
const handleError = (err, res) => {
|
||||
|
||||
// Send error infos
|
||||
if (err instanceof AppError) {
|
||||
|
||||
// Log
|
||||
if (err.statusCode == 500) {
|
||||
console.error("Error:", err.message);
|
||||
if (err.debugMsg) {
|
||||
console.debug(" >", err.debugMsg);
|
||||
}
|
||||
}
|
||||
|
||||
// Response
|
||||
return res.status(err.statusCode).json({
|
||||
status: err.status,
|
||||
message: err.message
|
||||
});
|
||||
}
|
||||
|
||||
// Default error
|
||||
console.error("Error:", err.message);
|
||||
res.status(500).json({
|
||||
message: 'Internal server error',
|
||||
status: 500
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = handleError;
|
|
@ -1,12 +0,0 @@
|
|||
const configManager = require("../utils/configManager");
|
||||
|
||||
async function getVersion() {
|
||||
|
||||
const version = await configManager.getVersion();
|
||||
const res = {
|
||||
version: version
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
module.exports = { getVersion }
|
|
@ -1,192 +0,0 @@
|
|||
const { getDatabase } = require('../database/index');
|
||||
const AppError = require('../utils/appError');
|
||||
const db = getDatabase();
|
||||
|
||||
|
||||
// --- Get ---
|
||||
|
||||
async function getAllMods() {
|
||||
return await db.query("SELECT name, display_name, author, description FROM Mods");
|
||||
}
|
||||
|
||||
async function getModByName(name) {
|
||||
return await db.query("SELECT name, display_name, author FROM Mods WHERE name = ?;", [name]);
|
||||
|
||||
}
|
||||
|
||||
async function getModFullInfos(name) {
|
||||
|
||||
// Query
|
||||
const base_infos = db.query(`SELECT * FROM Mods WHERE name = ?`, [name]);
|
||||
const other_infos = db.query(`SELECT full_description, license, links, creation_date, downloads_count
|
||||
FROM ModInfos WHERE name = ?`, [name]);
|
||||
const tags = getModTags(name);
|
||||
|
||||
// Merge
|
||||
const res = {...await base_infos, ...await other_infos, ...tags};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
async function listVersions(mod_name) {
|
||||
return await db.query("SELECT * FROM ModVersions WHERE mod = ?", [mod_name]);
|
||||
}
|
||||
|
||||
async function getVersionByNumber(mod_name, version_number) {
|
||||
return await db.query(`SELECT * FROM ModVersions
|
||||
WHERE mod = ?
|
||||
AND version_number = ?;`,
|
||||
[mod_name, version_number]);
|
||||
}
|
||||
|
||||
async function getVersion(mod_name, version_number, game_version, platform, environment) {
|
||||
return await db.query(`SELECT * FROM ModVersions
|
||||
WHERE mod = ?
|
||||
AND version_number = ?
|
||||
AND game_version = ?
|
||||
AND platform = ?
|
||||
AND environment = ?;`,
|
||||
[mod_name, version_number, game_version, platform, environment]);
|
||||
}
|
||||
|
||||
// --- Create ---
|
||||
|
||||
async function createMod(name, display_name, author, description, mod_infos) {
|
||||
|
||||
// Extract infos
|
||||
const { full_description, license, links, creation_date, tags } = mod_infos;
|
||||
|
||||
// Mods table
|
||||
await db.prepare("INSERT INTO Mods (name, display_name, author, description) \
|
||||
VALUES (?, ?, ?, ?)",
|
||||
[name, display_name, author, description]);
|
||||
|
||||
// ModInfos table
|
||||
await db.prepare(`INSERT INTO ModInfos (mod, full_description, license, links, creation_date, downloads_count)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
[name, full_description, license.type, links.toString(), creation_date, 0]);
|
||||
|
||||
// Tags
|
||||
if (tags) {
|
||||
const tags_proc = addTags(name, tags, []);
|
||||
}
|
||||
|
||||
|
||||
// License
|
||||
if (license.type == "custom") {
|
||||
await db.prepare(`UPDATE ModInfos SET custom_license = ?
|
||||
WHERE mod = ?`,
|
||||
[license.content, name]);
|
||||
}
|
||||
|
||||
// Await
|
||||
if (tags) {
|
||||
await tags_proc;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
async function addVersion(mod, version_number, channel, changelog, release_date, game_version, platform, environment, url) {
|
||||
|
||||
await db.prepare(`INSERT INTO ModVersions (mod, version_number, channel, changelog, release_date, game_version, environment, platform, url)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);`,
|
||||
[mod, version_number, channel, changelog, release_date, game_version, environment, platform, url]);
|
||||
return;
|
||||
}
|
||||
|
||||
async function addTags(mod, tags) {
|
||||
// Add asynchronously
|
||||
const promises = tags.map(async (tag) => {
|
||||
db.query(`INSERT INTO ModTags (mod, tag)
|
||||
VALUES (?, ?);`,
|
||||
[mod, tag]);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// --- Update ---
|
||||
|
||||
async function updateMod(name, display_name, author, description) {
|
||||
|
||||
if (display_name) {
|
||||
await updateModAttributes(name, "display_name", display_name);
|
||||
}
|
||||
|
||||
if (author) {
|
||||
await updateModAttribute(nale, "author", author);
|
||||
}
|
||||
|
||||
if (description) {
|
||||
await updateModAttribute(name, "description", description)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- Delete ---
|
||||
|
||||
async function deleteMod(name) {
|
||||
await db.prepare("DELETE FROM Mods WHERE name = ?", [name]);
|
||||
return;
|
||||
}
|
||||
|
||||
async function deleteVersion(name, version_number, game_version, platform, environment) {
|
||||
await db.prepare(`DELETE FROM ModVersions WHERE mod = ?
|
||||
AND version_number = ?
|
||||
AND game_version = ?
|
||||
AND platform = ?
|
||||
AND environment = ?;`,
|
||||
[name, version_number, game_version, platform, environment]);
|
||||
return;
|
||||
}
|
||||
|
||||
async function deleteTags(mod, tags) {
|
||||
// Remove asynchronously
|
||||
const promises = tags.map(async (tag) => {
|
||||
db.query(`DELETE FROM ModTags
|
||||
WHERE mod = ? AND tag = ?;`, [mod, tag]);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// --- Utils ---
|
||||
|
||||
async function updateModAttribute(name, attribute, value) {
|
||||
await db.prepare(`UPDATE Mods SET ${attribute} = ? WHERE name = ?`, [value, name]);
|
||||
return;
|
||||
}
|
||||
|
||||
async function updateModInfosAttribute(name, attribute, value) {
|
||||
await db.prepare(`UPDATE ModInfos SET ${attribute} = ? WHERE name = ?`, [value, name]);
|
||||
return;
|
||||
}
|
||||
|
||||
async function exists(name) {
|
||||
return db.exists("Mods", "name", name);
|
||||
}
|
||||
|
||||
async function containsVersion(name, version_number, game_version, platform, environment) {
|
||||
throw new AppError(501, "Not implemented");
|
||||
// return db.exists("Mods", "name", name);
|
||||
}
|
||||
|
||||
async function containsTag(name, tag) {
|
||||
throw new AppError(501, "Not implemented");
|
||||
// return db.exists("Mods", "name", name);
|
||||
}
|
||||
|
||||
|
||||
// --- Exports ---
|
||||
|
||||
module.exports = { getAllMods, getModByName, getModFullInfos,
|
||||
listVersions, getVersionByNumber, getVersion,
|
||||
createMod, addVersion, addTags,
|
||||
updateMod,
|
||||
deleteMod, deleteVersion, deleteTags,
|
||||
exists };
|
|
@ -1,125 +0,0 @@
|
|||
const { getDatabase } = require('../database/index');
|
||||
const AppError = require('../utils/appError');
|
||||
const db = getDatabase();
|
||||
|
||||
|
||||
// --- Get ---
|
||||
|
||||
async function getAllUsers() {
|
||||
return db.query("SELECT username, display_name, email, profile_picture FROM Users");
|
||||
}
|
||||
|
||||
async function getUserByName(name) {
|
||||
return await db.query("SELECT username, display_name, profile_picture, role FROM Users WHERE username = ?;", [name]);
|
||||
}
|
||||
|
||||
async function getUserByEmail(email) {
|
||||
return await db.query("SELECT email, username FROM Users WHERE email = ?;", [email]);
|
||||
}
|
||||
|
||||
async function getFullUserInfos(name) {
|
||||
return await db.query("SELECT username, display_name, email, profile_picture, role, settings FROM Users WHERE username = ?;", [name]);
|
||||
}
|
||||
|
||||
async function getUserPassword(name) {
|
||||
return await db.query("SELECT username, password FROM Users WHERE username = ?;", [name]);
|
||||
}
|
||||
|
||||
async function exists(name) {
|
||||
return await db.exists("Users", "username", name);
|
||||
}
|
||||
|
||||
|
||||
// --- Create ---
|
||||
|
||||
async function createUser( username, email, password, displayName, profilePicture, settings ) {
|
||||
|
||||
// Create user
|
||||
await db.prepare(`INSERT INTO Users (username, email, password, display_name, role )
|
||||
VALUES (?, ?, ?, ?, ? )`,
|
||||
[username, email, password, displayName, "user"]);
|
||||
|
||||
// Handle nullable fields
|
||||
if (profilePicture) {
|
||||
await updateUserAttribute(username, "profile_picture", profilePicture);
|
||||
}
|
||||
|
||||
if (settings) {
|
||||
await updateUserAttribute(username, "settings", settings);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
async function addFavoriteMods(username, favs) {
|
||||
|
||||
const promises = favs.map(async (mod) => {
|
||||
db.query(`INSERT INTO UserFavoriteMods
|
||||
(username, mod) VALUES (?, ?);`,
|
||||
[username, mod]);
|
||||
|
||||
});
|
||||
await Promise.all(promises);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// --- Update ---
|
||||
|
||||
async function updateUser(username, display_name, email, profile_picture, settings) {
|
||||
|
||||
if (display_name) {
|
||||
await updateUserAttribute(username, "display_name", display_name);
|
||||
}
|
||||
|
||||
if (email) {
|
||||
await updateUserAttribute(username, "email", email);
|
||||
}
|
||||
|
||||
if (profile_picture) {
|
||||
await updateUserAttribute(username, "profile_picture", profile_picture)
|
||||
}
|
||||
|
||||
if (settings) {
|
||||
await updateUserAttribute(username, "settings", settings);
|
||||
}
|
||||
}
|
||||
|
||||
async function updateUserPassword(username, password) {
|
||||
await db.prepare(`UPDATE Users SET password = ? WHERE username = ?`, [password, username]);
|
||||
}
|
||||
|
||||
async function updateUserAttribute(username, attribute, value) {
|
||||
await db.prepare(`UPDATE Users SET ${attribute} = ? WHERE username = ?`, [value, username]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// --- Delete ---
|
||||
|
||||
async function deleteUser(username) {
|
||||
await db.prepare("DELETE FROM Users WHERE username = ?", [username]);
|
||||
return;
|
||||
}
|
||||
|
||||
async function deleteFavoriteMods(username, favs) {
|
||||
|
||||
const promises = favs.map(async (mod) => {
|
||||
db.query(`DELETE FROM UserFavoriteMods
|
||||
WHERE username = ? AND mod = ?;`, [username, mod]);
|
||||
});
|
||||
|
||||
// Await
|
||||
await Promise.all(promises);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// --- Exports ---
|
||||
|
||||
module.exports = { getAllUsers, getUserByName, getUserByEmail, getFullUserInfos, getUserPassword,
|
||||
createUser, addFavoriteMods,
|
||||
updateUser,
|
||||
deleteUser, deleteFavoriteMods,
|
||||
exists }
|
|
@ -1,11 +0,0 @@
|
|||
const express = require("express");
|
||||
const controller = require("../controllers/index");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
|
||||
router.get('/version', async (res, req) => {
|
||||
controller.getVersion(res, req);
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -1,24 +0,0 @@
|
|||
const express = require("express");
|
||||
const { listMods } = require("../controllers/mods");
|
||||
// const { listModpacks } = require("../controllers/modpacks");
|
||||
const { listUsers } = require("../controllers/users");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// List mods
|
||||
router.get("/mods", async (req,res) => {
|
||||
listMods(req, res);
|
||||
});
|
||||
|
||||
// List modpacks
|
||||
// router.get("/modpacks", async (req,res) => {
|
||||
// listModpacks(req, res);
|
||||
// });
|
||||
|
||||
// List users
|
||||
router.get("/users", async (req,res) => {
|
||||
listUsers(req, res);
|
||||
});
|
||||
|
||||
|
||||
module.exports = router;
|
|
@ -1,11 +0,0 @@
|
|||
const express = require("express");
|
||||
const controller = require("../controllers/auth");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Login
|
||||
router.post("/", async (req, res) => {
|
||||
controller.login(req, res);
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -1,27 +0,0 @@
|
|||
const express = require("express");
|
||||
const controller = require("../controllers/mods");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Create a mod
|
||||
router.post("/", async (req, res) => {
|
||||
controller.createMod(req, res);
|
||||
});
|
||||
|
||||
// Modify mod
|
||||
router.put("/:name", async (req,res) => {
|
||||
controller.modifyMod(req,res);
|
||||
});
|
||||
|
||||
// Get mod infos
|
||||
router.get("/:name", async (req,res) => {
|
||||
controller.getModByName(req, res);
|
||||
});
|
||||
|
||||
// Delete mod
|
||||
router.delete("/:name", async (req,res) => {
|
||||
controller.deleteMod(req, res);
|
||||
});
|
||||
|
||||
|
||||
module.exports = router;
|
|
@ -1,27 +0,0 @@
|
|||
const express = require("express");
|
||||
const controller = require("../controllers/users");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// List users
|
||||
router.get("/", async (req,res) => {
|
||||
controller.listUsers(req,res);
|
||||
});
|
||||
|
||||
// Create a user
|
||||
router.post("/", async (req, res) => {
|
||||
controller.createUser(req, res);
|
||||
})
|
||||
|
||||
// Get user infos
|
||||
router.get("/:name", async (req,res) => {
|
||||
controller.getUserByName(req, res);
|
||||
});
|
||||
|
||||
// Delete user
|
||||
router.delete("/:name", async (req,res) => {
|
||||
controller.deleteUser(req, res);
|
||||
});
|
||||
|
||||
|
||||
module.exports = router;
|
|
@ -1,21 +0,0 @@
|
|||
const Ajv = require("ajv");
|
||||
const ajv = new Ajv();
|
||||
|
||||
// --- Schemas ---
|
||||
|
||||
const AuthUserSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
email: { type: 'string', format: 'email' },
|
||||
password: { type: 'string', minLength: 3, maxLength: 30 },
|
||||
},
|
||||
required: ['email', 'password'],
|
||||
additionalProperties: false
|
||||
};
|
||||
|
||||
const validateAuthUserData = ajv.compile(AuthUserSchema);
|
||||
|
||||
|
||||
// --- Exports ---
|
||||
|
||||
module.exports = { validateAuthUserData, validateAuthNodeData };
|
|
@ -1,21 +0,0 @@
|
|||
const Ajv = require("ajv");
|
||||
const ajv = new Ajv();
|
||||
|
||||
// --- Schemas ---
|
||||
//TODO
|
||||
|
||||
const newModSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string'},
|
||||
},
|
||||
required: ['name'],
|
||||
additionalProperties: false
|
||||
};
|
||||
|
||||
const validateNewModData = ajv.compile(newModSchema);
|
||||
|
||||
|
||||
// --- Exports ---
|
||||
|
||||
module.exports = { validateNewModData };
|
|
@ -1,21 +0,0 @@
|
|||
const Ajv = require("ajv");
|
||||
const ajv = new Ajv();
|
||||
|
||||
// --- Schemas ---
|
||||
//TODO
|
||||
|
||||
const newModpackSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string'},
|
||||
},
|
||||
required: ['name'],
|
||||
additionalProperties: false
|
||||
};
|
||||
|
||||
const validateNewModpackData = ajv.compile(newModpackSchema);
|
||||
|
||||
|
||||
// --- Exports ---
|
||||
|
||||
module.exports = { validateNewModpackData };
|
|
@ -1,23 +0,0 @@
|
|||
const Ajv = require("ajv");
|
||||
const ajv = new Ajv();
|
||||
|
||||
// --- Schemas ---
|
||||
//TODO
|
||||
|
||||
const newUserSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
email: { type: 'string', format: 'email' },
|
||||
name: { type: 'string' },
|
||||
password: { type: 'string', minLength: 3, maxLength: 30 },
|
||||
},
|
||||
required: ['name', 'email', 'password'],
|
||||
additionalProperties: false
|
||||
};
|
||||
|
||||
const validateNewUserData = ajv.compile(newUserSchema);
|
||||
|
||||
|
||||
// --- Exports ---
|
||||
|
||||
module.exports = { validateNewUserData };
|
|
@ -1,85 +0,0 @@
|
|||
const userModel = require("../models/user");
|
||||
const AppError = require("../utils/appError");
|
||||
const cryptoUtils = require("../utils/crypto");
|
||||
const configManager = require("../utils/configManager");
|
||||
const validate = require("../utils/validate_legacy");
|
||||
|
||||
const JWT_Secret = configManager.getJWTSecret();
|
||||
|
||||
async function login(username, email, password) {
|
||||
|
||||
// Check for null
|
||||
if (!(username || email) || !password) {
|
||||
throw new AppError(400, "Bad request", "missing credentials");
|
||||
}
|
||||
|
||||
// Get user data
|
||||
let user_get;
|
||||
if (email) { // If matches email
|
||||
user_get = await userModel.getUserByEmail(email);
|
||||
} else
|
||||
if (username) { // if matches username
|
||||
user_get = await userModel.getUserByName(username);
|
||||
} else {
|
||||
console.debug("Failed finding user, weird...")
|
||||
throw new AppError(401, "Unauthorized", "Invalid credentials");
|
||||
}
|
||||
|
||||
// Check if user exists
|
||||
if (!user_get || user_get.length == 0) {
|
||||
// throw new AppError(401, "Unauthorized: No user with this name");
|
||||
throw new AppError(401, "Unauthorized", "Invalid credentials");
|
||||
}
|
||||
// Just in case
|
||||
if (user_get.length > 1) {
|
||||
throw new AppError(500, "Internal server error", "Found multiple users with this name or email, please contact administration");
|
||||
}
|
||||
|
||||
const user = user_get[0];
|
||||
|
||||
// Get user password
|
||||
const saved_password_get = await userModel.getUserPassword(user.username);
|
||||
// Check if retrieved password sucessfully
|
||||
if (!saved_password_get || saved_password_get.length == 0) {
|
||||
throw new AppError(500, "Unable to retrieve user password");
|
||||
}
|
||||
saved_password = saved_password_get[0].password;
|
||||
// Check if retrieved password sucessfully again
|
||||
if (!saved_password) {
|
||||
throw new AppError(500, "Unable to retrieve user password");
|
||||
}
|
||||
|
||||
// Check if passwords match
|
||||
const passwords_match = await cryptoUtils.passwordsMatch(password, saved_password)
|
||||
if (!passwords_match) {
|
||||
// throw new AppError(401, "Unauthorized: Invalid password");
|
||||
console.debug(password, "differs from", saved_password);
|
||||
throw new AppError(401, "Unauthorized", "Invalid credentials");
|
||||
}
|
||||
|
||||
const payload = { type: "user",
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
role: user.role };
|
||||
|
||||
const token = await cryptoUtils.signToken(payload);
|
||||
return token;
|
||||
|
||||
// // Check if passwords match
|
||||
// const passwords_match = await bcrypt.compare(password, user[0].password);
|
||||
// if (!passwords_match) {
|
||||
// // throw new AppError(401, "Unauthorized: Invalid password");
|
||||
// console.debug("Password doesn't match")
|
||||
// throw new AppError(401, "Unauthorized", "Invalid credentials");
|
||||
// }
|
||||
|
||||
// return jwt.sign({ username: user[0].username, role: user[0].role }, await JWT_Secret);
|
||||
}
|
||||
|
||||
// function authorizeRole(user, roles) {
|
||||
// if (!user || !roles.includes(user.role)) {
|
||||
// throw new AppError(401, "Unauthorized: You don't have the necessary permissions to access this resource");
|
||||
// }
|
||||
// }
|
||||
|
||||
module.exports = { login };
|
|
@ -1,7 +0,0 @@
|
|||
const model = require("../models/index");
|
||||
|
||||
async function getVersion() {
|
||||
return model.getVersion();
|
||||
}
|
||||
|
||||
module.exports = { getVersion }
|
|
@ -1,164 +0,0 @@
|
|||
const model = require("../models/mod");
|
||||
const AppError = require("../utils/appError");
|
||||
const { validateModData } = require("../utils/validate_legacy");
|
||||
const { mdToHtml } = require("../utils/convert");
|
||||
const { sanitizeModData } = require("../utils/sanitize");
|
||||
|
||||
|
||||
// --- Get ---
|
||||
|
||||
async function getAllMods() {
|
||||
return model.getAllMods();
|
||||
}
|
||||
|
||||
async function getModByName(name) {
|
||||
const res = model.getModByName(name);
|
||||
if (res.length == 0) {
|
||||
throw new AppError(404, "Cannot find mod with this name", "Not found");
|
||||
}
|
||||
return res[0];
|
||||
}
|
||||
|
||||
async function getFullModInfos(name) {
|
||||
const res = model.getFullModInfos(name);
|
||||
if (res.length == 0) {
|
||||
throw new AppError(404, "Cannot find mod with this name", "Not found");
|
||||
}
|
||||
return res[0];
|
||||
}
|
||||
|
||||
async function getModVersion(infos) {
|
||||
const { mod, version_number, game_version, platform, environment} = infos;
|
||||
const res = model.getModVersion(mod, version_number, game_version, platform, environment);
|
||||
if (res.length == 0) {
|
||||
throw new AppError(404, "Cannot find mod with this name", "Not found");
|
||||
}
|
||||
return res[0];
|
||||
}
|
||||
|
||||
|
||||
// --- Create ---
|
||||
|
||||
async function createMod(mod_data, author) {
|
||||
|
||||
// Check body validity
|
||||
//TODO
|
||||
console.warn("Skipping validity checks for createMod");
|
||||
// await validateModData(mod_data);
|
||||
|
||||
// Generate data
|
||||
const { name, display_name, description, mod_infos } = mod_data;
|
||||
mod_infos.full_description = await mdToHtml(mod_infos.full_description); // Convert
|
||||
await sanitizeModData(mod_data); // Sanitize
|
||||
//TODO
|
||||
mod_infos.creation_date = 0
|
||||
|
||||
// Write changes to database
|
||||
await model.createMod(name, display_name, author, description, mod_infos);
|
||||
|
||||
// Return
|
||||
return getModByName(name);
|
||||
}
|
||||
|
||||
async function addVersion(version_data) {
|
||||
|
||||
// Validate
|
||||
//TODO
|
||||
console.warn("Skipping validity checks for addVersion");
|
||||
|
||||
// Generate data
|
||||
const { mod_name, version_number, channel, changelog, game_version,
|
||||
platform, environment, url } = version_data; // Split
|
||||
changelog = await mdToHtml(changelog); // Convert
|
||||
await sanitizeModData(mod_data); // Sanitize
|
||||
const release_date = (new Date()).toLocaleDateString();
|
||||
|
||||
// Write changes
|
||||
await model.addVersion(mod_name, version_number, channel, changelog,
|
||||
release_date, game_version, platform, environment, url); // Database
|
||||
|
||||
// Return
|
||||
return await model.getModVersion(mod_name, version_number, game_version, platform, environment );
|
||||
}
|
||||
|
||||
async function addTags(mod, tags) {
|
||||
|
||||
// Validate
|
||||
//TODO
|
||||
console.warn("Skipping validity checks for addTags");
|
||||
|
||||
// Write changes
|
||||
await model.addTags(mod, tags);
|
||||
|
||||
// Return
|
||||
const { tags:res } = await model.getFullModInfos(mod);
|
||||
return { "mod": mod, "tags": res};
|
||||
|
||||
}
|
||||
|
||||
// --- Update ---
|
||||
|
||||
async function updateMod(diff_data) {
|
||||
//TODO
|
||||
throw new AppError(501, "Not implemented");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Delete
|
||||
|
||||
async function deleteMod(name) {
|
||||
|
||||
// Check existence
|
||||
const mod = await model.getModByName(name);
|
||||
if (!mod) {
|
||||
throw new AppError(404, "No was found with this name", "Not found")
|
||||
}
|
||||
|
||||
// Authorize
|
||||
// TODO move outside of this function
|
||||
if (mod.author != mod.user) {
|
||||
throw new AppError(403, "You don't have the necessary permissions to execute this action", "Forbidden");
|
||||
}
|
||||
|
||||
// Write changes to database
|
||||
await model.deleteMod(name);
|
||||
|
||||
// Return
|
||||
return mod;
|
||||
}
|
||||
|
||||
async function deleteVersion(version_infos) {
|
||||
|
||||
// Validate
|
||||
// TODO
|
||||
|
||||
// Generate data
|
||||
const res = await getModVersion(version_infos);
|
||||
const { mod, version_number, game_version, platform, environment} = version_infos;
|
||||
|
||||
// Write changes to db
|
||||
await model.deleteVersion(mod, version_number, game_version, platform, environment);
|
||||
|
||||
// Return
|
||||
return res;
|
||||
}
|
||||
|
||||
async function deleteTags(mod, tags) {
|
||||
|
||||
// Validate (check existence)
|
||||
//TODO
|
||||
console.warn("Skipping validity checks for deleteTags");
|
||||
|
||||
// Wites changes to db
|
||||
await model.deleteTags(mod, tags);
|
||||
|
||||
// Return
|
||||
const { tags:res } = await model.getFullModInfos(mod);
|
||||
return { "mod": mod, "tags": res};
|
||||
}
|
||||
|
||||
module.exports = { getAllMods, getModByName, getFullModInfos,
|
||||
createMod, addTags, addVersion,
|
||||
updateMod,
|
||||
deleteMod, deleteTags, deleteVersion };
|
|
@ -1,46 +0,0 @@
|
|||
const model = require("../models/user");
|
||||
const AppError = require("../utils/appError");
|
||||
const cryptoUtils = require("../utils/crypto");
|
||||
const { validateUserData } = require("../utils/validate_legacy");
|
||||
const { sanitizeUserData } = require("../utils/sanitize");
|
||||
|
||||
async function getAllUsers() {
|
||||
return await model.getAllUsers();
|
||||
}
|
||||
|
||||
async function getUserByName(name) {
|
||||
const res = await model.getUserByName(name);
|
||||
return res[0];
|
||||
}
|
||||
|
||||
async function createUser(user_data) {
|
||||
|
||||
// Check body validity
|
||||
// TODO
|
||||
|
||||
// Sanitize
|
||||
// TODO
|
||||
|
||||
// Gather data
|
||||
const { username, email, password, display_name, profile_picture, settings } = user_data
|
||||
const password_hash = await cryptoUtils.hashPassword(password);
|
||||
|
||||
await model.createUser(username, email, password_hash, display_name, null, null);
|
||||
return model.getUserByName(username);
|
||||
}
|
||||
|
||||
async function deleteUser(name, token_user) {
|
||||
|
||||
// Check existence
|
||||
const exists = await model.exists(name);
|
||||
if (!exists) {
|
||||
throw new AppError(404, "Cannot find user with this name", "Not found");
|
||||
}
|
||||
|
||||
const res = await model.getUserByName(name);
|
||||
await model.deleteUser(name);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
module.exports = { getAllUsers, getUserByName, createUser, deleteUser };
|
|
@ -1,27 +0,0 @@
|
|||
class AppError extends Error {
|
||||
constructor(statusCode, message, status = "", debugMsg = "") {
|
||||
super(message);
|
||||
this.statusCode = statusCode;
|
||||
this.debugMsg = debugMsg;
|
||||
// Get status
|
||||
if (status === "") {
|
||||
if (statusCode.toString().startsWith("4")) {
|
||||
this.status = "Fail";
|
||||
} else {
|
||||
this.status = "Error";
|
||||
}
|
||||
} else {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.tryCatch = (controller) => async (req, res, next) => {
|
||||
try {
|
||||
await controller(req, res, next);
|
||||
} catch(err) {
|
||||
next(err);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AppError;
|
|
@ -1,89 +0,0 @@
|
|||
// --- Define constants ---
|
||||
|
||||
// Imports
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { version } = require("../../package.json");
|
||||
|
||||
|
||||
// Var decalaration
|
||||
const config_folder = "config";
|
||||
const config_file_name = "config.json"
|
||||
|
||||
// Global variables
|
||||
let config = {};
|
||||
|
||||
// --- Default config ---
|
||||
|
||||
const default_config = {
|
||||
|
||||
"port": 8000,
|
||||
|
||||
"users": {
|
||||
"admin": {
|
||||
"username": "admin",
|
||||
"password": "admin"
|
||||
}
|
||||
},
|
||||
|
||||
"database": {
|
||||
"type": "sqlite"
|
||||
},
|
||||
|
||||
"auth" : {
|
||||
"JWT_secret": "HGF7654EGBNKJNBJH6754356788GJHGY",
|
||||
"tokenExpiry": "1h"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- Functions ---
|
||||
|
||||
function loadConfig() {
|
||||
|
||||
let user_config;
|
||||
|
||||
// Parse
|
||||
try {
|
||||
// Get user config
|
||||
user_config = JSON.parse(fs.readFileSync(path.resolve(path.join(config_folder, config_file_name))));
|
||||
|
||||
// Warns
|
||||
if (!user_config.auth || !user_config.auth.JWT_secret) {
|
||||
console.warn("WARNING: No JWT secret provided, using the default one. Please note that using the default secret is a major security risk.")
|
||||
}
|
||||
|
||||
// Merge default and user configs (default values)
|
||||
config = { ...default_config, ...user_config };
|
||||
}
|
||||
catch (err) {
|
||||
// Error messages
|
||||
console.debug("Error:", err)
|
||||
console.error("Error loading configuration, using the default settings");
|
||||
console.debug("Search path:", path.resolve("./"));
|
||||
console.debug("Config file:", path.resolve(path.join(config_folder, config_file_name)))
|
||||
|
||||
config = default_config;
|
||||
}
|
||||
|
||||
return config;
|
||||
|
||||
}
|
||||
|
||||
|
||||
async function getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
async function getJWTSecret() {
|
||||
return config.auth.JWT_secret || process.env.JWT_secret;
|
||||
}
|
||||
|
||||
async function getVersion() {
|
||||
// Could be done with process.env.npm_package_version
|
||||
// but may not work without without npm
|
||||
return version;
|
||||
}
|
||||
|
||||
// Exports
|
||||
module.exports = { loadConfig, getConfig, getVersion, getJWTSecret };
|
|
@ -1,11 +0,0 @@
|
|||
const marked = require("marked");
|
||||
|
||||
async function mdToHtml(md_content) {
|
||||
if (md_content) {
|
||||
return marked.parse(md_content);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mdToHtml };
|
|
@ -1,61 +0,0 @@
|
|||
// --- Imports ---
|
||||
const jwt = require("jsonwebtoken");
|
||||
const bcrypt = require("bcrypt");
|
||||
const { getConfig, getJWTSecret } = require("./configManager");
|
||||
|
||||
|
||||
// --- Config ---
|
||||
|
||||
// Declarations
|
||||
let JWT_Secret;
|
||||
let token_expiry;
|
||||
// Constant values
|
||||
const saltRounds = 12;
|
||||
// Load
|
||||
(async () => {
|
||||
const config = await getConfig();
|
||||
JWT_Secret = await getJWTSecret();
|
||||
token_expiry = config.auth.tokenExpiry;
|
||||
signature_algorithm = config.auth.signatureAlgorithm;
|
||||
})();
|
||||
|
||||
|
||||
// --- Functions ---
|
||||
|
||||
async function hashPassword(passwd) {
|
||||
const hash = bcrypt.hashSync(passwd, saltRounds);
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
async function passwordsMatch(password, hashed_password) {
|
||||
return await bcrypt.compare(password, hashed_password);
|
||||
}
|
||||
|
||||
|
||||
async function signToken(payload, options = null) {
|
||||
if (options == null) {
|
||||
return jwt.sign(payload, JWT_Secret, { expiresIn: token_expiry, });
|
||||
}
|
||||
else {
|
||||
return jwt.sign(payload, JWT_Secret, options);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function verifyToken(token) {
|
||||
return new Promise( async (resolve, reject) => {
|
||||
await jwt.verify( token, JWT_Secret, (err, user) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(user);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// --- Exports ---
|
||||
module.exports = { passwordsMatch, hashPassword, verifyToken, signToken };
|
|
@ -1,19 +0,0 @@
|
|||
const createDOMPurify = require("dompurify");
|
||||
const { JSDOM } = require("jsdom");
|
||||
|
||||
// Initialize
|
||||
const window = new JSDOM("").window;
|
||||
const DOMPurify = createDOMPurify(window);
|
||||
|
||||
async function sanitizeText(text) {
|
||||
return DOMPurify.sanitize(text);
|
||||
}
|
||||
|
||||
async function sanitizeModData(mod_data) {
|
||||
console.warn("Skipping sanitanization (not implemented)");
|
||||
// mod_data.displayName = await sanitizeText(mod_data.displayName);
|
||||
// mod_data.otherInfos.description = await sanitizeText(mod_data.otherInfos.description);
|
||||
// mod_data.otherInfos.changelogs = await sanitizeText(mod_data.otherInfos.changelogs);
|
||||
}
|
||||
|
||||
module.exports = { sanitizeText, sanitizeModData };
|
|
@ -1,51 +0,0 @@
|
|||
// --- Imports ---
|
||||
const AppError = require("./appError");
|
||||
|
||||
|
||||
// --- Functions ---
|
||||
|
||||
async function validateNewModData(mod_data) {
|
||||
|
||||
throw new AppError(501, "Not implemented");
|
||||
//TODO
|
||||
// try {
|
||||
// node_schemas.validateNewModData(node_data);
|
||||
// } catch (err) {
|
||||
// throw new AppError(400, "Missing or invalid fields", "Bad request", err);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
async function validateNewUserData(user_data) {
|
||||
|
||||
throw new AppError(501, "Not implemented");
|
||||
//TODO
|
||||
// try {
|
||||
// node_schemas.validateNewUserData(node_data);
|
||||
// } catch (err) {
|
||||
// throw new AppError(400, "Missing or invalid fields", "Bad request", err);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
async function validateCretendials(identifier, password) {
|
||||
|
||||
throw new AppError(501, "Not implemented");
|
||||
}
|
||||
|
||||
|
||||
// --- Utils ---
|
||||
|
||||
async function isEmail(text) {
|
||||
const email_regex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
|
||||
return email_regex.test(text);
|
||||
}
|
||||
|
||||
async function isID(text) {
|
||||
const id_regex = /[a-zA-Z0-9_]+/;
|
||||
return id_regex.test(text);
|
||||
}
|
||||
|
||||
|
||||
module.exports = { validateNewModData, validateNewUserData, isEmail, isID };
|
|
@ -1,98 +0,0 @@
|
|||
const mod_model = require("../models/mod");
|
||||
const user_model = require("../models/user");
|
||||
const AppError = require("./appError");
|
||||
|
||||
async function validateModData(mod_data) {
|
||||
//TODO WIP
|
||||
// Check fields existence
|
||||
const not_null = mod_data &&
|
||||
Object.keys(mod_data).length == 5 &&
|
||||
mod_data.name &&
|
||||
mod_data.displayName &&
|
||||
mod_data.author &&
|
||||
mod_data.versions != null;
|
||||
|
||||
// mod_data.otherInfos != null &&
|
||||
// Object.keys(mod_data.otherInfos).length == 0 &&
|
||||
// mod_data.otherInfos.description != null &&
|
||||
// mod_data.otherInfos.links != null &&
|
||||
// mod_data.otherInfos.tags != null &&
|
||||
// mod_data.otherInfos.screenshots != null &&
|
||||
// mod_data.otherInfos.license != null &&
|
||||
// mod_data.otherInfos.changelogs != null;
|
||||
|
||||
if (!not_null) {
|
||||
console.debug("Item is missing expected fields:", mod_data);
|
||||
throw new AppError(400, "Bad request", "Missing expected fields");
|
||||
}
|
||||
|
||||
// Check fields format (check if sanitized)
|
||||
const is_valid_name = /^[a-zA-Z0-9_]+$/.test(mod_data.name);
|
||||
const is_valid_displayName = true;
|
||||
// const is_valid_displayName = /^[a-zA-Z0-9_]+$/.test(mod_data.name); // Temporary
|
||||
// const
|
||||
|
||||
const is_valid = is_valid_name && is_valid_displayName;
|
||||
if (!is_valid) {
|
||||
console.debug("Fields are not following the expected formats");
|
||||
throw new AppError(400, "Bad request", "The provided fields don't match the expected format");
|
||||
}
|
||||
|
||||
// Check if mod already exists
|
||||
const exists = await mod_model.exists(mod_data.name);
|
||||
if (exists) {
|
||||
console.debug("Error: Item already exists");
|
||||
throw new AppError(403, "Forbidden", "Content with this name already exists");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function validateUserData(user_data) {
|
||||
throw new AppError(501, "Not implemented");
|
||||
|
||||
//TODO
|
||||
|
||||
// Check fields existence
|
||||
// ...
|
||||
|
||||
if (!not_null) {
|
||||
console.debug("Missing expected fields:", mod_data);
|
||||
throw new AppError(400, "Bad request: Missing expected fields");
|
||||
}
|
||||
|
||||
// Check fields format (check if sanitized)
|
||||
const is_valid_username = /^[a-zA-Z0-9_]+$/.test(user_data.username);
|
||||
// const is_valid_email = ...
|
||||
// ...
|
||||
|
||||
const is_valid = is_valid_username && is_valid_email;
|
||||
if (!is_valid) {
|
||||
console.debug("Fields are not following the expected formats");
|
||||
throw new AppError(400, "Bad request: The provided fields don't match the expected format");
|
||||
}
|
||||
|
||||
// Check if user already exists
|
||||
const exists = await user_model.exists(user_data.username);
|
||||
if (exists) {
|
||||
console.debug("Error: User already exists");
|
||||
throw new AppError(403, "Forbidden: User with this name already exists");
|
||||
}
|
||||
}
|
||||
|
||||
async function validateCretendials(identifier, password) {
|
||||
|
||||
throw new AppError(501, "Not implemented");
|
||||
}
|
||||
|
||||
async function isEmail(text) {
|
||||
const email_regex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
|
||||
return email_regex.test(text);
|
||||
}
|
||||
|
||||
async function isID(text) {
|
||||
const id_regex = /[a-zA-Z0-9_]+/;
|
||||
return id_regex.test(text);
|
||||
}
|
||||
|
||||
|
||||
module.exports = { validateModData, validateUserData, isEmail, isID };
|
Loading…
Reference in a new issue