Compare commits

...

3 Commits

Author SHA1 Message Date
6b665bb41d Add Security disclaimer / reformat readme 2025-02-22 21:46:44 +01:00
5720b45c6b Fix formatting 2025-02-22 21:45:17 +01:00
de5a4b9f19 Add codecheck endpoint 2025-02-22 21:45:00 +01:00
6 changed files with 87 additions and 12 deletions

View File

@ -1,9 +1,13 @@
# HydrationHUB
HydrationHUB - TODO: Luistiger slogan?
## Serving static files from node_modules
## Security Disclaimer
This application is not designed for security and therefore has exploitable vulnerabilities.
This is due to the simplicity of the application and is sufficient for the intended purpose.
If you plan to use this application for a different purpose where security vulnerabilities are a concern, we would greatly appreciate your contributions.
## Static handling
### Serving static files from node_modules
Files from explicit dirs inside `node_modules` will be served below `/libs`.
## Serving static files from /static
### Serving static files from /static
Files from the `/static` folder will be served below `/static`.

View File

@ -8,6 +8,9 @@ import versionRoute from './version.js';
import user_route from './user.js';
import user_schema from './user_schema.js';
import user_codecheck_route from './user_codecheck.js';
import user_codecheck_schema from './user_codecheck_schema.js';
import products_route from './products.js';
import products_schema from './products_schema.js';
@ -28,6 +31,9 @@ Router.use('*', function (req, res, next) {
Router.route('/user').get(user_route.get).post(user_route.post).patch(user_route.patch).delete(user_route.del);
Router.route('/user/describe').get(user_schema);
Router.route('/user/codecheck').get(user_codecheck_route.get);
Router.route('/user/codecheck/describe').get(user_codecheck_schema);
Router.route('/products').get(products_route.get).post(products_route.post).patch(products_route.patch).delete(products_route.del);
Router.route('/products/describe').get(products_schema);

View File

@ -95,7 +95,7 @@ async function post(req: Request, res: Response) {
.create({
data: {
name: value.name,
code: (value.code === '0000') ? null : value.code
code: value.code === '0000' ? null : value.code
},
select: {
id: true
@ -125,7 +125,7 @@ async function patch(req: Request, res: Response) {
},
data: {
name: value.name,
code: (value.code === '0000') ? null : value.code
code: value.code === '0000' ? null : value.code
},
select: {
id: true
@ -156,7 +156,8 @@ async function del(req: Request, res: Response) {
})
.then((result) => {
res.status(200).json({ status: 'DELETED', message: 'Successfully deleted user', id: result.id });
}).catch((err) => {
})
.catch((err) => {
handlePrismaError(err, res, 'DEL user');
});
}

View File

@ -0,0 +1,34 @@
import { Request, Response } from 'express';
import db, { handlePrismaError } from '../../../handlers/db.js'; // Database
import log from '../../../handlers/log.js';
import { schema_get } from './user_codecheck_schema.js';
// MARK: GET check user code
async function get(req: Request, res: Response) {
const { error, value } = schema_get.validate(req.query);
if (error) {
log.api?.debug('GET check user code Error:', req.query, value, error.details[0].message);
res.status(400).json({ status: 'ERROR', errorcode: 'VALIDATION_ERROR', message: error.details[0].message });
} else {
log.api?.debug('GET check user code Success:', req.query, value);
await db.user
.findUnique({
where: {
id: value.id
}
})
.catch((err) => {
handlePrismaError(err, res, 'GET check user code');
})
.then((result) => {
// user has no code OR code must match
res.status(200).json(result?.code === '' || value.code === result?.code);
// log.api?.debug('result', result);
});
// res.status(200).json({ count, result });
// res.status(404).json({ status: 'ERROR', errorcode: 'NOT_FOUND', message: 'Could not find specified object' });
}
}
export default { get };

View File

@ -0,0 +1,32 @@
import { Request, Response } from 'express';
import validator from 'joi'; // DOCS: https://joi.dev/api
// MARK: GET check user code
const schema_get = validator.object({
id: validator.number().positive().precision(0).required(),
code: validator
.string()
.min(4)
.max(4)
.trim()
.regex(new RegExp(/^[0-9]+$/))
.required()
});
// Describe all schemas
const schema_get_desc = schema_get.describe();
// const schema_post_desc = schema_post.describe();
// const schema_patch_desc = schema_patch.describe();
// const schema_del_desc = schema_del.describe();
// GET route
export default async function get(req: Request, res: Response) {
res.status(200).json({
GET: schema_get_desc
// POST: schema_post_desc,
// PATCH: schema_patch_desc,
// DELETE: schema_del_desc
});
}
export { schema_get }; //, schema_post, schema_patch, schema_del };

View File

@ -1,8 +1,7 @@
import express from 'express';
import path from 'node:path';
import __path from "../handlers/path.js";
import log from "../handlers/log.js";
import __path from '../handlers/path.js';
import log from '../handlers/log.js';
// Route imports
import frontend_routes from './frontend/index.js';
@ -12,7 +11,7 @@ const Router = express.Router({ strict: false });
// static / libs routes
Router.use('/static', express.static(__path + '/static'));
Router.use('/libs/bulma', express.static(path.join(__path, 'node_modules', 'bulma', 'css'))); // http://192.168.221.10:3000/libs/bulma/bulma.css
Router.use('/libs/bulma', express.static(path.join(__path, 'node_modules', 'bulma', 'css'))); // /libs/bulma/bulma.css
Router.use('/libs/jquery', express.static(path.join(__path, 'node_modules', 'jquery', 'dist')));
Router.use('/libs/bootstrap-icons', express.static(path.join(__path, 'node_modules', 'bootstrap-icons')));
@ -20,7 +19,6 @@ Router.use('/libs/bootstrap-icons', express.static(path.join(__path, 'node_modul
Router.use('/api', api_routes);
Router.use('/', frontend_routes);
// Default route.
Router.all('*', function (req, res) {
// TODO: Respond based on content-type (with req.is('application/json'))