You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

143 lines
4.2 KiB

import { knex, validation } from '../../lib/ormish.js';
import logging from "../../lib/logging.js";
import { developer_admin, API } from '../../lib/api.js';
const log = logging.create("api/admin/table.js");
export const get = async (req, res) => {
const api = new API(req, res);
const { name, search, row_id, currentPage } = req.query;
try {
const page = parseInt(currentPage || "0", 10);
if(!api.admin_authenticated) {
return api.error(401, "Admin rights required.");
} else if(name && search) {
// get the list of columns to search
const col_info = await knex(name).columnInfo();
const query = knex(name);
let columns = Object.getOwnPropertyNames(col_info);
for(let col of columns) {
// SECURITY: string interpolation but not sure how to do this without it
query.orWhere(col, "like", `%${search}%`);
}
// loop through and construct a mega where clause
let result = await query.paginate({perPage: 20, currentPage: page});
return api.reply(200, result);
} else if(name && !row_id) {
// TODO: restrict the tables that can be queried?
let result = await knex(name).paginate({perPage: 20, currentPage: page});
return api.reply(200, result);
} else if(name && row_id) {
let result = await knex(name).where({id: row_id}).first();
return api.reply(200, result);
} else {
return api.error(500, "name query parameter required, or name and row_id.");
}
} catch(error) {
log.error(error);
return api.error(500, "Internal server error.");
}
}
get.authenticated = !developer_admin;
export const del = async (req, res) => {
const api = new API(req, res);
const { name, row_id } = req.query;
try {
if(!api.admin_authenticated) {
return api.error(401, "Admin rights required.");
} else if(name && row_id) {
let res = await knex(name).where({id: row_id}).delete();
return api.reply(200, {message: "OK", result: res});
} else {
return api.error(500, "name and row_id required for delete");
}
} catch(error) {
log.error(error);
return api.error(500, "Internal server error.");
}
}
del.authenticated = !developer_admin;
export const post = async (req, res) => {
const api = new API(req, res);
const { name, row_id } = req.query;
try {
if(!api.admin_authenticated) {
return api.error(401, "Admin rights required.");
} else if(name && row_id) {
// normally the validation rules come from the
// model class once and placed at the top of the
// module, but here we get it dynamically based
// on the name.
const rules = validation(name, {}, true);
const data = api.validate(rules);
// remove the id since they can't set it
delete data["id"];
if(!data._valid) {
return api.validation_error(res, data);
} else {
// remove id so it's not updated too
api.clean_form(data, rules, ["id"]);
let res = await knex(name).
where({id: row_id}).update(data);
return api.reply(200, {message: "OK", result: res});
}
} else {
return api.error(500, "name and row_id required for delete");
}
} catch(error) {
log.error(error);
return api.error(500, error.message || "Internal server error.");
}
}
post.authenticated = !developer_admin;
export const put = async (req, res) => {
const api = new API(req, res);
const { name } = req.query;
try {
if(!api.admin_authenticated) {
return api.error(401, "Admin rights required.");
} else if(name) {
const rules = validation(name, {}, true);
// don't validate id or accept it
const data = api.validate(rules);
// remove the id since they can't set it
delete data["id"];
if(!data._valid) {
return api.validation_error(res, data);
} else {
api.clean_form(data, rules, ["id"]);
let res = await knex(name).insert(data);
return api.reply(200, {message: "OK", id: res[0]});
}
} else {
return api.error(500, "name required for delete");
}
} catch(error) {
log.error(error);
return api.error(500, "Internal server error.");
}
}
put.authenticated = !developer_admin;