xn-auth 0.2.68.dev2__tar.gz → 0.2.69__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/.pre-commit-config.yaml +2 -2
  2. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/CLAUDE.md +1 -1
  3. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/PKG-INFO +2 -1
  4. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/pyproject.toml +1 -0
  5. xn_auth-0.2.69/x_auth/exceptions.py +2 -0
  6. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/x_auth/middleware.py +8 -20
  7. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/xn_auth.egg-info/PKG-INFO +2 -1
  8. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/xn_auth.egg-info/requires.txt +1 -0
  9. xn_auth-0.2.69/xn_auth.egg-info/scm_version.json +8 -0
  10. xn_auth-0.2.68.dev2/x_auth/exceptions.py +0 -5
  11. xn_auth-0.2.68.dev2/xn_auth.egg-info/scm_version.json +0 -8
  12. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/.env.dist +0 -0
  13. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/.gitignore +0 -0
  14. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/README.md +0 -0
  15. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/makefile +0 -0
  16. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/setup.cfg +0 -0
  17. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/tests/test_proxy.py +0 -0
  18. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/x_auth/controller.py +0 -0
  19. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/x_auth/enums.py +0 -0
  20. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/x_auth/models.py +0 -0
  21. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/x_auth/types.py +0 -0
  22. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/xn_auth.egg-info/SOURCES.txt +0 -0
  23. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/xn_auth.egg-info/dependency_links.txt +0 -0
  24. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/xn_auth.egg-info/scm_file_list.json +0 -0
  25. {xn_auth-0.2.68.dev2 → xn_auth-0.2.69}/xn_auth.egg-info/top_level.txt +0 -0
@@ -4,7 +4,7 @@ repos:
4
4
  - id: tag
5
5
  name: tag
6
6
  ### make tag with next ver only if "fix" in commit_msg or starts with "feat"
7
- entry: bash -c 'grep -e "^feat:" -e "^fix:" .git/COMMIT_EDITMSG && make patch || exit 0'
7
+ entry: bash -c 'if grep -qE "^(feat|fix):" .git/COMMIT_EDITMSG; then make patch; fi'
8
8
  language: system
9
9
  verbose: true
10
10
  pass_filenames: false
@@ -23,7 +23,7 @@ repos:
23
23
 
24
24
  - repo: https://github.com/astral-sh/ruff-pre-commit
25
25
  ### Ruff version.
26
- rev: v0.12.7
26
+ rev: v0.16.4
27
27
  hooks:
28
28
  ### Run the linter.
29
29
  - id: ruff
@@ -26,7 +26,7 @@ twine upload dist/*
26
26
  1. **Entry point**: `Auth` class in `controller.py` - initializes `JWTCookieAuth` from Litestar with custom middleware
27
27
  2. **Endpoints**: `/auth/tma` (Mini App initData) and `/auth/twa` (Login Widget) - both validate Telegram signatures and issue JWT tokens
28
28
  3. **Token handling**: Custom `Tok` class in `middleware.py` extends `Token` to catch `ExpiredSignatureError` and re-encode with fresh timestamps
29
- 4. **Auto-refresh**: `JWTAuthMiddleware` intercepts expired tokens, checks if user is blocked via `User.permissions()`, updates role if changed, and sets new cookie
29
+ 4. **Auto-refresh**: `JWTAuthMiddleware` intercepts expired tokens (signature still verified), refreshes `role`/`blocked` from `User.permissions()` and sets new cookie. the refresh is never refused — gating on `blocked` is up to the app (e.g. a guard)
30
30
 
31
31
  ### Key Components
32
32
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xn-auth
3
- Version: 0.2.68.dev2
3
+ Version: 0.2.69
4
4
  Summary: Auth adapter for XN-Api framework
5
5
  Author-email: Artemiev <mixartemev@gmail.com>
6
6
  License: MIT
@@ -21,6 +21,7 @@ Requires-Dist: pre-commit; extra == "dev"
21
21
  Requires-Dist: python-dotenv; extra == "dev"
22
22
  Requires-Dist: pytest; extra == "dev"
23
23
  Requires-Dist: pytest-asyncio; extra == "dev"
24
+ Requires-Dist: setuptools-scm>=8; extra == "dev"
24
25
  Requires-Dist: twine; extra == "dev"
25
26
 
26
27
  # X-Auth
@@ -26,6 +26,7 @@ dev = [
26
26
  "python-dotenv",
27
27
  "pytest",
28
28
  "pytest-asyncio",
29
+ "setuptools-scm>=8",
29
30
  "twine"
30
31
  ]
31
32
 
@@ -0,0 +1,2 @@
1
+ class ExpiredSignature(Exception):
2
+ def __init__(self, payload: dict): ...
@@ -32,15 +32,7 @@ class Tok(Token):
32
32
  logging.warning("JWToken expired")
33
33
  options["verify_exp"] = False
34
34
  payload = super().decode_payload(encoded_token, secret, algorithms, issuer, audience, options)
35
- payload.update(
36
- {
37
- "exp": (now := int(datetime.now(timezone.utc).timestamp())) + (payload["exp"] - payload["iat"]),
38
- "iat": now,
39
- }
40
- )
41
- tok = convert(payload, cls, strict=False)
42
- encoded_token = tok.encode(secret, algorithms[0])
43
- raise ExpiredSignature(int(payload["sub"]), encoded_token, secret, e)
35
+ raise ExpiredSignature(payload) from e # подпись проверена, просрочен только exp
44
36
 
45
37
 
46
38
  class JWTAuthMiddleware(JWTCookieAuthenticationMiddleware):
@@ -48,17 +40,13 @@ class JWTAuthMiddleware(JWTCookieAuthenticationMiddleware):
48
40
  try:
49
41
  await super().__call__(scope, receive, send)
50
42
  except ExpiredSignature as e:
51
- uid, uet, secret, _e = e.args # uid, updated encoded token
52
- blocked, role = await scope["app"].state.get("user_model").permissions(uid)
53
- if blocked:
54
- logging.error(f"User#{uid} can't refresh. Blocked!")
55
- raise _e
56
- payload = Tok.decode_payload(uet, secret, ["HS256"])
57
- if role.value != payload["extras"]["role"]:
58
- # update user role in jwtoken
59
- payload["extras"]["role"] = role.value
60
- tok = convert(payload, Tok, strict=False)
61
- uet = tok.encode(secret, "HS256")
43
+ (payload,) = e.args
44
+ # продлеваем всем, extras — свежие из БД; что делать с blocked (бот не пишет в ЛС), решает приложение
45
+ blocked, role = await scope["app"].state.get("user_model").permissions(int(payload["sub"]))
46
+ now = int(datetime.now(timezone.utc).timestamp())
47
+ payload.update(exp=now + payload["exp"] - payload["iat"], iat=now)
48
+ payload["extras"].update(role=role.value, blocked=blocked)
49
+ uet = convert(payload, Tok, strict=False).encode(self.token_secret, self.algorithm)
62
50
 
63
51
  async def send_wrapper(msg: Message) -> None:
64
52
  if msg["type"] == "http.response.start":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xn-auth
3
- Version: 0.2.68.dev2
3
+ Version: 0.2.69
4
4
  Summary: Auth adapter for XN-Api framework
5
5
  Author-email: Artemiev <mixartemev@gmail.com>
6
6
  License: MIT
@@ -21,6 +21,7 @@ Requires-Dist: pre-commit; extra == "dev"
21
21
  Requires-Dist: python-dotenv; extra == "dev"
22
22
  Requires-Dist: pytest; extra == "dev"
23
23
  Requires-Dist: pytest-asyncio; extra == "dev"
24
+ Requires-Dist: setuptools-scm>=8; extra == "dev"
24
25
  Requires-Dist: twine; extra == "dev"
25
26
 
26
27
  # X-Auth
@@ -11,4 +11,5 @@ pre-commit
11
11
  python-dotenv
12
12
  pytest
13
13
  pytest-asyncio
14
+ setuptools-scm>=8
14
15
  twine
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.2.69",
3
+ "distance": 0,
4
+ "node": "g81f29cc3107eb762cbf50176f5f5ee211168fe99",
5
+ "dirty": false,
6
+ "branch": "main",
7
+ "node_date": "2026-10-30"
8
+ }
@@ -1,5 +0,0 @@
1
- from jwt import ExpiredSignatureError
2
-
3
-
4
- class ExpiredSignature(Exception):
5
- def __init__(self, uid: int, encoded_token: str, secret: str, _e: ExpiredSignatureError): ...
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.2.67",
3
- "distance": 2,
4
- "node": "g04ae72ce55eeb456f913a8433078411503e587cd",
5
- "dirty": false,
6
- "branch": "main",
7
- "node_date": "2026-08-25"
8
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes