diff --git a/.github/workflows/test_full.yml b/.github/workflows/test_full.yml index c6404d3..9e52d65 100644 --- a/.github/workflows/test_full.yml +++ b/.github/workflows/test_full.yml @@ -37,9 +37,7 @@ jobs: run: pip install flit - name: Install Dependencies run: flit install --symlink - - name: Black - run: black --check ellar_jwt tests - name: Linting check - run: ruff check ellar_jwt tests & ruff check tests + run: ruff check ellar_jwt tests - name: mypy run: mypy ellar_jwt diff --git a/Makefile b/Makefile index e119b20..282f922 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ clean: ## Removing cached python compiled files find . -name \*pyo | xargs rm -fv find . -name \*~ | xargs rm -fv find . -name __pycache__ | xargs rm -rfv + find . -name .ruff_cache | xargs rm -rfv install: ## Install dependencies flit install --deps develop --symlink @@ -17,13 +18,12 @@ install-full: ## Install dependencies make install pre-commit install -f -lint: ## Run code linters - black --check ellar_jwt tests +lint:fmt ## Run code linters ruff check ellar_jwt tests mypy ellar_jwt -fmt format: ## Run code formatters - black ellar_jwt tests +fmt format:clean ## Run code formatters + ruff format ellar_jwt tests ruff check --fix ellar_jwt tests test: ## Run tests diff --git a/ellar_jwt/__init__.py b/ellar_jwt/__init__.py index 2e15fb9..69b60db 100644 --- a/ellar_jwt/__init__.py +++ b/ellar_jwt/__init__.py @@ -1,6 +1,6 @@ """JWT Module for Ellar""" -__version__ = "0.1.8" +__version__ = "0.2.0" from .module import JWTModule from .schemas import JWTConfiguration from .services import JWTService diff --git a/ellar_jwt/schemas.py b/ellar_jwt/schemas.py index 085004b..bf01542 100644 --- a/ellar_jwt/schemas.py +++ b/ellar_jwt/schemas.py @@ -3,8 +3,8 @@ from datetime import timedelta from ellar.common import Serializer +from ellar.pydantic import AnyUrl, Field, field_validator from jwt import algorithms -from pydantic import AnyHttpUrl, Field, validator class JWTConfiguration(Serializer): @@ -26,14 +26,14 @@ class JWTConfiguration(Serializer): audience: t.Optional[str] = Field(None) issuer: t.Optional[str] = Field(None) - jwk_url: t.Optional[AnyHttpUrl] = Field(None) + jwk_url: t.Optional[AnyUrl] = Field(None) jti: t.Optional[str] = Field("jti") lifetime: timedelta = Field(timedelta(minutes=5)) json_encoder: t.Any = Field(default=json.JSONEncoder) - @validator("algorithm") + @field_validator("algorithm", mode="before") def _validate_algorithm(cls, value: str) -> str: """ Ensure that the nominated algorithm is recognized, and that cryptography is installed for those diff --git a/ellar_jwt/services.py b/ellar_jwt/services.py index 2da6653..4cfc1d5 100644 --- a/ellar_jwt/services.py +++ b/ellar_jwt/services.py @@ -4,6 +4,7 @@ import anyio import jwt +from ellar.common import serialize_object from ellar.di import injectable from jwt import InvalidAlgorithmError, InvalidTokenError, PyJWKClient, PyJWKClientError @@ -20,7 +21,9 @@ def __init__(self, jwt_config: JWTConfiguration) -> None: self.jwt_config = jwt_config def get_jwks_client(self, jwt_config: JWTConfiguration) -> t.Optional[PyJWKClient]: - jwks_client = PyJWKClient(jwt_config.jwk_url) if jwt_config.jwk_url else None + jwks_client = ( + PyJWKClient(str(jwt_config.jwk_url)) if jwt_config.jwk_url else None + ) return jwks_client def get_leeway(self, jwt_config: JWTConfiguration) -> timedelta: @@ -60,7 +63,9 @@ def sign( Returns an encoded token for the given payload dictionary. """ _jwt_config = self._merge_configurations(**jwt_config) - jwt_payload = Token(jwt_config=_jwt_config).build(payload.copy()) + jwt_payload = Token(jwt_config=_jwt_config).build( + serialize_object(payload.copy()) + ) return jwt.encode( jwt_payload, @@ -93,7 +98,7 @@ def decode( """ try: _jwt_config = self._merge_configurations(**jwt_config) - return jwt.decode( # type: ignore[no-any-return] + return jwt.decode( # type:ignore[no-any-return] token, self.get_verifying_key(token, _jwt_config), algorithms=[_jwt_config.algorithm], diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index e072375..0000000 --- a/mypy.ini +++ /dev/null @@ -1,19 +0,0 @@ -[mypy] -python_version = 3.8 - -show_column_numbers = True - -follow_imports = normal -ignore_missing_imports = True - -# be strict -disallow_untyped_calls = True -warn_return_any = True -strict_optional = True -warn_no_return = True -warn_redundant_casts = True -warn_unused_ignores = True - -disallow_untyped_defs = True -check_untyped_defs = True -implicit_reexport = False diff --git a/pyproject.toml b/pyproject.toml index 4bc1bd7..bef2603 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ classifiers = [ ] dependencies = [ - "ellar >= 0.4.4", + "ellar >= 0.5.8", "pyjwt>=1.7.1,<3", "pyjwt[crypto]" ] @@ -62,11 +62,8 @@ Homepage = "https://eadwincode.github.io/ellar-jwt/" test = [ "pytest >= 7.1.3,<8.0.0", "pytest-cov >= 2.12.0,<5.0.0", - "mypy == 1.5.1", "ruff ==0.1.7", "mypy == 1.7.1", - "ruff ==0.1.7", - "black == 23.11.0", "pytest-asyncio", "autoflake", "types-python-dateutil", @@ -93,3 +90,22 @@ ignore = [ [tool.ruff.isort] known-third-party = ["ellar"] + +[tool.mypy] + +show_column_numbers = true + +follow_imports = 'normal' +ignore_missing_imports = true + +# be strict +disallow_untyped_calls = true +warn_return_any = true +strict_optional = true +warn_no_return = true +warn_redundant_casts = true +warn_unused_ignores = true + +disallow_untyped_defs = true +check_untyped_defs = true +implicit_reexport = false diff --git a/tests/test_jwt_service.py b/tests/test_jwt_service.py index e45fbbe..341e8ca 100644 --- a/tests/test_jwt_service.py +++ b/tests/test_jwt_service.py @@ -41,7 +41,7 @@ def default(self, obj): class TestJWTService: hmac_token_backend = JWTService( - JWTConfiguration(algorithm="HS256", signing_secret_key=SECRET) + JWTConfiguration(algorithm="HS256", signing_secret_key=SECRET), ) hmac_leeway_token_backend = JWTService( JWTConfiguration(algorithm="HS256", signing_secret_key=SECRET, leeway=LEEWAY) @@ -95,7 +95,8 @@ def test_init(self): # Should reject unknown algorithms with pytest.raises(ValueError): JWTConfiguration( - algorithm="oienarst oieanrsto i", signing_secret_key="not_secret" + algorithm="oienarst oieanrsto i", + signing_secret_key="not_secret", ) JWTConfiguration(algorithm="HS256", signing_secret_key="not_secret")