fix(http): fastify dependencies (closes #461, #491) (#520)

* 🚨 **[WIP]** fix: fastify dependencies

* update & fix http stuff
This commit is contained in:
Isaac
2024-01-21 02:19:26 +00:00
committed by GitHub
parent 3e7127a3d9
commit 5f77b28012
17 changed files with 143 additions and 167 deletions

View File

@@ -9,16 +9,34 @@ const { PermissionsBitField } = require('discord.js');
process.env.ORIGIN = process.env.HTTP_INTERNAL || process.env.HTTP_EXTERNAL;
module.exports = async client => {
// cookies plugin, must be registered before oauth2 since oauth2@7.2.0
fastify.register(require('@fastify/cookie'));
// jwt plugin
fastify.register(require('@fastify/jwt'), {
cookie: {
cookieName: 'token',
signed: false,
},
secret: process.env.ENCRYPTION_KEY,
});
// oauth2 plugin
fastify.states = new Map();
fastify.register(oauth, {
callbackUri: `${process.env.HTTP_EXTERNAL}/auth/callback`,
checkStateFunction: (state, callback) => {
if (fastify.states.has(state)) {
callback();
return;
// checkStateFunction: (req, callback) => {
// if (req.query.state === req.cookies['oauth2-redirect-state']) {
// callback();
// return;
// }
// callback(new Error('Invalid state'));
// },
checkStateFunction: async req => {
if (req.query.state !== req.cookies['oauth2-redirect-state']) {
throw new Error('Invalid state');
}
callback(new Error('Invalid state'));
return true;
},
credentials: {
auth: oauth.DISCORD_CONFIGURATION,
@@ -37,17 +55,6 @@ module.exports = async client => {
startRedirectPath: '/auth/login',
});
// cookies plugin
fastify.register(require('@fastify/cookie'));
// jwt plugin
fastify.register(require('@fastify/jwt'), {
cookie: {
cookieName: 'token',
signed: false,
},
secret: process.env.ENCRYPTION_KEY,
});
// auth
fastify.decorate('authenticate', async (req, res) => {
@@ -122,13 +129,13 @@ module.exports = async client => {
: responseTime >= 10
? '&e'
: '&a') + responseTime + 'ms';
const level = req.routerPath === '/status'
const level = req.routeOptions.url === '/status'
? 'debug'
: req.routerPath === '/*'
: req.routeOptions.url === '/*'
? 'verbose'
: 'info';
client.log[level].http(short(`${req.id} ${req.ip} ${req.method} ${req.routerPath ?? '*'} &m-+>&r ${status}&b in ${responseTime}`));
if (!req.routerPath) client.log.verbose.http(`${req.id} ${req.method} ${req.url}`);
client.log[level].http(short(`${req.id} ${req.ip} ${req.method} ${req.routeOptions.url ?? '*'} &m-+>&r ${status}&b in ${responseTime}`));
if (!req.routeOptions.url) client.log.verbose.http(`${req.id} ${req.method} ${req.url}`);
done();
});

View File

@@ -5,7 +5,7 @@ const { ApplicationCommandPermissionType } = require('discord.js');
module.exports.delete = fastify => ({
handler: async (req, res) => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const guild = client.guilds.cache.get(req.params.guild);
const categoryId = Number(req.params.category);
const original = categoryId && await client.prisma.category.findUnique({ where: { id: categoryId } });
@@ -33,7 +33,7 @@ module.exports.delete = fastify => ({
module.exports.get = fastify => ({
handler: async (req, res) => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const guildId = req.params.guild;
const categoryId = Number(req.params.category);
const category = await client.prisma.category.findUnique({
@@ -68,7 +68,7 @@ module.exports.get = fastify => ({
module.exports.patch = fastify => ({
handler: async (req, res) => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const guildId = req.params.guild;
const categoryId = Number(req.params.category);
/** @type {import('discord.js').Guild} */

View File

@@ -3,7 +3,7 @@ const { logAdminEvent } = require('../../../../../../../../lib/logging');
module.exports.delete = fastify => ({
handler: async (req, res) => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const guildId = req.params.guild;
const categoryId = Number(req.params.category);
const questionId = req.params.question;

View File

@@ -12,9 +12,9 @@ const {
} = require('../../../../../../lib/stats');
module.exports.get = fastify => ({
handler: async (req, res) => {
handler: async req => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
let { categories } = await client.prisma.guild.findUnique({
select: {
@@ -54,9 +54,9 @@ module.exports.get = fastify => ({
});
module.exports.post = fastify => ({
handler: async (req, res) => {
handler: async req => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const user = await client.users.fetch(req.user.id);
const guild = client.guilds.cache.get(req.params.guild);

View File

@@ -1,7 +1,7 @@
module.exports.get = fastify => ({
handler: async (req, res) => {
handler: async req => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const id = req.params.guild;
const guild = client.guilds.cache.get(id) ?? {};
const { query } = req.query;

View File

@@ -6,9 +6,9 @@ const {
const ms = require('ms');
module.exports.get = fastify => ({
handler: async (req, res) => {
handler: async req => {
/** @type {import("client")} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const id = req.params.guild;
const cacheKey = `cache/stats/guild:${id}`;
let cached = await client.keyv.get(cacheKey);

View File

@@ -14,9 +14,9 @@ const emoji = require('node-emoji');
const { logAdminEvent } = require('../../../../../lib/logging');
module.exports.post = fastify => ({
handler: async (req, res) => {
handler: async req => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const guild = client.guilds.cache.get(req.params.guild);
const data = req.body;

View File

@@ -1,9 +1,9 @@
const { PermissionsBitField } = require('discord.js');
module.exports.get = fastify => ({
handler: async (req, res) => {
handler: async req => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const id = req.params.guild;
const guild = client.guilds.cache.get(id);
const settings = await client.prisma.guild.findUnique({ where: { id } }) ??

View File

@@ -2,9 +2,9 @@ const { logAdminEvent } = require('../../../../../lib/logging.js');
const { Colors } = require('discord.js');
module.exports.delete = fastify => ({
handler: async (req, res) => {
handler: async req => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const id = req.params.guild;
await client.prisma.guild.delete({ where: { id } });
const settings = await client.prisma.guild.create({ data: { id } });
@@ -24,9 +24,9 @@ module.exports.delete = fastify => ({
});
module.exports.get = fastify => ({
handler: async (req, res) => {
handler: async req => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const id = req.params.guild;
const settings = await client.prisma.guild.findUnique({ where: { id } }) ??
await client.prisma.guild.create({ data: { id } });
@@ -37,7 +37,7 @@ module.exports.get = fastify => ({
});
module.exports.patch = fastify => ({
handler: async (req, res) => {
handler: async req => {
const data = req.body;
if (data.hasOwnProperty('id')) delete data.id;
if (data.hasOwnProperty('createdAt')) delete data.createdAt;
@@ -49,7 +49,7 @@ module.exports.patch = fastify => ({
}
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const id = req.params.guild;
const original = await client.prisma.guild.findUnique({ where: { id } });
const settings = await client.prisma.guild.update({

View File

@@ -4,7 +4,7 @@ const { logAdminEvent } = require('../../../../../../lib/logging');
module.exports.delete = fastify => ({
handler: async (req, res) => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const guildId = req.params.guild;
const tagId = Number(req.params.tag);
const original = tagId && await client.prisma.tag.findUnique({ where: { id: tagId } });
@@ -41,7 +41,7 @@ module.exports.delete = fastify => ({
module.exports.get = fastify => ({
handler: async (req, res) => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const guildId = req.params.guild;
const tagId = Number(req.params.tag);
const tag = await client.prisma.tag.findUnique({ where: { id: tagId } });
@@ -56,7 +56,7 @@ module.exports.get = fastify => ({
module.exports.patch = fastify => ({
handler: async (req, res) => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const guildId = req.params.guild;
const tagId = Number(req.params.tag);
const guild = client.guilds.cache.get(req.params.guild);

View File

@@ -2,9 +2,9 @@ const ms = require('ms');
const { logAdminEvent } = require('../../../../../../lib/logging');
module.exports.get = fastify => ({
handler: async (req, res) => {
handler: async req => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const { tags } = await client.prisma.guild.findUnique({
select: { tags: true },
@@ -18,9 +18,9 @@ module.exports.get = fastify => ({
module.exports.post = fastify => ({
handler: async (req, res) => {
handler: async req => {
/** @type {import('client')} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const guild = client.guilds.cache.get(req.params.guild);
const data = req.body;
const tag = await client.prisma.tag.create({

View File

@@ -2,7 +2,7 @@ const { PermissionsBitField } = require('discord.js');
module.exports.get = fastify => ({
handler: async (req, res) => {
const { client } = res.context.config;
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

View File

@@ -4,9 +4,9 @@ const {
const ms = require('ms');
module.exports.get = () => ({
handler: async (req, res) => {
handler: async req => {
/** @type {import("client")} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
const cacheKey = 'cache/stats/client';
let cached = await client.keyv.get(cacheKey);

View File

@@ -1,7 +1,7 @@
module.exports.get = () => ({
handler: async (req, res) => {
handler: async req => {
/** @type {import("client")} */
const client = res.context.config.client;
const client = req.routeOptions.config.client;
return client.i18n.locales;
},
});
});

View File

@@ -2,18 +2,25 @@ const { domain } = require('../../lib/http');
module.exports.get = () => ({
handler: async function (req, res) { // MUST NOT use arrow function syntax
const {
access_token: accessToken,
expires_in: expiresIn,
} = await this.discord.getAccessTokenFromAuthorizationCodeFlow(req);
const data = await (await fetch('https://discord.com/api/oauth2/token', {
body: new URLSearchParams({
client_id: req.routeOptions.config.client.user.id,
client_secret: process.env.DISCORD_SECRET,
code: req.query.code,
grant_type: 'authorization_code',
redirect_uri: `${process.env.HTTP_EXTERNAL}/auth/callback`,
}).toString(),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
})).json();
const redirect = this.states.get(req.query.state) || '/';
this.states.delete(req.query.state);
const user = await (await fetch('https://discordapp.com/api/users/@me', { headers: { 'Authorization': `Bearer ${accessToken}` } })).json();
const user = await (await fetch('https://discordapp.com/api/users/@me', { headers: { 'Authorization': `Bearer ${data.access_token}` } })).json();
const token = this.jwt.sign({
accessToken,
accessToken: data.access_token,
avatar: user.avatar,
discriminator: user.discriminator,
expiresAt: Date.now() + (expiresIn * 1000),
expiresAt: Date.now() + (data.expires_in * 1000),
id: user.id,
locale: user.locale,
username: user.username,
@@ -21,7 +28,7 @@ module.exports.get = () => ({
res.setCookie('token', token, {
domain,
httpOnly: true,
maxAge: expiresIn,
maxAge: data.expires_in,
path: '/',
sameSite: 'Lax',
secure: false,