feat: edit people on the admin dashboard
This commit is contained in:
parent
a65bb1bb5d
commit
d3a8d01824
|
@ -18,9 +18,20 @@ interface UserTable {
|
|||
username: string;
|
||||
global_name: string;
|
||||
email: string;
|
||||
avatar: string;
|
||||
banner: string;
|
||||
accent_color: number;
|
||||
avatar?: string;
|
||||
banner?: string;
|
||||
accent_color?: number;
|
||||
permissions: number;
|
||||
}
|
||||
|
||||
interface UserTableWithoutEmail {
|
||||
id: number;
|
||||
did: string;
|
||||
username: string;
|
||||
global_name: string;
|
||||
avatar?: string;
|
||||
banner?: string;
|
||||
accent_color?: number;
|
||||
permissions: number;
|
||||
}
|
||||
|
||||
|
@ -147,6 +158,12 @@ class Database {
|
|||
return (rows as UserTable[])[0];
|
||||
}
|
||||
|
||||
async getUsers(): Promise<UserTableWithoutEmail[]> {
|
||||
const [ rows ] = await this.mysqlPool!.execute('SELECT id, did, username, global_name, avatar, banner, accent_color, permissions FROM users');
|
||||
|
||||
return rows as UserTableWithoutEmail[];
|
||||
}
|
||||
|
||||
async getUserUsername(username: string): Promise<UserTable> {
|
||||
const [ rows ] = await this.mysqlPool!.execute('SELECT * FROM users WHERE username = ?', [ username ]);
|
||||
|
||||
|
@ -196,6 +213,12 @@ class Database {
|
|||
|
||||
return rows;
|
||||
}
|
||||
|
||||
async updateUserPermissions(id: number, permissions: any) {
|
||||
await this.mysqlPool!.execute('UPDATE users SET permissions = ? WHERE id = ?', [ permissions, id ]);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
export default Database;
|
|
@ -1,11 +1,52 @@
|
|||
import PageContent from '@/components/PageContent';
|
||||
import { useUser } from '@/context/UserContext';
|
||||
import { getCookieFromContext } from '@/utils/cookies';
|
||||
import { useRef } from 'react';
|
||||
import { use, useEffect, useState } from 'react';
|
||||
|
||||
import Image from 'next/image';
|
||||
|
||||
export default function Admin() {
|
||||
const { user, isLoggedIn } = useUser();
|
||||
|
||||
const [ users, setUsers ] = useState<any[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/api/v1/users')
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
setUsers(data);
|
||||
});
|
||||
}, [ ]);
|
||||
|
||||
const addTeamMember = (userId: number) => {
|
||||
alert(userId);
|
||||
};
|
||||
|
||||
const editPermissions = (user: any) => {
|
||||
const perms = prompt('Enter new permissions for user (1 == Admin; There is nothing more.):', user.permissions);
|
||||
|
||||
if (perms === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`/api/v1/user/${user.username}`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
permissions: perms,
|
||||
})
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status === 204) {
|
||||
alert('Permissions updated.');
|
||||
} else {
|
||||
alert('Failed to update permissions.');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (!isLoggedIn) {
|
||||
return null;
|
||||
}
|
||||
|
@ -18,6 +59,43 @@ export default function Admin() {
|
|||
|
||||
<p>What are we doin' today?</p>
|
||||
|
||||
<h2>Users</h2>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Avatar</th>
|
||||
<th>Username</th>
|
||||
<th>Global Name</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{users && (
|
||||
users.map((u) => (
|
||||
<tr key={u.id}>
|
||||
<td>
|
||||
<Image src={`https://cdn.discordapp.com/avatars/${u.did}/${u.avatar}.png`} alt={user.global_name} width={32} height={32} />
|
||||
</td>
|
||||
<td>{u.username}</td>
|
||||
<td>{u.global_name}</td>
|
||||
<td>
|
||||
<button onClick={() => { addTeamMember(u.id); }}>
|
||||
Add As Team Member (On the /about page.)
|
||||
</button>
|
||||
<button onClick={() => { editPermissions(u); }}>
|
||||
Edit Permissions
|
||||
</button>
|
||||
<button onClick={() => { alert('GDPR? Yeah no, will implement later.'); }}>
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>Your User in JSON Format</h2>
|
||||
|
||||
<p>In case you need it for some reason.</p>
|
||||
|
|
|
@ -9,9 +9,9 @@ type Data = {
|
|||
global_name: string;
|
||||
};
|
||||
email: string;
|
||||
avatar: string;
|
||||
banner: string;
|
||||
accent_color: number;
|
||||
avatar?: string;
|
||||
banner?: string;
|
||||
accent_color?: number;
|
||||
permissions: number;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Database from '@/lib/Database';
|
||||
import { isUserAdmin } from '@/utils/auth_util';
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
type Data = {
|
||||
|
@ -8,9 +9,9 @@ type Data = {
|
|||
username: string;
|
||||
global_name: string;
|
||||
};
|
||||
avatar: string;
|
||||
banner: string;
|
||||
accent_color: number;
|
||||
avatar?: string;
|
||||
banner?: string;
|
||||
accent_color?: number;
|
||||
permissions: number;
|
||||
};
|
||||
|
||||
|
@ -30,6 +31,29 @@ export default async function handler(
|
|||
return res.status(404).json({ error: 'Not Found' });
|
||||
}
|
||||
|
||||
// hehe only admins update users :trolley:
|
||||
// also validation yeah uh... didn't have budget for that
|
||||
// tech debt for the win
|
||||
if (req.method === 'PATCH') {
|
||||
const sid = req.cookies.session;
|
||||
|
||||
const isAdmin = isUserAdmin(sid);
|
||||
|
||||
if (!isAdmin) {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
|
||||
const { permissions } = req.body;
|
||||
|
||||
if (permissions) {
|
||||
await db.updateUserPermissions(user.id, permissions);
|
||||
}
|
||||
|
||||
res.status(204).end();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
id: user.id,
|
||||
discord_id: user.did,
|
||||
|
|
24
pages/api/v1/users.ts
Normal file
24
pages/api/v1/users.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import Database from '@/lib/Database';
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
interface Response {
|
||||
id: number;
|
||||
did: string;
|
||||
username: string;
|
||||
global_name: string;
|
||||
avatar?: string;
|
||||
banner?: string;
|
||||
accent_color?: number;
|
||||
permissions: number;
|
||||
}
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<Response[]>,
|
||||
) {
|
||||
const db = new Database();
|
||||
|
||||
const users = await db.getUsers();
|
||||
|
||||
res.status(200).json(users);
|
||||
}
|
29
utils/auth_util.ts
Normal file
29
utils/auth_util.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import Database from '@/lib/Database';
|
||||
import { hasPermission, Permission } from './permissions';
|
||||
|
||||
const db = new Database();
|
||||
|
||||
interface doas {
|
||||
user?: any;
|
||||
hasPermission: boolean;
|
||||
}
|
||||
|
||||
export async function isUserAdmin(sid?: string): Promise<doas> {
|
||||
if (!sid)
|
||||
return { hasPermission: false };
|
||||
|
||||
const session = await db.getSession(sid!);
|
||||
|
||||
if (!session)
|
||||
return { hasPermission: false };
|
||||
|
||||
const user = await db.getUser(session.uid);
|
||||
|
||||
if (!user)
|
||||
return { hasPermission: false };
|
||||
|
||||
return {
|
||||
user,
|
||||
hasPermission: hasPermission(user.permissions, Permission.Admin)
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue