jamlib 3.0.0b12.dev3__tar.gz → 3.0.0b13__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 (103) hide show
  1. {jamlib-3.0.0b12.dev3/src/jamlib.egg-info → jamlib-3.0.0b13}/PKG-INFO +1 -1
  2. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/pyproject.toml +1 -1
  3. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/__init__.py +1 -1
  4. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/exceptions/__init__.py +8 -1
  5. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/exceptions/plugins.py +13 -0
  6. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/ext/litestar/__init__.py +3 -1
  7. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/ext/litestar/plugins.py +56 -10
  8. jamlib-3.0.0b13/src/jam/ext/starlette/__init__.py +18 -0
  9. jamlib-3.0.0b13/src/jam/ext/starlette/backends.py +153 -0
  10. jamlib-3.0.0b13/src/jam/ext/starlette/objects.py +53 -0
  11. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/jwt/__algorithms__.py +5 -1
  12. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13/src/jamlib.egg-info}/PKG-INFO +1 -1
  13. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jamlib.egg-info/SOURCES.txt +2 -2
  14. jamlib-3.0.0b12.dev3/src/jam/ext/starlette/__init__.py +0 -12
  15. jamlib-3.0.0b12.dev3/src/jam/ext/starlette/auth_backends.py +0 -143
  16. jamlib-3.0.0b12.dev3/src/jam/ext/starlette/value.py +0 -18
  17. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/LICENSE.md +0 -0
  18. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/README.md +0 -0
  19. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/setup.cfg +0 -0
  20. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/__base__.py +0 -0
  21. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/__base_encoder__.py +0 -0
  22. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/__deprecated__.py +0 -0
  23. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/__base__.py +0 -0
  24. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/__init__.py +0 -0
  25. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/instance.py +0 -0
  26. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/jwt/__init__.py +0 -0
  27. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/oauth2/__base__.py +0 -0
  28. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/oauth2/__init__.py +0 -0
  29. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/oauth2/builtin/__init__.py +0 -0
  30. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/oauth2/builtin/github.py +0 -0
  31. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/oauth2/builtin/gitlab.py +0 -0
  32. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/oauth2/builtin/google.py +0 -0
  33. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/oauth2/builtin/yandex.py +0 -0
  34. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/oauth2/client.py +0 -0
  35. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/sessions/__base__.py +0 -0
  36. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/sessions/__init__.py +0 -0
  37. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/sessions/json.py +0 -0
  38. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/aio/sessions/redis.py +0 -0
  39. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/encoders.py +0 -0
  40. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/exceptions/base.py +0 -0
  41. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/exceptions/jwt.py +0 -0
  42. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/exceptions/oauth2.py +0 -0
  43. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/exceptions/paseto.py +0 -0
  44. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/exceptions/sessions.py +0 -0
  45. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/ext/__init__.py +0 -0
  46. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/ext/fastapi/__init__.py +0 -0
  47. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/ext/flask/__init__.py +0 -0
  48. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/ext/flask/extensions.py +0 -0
  49. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/ext/litestar/middleware.py +0 -0
  50. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/ext/litestar/objects.py +0 -0
  51. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/instance.py +0 -0
  52. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/jwt/__base__.py +0 -0
  53. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/jwt/__init__.py +0 -0
  54. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/jwt/__types__.py +0 -0
  55. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/jwt/lists/__abc_list_repo__.py +0 -0
  56. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/jwt/lists/__init__.py +0 -0
  57. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/jwt/lists/json.py +0 -0
  58. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/jwt/lists/redis.py +0 -0
  59. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/jwt/module.py +0 -0
  60. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/jwt/utils.py +0 -0
  61. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/logger.py +0 -0
  62. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/oauth2/__base__.py +0 -0
  63. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/oauth2/__init__.py +0 -0
  64. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/oauth2/builtin/__init__.py +0 -0
  65. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/oauth2/builtin/github.py +0 -0
  66. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/oauth2/builtin/gitlab.py +0 -0
  67. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/oauth2/builtin/google.py +0 -0
  68. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/oauth2/builtin/yandex.py +0 -0
  69. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/oauth2/client.py +0 -0
  70. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/otp/__base__.py +0 -0
  71. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/otp/__init__.py +0 -0
  72. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/otp/hotp.py +0 -0
  73. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/otp/totp.py +0 -0
  74. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/paseto/__base__.py +0 -0
  75. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/paseto/__init__.py +0 -0
  76. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/paseto/utils.py +0 -0
  77. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/paseto/v1.py +0 -0
  78. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/paseto/v2.py +0 -0
  79. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/paseto/v3.py +0 -0
  80. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/paseto/v4.py +0 -0
  81. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/py.typed +0 -0
  82. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/sessions/__base__.py +0 -0
  83. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/sessions/__init__.py +0 -0
  84. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/sessions/json.py +0 -0
  85. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/sessions/redis.py +0 -0
  86. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/tests/__init__.py +0 -0
  87. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/tests/clients.py +0 -0
  88. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/tests/fakers.py +0 -0
  89. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/utils/__init__.py +0 -0
  90. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/utils/aes.py +0 -0
  91. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/utils/await_maybe.py +0 -0
  92. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/utils/basic_auth.py +0 -0
  93. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/utils/config_maker.py +0 -0
  94. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/utils/ed.py +0 -0
  95. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/utils/otp_keys.py +0 -0
  96. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/utils/rsa.py +0 -0
  97. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/utils/salt_hash.py +0 -0
  98. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/utils/symmetric.py +0 -0
  99. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/utils/xchacha20poly1305.py +0 -0
  100. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jam/utils/xor.py +0 -0
  101. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jamlib.egg-info/dependency_links.txt +0 -0
  102. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jamlib.egg-info/requires.txt +0 -0
  103. {jamlib-3.0.0b12.dev3 → jamlib-3.0.0b13}/src/jamlib.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jamlib
3
- Version: 3.0.0b12.dev3
3
+ Version: 3.0.0b13
4
4
  Summary: Simple and universal library for authorization.
5
5
  Author-email: Makridenko Adrian <adrianmakridenko@duck.com>, Ksenia Travnikova <kseniatravnikova@duck.com>
6
6
  License: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "jamlib"
3
- version = "3.0.0b12.dev3"
3
+ version = "3.0.0b13"
4
4
  description = "Simple and universal library for authorization."
5
5
  authors = [
6
6
  {name = "Makridenko Adrian",email = "adrianmakridenko@duck.com"},
@@ -12,5 +12,5 @@ from jam.encoders import JsonEncoder
12
12
  from jam.instance import Jam
13
13
 
14
14
 
15
- __version__ = "3.0.0b12.dev3"
15
+ __version__ = "3.0.0b13"
16
16
  __all__ = ["Jam", "JsonEncoder", "BaseJam", "BaseEncoder"]
@@ -36,7 +36,12 @@ from .paseto import (
36
36
  JamPASETOInvalidTokenFormat
37
37
  )
38
38
 
39
- from .plugins import JamLitestarPluginConfigError, JamLitestarPluginError
39
+ from .plugins import (
40
+ JamLitestarPluginConfigError,
41
+ JamLitestarPluginError,
42
+ JamStarlettePluginConfigError,
43
+ JamStarlettePluginError
44
+ )
40
45
 
41
46
  from .sessions import (
42
47
  JamSessionNotFound,
@@ -67,6 +72,8 @@ __all__ = [
67
72
  "JamPASTOKeyVerificationError",
68
73
  "JamLitestarPluginConfigError",
69
74
  "JamLitestarPluginError",
75
+ "JamStarlettePluginConfigError",
76
+ "JamStarlettePluginError",
70
77
  "JamSessionNotFound",
71
78
  "JamSessionEmptyAESKey",
72
79
  ]
@@ -15,3 +15,16 @@ class JamLitestarPluginError(JamError):
15
15
 
16
16
  default_message = "An error occurred for a litestar plugin."
17
17
  default_code = "jam.plugin.litestar"
18
+
19
+ class JamStarlettePluginConfigError(JamConfigurationError):
20
+ """Exception raised when a configuration error occurs for a starlette plugin."""
21
+
22
+ default_message = "Configuration error occurred for a starlette plugin."
23
+ default_code = "jam.configuration.plugin.starlette"
24
+
25
+
26
+ class JamStarlettePluginError(JamError):
27
+ """Exception raised when an error occurs for a starlette plugin."""
28
+
29
+ default_message = "An error occurred for a starlette plugin."
30
+ default_code = "jam.plugin.starlette"
@@ -16,7 +16,8 @@ from .plugins import (
16
16
  BasePlugin,
17
17
  JamJWTPlugin,
18
18
  JamSessionPlugin,
19
- JamPASETOPlugin
19
+ JamPASETOPlugin,
20
+ JamOAuth2Plugin,
20
21
  )
21
22
 
22
23
  __all__ = [
@@ -27,4 +28,5 @@ __all__ = [
27
28
  "JamJWTPlugin",
28
29
  "JamSessionPlugin",
29
30
  "JamPASETOPlugin",
31
+ "JamOAuth2Plugin",
30
32
  ]
@@ -17,6 +17,7 @@ from jam.ext.litestar.middleware import (
17
17
  )
18
18
  from jam.ext.litestar.objects import BaseUser
19
19
  from jam.jwt import JWT
20
+ from jam.oauth2 import create_instance as create_oauth2
20
21
  from jam.paseto import create_instance as create_paseto
21
22
  from jam.utils.config_maker import GENERIC_POINTER, __config_maker__
22
23
 
@@ -25,23 +26,34 @@ class BasePlugin(InitPlugin):
25
26
  """Base Litestar plugin."""
26
27
 
27
28
  MODULE: Callable
28
- _MIDDLEWARE: type[BaseMiddleware]
29
+ MIDDLEWARE: type[BaseMiddleware]
29
30
  _DI_KEY: str
30
31
  _CONFIG_KEY: str
31
32
 
32
33
  def _setup_config(self, config: dict[str, Any]) -> None:
33
34
  self._auth = self.MODULE(**config)
34
35
 
35
- def __init__( # noqa
36
+ def __init__(
36
37
  self,
37
38
  config: dict[str, Any] | str | None = None,
38
39
  pointer: str = GENERIC_POINTER,
39
40
  cookie_name: str | None = None,
40
41
  header_name: str | None = None,
41
42
  middleware: bool = True,
42
- middleware_user: type[BaseUser] | None = None,
43
+ user: type[BaseUser] | None = None,
43
44
  **kwargs,
44
45
  ) -> None:
46
+ """Initialize the plugin.
47
+
48
+ Args:
49
+ config (dict[str, Any] | str | None): Jam config as path/to/file or dict.
50
+ pointer (str): Config pointer
51
+ cookie_name (str | None): Cookie name to read token
52
+ header_name (str | None): Header name to read token
53
+ middleware (bool): Use middleware?
54
+ user (type[BaseUser]): User for request state. See: DOCUMENTATION
55
+ **kwargs: Config arguments if config=None
56
+ """
45
57
  if middleware and (not cookie_name and not header_name):
46
58
  raise JamLitestarPluginConfigError(
47
59
  message="Cookie name and header name cannot be both None.",
@@ -50,11 +62,11 @@ class BasePlugin(InitPlugin):
50
62
  "header_name": header_name,
51
63
  },
52
64
  )
53
- if middleware and not middleware_user:
65
+ if middleware and not user:
54
66
  raise JamLitestarPluginConfigError(
55
67
  message="Middleware user cannot be None when middleware is True.",
56
68
  details={
57
- "middleware_user": middleware_user,
69
+ "middleware_user": user,
58
70
  },
59
71
  )
60
72
 
@@ -67,11 +79,11 @@ class BasePlugin(InitPlugin):
67
79
  self._middleware = None
68
80
 
69
81
  if middleware:
70
- _middleware = self._MIDDLEWARE
82
+ _middleware = self.MIDDLEWARE
71
83
  _middleware.COOKIE_NAME = cookie_name
72
84
  _middleware.HEADER_NAME = header_name
73
85
  _middleware.AUTH_MODULE = self._auth
74
- _middleware.USER = middleware_user # type: ignore
86
+ _middleware.USER = user # type: ignore
75
87
  self._middleware = _middleware
76
88
 
77
89
  def on_app_init(self, app_config: AppConfig) -> AppConfig: # noqa
@@ -88,7 +100,7 @@ class JamJWTPlugin(BasePlugin):
88
100
  """JWT plugin for litestar."""
89
101
 
90
102
  MODULE = JWT
91
- _MIDDLEWARE = JWTMiddleware
103
+ MIDDLEWARE = JWTMiddleware
92
104
  _DI_KEY = "jwt"
93
105
  _CONFIG_KEY = "jwt"
94
106
 
@@ -97,7 +109,7 @@ class JamSessionPlugin(BasePlugin):
97
109
  """Sessions plugin for litestar."""
98
110
 
99
111
  MODULE = staticmethod(create_session)
100
- _MIDDLEWARE = SessionMiddleware
112
+ MIDDLEWARE = SessionMiddleware
101
113
  _DI_KEY = "session"
102
114
  _CONFIG_KEY = "sessions"
103
115
 
@@ -106,6 +118,40 @@ class JamPASETOPlugin(BasePlugin):
106
118
  """PASETO plugin for litestar."""
107
119
 
108
120
  MODULE = staticmethod(create_paseto)
109
- _MIDDLEWARE = PASETOMiddleware
121
+ MIDDLEWARE = PASETOMiddleware
110
122
  _DI_KEY = "paseto"
111
123
  _CONFIG_KEY = "paseto"
124
+
125
+
126
+ class JamOAuth2Plugin(BasePlugin):
127
+ """OAuth2 plugin for litestar."""
128
+
129
+ MODULE = staticmethod(create_oauth2)
130
+ _DI_KEY = "oauth2"
131
+ _CONFIG_KEY = "oauth2"
132
+
133
+ def __init__(
134
+ self,
135
+ config: str | dict[str, Any] | None = None,
136
+ pointer: str = GENERIC_POINTER,
137
+ **kwargs,
138
+ ) -> None:
139
+ """Initialize the OAuth2 plugin.
140
+
141
+ Args:
142
+ config (dict[str, Any] | str | None): Jam config as path/to/file or dict.
143
+ pointer (str): Config pointer
144
+ **kwargs: Config arguments if config=None
145
+ """
146
+ _config: dict[str, Any] | None = (
147
+ __config_maker__(config, pointer) if config else None
148
+ )
149
+
150
+ params = _config.pop(self._CONFIG_KEY) if _config else kwargs
151
+ self._setup_config(params)
152
+
153
+ def on_app_init(self, app_config: AppConfig) -> AppConfig: # noqa
154
+ app_config.dependencies[self._DI_KEY] = Provide(
155
+ lambda: self._auth, sync_to_thread=True
156
+ )
157
+ return app_config
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ """Starlette integration.
4
+
5
+ Starlette docs: https://starlette.dev
6
+ """
7
+
8
+ from .objects import BaseUser, SimpleUser
9
+ from .backends import JWTBackend, SessionBackend, PASETOBackend
10
+
11
+
12
+ __all__ = [
13
+ "BaseUser",
14
+ "SimpleUser",
15
+ "JWTBackend",
16
+ "SessionBackend",
17
+ "PASETOBackend",
18
+ ]
@@ -0,0 +1,153 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from collections.abc import Callable
4
+ from typing import Any
5
+
6
+ from starlette.authentication import (
7
+ AuthCredentials,
8
+ AuthenticationBackend,
9
+ UnauthenticatedUser,
10
+ )
11
+ from starlette.authentication import BaseUser as StarletteBaseUser
12
+ from starlette.requests import HTTPConnection
13
+
14
+ from jam.aio.sessions import create_instance as create_session
15
+ from jam.exceptions import JamStarlettePluginConfigError
16
+ from jam.ext.starlette.objects import BaseUser, SimpleUser
17
+ from jam.jwt import JWT
18
+ from jam.paseto import create_instance as create_paseto
19
+ from jam.utils.config_maker import GENERIC_POINTER, __config_maker__
20
+
21
+
22
+ class BaseBackend(AuthenticationBackend):
23
+ """Base Jam backend."""
24
+
25
+ MODULE: Callable
26
+ _CONFIG_KEY: str
27
+
28
+ def __init__( # noqa
29
+ self,
30
+ config: str | dict[str, Any] | None = None,
31
+ pointer: str = GENERIC_POINTER,
32
+ cookie_name: str | None = None,
33
+ header_name: str | None = None,
34
+ user: type[BaseUser] = SimpleUser,
35
+ **kwargs,
36
+ ) -> None:
37
+ if not cookie_name and not header_name:
38
+ raise JamStarlettePluginConfigError(
39
+ message="cookie_name or header_name must be provided.",
40
+ details={
41
+ "cookie_name": cookie_name,
42
+ "header_name": header_name,
43
+ },
44
+ )
45
+ self._cookie_name = cookie_name
46
+ self._header_name = header_name
47
+ self._user = user
48
+ self._config_setup(config, pointer, kwargs)
49
+
50
+ def _get_auth_token(self, connection: HTTPConnection) -> str | None:
51
+ if self._cookie_name:
52
+ token = connection.cookies.get(self._cookie_name, None)
53
+ elif self._header_name:
54
+ token_bear = connection.headers.get(self._header_name, None)
55
+ if token_bear:
56
+ token = token_bear.split("Bearer ")[1] # noqa: E701
57
+ else:
58
+ token = None # noqa: E701
59
+ else:
60
+ raise JamStarlettePluginConfigError(
61
+ message="cookie_name or header_name must be provided.",
62
+ details={
63
+ "cookie_name": self._cookie_name,
64
+ "header_name": self._header_name,
65
+ },
66
+ )
67
+ return token
68
+
69
+ def _config_setup(
70
+ self,
71
+ config: dict[str, Any] | str | None,
72
+ pointer: str,
73
+ kwargs: dict[str, Any],
74
+ ) -> None:
75
+ try:
76
+ if config:
77
+ config_ = __config_maker__(config, pointer)[self._CONFIG_KEY]
78
+ self._auth = self.MODULE(**config_)
79
+ else:
80
+ self._auth = self.MODULE(**kwargs)
81
+ except Exception as e:
82
+ raise JamStarlettePluginConfigError(
83
+ message="Error while building auth modile.",
84
+ details={
85
+ "module": self.MODULE.__str__,
86
+ "config": {
87
+ "config": config,
88
+ "pointer": pointer,
89
+ "kwargs": kwargs,
90
+ },
91
+ "config_key": self._CONFIG_KEY,
92
+ "error": str(e),
93
+ },
94
+ )
95
+
96
+
97
+ class JWTBackend(BaseBackend):
98
+ """JWT Backend for litestar."""
99
+
100
+ MODULE = JWT
101
+ _CONFIG_KEY = "jwt"
102
+
103
+ async def authenticate( # noqa
104
+ self, conn: HTTPConnection
105
+ ) -> tuple[AuthCredentials, StarletteBaseUser] | None:
106
+ setattr(conn.state, "jwt", self._auth)
107
+ token = self._get_auth_token(conn)
108
+ if token:
109
+ data = self._auth.decode(token)
110
+ user = self._user.from_payload(data)
111
+ return AuthCredentials(["authenticated"]), user
112
+
113
+ return AuthCredentials(None), UnauthenticatedUser()
114
+
115
+
116
+ class SessionBackend(BaseBackend):
117
+ """Session backend."""
118
+
119
+ MODULE = staticmethod(create_session)
120
+ _CONFIG_KEY = "sessions"
121
+
122
+ async def authenticate( # noqa
123
+ self, conn: HTTPConnection
124
+ ) -> tuple[AuthCredentials, StarletteBaseUser] | None:
125
+ setattr(conn.state, "session", self._auth)
126
+ session_id = self._get_auth_token(conn)
127
+ if session_id:
128
+ data = await self._auth.get(session_id)
129
+ if data:
130
+ user = self._user.from_payload(data)
131
+ return AuthCredentials(["authenticated"]), user
132
+
133
+ return AuthCredentials(None), UnauthenticatedUser()
134
+
135
+
136
+ class PASETOBackend(BaseBackend):
137
+ """PASETO auth backend."""
138
+
139
+ MODULE = staticmethod(create_paseto)
140
+ _CONFIG_KEY = "paseto"
141
+
142
+ async def authenticate( # noqa
143
+ self, conn: HTTPConnection
144
+ ) -> tuple[AuthCredentials, StarletteBaseUser] | None:
145
+ setattr(conn.state, "paseto", self._auth)
146
+ token = self._get_auth_token(conn)
147
+ if token:
148
+ data = self._auth.decode(token)
149
+ if data:
150
+ user = self._user.from_payload(data)
151
+ return AuthCredentials(["authenticated"]), user
152
+
153
+ return AuthCredentials(None), UnauthenticatedUser()
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from abc import ABC, abstractmethod
4
+ from dataclasses import dataclass
5
+ from typing import Any, TypeVar
6
+
7
+ from starlette.authentication import BaseUser as StarletteBaseUser
8
+
9
+
10
+ User = TypeVar("User", bound="BaseUser")
11
+
12
+
13
+ class BaseUser(ABC, StarletteBaseUser):
14
+ """BaseUser with builder from payload."""
15
+
16
+ @classmethod
17
+ @abstractmethod
18
+ def from_payload(cls, payload: dict[str, Any]) -> User:
19
+ """Create instance by payload.
20
+
21
+ Args:
22
+ payload (dict[str, Any]): Payload from auth
23
+
24
+ Example:
25
+ ```python
26
+
27
+ class MyUser(JamBaseUser):
28
+ id: int
29
+ username: str
30
+
31
+ @classmethod
32
+ def from_payload(cls, payload):
33
+ return cls(
34
+ id=payload["id"],
35
+ username=payload["username"]
36
+ )
37
+
38
+ payload = jwt.decode(token)
39
+ user = MyUser.from_payload(payload)
40
+ ```
41
+ """
42
+ raise NotImplementedError
43
+
44
+
45
+ @dataclass(slots=True)
46
+ class SimpleUser(BaseUser):
47
+ """Simple user with payload only."""
48
+
49
+ payload: dict[str, Any]
50
+
51
+ @classmethod
52
+ def from_payload(cls, payload: dict[str, Any]): # noqa
53
+ return cls(payload=payload)
@@ -100,7 +100,11 @@ class BaseAlgorithm(ABC):
100
100
  from pathlib import Path
101
101
 
102
102
  path = Path(data)
103
- return path.read_bytes() if path.is_file() else data.encode()
103
+ try:
104
+ is_file = path.is_file()
105
+ except OSError:
106
+ is_file = False
107
+ return path.read_bytes() if is_file else data.encode()
104
108
 
105
109
  def _load_private_key(
106
110
  self, key_bytes: bytes | None, key_obj: Any | None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jamlib
3
- Version: 3.0.0b12.dev3
3
+ Version: 3.0.0b13
4
4
  Summary: Simple and universal library for authorization.
5
5
  Author-email: Makridenko Adrian <adrianmakridenko@duck.com>, Ksenia Travnikova <kseniatravnikova@duck.com>
6
6
  License: Apache-2.0
@@ -41,8 +41,8 @@ src/jam/ext/litestar/middleware.py
41
41
  src/jam/ext/litestar/objects.py
42
42
  src/jam/ext/litestar/plugins.py
43
43
  src/jam/ext/starlette/__init__.py
44
- src/jam/ext/starlette/auth_backends.py
45
- src/jam/ext/starlette/value.py
44
+ src/jam/ext/starlette/backends.py
45
+ src/jam/ext/starlette/objects.py
46
46
  src/jam/jwt/__algorithms__.py
47
47
  src/jam/jwt/__base__.py
48
48
  src/jam/jwt/__init__.py
@@ -1,12 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- """
4
- Starlette integration.
5
-
6
- Starlette docs: https://starlette.dev
7
- """
8
-
9
- from .auth_backends import JWTBackend, SessionBackend
10
-
11
-
12
- __all__ = ["JWTBackend", "SessionBackend"]
@@ -1,143 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- from typing import Any
4
-
5
- from starlette.authentication import (
6
- AuthCredentials,
7
- AuthenticationBackend,
8
- AuthenticationError,
9
- BaseUser,
10
- )
11
- from starlette.requests import HTTPConnection
12
-
13
- from jam.__base__ import BaseJam
14
- from jam.utils.await_maybe import await_maybe
15
-
16
- from .value import Payload
17
-
18
-
19
- class JWTBackend(AuthenticationBackend):
20
- """JWT Backend for Starlette AuthenticationMiddleware."""
21
-
22
- def __init__(
23
- self,
24
- jam: BaseJam,
25
- cookie_name: str | None = None,
26
- header_name: str | None = "Authorization",
27
- ) -> None:
28
- """Constructor.
29
-
30
- Args:
31
- jam (BaseJam): Jam instance
32
- cookie_name (str | None): Access token cookie name
33
- header_name (str | None): Access token header name
34
- """
35
- self._jam = jam
36
- self.cookie_name = cookie_name
37
- self.header_name = header_name
38
- self.__use_list = bool(getattr(self._jam.jwt, "list", False))
39
-
40
- async def authenticate(
41
- self, conn: HTTPConnection
42
- ) -> tuple[AuthCredentials, BaseUser] | None:
43
- """Starlette authentication handler."""
44
- logger = self._jam._logger
45
- token = None
46
-
47
- logger.debug("JWTBackend: Attempting to extract token from request")
48
- if self.cookie_name:
49
- token = conn.cookies.get(self.cookie_name)
50
- if token:
51
- logger.debug(f"Token found in cookie '{self.cookie_name}'")
52
-
53
- if not token and self.header_name:
54
- header = conn.headers.get(self.header_name)
55
- if header and header.startswith("Bearer "):
56
- token = header.split("Bearer ")[1]
57
- logger.debug(f"Token found in header '{self.header_name}'")
58
-
59
- if not token:
60
- logger.debug("No token found in request")
61
- return None
62
-
63
- logger.debug(
64
- f"Verifying JWT token (length: {len(token)} chars), check_list={self.__use_list}"
65
- )
66
- try:
67
- payload: dict[str, Any] = await await_maybe(
68
- self._jam.jwt_verify_token(
69
- token=token, check_exp=True, check_list=self.__use_list
70
- )
71
- )
72
- logger.debug(
73
- f"JWT token verified successfully, payload keys: {list(payload.keys())}"
74
- )
75
- except Exception as e:
76
- logger.warning(f"Token verify error: {e}")
77
- raise AuthenticationError("Token verification failed.")
78
-
79
- return AuthCredentials(["authenticated"]), Payload(payload=payload)
80
-
81
-
82
- class SessionBackend(AuthenticationBackend):
83
- """Sessions backend for starlette."""
84
-
85
- def __init__(
86
- self,
87
- jam: BaseJam,
88
- cookie_name: str | None = "sessionId",
89
- header_name: str | None = None,
90
- ) -> None:
91
- """Constructor.
92
-
93
- Args:
94
- jam (BaseJam): Jam instance
95
- cookie_name (str | None): Session id cookie name
96
- header_name (str | None): Session id header name
97
- """
98
- self._jam = jam
99
- self.cookie_name = cookie_name
100
- self.header_name = header_name
101
-
102
- async def authenticate(
103
- self, conn: HTTPConnection
104
- ) -> tuple[AuthCredentials, BaseUser] | None:
105
- """Starlette authentication handler."""
106
- logger = self._jam._logger
107
- session_id = None
108
-
109
- logger.debug(
110
- "SessionBackend: Attempting to extract session ID from request"
111
- )
112
- if self.cookie_name:
113
- session_id = conn.cookies.get(self.cookie_name)
114
- if session_id:
115
- logger.debug(f"Session ID found in cookie '{self.cookie_name}'")
116
-
117
- if not session_id and self.header_name:
118
- header = conn.headers.get(self.header_name)
119
- if header and header.startswith("Bearer "):
120
- session_id = header.split("Bearer ")[1]
121
- logger.debug(f"Session ID found in header '{self.header_name}'")
122
-
123
- if not session_id:
124
- logger.debug("No session ID found in request")
125
- return None
126
-
127
- logger.debug(f"Getting session data for session ID: {session_id}")
128
- try:
129
- payload: dict[str, Any] | None = await await_maybe( # type: ignore[arg-type]
130
- self._jam.session_get(session_id) # type: ignore[arg-type]
131
- )
132
- if payload:
133
- logger.debug(
134
- f"Session data retrieved successfully, keys: {list(payload.keys())}"
135
- )
136
- else:
137
- logger.debug(f"Session {session_id} not found")
138
- # TODO: Return unauthized user
139
- except Exception as e:
140
- logger.warning(f"Session retrieval error: {e}")
141
- raise AuthenticationError("Token verification failed.")
142
-
143
- return AuthCredentials(["authenticated"]), Payload(payload=payload)
@@ -1,18 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- from typing import Any
4
-
5
- from starlette.authentication import BaseUser
6
-
7
-
8
- class Payload(BaseUser):
9
- """Auth payload."""
10
-
11
- def __init__(self, payload: dict[str, Any] | None):
12
- """Auth payload."""
13
- self.payload = payload
14
-
15
- @property
16
- def is_authenticated(self) -> bool:
17
- """Auth checker."""
18
- return True
File without changes
File without changes
File without changes