160 lines
4.1 KiB
TypeScript
160 lines
4.1 KiB
TypeScript
import { Request, Response, Router } from 'express';
|
|
import { http } from '@scode/consts';
|
|
import { ControlModel, DatabaseModel } from '@scode/modelling';
|
|
import { CrudHandler } from './CrudHandler';
|
|
import { HttpHandler } from './HttpHandler';
|
|
import { DatabaseCrudOptionsReader } from './DatabaseCrudOptionsReader';
|
|
|
|
export class DatabaseCrudHandler extends HttpHandler implements CrudHandler {
|
|
protected cm: new () => ControlModel;
|
|
protected dm: new () => DatabaseModel;
|
|
protected options: DatabaseCrudOptionsReader;
|
|
|
|
public constructor<T extends ControlModel, U extends DatabaseModel> (
|
|
table: string,
|
|
cm: new () => ControlModel,
|
|
dm: new () => DatabaseModel
|
|
) {
|
|
super ();
|
|
this.cm = cm;
|
|
this.dm = dm;
|
|
this.options = new DatabaseCrudOptionsReader (options);
|
|
}
|
|
|
|
protected validate_body (
|
|
req: Request,
|
|
res: Response
|
|
): Promise<Record<string, unknown>> | Record<string, unknown> {
|
|
if (typeof req.body === 'undefined') {
|
|
res.status (http.status_bad_request);
|
|
res.end ('body was undefined');
|
|
return null;
|
|
}
|
|
try {
|
|
return JSON.parse (req.body);
|
|
}
|
|
catch (e) {
|
|
res.status (http.status_bad_request);
|
|
res.end ('invalid json input');
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public async create (req: Request, res: Response): Promise<void> {
|
|
if (!await this.options.create_authorization (req, res))
|
|
return;
|
|
|
|
const body_data = await this.validate_body (req, res);
|
|
if (body_data === null)
|
|
return;
|
|
|
|
const cm = new this.cm;
|
|
cm.object = body_data;
|
|
cm.update ();
|
|
|
|
const dm = new this.dm;
|
|
for (const key of Object.keys (body_data))
|
|
dm.set (key, cm.get (key));
|
|
await dm.write ();
|
|
|
|
res.status (http.status_created)
|
|
.end (dm.id);
|
|
}
|
|
|
|
public async read (req: Request, res: Response): Promise<void> {
|
|
if (!await this.options.read_authorization (req, res))
|
|
return;
|
|
|
|
if (typeof req.headers.id === 'undefined') {
|
|
res.status (http.status_bad_request)
|
|
.end ('id undefined');
|
|
return;
|
|
}
|
|
|
|
const dm = new this.dm (req.headers.id);
|
|
const found = await dm.read ();
|
|
|
|
const cm = new this.cm (dm.object);
|
|
cm.update ();
|
|
|
|
res.status (found ? http.status_ok : http.status_not_found)
|
|
.json (cm.object);
|
|
}
|
|
|
|
public async update (req: Request, res: Response): Promise<void> {
|
|
if (!await this.options.update_authorization (req, res))
|
|
return;
|
|
|
|
const body_data = await this.validate_body (req, res);
|
|
if (body_data === null)
|
|
return;
|
|
|
|
if (typeof req.headers.id === 'undefined') {
|
|
res.status (http.status_bad_request)
|
|
.end ('id undefined');
|
|
return;
|
|
}
|
|
|
|
const dm = new this.dm (req.headers.id);
|
|
const found = await dm.read ();
|
|
if (!found) {
|
|
res.status (http.status_not_found)
|
|
.end ();
|
|
return;
|
|
}
|
|
|
|
const cm = new this.cm (dm.object);
|
|
cm.update ();
|
|
|
|
for (const key of Object.keys (body_data))
|
|
cm.set (key, body_data[key]);
|
|
cm.update ();
|
|
|
|
dm.object = cm.object;
|
|
const written = await dm.write ();
|
|
|
|
res.status (written ? http.status_ok : http.status_internal_server_error)
|
|
.end ();
|
|
}
|
|
|
|
public async delete (req: Request, res: Response): Promise<void> {
|
|
if (!await this.options.delete_authorization (req, res))
|
|
return;
|
|
|
|
if (typeof req.headers.id === 'undefined') {
|
|
res.status (http.status_bad_request)
|
|
.end ('id undefined');
|
|
return;
|
|
}
|
|
|
|
const dm = new this.dm (req.headers.id);
|
|
const found = await dm.read ();
|
|
if (!found) {
|
|
res.status (http.status_not_found)
|
|
.end ();
|
|
return;
|
|
}
|
|
|
|
const deleted = await dm.delete ();
|
|
|
|
res.status (deleted ? http.status_ok : http.status_internal_server_error)
|
|
.end ();
|
|
}
|
|
|
|
protected async create_or_update (
|
|
req: Request,
|
|
res: Response
|
|
): Promise<void> {
|
|
if (typeof req.headers.id === 'undefined')
|
|
await this.create (req, res);
|
|
else
|
|
await this.update (req, res);
|
|
}
|
|
|
|
public register_handlers (router: Router): void {
|
|
router.post ('/', this.create_or_update);
|
|
router.get ('/', this.read);
|
|
router.delete ('/', this.delete);
|
|
}
|
|
}
|