From bc10c3d01457449c7f2e57c9a518fb2720986d68 Mon Sep 17 00:00:00 2001 From: Jan Date: Fri, 10 Jun 2022 23:32:53 +0200 Subject: [PATCH] support iframing dashboard --- .vscode/settings.json | 3 + api/src/routes/dash/server-automod.ts | 2 +- bot/src/bot/modules/event_handler.ts | 33 +++++++++ web/src/App.tsx | 15 +++- .../pages/ServerDashboard/ServerDashboard.tsx | 68 ++++++++++--------- 5 files changed, 87 insertions(+), 34 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d3def91 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.formatOnSave": false +} diff --git a/api/src/routes/dash/server-automod.ts b/api/src/routes/dash/server-automod.ts index 6f8bfae..ff8bc83 100644 --- a/api/src/routes/dash/server-automod.ts +++ b/api/src/routes/dash/server-automod.ts @@ -34,7 +34,7 @@ app.get('/dash/server/:server/automod',requireAuth({ permission: 2 }) , async (r const serverConfig: FindOneResult = await db.get('servers').findOne({ id: server }); const result = { - antispam: (serverConfig.automodSettings?.spam as AntispamRule[]|undefined) + antispam: (serverConfig?.automodSettings?.spam as AntispamRule[]|undefined) ?.map(r => ({ // Removing unwanted fields from response action: r.action, channels: r.channels, diff --git a/bot/src/bot/modules/event_handler.ts b/bot/src/bot/modules/event_handler.ts index c4e7166..9cf8db5 100644 --- a/bot/src/bot/modules/event_handler.ts +++ b/bot/src/bot/modules/event_handler.ts @@ -1,4 +1,5 @@ import { ulid } from "ulid"; +import crypto from "crypto"; import { client, dbs } from "../.."; import Infraction from "../../struct/antispam/Infraction"; import InfractionType from "../../struct/antispam/InfractionType"; @@ -7,6 +8,8 @@ import logger from "../logger"; import { hasPermForChannel, storeInfraction } from "../util"; import { DEFAULT_PREFIX } from "./command_handler"; +const DM_SESSION_LIFETIME = 1000 * 60 * 60 * 24 * 30; + // Listen to system messages client.on('message', async message => { if (typeof message.content != 'object') { @@ -81,6 +84,36 @@ client.on('message', async message => { } }); +// DM message based API session token retrieval +client.on('message', async message => { + console.log(message.channel?.channel_type, message.nonce, message.content) + if ( + message.channel?.channel_type == "DirectMessage" && + message.nonce?.startsWith("REQUEST_SESSION_TOKEN-") && + message.content?.toLowerCase().startsWith("requesting session token.") + ) { + logger.info('Received session token request in DMs.'); + + const token = crypto.randomBytes(48).toString('base64').replace(/=/g, ''); + + await client.db.get('sessions').insert({ + user: message.author_id, + token: token, + nonce: message.nonce, + invalid: false, + expires: Date.now() + DM_SESSION_LIFETIME, + }) + + // Don't need to risk exposing the user to the token, so we'll send it in the nonce + await message.channel.sendMessage({ + content: 'Token request granted.', + nonce: `${ulid()}; TOKEN:${token}`, + replies: [ { id: message.author_id, mention: false } ], + }); + return; + } +}) + // Send a message when added to a server client.on('member/join', (member) => { if (member._id.user != client.user?._id) return; diff --git a/web/src/App.tsx b/web/src/App.tsx index 449373d..05ea674 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,4 +1,4 @@ -import { Route, BrowserRouter, Routes } from 'react-router-dom'; +import { Route, BrowserRouter, Routes, useLocation } from 'react-router-dom'; import Home from './pages/Home'; import './App.css'; import '@revoltchat/ui/src/styles/dark.css'; @@ -6,6 +6,7 @@ import '@revoltchat/ui/src/styles/common.css'; import RequireAuth from './components/RequireAuth'; import DashboardHome from './pages/DashboardHome'; import ServerDashboard from './pages/ServerDashboard/ServerDashboard'; +import localforage from 'localforage'; const API_URL = import.meta.env.VITE_API_URL?.toString() || 'http://localhost:9000'; @@ -14,6 +15,18 @@ const BOT_PREFIX = import.meta.env.VITE_BOT_PREFIX?.toString() || '/'; function App() { + const authConfig = new URLSearchParams(window.location.search).get('setAuth'); + + if (authConfig) { + console.log('Using provided auth data'); + + const [ user, token ] = authConfig.split(':'); + localforage.setItem('auth', { + user: decodeURIComponent(user), + token: decodeURIComponent(token), + }) + } + return ( diff --git a/web/src/pages/ServerDashboard/ServerDashboard.tsx b/web/src/pages/ServerDashboard/ServerDashboard.tsx index 3a8a6cd..8e6c6ae 100644 --- a/web/src/pages/ServerDashboard/ServerDashboard.tsx +++ b/web/src/pages/ServerDashboard/ServerDashboard.tsx @@ -74,6 +74,8 @@ const ServerDashboard: FunctionComponent = () => { const { serverid } = useParams(); + const embedded = !!(new URLSearchParams(window.location.search).get('embedded')); + const saveConfig = useCallback(async () => { if (Object.values(changed).filter(i => i).length == 0) return; @@ -135,43 +137,45 @@ const ServerDashboard: FunctionComponent = () => { return ( <> {status.length ? {status} : <>} -
- -
- - Back -
- - - {serverInfo?.name ?? 'Loading...'} - - - • - - - {serverInfo.description || No server description set} - -
+ +
+ + Back +
+ + + {serverInfo?.name ?? 'Loading...'} + + + • + + + {serverInfo.description || No server description set} + + + )}