patch auth-validators
This commit is contained in:
parent
a5dbefe757
commit
72de495c02
@ -1,5 +1,4 @@
|
|||||||
import httpx
|
import httpx
|
||||||
import re
|
|
||||||
from fastapi import Depends, Request, HTTPException, status
|
from fastapi import Depends, Request, HTTPException, status
|
||||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||||
from typing import List
|
from typing import List
|
||||||
@ -7,6 +6,7 @@ from typing import List
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from config import settings
|
from config import settings
|
||||||
from .ssl_transport import ssl_transport
|
from .ssl_transport import ssl_transport
|
||||||
|
from .validators import validate_username as core_validate_username, validate_password as core_validate_password
|
||||||
|
|
||||||
auth_scheme = HTTPBearer()
|
auth_scheme = HTTPBearer()
|
||||||
|
|
||||||
@ -86,54 +86,15 @@ def validate_username(value: str,
|
|||||||
- no consecutive underscores
|
- no consecutive underscores
|
||||||
- only [A-Za-z0-9_]
|
- only [A-Za-z0-9_]
|
||||||
"""
|
"""
|
||||||
# Проверка типа и длины
|
valid, result = core_validate_username(value, field_name, need_back=True, min_length=min_length, max_length=max_length)
|
||||||
if not isinstance(value, str) or not (min_length <= len(value) <= max_length):
|
if not valid:
|
||||||
msg = f"{field_name.capitalize()} must be between {min_length} and {max_length} characters long"
|
|
||||||
if with_httpexception:
|
if with_httpexception:
|
||||||
raise HTTPException(status_code=error_status_code, detail=error_detail)
|
raise HTTPException(status_code=error_status_code, detail=error_detail)
|
||||||
if need_back:
|
if need_back:
|
||||||
return False, msg
|
return False, result
|
||||||
raise ValueError(msg)
|
raise ValueError(result)
|
||||||
|
|
||||||
# Пробелы
|
return result if need_back else result
|
||||||
if any(c.isspace() for c in value):
|
|
||||||
msg = f"{field_name.capitalize()} must not contain whitespace characters"
|
|
||||||
if with_httpexception:
|
|
||||||
raise HTTPException(status_code=error_status_code, detail=error_detail)
|
|
||||||
if need_back:
|
|
||||||
return False, msg
|
|
||||||
raise ValueError(msg)
|
|
||||||
|
|
||||||
# Начинается с подчеркивания
|
|
||||||
if value.startswith('_'):
|
|
||||||
msg = f"{field_name.capitalize()} must not start with an underscore"
|
|
||||||
if with_httpexception:
|
|
||||||
raise HTTPException(status_code=error_status_code, detail=error_detail)
|
|
||||||
if need_back:
|
|
||||||
return False, msg
|
|
||||||
raise ValueError(msg)
|
|
||||||
|
|
||||||
# Двойные подчеркивания
|
|
||||||
if '__' in value:
|
|
||||||
msg = f"{field_name.capitalize()} must not contain consecutive underscores"
|
|
||||||
if with_httpexception:
|
|
||||||
raise HTTPException(status_code=error_status_code, detail=error_detail)
|
|
||||||
if need_back:
|
|
||||||
return False, msg
|
|
||||||
raise ValueError(msg)
|
|
||||||
|
|
||||||
# Только допустимые символы
|
|
||||||
if not re.fullmatch(r'[A-Za-z0-9_]+', value):
|
|
||||||
msg = f"{field_name.capitalize()} must contain only English letters, digits, and underscores"
|
|
||||||
if with_httpexception:
|
|
||||||
raise HTTPException(status_code=error_status_code, detail=error_detail)
|
|
||||||
if need_back:
|
|
||||||
return False, msg
|
|
||||||
raise ValueError(msg)
|
|
||||||
|
|
||||||
if need_back:
|
|
||||||
return True, value.lower()
|
|
||||||
return value.lower()
|
|
||||||
|
|
||||||
|
|
||||||
def validate_password(value: str,
|
def validate_password(value: str,
|
||||||
@ -149,27 +110,14 @@ def validate_password(value: str,
|
|||||||
Supports HTTPException raising if `with_httpexception=True`.
|
Supports HTTPException raising if `with_httpexception=True`.
|
||||||
Returns (True, value) or raises ValueError.
|
Returns (True, value) or raises ValueError.
|
||||||
"""
|
"""
|
||||||
# Проверка типа и длины
|
valid, result = core_validate_password(value, field_name, need_back=True, min_length=min_length, max_length=max_length)
|
||||||
if not isinstance(value, str) or not (min_length <= len(value) <= max_length):
|
if not valid:
|
||||||
msg = f"{field_name.capitalize()} must be between {min_length} and {max_length} characters long"
|
|
||||||
if with_httpexception:
|
if with_httpexception:
|
||||||
raise HTTPException(status_code=error_status_code, detail=error_detail)
|
raise HTTPException(status_code=error_status_code, detail=error_detail)
|
||||||
if need_back:
|
if need_back:
|
||||||
return False, msg
|
return False, result
|
||||||
raise ValueError(msg)
|
raise ValueError(result)
|
||||||
|
|
||||||
# if any(c.isspace() for c in value):
|
|
||||||
# raise ValueError(f"{field_name.capitalize()} must not contain whitespace characters")
|
|
||||||
|
|
||||||
# if not re.search(r'[A-Z]', value):
|
|
||||||
# raise ValueError(f"{field_name.capitalize()} must contain at least one uppercase letter")
|
|
||||||
|
|
||||||
# if not re.search(r'\d', value):
|
|
||||||
# raise ValueError(f"{field_name.capitalize()} must contain at least one digit")
|
|
||||||
|
|
||||||
# if not re.search(r'[!@#$%^&*()\-_=+\[\]{};:\'",.<>?/|\\]', value):
|
|
||||||
# raise ValueError(f"{field_name.capitalize()} must contain at least one special character")
|
|
||||||
|
|
||||||
if need_back:
|
if need_back:
|
||||||
return True, value
|
return True, value.lower()
|
||||||
return value
|
return value.lower()
|
||||||
|
|||||||
71
common_lib/utils/validators.py
Normal file
71
common_lib/utils/validators.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
def validate_username(value: str,
|
||||||
|
field_name: str = "login",
|
||||||
|
need_back=False,
|
||||||
|
min_length=3,
|
||||||
|
max_length=32) -> str:
|
||||||
|
"""
|
||||||
|
Username validator:
|
||||||
|
- checks for length
|
||||||
|
- no spaces
|
||||||
|
- no leading underscore
|
||||||
|
- no consecutive underscores
|
||||||
|
- only [A-Za-z0-9_]
|
||||||
|
"""
|
||||||
|
# Проверка типа и длины
|
||||||
|
if not isinstance(value, str) or not (min_length <= len(value) <= max_length):
|
||||||
|
msg = f"{field_name.capitalize()} must be between {min_length} and {max_length} characters long"
|
||||||
|
return (False, msg) if need_back else False
|
||||||
|
|
||||||
|
# Пробелы
|
||||||
|
if any(c.isspace() for c in value):
|
||||||
|
msg = f"{field_name.capitalize()} must not contain whitespace characters"
|
||||||
|
return (False, msg) if need_back else False
|
||||||
|
|
||||||
|
# Начинается с подчеркивания
|
||||||
|
if value.startswith('_'):
|
||||||
|
msg = f"{field_name.capitalize()} must not start with an underscore"
|
||||||
|
return (False, msg) if need_back else False
|
||||||
|
|
||||||
|
# Двойные подчеркивания
|
||||||
|
if '__' in value:
|
||||||
|
msg = f"{field_name.capitalize()} must not contain consecutive underscores"
|
||||||
|
return (False, msg) if need_back else False
|
||||||
|
|
||||||
|
# Только допустимые символы
|
||||||
|
if not re.fullmatch(r'[A-Za-z0-9_]+', value):
|
||||||
|
msg = f"{field_name.capitalize()} must contain only English letters, digits, and underscores"
|
||||||
|
return (False, msg) if need_back else False
|
||||||
|
|
||||||
|
return (True, value.lower()) if need_back else value.lower()
|
||||||
|
|
||||||
|
|
||||||
|
def validate_password(value: str,
|
||||||
|
field_name: str = "password",
|
||||||
|
need_back=False,
|
||||||
|
min_length=8,
|
||||||
|
max_length=128) -> str:
|
||||||
|
"""
|
||||||
|
Validates password length and (optionally) other rules.
|
||||||
|
Supports HTTPException raising if `with_httpexception=True`.
|
||||||
|
Returns (True, value) or raises ValueError.
|
||||||
|
"""
|
||||||
|
# Проверка типа и длины
|
||||||
|
if not isinstance(value, str) or not (min_length <= len(value) <= max_length):
|
||||||
|
msg = f"{field_name.capitalize()} must be between {min_length} and {max_length} characters long"
|
||||||
|
return (False, msg) if need_back else False
|
||||||
|
|
||||||
|
# if any(c.isspace() for c in value):
|
||||||
|
# raise ValueError(f"{field_name.capitalize()} must not contain whitespace characters")
|
||||||
|
|
||||||
|
# if not re.search(r'[A-Z]', value):
|
||||||
|
# raise ValueError(f"{field_name.capitalize()} must contain at least one uppercase letter")
|
||||||
|
|
||||||
|
# if not re.search(r'\d', value):
|
||||||
|
# raise ValueError(f"{field_name.capitalize()} must contain at least one digit")
|
||||||
|
|
||||||
|
# if not re.search(r'[!@#$%^&*()\-_=+\[\]{};:\'",.<>?/|\\]', value):
|
||||||
|
# raise ValueError(f"{field_name.capitalize()} must contain at least one special character")
|
||||||
|
|
||||||
|
return (True, value) if need_back else value
|
||||||
@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "common-lib"
|
name = "common-lib"
|
||||||
version = "0.0.14"
|
version = "0.0.15"
|
||||||
description = "Библиотека общих компонентов для микросервисов yobble"
|
description = "Библиотека общих компонентов для микросервисов yobble"
|
||||||
authors = [{ name = "cheykrym", email = "you@example.com" }]
|
authors = [{ name = "cheykrym", email = "you@example.com" }]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user