support iframing dashboard
This commit is contained in:
parent
6b5df8c33a
commit
bc10c3d014
5 changed files with 87 additions and 34 deletions
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"editor.formatOnSave": false
|
||||||
|
}
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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={[
|
||||||
|
|
Loading…
Reference in a new issue