From 6bf06e2391cb3930dcd1b380bacd20bcb3269c21 Mon Sep 17 00:00:00 2001 From: Patric Plattner <patric@patricplattner.de> Date: Mon, 30 Aug 2021 02:18:03 +0200 Subject: [PATCH] Adding permission system. --- .dockerignore | 3 +- .gitignore | 3 +- .idea/finf-discord-js.iml | 1 + commands/AssignPermission.js | 14 +++++++ commands/ListPermissions.js | 5 +++ commands/RevokePermission.js | 14 +++++++ components/permConfig.js | 77 ++++++++++++++++++++++++++++++++++++ components/roles.js | 22 +++++++++++ docker-compose.yml | 2 + index.js | 2 +- models/ServerConfig.js | 16 ++++++++ package.json | 2 +- {config => util}/db.js | 0 util/perm.js | 17 ++++++++ 14 files changed, 174 insertions(+), 4 deletions(-) create mode 100644 commands/AssignPermission.js create mode 100644 commands/ListPermissions.js create mode 100644 commands/RevokePermission.js create mode 100644 components/permConfig.js create mode 100644 models/ServerConfig.js rename {config => util}/db.js (100%) create mode 100644 util/perm.js diff --git a/.dockerignore b/.dockerignore index 2afd11a..45ec588 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,4 +3,5 @@ node_modules npm-debug.log .env .env.example -.DS_store \ No newline at end of file +.DS_store +mongo \ No newline at end of file diff --git a/.gitignore b/.gitignore index c223885..8a59002 100644 --- a/.gitignore +++ b/.gitignore @@ -235,4 +235,5 @@ dist .pnp.* .env -.DS_store \ No newline at end of file +.DS_store +mongo \ No newline at end of file diff --git a/.idea/finf-discord-js.iml b/.idea/finf-discord-js.iml index 0c8867d..1616246 100644 --- a/.idea/finf-discord-js.iml +++ b/.idea/finf-discord-js.iml @@ -5,6 +5,7 @@ <excludeFolder url="file://$MODULE_DIR$/temp" /> <excludeFolder url="file://$MODULE_DIR$/.tmp" /> <excludeFolder url="file://$MODULE_DIR$/tmp" /> + <excludeFolder url="file://$MODULE_DIR$/mongo" /> </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> diff --git a/commands/AssignPermission.js b/commands/AssignPermission.js new file mode 100644 index 0000000..b2009c4 --- /dev/null +++ b/commands/AssignPermission.js @@ -0,0 +1,14 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); + +module.exports = new SlashCommandBuilder() + .setName('assign_permission') + .setDescription('Assign a permission to a role') + .addStringOption(option => + option.setName('permission') + .setDescription('Permission to assign.') + .setRequired(true) + .addChoice("Role Menus", 'role_menu')) + .addRoleOption(option => + option.setName('role') + .setDescription('Role to assign permission to.') + .setRequired(true)) \ No newline at end of file diff --git a/commands/ListPermissions.js b/commands/ListPermissions.js new file mode 100644 index 0000000..b6d35be --- /dev/null +++ b/commands/ListPermissions.js @@ -0,0 +1,5 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); + +module.exports = new SlashCommandBuilder() + .setName('list_permissions') + .setDescription('List all Permissions for this Server.'); \ No newline at end of file diff --git a/commands/RevokePermission.js b/commands/RevokePermission.js new file mode 100644 index 0000000..45b18c4 --- /dev/null +++ b/commands/RevokePermission.js @@ -0,0 +1,14 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); + +module.exports = new SlashCommandBuilder() + .setName('revoke_permission') + .setDescription('Revoke a permission from a role') + .addStringOption(option => + option.setName('permission') + .setDescription('Permission to revoke.') + .setRequired(true) + .addChoice("Role Menus", 'role_menu')) + .addRoleOption(option => + option.setName('role') + .setDescription('Role to revoke permission from.') + .setRequired(true)) \ No newline at end of file diff --git a/components/permConfig.js b/components/permConfig.js new file mode 100644 index 0000000..4235839 --- /dev/null +++ b/components/permConfig.js @@ -0,0 +1,77 @@ +const ServerConfig = require('../models/ServerConfig'); +const {Permissions} = require('discord.js'); + +async function assignPermission(interaction) { + if (interaction.member.permissions.has(Permissions.FLAGS.ADMINISTRATOR)) { + const role = interaction.options.getRole('role'); + const perm = interaction.options.getString('permission'); + let config = await ServerConfig.findOne({guildID: interaction.guild.id.toString()}); + if (config == null) { + config = new ServerConfig(); + config.guildID = interaction.guild.id.toString(); + config.permissions.roleMenu = []; + } + if (perm === 'role_menu') { + if (!config.permissions.roleMenu.includes(role.id.toString())) { + config.permissions.roleMenu.push(role.id.toString()); + } + } + await config.save(); + await interaction.reply({content: `Role ${role.name} has been added to ${perm} permission.`, ephemeral: true}); + } else { + await interaction.reply({content: 'Only administrators can access this command.', ephemeral: true}); + } +} + +async function revokePermission(interaction) { + if (interaction.member.permissions.has(Permissions.FLAGS.ADMINISTRATOR)) { + const role = interaction.options.getRole('role'); + const perm = interaction.options.getString('permission'); + let config = await ServerConfig.findOne({guildID: interaction.guild.id.toString()}); + if (config == null) { + config = new ServerConfig(); + config.guildID = interaction.guild.id.toString(); + config.permissions.roleMenu = []; + } + if (perm === 'role_menu') { + if (config.permissions.roleMenu.includes(role.id.toString())) { + config.permissions.roleMenu.splice(config.permissions.roleMenu.indexOf(role.id.toString()), 1); + } + } + await config.save(); + await interaction.reply({ + content: `Role ${role.name} has been removed from ${perm} permission.`, + ephemeral: true + }); + } else { + await interaction.reply({content: 'Only administrators can access this command.', ephemeral: true}); + } +} + +async function listPermissions(interaction) { + if (interaction.member.permissions.has(Permissions.FLAGS.ADMINISTRATOR)) { + let config = await ServerConfig.findOne({guildID: interaction.guild.id.toString()}); + if (config == null) { + config = new ServerConfig(); + config.guildID = interaction.guild.id.toString(); + config.permissions.roleMenu = []; + } + const roles = await Promise.all(config.permissions.roleMenu.map(async (roleID) => (await interaction.guild.roles.fetch(roleID)).name)); + + await interaction.reply({content: `List of Permissions:\n\nRole Menu: ${roles.join(',')}`, ephemeral: true}); + } +} + +const slashCommandHandler = async (interaction) => { + if (interaction.commandName === 'assign_permission') { + await assignPermission(interaction); + } else if (interaction.commandName === 'revoke_permission') { + await revokePermission(interaction); + } else if (interaction.commandName === 'list_permissions') { + await listPermissions(interaction); + } +} + +module.exports = { + slashCommandHandler +} \ No newline at end of file diff --git a/components/roles.js b/components/roles.js index 6721134..0968774 100644 --- a/components/roles.js +++ b/components/roles.js @@ -1,8 +1,14 @@ const RoleMenu = require('../models/RoleMenu'); const {MessageActionRow, MessageSelectMenu} = require("discord.js"); +const checkPerm = require('../util/perm'); // slashcommand handler async function addRoleMenu(interaction) { + console.log('test'); + if (!(await checkPerm(interaction.member, 'role_menu'))) { + await interaction.reply({content: 'You are not authorized to do this.', ephemeral: true}) + return; + } const channel = interaction.options.getChannel('channel'); const messageContent = interaction.options.getString('message'); const type = interaction.options.getString('type'); @@ -32,6 +38,10 @@ async function addRoleMenu(interaction) { } async function deleteRoleMenu(interaction) { + if (!(await checkPerm(interaction.member, 'role_menu'))) { + await interaction.reply({content: 'You are not authorized to do this.', ephemeral: true}) + return; + } const channel = interaction.options.getChannel('channel'); const messageID = interaction.options.getString('message_id'); let menu = await RoleMenu.findOne({guildID: channel.guild.id, channelID: channel.id, messageID}); @@ -58,6 +68,10 @@ async function deleteRoleMenu(interaction) { } async function addRoleToMenu(interaction) { + if (!(await checkPerm(interaction.member, 'role_menu'))) { + await interaction.reply({content: 'You are not authorized to do this.', ephemeral: true}) + return; + } const channel = interaction.options.getChannel('channel'); const messageID = interaction.options.getString('message_id'); const role = interaction.options.getRole('role') @@ -123,6 +137,10 @@ async function addRoleToMenu(interaction) { } async function deleteRoleFromMenu(interaction) { + if (!(await checkPerm(interaction.member, 'role_menu'))) { + await interaction.reply({content: 'You are not authorized to do this.', ephemeral: true}) + return; + } const channel = interaction.options.getChannel('channel'); const messageID = interaction.options.getString('message_id'); const role = interaction.options.getRole('role'); @@ -183,6 +201,10 @@ async function deleteRoleFromMenu(interaction) { } async function editRoleMenu(interaction) { + if (!(await checkPerm(interaction.member, 'role_menu'))) { + await interaction.reply({content: 'You are not authorized to do this.', ephemeral: true}) + return; + } const channel = interaction.options.getChannel('channel'); const messageID = interaction.options.getString('message_id'); const messageContent = interaction.options.getString('message'); diff --git a/docker-compose.yml b/docker-compose.yml index 43cb997..ae04fab 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,8 @@ services: mongo: image: mongo + volumes: + - "./mongo:/data/db" ports: - "${MONGO_PORT}:${MONGO_PORT}" restart: always diff --git a/index.js b/index.js index 49b1841..65968dd 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -const connectDB = require('./config/db') +const connectDB = require('./util/db') const {Client, Intents, MessageActionRow, MessageButton, MessageSelectMenu, MessageEmbed} = require('discord.js'); const fs = require('fs'); const botConfig = { diff --git a/models/ServerConfig.js b/models/ServerConfig.js new file mode 100644 index 0000000..1428e8a --- /dev/null +++ b/models/ServerConfig.js @@ -0,0 +1,16 @@ +const {Schema, model} = require('mongoose'); + +const ServerConfigSchema = new Schema({ + guildID: { + type: String, + unique: true, + required: true + }, + permissions: { + roleMenu: [{ + type: String + }]} +}); + + +module.exports = model('serverconfig', ServerConfigSchema); \ No newline at end of file diff --git a/package.json b/package.json index 420b0a1..a5d606b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "finf-discord", - "version": "0.1.0", + "version": "0.1.1", "description": "", "main": "index.ts", "scripts": { diff --git a/config/db.js b/util/db.js similarity index 100% rename from config/db.js rename to util/db.js diff --git a/util/perm.js b/util/perm.js new file mode 100644 index 0000000..7cf3f0f --- /dev/null +++ b/util/perm.js @@ -0,0 +1,17 @@ +const ServerConfig = require('../models/ServerConfig'); +const {Permissions} = require('discord.js'); + +module.exports = async (member, permission) => { + const guildID = member.guild.id; + const config = await ServerConfig.findOne({guildID}); + if (config == null) { + return false; + } + if (permission === 'role_menu') { + console.log(member.roles.cache); + console.log(config.permissions.roleMenu); + return member.roles.cache.some((role) => config.permissions.roleMenu.some((prole) => prole == role.id.toString())) + || member.permissions.has(Permissions.FLAGS.ADMINISTRATOR); + } + return false; +} \ No newline at end of file -- GitLab