diff --git a/src/api/routes/policies/stats.ts b/src/api/routes/policies/stats.ts
new file mode 100644
index 00000000..d3aad2ec
--- /dev/null
+++ b/src/api/routes/policies/stats.ts
@@ -0,0 +1,22 @@
+import { route } from "@fosscord/api";
+import { Config, getRights, Guild, Member, Message, User } from "@fosscord/util";
+import { Request, Response, Router } from "express";
+const router = Router();
+
+router.get("/", route({}), async (req: Request, res: Response) => {
+ let users, guilds, msgs, memberships;
+ // needs to be let otherwise we can't for
+
+ let config = Config.get();
+ if (!config.security.statsWorldReadable) {
+ let rights = await getRights(req.user_id);
+ rights.hasThrow("VIEW_SERVER_STATS");
+ }
+ users = await User.count();
+ guilds = await Guild.count();
+ msgs = await Message.count();
+ memberships = await Member.count();
+ res.json({ user_count: users, guild_count: guilds, msg_count: msgs, membership_rels: memberships });
+});
+
+export default router;
diff --git a/src/util/config/types/SecurityConfiguration.ts b/src/util/config/types/SecurityConfiguration.ts
index a2cebbd3..5a3d5aa6 100644
--- a/src/util/config/types/SecurityConfiguration.ts
+++ b/src/util/config/types/SecurityConfiguration.ts
@@ -16,4 +16,5 @@ export class SecurityConfiguration {
ipdataApiKey: string | null = "eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9";
mfaBackupCodeCount: number = 10;
mfaBackupCodeBytes: number = 4;
+ statsWorldReadable: boolean = true;
}
diff --git a/src/util/migrations/mariadb/1661273147273-test.ts b/src/util/migrations/mariadb/1661273147273-test.ts
index 4e077a11..0090e2aa 100644
--- a/src/util/migrations/mariadb/1661273147273-test.ts
+++ b/src/util/migrations/mariadb/1661273147273-test.ts
@@ -1,23 +1,23 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class test1661273147273 implements MigrationInterface {
- name = 'test1661273147273'
+ name = "test1661273147273";
- public async up(queryRunner: QueryRunner): Promise<void> {
- await queryRunner.query(`
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
ALTER TABLE \`invites\` DROP FOREIGN KEY \`FK_15c35422032e0b22b4ada95f48f\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
DROP INDEX \`IDX_2ce5a55796fe4c2f77ece57a64\` ON \`applications\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
CREATE TABLE \`plugin_config\` (
\`key\` varchar(255) NOT NULL,
\`value\` text NULL,
PRIMARY KEY (\`key\`)
) ENGINE = InnoDB
`);
- await queryRunner.query(`
+ await queryRunner.query(`
CREATE TABLE \`user_settings\` (
\`id\` varchar(255) NOT NULL,
\`afk_timeout\` int NULL,
@@ -54,96 +54,95 @@ export class test1661273147273 implements MigrationInterface {
PRIMARY KEY (\`id\`)
) ENGINE = InnoDB
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`users\` DROP COLUMN \`settings\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`users\`
ADD \`settingsId\` varchar(255) NULL
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`users\`
ADD UNIQUE INDEX \`IDX_76ba283779c8441fd5ff819c8c\` (\`settingsId\`)
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`channels\`
ADD \`flags\` int NULL
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`channels\`
ADD \`default_thread_rate_limit_per_user\` int NULL
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`guilds\`
ADD \`premium_progress_bar_enabled\` tinyint NULL
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`users\` CHANGE \`bio\` \`bio\` varchar(255) NULL
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`users\` CHANGE \`mfa_enabled\` \`mfa_enabled\` tinyint NULL
`);
- await queryRunner.query(`
+ await queryRunner.query(`
CREATE UNIQUE INDEX \`REL_76ba283779c8441fd5ff819c8c\` ON \`users\` (\`settingsId\`)
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`users\`
ADD CONSTRAINT \`FK_76ba283779c8441fd5ff819c8cf\` FOREIGN KEY (\`settingsId\`) REFERENCES \`user_settings\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`invites\`
ADD CONSTRAINT \`FK_15c35422032e0b22b4ada95f48f\` FOREIGN KEY (\`inviter_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
`);
- }
+ }
- public async down(queryRunner: QueryRunner): Promise<void> {
- await queryRunner.query(`
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
ALTER TABLE \`invites\` DROP FOREIGN KEY \`FK_15c35422032e0b22b4ada95f48f\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`users\` DROP FOREIGN KEY \`FK_76ba283779c8441fd5ff819c8cf\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
DROP INDEX \`REL_76ba283779c8441fd5ff819c8c\` ON \`users\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`users\` CHANGE \`mfa_enabled\` \`mfa_enabled\` tinyint NOT NULL
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`users\` CHANGE \`bio\` \`bio\` varchar(255) NOT NULL
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`guilds\` DROP COLUMN \`premium_progress_bar_enabled\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`channels\` DROP COLUMN \`default_thread_rate_limit_per_user\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`channels\` DROP COLUMN \`flags\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`users\` DROP INDEX \`IDX_76ba283779c8441fd5ff819c8c\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`users\` DROP COLUMN \`settingsId\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`users\`
ADD \`settings\` text NOT NULL
`);
- await queryRunner.query(`
+ await queryRunner.query(`
DROP TABLE \`user_settings\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
DROP TABLE \`plugin_config\`
`);
- await queryRunner.query(`
+ await queryRunner.query(`
CREATE UNIQUE INDEX \`IDX_2ce5a55796fe4c2f77ece57a64\` ON \`applications\` (\`bot_user_id\`)
`);
- await queryRunner.query(`
+ await queryRunner.query(`
ALTER TABLE \`invites\`
ADD CONSTRAINT \`FK_15c35422032e0b22b4ada95f48f\` FOREIGN KEY (\`inviter_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
`);
- }
-
+ }
}
diff --git a/src/util/migrations/mariadb/1661273179287-test2.ts b/src/util/migrations/mariadb/1661273179287-test2.ts
index 0f77f284..973d8124 100644
--- a/src/util/migrations/mariadb/1661273179287-test2.ts
+++ b/src/util/migrations/mariadb/1661273179287-test2.ts
@@ -1,18 +1,17 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class test21661273179287 implements MigrationInterface {
- name = 'test21661273179287'
+ name = "test21661273179287";
- public async up(queryRunner: QueryRunner): Promise<void> {
- await queryRunner.query(`
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
DROP INDEX \`IDX_76ba283779c8441fd5ff819c8c\` ON \`users\`
`);
- }
+ }
- public async down(queryRunner: QueryRunner): Promise<void> {
- await queryRunner.query(`
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
CREATE UNIQUE INDEX \`IDX_76ba283779c8441fd5ff819c8c\` ON \`users\` (\`settingsId\`)
`);
- }
-
+ }
}
diff --git a/src/util/util/Database.ts b/src/util/util/Database.ts
index b9f8365e..647de26a 100644
--- a/src/util/util/Database.ts
+++ b/src/util/util/Database.ts
@@ -96,7 +96,7 @@ function getDataSourceOptions(): DataSourceOptions {
name: "default",
migrations: synchronizeInsteadOfMigrations ? [] : [path.join(__dirname, "..", "migrations", type, "*.js")],
migrationsRun: !synchronizeInsteadOfMigrations,
- applicationName: `Fosscord Server`,
+ applicationName: `Fosscord Server`
} as DataSourceOptions;
}
diff --git a/src/util/util/Rights.ts b/src/util/util/Rights.ts
index 51bb098c..236bfea7 100644
--- a/src/util/util/Rights.ts
+++ b/src/util/util/Rights.ts
@@ -63,7 +63,11 @@ export class Rights extends BitField {
RESPOND_TO_INTERACTIONS: BitFlag(41), // can respond to interactions
SEND_BACKDATED_EVENTS: BitFlag(42), // can send backdated events
USE_MASS_INVITES: BitFlag(43), // added per @xnacly's request — can accept mass invites
- ACCEPT_INVITES: BitFlag(44) // added per @xnacly's request — can accept user-specific invites and DM requests
+ ACCEPT_INVITES: BitFlag(44), // added per @xnacly's request — can accept user-specific invites and DM requests
+ SELF_EDIT_FLAGS: BitFlag(45), // can modify own flags
+ EDIT_FLAGS: BitFlag(46), // can set others' flags
+ MANAGE_GROUPS: BitFlag(47), // can manage others' groups
+ VIEW_SERVER_STATS: BitFlag(48) // added per @chrischrome's request — can view server stats)
};
any(permission: RightResolvable, checkOperator = true) {
|