This commit is contained in:
lingdocs 2021-08-25 12:32:15 +04:00
parent 3f798d5534
commit fe04638859
6 changed files with 59 additions and 6 deletions

View File

@ -47,6 +47,11 @@ export async function getLingdocsUser(field: "email" | "userId" | "githubId" | "
return user.docs[0] as T.LingdocsUser;
}
export async function getAllLingdocsUsers(): Promise<T.LingdocsUser[]> {
const users = await usersDb.find({ selector: { userId: { $exists: true }}});
return users.docs as T.LingdocsUser[];
}
export async function insertLingdocsUser(user: T.LingdocsUser): Promise<T.LingdocsUser> {
const res = await usersDb.insert(user);
const newUser = processAPIResponse(user, res);

View File

@ -74,7 +74,7 @@ export async function createNewUser(input: {
tests: [],
lastLogin: now,
lastActive: now,
textOptions: undefined,
userTextOptionsRecord: undefined,
};
const user = await insertLingdocsUser(newUser);
sendVerificationEmail(user, email.token).catch(console.error);
@ -92,7 +92,7 @@ export async function createNewUser(input: {
tests: [],
lastLogin: now,
lastActive: now,
textOptions: undefined,
userTextOptionsRecord: undefined,
};
const user = await insertLingdocsUser(newUser);
return user;
@ -113,7 +113,7 @@ export async function createNewUser(input: {
tests: [],
lastActive: now,
level: "basic",
textOptions: undefined,
userTextOptionsRecord: undefined,
}
const user = await insertLingdocsUser(newUser);
sendVerificationEmail(user, em.token);
@ -130,7 +130,7 @@ export async function createNewUser(input: {
tests: [],
lastActive: now,
level: "basic",
textOptions: undefined,
userTextOptionsRecord: undefined,
}
const user = await insertLingdocsUser(newUser);
return user;

View File

@ -1,6 +1,7 @@
import { Router } from "express";
import { PassportStatic } from "passport";
import {
getAllLingdocsUsers,
getLingdocsUser,
updateLingdocsUser,
} from "../lib/couch-db";
@ -136,10 +137,22 @@ const authRouter = (passport: PassportStatic) => {
return res.send({ ok: true, user });
});
} catch(e) {
return next(e);
next(e);
}
});
router.get("/admin", async (req, res, next) => {
try {
if (!req.user.admin) {
return res.redirect("/");
}
const users = await getAllLingdocsUsers();
res.render("admin", { users });
} catch (e) {
next(e);
}
})
router.get("/email-verification/:uuid/:token", async (req, res, next) => {
const page = "email-verification";
const { uuid, token } = req.params;

34
account/views/admin.ejs Normal file
View File

@ -0,0 +1,34 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="LingDocs Signin">
<title>Admin · LingDocs</title>
<link href="/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h1 class="my-4">LingDocs Auth Admin</h1>
<table class="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Level</th>
</tr>
</thead>
<tbody>
<% for(var i=0; i < users.length; i++) { %>
<tr>
<td><%= users[i].name %></td>
<td><%= users[i].email %></td>
<td><%= users[i].level %></td>
</tr>
<% } %>
</tbody>
</table>
</div>
</body>
</html>

View File

@ -27,6 +27,7 @@ export type UserTextOptionsRecord = {
// TODO: TYPE GUARDING SO WE NEVER HAVE A USER WITH NO Id or Password
export type LingdocsUser = {
userId: UUID,
admin?: boolean,
password?: Hash,
name: string,
email?: string,

View File

@ -184,7 +184,7 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
<Modal.Header closeButton>
<Modal.Title>Upgrade Account</Modal.Title>
</Modal.Header>
<Modal.Body>Enter the secret upgrade password to upgrade your account or <a href="javascript:;" onClick={handleUpgradeRequest}>request an upgrade</a>.</Modal.Body>
<Modal.Body>Enter the secret upgrade password to upgrade your account or <button className="btn btn-sm btn-outline-secondary" onClick={handleUpgradeRequest}>request an upgrade</button>.</Modal.Body>
<div className="form-group px-3">
<label htmlFor="upgradePasswordForm">Upgrade password:</label>
<input