kutt/server/queries/domain.queries.js
2024-11-19 07:58:57 +03:30

219 lines
5.1 KiB
JavaScript

const redis = require("../redis");
const utils = require("../utils");
const knex = require("../knex");
const env = require("../env");
async function find(match) {
if (match.address && env.REDIS_ENABLED) {
const cachedDomain = await redis.client.get(redis.key.domain(match.address));
if (cachedDomain) return JSON.parse(cachedDomain);
}
const domain = await knex("domains").where(match).first();
if (domain && env.REDIS_ENABLED) {
const key = redis.key.domain(domain.address);
redis.client.set(key, JSON.stringify(domain), "EX", 60 * 15);
}
return domain;
}
function get(match) {
return knex("domains").where(match);
}
async function add(params) {
params.address = params.address.toLowerCase();
const existingDomain = await knex("domains").where("address", params.address).first();
let id = existingDomain?.id;
const newDomain = {
address: params.address,
homepage: params.homepage,
user_id: params.user_id,
banned: !!params.banned,
banned_by_id: params.banned_by_id
};
if (id) {
await knex("domains").where("id", id).update({
...newDomain,
updated_at: params.updated_at || utils.dateToUTC(new Date())
});
} else {
// Mysql and sqlite don't support returning but return the inserted id by default
const [createdDomain] = await knex("domains").insert(newDomain).returning("id");
id = createdDomain.id;
}
// Query domain instead of using returning as sqlite and mysql don't support it
const domain = await knex("domains").where("id", id).first();
if (env.REDIS_ENABLED) {
redis.remove.domain(domain);
}
return domain;
}
async function update(match, update) {
await knex("domains")
.where(match)
.update({ ...update, updated_at: utils.dateToUTC(new Date()) });
const domains = await knex("domains").select("*").where(match);
if (env.REDIS_ENABLED) {
domains.forEach(redis.remove.domain);
}
return domains;
}
function normalizeMatch(match) {
const newMatch = { ...match };
if (newMatch.address) {
newMatch["domains.address"] = newMatch.address;
delete newMatch.address;
}
if (newMatch.user_id) {
newMatch["domains.user_id"] = newMatch.user_id;
delete newMatch.user_id;
}
if (newMatch.uuid) {
newMatch["domains.uuid"] = newMatch.uuid;
delete newMatch.uuid;
}
if (newMatch.banned !== undefined) {
newMatch["domains.banned"] = newMatch.banned;
delete newMatch.banned;
}
return newMatch;
}
const selectable_admin = [
"domains.id",
"domains.address",
"domains.homepage",
"domains.banned",
"domains.created_at",
"domains.updated_at",
"domains.user_id",
"domains.uuid",
"users.email as email",
"links_count"
];
async function getAdmin(match, params) {
const query = knex("domains").select(...selectable_admin);
Object.entries(normalizeMatch(match)).forEach(([key, value]) => {
query.andWhere(key, ...(Array.isArray(value) ? value : [value]));
});
query
.offset(params.skip)
.limit(params.limit)
.fromRaw("domains")
.orderBy("domains.id", "desc")
.groupBy(1)
.groupBy("l.links_count")
.groupBy("users.email");
if (params?.user) {
const id = parseInt(params?.user);
if (Number.isNaN(id)) {
query.andWhereILike("users.email", "%" + params.user + "%");
} else {
query.andWhere("domains.user_id", id);
}
}
if (params?.search) {
query.andWhereRaw(
"concat_ws(' ', domains.address, domains.homepage) ILIKE '%' || ? || '%'",
[params.search]
);
}
if (params?.links !== undefined) {
query.andWhere("links_count", params?.links ? "is not" : "is", null);
}
query.leftJoin(
knex("links").select("domain_id").count("id as links_count").groupBy("domain_id").as("l"),
"domains.id",
"l.domain_id"
);
query.leftJoin("users", "domains.user_id", "users.id");
return query;
}
async function totalAdmin(match, params) {
const query = knex("domains");
Object.entries(normalizeMatch(match)).forEach(([key, value]) => {
query.andWhere(key, ...(Array.isArray(value) ? value : [value]));
});
if (params?.user) {
const id = parseInt(params?.user);
if (Number.isNaN(id)) {
query.andWhereILike("users.email", "%" + params.user + "%");
} else {
query.andWhere("domains.user_id", id);
}
}
if (params?.search) {
query.andWhereILike("domains.address", "%" + params.search + "%");
}
if (params?.links !== undefined) {
query.leftJoin(
knex("links").select("domain_id").count("id as links_count").groupBy("domain_id").as("l"),
"domains.id",
"l.domain_id"
);
query.andWhere("links_count", params?.links ? "is not" : "is", null);
}
query.leftJoin("users", "domains.user_id", "users.id");
query.count("domains.id");
const [{ count }] = await query;
return typeof count === "number" ? count : parseInt(count);
}
async function remove(domain) {
const deletedDomain = await knex("domains").where("id", domain.id).delete();
if (env.REDIS_ENABLED) {
redis.remove.domain(domain);
}
return !!deletedDomain;
}
module.exports = {
add,
find,
get,
getAdmin,
remove,
totalAdmin,
update,
}