little authentication overhaul
This commit is contained in:
parent
8b877f4740
commit
7cf3553026
6 changed files with 42 additions and 24 deletions
|
@ -1,6 +1,6 @@
|
||||||
import { app, db } from '../..';
|
import { app, db } from '../..';
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { badRequest, isAuthenticated, unauthorized } from '../../utils';
|
import { badRequest, isAuthenticated, requireAuth, unauthorized } from '../../utils';
|
||||||
import { botReq } from '../internal/ws';
|
import { botReq } from '../internal/ws';
|
||||||
import { FindOneResult } from 'monk';
|
import { FindOneResult } from 'monk';
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ type AntispamRule = {
|
||||||
message: string | null;
|
message: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.get('/dash/server/:server/automod', async (req: Request, res: Response) => {
|
app.get('/dash/server/:server/automod',requireAuth({ permission: 2 }) , async (req: Request, res: Response) => {
|
||||||
const user = await isAuthenticated(req, res, true);
|
const user = await isAuthenticated(req, res, true);
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ app.get('/dash/server/:server/automod', async (req: Request, res: Response) => {
|
||||||
res.send(result);
|
res.send(result);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.patch('/dash/server/:server/automod/:ruleid', async (req: Request, res: Response) => {
|
app.patch('/dash/server/:server/automod/:ruleid', requireAuth({ permission: 2 }), async (req: Request, res: Response) => {
|
||||||
const user = await isAuthenticated(req, res, true);
|
const user = await isAuthenticated(req, res, true);
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|
||||||
|
@ -56,16 +56,6 @@ app.patch('/dash/server/:server/automod/:ruleid', async (req: Request, res: Resp
|
||||||
const body = req.body;
|
const body = req.body;
|
||||||
if (!server || !ruleid) return badRequest(res);
|
if (!server || !ruleid) 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: 'Server not found' });
|
|
||||||
|
|
||||||
const permissionLevel: 0|1|2|3 = response.perms;
|
|
||||||
if (permissionLevel < 2) return unauthorized(res, `Only bot managers can manage moderation rules.`);
|
|
||||||
|
|
||||||
const serverConfig: FindOneResult<any> = await db.get('servers').findOne({ id: server });
|
const serverConfig: FindOneResult<any> = await db.get('servers').findOne({ id: server });
|
||||||
const antiSpamRules: AntispamRule[] = serverConfig.automodSettings?.spam ?? [];
|
const antiSpamRules: AntispamRule[] = serverConfig.automodSettings?.spam ?? [];
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { app, db } from '../..';
|
import { app, db } from '../..';
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { badRequest, getPermissionLevel, isAuthenticated, unauthorized } from '../../utils';
|
import { badRequest, getPermissionLevel, isAuthenticated, requireAuth, unauthorized } from '../../utils';
|
||||||
import { botReq } from '../internal/ws';
|
import { botReq } from '../internal/ws';
|
||||||
|
|
||||||
type User = { id: string, username?: string, avatarURL?: string }
|
type User = { id: string, username?: string, avatarURL?: string }
|
||||||
|
@ -18,7 +18,7 @@ type ServerDetails = {
|
||||||
channels: Channel[],
|
channels: Channel[],
|
||||||
}
|
}
|
||||||
|
|
||||||
app.get('/dash/server/:server', async (req: Request, res: Response) => {
|
app.get('/dash/server/:server', requireAuth({ permission: 0 }), async (req: Request, res: Response) => {
|
||||||
const user = await isAuthenticated(req, res, true);
|
const user = await isAuthenticated(req, res, true);
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { app } from '../..';
|
import { app } from '../..';
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { isAuthenticated, unauthorized } from '../../utils';
|
import { isAuthenticated, requireAuth, unauthorized } from '../../utils';
|
||||||
import { botReq } from '../internal/ws';
|
import { botReq } from '../internal/ws';
|
||||||
|
|
||||||
type Server = { id: string, perms: 0|1|2|3, name: string, iconURL?: string, bannerURL?: string }
|
type Server = { id: string, perms: 0|1|2|3, name: string, iconURL?: string, bannerURL?: string }
|
||||||
|
|
||||||
app.get('/dash/servers', async (req: Request, res: Response) => {
|
app.get('/dash/servers', requireAuth({ requireLogin: true }), async (req: Request, res: Response) => {
|
||||||
const user = await isAuthenticated(req);
|
const user = await isAuthenticated(req, res, true);
|
||||||
if (!user) return unauthorized(res);
|
if (!user) return;
|
||||||
|
|
||||||
const response = await botReq('getUserServers', { user });
|
const response = await botReq('getUserServers', { user });
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Request, Response } from 'express';
|
||||||
import { botReq } from './internal/ws';
|
import { botReq } from './internal/ws';
|
||||||
import { db } from '..';
|
import { db } from '..';
|
||||||
import { FindOneResult } from 'monk';
|
import { FindOneResult } from 'monk';
|
||||||
import { badRequest } from '../utils';
|
import { badRequest, isAuthenticated, requireAuth } from '../utils';
|
||||||
import { RateLimiter } from '../middlewares/ratelimit';
|
import { RateLimiter } from '../middlewares/ratelimit';
|
||||||
|
|
||||||
class BeginReqBody {
|
class BeginReqBody {
|
||||||
|
@ -19,7 +19,12 @@ class CompleteReqBody {
|
||||||
const beginRatelimiter = new RateLimiter('/login/begin', { limit: 10, timeframe: 300 });
|
const beginRatelimiter = new RateLimiter('/login/begin', { limit: 10, timeframe: 300 });
|
||||||
const completeRatelimiter = new RateLimiter('/login/complete', { limit: 5, timeframe: 30 });
|
const completeRatelimiter = new RateLimiter('/login/complete', { limit: 5, timeframe: 30 });
|
||||||
|
|
||||||
app.post('/login/begin', (...args) => beginRatelimiter.execute(...args), async (req: Request, res: Response) => {
|
app.post('/login/begin',
|
||||||
|
(...args) => beginRatelimiter.execute(...args),
|
||||||
|
requireAuth({ noAuthOnly: true }),
|
||||||
|
async (req: Request, res: Response) => {
|
||||||
|
if (typeof await isAuthenticated(req) == 'string') return res.status(403).send({ error: 'You are already authenticated' });
|
||||||
|
|
||||||
const body = req.body as BeginReqBody;
|
const body = req.body as BeginReqBody;
|
||||||
if (!body.user || typeof body.user != 'string') return badRequest(res);
|
if (!body.user || typeof body.user != 'string') return badRequest(res);
|
||||||
|
|
||||||
|
@ -30,7 +35,10 @@ app.post('/login/begin', (...args) => beginRatelimiter.execute(...args), async (
|
||||||
res.status(200).send({ success: true, nonce: r.nonce, code: r.code, uid: r.uid });
|
res.status(200).send({ success: true, nonce: r.nonce, code: r.code, uid: r.uid });
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/login/complete', (...args) => completeRatelimiter.execute(...args), async (req: Request, res: Response) => {
|
app.post('/login/complete',
|
||||||
|
(...args) => completeRatelimiter.execute(...args),
|
||||||
|
requireAuth({ noAuthOnly: true }),
|
||||||
|
async (req: Request, res: Response) => {
|
||||||
const body = req.body as CompleteReqBody;
|
const body = req.body as CompleteReqBody;
|
||||||
if ((!body.user || typeof body.user != 'string') ||
|
if ((!body.user || typeof body.user != 'string') ||
|
||||||
(!body.nonce || typeof body.nonce != 'string') ||
|
(!body.nonce || typeof body.nonce != 'string') ||
|
||||||
|
|
|
@ -49,4 +49,24 @@ async function getPermissionLevel(user: string, server: string) {
|
||||||
return await botReq('getPermissionLevel', { user, server });
|
return await botReq('getPermissionLevel', { user, server });
|
||||||
}
|
}
|
||||||
|
|
||||||
export { isAuthenticated, getSessionInfo, badRequest, unauthorized, getPermissionLevel }
|
type RequireAuthConfig = { permission?: 0|1|2|3, requireLogin?: boolean, noAuthOnly?: boolean }
|
||||||
|
function requireAuth(config: RequireAuthConfig): (req: Request, res: Response, next: () => void) => void {
|
||||||
|
return async (req: Request, res: Response, next: () => void) => {
|
||||||
|
const auth = await isAuthenticated(req);
|
||||||
|
|
||||||
|
if (config.noAuthOnly && typeof auth == 'string') return res.status(403).send({ error: 'Cannot access this route with authentication' });
|
||||||
|
if (config.requireLogin && !auth) return unauthorized(res, 'Authentication required for this route');
|
||||||
|
|
||||||
|
if (config.permission != undefined) {
|
||||||
|
if (!auth) return unauthorized(res, 'Authentication required for this route');
|
||||||
|
const server_id = req.params.serverid || req.params.server;
|
||||||
|
const levelRes = await getPermissionLevel(auth, server_id);
|
||||||
|
if (!levelRes.success) return res.status(500).send({ error: 'Unknown server or other error' });
|
||||||
|
if (levelRes.level < config.permission) return unauthorized(res, 'Your permission level is too low');
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { isAuthenticated, getSessionInfo, badRequest, unauthorized, getPermissionLevel, requireAuth }
|
||||||
|
|
|
@ -100,7 +100,7 @@ async function checkSudoPermission(message: Message): Promise<boolean> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function getPermissionLevel(user: User|Member, server: Server): Promise<0|1|2|3> {
|
async function getPermissionLevel(user: User|Member, server: Server): Promise<0|1|2|3> {
|
||||||
if (isSudo(user instanceof User ? user : (user.user || await client.users.fetch(user._id.user)))) return 2;
|
if (isSudo(user instanceof User ? user : (user.user || await client.users.fetch(user._id.user)))) return 3;
|
||||||
|
|
||||||
const member = user instanceof User ? await server.fetchMember(user) : user;
|
const member = user instanceof User ? await server.fetchMember(user) : user;
|
||||||
if (user instanceof Member) user = user.user!;
|
if (user instanceof Member) user = user.user!;
|
||||||
|
|
Loading…
Reference in a new issue