@opengis/fastify-table
Version:
core-plugins
161 lines (160 loc) • 6.37 kB
JavaScript
import { config, getAccess, getTemplate, getMeta, setToken, applyHook, getToken, pgClients, } from "../../../../utils.js";
import extraDataGet from "../../../plugins/extra/extraDataGet.js";
export default async function tableAPI(req, reply, called) {
const { pg = pgClients.client, params, user = {}, query = {} } = req;
const tokenData = await getToken({
token: params?.table,
uid: user.uid,
json: 1,
});
const hookData = (await applyHook("preTable", {
pg,
table: params?.table,
id: params?.id,
...(tokenData || {}),
user,
}));
if (hookData?.message && hookData?.status) {
return reply.status(hookData?.status).send(hookData?.message);
}
const templateName = hookData?.table || tokenData?.table || params.table;
const loadTable = await getTemplate("table", templateName);
if (!loadTable &&
!pg.pk?.[tokenData?.table] &&
!(pg.pk?.[templateName] && called)) {
return reply.status(404).send({ error: "not found", code: 404 });
}
const { table: table1 = params.table, form: form1, obj, } = hookData || loadTable || tokenData || {};
const table = loadTable?.table || table1;
const form = loadTable?.form || form1;
const id = hookData?.id || tokenData?.id || params.id;
if (tokenData && !id) {
return reply.status(403).send({ error: "invalid token", code: 403 });
}
if (!table && !id) {
return reply.status(400).send("not enough params");
}
const { actions = [], query: accessQuery } = (await getAccess({
table: templateName,
form,
id,
user,
}, pg)) || {};
if (!tokenData &&
!config?.local &&
!config.security?.disableToken &&
!called) {
return reply.status(400).send("invalid token");
}
if (!actions.includes("edit") && !config?.local && !tokenData && !called) {
return reply
.status(403)
.send({ error: "access restricted: actions", code: 403 });
}
const { pk, columns: dbColumns = [] } = await getMeta({
pg,
table,
});
if (!pk) {
return reply
.status(404)
.send({ error: `table not found: ${table}`, code: 404 });
}
// const cols = columns.map((el) => el.name || el).join(',');
const formData = (await getTemplate("form", form)) || {};
const schema = formData?.schema || formData || {};
// skip DataTable from another table
const extraKeys = Object.keys(schema).filter((key) => schema[key]?.table &&
schema[key]?.parent_id &&
Object.hasOwn(schema[key], "colModel"));
// skip non-existing columns
const columnList = dbColumns.map((el) => el.name || el).join(",");
const { fields = [] } = !loadTable?.table
? await pg.query(`select * from ${table} limit 0`)
: {};
const cols = loadTable?.table
? Object.keys(schema || {})
.filter((col) => columnList.includes(col) && !extraKeys.includes(col))
?.map((col) => col?.includes("geom") && schema?.[col]?.type === "Geom"
? `st_asgeojson(${col})::json as "${col}"`
: `"${col}"`)
?.join(",")
: fields
.map((el) => el?.name?.includes("geom") && pg.pgType[el?.dataTypeID] === "geometry"
? `st_asgeojson(${el.name})::json as "${el.name}"`
: `"${el?.name}"`)
.join(",");
const where = [`"${pk}" = $1`, loadTable?.query, accessQuery]
.filter(Boolean)
.filter((el) => user?.user_type === "superadmin" ? !el.includes("{{uid}}") : true);
const geom = dbColumns.find((el) => el.name === "geom" && pg.pgType[el.dataTypeID] === "geometry")
? ",st_asgeojson(geom)::json as geom"
: "";
const q = `select "${pk}" as id, ${cols || "*"} ${geom} from ${table} t where ${where.join(" and ") || "true"} limit 1`;
if (query?.sql === "1") {
const extraQ = extraKeys
?.map((key) => {
const { colModel, table: extraTable, parent_id: parentId, } = schema[key];
const colModel1 = Array.isArray(colModel)
? colModel
: Object.values(colModel || {});
return colModel1.length
? `/*${key}*/ select ${parentId} as parent, ${colModel1
.map((col) => col.name || col.key)
.join(",")} from ${extraTable} a where ${parentId}::text=$1`
: null;
})
.filter((el) => el)
.join(";");
return `${q};${extraQ || ""}`.replace(/\$1/g, `'${id}'`);
}
const data = await pg
.query(q.replace(/{{uid}}/, user?.uid), [id])
.then((el) => el.rows[0]);
if (!data) {
return reply
.status(404)
.send({ error: `object not found: ${id}`, code: 404 });
}
Object.keys(schema)
.filter((key) => schema[key]?.type === "DataTable")
.forEach((key) => {
if (data[key] && !Array.isArray(data[key])) {
data[key] = null;
}
});
if (extraKeys?.length) {
await Promise.all(extraKeys?.map(async (key) => {
const { colModel, table: extraTable, parent_id: parentId, } = schema[key];
const colModel1 = Array.isArray(colModel)
? colModel
: Object.values(colModel || {});
const q1 = `select ${parentId} as parent, ${colModel1
.map((col) => col.name || col.key)
.join(",")} from ${extraTable} a where ${parentId}=$1`;
// console.log(table, formName, q1);
const { rows: extraRows } = await pg.query(q1, [id]);
Object.assign(data, { [key]: extraRows });
}));
}
if (user?.uid &&
!config.security?.disableToken &&
actions.includes("edit") &&
!called) {
data.token = tokenData?.table
? params.table
: setToken({
ids: [JSON.stringify({ id, table, form, obj })],
uid: user.uid,
array: 1,
})?.[0];
}
await extraDataGet({ rows: [data], table, form }, pg);
const res = await applyHook("afterTable", {
pg,
table,
payload: [data],
user,
});
return res || data || {};
}