From caf8482fba5d95eeea370b4a8a5fdb8f3f3a1b18 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 9 Aug 2025 21:34:47 +0400 Subject: [PATCH] refac --- backend/open_webui/routers/users.py | 50 ++++++++++++++++++++++++++-- static/static/user.png | Bin 0 -> 7858 bytes static/user.png | Bin 6037 -> 7858 bytes 3 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 static/static/user.png diff --git a/backend/open_webui/routers/users.py b/backend/open_webui/routers/users.py index e936fa1838..4bb6956f29 100644 --- a/backend/open_webui/routers/users.py +++ b/backend/open_webui/routers/users.py @@ -1,5 +1,13 @@ import logging from typing import Optional +import base64 +import io + + +from fastapi import APIRouter, Depends, HTTPException, Request, status +from fastapi.responses import Response, StreamingResponse, FileResponse +from pydantic import BaseModel + from open_webui.models.auths import Auths from open_webui.models.groups import Groups @@ -21,9 +29,8 @@ from open_webui.socket.main import ( get_user_active_status, ) from open_webui.constants import ERROR_MESSAGES -from open_webui.env import SRC_LOG_LEVELS -from fastapi import APIRouter, Depends, HTTPException, Request, status -from pydantic import BaseModel +from open_webui.env import SRC_LOG_LEVELS, STATIC_DIR + from open_webui.utils.auth import get_admin_user, get_password_hash, get_verified_user from open_webui.utils.access_control import get_permissions, has_permission @@ -329,6 +336,43 @@ async def get_user_by_id(user_id: str, user=Depends(get_verified_user)): ) +############################ +# GetUserProfileImageById +############################ + + +@router.get("/{user_id}/profile/image") +async def get_user_profile_image_by_id(user_id: str, user=Depends(get_verified_user)): + user = Users.get_user_by_id(user_id) + if user: + if user.profile_image_url: + # check if it's url or base64 + if user.profile_image_url.startswith("http"): + return Response( + status_code=status.HTTP_302_FOUND, + headers={"Location": user.profile_image_url}, + ) + elif user.profile_image_url.startswith("data:image"): + try: + header, base64_data = user.profile_image_url.split(",", 1) + image_data = base64.b64decode(base64_data) + image_buffer = io.BytesIO(image_data) + + return StreamingResponse( + image_buffer, + media_type="image/png", + headers={"Content-Disposition": "inline; filename=image.png"}, + ) + except Exception as e: + pass + return FileResponse(f"{STATIC_DIR}/user.png") + else: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.USER_NOT_FOUND, + ) + + ############################ # GetUserActiveStatusById ############################ diff --git a/static/static/user.png b/static/static/user.png new file mode 100644 index 0000000000000000000000000000000000000000..7bdc70d159cfb0a032bec208e3775ab82755b299 GIT binary patch literal 7858 zcmY*-2{e@N`~Dc)*oTs}j5kZ!36U_vU_{84E&G~%mwk(&Fr(~bn?ypE>`O5iAsIr} zlI0_z8TapoaemfzV7FKp6h+jd*0{1t|S9JEhc(ydJqW2q>Vxvf%?X_^Bh(PxmZ_GVZ|8-~b#*eM@ zbKLeOf2JumUu~VFF^f*}CKS>(hpdwBG}z<+mgyn-l;u$9~7c{PI#{V$#W z&bjr!_*g>!KS6r~jCllHH98)0K^=Kf!T%qIcD7UE4Kx7YC}fbUiyPq7wB@l>vsZ)L ztH~$O89Q#>e4h+BUG8~N#?b@A%MUrO zu&^*Q>qnlwn_S;L8W{a_w$e9kDDG^0&s{(sIn-ySg9drGQaGY*SAw(=4v-|)mtdoc zjm^yht9exwS)05hG8(kUMa1Hve z#+kvt9|n`1ni~$oBkDS=M6Uy|TK>if?lO?fjt#v9Wx5?W#n*G|U{amD`bBuL;1a1~ zA6R@O0-T-ZRV5CNEkBjHUP~&L=tM+a{gU zJ0E$>=X=zAdC2$}0#i@4LrRQDK2pYc-=0?z1}eO>5}6s?IG78Q(F*&=VFMG>?ShTV zAQ@X@^P6>y_hKI1Y4$uyJuu)tJ8E^uHPJq!!KUz6wLC{6ivl@0_pD^!@qdMXt11j0 zR=pi*09{RAtt{Qupm~ioXgdCMm={A3N3UdGcj8#jO6l@C`6!4);ui`%zo^r3mUhu7 zQY;;V#<6cVA9Y5w&!OPR*}=nH4XRW5W;$4hChlYPcp*M4OUMf;h#O{UV2 z=;F`6<$jL<>5W>mZi`xmP7%CWV#8TniJUDiG%^)WZ^qrDU=xw3ujW-Ah#qAs-);?4 zlvVu*6LEShm&*VvJh7Kg5XFUTob;yfAeWXso__QRJN-C+rCPn-@l3~|H(meiB%R;hFF5`7L=#UmK19Ut`ZIa4t;M^2wKi1XbhSSq%dIreJ0D{aFjWNvth+`i9Rs7oc_3siS< z-qid7vNv~cYZV64b&DQ&vwRnfP^{)>>mG{Z6q2fR8S!3gc~MbkmHv5f0Bi^12k@Wg z>zf5gWcko9mj&+6o7Pwdak_?vnfG*OczlEXveG!cF_{Bk~j!{>kIJ6@1t z0y-PQz6k=W47tzwzkW~C5@Lx33CWvTbZj`ZOMy^np4x4sR(KVb&KXKY@m;3;btsUI zbD&%sNK{5$V4Rrtb{^n6gcf3V7UamG2yf8M<#Q_dBA9_h2mCtw*xP%lNPh@5`+6P?GrPD z@gk{OKJb5*6`|i0%=3`(j_n_+OEyjS(j@vD7ASV`@Q;2;L9ZM^P%b$_zsUV1=U%q# z9LfqGZE>4j)!=WQR?@tL{`IOC>%S_Gh@1p!x#611N zcc|S1y8Tix>AZ}#!}{IFKOgw976-d+{$pB_l{3xu=*weWe3sBH?nLP!UPAtyHyXEQ z3p)>Tpru~>BY@UNZf3gFd`?~&(I93rf)}+Ih@(2L$+(&23d%!?;_CH4&DUs9YC%Kz zR)+xBduhHK>20@Y+*hPh>&}XtS=6YwlQL_jZ_OW4k^o|JC4X)ApG&JUv=sK^A4%rN zB>yZ`s4zgBmSJUe?!qZiKzl4^UN^bmh`g~Otk~^CwrM&XwUdogv9!hT)|-t!*+fCS z(rQQ4cN+A~V|>dHB74fUBWU^2G3yMk{BMc-M#3B>o~Zt(w6*wmwoTu@bdy^sN#0IK z>q$Ab%X|VtC6Kgv_r%$l6LZlSqgXzq998uq+fn}Ye_`MJu}d#9x_#rCB`j3}+a&bbIf4yCFt0_i&Mck;PIx#6W<-Nc zvf|*`qJ#lIMw-e}FBi~WpzPM&u2aFwSUznu9)7IeGz5oYr=&J@xd`-J_Zy8RgdjXB z0qG4aV!6ziK-iK(G6O^n>GA89a0U8>8^!lAIImWj4-Br0^4;z0*uC+FYKb>yKtuwD z<}V_5*B^(nOtr_{wX~IOjfQz}zONhi+ZxCnqX0~7hYjvRhco3&Gv^v *S`Cr$hj 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 literal 0 HcmV?d00001 diff --git a/static/user.png b/static/user.png index 2771e7286684e0935f952ef671dfe1f75f422256..7bdc70d159cfb0a032bec208e3775ab82755b299 100644 GIT binary patch literal 7858 zcmY*-2{e@N`~Dc)*oTs}j5kZ!36U_vU_{84E&G~%mwk(&Fr(~bn?ypE>`O5iAsIr} zlI0_z8TapoaemfzV7FKp6h+jd*0{1t|S9JEhc(ydJqW2q>Vxvf%?X_^Bh(PxmZ_GVZ|8-~b#*eM@ zbKLeOf2JumUu~VFF^f*}CKS>(hpdwBG}z<+mgyn-l;u$9~7c{PI#{V$#W z&bjr!_*g>!KS6r~jCllHH98)0K^=Kf!T%qIcD7UE4Kx7YC}fbUiyPq7wB@l>vsZ)L ztH~$O89Q#>e4h+BUG8~N#?b@A%MUrO zu&^*Q>qnlwn_S;L8W{a_w$e9kDDG^0&s{(sIn-ySg9drGQaGY*SAw(=4v-|)mtdoc zjm^yht9exwS)05hG8(kUMa1Hve z#+kvt9|n`1ni~$oBkDS=M6Uy|TK>if?lO?fjt#v9Wx5?W#n*G|U{amD`bBuL;1a1~ zA6R@O0-T-ZRV5CNEkBjHUP~&L=tM+a{gU zJ0E$>=X=zAdC2$}0#i@4LrRQDK2pYc-=0?z1}eO>5}6s?IG78Q(F*&=VFMG>?ShTV zAQ@X@^P6>y_hKI1Y4$uyJuu)tJ8E^uHPJq!!KUz6wLC{6ivl@0_pD^!@qdMXt11j0 zR=pi*09{RAtt{Qupm~ioXgdCMm={A3N3UdGcj8#jO6l@C`6!4);ui`%zo^r3mUhu7 zQY;;V#<6cVA9Y5w&!OPR*}=nH4XRW5W;$4hChlYPcp*M4OUMf;h#O{UV2 z=;F`6<$jL<>5W>mZi`xmP7%CWV#8TniJUDiG%^)WZ^qrDU=xw3ujW-Ah#qAs-);?4 zlvVu*6LEShm&*VvJh7Kg5XFUTob;yfAeWXso__QRJN-C+rCPn-@l3~|H(meiB%R;hFF5`7L=#UmK19Ut`ZIa4t;M^2wKi1XbhSSq%dIreJ0D{aFjWNvth+`i9Rs7oc_3siS< z-qid7vNv~cYZV64b&DQ&vwRnfP^{)>>mG{Z6q2fR8S!3gc~MbkmHv5f0Bi^12k@Wg z>zf5gWcko9mj&+6o7Pwdak_?vnfG*OczlEXveG!cF_{Bk~j!{>kIJ6@1t z0y-PQz6k=W47tzwzkW~C5@Lx33CWvTbZj`ZOMy^np4x4sR(KVb&KXKY@m;3;btsUI zbD&%sNK{5$V4Rrtb{^n6gcf3V7UamG2yf8M<#Q_dBA9_h2mCtw*xP%lNPh@5`+6P?GrPD z@gk{OKJb5*6`|i0%=3`(j_n_+OEyjS(j@vD7ASV`@Q;2;L9ZM^P%b$_zsUV1=U%q# z9LfqGZE>4j)!=WQR?@tL{`IOC>%S_Gh@1p!x#611N zcc|S1y8Tix>AZ}#!}{IFKOgw976-d+{$pB_l{3xu=*weWe3sBH?nLP!UPAtyHyXEQ z3p)>Tpru~>BY@UNZf3gFd`?~&(I93rf)}+Ih@(2L$+(&23d%!?;_CH4&DUs9YC%Kz zR)+xBduhHK>20@Y+*hPh>&}XtS=6YwlQL_jZ_OW4k^o|JC4X)ApG&JUv=sK^A4%rN zB>yZ`s4zgBmSJUe?!qZiKzl4^UN^bmh`g~Otk~^CwrM&XwUdogv9!hT)|-t!*+fCS z(rQQ4cN+A~V|>dHB74fUBWU^2G3yMk{BMc-M#3B>o~Zt(w6*wmwoTu@bdy^sN#0IK z>q$Ab%X|VtC6Kgv_r%$l6LZlSqgXzq998uq+fn}Ye_`MJu}d#9x_#rCB`j3}+a&bbIf4yCFt0_i&Mck;PIx#6W<-Nc zvf|*`qJ#lIMw-e}FBi~WpzPM&u2aFwSUznu9)7IeGz5oYr=&J@xd`-J_Zy8RgdjXB z0qG4aV!6ziK-iK(G6O^n>GA89a0U8>8^!lAIImWj4-Br0^4;z0*uC+FYKb>yKtuwD z<}V_5*B^(nOtr_{wX~IOjfQz}zONhi+ZxCnqX0~7hYjvRhco3&Gv^v *S`Cr$hj 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 literal 6037 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