support iframing dashboard

This commit is contained in:
Jan 2022-06-10 23:32:53 +02:00
parent 6b5df8c33a
commit bc10c3d014
No known key found for this signature in database
GPG key ID: 5D5E18ACB990F57A
5 changed files with 87 additions and 34 deletions

3
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"editor.formatOnSave": false
}

View file

@ -34,7 +34,7 @@ app.get('/dash/server/:server/automod',requireAuth({ permission: 2 }) , async (r
const serverConfig: FindOneResult<any> = await db.get('servers').findOne({ id: server }); const serverConfig: FindOneResult<any> = await db.get('servers').findOne({ id: server });
const result = { const result = {
antispam: (serverConfig.automodSettings?.spam as AntispamRule[]|undefined) antispam: (serverConfig?.automodSettings?.spam as AntispamRule[]|undefined)
?.map(r => ({ // Removing unwanted fields from response ?.map(r => ({ // Removing unwanted fields from response
action: r.action, action: r.action,
channels: r.channels, channels: r.channels,

View file

@ -1,4 +1,5 @@
import { ulid } from "ulid"; import { ulid } from "ulid";
import crypto from "crypto";
import { client, dbs } from "../.."; import { client, dbs } from "../..";
import Infraction from "../../struct/antispam/Infraction"; import Infraction from "../../struct/antispam/Infraction";
import InfractionType from "../../struct/antispam/InfractionType"; import InfractionType from "../../struct/antispam/InfractionType";
@ -7,6 +8,8 @@ import logger from "../logger";
import { hasPermForChannel, storeInfraction } from "../util"; import { hasPermForChannel, storeInfraction } from "../util";
import { DEFAULT_PREFIX } from "./command_handler"; import { DEFAULT_PREFIX } from "./command_handler";
const DM_SESSION_LIFETIME = 1000 * 60 * 60 * 24 * 30;
// Listen to system messages // Listen to system messages
client.on('message', async message => { client.on('message', async message => {
if (typeof message.content != 'object') { 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 // Send a message when added to a server
client.on('member/join', (member) => { client.on('member/join', (member) => {
if (member._id.user != client.user?._id) return; if (member._id.user != client.user?._id) return;

View file

@ -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 Home from './pages/Home';
import './App.css'; import './App.css';
import '@revoltchat/ui/src/styles/dark.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 RequireAuth from './components/RequireAuth';
import DashboardHome from './pages/DashboardHome'; import DashboardHome from './pages/DashboardHome';
import ServerDashboard from './pages/ServerDashboard/ServerDashboard'; import ServerDashboard from './pages/ServerDashboard/ServerDashboard';
import localforage from 'localforage';
const API_URL = import.meta.env.VITE_API_URL?.toString() const API_URL = import.meta.env.VITE_API_URL?.toString()
|| 'http://localhost:9000'; || 'http://localhost:9000';
@ -14,6 +15,18 @@ const BOT_PREFIX = import.meta.env.VITE_BOT_PREFIX?.toString()
|| '/'; || '/';
function App() { 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 ( return (
<BrowserRouter> <BrowserRouter>
<Routes> <Routes>

View file

@ -74,6 +74,8 @@ const ServerDashboard: FunctionComponent = () => {
const { serverid } = useParams(); const { serverid } = useParams();
const embedded = !!(new URLSearchParams(window.location.search).get('embedded'));
const saveConfig = useCallback(async () => { const saveConfig = useCallback(async () => {
if (Object.values(changed).filter(i => i).length == 0) return; if (Object.values(changed).filter(i => i).length == 0) return;
@ -135,43 +137,45 @@ const ServerDashboard: FunctionComponent = () => {
return ( return (
<> <>
{status.length ? <a>{status}</a> : <></>} {status.length ? <a>{status}</a> : <></>}
<div {!embedded && (
style={{ <div
marginTop: '8px',
marginLeft: '8px',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden',
color: 'var(--secondary-foreground)',
maxWidth: 'calc(100% - 20px)',
}}
>
<Link to='/dashboard' style={{ float: 'left' }}>
<div style={{ display: 'flex' }}>
<Icon path={mdiChevronLeft} style={{ height: '25px' }} />
<span>Back</span>
</div>
</Link>
<span
style={{ style={{
color: 'var(--foreground)', marginTop: '8px',
marginLeft: '8px', marginLeft: '8px',
}} textOverflow: 'ellipsis',
> whiteSpace: 'nowrap',
{serverInfo?.name ?? 'Loading...'} overflow: 'hidden',
</span>
<span style={{ color: 'var(--secondary-foreground)', marginLeft: '6px' }}>
</span>
<span
style={{
color: 'var(--secondary-foreground)', color: 'var(--secondary-foreground)',
marginLeft: '6px', maxWidth: 'calc(100% - 20px)',
}} }}
> >
{serverInfo.description || <i>No server description set</i>} <Link to='/dashboard' style={{ float: 'left' }}>
</span> <div style={{ display: 'flex' }}>
</div> <Icon path={mdiChevronLeft} style={{ height: '25px' }} />
<span>Back</span>
</div>
</Link>
<span
style={{
color: 'var(--foreground)',
marginLeft: '8px',
}}
>
{serverInfo?.name ?? 'Loading...'}
</span>
<span style={{ color: 'var(--secondary-foreground)', marginLeft: '6px' }}>
</span>
<span
style={{
color: 'var(--secondary-foreground)',
marginLeft: '6px',
}}
>
{serverInfo.description || <i>No server description set</i>}
</span>
</div>
)}
<CategorySelector <CategorySelector
keys={[ keys={[