@opengis/fastify-table
Version:
core-plugins
141 lines (140 loc) • 4.65 kB
JavaScript
import { config, logger } from "../../../../utils.js";
import block from "../sqlInjection.js";
export default function checkPolicy(req, reply) {
const { originalUrl: path, hostname, query, params, headers, method, routeOptions, unittest, // legacy
} = req;
const user = req.user || req.session?.passport?.user;
// ! skip locally, skip tests
if ((config.local || unittest || process.env.NODE_ENV === "test") &&
user?.user_type !== "viewer") {
return null;
}
// ! skip non-API Requests, handle with vite/vike
const isApi = routeOptions.method &&
routeOptions.url &&
typeof routeOptions.handler === "function" &&
routeOptions.url !== "*";
if (!isApi) {
return null;
}
const body = req.body
? JSON.stringify(req?.body || {}).substring(30)
: undefined;
const isAdmin = process.env.NODE_ENV === "admin" ||
hostname.split(":").shift() === config.adminDomain ||
config.admin ||
hostname.startsWith("admin");
const { role, referer, policy = [], allowSql, } = (routeOptions?.config || {});
// role=admin|regular
const isRole = (role && (!user?.user_type || !role?.includes?.(user?.user_type))) ||
(policy.includes("admin") && user?.user_type !== "admin");
const allowExtPublic = [".png", ".jpg", ".svg"];
const ext = path.toLowerCase().substr(-4);
const isPublic = Array.isArray(policy)
? policy.includes("public")
: policy === "L0";
const requireUser = Array.isArray(policy)
? policy.includes("user")
: ["L1", "L2", "L3"].includes(policy);
const requireReferer = Array.isArray(policy)
? policy.includes("referer")
: referer;
if (method !== "GET" && user?.user_type === "viewer") {
logger.file("policy/role", {
path,
method,
userRole: user.user_type,
});
return reply.status(403).send({ error: "access restricted: 0", code: 403 });
}
// ! role
if (isRole) {
logger.file("policy/role", {
role,
userRole: user?.user_type || "none",
path,
method,
params,
query,
body,
uid: user?.uid,
});
return reply.status(403).send({ error: "access restricted: 0", code: 403 });
}
// ! file injection
if (JSON.stringify(params || {})?.includes("../") ||
JSON.stringify(query || {})?.includes("../") ||
path?.includes("../")) {
logger.file("injection/file", {
path,
method,
params,
query,
body,
uid: user?.uid,
});
return reply.status(409).send({ error: "access restricted: 1", code: 409 });
}
// ! invalid file extension
if (path.includes("files/") && allowExtPublic.includes(ext)) {
return null;
}
// ! sql injection
const stopWords = block.filter((el) => path.includes(el) || JSON.stringify(req.body || {}).includes(el));
if (stopWords?.length && !allowSql) {
logger.file("injection/sql", {
path,
method,
params,
query,
body,
stopWords,
uid: user?.uid,
});
return reply.status(409).send({ error: "access restricted: 2", code: 409 });
}
// ! user required, but not logged in
if (requireUser && !user) {
logger.file("policy/user", {
path,
method,
params,
query,
body,
});
return reply.status(401).send({ error: "access restricted: 3", code: 401 });
}
// ! referer
if (requireReferer && !headers?.referer?.includes?.(hostname)) {
logger.file("policy/referer", {
path,
method,
params,
query,
body,
uid: user?.uid,
});
return reply.status(403).send({ error: "access restricted: 4", code: 403 });
}
// ! public / token
if (isPublic || config.debug) {
return null;
}
// ! block any API for admin panel (without authorization)
if (isAdmin &&
!req.url?.includes?.("/assets") &&
!config.debug &&
!user?.uid) {
logger.file("policy/api", {
path,
method,
params,
query,
body,
message: "access restricted: 6",
uid: user?.uid,
});
return reply.status(403).send({ error: "access restricted: 6", code: 403 });
}
return null;
}