access.ts 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import {
  2. ApiPath,
  3. DEFAULT_API_HOST,
  4. ServiceProvider,
  5. StoreKey,
  6. } from "../constant";
  7. import { getHeaders } from "../client/api";
  8. import { getClientConfig } from "../config/client";
  9. import { createPersistStore } from "../utils/store";
  10. import { ensure } from "../utils/clone";
  11. let fetchState = 0; // 0 not fetch, 1 fetching, 2 done
  12. const DEFAULT_OPENAI_URL =
  13. getClientConfig()?.buildMode === "export" ? DEFAULT_API_HOST : ApiPath.OpenAI;
  14. const DEFAULT_ACCESS_STATE = {
  15. accessCode: "",
  16. useCustomConfig: false,
  17. provider: ServiceProvider.OpenAI,
  18. // openai
  19. openaiUrl: DEFAULT_OPENAI_URL,
  20. openaiApiKey: "",
  21. // azure
  22. azureUrl: "",
  23. azureApiKey: "",
  24. azureApiVersion: "2023-08-01-preview",
  25. // server config
  26. needCode: true,
  27. hideUserApiKey: false,
  28. hideBalanceQuery: false,
  29. disableGPT4: false,
  30. disableFastLink: false,
  31. customModels: "",
  32. };
  33. export const useAccessStore = createPersistStore(
  34. { ...DEFAULT_ACCESS_STATE },
  35. (set, get) => ({
  36. enabledAccessControl() {
  37. this.fetch();
  38. return get().needCode;
  39. },
  40. isValidOpenAI() {
  41. return ensure(get(), ["openaiUrl", "openaiApiKey"]);
  42. },
  43. isValidAzure() {
  44. return ensure(get(), ["azureUrl", "azureApiKey", "azureApiVersion"]);
  45. },
  46. isAuthorized() {
  47. this.fetch();
  48. // has token or has code or disabled access control
  49. return (
  50. this.isValidOpenAI() ||
  51. this.isValidAzure() ||
  52. !this.enabledAccessControl() ||
  53. (this.enabledAccessControl() && ensure(get(), ["accessCode"]))
  54. );
  55. },
  56. fetch() {
  57. if (fetchState > 0 || getClientConfig()?.buildMode === "export") return;
  58. fetchState = 1;
  59. fetch("/api/config", {
  60. method: "post",
  61. body: null,
  62. headers: {
  63. ...getHeaders(),
  64. },
  65. })
  66. .then((res) => res.json())
  67. .then((res: DangerConfig) => {
  68. console.log("[Config] got config from server", res);
  69. set(() => ({ ...res }));
  70. })
  71. .catch(() => {
  72. console.error("[Config] failed to fetch config");
  73. })
  74. .finally(() => {
  75. fetchState = 2;
  76. });
  77. },
  78. }),
  79. {
  80. name: StoreKey.Access,
  81. version: 2,
  82. migrate(persistedState, version) {
  83. if (version < 2) {
  84. const state = persistedState as {
  85. token: string;
  86. openaiApiKey: string;
  87. azureApiVersion: string;
  88. };
  89. state.openaiApiKey = state.token;
  90. state.azureApiVersion = "2023-08-01-preview";
  91. }
  92. return persistedState as any;
  93. },
  94. },
  95. );