diff --git a/src/admin/common.ts b/src/admin/common.ts index b7535ba..d9b30a6 100644 --- a/src/admin/common.ts +++ b/src/admin/common.ts @@ -45,6 +45,7 @@ export function paginate(set: unknown[], page: number, pageSize: number = 20) { export const UserSchema = z .object({ ip: z.array(z.string()).optional(), + nickname: z.string().max(80).optional(), type: z.enum(["normal", "special"]).optional(), promptCount: z.number().optional(), tokenCount: z.any().optional(), // never used, but remains for compatibility diff --git a/src/admin/csrf.ts b/src/admin/csrf.ts index 6f57f58..cb9ab43 100644 --- a/src/admin/csrf.ts +++ b/src/admin/csrf.ts @@ -8,7 +8,11 @@ const { generateToken, doubleCsrfProtection } = doubleCsrf({ getSecret: () => CSRF_SECRET, cookieName: "csrf", cookieOptions: { sameSite: "strict", path: "/" }, - getTokenFromRequest: (req) => req.body["_csrf"] || req.query["_csrf"], + getTokenFromRequest: (req) => { + const val = req.body["_csrf"] || req.query["_csrf"]; + delete req.body["_csrf"]; + return val; + }, }); const injectCsrfToken: express.RequestHandler = (req, res, next) => { diff --git a/src/admin/routes.ts b/src/admin/routes.ts index 4b54f21..6874a3e 100644 --- a/src/admin/routes.ts +++ b/src/admin/routes.ts @@ -37,7 +37,8 @@ adminRouter.use( } else if (err.name === "ForbiddenError") { data.status = 403; if (err.message === "invalid csrf token") { - data.message = "Invalid CSRF token; try refreshing the previous page before submitting again."; + data.message = + "Invalid CSRF token; try refreshing the previous page before submitting again."; } return res.status(403).render("admin/error", { ...data, flash: null }); } diff --git a/src/proxy/auth/user-store.ts b/src/proxy/auth/user-store.ts index ab38f6b..013665c 100644 --- a/src/proxy/auth/user-store.ts +++ b/src/proxy/auth/user-store.ts @@ -21,6 +21,8 @@ type QuotaModel = "claude" | "turbo" | "gpt4"; export interface User { /** The user's personal access token. */ token: string; + /** The user's nickname. */ + nickname?: string; /** The IP addresses the user has connected from. */ ip: string[]; /** The user's privilege level. */ diff --git a/src/views/_partials/admin-header.ejs b/src/views/_partials/admin-header.ejs index 2bd04ac..4f2daf8 100644 --- a/src/views/_partials/admin-header.ejs +++ b/src/views/_partials/admin-header.ejs @@ -26,6 +26,9 @@ border-collapse: collapse; border: 1px solid #ccc; } + table.striped tr:nth-child(even) { + background-color: #eaeaea + } table td, table th { border: 1px solid #ccc; padding: 0.25em 0.5em; @@ -35,6 +38,7 @@ } td.actions { padding: 0; + width: 0; text-align: center; } td.actions a { diff --git a/src/views/admin/error.ejs b/src/views/admin/error.ejs index 809311b..6c4072b 100644 --- a/src/views/admin/error.ejs +++ b/src/views/admin/error.ejs @@ -1,5 +1,5 @@ <%- include("../_partials/admin-header", { title: "Error" }) %> -
+

⚠️ Error <%= status %>: <%= message %>

<%= stack %>
Go Back | Go Home diff --git a/src/views/admin/import-users.ejs b/src/views/admin/import-users.ejs index 8e7c2c6..ba43978 100644 --- a/src/views/admin/import-users.ejs +++ b/src/views/admin/import-users.ejs @@ -6,6 +6,7 @@