diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d306ce76..b46cf6d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,6 +25,8 @@ jobs: - uses: pre-commit/action@v3.0.0 with: extra_args: --all-files --verbose + - name: Mypy check + run: bash scripts/mypy.sh test: name: test on python ${{ matrix.python-version }} runs-on: ubuntu-latest diff --git a/authx/_internal/_session.py b/authx/_internal/_session.py new file mode 100644 index 00000000..f2805033 --- /dev/null +++ b/authx/_internal/_session.py @@ -0,0 +1,41 @@ +from datetime import timedelta +from typing import Callable, Optional +from uuid import uuid4 + +from pydantic_settings import BaseSettings + + +def genSessionId() -> str: + return uuid4().hex + + +settings = {"sessionIdGenerator": genSessionId} + + +class Config(BaseSettings): + redisURL: str = "redis://localhost:6379/0" + settings: dict = settings + sessionIdName: str = "ssid" + expireTime: timedelta = timedelta(hours=6) + + def genSessionId(self) -> str: + return self.settings["sessionIdGenerator"]() + + +config = Config() + + +def basicConfig( + redisURL: Optional[str] = "", + sessionIdName: Optional[str] = "", + sessionIdGenerator: Optional[Callable[[], str]] = None, + expireTime: Optional[timedelta] = None, +): + if redisURL: + config.redisURL = redisURL + if sessionIdName: + config.sessionIdName = sessionIdName + if sessionIdGenerator: + config.settings["sessionIdGenerator"] = sessionIdGenerator + if expireTime: + config.expireTime = expireTime diff --git a/authx/config.py b/authx/config.py index 9f23b3ca..a302c8de 100644 --- a/authx/config.py +++ b/authx/config.py @@ -2,7 +2,8 @@ from typing import List, Optional, Sequence from jwt.algorithms import get_default_algorithms, requires_cryptography -from pydantic import BaseSettings, Field +from pydantic import Field +from pydantic_settings import BaseSettings from authx.exceptions import BadConfigurationError from authx.types import AlgorithmType, HTTPMethods, SameSitePolicy, StringOrSequence, TokenLocations diff --git a/authx/schema.py b/authx/schema.py index 862f1952..2cea37b3 100644 --- a/authx/schema.py +++ b/authx/schema.py @@ -2,7 +2,7 @@ from hmac import compare_digest from typing import Any, Dict, List, Optional, Sequence -from pydantic import BaseModel, Extra, Field, ValidationError, validator +from pydantic import BaseModel, ConfigDict, Field, ValidationError, validator from authx._internal._utils import get_now, get_now_ts, get_uuid from authx.exceptions import ( @@ -18,6 +18,8 @@ class TokenPayload(BaseModel): + model_config = ConfigDict(extra='allow') + jti: Optional[str] = Field(default_factory=get_uuid) iss: Optional[str] = None sub: Optional[str] = None @@ -30,16 +32,13 @@ class TokenPayload(BaseModel): scopes: Optional[List[str]] = None fresh: bool = False - class Config: - extra = Extra.allow - @property def _additional_fields(self): return set(self.__dict__) - set(self.__fields__) @property def extra_dict(self): - return self.dict(include=self._additional_fields) + return self.model_dump(include=self._additional_fields) @property def issued_at(self) -> datetime.datetime: @@ -122,7 +121,7 @@ def decode( issuer=issuer, verify=verify, ) - return cls.parse_obj(payload) + return cls.model_validate(payload) class RequestToken(BaseModel): @@ -153,7 +152,7 @@ def verify( issuer=issuer, ) # Parse payload - payload = TokenPayload.parse_obj(decoded_token) + payload = TokenPayload.model_validate(decoded_token) except JWTDecodeError as e: raise JWTDecodeError(*e.args) from e except ValidationError as e: diff --git a/pyproject.toml b/pyproject.toml index 5a354c2a..47d34803 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,9 +46,9 @@ classifiers = [ ] dependencies = [ - "fastapi >=0.65.2,<0.99.0", + "fastapi >=0.65.2,<0.200.0", "pyjwt[crypto] >=2.6.0,<3.0.0", - "pydantic >=1.7.4,!=1.8,!=1.8.1,<2.0.0", + "pydantic >=2.0.3" ] dynamic = ["version"] diff --git a/requirements/docs.txt b/requirements/docs.txt index 7b04c838..7a53b48d 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -4,13 +4,13 @@ # # pip-compile --output-file=requirements/docs.txt requirements/docs.in # -babel==2.13.0 +babel==2.13.1 # via mkdocs-material beautifulsoup4==4.12.2 # via mkdocs-mermaid2-plugin certifi==2023.7.22 # via requests -charset-normalizer==3.3.0 +charset-normalizer==3.3.2 # via requests click==8.1.7 # via @@ -36,9 +36,9 @@ jinja2==3.1.2 # -r requirements/docs.in # mkdocs # mkdocs-material -jsbeautifier==1.14.9 +jsbeautifier==1.14.11 # via mkdocs-mermaid2-plugin -markdown==3.5 +markdown==3.5.1 # via # markdown-include # mdx-include @@ -63,9 +63,9 @@ mkdocs==1.5.3 # mkdocs-mermaid2-plugin mkdocs-markdownextradata-plugin==0.2.5 # via -r requirements/docs.in -mkdocs-material==9.4.6 +mkdocs-material==9.4.8 # via -r requirements/docs.in -mkdocs-material-extensions==1.2 +mkdocs-material-extensions==1.3 # via mkdocs-material mkdocs-mermaid2-plugin==1.1.1 # via -r requirements/docs.in @@ -81,7 +81,7 @@ pygments==2.16.1 # via # mkdocs-material # rich -pymdown-extensions==10.3 +pymdown-extensions==10.3.1 # via # -r requirements/docs.in # mkdocs-material @@ -123,7 +123,7 @@ typer[all]==0.7.0 # typer-cli typer-cli==0.0.13 # via -r requirements/docs.in -urllib3==2.0.6 +urllib3==2.0.7 # via requests watchdog==3.0.0 # via mkdocs diff --git a/requirements/linting.txt b/requirements/linting.txt index b6cc148d..27ab40cf 100644 --- a/requirements/linting.txt +++ b/requirements/linting.txt @@ -4,7 +4,7 @@ # # pip-compile --output-file=requirements/linting.txt requirements/linting.in # -black==23.9.1 +black==23.10.1 # via -r requirements/linting.in cfgv==3.4.0 # via pre-commit @@ -12,11 +12,11 @@ click==8.1.7 # via black distlib==0.3.7 # via virtualenv -filelock==3.12.4 +filelock==3.13.1 # via virtualenv -identify==2.5.30 +identify==2.5.31 # via pre-commit -mypy==1.6.0 +mypy==1.6.1 # via -r requirements/linting.in mypy-extensions==1.0.0 # via @@ -38,13 +38,13 @@ pyupgrade==3.15.0 # via -r requirements/linting.in pyyaml==6.0.1 # via pre-commit -ruff==0.0.292 +ruff==0.1.4 # via -r requirements/linting.in tokenize-rt==5.2.0 # via pyupgrade typing-extensions==4.8.0 # via mypy -virtualenv==20.24.5 +virtualenv==20.24.6 # via pre-commit # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/optional.txt b/requirements/optional.txt index 7640c11a..aec1b38f 100644 --- a/requirements/optional.txt +++ b/requirements/optional.txt @@ -8,7 +8,7 @@ async-timeout==4.0.3 # via redis ecdsa==0.18.0 # via python-jose -prometheus-client==0.17.1 +prometheus-client==0.18.0 # via -r requirements/optional.in pyasn1==0.5.0 # via diff --git a/requirements/pyproject.txt b/requirements/pyproject.txt index 4a31b23f..5dcd55ec 100644 --- a/requirements/pyproject.txt +++ b/requirements/pyproject.txt @@ -4,27 +4,38 @@ # # pip-compile --extra=all --output-file=requirements/pyproject.txt pyproject.toml # -anyio==4.0.0 - # via starlette +annotated-types==0.6.0 + # via pydantic +anyio==3.7.1 + # via + # fastapi + # starlette cffi==1.16.0 # via cryptography -cryptography==41.0.4 +cryptography==41.0.5 # via pyjwt -fastapi==0.98.0 +fastapi==0.104.1 # via authx (pyproject.toml) idna==3.4 # via anyio pycparser==2.21 # via cffi -pydantic==1.10.13 +pydantic==2.4.2 # via # authx (pyproject.toml) # fastapi +pydantic-core==2.10.1 + # via pydantic pyjwt[crypto]==2.8.0 - # via authx (pyproject.toml) + # via + # authx (pyproject.toml) + # pyjwt sniffio==1.3.0 # via anyio starlette==0.27.0 # via fastapi typing-extensions==4.8.0 - # via pydantic + # via + # fastapi + # pydantic + # pydantic-core diff --git a/requirements/testing.in b/requirements/testing.in index 5660ba07..f7b1620f 100644 --- a/requirements/testing.in +++ b/requirements/testing.in @@ -2,10 +2,11 @@ pytest pytest-asyncio pytest-cov httpx +anyio<4 requests SQLAlchemy itsdangerous websockets uvicorn uvloop -freezegun \ No newline at end of file +freezegun diff --git a/requirements/testing.txt b/requirements/testing.txt index 495ee712..ec20d132 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -4,28 +4,34 @@ # # pip-compile --output-file=requirements/testing.txt requirements/testing.in # -anyio==4.0.0 - # via httpcore +anyio==3.7.1 + # via + # -r requirements/testing.in + # httpx certifi==2023.7.22 # via # httpcore # httpx # requests -charset-normalizer==3.3.0 +charset-normalizer==3.3.2 # via requests click==8.1.7 # via uvicorn coverage[toml]==7.3.2 - # via pytest-cov + # via + # coverage + # pytest-cov freezegun==1.2.2 # via -r requirements/testing.in +greenlet==3.0.1 + # via sqlalchemy h11==0.14.0 # via # httpcore # uvicorn -httpcore==0.18.0 +httpcore==1.0.1 # via httpx -httpx==0.25.0 +httpx==0.25.1 # via -r requirements/testing.in idna==3.4 # via @@ -40,7 +46,7 @@ packaging==23.2 # via pytest pluggy==1.3.0 # via pytest -pytest==7.4.2 +pytest==7.4.3 # via # -r requirements/testing.in # pytest-asyncio @@ -58,17 +64,16 @@ six==1.16.0 sniffio==1.3.0 # via # anyio - # httpcore # httpx -sqlalchemy==2.0.22 +sqlalchemy==2.0.23 # via -r requirements/testing.in typing-extensions==4.8.0 # via sqlalchemy -urllib3==2.0.6 +urllib3==2.0.7 # via requests -uvicorn==0.23.2 +uvicorn==0.24.0.post1 # via -r requirements/testing.in -uvloop==0.18.0 +uvloop==0.19.0 # via -r requirements/testing.in -websockets==11.0.3 +websockets==12.0 # via -r requirements/testing.in diff --git a/scripts/requirements.sh b/scripts/requirements.sh old mode 100644 new mode 100755