diff --git a/src/http.js b/src/http.js index b3686944..688795f1 100644 --- a/src/http.js +++ b/src/http.js @@ -4,7 +4,7 @@ const { randomBytes } = require('crypto'); const { short } = require('leeks.js'); const { join } = require('path'); const { files } = require('node-dir'); -const { PermissionsBitField } = require('discord.js'); +const { getPrivilegeLevel } = require('./lib/users'); process.env.ORIGIN = process.env.HTTP_INTERNAL || process.env.HTTP_EXTERNAL; @@ -65,6 +65,33 @@ module.exports = async client => { } }); + fastify.decorate('isMember', async (req, res) => { + try { + const userId = req.user.id; + const guildId = req.params.guild; + const guild = client.guilds.cache.get(guildId); + if (!guild) { + return res.code(404).send({ + error: 'Not Found', + message: 'The requested resource could not be found.', + statusCode: 404, + + }); + } + const guildMember = await guild.members.fetch(userId); + if (!guildMember) { + return res.code(403).send({ + error: 'Forbidden', + message: 'You are not permitted for this action.', + statusCode: 403, + + }); + } + } catch (err) { + res.send(err); + } + }); + fastify.decorate('isAdmin', async (req, res) => { try { const userId = req.user.id; @@ -79,7 +106,7 @@ module.exports = async client => { }); } const guildMember = await guild.members.fetch(userId); - const isAdmin = guildMember?.permissions.has(PermissionsBitField.Flags.ManageGuild) || client.supers.includes(userId); + const isAdmin = await getPrivilegeLevel(guildMember) >= 2; if (!isAdmin) { return res.code(403).send({ error: 'Forbidden', diff --git a/src/lib/users.js b/src/lib/users.js index c263662f..1a2ec2b6 100644 --- a/src/lib/users.js +++ b/src/lib/users.js @@ -46,3 +46,23 @@ module.exports.isStaff = async (guild, userId) => { const staffRoles = await client.keyv.get(`cache/guild-staff:${guild.id}`) || await updateStaffRoles(guild); return staffRoles.some(r => guildMember.roles.cache.has(r)); }; + +/** + * + * @param {import("discord.js")} member + * @returns {Promise} + * - `4` = OPERATOR (SUPER) + * - `3` = GUILD_OWNER + * - `2` = GUILD_ADMIN + * - `1` = GUILD_STAFF + * - `0` = GUILD_MEMBER + * - `-1` = NONE (NOT A MEMBER) + */ +module.exports.getPrivilegeLevel = async member => { + if (!member) return -1; + else if (member.guild.client.supers.includes(member.id)) return 4; + else if (member.guild.ownerId === member.id) return 3; + else if (member.permissions.has(PermissionsBitField.Flags.ManageGuild)) return 2; + else if (await this.isStaff(member.guild, member.id)) return 1; + else return 0; +}; diff --git a/src/routes/api/guilds/[guild]/index.js b/src/routes/api/guilds/[guild]/index.js index caff864c..eb854d5f 100644 --- a/src/routes/api/guilds/[guild]/index.js +++ b/src/routes/api/guilds/[guild]/index.js @@ -1,3 +1,4 @@ +const { getPrivilegeLevel } = require('../../../../lib/users'); const { iconURL } = require('../../../../lib/misc'); module.exports.get = fastify => ({ @@ -9,8 +10,9 @@ module.exports.get = fastify => ({ id: guild.id, logo: iconURL(guild), name: guild.name, + privilegeLevel: await getPrivilegeLevel(await guild.members.fetch(req.user.id)), }); }, - onRequest: [fastify.authenticate], + onRequest: [fastify.authenticate, fastify.isMember], }); diff --git a/src/routes/api/guilds/index.js b/src/routes/api/guilds/index.js index e608167e..a8931bb2 100644 --- a/src/routes/api/guilds/index.js +++ b/src/routes/api/guilds/index.js @@ -1,3 +1,4 @@ +const { getPrivilegeLevel } = require('../../../lib/users'); const { iconURL } = require('../../../lib/misc'); module.exports.get = fastify => ({ @@ -5,13 +6,19 @@ module.exports.get = fastify => ({ const { client } = req.routeOptions.config; const guilds = await (await fetch('https://discordapp.com/api/users/@me/guilds', { headers: { 'Authorization': `Bearer ${req.user.accessToken}` } })).json(); res.send( - guilds - .filter(guild => client.guilds.cache.has(guild.id)) - .map(guild => ({ - id: guild.id, - logo: iconURL(client.guilds.cache.get(guild.id)), - name: guild.name, - })), + await Promise.all( + guilds + .filter(partialGuild => client.guilds.cache.has(partialGuild.id)) + .map(async partialGuild => { + const guild = client.guilds.cache.get(partialGuild.id); + return { + id: guild.id, + logo: iconURL(guild), + name: guild.name, + privilegeLevel: await getPrivilegeLevel(await guild.members.fetch(req.user.id)), + }; + }), + ), ); }, onRequest: [fastify.authenticate],