Add access control rework
This commit is contained in:
196
server/src/migrations/1000000000005-ServerRoleAccessControl.ts
Normal file
196
server/src/migrations/1000000000005-ServerRoleAccessControl.ts
Normal file
@@ -0,0 +1,196 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
type LegacyServerRow = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
ownerId: string;
|
||||
ownerPublicKey: string;
|
||||
passwordHash: string | null;
|
||||
isPrivate: number;
|
||||
maxUsers: number;
|
||||
currentUsers: number;
|
||||
createdAt: number;
|
||||
lastSeen: number;
|
||||
};
|
||||
|
||||
const SYSTEM_ROLE_IDS = {
|
||||
everyone: 'system-everyone',
|
||||
moderator: 'system-moderator',
|
||||
admin: 'system-admin'
|
||||
} as const;
|
||||
|
||||
function buildDefaultServerRoles() {
|
||||
return [
|
||||
{
|
||||
roleId: SYSTEM_ROLE_IDS.everyone,
|
||||
name: '@everyone',
|
||||
color: '#6b7280',
|
||||
position: 0,
|
||||
isSystem: 1,
|
||||
manageServer: 'inherit',
|
||||
manageRoles: 'inherit',
|
||||
manageChannels: 'inherit',
|
||||
manageIcon: 'inherit',
|
||||
kickMembers: 'inherit',
|
||||
banMembers: 'inherit',
|
||||
manageBans: 'inherit',
|
||||
deleteMessages: 'inherit',
|
||||
joinVoice: 'allow',
|
||||
shareScreen: 'allow',
|
||||
uploadFiles: 'allow'
|
||||
},
|
||||
{
|
||||
roleId: SYSTEM_ROLE_IDS.moderator,
|
||||
name: 'Moderator',
|
||||
color: '#10b981',
|
||||
position: 200,
|
||||
isSystem: 1,
|
||||
manageServer: 'inherit',
|
||||
manageRoles: 'inherit',
|
||||
manageChannels: 'inherit',
|
||||
manageIcon: 'inherit',
|
||||
kickMembers: 'allow',
|
||||
banMembers: 'inherit',
|
||||
manageBans: 'inherit',
|
||||
deleteMessages: 'allow',
|
||||
joinVoice: 'inherit',
|
||||
shareScreen: 'inherit',
|
||||
uploadFiles: 'inherit'
|
||||
},
|
||||
{
|
||||
roleId: SYSTEM_ROLE_IDS.admin,
|
||||
name: 'Admin',
|
||||
color: '#60a5fa',
|
||||
position: 300,
|
||||
isSystem: 1,
|
||||
manageServer: 'inherit',
|
||||
manageRoles: 'inherit',
|
||||
manageChannels: 'allow',
|
||||
manageIcon: 'allow',
|
||||
kickMembers: 'allow',
|
||||
banMembers: 'allow',
|
||||
manageBans: 'allow',
|
||||
deleteMessages: 'allow',
|
||||
joinVoice: 'inherit',
|
||||
shareScreen: 'inherit',
|
||||
uploadFiles: 'inherit'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
export class ServerRoleAccessControl1000000000005 implements MigrationInterface {
|
||||
name = 'ServerRoleAccessControl1000000000005';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS "server_roles" (
|
||||
"serverId" TEXT NOT NULL,
|
||||
"roleId" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"color" TEXT,
|
||||
"position" INTEGER NOT NULL,
|
||||
"isSystem" INTEGER NOT NULL DEFAULT 0,
|
||||
"manageServer" TEXT NOT NULL DEFAULT 'inherit',
|
||||
"manageRoles" TEXT NOT NULL DEFAULT 'inherit',
|
||||
"manageChannels" TEXT NOT NULL DEFAULT 'inherit',
|
||||
"manageIcon" TEXT NOT NULL DEFAULT 'inherit',
|
||||
"kickMembers" TEXT NOT NULL DEFAULT 'inherit',
|
||||
"banMembers" TEXT NOT NULL DEFAULT 'inherit',
|
||||
"manageBans" TEXT NOT NULL DEFAULT 'inherit',
|
||||
"deleteMessages" TEXT NOT NULL DEFAULT 'inherit',
|
||||
"joinVoice" TEXT NOT NULL DEFAULT 'inherit',
|
||||
"shareScreen" TEXT NOT NULL DEFAULT 'inherit',
|
||||
"uploadFiles" TEXT NOT NULL DEFAULT 'inherit',
|
||||
PRIMARY KEY ("serverId", "roleId")
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`CREATE INDEX IF NOT EXISTS "idx_server_roles_serverId" ON "server_roles" ("serverId")`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS "server_user_roles" (
|
||||
"serverId" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"roleId" TEXT NOT NULL,
|
||||
"oderId" TEXT,
|
||||
PRIMARY KEY ("serverId", "userId", "roleId")
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`CREATE INDEX IF NOT EXISTS "idx_server_user_roles_serverId" ON "server_user_roles" ("serverId")`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS "server_channel_permissions" (
|
||||
"serverId" TEXT NOT NULL,
|
||||
"channelId" TEXT NOT NULL,
|
||||
"targetType" TEXT NOT NULL,
|
||||
"targetId" TEXT NOT NULL,
|
||||
"permission" TEXT NOT NULL,
|
||||
"value" TEXT NOT NULL,
|
||||
PRIMARY KEY ("serverId", "channelId", "targetType", "targetId", "permission")
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`CREATE INDEX IF NOT EXISTS "idx_server_channel_permissions_serverId" ON "server_channel_permissions" ("serverId")`);
|
||||
|
||||
const servers = await queryRunner.query(`
|
||||
SELECT "id", "name", "description", "ownerId", "ownerPublicKey", "passwordHash", "isPrivate", "maxUsers", "currentUsers", "createdAt", "lastSeen"
|
||||
FROM "servers"
|
||||
`) as LegacyServerRow[];
|
||||
|
||||
for (const server of servers) {
|
||||
for (const role of buildDefaultServerRoles()) {
|
||||
await queryRunner.query(
|
||||
`INSERT OR REPLACE INTO "server_roles" ("serverId", "roleId", "name", "color", "position", "isSystem", "manageServer", "manageRoles", "manageChannels", "manageIcon", "kickMembers", "banMembers", "manageBans", "deleteMessages", "joinVoice", "shareScreen", "uploadFiles") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[
|
||||
server.id,
|
||||
role.roleId,
|
||||
role.name,
|
||||
role.color,
|
||||
role.position,
|
||||
role.isSystem,
|
||||
role.manageServer,
|
||||
role.manageRoles,
|
||||
role.manageChannels,
|
||||
role.manageIcon,
|
||||
role.kickMembers,
|
||||
role.banMembers,
|
||||
role.manageBans,
|
||||
role.deleteMessages,
|
||||
role.joinVoice,
|
||||
role.shareScreen,
|
||||
role.uploadFiles
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE "servers_next" (
|
||||
"id" TEXT PRIMARY KEY NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"ownerId" TEXT NOT NULL,
|
||||
"ownerPublicKey" TEXT NOT NULL,
|
||||
"passwordHash" TEXT,
|
||||
"isPrivate" INTEGER NOT NULL DEFAULT 0,
|
||||
"maxUsers" INTEGER NOT NULL DEFAULT 0,
|
||||
"currentUsers" INTEGER NOT NULL DEFAULT 0,
|
||||
"slowModeInterval" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdAt" INTEGER NOT NULL,
|
||||
"lastSeen" INTEGER NOT NULL
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
INSERT INTO "servers_next" ("id", "name", "description", "ownerId", "ownerPublicKey", "passwordHash", "isPrivate", "maxUsers", "currentUsers", "slowModeInterval", "createdAt", "lastSeen")
|
||||
SELECT "id", "name", "description", "ownerId", "ownerPublicKey", "passwordHash", "isPrivate", "maxUsers", "currentUsers", 0, "createdAt", "lastSeen"
|
||||
FROM "servers"
|
||||
`);
|
||||
await queryRunner.query(`DROP TABLE "servers"`);
|
||||
await queryRunner.query(`ALTER TABLE "servers_next" RENAME TO "servers"`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS "server_channel_permissions"`);
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS "server_user_roles"`);
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS "server_roles"`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user