From f1199eb6ca90a26f299efe139bc49f7ff1be62a8 Mon Sep 17 00:00:00 2001 From: MiXaiLL76 Date: Tue, 31 Mar 2026 00:29:16 +0300 Subject: [PATCH] back to format --- backend/open_webui/models/auths.py | 41 ++++---- backend/open_webui/routers/auths.py | 152 +++++++++++++++------------- 2 files changed, 104 insertions(+), 89 deletions(-) diff --git a/backend/open_webui/models/auths.py b/backend/open_webui/models/auths.py index c6d09a398d..5d7c084296 100644 --- a/backend/open_webui/models/auths.py +++ b/backend/open_webui/models/auths.py @@ -1,13 +1,14 @@ import logging import uuid +from typing import Optional -from open_webui.internal.db import Base, get_db_context +from sqlalchemy.exc import IntegrityError +from sqlalchemy.orm import Session +from open_webui.internal.db import Base, JSONField, get_db, get_db_context from open_webui.models.users import User, UserModel, UserProfileImageResponse, Users from open_webui.utils.validate import validate_profile_image_url from pydantic import BaseModel, field_validator from sqlalchemy import Boolean, Column, String, Text -from sqlalchemy.exc import IntegrityError -from sqlalchemy.orm import Session log = logging.getLogger(__name__) @@ -43,7 +44,7 @@ class Token(BaseModel): class ApiKey(BaseModel): - api_key: str | None = None + api_key: Optional[str] = None class SigninResponse(Token, UserProfileImageResponse): @@ -73,18 +74,18 @@ class SignupForm(BaseModel): name: str email: str password: str - profile_image_url: str | None = '/user.png' + profile_image_url: Optional[str] = '/user.png' @field_validator('profile_image_url') @classmethod - def check_profile_image_url(cls, v: str | None) -> str | None: + def check_profile_image_url(cls, v: Optional[str]) -> Optional[str]: if v is not None: return validate_profile_image_url(v) return v class AddUserForm(SignupForm): - role: str | None = 'pending' + role: Optional[str] = 'pending' class AuthsTable: @@ -95,10 +96,10 @@ class AuthsTable: name: str, profile_image_url: str = '/user.png', role: str = 'pending', - oauth: dict | None = None, - db: Session | None = None, - id: str | None = None, - ) -> UserModel | None: + oauth: Optional[dict] = None, + db: Optional[Session] = None, + id: Optional[str] = None, + ) -> Optional[UserModel]: with get_db_context(db) as db: log.info('insert_new_auth') @@ -156,7 +157,9 @@ class AuthsTable: log.error(f'Failed to insert auth: {str(e)}') return None - def authenticate_user(self, email: str, verify_password: callable, db: Session | None = None) -> UserModel | None: + def authenticate_user( + self, email: str, verify_password: callable, db: Optional[Session] = None + ) -> Optional[UserModel]: log.info(f'authenticate_user: {email}') user = Users.get_user_by_email(email, db=db) @@ -176,8 +179,8 @@ class AuthsTable: except Exception: return None - def authenticate_user_by_api_key(self, api_key: str, db: Session | None = None) -> UserModel | None: - log.info('authenticate_user_by_api_key') + def authenticate_user_by_api_key(self, api_key: str, db: Optional[Session] = None) -> Optional[UserModel]: + log.info(f'authenticate_user_by_api_key') # if no api_key, return None if not api_key: return None @@ -188,7 +191,7 @@ class AuthsTable: except Exception: return False - def authenticate_user_by_email(self, email: str, db: Session | None = None) -> UserModel | None: + def authenticate_user_by_email(self, email: str, db: Optional[Session] = None) -> Optional[UserModel]: log.info(f'authenticate_user_by_email: {email}') try: with get_db_context(db) as db: @@ -206,7 +209,7 @@ class AuthsTable: except Exception: return None - def update_user_password_by_id(self, id: str, new_password: str, db: Session | None = None) -> bool: + def update_user_password_by_id(self, id: str, new_password: str, db: Optional[Session] = None) -> bool: try: with get_db_context(db) as db: result = db.query(Auth).filter_by(id=id).update({'password': new_password}) @@ -215,7 +218,7 @@ class AuthsTable: except Exception: return False - def update_email_by_id(self, id: str, email: str, db: Session | None = None) -> bool: + def update_email_by_id(self, id: str, email: str, db: Optional[Session] = None) -> bool: try: with get_db_context(db) as db: result = db.query(Auth).filter_by(id=id).update({'email': email}) @@ -227,7 +230,7 @@ class AuthsTable: except Exception: return False - def delete_auth_by_id(self, id: str, db: Session | None = None) -> bool: + def delete_auth_by_id(self, id: str, db: Optional[Session] = None) -> bool: try: with get_db_context(db) as db: # Delete User @@ -244,4 +247,4 @@ class AuthsTable: return False -Auths = AuthsTable() +Auths = AuthsTable() \ No newline at end of file diff --git a/backend/open_webui/routers/auths.py b/backend/open_webui/routers/auths.py index 1103f22e7d..0d290c3907 100644 --- a/backend/open_webui/routers/auths.py +++ b/backend/open_webui/routers/auths.py @@ -1,79 +1,91 @@ import asyncio +import re +import uuid +import time import datetime import logging -import re -import time -import urllib -import uuid -from ssl import CERT_NONE, CERT_REQUIRED, PROTOCOL_TLS - from aiohttp import ClientSession -from fastapi import APIRouter, Depends, HTTPException, Request, status -from fastapi.responses import JSONResponse, Response -from ldap3 import NONE, Connection, Server, Tls -from ldap3.utils.conv import escape_filter_chars -from open_webui.config import ( - ENABLE_PASSWORD_AUTH, - OAUTH_MERGE_ACCOUNTS_BY_EMAIL, - OAUTH_PROVIDERS, - OPENID_END_SESSION_ENDPOINT, - OPENID_PROVIDER_URL, -) -from open_webui.constants import ERROR_MESSAGES, WEBHOOK_MESSAGES -from open_webui.env import ( - ENABLE_INITIAL_ADMIN_SIGNUP, - ENABLE_OAUTH_TOKEN_EXCHANGE, - WEBUI_AUTH, - WEBUI_AUTH_COOKIE_SAME_SITE, - WEBUI_AUTH_COOKIE_SECURE, - WEBUI_AUTH_SIGNOUT_REDIRECT_URL, - WEBUI_AUTH_TRUSTED_EMAIL_HEADER, - WEBUI_AUTH_TRUSTED_GROUPS_HEADER, - WEBUI_AUTH_TRUSTED_NAME_HEADER, - WEBUI_AUTH_TRUSTED_ROLE_HEADER, -) -from open_webui.internal.db import get_session +import urllib + + from open_webui.models.auths import ( AddUserForm, ApiKey, Auths, + Token, LdapForm, SigninForm, SigninResponse, SignupForm, - Token, UpdatePasswordForm, ) -from open_webui.models.groups import Groups -from open_webui.models.oauth_sessions import OAuthSessions from open_webui.models.users import ( - UpdateProfileForm, UserModel, UserProfileImageResponse, Users, + UpdateProfileForm, UserStatus, ) -from open_webui.utils.access_control import get_permissions, has_permission +from open_webui.models.groups import Groups +from open_webui.models.oauth_sessions import OAuthSessions + +from open_webui.constants import ERROR_MESSAGES, WEBHOOK_MESSAGES +from open_webui.env import ( + WEBUI_AUTH, + WEBUI_AUTH_TRUSTED_EMAIL_HEADER, + WEBUI_AUTH_TRUSTED_NAME_HEADER, + WEBUI_AUTH_TRUSTED_GROUPS_HEADER, + WEBUI_AUTH_TRUSTED_ROLE_HEADER, + WEBUI_AUTH_COOKIE_SAME_SITE, + WEBUI_AUTH_COOKIE_SECURE, + WEBUI_AUTH_SIGNOUT_REDIRECT_URL, + ENABLE_INITIAL_ADMIN_SIGNUP, + ENABLE_OAUTH_TOKEN_EXCHANGE, + AIOHTTP_CLIENT_SESSION_SSL, +) +from fastapi import APIRouter, Depends, HTTPException, Request, status +from fastapi.responses import RedirectResponse, Response, JSONResponse +from open_webui.config import ( + OPENID_PROVIDER_URL, + OPENID_END_SESSION_ENDPOINT, + ENABLE_OAUTH_SIGNUP, + ENABLE_LDAP, + ENABLE_PASSWORD_AUTH, + OAUTH_PROVIDERS, + OAUTH_MERGE_ACCOUNTS_BY_EMAIL, +) +from pydantic import BaseModel + +from open_webui.utils.misc import parse_duration, validate_email_format from open_webui.utils.auth import ( - create_api_key, - create_token, - decode_token, - get_admin_user, - get_current_user, - get_http_authorization_cred, - get_password_hash, - get_verified_user, - invalidate_token, validate_password, verify_password, + decode_token, + invalidate_token, + create_api_key, + create_token, + get_admin_user, + get_verified_user, + get_current_user, + get_password_hash, + get_http_authorization_cred, ) -from open_webui.utils.groups import apply_default_group_assignment -from open_webui.utils.misc import parse_duration, validate_email_format -from open_webui.utils.rate_limit import RateLimiter -from open_webui.utils.redis import get_redis_client -from open_webui.utils.webhook import post_webhook -from pydantic import BaseModel +from open_webui.internal.db import get_session from sqlalchemy.orm import Session +from open_webui.utils.webhook import post_webhook +from open_webui.utils.access_control import get_permissions, has_permission +from open_webui.utils.groups import apply_default_group_assignment + +from open_webui.utils.redis import get_redis_client +from open_webui.utils.rate_limit import RateLimiter + + +from typing import Optional, List + +from ssl import CERT_NONE, CERT_REQUIRED, PROTOCOL_TLS + +from ldap3 import Server, Connection, NONE, Tls +from ldap3.utils.conv import escape_filter_chars router = APIRouter() @@ -107,7 +119,7 @@ def create_session_response(request: Request, user, db, response: Response = Non ) if set_cookie and response: - datetime_expires_at = datetime.datetime.fromtimestamp(expires_at, datetime.UTC) if expires_at else None + datetime_expires_at = datetime.datetime.fromtimestamp(expires_at, datetime.timezone.utc) if expires_at else None max_age = int(expires_delta.total_seconds()) if expires_delta else None response.set_cookie( key='token', @@ -140,14 +152,14 @@ def create_session_response(request: Request, user, db, response: Response = Non class SessionUserResponse(Token, UserProfileImageResponse): - expires_at: int | None = None - permissions: dict | None = None + expires_at: Optional[int] = None + permissions: Optional[dict] = None class SessionUserInfoResponse(SessionUserResponse, UserStatus): - bio: str | None = None - gender: str | None = None - date_of_birth: datetime.date | None = None + bio: Optional[str] = None + gender: Optional[str] = None + date_of_birth: Optional[datetime.date] = None @router.get('/', response_model=SessionUserInfoResponse) @@ -178,7 +190,7 @@ async def get_session_user( response.set_cookie( key='token', value=token, - expires=(datetime.datetime.fromtimestamp(expires_at, datetime.UTC) if expires_at else None), + expires=(datetime.datetime.fromtimestamp(expires_at, datetime.timezone.utc) if expires_at else None), httponly=True, # Ensures the cookie is not accessible via JavaScript samesite=WEBUI_AUTH_COOKIE_SAME_SITE, secure=WEBUI_AUTH_COOKIE_SECURE, @@ -617,7 +629,7 @@ async def signin( name = request.headers.get(WEBUI_AUTH_TRUSTED_NAME_HEADER, email) try: name = urllib.parse.unquote(name, encoding='utf-8') - except Exception: + except Exception as e: pass if not Users.get_user_by_email(email.lower(), db=db): @@ -1024,7 +1036,7 @@ async def get_admin_config(request: Request, user=Depends(get_admin_user)): class AdminConfig(BaseModel): SHOW_ADMIN_DETAILS: bool - ADMIN_EMAIL: str | None = None + ADMIN_EMAIL: Optional[str] = None WEBUI_URL: str ENABLE_SIGNUP: bool ENABLE_API_KEYS: bool @@ -1036,15 +1048,15 @@ class AdminConfig(BaseModel): ENABLE_COMMUNITY_SHARING: bool ENABLE_MESSAGE_RATING: bool ENABLE_FOLDERS: bool - FOLDER_MAX_FILE_COUNT: int | str | None = None + FOLDER_MAX_FILE_COUNT: Optional[int | str] = None ENABLE_CHANNELS: bool ENABLE_MEMORIES: bool ENABLE_NOTES: bool ENABLE_USER_WEBHOOKS: bool ENABLE_USER_STATUS: bool - PENDING_USER_OVERLAY_TITLE: str | None = None - PENDING_USER_OVERLAY_CONTENT: str | None = None - RESPONSE_WATERMARK: str | None = None + PENDING_USER_OVERLAY_TITLE: Optional[str] = None + PENDING_USER_OVERLAY_CONTENT: Optional[str] = None + RESPONSE_WATERMARK: Optional[str] = None @router.post('/admin/config') @@ -1117,7 +1129,7 @@ async def update_admin_config(request: Request, form_data: AdminConfig, user=Dep class LdapServerConfig(BaseModel): label: str host: str - port: int | None = None + port: Optional[int] = None attribute_for_mail: str = 'mail' attribute_for_username: str = 'uid' app_dn: str @@ -1125,9 +1137,9 @@ class LdapServerConfig(BaseModel): search_base: str search_filters: str = '' use_tls: bool = True - certificate_path: str | None = None + certificate_path: Optional[str] = None validate_cert: bool = True - ciphers: str | None = 'ALL' + ciphers: Optional[str] = 'ALL' @router.get('/admin/config/ldap/server', response_model=LdapServerConfig) @@ -1200,7 +1212,7 @@ async def get_ldap_config(request: Request, user=Depends(get_admin_user)): class LdapConfigForm(BaseModel): - enable_ldap: bool | None = None + enable_ldap: Optional[bool] = None @router.post('/admin/config/ldap') @@ -1323,7 +1335,7 @@ async def token_exchange( # Get sub claim sub = user_data.get(request.app.state.config.OAUTH_SUB_CLAIM or OAUTH_PROVIDERS[provider].get('sub_claim', 'sub')) if not sub: - log.warning('Token exchange failed: sub claim missing from user data') + log.warning(f'Token exchange failed: sub claim missing from user data') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Token missing required 'sub' claim", @@ -1331,7 +1343,7 @@ async def token_exchange( email = user_data.get(email_claim, '') if not email: - log.warning('Token exchange failed: email claim missing from user data') + log.warning(f'Token exchange failed: email claim missing from user data') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Token missing required email claim',