From bec04279aaaba8ed1ca007455d09f9184413344a Mon Sep 17 00:00:00 2001 From: sihuangwlp Date: Thu, 20 Jun 2024 14:15:49 +0800 Subject: [PATCH 1/4] Add AUTOMATIC1111_API_AUTH support --- backend/apps/images/main.py | 53 +++++++++++++------ backend/config.py | 5 ++ .../components/admin/Settings/Images.svelte | 28 +++++++++- src/lib/i18n/locales/zh-CN/translation.json | 4 ++ 4 files changed, 73 insertions(+), 17 deletions(-) diff --git a/backend/apps/images/main.py b/backend/apps/images/main.py index af7e5592d..07ae4083a 100644 --- a/backend/apps/images/main.py +++ b/backend/apps/images/main.py @@ -1,5 +1,6 @@ import re import requests +import base64 from fastapi import ( FastAPI, Request, @@ -36,6 +37,7 @@ from config import ( IMAGE_GENERATION_ENGINE, ENABLE_IMAGE_GENERATION, AUTOMATIC1111_BASE_URL, + AUTOMATIC1111_API_AUTH, COMFYUI_BASE_URL, COMFYUI_CFG_SCALE, COMFYUI_SAMPLER, @@ -49,7 +51,6 @@ from config import ( AppConfig, ) - log = logging.getLogger(__name__) log.setLevel(SRC_LOG_LEVELS["IMAGES"]) @@ -75,11 +76,10 @@ app.state.config.OPENAI_API_KEY = IMAGES_OPENAI_API_KEY app.state.config.MODEL = IMAGE_GENERATION_MODEL - app.state.config.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL +app.state.config.AUTOMATIC1111_API_AUTH = AUTOMATIC1111_API_AUTH app.state.config.COMFYUI_BASE_URL = COMFYUI_BASE_URL - app.state.config.IMAGE_SIZE = IMAGE_SIZE app.state.config.IMAGE_STEPS = IMAGE_STEPS app.state.config.COMFYUI_CFG_SCALE = COMFYUI_CFG_SCALE @@ -88,6 +88,16 @@ app.state.config.COMFYUI_SCHEDULER = COMFYUI_SCHEDULER app.state.config.COMFYUI_SD3 = COMFYUI_SD3 +def get_automatic1111_api_auth(): + if app.state.config.AUTOMATIC1111_API_AUTH == None: + return "" + else: + auth1111_byte_string = app.state.config.AUTOMATIC1111_API_AUTH.encode('utf-8') + auth1111_base64_encoded_bytes = base64.b64encode(auth1111_byte_string) + auth1111_base64_encoded_string = auth1111_base64_encoded_bytes.decode('utf-8') + return f"Basic {auth1111_base64_encoded_string}" + + @app.get("/config") async def get_config(request: Request, user=Depends(get_admin_user)): return { @@ -120,15 +130,15 @@ class EngineUrlUpdateForm(BaseModel): async def get_engine_url(user=Depends(get_admin_user)): return { "AUTOMATIC1111_BASE_URL": app.state.config.AUTOMATIC1111_BASE_URL, + "AUTOMATIC1111_API_AUTH": app.state.config.AUTOMATIC1111_API_AUTH, "COMFYUI_BASE_URL": app.state.config.COMFYUI_BASE_URL, } @app.post("/url/update") async def update_engine_url( - form_data: EngineUrlUpdateForm, user=Depends(get_admin_user) + form_data: EngineUrlUpdateForm, user=Depends(get_admin_user) ): - if form_data.AUTOMATIC1111_BASE_URL == None: app.state.config.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL else: @@ -150,8 +160,14 @@ async def update_engine_url( except Exception as e: raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e)) + if form_data.AUTOMATIC1111_API_AUTH == None: + app.state.config.AUTOMATIC1111_API_AUTH = AUTOMATIC1111_API_AUTH + else: + app.state.config.AUTOMATIC1111_API_AUTH = form_data.AUTOMATIC1111_API_AUTH + return { "AUTOMATIC1111_BASE_URL": app.state.config.AUTOMATIC1111_BASE_URL, + "AUTOMATIC1111_API_AUTH": app.state.config.AUTOMATIC1111_API_AUTH, "COMFYUI_BASE_URL": app.state.config.COMFYUI_BASE_URL, "status": True, } @@ -172,7 +188,7 @@ async def get_openai_config(user=Depends(get_admin_user)): @app.post("/openai/config/update") async def update_openai_config( - form_data: OpenAIConfigUpdateForm, user=Depends(get_admin_user) + form_data: OpenAIConfigUpdateForm, user=Depends(get_admin_user) ): if form_data.key == "": raise HTTPException(status_code=400, detail=ERROR_MESSAGES.API_KEY_NOT_FOUND) @@ -198,7 +214,7 @@ async def get_image_size(user=Depends(get_admin_user)): @app.post("/size/update") async def update_image_size( - form_data: ImageSizeUpdateForm, user=Depends(get_admin_user) + form_data: ImageSizeUpdateForm, user=Depends(get_admin_user) ): pattern = r"^\d+x\d+$" # Regular expression pattern if re.match(pattern, form_data.size): @@ -225,7 +241,7 @@ async def get_image_size(user=Depends(get_admin_user)): @app.post("/steps/update") async def update_image_size( - form_data: ImageStepsUpdateForm, user=Depends(get_admin_user) + form_data: ImageStepsUpdateForm, user=Depends(get_admin_user) ): if form_data.steps >= 0: app.state.config.IMAGE_STEPS = form_data.steps @@ -262,7 +278,8 @@ def get_models(user=Depends(get_current_user)): else: r = requests.get( - url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/sd-models" + url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/sd-models", + headers={"authorization": get_automatic1111_api_auth()} ) models = r.json() return list( @@ -289,7 +306,8 @@ async def get_default_model(user=Depends(get_admin_user)): return {"model": (app.state.config.MODEL if app.state.config.MODEL else "")} else: r = requests.get( - url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options" + url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options", + headers={"authorization": get_automatic1111_api_auth()} ) options = r.json() return {"model": options["sd_model_checkpoint"]} @@ -307,8 +325,10 @@ def set_model_handler(model: str): app.state.config.MODEL = model return app.state.config.MODEL else: + api_auth = get_automatic1111_api_auth() r = requests.get( - url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options" + url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options", + headers={"authorization": api_auth} ) options = r.json() @@ -317,6 +337,7 @@ def set_model_handler(model: str): r = requests.post( url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options", json=options, + headers={"authorization": api_auth}, ) return options @@ -324,8 +345,8 @@ def set_model_handler(model: str): @app.post("/models/default/update") def update_default_model( - form_data: UpdateModelForm, - user=Depends(get_current_user), + form_data: UpdateModelForm, + user=Depends(get_current_user), ): return set_model_handler(form_data.model) @@ -401,10 +422,9 @@ def save_url_image(url): @app.post("/generations") def generate_image( - form_data: GenerateImageForm, - user=Depends(get_current_user), + form_data: GenerateImageForm, + user=Depends(get_current_user), ): - width, height = tuple(map(int, app.state.config.IMAGE_SIZE.split("x"))) r = None @@ -519,6 +539,7 @@ def generate_image( r = requests.post( url=f"{app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/txt2img", json=data, + headers={"authorization": get_automatic1111_api_auth()}, ) res = r.json() diff --git a/backend/config.py b/backend/config.py index 1a38a450d..f91cee054 100644 --- a/backend/config.py +++ b/backend/config.py @@ -1001,6 +1001,11 @@ AUTOMATIC1111_BASE_URL = PersistentConfig( "image_generation.automatic1111.base_url", os.getenv("AUTOMATIC1111_BASE_URL", ""), ) +AUTOMATIC1111_API_AUTH = PersistentConfig( + "AUTOMATIC1111_API_AUTH", + "image_generation.automatic1111.api_auth", + os.getenv("AUTOMATIC1111_API_AUTH", ""), +) COMFYUI_BASE_URL = PersistentConfig( "COMFYUI_BASE_URL", diff --git a/src/lib/components/admin/Settings/Images.svelte b/src/lib/components/admin/Settings/Images.svelte index 0e4db533e..173efaf5f 100644 --- a/src/lib/components/admin/Settings/Images.svelte +++ b/src/lib/components/admin/Settings/Images.svelte @@ -29,6 +29,7 @@ let enableImageGeneration = false; let AUTOMATIC1111_BASE_URL = ''; + let AUTOMATIC1111_API_AUTH = ''; let COMFYUI_BASE_URL = ''; let OPENAI_API_BASE_URL = ''; @@ -75,6 +76,7 @@ } else { const res = await updateImageGenerationEngineUrls(localStorage.token, { AUTOMATIC1111_BASE_URL: AUTOMATIC1111_BASE_URL + AUTOMATIC1111_API_AUTH: AUTOMATIC1111_API_AUTH }).catch((error) => { toast.error(error); return null; @@ -82,6 +84,7 @@ if (res) { AUTOMATIC1111_BASE_URL = res.AUTOMATIC1111_BASE_URL; + AUTOMATIC1111_API_AUTH = res.AUTOMATIC1111_API_AUTH; await getModels(); @@ -89,7 +92,7 @@ toast.success($i18n.t('Server connection verified')); } } else { - ({ AUTOMATIC1111_BASE_URL } = await getImageGenerationEngineUrls(localStorage.token)); + ({ AUTOMATIC1111_BASE_URL,AUTOMATIC1111_API_AUTH } = await getImageGenerationEngineUrls(localStorage.token)); } } }; @@ -128,6 +131,7 @@ const URLS = await getImageGenerationEngineUrls(localStorage.token); AUTOMATIC1111_BASE_URL = URLS.AUTOMATIC1111_BASE_URL; + AUTOMATIC1111_API_AUTH = URLS.AUTOMATIC1111_API_AUTH; COMFYUI_BASE_URL = URLS.COMFYUI_BASE_URL; const config = await getOpenAIConfig(localStorage.token); @@ -270,6 +274,28 @@ {$i18n.t('(e.g. `sh webui.sh --api`)')} + +
{$i18n.t('AUTOMATIC1111 Api Auth String')}
+
+
+ +
+
+ +
+ {$i18n.t('Include `--api-auth` flag when running stable-diffusion-webui')} + + {$i18n.t('(e.g. `sh webui.sh --api --api-auth username:password`)')} + +
{:else if imageGenerationEngine === 'comfyui'}
{$i18n.t('ComfyUI Base URL')}
diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json index 40a51f0c2..3f94338c8 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -2,6 +2,7 @@ "'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' 或 '-1' 表示无过期时间。", "(Beta)": "(测试版)", "(e.g. `sh webui.sh --api`)": "(例如 `sh webui.sh --api`)", + "(e.g. `sh webui.sh --api --api-auth username:password`)": "(例如 `sh webui.sh --api --api-auth username:password`)", "(latest)": "(最新版)", "{{ models }}": "{{ models }}", "{{ owner }}: You cannot delete a base model": "{{ owner }}:您不能删除基础模型", @@ -63,6 +64,7 @@ "Audio": "语音", "August": "八月", "Auto-playback response": "自动念出回复内容", + "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api鉴权字符串", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 基础地址", "AUTOMATIC1111 Base URL is required.": "需要 AUTOMATIC1111 基础地址。", "available!": "版本可用!", @@ -211,6 +213,7 @@ "Enter stop sequence": "输入停止序列 (Stop Sequence)", "Enter Tavily API Key": "", "Enter Top K": "输入 Top K", + "Enter api auth string (e.g. username:password)": "输入api鉴权路径 (例如:username:password)", "Enter URL (e.g. http://127.0.0.1:7860/)": "输入地址 (例如:http://127.0.0.1:7860/)", "Enter URL (e.g. http://localhost:11434)": "输入地址 (例如:http://localhost:11434)", "Enter Your Email": "输入您的电子邮箱", @@ -265,6 +268,7 @@ "Import Models": "导入模型", "Import Prompts": "导入提示词", "Import Tools": "导入工具", + "Include `--api-auth` flag when running stable-diffusion-webui": "运行 stable-diffusion-webui 时包含 `--api-auth` 标志", "Include `--api` flag when running stable-diffusion-webui": "运行 stable-diffusion-webui 时包含 `--api` 标志", "Info": "信息", "Input commands": "输入命令", From d3160166e92812830664132d89b38265e2b6f9e1 Mon Sep 17 00:00:00 2001 From: sihuangwlp Date: Thu, 20 Jun 2024 14:38:13 +0800 Subject: [PATCH 2/4] Complete missing commas --- src/lib/components/admin/Settings/Images.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/admin/Settings/Images.svelte b/src/lib/components/admin/Settings/Images.svelte index 173efaf5f..7e0e5a7dd 100644 --- a/src/lib/components/admin/Settings/Images.svelte +++ b/src/lib/components/admin/Settings/Images.svelte @@ -75,7 +75,7 @@ } } else { const res = await updateImageGenerationEngineUrls(localStorage.token, { - AUTOMATIC1111_BASE_URL: AUTOMATIC1111_BASE_URL + AUTOMATIC1111_BASE_URL: AUTOMATIC1111_BASE_URL, AUTOMATIC1111_API_AUTH: AUTOMATIC1111_API_AUTH }).catch((error) => { toast.error(error); From e16ae92edc8c471a8bc66b33d4d2ae544317b231 Mon Sep 17 00:00:00 2001 From: sihuangwlp Date: Thu, 20 Jun 2024 14:53:38 +0800 Subject: [PATCH 3/4] complate missing field AUTOMATIC1111_API_AUTH --- backend/apps/images/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/apps/images/main.py b/backend/apps/images/main.py index 07ae4083a..a5690649a 100644 --- a/backend/apps/images/main.py +++ b/backend/apps/images/main.py @@ -123,6 +123,7 @@ async def update_config(form_data: ConfigUpdateForm, user=Depends(get_admin_user class EngineUrlUpdateForm(BaseModel): AUTOMATIC1111_BASE_URL: Optional[str] = None + AUTOMATIC1111_API_AUTH: Optional[str] = None COMFYUI_BASE_URL: Optional[str] = None From 36de6576b89bc52cea1411601b86c046c44eaa95 Mon Sep 17 00:00:00 2001 From: sihuangwlp Date: Thu, 20 Jun 2024 21:21:37 +0800 Subject: [PATCH 4/4] fix issue with i18n --- src/lib/components/admin/Settings/Images.svelte | 2 +- src/lib/i18n/locales/zh-CN/translation.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/components/admin/Settings/Images.svelte b/src/lib/components/admin/Settings/Images.svelte index 7e0e5a7dd..a6401031c 100644 --- a/src/lib/components/admin/Settings/Images.svelte +++ b/src/lib/components/admin/Settings/Images.svelte @@ -293,7 +293,7 @@ href="https://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/13993" target="_blank" > - {$i18n.t('(e.g. `sh webui.sh --api --api-auth username:password`)')} + {$i18n.t('(e.g. `sh webui.sh --api --api-auth username_password`)').replace('_',':')}
{:else if imageGenerationEngine === 'comfyui'} diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json index 3f94338c8..eab1c266e 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -2,7 +2,7 @@ "'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' 或 '-1' 表示无过期时间。", "(Beta)": "(测试版)", "(e.g. `sh webui.sh --api`)": "(例如 `sh webui.sh --api`)", - "(e.g. `sh webui.sh --api --api-auth username:password`)": "(例如 `sh webui.sh --api --api-auth username:password`)", + "(e.g. `sh webui.sh --api --api-auth username_password`)": "(例如 `sh webui.sh --api --api-auth username_password`)", "(latest)": "(最新版)", "{{ models }}": "{{ models }}", "{{ owner }}: You cannot delete a base model": "{{ owner }}:您不能删除基础模型",