This commit is contained in:
lingdocs 2021-08-26 12:19:09 +04:00
parent 934e5c7b05
commit 7b954238b3
7 changed files with 44 additions and 12 deletions

View File

@ -104,7 +104,8 @@ export async function updateLingdocsUser(uuid: T.UUID, toUpdate:
requestedUpgradeToStudent: undefined, requestedUpgradeToStudent: undefined,
} | } |
{ userTextOptionsRecord: T.UserTextOptionsRecord } | { userTextOptionsRecord: T.UserTextOptionsRecord } |
{ requestedUpgradeToStudent: true } { upgradeToStudentRequest: "waiting" } |
{ upgradeToStudentRequest: "denied" }
): Promise<T.LingdocsUser> { ): Promise<T.LingdocsUser> {
const user = await getLingdocsUser("userId", uuid); const user = await getLingdocsUser("userId", uuid);
if (!user) throw new Error("unable to update - user not found " + uuid); if (!user) throw new Error("unable to update - user not found " + uuid);

View File

@ -71,6 +71,12 @@ export async function upgradeUser(userId: T.UUID): Promise<T.UpgradeUserResponse
}; };
} }
export async function denyUserUpgradeRequest(userId: T.UUID): Promise<void> {
await updateLingdocsUser(userId, {
upgradeToStudentRequest: "denied",
});
}
export async function createNewUser(input: { export async function createNewUser(input: {
strategy: "local", strategy: "local",
email: string, email: string,

View File

@ -148,7 +148,7 @@ apiRouter.post("/user/upgradeToStudentRequest", async (req, res, next) => {
return; return;
} }
sendUpgradeRequestToAdmin(req.user).catch(console.error); sendUpgradeRequestToAdmin(req.user).catch(console.error);
await updateLingdocsUser(req.user.userId, { requestedUpgradeToStudent: true }); await updateLingdocsUser(req.user.userId, { upgradeToStudentRequest: "waiting" });
res.send({ ok: true, message: "request for upgrade sent" }); res.send({ ok: true, message: "request for upgrade sent" });
} catch (e) { } catch (e) {
next(e); next(e);

View File

@ -15,6 +15,7 @@ import {
} from "../lib/password-utils"; } from "../lib/password-utils";
import { import {
upgradeUser, upgradeUser,
denyUserUpgradeRequest,
} from "../lib/user-utils"; } from "../lib/user-utils";
import { validateReCaptcha } from "../lib/recaptcha"; import { validateReCaptcha } from "../lib/recaptcha";
import { import {
@ -157,13 +158,21 @@ const authRouter = (passport: PassportStatic) => {
} }
}); });
router.post("/admin/upgradeToStudent/:userId", async (req, res, next) => { /**
* Grant request for upgrade to student
*/
router.post("/admin/upgradeToStudent/:userId/:grantOrDeny", async (req, res, next) => {
try { try {
if (!req.user || !req.user.admin) { if (!req.user || !req.user.admin) {
return res.redirect("/"); return res.redirect("/");
} }
const userId = req.params.userId; const userId = req.params.userId as T.UUID;
await upgradeUser(userId as T.UUID); const grantOrDeny = req.params.grantOrDeny as "grant" | "deny";
if (grantOrDeny === "grant") {
await upgradeUser(userId);
} else {
await denyUserUpgradeRequest(userId);
}
res.redirect("/admin"); res.redirect("/admin");
} catch (e) { } catch (e) {
next(e); next(e);

View File

@ -60,10 +60,22 @@
<% } %> <% } %>
</td> </td>
<td> <td>
<% if (users[i].requestedUpgradeToStudent) { %> <% if (users[i].upgradeToStudentRequest === "waiting") { %>
<form action="/admin/upgradeToStudent/<%= users[i].userId %>" method="POST"> <div class="d-flex flex-row">
<button class="btn btn-sm btn-primary" type="submit"><i class="fas fa-stamp mr-2"></i> Grant Upgrade Request</button> <div>Requested Upgrade </div>
</form> <div>
<form action="/admin/upgradeToStudent/<%= users[i].userId %>/grand" method="POST">
<button class="btn btn-sm btn-success" type="submit"><i class="fas fa-thumbs-up mr-2"></i> Grant </button>
</form>
</div>
<div>
<form action="/admin/upgradeToStudent/<%= users[i].userId %>/deny" method="POST">
<button class="btn btn-sm btn-danger" type="submit"><i class="fas fa-thumbs-down mr-2"></i> Deny </button>
</form>
</div>
</div>
<% } else if (users[i].upgradeToStudentRequest === "waiting"){ %>
Upgrade Denied
<% } else { %> <% } else { %>
<%= users[i].level %> <%= users[i].level %>
<% } %> <% } %>

View File

@ -39,7 +39,7 @@ export type LingdocsUser = {
tokenHash: Hash, tokenHash: Hash,
requestedOn: TimeStamp, requestedOn: TimeStamp,
}, },
requestedUpgradeToStudent?: boolean, upgradeToStudentRequest?: "waiting" | "denied",
tests: [], tests: [],
lastLogin: TimeStamp, lastLogin: TimeStamp,
lastActive: TimeStamp, lastActive: TimeStamp,

View File

@ -155,10 +155,14 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
</div> </div>
</div> </div>
</li>} </li>}
<li className="list-group-item">Account Level: {capitalize(user.level)} {user.requestedUpgradeToStudent ? "(Upgrade Requested)" : ""}</li> <li className="list-group-item">Account Level: {capitalize(user.level)} {user.upgradeToStudentRequest === "waiting"
? "(Upgrade Requested)"
: user.upgradeToStudentRequest === "denied"
? "(Upgrade Denied)"
: ""}</li>
<li className="list-group-item">Signs in with: <li className="list-group-item">Signs in with:
{(user.password && user.email) && <span> {(user.password && user.email) && <span>
<i className="fas fa-key ml-2"></i> <span className="small">Password</span> <i className="fas fa-key ml-3"></i> <span className="small">Password</span>
</span>} </span>}
{providers.map((provider) => ( {providers.map((provider) => (
user[provider] && <span> user[provider] && <span>