From a1095f7c5c32708f229ce48913237a80dbc38c73 Mon Sep 17 00:00:00 2001 From: JandereDev Date: Tue, 25 Jan 2022 08:36:48 +0100 Subject: [PATCH] server dashboard api and whatever --- api/src/index.ts | 1 + api/src/routes/dash/server.ts | 32 ++++++++++++ api/src/routes/dash/servers.ts | 4 +- api/src/routes/login.ts | 5 +- api/src/utils.ts | 10 +++- bot/src/bot/modules/api/server_details.ts | 61 +++++++++++++++++++++++ bot/src/bot/modules/api_communication.ts | 1 + web/src/pages/ServerDashboard.tsx | 24 ++++++++- 8 files changed, 129 insertions(+), 9 deletions(-) create mode 100644 api/src/routes/dash/server.ts create mode 100644 bot/src/bot/modules/api/server_details.ts diff --git a/api/src/index.ts b/api/src/index.ts index 2f53c66..306d9fa 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -26,6 +26,7 @@ export { logger, app, db, PORT, SESSION_LIFETIME } import('./routes/root'), import('./routes/login'), import('./routes/dash/servers'), + import('./routes/dash/server'), ]); logger.done('All routes and middlewares loaded'); })(); diff --git a/api/src/routes/dash/server.ts b/api/src/routes/dash/server.ts new file mode 100644 index 0000000..8904e86 --- /dev/null +++ b/api/src/routes/dash/server.ts @@ -0,0 +1,32 @@ +import { app } from '../..'; +import { Request, Response } from 'express'; +import { badRequest, isAuthenticated, unauthorized } from '../../utils'; +import { botReq } from '../internal/ws'; + +type ServerDetails = { + id: string, + perms: 0|1|2, + name: string, + description?: string, + iconURL?: string, + bannerURL?: string, + serverConfig: any, +} + +app.get('/dash/server/:server', async (req: Request, res: Response) => { + const user = await isAuthenticated(req, res, true); + if (!user) return unauthorized(res); + + const { server } = req.params; + if (!server || typeof server != 'string') return badRequest(res); + + const response = await botReq('getUserServerDetails', { user, server }); + if (!response.success) { + return res.status(response.statusCode ?? 500).send({ error: response.error }); + } + + if (!response.server) return res.status(404).send({ error: 'Not found' }); + + const s: ServerDetails = response.server; + res.send({ server: s }); +}); diff --git a/api/src/routes/dash/servers.ts b/api/src/routes/dash/servers.ts index 7a34fde..025d0fe 100644 --- a/api/src/routes/dash/servers.ts +++ b/api/src/routes/dash/servers.ts @@ -1,13 +1,13 @@ import { app } from '../..'; import { Request, Response } from 'express'; -import { isAuthenticated } from '../../utils'; +import { isAuthenticated, unauthorized } from '../../utils'; import { botReq } from '../internal/ws'; type Server = { id: string, perms: 0|1|2, name: string, iconURL?: string, bannerURL?: string } app.get('/dash/servers', async (req: Request, res: Response) => { const user = await isAuthenticated(req, res, true); - if (!user) return; + if (!user) return unauthorized(res); const response = await botReq('getUserServers', { user }); if (!response.success) { diff --git a/api/src/routes/login.ts b/api/src/routes/login.ts index bf8471c..03bd244 100644 --- a/api/src/routes/login.ts +++ b/api/src/routes/login.ts @@ -4,6 +4,7 @@ import { Request, Response } from 'express'; import { botReq } from './internal/ws'; import { db } from '..'; import { FindOneResult } from 'monk'; +import { badRequest } from '../utils'; class BeginReqBody { user: string; @@ -61,7 +62,3 @@ app.post('/login/complete', async (req: Request, res: Response) => { res.status(200).send({ success: true, user: body.user.toUpperCase(), token: sessionToken }); }); - -function badRequest(res: Response) { - res.status(400).send(JSON.stringify({ "error": "Invalid request body" }, null, 4)); -} diff --git a/api/src/utils.ts b/api/src/utils.ts index 387aa31..ea389ae 100644 --- a/api/src/utils.ts +++ b/api/src/utils.ts @@ -36,4 +36,12 @@ async function getSessionInfo(user: string, token: string): Promise return { exists: !!session, valid: !!(session && !session.invalid && session.expires > Date.now()), nonce: session?.nonce } } -export { isAuthenticated, getSessionInfo } +function badRequest(res: Response) { + res.status(400).send(JSON.stringify({ "error": "Invalid request body" }, null, 4)); +} + +function unauthorized(res: Response) { + res.status(401).send(JSON.stringify({ "error": "Unauthorized" }, null, 4)); +} + +export { isAuthenticated, getSessionInfo, badRequest, unauthorized } diff --git a/bot/src/bot/modules/api/server_details.ts b/bot/src/bot/modules/api/server_details.ts new file mode 100644 index 0000000..965b574 --- /dev/null +++ b/bot/src/bot/modules/api/server_details.ts @@ -0,0 +1,61 @@ +import { Member } from "revolt.js/dist/maps/Members"; +import { User } from "revolt.js/dist/maps/Users"; +import { client } from "../../.."; +import AutomodSettings from "../../../struct/antispam/AutomodSettings"; +import ServerConfig from "../../../struct/ServerConfig"; +import { getPermissionLevel } from "../../util"; +import { wsEvents, WSResponse } from "../api_communication"; + +type ReqData = { user: string, server: string } + +type ServerDetails = { + id: string, + perms: 0|1|2, + name: string, + description?: string, + iconURL?: string, + bannerURL?: string, + serverConfig?: ServerConfig, +} + +wsEvents.on('req:getUserServerDetails', async (data: ReqData, cb: (data: WSResponse) => void) => { + try { + const server = client.servers.get(data.server); + if (!server) return cb({ success: false, error: 'The requested server could not be found', statusCode: 404 }); + + let user: User; + try { + user = client.users.get(data.user) || await client.users.fetch(data.user); + } catch(e) { + cb({ success: false, error: 'The requested user could not be found', statusCode: 404 }); + return; + } + + let member: Member; + try { + member = await server.fetchMember(user); + } catch(e) { + cb({ success: false, error: 'The requested user is not a member of that server', statusCode: 401 }); + return; + } + + const serverConfig: ServerConfig = await client.db.get('servers').findOne({ id: server._id }); + + // todo: remove unwanted keys from server config + + const response: ServerDetails = { + id: server._id, + name: server.name, + perms: await getPermissionLevel(member, server), + description: server.description ?? undefined, + bannerURL: server.generateBannerURL(), + iconURL: server.generateIconURL(), + serverConfig, + } + + cb({ success: true, server: response }); + } catch(e) { + console.error(e); + cb({ success: false, error: `${e}` }); + } +}); diff --git a/bot/src/bot/modules/api_communication.ts b/bot/src/bot/modules/api_communication.ts index 4a0ce7a..34a17b0 100644 --- a/bot/src/bot/modules/api_communication.ts +++ b/bot/src/bot/modules/api_communication.ts @@ -134,3 +134,4 @@ wsEvents.on('req:requestLogin', async (data: any, cb: (data: WSResponse) => void export { wsEvents, wsSend, WSResponse } import('./api/servers'); +import('./api/server_details'); diff --git a/web/src/pages/ServerDashboard.tsx b/web/src/pages/ServerDashboard.tsx index 23985c0..ad61899 100644 --- a/web/src/pages/ServerDashboard.tsx +++ b/web/src/pages/ServerDashboard.tsx @@ -4,7 +4,7 @@ import { FunctionComponent, useCallback, useEffect, useState } from "react"; import { Button } from '@revoltchat/ui/lib/components/atoms/inputs/Button'; import { InputBox } from '@revoltchat/ui/lib/components/atoms/inputs/InputBox'; import { H1 } from '@revoltchat/ui/lib/components/atoms/heading/H1'; -import { H2 } from '@revoltchat/ui/lib/components/atoms/heading/H2'; +import { H4 } from '@revoltchat/ui/lib/components/atoms/heading/H4'; import { API_URL } from "../App"; import { getAuthHeaders } from "../utils"; import { useParams } from "react-router-dom"; @@ -12,10 +12,30 @@ import { useParams } from "react-router-dom"; type Server = { id: string, perms: 0|1|2, name: string, iconURL?: string, bannerURL?: string } const ServerDashboard: FunctionComponent = () => { + const [serverInfo, setServerInfo] = useState({} as any); + const [status, setStatus] = useState(''); const { serverid } = useParams(); + const loadInfo = useCallback(async () => { + try { + const res = await axios.get(`${API_URL}/dash/server/${serverid}`, { headers: await getAuthHeaders() }); + setServerInfo(res.data.server); + } catch(e: any) { + console.error(e); + setStatus(`${e?.message ?? e}`); + } + }, [serverInfo]); + + useEffect(() => { loadInfo() }, []); + return ( - sus + <> +

{serverInfo?.name ?? 'Loading...'}

+ {status.length ? {status} :
} + + ); }