access.ts 2.7 KB

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