20% battery left
This commit is contained in:
+9
-9
@@ -6,7 +6,7 @@ import { revalidatePath } from "next/cache";
|
||||
import { redirect } from "next/navigation";
|
||||
import { after } from "next/server";
|
||||
import type { TypedFormData } from "@/app/(ui)/endgame/type";
|
||||
import { apiAuthCheck } from "./auth";
|
||||
import { adminCheck } from "./auth";
|
||||
import { uidRegex } from "./const";
|
||||
import { db } from "./db";
|
||||
import { cdnReferences } from "./db/references";
|
||||
@@ -83,7 +83,7 @@ export async function submitArtifact(formData: FormData) {
|
||||
}
|
||||
|
||||
export async function toggleCheck(submissionId: string) {
|
||||
if (!(await apiAuthCheck())) throw "Unauthorized";
|
||||
if (!(await adminCheck())) throw "Unauthorized";
|
||||
await db
|
||||
.update(submissions)
|
||||
.set({
|
||||
@@ -97,7 +97,7 @@ export async function toggleCheck(submissionId: string) {
|
||||
}
|
||||
|
||||
export async function toggleLock() {
|
||||
if (!(await apiAuthCheck())) throw "Unauthorized";
|
||||
if (!(await adminCheck())) throw "Unauthorized";
|
||||
const existing = await db
|
||||
.update(artifactSettings)
|
||||
.set({
|
||||
@@ -115,7 +115,7 @@ export async function toggleLock() {
|
||||
}
|
||||
|
||||
export async function setLimit(limit: number) {
|
||||
if (!(await apiAuthCheck())) throw "Unauthorized";
|
||||
if (!(await adminCheck())) throw "Unauthorized";
|
||||
|
||||
if (
|
||||
(
|
||||
@@ -135,7 +135,7 @@ export async function setLimit(limit: number) {
|
||||
}
|
||||
|
||||
export async function wipe() {
|
||||
if (!(await apiAuthCheck())) throw "Unauthorized";
|
||||
if (!(await adminCheck())) throw "Unauthorized";
|
||||
await db.delete(submissions);
|
||||
await db.execute(
|
||||
sql`ALTER SEQUENCE artifact.submissions_queue_seq RESTART WITH 1`,
|
||||
@@ -148,7 +148,7 @@ export async function wipe() {
|
||||
}
|
||||
|
||||
export async function random() {
|
||||
if (!(await apiAuthCheck())) throw "Unauthorized";
|
||||
if (!(await adminCheck())) throw "Unauthorized";
|
||||
const [sub] = await db
|
||||
.select()
|
||||
.from(submissions)
|
||||
@@ -162,7 +162,7 @@ export async function random() {
|
||||
export async function tlState(
|
||||
data: Partial<typeof tierlistStates.$inferInsert>,
|
||||
) {
|
||||
if (!(await apiAuthCheck())) throw "Unauthorized";
|
||||
if (!(await adminCheck())) throw "Unauthorized";
|
||||
const [existing] = await db
|
||||
.select()
|
||||
.from(tierlistStates)
|
||||
@@ -200,7 +200,7 @@ export async function tlPlacements(
|
||||
list: string,
|
||||
placements: Record<string, string[]>,
|
||||
) {
|
||||
if (!(await apiAuthCheck())) throw "Unauthorized";
|
||||
if (!(await adminCheck())) throw "Unauthorized";
|
||||
|
||||
// biome-ignore lint/correctness/noUnusedVariables: immutable property removal
|
||||
const { untiered, ...placementObj } = placements;
|
||||
@@ -284,7 +284,7 @@ export async function actionLog(text: string, details?: unknown) {
|
||||
after(async () => {
|
||||
// If not running in Next.js, skip.
|
||||
if (typeof process.versions.bun !== "undefined") return;
|
||||
const session = await apiAuthCheck();
|
||||
const session = await adminCheck();
|
||||
|
||||
const res = await db
|
||||
.insert(auditLog)
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@ export const auth = betterAuth({
|
||||
"http://astral:3000",
|
||||
"http://localhost:3000",
|
||||
"https://dev3000.dgnr.us",
|
||||
"http://m.dgnr.us",
|
||||
],
|
||||
database: drizzleAdapter(db, {
|
||||
provider: "pg", // or "mysql", "sqlite"
|
||||
@@ -29,7 +30,7 @@ export const auth = betterAuth({
|
||||
}),
|
||||
});
|
||||
|
||||
export async function apiAuthCheck() {
|
||||
export async function adminCheck() {
|
||||
"use server";
|
||||
|
||||
const session = await auth.api.getSession({
|
||||
|
||||
+43
-17
@@ -1,10 +1,23 @@
|
||||
"use client";
|
||||
|
||||
import { createContext, use, useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
createContext,
|
||||
use,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
type WebsiteComms = Partial<{ manual: boolean; debug: boolean }>;
|
||||
type WebsiteComms = Partial<{
|
||||
manual: boolean;
|
||||
debug: boolean;
|
||||
connected: boolean;
|
||||
updated: boolean;
|
||||
_raw: Record<string, unknown>;
|
||||
}>;
|
||||
|
||||
type WebsiteSignals = { beforeSubmit: undefined } & WebsiteComms;
|
||||
type WebsiteSignals = { beforeSubmit?: undefined } & WebsiteComms;
|
||||
|
||||
type WebsiteCommsMutator = {
|
||||
get<K extends keyof WebsiteComms>(key: K): WebsiteComms[K];
|
||||
@@ -45,13 +58,20 @@ export default function CommsProvider({
|
||||
[K in keyof WebsiteSignals]?: Array<(value: WebsiteSignals[K]) => void>;
|
||||
}>({});
|
||||
|
||||
const set: WebsiteCommsMutator["set"] = (k, v) => {
|
||||
storeRef.current = { ...storeRef.current, [k]: v };
|
||||
if (k !== "_raw") {
|
||||
console.log(`SET ${k} = ${v}`);
|
||||
const { _raw, ...withoutRaw } = storeRef.current;
|
||||
set("_raw", withoutRaw);
|
||||
}
|
||||
(listeners.current[k] || []).map((l) => l(v));
|
||||
forceUpdate({});
|
||||
};
|
||||
|
||||
const contextValue = useRef<WebsiteCommsMutator>({
|
||||
get: (k) => storeRef.current[k],
|
||||
set: (k, v) => {
|
||||
storeRef.current = { ...storeRef.current, [k]: v };
|
||||
(listeners.current[k] || []).map((l) => l(v));
|
||||
forceUpdate({});
|
||||
},
|
||||
set,
|
||||
on: (k, listener) => {
|
||||
// @ts-expect-error
|
||||
listeners.current[k] = [...(listeners.current[k] || []), listener];
|
||||
@@ -95,15 +115,18 @@ export const comms = {
|
||||
return comms.on(name, listener);
|
||||
}, [name]);
|
||||
|
||||
function mutator(
|
||||
value:
|
||||
| WebsiteComms[typeof name]
|
||||
| ((prev: WebsiteComms[typeof name]) => WebsiteComms[typeof name]),
|
||||
) {
|
||||
const v = typeof value === "function" ? value(comms.get(name)) : value;
|
||||
if (comms.active) comms.set(name, v);
|
||||
else setState(v);
|
||||
}
|
||||
const mutator = useCallback(
|
||||
(
|
||||
value:
|
||||
| WebsiteComms[typeof name]
|
||||
| ((prev: WebsiteComms[typeof name]) => WebsiteComms[typeof name]),
|
||||
) => {
|
||||
const v = typeof value === "function" ? value(comms.get(name)) : value;
|
||||
if (comms.active) comms.set(name, v);
|
||||
else setState(v);
|
||||
},
|
||||
[name],
|
||||
);
|
||||
|
||||
return [state, mutator] as const;
|
||||
},
|
||||
@@ -121,4 +144,7 @@ export const comms = {
|
||||
return comms.on(key, listener);
|
||||
}, [comms, key, listener]);
|
||||
},
|
||||
raw() {
|
||||
return [comms.var("_raw")[0]];
|
||||
},
|
||||
};
|
||||
|
||||
+16
-3
@@ -13,6 +13,8 @@ type ServerEventSource = {
|
||||
id: number;
|
||||
};
|
||||
|
||||
type EventSourceMOTD = { event?: string; data: unknown };
|
||||
|
||||
export class EventSourceManager {
|
||||
private list: ServerEventSource[] = [];
|
||||
private id = 0;
|
||||
@@ -21,16 +23,27 @@ export class EventSourceManager {
|
||||
{
|
||||
onDisconnect,
|
||||
signal,
|
||||
}: { onDisconnect?: () => void; signal?: AbortSignal } = {},
|
||||
motd,
|
||||
}: {
|
||||
onDisconnect?: () => void;
|
||||
signal?: AbortSignal;
|
||||
motd?: EventSourceMOTD | EventSourceMOTD[];
|
||||
} = {},
|
||||
): Response {
|
||||
let timeout: NodeJS.Timeout | undefined;
|
||||
this.id++;
|
||||
if (this.id > 100000) this.id = 0;
|
||||
const id = this.id;
|
||||
console.log(` SUB ${topic}#${id} (C${this.list.length})`);
|
||||
console.log(
|
||||
` SUB ${topic}#${id} (C${this.list.length})`,
|
||||
);
|
||||
|
||||
const push = (s: ServerEventSource) => {
|
||||
this.list.push(s);
|
||||
|
||||
// Send MOTD
|
||||
if (Array.isArray(motd)) motd.map((m) => s.send(m.data, m.event));
|
||||
else if (motd) s.send(motd.data, motd.event);
|
||||
};
|
||||
const remove = (id: number) => {
|
||||
if (this.list.findIndex((e) => e.id === id) < 0) return;
|
||||
@@ -99,7 +112,7 @@ export class EventSourceManager {
|
||||
{ event, topic = "_global" }: { event?: string; topic?: string },
|
||||
) {
|
||||
console.log(` PUB #${topic}`);
|
||||
setImmediate(() => {
|
||||
queueMicrotask(() => {
|
||||
for (const s of this.list) {
|
||||
if (s.topic !== topic) continue;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user