From 3c56103de0cfd2a414bd058445da3d1d1a575655 Mon Sep 17 00:00:00 2001 From: nai-degen Date: Tue, 29 Aug 2023 14:20:28 -0500 Subject: [PATCH] adds optional user_token nicknames --- src/admin/common.ts | 1 + src/admin/csrf.ts | 6 ++- src/admin/routes.ts | 3 +- src/proxy/auth/user-store.ts | 2 + src/views/_partials/admin-header.ejs | 4 ++ src/views/admin/error.ejs | 2 +- src/views/admin/import-users.ejs | 1 + src/views/admin/list-users.ejs | 32 ++++++++++-- src/views/admin/view-user.ejs | 76 +++++++++++++++++++++++----- 9 files changed, 106 insertions(+), 21 deletions(-) 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 @@

  • token (required): a unique identifier for the user
  • +
  • nickname (optional): a nickname for the user, max 80 chars
  • ip (optional): IP addresses the user has connected from
  • type (optional): either normal or diff --git a/src/views/admin/list-users.ejs b/src/views/admin/list-users.ejs index 4ab26d7..4ee9367 100644 --- a/src/views/admin/list-users.ejs +++ b/src/views/admin/list-users.ejs @@ -1,14 +1,15 @@ <%- include("../_partials/admin-header", { title: "Users - OAI Reverse Proxy Admin" }) %>

    User Token List

    - <% if (users.length === 0) { %>

    No users found.

    <% } else { %> + + - + @@ -22,7 +23,14 @@ <% users.forEach(function(user){ %> @@ -41,7 +49,6 @@ <% }); %>
    User TokenUser class="active"<% } %> >IPs class="active"<% } %> >Prompts class="active"<% } %> >Tokens
    - <%= user.token %> + + <%= user.token %> + <% if (user.nickname) { %> + + <% } else { %> + + <% } %> + <%= user.ip.length %> <%= user.promptCount %>
    -
      <% if (page > 1) { %>
    • «
    • @@ -57,6 +64,23 @@ <% } %> <%- include("../_partials/admin-footer") %>