access.ts 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import { create } from "zustand";
  2. import { persist } from "zustand/middleware";
  3. import { DEFAULT_API_HOST, StoreKey } from "../constant";
  4. import { getHeaders } from "../client/api";
  5. import { BOT_HELLO } from "./chat";
  6. import { getClientConfig } from "../config/client";
  7. export interface AccessControlStore {
  8. accessCode: string;
  9. token: string;
  10. needCode: boolean;
  11. hideUserApiKey: boolean;
  12. openaiUrl: string;
  13. hideBalanceQuery: boolean;
  14. updateToken: (_: string) => void;
  15. updateCode: (_: string) => void;
  16. updateOpenAiUrl: (_: string) => void;
  17. enabledAccessControl: () => boolean;
  18. isAuthorized: () => boolean;
  19. fetch: () => void;
  20. }
  21. let fetchState = 0; // 0 not fetch, 1 fetching, 2 done
  22. const DEFAULT_OPENAI_URL =
  23. getClientConfig()?.buildMode === "export" ? DEFAULT_API_HOST : "/api/openai/";
  24. console.log("[API] default openai url", DEFAULT_OPENAI_URL);
  25. export const useAccessStore = create<AccessControlStore>()(
  26. persist(
  27. (set, get) => ({
  28. token: "",
  29. accessCode: "",
  30. needCode: true,
  31. hideUserApiKey: false,
  32. openaiUrl: DEFAULT_OPENAI_URL,
  33. hideBalanceQuery: false,
  34. enabledAccessControl() {
  35. get().fetch();
  36. return get().needCode;
  37. },
  38. updateCode(code: string) {
  39. set(() => ({ accessCode: code }));
  40. },
  41. updateToken(token: string) {
  42. set(() => ({ token }));
  43. },
  44. updateOpenAiUrl(url: string) {
  45. set(() => ({ openaiUrl: url }));
  46. },
  47. isAuthorized() {
  48. get().fetch();
  49. // has token or has code or disabled access control
  50. return (
  51. !!get().token || !!get().accessCode || !get().enabledAccessControl()
  52. );
  53. },
  54. fetch() {
  55. if (fetchState > 0 || getClientConfig()?.buildMode === "export") return;
  56. fetchState = 1;
  57. fetch("/api/config", {
  58. method: "post",
  59. body: null,
  60. headers: {
  61. ...getHeaders(),
  62. },
  63. })
  64. .then((res) => res.json())
  65. .then((res: DangerConfig) => {
  66. console.log("[Config] got config from server", res);
  67. set(() => ({ ...res }));
  68. if ((res as any).botHello) {
  69. BOT_HELLO.content = (res as any).botHello;
  70. }
  71. })
  72. .catch(() => {
  73. console.error("[Config] failed to fetch config");
  74. })
  75. .finally(() => {
  76. fetchState = 2;
  77. });
  78. },
  79. }),
  80. {
  81. name: StoreKey.Access,
  82. version: 1,
  83. },
  84. ),
  85. );