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,
},
|