aspyx-service 0.10.4__tar.gz → 0.10.6__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.
Potentially problematic release.
This version of aspyx-service might be problematic. Click here for more details.
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/PKG-INFO +28 -11
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/README.md +26 -8
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/performance-test/client.py +4 -3
- aspyx_service-0.10.6/performance-test/main.py +34 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/performance-test/performance-test.py +14 -8
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/performance-test/server.py +19 -5
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/pyproject.toml +2 -3
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/src/aspyx_service/__init__.py +8 -7
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/src/aspyx_service/authorization.py +4 -13
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/src/aspyx_service/channels.py +9 -7
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/src/aspyx_service/restchannel.py +2 -6
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/src/aspyx_service/server.py +153 -32
- aspyx_service-0.10.6/src/aspyx_service/session.py +136 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/tests/common.py +59 -25
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/tests/test_async_service.py +8 -3
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/tests/test_jwt.py +38 -19
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/tests/test_serialization.py +1 -1
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/tests/test_service.py +1 -1
- aspyx_service-0.10.4/performance-test/main.py +0 -23
- aspyx_service-0.10.4/src/aspyx_service/serialization.py +0 -137
- aspyx_service-0.10.4/src/aspyx_service/session.py +0 -97
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/.gitignore +0 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/LICENSE +0 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/performance-test/__init__.py +0 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/performance-test/config.yaml +0 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/performance-test/readme.txt +0 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/performance-test/start_server_8000.sh +0 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/performance-test/start_server_8001.sh +0 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/src/aspyx_service/healthcheck.py +0 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/src/aspyx_service/registries.py +0 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/src/aspyx_service/service.py +0 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/tests/__init__.py +0 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/tests/config.yaml +0 -0
- {aspyx_service-0.10.4 → aspyx_service-0.10.6}/tests/test_healthcheck.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aspyx_service
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.6
|
|
4
4
|
Summary: Aspyx Service framework
|
|
5
5
|
Author-email: Andreas Ernst <andreas.ernst7@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -26,8 +26,7 @@ License: MIT License
|
|
|
26
26
|
SOFTWARE.
|
|
27
27
|
License-File: LICENSE
|
|
28
28
|
Requires-Python: >=3.9
|
|
29
|
-
Requires-Dist: aspyx>=1.
|
|
30
|
-
Requires-Dist: cachetools~=5.5.2
|
|
29
|
+
Requires-Dist: aspyx>=1.6.0
|
|
31
30
|
Requires-Dist: fastapi~=0.115.13
|
|
32
31
|
Requires-Dist: httpx~=0.28.1
|
|
33
32
|
Requires-Dist: msgpack~=1.1.1
|
|
@@ -110,18 +109,20 @@ class TestComponent(Component):
|
|
|
110
109
|
After booting the DI infrastructure with a main module we could already call a service:
|
|
111
110
|
|
|
112
111
|
**Example**:
|
|
112
|
+
|
|
113
113
|
```python
|
|
114
114
|
@module(imports=[ServiceModule])
|
|
115
115
|
class Module:
|
|
116
116
|
def __init__(self):
|
|
117
117
|
pass
|
|
118
|
-
|
|
118
|
+
|
|
119
119
|
@create()
|
|
120
120
|
def create_registry(self) -> ConsulComponentRegistry:
|
|
121
|
-
return ConsulComponentRegistry(Server.port, Consul(host="localhost", port=8500))
|
|
121
|
+
return ConsulComponentRegistry(Server.port, Consul(host="localhost", port=8500)) # a consul based registry!
|
|
122
|
+
|
|
122
123
|
|
|
123
124
|
environment = Environment(Module)
|
|
124
|
-
service_manager = environment.
|
|
125
|
+
service_manager = environment.read(ServiceManager)
|
|
125
126
|
|
|
126
127
|
service = service_manager.get_service(TestService)
|
|
127
128
|
|
|
@@ -202,6 +203,14 @@ The library offers:
|
|
|
202
203
|
As well as the DI and AOP core, all mechanisms are heavily optimized.
|
|
203
204
|
A simple benchmark resulted in message roundtrips in significanlty under a ms per call.
|
|
204
205
|
|
|
206
|
+
## Installation
|
|
207
|
+
|
|
208
|
+
Just install from PyPI with
|
|
209
|
+
|
|
210
|
+
`pip install aspyx-service`
|
|
211
|
+
|
|
212
|
+
The library is tested with all Python version >= 3.9
|
|
213
|
+
|
|
205
214
|
Let's see some details
|
|
206
215
|
|
|
207
216
|
## Service and Component declaration
|
|
@@ -484,18 +493,26 @@ class ChannelAdvice:
|
|
|
484
493
|
|
|
485
494
|
## FastAPI server
|
|
486
495
|
|
|
487
|
-
|
|
496
|
+
The required - `FastAPI` - infrastructure to expose those services requires:
|
|
488
497
|
|
|
498
|
+
- a `FastAPI` instance
|
|
499
|
+
- an injectable `FastAPIServer`
|
|
500
|
+
- and a final `boot` call with the root module, which will return an `Environment`
|
|
489
501
|
|
|
490
502
|
```python
|
|
491
|
-
|
|
492
|
-
|
|
503
|
+
fast_api = FastAPI() # so you can run it with uvivorn from command-line
|
|
504
|
+
|
|
505
|
+
@module(imports=[ServiceModule])
|
|
506
|
+
class Module:
|
|
493
507
|
def __init__(self):
|
|
494
508
|
pass
|
|
509
|
+
|
|
510
|
+
@create()
|
|
511
|
+
def create_server(self, service_manager: ServiceManager, component_registry: ComponentRegistry) -> FastAPIServer:
|
|
512
|
+
return FastAPIServer(fastapi, service_manager, component_registry)
|
|
495
513
|
|
|
496
|
-
server = FastAPIServer(host="0.0.0.0", port=8000)
|
|
497
514
|
|
|
498
|
-
|
|
515
|
+
environment = FastAPIServer.boot(Moudle, host="0.0.0.0", port=8000)
|
|
499
516
|
```
|
|
500
517
|
|
|
501
518
|
This setup will also expose all service interfaces decorated with the corresponding http decorators!
|
|
@@ -73,18 +73,20 @@ class TestComponent(Component):
|
|
|
73
73
|
After booting the DI infrastructure with a main module we could already call a service:
|
|
74
74
|
|
|
75
75
|
**Example**:
|
|
76
|
+
|
|
76
77
|
```python
|
|
77
78
|
@module(imports=[ServiceModule])
|
|
78
79
|
class Module:
|
|
79
80
|
def __init__(self):
|
|
80
81
|
pass
|
|
81
|
-
|
|
82
|
+
|
|
82
83
|
@create()
|
|
83
84
|
def create_registry(self) -> ConsulComponentRegistry:
|
|
84
|
-
return ConsulComponentRegistry(Server.port, Consul(host="localhost", port=8500))
|
|
85
|
+
return ConsulComponentRegistry(Server.port, Consul(host="localhost", port=8500)) # a consul based registry!
|
|
86
|
+
|
|
85
87
|
|
|
86
88
|
environment = Environment(Module)
|
|
87
|
-
service_manager = environment.
|
|
89
|
+
service_manager = environment.read(ServiceManager)
|
|
88
90
|
|
|
89
91
|
service = service_manager.get_service(TestService)
|
|
90
92
|
|
|
@@ -165,6 +167,14 @@ The library offers:
|
|
|
165
167
|
As well as the DI and AOP core, all mechanisms are heavily optimized.
|
|
166
168
|
A simple benchmark resulted in message roundtrips in significanlty under a ms per call.
|
|
167
169
|
|
|
170
|
+
## Installation
|
|
171
|
+
|
|
172
|
+
Just install from PyPI with
|
|
173
|
+
|
|
174
|
+
`pip install aspyx-service`
|
|
175
|
+
|
|
176
|
+
The library is tested with all Python version >= 3.9
|
|
177
|
+
|
|
168
178
|
Let's see some details
|
|
169
179
|
|
|
170
180
|
## Service and Component declaration
|
|
@@ -447,18 +457,26 @@ class ChannelAdvice:
|
|
|
447
457
|
|
|
448
458
|
## FastAPI server
|
|
449
459
|
|
|
450
|
-
|
|
460
|
+
The required - `FastAPI` - infrastructure to expose those services requires:
|
|
451
461
|
|
|
462
|
+
- a `FastAPI` instance
|
|
463
|
+
- an injectable `FastAPIServer`
|
|
464
|
+
- and a final `boot` call with the root module, which will return an `Environment`
|
|
452
465
|
|
|
453
466
|
```python
|
|
454
|
-
|
|
455
|
-
|
|
467
|
+
fast_api = FastAPI() # so you can run it with uvivorn from command-line
|
|
468
|
+
|
|
469
|
+
@module(imports=[ServiceModule])
|
|
470
|
+
class Module:
|
|
456
471
|
def __init__(self):
|
|
457
472
|
pass
|
|
473
|
+
|
|
474
|
+
@create()
|
|
475
|
+
def create_server(self, service_manager: ServiceManager, component_registry: ComponentRegistry) -> FastAPIServer:
|
|
476
|
+
return FastAPIServer(fastapi, service_manager, component_registry)
|
|
458
477
|
|
|
459
|
-
server = FastAPIServer(host="0.0.0.0", port=8000)
|
|
460
478
|
|
|
461
|
-
|
|
479
|
+
environment = FastAPIServer.boot(Moudle, host="0.0.0.0", port=8000)
|
|
462
480
|
```
|
|
463
481
|
|
|
464
482
|
This setup will also expose all service interfaces decorated with the corresponding http decorators!
|
|
@@ -7,11 +7,12 @@ from dataclasses import dataclass
|
|
|
7
7
|
|
|
8
8
|
from pydantic import BaseModel
|
|
9
9
|
|
|
10
|
-
from aspyx.di import module
|
|
11
|
-
|
|
12
10
|
from aspyx_service import ServiceModule, delete, post, put, get, rest, Body
|
|
13
11
|
from aspyx_service.service import component, Component, Service, service
|
|
14
12
|
|
|
13
|
+
from aspyx.di import module
|
|
14
|
+
|
|
15
|
+
|
|
15
16
|
class Pydantic(BaseModel):
|
|
16
17
|
i: int
|
|
17
18
|
f: float
|
|
@@ -151,4 +152,4 @@ class TestComponent(Component): # pylint: disable=abstract-method
|
|
|
151
152
|
@module(imports=[ServiceModule])
|
|
152
153
|
class ClientModule:
|
|
153
154
|
def __init__(self):
|
|
154
|
-
pass
|
|
155
|
+
pass
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""
|
|
2
|
+
the server hosting the test services
|
|
3
|
+
"""
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
from fastapi import FastAPI
|
|
8
|
+
|
|
9
|
+
from aspyx_service import FastAPIServer, RequestContext
|
|
10
|
+
from server import ServerModule
|
|
11
|
+
from aspyx.util import Logger
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Logger.configure(default_level=logging.DEBUG, levels={
|
|
15
|
+
"httpx": logging.ERROR,
|
|
16
|
+
"aspyx.di": logging.ERROR,
|
|
17
|
+
"aspyx.di.aop": logging.ERROR,
|
|
18
|
+
"aspyx.service": logging.ERROR
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
PORT = int(os.getenv("FAST_API_PORT", "8000"))
|
|
22
|
+
|
|
23
|
+
app = FastAPI()
|
|
24
|
+
|
|
25
|
+
app.add_middleware(RequestContext)
|
|
26
|
+
#app.add_middleware(TokenContextMiddleware)
|
|
27
|
+
|
|
28
|
+
ServerModule.fastapi = app
|
|
29
|
+
|
|
30
|
+
FastAPIServer.boot(ServerModule, host="0.0.0.0", port=PORT, start_thread= False)
|
|
31
|
+
|
|
32
|
+
if __name__ == "__main__":
|
|
33
|
+
import uvicorn
|
|
34
|
+
uvicorn.run("main:app", host="0.0.0.0", port=PORT, reload=True, log_level="warning", access_log=False)
|
|
@@ -10,18 +10,20 @@ from typing import Callable, TypeVar, Type, Awaitable, Any, Dict, cast
|
|
|
10
10
|
|
|
11
11
|
from consul import Consul
|
|
12
12
|
|
|
13
|
+
from aspyx_service import ConsulComponentRegistry, SessionManager
|
|
14
|
+
|
|
13
15
|
from aspyx.di import module, Environment, create
|
|
14
16
|
from aspyx.di.aop import advice, around, methods, Invocation
|
|
15
17
|
from aspyx.util import Logger
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
|
|
18
20
|
from aspyx_service.service import ServiceManager, ComponentRegistry, Channel
|
|
19
21
|
|
|
20
|
-
Logger.configure(default_level=logging.
|
|
21
|
-
"httpx": logging.
|
|
22
|
-
"aspyx.di": logging.
|
|
23
|
-
"aspyx.di.aop": logging.
|
|
24
|
-
"aspyx.service": logging.
|
|
22
|
+
Logger.configure(default_level=logging.INFO, levels={
|
|
23
|
+
"httpx": logging.CRITICAL,
|
|
24
|
+
"aspyx.di": logging.INFO,
|
|
25
|
+
"aspyx.di.aop": logging.INFO,
|
|
26
|
+
"aspyx.service": logging.INFO
|
|
25
27
|
})
|
|
26
28
|
|
|
27
29
|
from client import TestService, TestRestService, Pydantic, Data, TestAsyncRestService, TestAsyncService, ClientModule
|
|
@@ -46,6 +48,10 @@ class TestModule:
|
|
|
46
48
|
def __init__(self):
|
|
47
49
|
pass
|
|
48
50
|
|
|
51
|
+
@create()
|
|
52
|
+
def create_session_storage(self) -> SessionManager.Storage:
|
|
53
|
+
return SessionManager.InMemoryStorage(max_size=1000, ttl=3600)
|
|
54
|
+
|
|
49
55
|
@create()
|
|
50
56
|
def create_registry(self) -> ComponentRegistry:
|
|
51
57
|
return ConsulComponentRegistry(port=8000, consul=Consul(host="localhost", port=8500))
|
|
@@ -207,7 +213,7 @@ async def main():
|
|
|
207
213
|
# async
|
|
208
214
|
|
|
209
215
|
await run_async_loops("async rest", loops, TestAsyncRestService, manager.get_service(TestAsyncRestService, preferred_channel="rest"),
|
|
210
|
-
|
|
216
|
+
lambda service: service.get("world"))
|
|
211
217
|
await run_async_loops("async json", loops, TestAsyncService, manager.get_service(TestAsyncService, preferred_channel="dispatch-json"),
|
|
212
218
|
lambda service: service.hello("world"))
|
|
213
219
|
await run_async_loops("async msgpack", loops, TestAsyncService, manager.get_service(TestAsyncService, preferred_channel="dispatch-msgpack"),
|
|
@@ -276,4 +282,4 @@ async def main():
|
|
|
276
282
|
lambda service: service.hello("world"))
|
|
277
283
|
|
|
278
284
|
if __name__ == "__main__":
|
|
279
|
-
asyncio.run(main())
|
|
285
|
+
asyncio.run(main())
|
|
@@ -5,15 +5,19 @@ import os
|
|
|
5
5
|
from typing import Optional
|
|
6
6
|
|
|
7
7
|
from consul import Consul
|
|
8
|
+
from fastapi import FastAPI
|
|
8
9
|
|
|
10
|
+
from aspyx_service import HealthCheckManager, ServiceModule, ConsulComponentRegistry, SessionManager, FastAPIServer
|
|
11
|
+
|
|
12
|
+
from client import ClientModule, TestService, TestAsyncService, Data, Pydantic, TestRestService, TestAsyncRestService, TestComponent
|
|
13
|
+
|
|
14
|
+
from aspyx_service.service import ChannelAddress, Server, \
|
|
15
|
+
component_services, AbstractComponent, implementation, health, ComponentRegistry, ServiceManager
|
|
9
16
|
from aspyx.di import on_running, module, create
|
|
10
17
|
from aspyx.di.aop import Invocation, advice, error
|
|
11
18
|
from aspyx.exception import handle, ExceptionManager
|
|
12
|
-
from aspyx_service import HealthCheckManager, ServiceModule, ConsulComponentRegistry
|
|
13
|
-
from aspyx_service.service import ChannelAddress, Server, \
|
|
14
|
-
component_services, AbstractComponent, implementation, health, ComponentRegistry
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
|
|
17
21
|
|
|
18
22
|
|
|
19
23
|
# implementation classes
|
|
@@ -142,6 +146,8 @@ class TestComponentImpl(AbstractComponent, TestComponent):
|
|
|
142
146
|
|
|
143
147
|
@module(imports=[ClientModule, ServiceModule])
|
|
144
148
|
class ServerModule:
|
|
149
|
+
fastapi: Optional[FastAPI] = None
|
|
150
|
+
|
|
145
151
|
def __init__(self):
|
|
146
152
|
pass
|
|
147
153
|
|
|
@@ -149,6 +155,14 @@ class ServerModule:
|
|
|
149
155
|
#def create_yaml_source(self) -> YamlConfigurationSource:
|
|
150
156
|
# return YamlConfigurationSource(f"{Path(__file__).parent}/config.yaml")
|
|
151
157
|
|
|
158
|
+
@create()
|
|
159
|
+
def create_server(self, service_manager: ServiceManager, component_registry: ComponentRegistry) -> FastAPIServer:
|
|
160
|
+
return FastAPIServer(self.fastapi, service_manager, component_registry)
|
|
161
|
+
|
|
162
|
+
@create()
|
|
163
|
+
def create_session_storage(self) -> SessionManager.Storage:
|
|
164
|
+
return SessionManager.InMemoryStorage(max_size=1000, ttl=3600)
|
|
165
|
+
|
|
152
166
|
@create()
|
|
153
167
|
def create_registry(self) -> ComponentRegistry:
|
|
154
|
-
return ConsulComponentRegistry(port=int(os.getenv("FAST_API_PORT", 8000)), consul=Consul(host="localhost", port=8500))
|
|
168
|
+
return ConsulComponentRegistry(port=int(os.getenv("FAST_API_PORT", "8000")), consul=Consul(host="localhost", port=8500))
|
|
@@ -2,19 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
[project]
|
|
4
4
|
name = "aspyx_service"
|
|
5
|
-
version = "0.10.
|
|
5
|
+
version = "0.10.6"
|
|
6
6
|
description = "Aspyx Service framework"
|
|
7
7
|
authors = [{ name = "Andreas Ernst", email = "andreas.ernst7@gmail.com" }]
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
license = { file = "LICENSE" }
|
|
10
10
|
requires-python = ">=3.9"
|
|
11
11
|
dependencies = [
|
|
12
|
-
"aspyx>=1.
|
|
12
|
+
"aspyx>=1.6.0",
|
|
13
13
|
"python-consul2~=0.1.5",
|
|
14
14
|
"fastapi~=0.115.13",
|
|
15
15
|
"httpx~=0.28.1",
|
|
16
16
|
"msgpack~=1.1.1",
|
|
17
|
-
"cachetools~= 5.5.2",
|
|
18
17
|
"uvicorn[standard]"
|
|
19
18
|
]
|
|
20
19
|
|
|
@@ -7,12 +7,11 @@ from aspyx.di import module
|
|
|
7
7
|
from .service import AuthorizationException, MissingTokenException, RemoteServiceException, ServiceCommunicationException, TokenException, TokenExpiredException, InvalidTokenException, component_services, ServiceException, Server, Channel, ComponentDescriptor, inject_service, ChannelAddress, ChannelInstances, ServiceManager, Component, Service, AbstractComponent, ComponentStatus, ComponentRegistry, implementation, health, component, service
|
|
8
8
|
from .channels import HTTPXChannel, DispatchJSONChannel, TokenContext
|
|
9
9
|
from .registries import ConsulComponentRegistry
|
|
10
|
-
from .server import FastAPIServer, RequestContext
|
|
10
|
+
from .server import FastAPIServer, RequestContext, ResponseContext, TokenContextMiddleware
|
|
11
11
|
from .healthcheck import health_checks, health_check, HealthCheckManager, HealthStatus
|
|
12
12
|
from .restchannel import RestChannel, post, get, put, delete, QueryParam, Body, rest
|
|
13
|
-
from .session import Session, SessionManager
|
|
14
|
-
from .authorization import AuthorizationManager, AbstractAuthorizationFactory
|
|
15
|
-
|
|
13
|
+
from .session import Session, SessionManager, SessionContext
|
|
14
|
+
from .authorization import AuthorizationManager, AbstractAuthorizationFactory
|
|
16
15
|
|
|
17
16
|
@module()
|
|
18
17
|
class ServiceModule:
|
|
@@ -53,12 +52,12 @@ __all__ = [
|
|
|
53
52
|
|
|
54
53
|
"AuthorizationManager",
|
|
55
54
|
"AbstractAuthorizationFactory",
|
|
56
|
-
"AuthorizationException",
|
|
57
55
|
|
|
58
56
|
# session
|
|
59
57
|
|
|
60
58
|
"Session",
|
|
61
59
|
"SessionManager",
|
|
60
|
+
"SessionContext",
|
|
62
61
|
|
|
63
62
|
# healthcheck
|
|
64
63
|
|
|
@@ -91,10 +90,12 @@ __all__ = [
|
|
|
91
90
|
# registries
|
|
92
91
|
|
|
93
92
|
"ConsulComponentRegistry",
|
|
94
|
-
"RequestContext",
|
|
95
93
|
|
|
96
94
|
# server
|
|
97
95
|
|
|
98
96
|
"FastAPIServer",
|
|
99
|
-
"RequestContext"
|
|
97
|
+
"RequestContext",
|
|
98
|
+
"ResponseContext",
|
|
99
|
+
"TokenContext",
|
|
100
|
+
"TokenContextMiddleware",
|
|
100
101
|
]
|
|
@@ -9,13 +9,6 @@ from aspyx.di import injectable, inject, order
|
|
|
9
9
|
from aspyx.di.aop import Invocation
|
|
10
10
|
from aspyx.reflection import TypeDescriptor, Decorators
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
class AuthorizationException(Exception):
|
|
14
|
-
"""
|
|
15
|
-
Any authorization exception
|
|
16
|
-
"""
|
|
17
|
-
pass
|
|
18
|
-
|
|
19
12
|
def get_method_class(method):
|
|
20
13
|
if inspect.ismethod(method) or inspect.isfunction(method):
|
|
21
14
|
qualname = method.__qualname__
|
|
@@ -38,11 +31,10 @@ class AuthorizationManager:
|
|
|
38
31
|
"""
|
|
39
32
|
Base class for authorization checks
|
|
40
33
|
"""
|
|
41
|
-
def
|
|
34
|
+
def authorize(self, invocation: Invocation):
|
|
42
35
|
"""
|
|
43
|
-
execute the authorization check. Throws an exception in case of violations
|
|
36
|
+
execute the authorization check. Throws an exception in case of violations
|
|
44
37
|
"""
|
|
45
|
-
pass
|
|
46
38
|
|
|
47
39
|
class AuthorizationFactory(ABC):
|
|
48
40
|
"""
|
|
@@ -62,7 +54,6 @@ class AuthorizationManager:
|
|
|
62
54
|
Returns:
|
|
63
55
|
an authorization check or None
|
|
64
56
|
"""
|
|
65
|
-
pass
|
|
66
57
|
|
|
67
58
|
# constructor
|
|
68
59
|
|
|
@@ -111,9 +102,9 @@ class AuthorizationManager:
|
|
|
111
102
|
|
|
112
103
|
return checks
|
|
113
104
|
|
|
114
|
-
def
|
|
105
|
+
def authorize(self, invocation: Invocation):
|
|
115
106
|
for check in self.get_checks(invocation.func):
|
|
116
|
-
check.
|
|
107
|
+
check.authorize(invocation)
|
|
117
108
|
|
|
118
109
|
class AbstractAuthorizationFactory(AuthorizationManager.AuthorizationFactory):
|
|
119
110
|
"""
|
|
@@ -16,11 +16,11 @@ from pydantic import BaseModel
|
|
|
16
16
|
from aspyx.di.configuration import inject_value
|
|
17
17
|
from aspyx.reflection import DynamicProxy, TypeDescriptor
|
|
18
18
|
from aspyx.threading import ThreadLocal, ContextLocal
|
|
19
|
+
from aspyx.util import get_deserializer, TypeDeserializer, TypeSerializer, get_serializer
|
|
19
20
|
from .service import ServiceManager, ServiceCommunicationException, TokenExpiredException, InvalidTokenException, \
|
|
20
21
|
AuthorizationException, MissingTokenException
|
|
21
22
|
|
|
22
23
|
from .service import ComponentDescriptor, ChannelInstances, ServiceException, channel, Channel, RemoteServiceException
|
|
23
|
-
from .serialization import get_deserializer, TypeDeserializer, TypeSerializer, get_serializer
|
|
24
24
|
|
|
25
25
|
class TokenContext:
|
|
26
26
|
"""
|
|
@@ -208,10 +208,11 @@ class HTTPXChannel(Channel):
|
|
|
208
208
|
if "invalid_token" in www_auth:
|
|
209
209
|
if 'expired' in www_auth:
|
|
210
210
|
raise TokenExpiredException() from e
|
|
211
|
-
|
|
211
|
+
|
|
212
|
+
if 'missing' in www_auth:
|
|
212
213
|
raise MissingTokenException() from e
|
|
213
|
-
|
|
214
|
-
|
|
214
|
+
|
|
215
|
+
raise InvalidTokenException() from e
|
|
215
216
|
|
|
216
217
|
raise AuthorizationException(str(e)) from e
|
|
217
218
|
except httpx.HTTPError as e:
|
|
@@ -451,10 +452,11 @@ class DispatchMSPackChannel(HTTPXChannel):
|
|
|
451
452
|
if "invalid_token" in www_auth:
|
|
452
453
|
if 'expired' in www_auth:
|
|
453
454
|
raise TokenExpiredException() from e
|
|
454
|
-
|
|
455
|
+
|
|
456
|
+
if 'missing' in www_auth:
|
|
455
457
|
raise MissingTokenException() from e
|
|
456
|
-
|
|
457
|
-
|
|
458
|
+
|
|
459
|
+
raise InvalidTokenException() from e
|
|
458
460
|
|
|
459
461
|
raise RemoteServiceException(str(e)) from e
|
|
460
462
|
|
|
@@ -6,19 +6,15 @@ import re
|
|
|
6
6
|
from dataclasses import is_dataclass
|
|
7
7
|
|
|
8
8
|
from typing import get_type_hints, TypeVar, Annotated, Callable, get_origin, get_args, Type
|
|
9
|
-
|
|
10
|
-
|
|
11
9
|
from pydantic import BaseModel
|
|
12
10
|
|
|
13
|
-
from .channels import HTTPXChannel
|
|
14
|
-
|
|
15
11
|
from aspyx.reflection import DynamicProxy, Decorators
|
|
12
|
+
|
|
13
|
+
from .channels import HTTPXChannel
|
|
16
14
|
from .service import channel, ServiceCommunicationException
|
|
17
15
|
|
|
18
16
|
T = TypeVar("T")
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
18
|
class BodyMarker:
|
|
23
19
|
pass
|
|
24
20
|
|