summary refs log tree commit diff
path: root/util/src
diff options
context:
space:
mode:
authorFlam3rboy <34555296+Flam3rboy@users.noreply.github.com>2021-09-28 22:27:01 +0200
committerFlam3rboy <34555296+Flam3rboy@users.noreply.github.com>2021-09-28 22:27:01 +0200
commit3e9952ea8026743c86d25152c8febbe55722a135 (patch)
treef928ba0428a0f284ffc4c2146f412249c9693b7e /util/src
parentMerge branch 'master' of https://github.com/fosscord/fosscord-server (diff)
parent:bug: fix channel permission overwrites (diff)
downloadserver-3e9952ea8026743c86d25152c8febbe55722a135.tar.xz
Merge branch 'master' of https://github.com/fosscord/fosscord-server
Diffstat (limited to 'util/src')
-rw-r--r--util/src/entities/Channel.ts4
-rw-r--r--util/src/entities/Config.ts29
-rw-r--r--util/src/util/Config.ts58
-rw-r--r--util/src/util/Database.ts2
-rw-r--r--util/src/util/Permissions.ts15
-rw-r--r--util/src/util/cdn.ts4
6 files changed, 87 insertions, 25 deletions
diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts

index ece82bd0..1644b265 100644 --- a/util/src/entities/Channel.ts +++ b/util/src/entities/Channel.ts
@@ -320,8 +320,8 @@ export class Channel extends BaseClass { } export interface ChannelPermissionOverwrite { - allow: bigint; // for bitfields we use bigints - deny: bigint; // for bitfields we use bigints + allow: string; + deny: string; id: string; type: ChannelPermissionOverwriteType; } diff --git a/util/src/entities/Config.ts b/util/src/entities/Config.ts
index a460b437..6d9db470 100644 --- a/util/src/entities/Config.ts +++ b/util/src/entities/Config.ts
@@ -1,12 +1,15 @@ -import { Column, Entity, JoinColumn, ManyToOne } from "typeorm"; -import { BaseClass } from "./BaseClass"; +import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from "typeorm"; +import { BaseClass, BaseClassWithoutId } from "./BaseClass"; import crypto from "crypto"; import { Snowflake } from "../util/Snowflake"; @Entity("config") -export class ConfigEntity extends BaseClass { - @Column({ type: "simple-json" }) - value: ConfigValue; +export class ConfigEntity extends BaseClassWithoutId { + @PrimaryColumn() + key: string; + + @Column({ type: "simple-json", nullable: true }) + value: number | boolean | null | string | undefined; } export interface RateLimitOptions { @@ -37,14 +40,16 @@ export interface KafkaBroker { export interface ConfigValue { gateway: { endpointClient: string | null; - endpoint: string | null; + endpointPrivate: string | null; + endpointPublic: string | null; }; cdn: { endpointClient: string | null; - endpoint: string | null; + endpointPublic: string | null; + endpointPrivate: string | null; }; general: { - instance_id: string; + instanceId: string; }; permissions: { user: { @@ -149,14 +154,16 @@ export interface ConfigValue { export const DefaultConfigOptions: ConfigValue = { gateway: { endpointClient: null, - endpoint: null, + endpointPrivate: null, + endpointPublic: null, }, cdn: { endpointClient: null, - endpoint: null, + endpointPrivate: null, + endpointPublic: null, }, general: { - instance_id: Snowflake.generate(), + instanceId: Snowflake.generate(), }, permissions: { user: { diff --git a/util/src/util/Config.ts b/util/src/util/Config.ts
index c87d598e..6a9e0e5a 100644 --- a/util/src/util/Config.ts +++ b/util/src/util/Config.ts
@@ -1,22 +1,66 @@ import "missing-native-js-functions"; import { ConfigValue, ConfigEntity, DefaultConfigOptions } from "../entities/Config"; -var config: ConfigEntity; +var config: ConfigValue; +var pairs: ConfigEntity[]; + // TODO: use events to inform about config updates +// Config keys are separated with _ export const Config = { init: async function init() { if (config) return config; - config = (await ConfigEntity.findOne({ id: "0" })) || new ConfigEntity({ id: "0" }); + pairs = await ConfigEntity.find(); + config = pairsToConfig(pairs); - return this.set((config.value || {}).merge(DefaultConfigOptions)); + return this.set((config || {}).merge(DefaultConfigOptions)); }, get: function get() { - return config.value as ConfigValue; + return config; }, set: function set(val: Partial<ConfigValue>) { - if (!config) return; - config.value = val.merge(config?.value || {}); - return config.save(); + if (!config || !val) return; + config = val.merge(config); + console.log(config); + + return applyConfig(config); }, }; + +function applyConfig(val: ConfigValue) { + async function apply(obj: any, key = ""): Promise<any> { + if (typeof obj === "object" && obj !== null) + return Promise.all(Object.keys(obj).map((k) => apply(obj[k], key ? `${key}_${k}` : k))); + + let pair = pairs.find((x) => x.key === key); + if (!pair) pair = new ConfigEntity(); + + pair.key = key; + pair.value = obj; + return pair.save(); + } + + return apply(val); +} + +function pairsToConfig(pairs: ConfigEntity[]) { + var value: any = {}; + + pairs.forEach((p) => { + const keys = p.key.split("_"); + let prev = ""; + let obj = value; + let i = 0; + + for (const key of keys) { + if (Number(key) && !obj[prev]) obj = obj[prev] = []; + if (i++ === keys.length - 1) obj[key] = p.value; + else if (!obj[key]) obj[key] = {}; + + prev = key; + obj = obj[key]; + } + }); + + return value as ConfigValue; +} diff --git a/util/src/util/Database.ts b/util/src/util/Database.ts
index 0c3d7cef..ab7c70c5 100644 --- a/util/src/util/Database.ts +++ b/util/src/util/Database.ts
@@ -22,7 +22,7 @@ export function initDatabase() { // entities: Object.values(Models).filter((x) => x.constructor.name !== "Object"), synchronize: true, - logging: true, + logging: false, cache: { duration: 1000 * 3, // cache all find queries for 3 seconds }, diff --git a/util/src/util/Permissions.ts b/util/src/util/Permissions.ts
index 44852f1e..f0012c96 100644 --- a/util/src/util/Permissions.ts +++ b/util/src/util/Permissions.ts
@@ -3,6 +3,7 @@ import { Channel, ChannelPermissionOverwrite, Guild, Member, Role } from "../entities"; import { BitField } from "./BitField"; import "missing-native-js-functions"; +import { BitFieldResolvable } from "."; // TODO: check role hierarchy permission var HTTPError: any; @@ -17,11 +18,19 @@ export type PermissionResolvable = bigint | number | Permissions | PermissionRes type PermissionString = keyof typeof Permissions.FLAGS; -const CUSTOM_PERMISSION_OFFSET = BigInt(1) << BigInt(48); // 16 free custom permission bits, and 11 for discord to add new ones +// BigInt doesn't have a bit limit (https://stackoverflow.com/questions/53335545/whats-the-biggest-bigint-value-in-js-as-per-spec) +const CUSTOM_PERMISSION_OFFSET = BigInt(1) << BigInt(64); // 27 permission bits left for discord to add new ones export class Permissions extends BitField { cache: PermissionCache = {}; + constructor(bits: BitFieldResolvable = 0) { + super(bits); + if (this.bitfield & Permissions.FLAGS.ADMINISTRATOR) { + this.bitfield = ALL_PERMISSIONS; + } + } + static FLAGS = { CREATE_INSTANT_INVITE: BigInt(1) << BigInt(0), KICK_MEMBERS: BigInt(1) << BigInt(1), @@ -92,7 +101,7 @@ export class Permissions extends BitField { } overwriteChannel(overwrites: ChannelPermissionOverwrite[]) { - if (!overwrites) return this + if (!overwrites) return this; if (!this.cache) throw new Error("permission chache not available"); overwrites = overwrites.filter((x) => { if (x.type === 0 && this.cache.roles?.some((r) => r.id === x.id)) return true; @@ -175,6 +184,8 @@ export class Permissions extends BitField { } } +const ALL_PERMISSIONS = Object.values(Permissions.FLAGS).reduce((total, val) => total | val, BigInt(0)); + export type PermissionCache = { channel?: Channel | undefined; member?: Member | undefined; diff --git a/util/src/util/cdn.ts b/util/src/util/cdn.ts
index 754d6244..2de23f5d 100644 --- a/util/src/util/cdn.ts +++ b/util/src/util/cdn.ts
@@ -11,7 +11,7 @@ export async function uploadFile(path: string, file: Express.Multer.File) { filename: file.originalname, }); - const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, { + const response = await fetch(`${Config.get().cdn.endpointPrivate || "http://localhost:3003"}${path}`, { headers: { signature: Config.get().security.requestSignature, ...form.getHeaders(), @@ -41,7 +41,7 @@ export async function handleFile(path: string, body?: string): Promise<string | } export async function deleteFile(path: string) { - const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, { + const response = await fetch(`${Config.get().cdn.endpointPrivate || "http://localhost:3003"}${path}`, { headers: { signature: Config.get().security.requestSignature, },