From a5b39983047e86c71d9fccf925708863cf9fcb44 Mon Sep 17 00:00:00 2001 From: Yidadaa Date: Sat, 25 Mar 2023 22:24:52 +0800 Subject: [PATCH 1/4] fix: #23 errors when dev on windows --- app/layout.tsx | 9 +++++++-- package.json | 7 +++---- yarn.lock | 5 +++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/app/layout.tsx b/app/layout.tsx index f096ca2..3ac3b83 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,13 +1,18 @@ +/* eslint-disable @next/next/no-page-custom-font */ import "./styles/globals.scss"; import "./styles/markdown.scss"; import "./styles/prism.scss"; +import process from "child_process"; export const metadata = { title: "ChatGPT Next Web", - description: "Your personal ChatGPT Chat Bot." + description: "Your personal ChatGPT Chat Bot.", }; -const COMMIT_ID = process.env.COMMIT_ID +const COMMIT_ID = process + .execSync("git rev-parse --short HEAD") + .toString() + .trim(); export default function RootLayout({ children, diff --git a/package.json b/package.json index abc67e1..4b84ffd 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,9 @@ "version": "1.1", "private": false, "scripts": { - "dev": "cross-env COMMIT_ID=$(git rev-parse --short HEAD) next dev", - "build": "cross-env COMMIT_ID=$(git rev-parse --short HEAD) next build", - "start": "cross-env COMMIT_ID=$(git rev-parse --short HEAD) next start", + "dev": "next dev", + "build": "next build", + "start": "next start", "lint": "next lint" }, "dependencies": { @@ -20,7 +20,6 @@ "eslint": "8.35.0", "eslint-config-next": "13.2.3", "eventsource-parser": "^0.1.0", - "git-rev-sync": "^3.0.2", "next": "^13.2.3", "openai": "^3.2.1", "react": "^18.2.0", diff --git a/yarn.lock b/yarn.lock index 8e94c23..98d8759 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1313,6 +1313,11 @@ dependencies: "@types/ms" "*" +"@types/git-rev-sync@^2.0.0": + version "2.0.0" + resolved "https://registry.npmmirror.com/@types/git-rev-sync/-/git-rev-sync-2.0.0.tgz#9de6e18cb01e65f769de77175bbe93254664023e" + integrity sha512-qGYApbb0m8Ofy3pwYks+kYVIZQAN/cqNucJGbl5O5GpLw9JSzp74rkTWDhPv3brrJfJb5/ixtimLJpo4tfh2QA== + "@types/hast@^2.0.0": version "2.3.4" resolved "https://registry.npmmirror.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" From 2c899cf00eb729cc4aad2a13a74d2cabea9e7200 Mon Sep 17 00:00:00 2001 From: Yifei Zhang Date: Sun, 26 Mar 2023 06:53:40 +0000 Subject: [PATCH 2/4] feat: #2 add access control by access code --- README.md | 20 +++++++++++++ app/api/access.ts | 16 +++++++++++ app/components/settings.tsx | 25 +++++++++++++++-- app/layout.tsx | 26 +++++++++++++---- app/locales/cn.ts | 8 ++++++ app/locales/en.ts | 9 ++++++ app/requests.ts | 26 +++++++++++++++-- app/store/access.ts | 30 ++++++++++++++++++++ app/store/app.ts | 1 + app/store/index.ts | 1 + app/styles/globals.scss | 4 ++- app/utils.ts | 23 +++++++++------ middleware.ts | 30 ++++++++++++++++++++ package.json | 2 ++ tsconfig.json | 2 +- yarn.lock | 56 +++++++++---------------------------- 16 files changed, 216 insertions(+), 63 deletions(-) create mode 100644 app/api/access.ts create mode 100644 app/store/access.ts create mode 100644 middleware.ts diff --git a/README.md b/README.md index bef81a1..6323a2c 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ One-Click to deploy your own ChatGPT web UI. 如果你按照上述步骤一键部署了自己的项目,可能会发现总是提示“存在更新”的问题,这是由于 Vercel 会默认为你创建一个新项目而不是 fork 本项目,这会导致无法正确地检测更新。 推荐你按照下列步骤重新部署: + - 删除掉原先的 repo; - fork 本项目; - 前往 vercel 控制台,删除掉原先的 project,然后新建 project,选择你刚刚 fork 出来的项目重新进行部署即可; @@ -65,6 +66,7 @@ One-Click to deploy your own ChatGPT web UI. If you have deployed your own project with just one click following the steps above, you may encounter the issue of "Updates Available" constantly showing up. This is because Vercel will create a new project for you by default instead of forking this project, resulting in the inability to detect updates correctly. We recommend that you follow the steps below to re-deploy: + - Delete the original repo; - Fork this project; - Go to the Vercel dashboard, delete the original project, then create a new project and select the project you just forked to redeploy; @@ -74,6 +76,24 @@ This project will be continuously maintained. If you want to keep the code repos You can star or watch this project or follow author to get release notifictions in time. +## 访问控制 Access Control + +本项目提供有限的权限控制功能,请在环境变量页增加名为 `CODE` 的环境变量,值为用英文逗号分隔的自定义控制码: + +``` +code1,code2,code3 +``` + +增加或修改该环境变量后,请重新部署项目使改动生效。 + +This project provides limited access control. Please add an environment variable named `CODE` on the environment variables page. The value should be a custom control code separated by comma like this: + +``` +code1,code2,code3 +``` + +After adding or modifying this environment variable, please redeploy the project for the changes to take effect. + ## 开发 Development 点击下方按钮,开始二次开发: diff --git a/app/api/access.ts b/app/api/access.ts new file mode 100644 index 0000000..13ada21 --- /dev/null +++ b/app/api/access.ts @@ -0,0 +1,16 @@ +import md5 from "spark-md5"; + +export function getAccessCodes(): Set { + const code = process.env.CODE; + + try { + const codes = (code?.split(",") ?? []) + .filter((v) => !!v) + .map((v) => md5.hash(v.trim())); + return new Set(codes); + } catch (e) { + return new Set(); + } +} + +export const ACCESS_CODES = getAccessCodes(); diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 9623c3f..ec22a1a 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useState, useEffect, useRef, useMemo } from "react"; import EmojiPicker, { Theme as EmojiTheme } from "emoji-picker-react"; @@ -17,6 +17,7 @@ import { Theme, ALL_MODELS, useUpdateStore, + useAccessStore, } from "../store"; import { Avatar } from "./home"; @@ -38,7 +39,7 @@ function SettingItem(props: {
{props.subTitle}
)} -
{props.children}
+ {props.children} ); } @@ -71,6 +72,12 @@ export function Settings(props: { closeSettings: () => void }) { checkUpdate(); }, []); + const accessStore = useAccessStore(); + const enabledAccessControl = useMemo( + () => accessStore.enabledAccessControl(), + [] + ); + return ( <>
@@ -232,6 +239,20 @@ export function Settings(props: { closeSettings: () => void }) {
+ + { + accessStore.updateCode(e.currentTarget.value); + }} + > + + 0 ? "enabled" : "disabled", + }; + + return ( + <> + {Object.entries(metas).map(([k, v]) => ( + + ))} + + ); +} export default function RootLayout({ children, @@ -26,7 +42,7 @@ export default function RootLayout({ name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" /> - + diff --git a/app/locales/cn.ts b/app/locales/cn.ts index a6ff455..ab6af58 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -1,5 +1,8 @@ const cn = { WIP: "该功能仍在开发中……", + Error: { + Unauthorized: "现在是未授权状态,请在设置页填写授权码。", + }, ChatItem: { ChatItemCount: (count: number) => `${count} 条对话`, }, @@ -65,6 +68,11 @@ const cn = { Title: "历史消息长度压缩阈值", SubTitle: "当未压缩的历史消息超过该值时,将进行压缩", }, + AccessCode: { + Title: "访问码", + SubTitle: "现在是受控访问状态", + Placeholder: "请输入访问码", + }, Model: "模型 (model)", Temperature: { Title: "随机性 (temperature)", diff --git a/app/locales/en.ts b/app/locales/en.ts index 5059701..85a0caf 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -2,6 +2,10 @@ import type { LocaleType } from "./index"; const en: LocaleType = { WIP: "WIP...", + Error: { + Unauthorized: + "Unauthorized access, please enter access code in settings page.", + }, ChatItem: { ChatItemCount: (count: number) => `${count} messages`, }, @@ -69,6 +73,11 @@ const en: LocaleType = { SubTitle: "Will compress if uncompressed messages length exceeds the value", }, + AccessCode: { + Title: "Access Code", + SubTitle: "Access control enabled", + Placeholder: "Need Access Code", + }, Model: "Model", Temperature: { Title: "Temperature", diff --git a/app/requests.ts b/app/requests.ts index d502dc1..484fbb9 100644 --- a/app/requests.ts +++ b/app/requests.ts @@ -1,5 +1,6 @@ import type { ChatRequest, ChatReponse } from "./api/chat/typing"; -import { filterConfig, Message, ModelConfig } from "./store"; +import { filterConfig, Message, ModelConfig, useAccessStore } from "./store"; +import Locale from "./locales"; const TIME_OUT_MS = 30000; @@ -26,6 +27,17 @@ const makeRequestParam = ( }; }; +function getHeaders() { + const accessStore = useAccessStore.getState(); + let headers: Record = {}; + + if (accessStore.enabledAccessControl()) { + headers["access-code"] = accessStore.accessCode; + } + + return headers; +} + export async function requestChat(messages: Message[]) { const req: ChatRequest = makeRequestParam(messages, { filterBot: true }); @@ -33,6 +45,7 @@ export async function requestChat(messages: Message[]) { method: "POST", headers: { "Content-Type": "application/json", + ...getHeaders(), }, body: JSON.stringify(req), }); @@ -69,6 +82,7 @@ export async function requestChatStream( method: "POST", headers: { "Content-Type": "application/json", + ...getHeaders(), }, body: JSON.stringify(req), signal: controller.signal, @@ -82,6 +96,8 @@ export async function requestChatStream( controller.abort(); }; + console.log(res); + if (res.ok) { const reader = res.body?.getReader(); const decoder = new TextDecoder(); @@ -102,14 +118,18 @@ export async function requestChatStream( } } + finish(); + } else if (res.status === 401) { + console.error("Anauthorized"); + responseText = Locale.Error.Unauthorized; finish(); } else { console.error("Stream Error"); options?.onError(new Error("Stream Error")); } } catch (err) { - console.error("NetWork Error"); - options?.onError(new Error("NetWork Error")); + console.error("NetWork Error", err); + options?.onError(err as Error); } } diff --git a/app/store/access.ts b/app/store/access.ts new file mode 100644 index 0000000..4ec2111 --- /dev/null +++ b/app/store/access.ts @@ -0,0 +1,30 @@ +import { create } from "zustand"; +import { persist } from "zustand/middleware"; +import { queryMeta } from "../utils"; + +export interface AccessControlStore { + accessCode: string; + + updateCode: (_: string) => void; + enabledAccessControl: () => boolean; +} + +export const ACCESS_KEY = "access-control"; + +export const useAccessStore = create()( + persist( + (set, get) => ({ + accessCode: "", + enabledAccessControl() { + return queryMeta("access") === "enabled"; + }, + updateCode(code: string) { + set((state) => ({ accessCode: code })); + }, + }), + { + name: ACCESS_KEY, + version: 1, + } + ) +); diff --git a/app/store/app.ts b/app/store/app.ts index 91abb2c..3c4fcde 100644 --- a/app/store/app.ts +++ b/app/store/app.ts @@ -308,6 +308,7 @@ export const useChatStore = create()( onMessage(content, done) { if (done) { botMessage.streaming = false; + botMessage.content = content; get().onNewMessage(botMessage); } else { botMessage.content = content; diff --git a/app/store/index.ts b/app/store/index.ts index b247a7c..3bdb58c 100644 --- a/app/store/index.ts +++ b/app/store/index.ts @@ -1,2 +1,3 @@ export * from "./app"; export * from "./update"; +export * from "./access"; diff --git a/app/styles/globals.scss b/app/styles/globals.scss index fde2239..e7d3522 100644 --- a/app/styles/globals.scss +++ b/app/styles/globals.scss @@ -167,7 +167,8 @@ input[type="range"]::-webkit-slider-thumb:hover { width: 24px; } -input[type="number"] { +input[type="number"], +input[type="text"] { appearance: none; border-radius: 10px; border: var(--border-in-light); @@ -176,6 +177,7 @@ input[type="number"] { background: var(--white); color: var(--black); padding: 0 10px; + max-width: 50%; } div.math { diff --git a/app/utils.ts b/app/utils.ts index bcf45d9..1fe6889 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -57,20 +57,27 @@ export function selectOrCopy(el: HTMLElement, content: string) { return true; } +export function queryMeta(key: string, defaultValue?: string): string { + let ret: string; + if (document) { + const meta = document.head.querySelector( + `meta[name='${key}']` + ) as HTMLMetaElement; + ret = meta?.content ?? ""; + } else { + ret = defaultValue ?? ""; + } + + return ret; +} + let currentId: string; export function getCurrentCommitId() { if (currentId) { return currentId; } - if (document) { - const meta = document.head.querySelector( - "meta[name='version']" - ) as HTMLMetaElement; - currentId = meta?.content ?? ""; - } else { - currentId = process.env.COMMIT_ID ?? ""; - } + currentId = queryMeta("version"); return currentId; } diff --git a/middleware.ts b/middleware.ts new file mode 100644 index 0000000..afb54c3 --- /dev/null +++ b/middleware.ts @@ -0,0 +1,30 @@ +import { NextRequest, NextResponse } from "next/server"; +import { ACCESS_CODES } from "./app/api/access"; +import md5 from "spark-md5"; + +export const config = { + matcher: ["/api/chat", "/api/chat-stream"], +}; + +export function middleware(req: NextRequest, res: NextResponse) { + const accessCode = req.headers.get("access-code"); + const hashedCode = md5.hash(accessCode ?? "").trim(); + + console.log("[Auth] allowed hashed codes: ", [...ACCESS_CODES]); + console.log("[Auth] got access code:", accessCode); + console.log("[Auth] hashed access code:", hashedCode); + + if (!ACCESS_CODES.has(hashedCode)) { + return NextResponse.json( + { + needAccessCode: true, + hint: "Please go settings page and fill your access code.", + }, + { + status: 401, + } + ); + } + + return NextResponse.next(); +} diff --git a/package.json b/package.json index 4b84ffd..df74cb9 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", "@types/react-katex": "^3.0.0", + "@types/spark-md5": "^3.0.2", "@vercel/analytics": "^0.1.11", "cross-env": "^7.0.3", "emoji-picker-react": "^4.4.7", @@ -30,6 +31,7 @@ "remark-gfm": "^3.0.1", "remark-math": "^5.1.1", "sass": "^1.59.2", + "spark-md5": "^3.0.2", "typescript": "4.9.5", "zustand": "^4.3.6" } diff --git a/tsconfig.json b/tsconfig.json index e06a445..14d1893 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "ES2015", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, diff --git a/yarn.lock b/yarn.lock index 98d8759..7e69c5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1313,11 +1313,6 @@ dependencies: "@types/ms" "*" -"@types/git-rev-sync@^2.0.0": - version "2.0.0" - resolved "https://registry.npmmirror.com/@types/git-rev-sync/-/git-rev-sync-2.0.0.tgz#9de6e18cb01e65f769de77175bbe93254664023e" - integrity sha512-qGYApbb0m8Ofy3pwYks+kYVIZQAN/cqNucJGbl5O5GpLw9JSzp74rkTWDhPv3brrJfJb5/ixtimLJpo4tfh2QA== - "@types/hast@^2.0.0": version "2.3.4" resolved "https://registry.npmmirror.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" @@ -1395,6 +1390,11 @@ resolved "https://registry.npmmirror.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== +"@types/spark-md5@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/spark-md5/-/spark-md5-3.0.2.tgz#da2e8a778a20335fc4f40b6471c4b0d86b70da55" + integrity sha512-82E/lVRaqelV9qmRzzJ1PKTpyrpnT7mwdneKNJB9hUtypZDMggloDfFUCIqRRx3lYRxteCwXSq9c+W71Vf0QnQ== + "@types/unist@*", "@types/unist@^2.0.0": version "2.0.6" resolved "https://registry.npmmirror.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" @@ -2138,7 +2138,7 @@ escalade@^3.1.1: resolved "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== @@ -2526,15 +2526,6 @@ get-tsconfig@^4.2.0: resolved "https://registry.npmmirror.com/get-tsconfig/-/get-tsconfig-4.4.0.tgz#64eee64596668a81b8fce18403f94f245ee0d4e5" integrity sha512-0Gdjo/9+FzsYhXCEFueo2aY1z1tpXrxWZzP7k8ul9qt1U5o8rYJwTJYmaeHdrVosYIVYkOy2iwCJ9FdpocJhPQ== -git-rev-sync@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/git-rev-sync/-/git-rev-sync-3.0.2.tgz#9763c730981187c3419b75dd270088cc5f0e161b" - integrity sha512-Nd5RiYpyncjLv0j6IONy0lGzAqdRXUaBctuGBbrEA2m6Bn4iDrN/9MeQTXuiquw8AEKL9D2BW0nw5m/lQvxqnQ== - dependencies: - escape-string-regexp "1.0.5" - graceful-fs "4.1.15" - shelljs "0.8.5" - glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -2561,7 +2552,7 @@ glob@7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.1.3: +glob@^7.1.3: version "7.2.3" resolved "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -2632,11 +2623,6 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@4.1.15: - version "4.1.15" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" - integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== - graceful-fs@^4.2.4: version "4.2.10" resolved "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" @@ -2804,11 +2790,6 @@ internal-slot@^1.0.3, internal-slot@^1.0.4: has "^1.0.3" side-channel "^1.0.4" -interpret@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - is-alphabetical@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz#01072053ea7c1036df3c7d19a6daaec7f19e789b" @@ -4014,13 +3995,6 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== - dependencies: - resolve "^1.1.6" - refractor@^4.7.0: version "4.8.1" resolved "https://registry.yarnpkg.com/refractor/-/refractor-4.8.1.tgz#fbdd889333a3d86c9c864479622855c9b38e9d42" @@ -4168,7 +4142,7 @@ resolve-from@^4.0.0: resolved "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve@^1.1.6, resolve@^1.14.2, resolve@^1.22.1: +resolve@^1.14.2, resolve@^1.22.1: version "1.22.1" resolved "https://registry.npmmirror.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -4261,15 +4235,6 @@ shebang-regex@^3.0.0: resolved "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shelljs@0.8.5: - version "0.8.5" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" - integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - side-channel@^1.0.4: version "1.0.4" resolved "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -4304,6 +4269,11 @@ space-separated-tokens@^2.0.0: resolved "https://registry.npmmirror.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== +spark-md5@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/spark-md5/-/spark-md5-3.0.2.tgz#7952c4a30784347abcee73268e473b9c0167e3fc" + integrity sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw== + stable@^0.1.8: version "0.1.8" resolved "https://registry.npmmirror.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" From 3136d6d3fd945f672f134c6534b391dd9d853261 Mon Sep 17 00:00:00 2001 From: Yifei Zhang Date: Sun, 26 Mar 2023 06:57:13 +0000 Subject: [PATCH 3/4] fix: #10 replace export icon --- app/icons/export.svg | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/app/icons/export.svg b/app/icons/export.svg index 4c76b2c..d3ae520 100644 --- a/app/icons/export.svg +++ b/app/icons/export.svg @@ -1,24 +1 @@ - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file From d0d1673cccac3d75edf42a8ae617cfecfac864c6 Mon Sep 17 00:00:00 2001 From: Yifei Zhang Date: Sun, 26 Mar 2023 07:06:06 +0000 Subject: [PATCH 4/4] fixup: disable access control when CODE is empty --- app/components/settings.tsx | 30 +++++++++++++++++------------- middleware.ts | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/app/components/settings.tsx b/app/components/settings.tsx index ec22a1a..a0a477a 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -239,19 +239,23 @@ export function Settings(props: { closeSettings: () => void }) { - - { - accessStore.updateCode(e.currentTarget.value); - }} - > - + {enabledAccessControl ? ( + + { + accessStore.updateCode(e.currentTarget.value); + }} + > + + ) : ( + <> + )} 0 && !ACCESS_CODES.has(hashedCode)) { return NextResponse.json( { needAccessCode: true,