alpha-python 0.6.3__tar.gz → 0.7.1__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.
- {alpha_python-0.6.3 → alpha_python-0.7.1}/PKG-INFO +1 -1
- {alpha_python-0.6.3 → alpha_python-0.7.1}/pyproject.toml +1 -1
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/__init__.py +19 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/__init__.py +7 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/api_repository.py +5 -5
- alpha_python-0.7.1/src/alpha/interfaces/http_client.py +61 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/providers.py +6 -2
- alpha_python-0.7.1/src/alpha/interfaces/refresh_repository.py +60 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/providers/models/token.py +47 -9
- alpha_python-0.7.1/src/alpha/repositories/__init__.py +25 -0
- alpha_python-0.7.1/src/alpha/repositories/refresh/__init__.py +19 -0
- alpha_python-0.7.1/src/alpha/repositories/refresh/cache_repository.py +57 -0
- alpha_python-0.7.1/src/alpha/repositories/refresh/database_repository.py +145 -0
- alpha_python-0.7.1/src/alpha/repositories/refresh/file_repository.py +167 -0
- alpha_python-0.7.1/src/alpha/repositories/refresh/memory_repository.py +122 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/repositories/rest_api_repository.py +100 -32
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/services/authentication_service.py +98 -405
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/openapi_test/container.py +10 -2
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/openapi_test/models.py +48 -10
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha_python.egg-info/PKG-INFO +1 -1
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha_python.egg-info/SOURCES.txt +7 -0
- alpha_python-0.6.3/src/alpha/repositories/__init__.py +0 -9
- {alpha_python-0.6.3 → alpha_python-0.7.1}/LICENSE +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/README.md +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/setup.cfg +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/adapters/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/adapters/rest_api_unit_of_work.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/adapters/sqla_unit_of_work.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/cli.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/containers/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/containers/container.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/domain/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/domain/models/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/domain/models/base_model.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/domain/models/group.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/domain/models/life_cycle_base.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/domain/models/role.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/domain/models/user.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/encoder.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/exceptions.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/_type_conversion_matrix.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/_type_mapping.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/class_factories.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/default_field_factory.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/field_iterator.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/jwt_factory.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/logging_handler_factory.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/model_class_factory.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/models/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/models/factory_classes.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/password_factory.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/request_factory.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/response_factory.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/factories/type_factories.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/api_generate_handler.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/api_run_handler.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/base_handler.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/gen-code.sh +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/models/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/models/argument.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/models/command.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/models/section.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/models/subparser.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/run-api.sh +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/Dockerfile.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/README.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/__init__model.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/__init__test.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/__main__.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/base_model.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/controller.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/controller_test.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/dockerignore.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/encoder.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/git_push.sh.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/gitignore.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/model.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/openapi.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/param_type.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/requirements.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/security_controller_.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/setup.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/test-requirements.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/tox.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/travis.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/typing_utils.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/handlers/templates/python-flask/util.mustache +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/connectors/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/connectors/ldap_connector.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/connectors/oidc_connector.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/connectors/sql_alchemy.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/databases/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/databases/sql_alchemy.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/models/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/models/filter_operators.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/models/json_patch.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/models/order_by.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/models/query_clause.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/infra/models/search_filter.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/attrs_instance.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/dataclass_instance.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/factories.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/handler.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/openapi_model.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/patchable.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/pydantic_instance.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/sql_database.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/sql_mapper.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/sql_repository.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/token_factory.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/unit_of_work.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/interfaces/updatable.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/mixins/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/mixins/group_lifecycle.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/mixins/jwt_provider.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/mixins/user_lifecycle.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/providers/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/providers/api_key_provider.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/providers/database_provider.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/providers/ldap_provider.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/providers/models/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/providers/models/credentials.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/providers/models/identity.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/providers/oidc_provider.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/py.typed +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/repositories/models/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/repositories/models/repository_model.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/repositories/sql_alchemy_repository.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/services/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/services/models/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/services/models/cookie.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/services/user_lifecycle_management.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/_http_codes.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/cookie.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/is_attrs.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/is_pydantic.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/logging_configurator.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/logging_level_checker.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/openapi_test/__init__.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/openapi_test/exceptions.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/openapi_test/orm.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/openapi_test/response.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/openapi_test/service.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/request_headers.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/response_object.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/secret_generator.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/verify_identity.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha/utils/version_checker.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha_python.egg-info/dependency_links.txt +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha_python.egg-info/entry_points.txt +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha_python.egg-info/requires.txt +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/src/alpha_python.egg-info/top_level.txt +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/tests/test_cli.py +0 -0
- {alpha_python-0.6.3 → alpha_python-0.7.1}/tests/test_encoder.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: alpha-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Alpha is intended to be the first dependency you need to add to your Python application. It is a Python library which contains standard building blocks that can be used in applications that are used as APIs and/or make use of database interaction.
|
|
5
5
|
Author-email: Bart Reijling <bart@reijling.eu>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "alpha-python"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.1"
|
|
4
4
|
description = "Alpha is intended to be the first dependency you need to add to your Python application. It is a Python library which contains standard building blocks that can be used in applications that are used as APIs and/or make use of database interaction."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -30,6 +30,7 @@ from alpha.interfaces.pydantic_instance import PydanticInstance
|
|
|
30
30
|
from alpha.interfaces.openapi_model import OpenAPIModel
|
|
31
31
|
from alpha.interfaces.updatable import Updatable
|
|
32
32
|
from alpha.interfaces.patchable import Patchable
|
|
33
|
+
from alpha.interfaces.http_client import HTTPClient, HTTPResponse
|
|
33
34
|
from alpha.interfaces.api_repository import ApiRepository
|
|
34
35
|
from alpha.interfaces.sql_repository import SqlRepository
|
|
35
36
|
from alpha.interfaces.sql_mapper import SqlMapper
|
|
@@ -64,6 +65,18 @@ from alpha.providers.oidc_provider import (
|
|
|
64
65
|
from alpha.repositories.models.repository_model import RepositoryModel
|
|
65
66
|
from alpha.repositories.rest_api_repository import RestApiRepository
|
|
66
67
|
from alpha.repositories.sql_alchemy_repository import SqlAlchemyRepository
|
|
68
|
+
from alpha.repositories.refresh.cache_repository import (
|
|
69
|
+
CacheRefreshRepository,
|
|
70
|
+
)
|
|
71
|
+
from alpha.repositories.refresh.database_repository import (
|
|
72
|
+
DatabaseRefreshRepository,
|
|
73
|
+
)
|
|
74
|
+
from alpha.repositories.refresh.file_repository import (
|
|
75
|
+
FileRefreshRepository,
|
|
76
|
+
)
|
|
77
|
+
from alpha.repositories.refresh.memory_repository import (
|
|
78
|
+
MemoryRefreshRepository,
|
|
79
|
+
)
|
|
67
80
|
from alpha.services.authentication_service import AuthenticationService
|
|
68
81
|
from alpha.services.user_lifecycle_management import UserLifecycleManagement
|
|
69
82
|
from alpha.utils.is_attrs import is_attrs
|
|
@@ -128,6 +141,8 @@ __all__ = [
|
|
|
128
141
|
"OpenAPIModel",
|
|
129
142
|
"Updatable",
|
|
130
143
|
"Patchable",
|
|
144
|
+
"HTTPClient",
|
|
145
|
+
"HTTPResponse",
|
|
131
146
|
"ApiRepository",
|
|
132
147
|
"SqlRepository",
|
|
133
148
|
"SqlMapper",
|
|
@@ -156,6 +171,10 @@ __all__ = [
|
|
|
156
171
|
"RepositoryModel",
|
|
157
172
|
"RestApiRepository",
|
|
158
173
|
"SqlAlchemyRepository",
|
|
174
|
+
"CacheRefreshRepository",
|
|
175
|
+
"DatabaseRefreshRepository",
|
|
176
|
+
"FileRefreshRepository",
|
|
177
|
+
"MemoryRefreshRepository",
|
|
159
178
|
"AuthenticationService",
|
|
160
179
|
"UserLifecycleManagement",
|
|
161
180
|
"is_attrs",
|
|
@@ -6,9 +6,13 @@ from alpha.interfaces.openapi_model import OpenAPIModel
|
|
|
6
6
|
from alpha.interfaces.updatable import Updatable
|
|
7
7
|
from alpha.interfaces.patchable import Patchable
|
|
8
8
|
|
|
9
|
+
# import all http client related interfaces
|
|
10
|
+
from alpha.interfaces.http_client import HTTPClient, HTTPResponse
|
|
11
|
+
|
|
9
12
|
# import all repository related interfaces
|
|
10
13
|
from alpha.interfaces.api_repository import ApiRepository
|
|
11
14
|
from alpha.interfaces.sql_repository import SqlRepository
|
|
15
|
+
from alpha.interfaces.refresh_repository import RefreshRepository
|
|
12
16
|
|
|
13
17
|
# import all database related interfaces
|
|
14
18
|
from alpha.interfaces.sql_mapper import SqlMapper
|
|
@@ -33,8 +37,11 @@ __all__ = [
|
|
|
33
37
|
"OpenAPIModel",
|
|
34
38
|
"Updatable",
|
|
35
39
|
"Patchable",
|
|
40
|
+
"HTTPClient",
|
|
41
|
+
"HTTPResponse",
|
|
36
42
|
"ApiRepository",
|
|
37
43
|
"SqlRepository",
|
|
44
|
+
"RefreshRepository",
|
|
38
45
|
"SqlMapper",
|
|
39
46
|
"SqlDatabase",
|
|
40
47
|
"UnitOfWork",
|
|
@@ -263,7 +263,7 @@ class ApiRepository(Protocol[DomainModel]):
|
|
|
263
263
|
Whether to use the model factory method for creating models from
|
|
264
264
|
response data.
|
|
265
265
|
endpoint
|
|
266
|
-
The API endpoint
|
|
266
|
+
The API endpoint from which the object should be retrieved.
|
|
267
267
|
parent_endpoint
|
|
268
268
|
The parent API endpoint, if the resource is nested under a parent
|
|
269
269
|
resource.
|
|
@@ -340,7 +340,7 @@ class ApiRepository(Protocol[DomainModel]):
|
|
|
340
340
|
Whether to use the model factory method for creating models from
|
|
341
341
|
response data.
|
|
342
342
|
endpoint
|
|
343
|
-
The API endpoint
|
|
343
|
+
The API endpoint from which the objects should be retrieved.
|
|
344
344
|
parent_endpoint
|
|
345
345
|
The parent API endpoint, if the resource is nested under a parent
|
|
346
346
|
resource.
|
|
@@ -441,7 +441,7 @@ class ApiRepository(Protocol[DomainModel]):
|
|
|
441
441
|
Whether to use the model factory method for creating models from
|
|
442
442
|
response data.
|
|
443
443
|
endpoint
|
|
444
|
-
The API endpoint to which the
|
|
444
|
+
The API endpoint to which the patch should be applied.
|
|
445
445
|
parent_endpoint
|
|
446
446
|
The parent API endpoint, if the resource is nested under a parent
|
|
447
447
|
resource.
|
|
@@ -485,7 +485,7 @@ class ApiRepository(Protocol[DomainModel]):
|
|
|
485
485
|
Parameters
|
|
486
486
|
----------
|
|
487
487
|
endpoint
|
|
488
|
-
The API endpoint
|
|
488
|
+
The API endpoint from which the object should be removed.
|
|
489
489
|
parent_endpoint
|
|
490
490
|
The parent API endpoint, if the resource is nested under a parent
|
|
491
491
|
resource.
|
|
@@ -585,7 +585,7 @@ class ApiRepository(Protocol[DomainModel]):
|
|
|
585
585
|
Whether to use the model factory method for creating models from
|
|
586
586
|
response data.
|
|
587
587
|
endpoint
|
|
588
|
-
The API endpoint to which the object should be
|
|
588
|
+
The API endpoint to which the object should be updated.
|
|
589
589
|
parent_endpoint
|
|
590
590
|
The parent API endpoint, if the resource is nested under a parent
|
|
591
591
|
resource.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from typing import MutableMapping, Protocol, Any, runtime_checkable
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@runtime_checkable
|
|
5
|
+
class HTTPResponse(Protocol):
|
|
6
|
+
"""Interface for HTTP response objects returned by HTTP clients.
|
|
7
|
+
|
|
8
|
+
This interface is compatible with the response objects returned by popular
|
|
9
|
+
synchronous HTTP client libraries, for example, the `requests` library,
|
|
10
|
+
`httpx` library or any custom implementation that follows the same
|
|
11
|
+
attributes and method signatures.
|
|
12
|
+
|
|
13
|
+
This interface defines the attributes and methods that an HTTP response
|
|
14
|
+
object should have to be compatible with the REST API repository. It
|
|
15
|
+
includes attributes for accessing the response status code, headers, and
|
|
16
|
+
content, as well as a method for parsing the response content as JSON.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
status_code: int
|
|
20
|
+
headers: dict[str, str]
|
|
21
|
+
content: bytes
|
|
22
|
+
text: str
|
|
23
|
+
|
|
24
|
+
def json(self) -> Any: ...
|
|
25
|
+
def raise_for_status(self) -> None: ...
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@runtime_checkable
|
|
29
|
+
class HTTPClient(Protocol):
|
|
30
|
+
"""Interface for HTTP clients like requests, httpx or a custom
|
|
31
|
+
implementation.
|
|
32
|
+
|
|
33
|
+
This interface is compatible with the popular synchronous HTTP client
|
|
34
|
+
libraries, for example, the `requests` library, `httpx` library or any
|
|
35
|
+
custom implementation that follows the same method signatures.
|
|
36
|
+
|
|
37
|
+
This interface defines the methods that an HTTP client should implement to
|
|
38
|
+
be compatible with the REST API repository. It includes methods for making
|
|
39
|
+
HTTP requests (POST, GET, DELETE, PUT, PATCH) and allows for additional
|
|
40
|
+
parameters to be passed as needed.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
cookies: MutableMapping[str, str]
|
|
44
|
+
headers: MutableMapping[str, str]
|
|
45
|
+
|
|
46
|
+
def request(
|
|
47
|
+
self, method: str, url: str, **kwargs: Any
|
|
48
|
+
) -> HTTPResponse: ...
|
|
49
|
+
def close(self) -> None: ...
|
|
50
|
+
|
|
51
|
+
def post(
|
|
52
|
+
self, url: str, json: Any = None, **kwargs: Any
|
|
53
|
+
) -> HTTPResponse: ...
|
|
54
|
+
def get(self, url: str, **kwargs: Any) -> HTTPResponse: ...
|
|
55
|
+
def delete(self, url: str, **kwargs: Any) -> HTTPResponse: ...
|
|
56
|
+
def put(
|
|
57
|
+
self, url: str, json: Any = None, **kwargs: Any
|
|
58
|
+
) -> HTTPResponse: ...
|
|
59
|
+
def patch(
|
|
60
|
+
self, url: str, json: Any = None, **kwargs: Any
|
|
61
|
+
) -> HTTPResponse: ...
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"""This module contains interfaces for various types of identity providers."""
|
|
2
2
|
|
|
3
|
-
from typing import ClassVar, Protocol, runtime_checkable
|
|
3
|
+
from typing import TYPE_CHECKING, ClassVar, Protocol, runtime_checkable, Any
|
|
4
4
|
|
|
5
5
|
from alpha.interfaces.token_factory import TokenFactory
|
|
6
6
|
from alpha.providers.models.credentials import PasswordCredentials
|
|
7
7
|
from alpha.providers.models.identity import Identity
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from alpha.providers.models.token import Token
|
|
11
|
+
else:
|
|
12
|
+
Token = Any
|
|
9
13
|
|
|
10
14
|
|
|
11
15
|
@runtime_checkable
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Protocol, Any
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from alpha.providers.models.token import Token
|
|
5
|
+
else:
|
|
6
|
+
Token = Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class RefreshRepository(Protocol):
|
|
10
|
+
"""Repository interface for managing refresh tokens."""
|
|
11
|
+
|
|
12
|
+
def get(self, token: str) -> Token:
|
|
13
|
+
"""Get a token by its value.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
token
|
|
18
|
+
Token value.
|
|
19
|
+
|
|
20
|
+
Returns
|
|
21
|
+
-------
|
|
22
|
+
Token
|
|
23
|
+
Token object with the given token value.
|
|
24
|
+
"""
|
|
25
|
+
...
|
|
26
|
+
|
|
27
|
+
def create(self, subject: str) -> Token:
|
|
28
|
+
"""Create a new token for a given subject.
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
subject
|
|
33
|
+
Subject identifier
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
Token
|
|
38
|
+
Newly created token object.
|
|
39
|
+
"""
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
def delete(self, token: str) -> None:
|
|
43
|
+
"""Delete a token by its value.
|
|
44
|
+
|
|
45
|
+
Parameters
|
|
46
|
+
----------
|
|
47
|
+
token
|
|
48
|
+
Token value.
|
|
49
|
+
"""
|
|
50
|
+
...
|
|
51
|
+
|
|
52
|
+
def delete_all(self, subject: str) -> None:
|
|
53
|
+
"""Delete all tokens for a given subject.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
subject
|
|
58
|
+
Subject identifier.
|
|
59
|
+
"""
|
|
60
|
+
...
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
from uuid import UUID
|
|
2
|
-
from datetime import datetime
|
|
2
|
+
from datetime import datetime, timedelta, timezone
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from typing import Any, Literal
|
|
5
5
|
|
|
6
6
|
from alpha.domain.models.base_model import BaseDomainModel
|
|
7
|
+
from alpha.utils.secret_generator import generate_secret
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
@dataclass
|
|
@@ -79,6 +80,40 @@ class Token(BaseDomainModel):
|
|
|
79
80
|
),
|
|
80
81
|
)
|
|
81
82
|
|
|
83
|
+
@classmethod
|
|
84
|
+
def create_refresh(
|
|
85
|
+
cls,
|
|
86
|
+
subject: str,
|
|
87
|
+
max_age_seconds: int = 7 * 24 * 3600,
|
|
88
|
+
token_length: int = 32,
|
|
89
|
+
) -> "Token":
|
|
90
|
+
"""Factory method to create a new Refresh Token instance.
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
subject
|
|
95
|
+
The subject or user associated with the token.
|
|
96
|
+
max_age_seconds
|
|
97
|
+
Optional maximum age of the token in seconds. Defaults to 7 days.
|
|
98
|
+
If provided, the expires_at will be set to created_at +
|
|
99
|
+
max_age_seconds.
|
|
100
|
+
token_length
|
|
101
|
+
Optional length of the token value. Defaults to 32.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
Token
|
|
106
|
+
A new Refresh Token instance with the provided attributes and generated id and created_at.
|
|
107
|
+
"""
|
|
108
|
+
return cls(
|
|
109
|
+
value=generate_secret(token_length),
|
|
110
|
+
token_type="Refresh",
|
|
111
|
+
subject=subject,
|
|
112
|
+
created_at=datetime.now(tz=timezone.utc),
|
|
113
|
+
expires_at=datetime.now(tz=timezone.utc)
|
|
114
|
+
+ timedelta(seconds=max_age_seconds),
|
|
115
|
+
)
|
|
116
|
+
|
|
82
117
|
def to_dict(self) -> dict[str, str | None]:
|
|
83
118
|
"""Converts the Token instance to a dictionary.
|
|
84
119
|
|
|
@@ -97,15 +132,18 @@ class Token(BaseDomainModel):
|
|
|
97
132
|
- "expires_at": ISO format datetime string for when the token
|
|
98
133
|
expires or None.
|
|
99
134
|
"""
|
|
100
|
-
|
|
101
|
-
|
|
135
|
+
|
|
136
|
+
obj: dict[str, str | None] = {
|
|
102
137
|
"value": self.value,
|
|
103
138
|
"subject": self.subject,
|
|
104
139
|
"token_type": self.token_type,
|
|
105
|
-
"created_at": (
|
|
106
|
-
self.created_at.isoformat() if self.created_at else None
|
|
107
|
-
),
|
|
108
|
-
"expires_at": (
|
|
109
|
-
self.expires_at.isoformat() if self.expires_at else None
|
|
110
|
-
),
|
|
111
140
|
}
|
|
141
|
+
|
|
142
|
+
if self.id:
|
|
143
|
+
obj["id"] = str(self.id)
|
|
144
|
+
if self.created_at:
|
|
145
|
+
obj["created_at"] = self.created_at.isoformat()
|
|
146
|
+
if self.expires_at:
|
|
147
|
+
obj["expires_at"] = self.expires_at.isoformat()
|
|
148
|
+
|
|
149
|
+
return obj
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from alpha.repositories.models.repository_model import RepositoryModel
|
|
2
|
+
from alpha.repositories.refresh.cache_repository import (
|
|
3
|
+
CacheRefreshRepository,
|
|
4
|
+
)
|
|
5
|
+
from alpha.repositories.refresh.database_repository import (
|
|
6
|
+
DatabaseRefreshRepository,
|
|
7
|
+
)
|
|
8
|
+
from alpha.repositories.refresh.file_repository import (
|
|
9
|
+
FileRefreshRepository,
|
|
10
|
+
)
|
|
11
|
+
from alpha.repositories.refresh.memory_repository import (
|
|
12
|
+
MemoryRefreshRepository,
|
|
13
|
+
)
|
|
14
|
+
from alpha.repositories.rest_api_repository import RestApiRepository
|
|
15
|
+
from alpha.repositories.sql_alchemy_repository import SqlAlchemyRepository
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"RepositoryModel",
|
|
19
|
+
"RestApiRepository",
|
|
20
|
+
"SqlAlchemyRepository",
|
|
21
|
+
"CacheRefreshRepository",
|
|
22
|
+
"DatabaseRefreshRepository",
|
|
23
|
+
"FileRefreshRepository",
|
|
24
|
+
"MemoryRefreshRepository",
|
|
25
|
+
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from alpha.repositories.refresh.cache_repository import (
|
|
2
|
+
CacheRefreshRepository,
|
|
3
|
+
)
|
|
4
|
+
from alpha.repositories.refresh.database_repository import (
|
|
5
|
+
DatabaseRefreshRepository,
|
|
6
|
+
)
|
|
7
|
+
from alpha.repositories.refresh.file_repository import (
|
|
8
|
+
FileRefreshRepository,
|
|
9
|
+
)
|
|
10
|
+
from alpha.repositories.refresh.memory_repository import (
|
|
11
|
+
MemoryRefreshRepository,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"CacheRefreshRepository",
|
|
16
|
+
"DatabaseRefreshRepository",
|
|
17
|
+
"FileRefreshRepository",
|
|
18
|
+
"MemoryRefreshRepository",
|
|
19
|
+
]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from alpha.providers.models.token import Token
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CacheRefreshRepository:
|
|
7
|
+
def __init__(
|
|
8
|
+
self,
|
|
9
|
+
cache_connector: Any,
|
|
10
|
+
token_model: type[Token] = Token,
|
|
11
|
+
token_max_age_seconds: int = 7 * 24 * 3600,
|
|
12
|
+
token_length: int = 32,
|
|
13
|
+
):
|
|
14
|
+
"""Initialize the CacheRefreshRepository with the given cache connector.
|
|
15
|
+
|
|
16
|
+
*** This class is not fully implemented yet. The methods are defined
|
|
17
|
+
but not implemented. ***
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
cache_connector
|
|
22
|
+
The cache connector instance to use for cache operations.
|
|
23
|
+
token_model
|
|
24
|
+
The model class for tokens, by default Token. The model class
|
|
25
|
+
should have a `from_dict` class method that takes a dictionary and
|
|
26
|
+
returns an instance of the model. The dictionary will have the same
|
|
27
|
+
structure as the token data in the JSON file. The model class
|
|
28
|
+
should also have a `to_dict` method that converts an instance of
|
|
29
|
+
the model to a dictionary with the same structure as the token data
|
|
30
|
+
in the JSON file. The model class should also have a
|
|
31
|
+
`create_refresh` class method that creates a new refresh token.
|
|
32
|
+
token_max_age_seconds
|
|
33
|
+
The maximum age of a token in seconds, by default the equivalent of
|
|
34
|
+
7 days in seconds
|
|
35
|
+
token_length
|
|
36
|
+
The length of the generated token string, by default 32 characters
|
|
37
|
+
"""
|
|
38
|
+
self._cache_connector = cache_connector
|
|
39
|
+
self._token_model = token_model
|
|
40
|
+
self._token_max_age_seconds = token_max_age_seconds
|
|
41
|
+
self._token_length = token_length
|
|
42
|
+
|
|
43
|
+
def get(self, token: str) -> Token:
|
|
44
|
+
"""Get a token by its value."""
|
|
45
|
+
raise NotImplementedError("Method not implemented yet.")
|
|
46
|
+
|
|
47
|
+
def create(self, subject: str) -> Token:
|
|
48
|
+
"""Create a new token for a given subject."""
|
|
49
|
+
raise NotImplementedError("Method not implemented yet.")
|
|
50
|
+
|
|
51
|
+
def delete(self, token: str) -> None:
|
|
52
|
+
"""Delete a token by its value."""
|
|
53
|
+
raise NotImplementedError("Method not implemented yet.")
|
|
54
|
+
|
|
55
|
+
def delete_all(self, subject: str) -> None:
|
|
56
|
+
"""Delete all tokens for a given subject."""
|
|
57
|
+
raise NotImplementedError("Method not implemented yet.")
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
from alpha import exceptions
|
|
2
|
+
from alpha.infra.connectors.sql_alchemy import SqlAlchemyDatabase
|
|
3
|
+
from alpha.providers.models.token import Token
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DatabaseRefreshRepository:
|
|
7
|
+
"""Implementation of the RefreshRepository interface for database
|
|
8
|
+
operations.
|
|
9
|
+
|
|
10
|
+
This repository uses a SQLAlchemy database connector to manage refresh
|
|
11
|
+
tokens in a database. It provides methods to get, create, delete, and
|
|
12
|
+
delete all refresh tokens for a given subject. The tokens are stored in a
|
|
13
|
+
database table which is mapped to the token model.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
database_connector: SqlAlchemyDatabase,
|
|
19
|
+
token_model: type[Token] = Token,
|
|
20
|
+
token_max_age_seconds: int = 7 * 24 * 3600,
|
|
21
|
+
token_length: int = 32,
|
|
22
|
+
):
|
|
23
|
+
"""Initialize the DatabaseRefreshRepository with the given database
|
|
24
|
+
connector and token model.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
database_connector
|
|
29
|
+
The database connector instance to use for database operations.
|
|
30
|
+
token_model
|
|
31
|
+
The model class for tokens, by default Token. The model class
|
|
32
|
+
should have a `from_dict` class method that takes a dictionary and
|
|
33
|
+
returns an instance of the model. The dictionary will have the same
|
|
34
|
+
structure as the token data in the JSON file. The model class
|
|
35
|
+
should also have a `to_dict` method that converts an instance of
|
|
36
|
+
the model to a dictionary with the same structure as the token data
|
|
37
|
+
in the JSON file. The model class should also have a
|
|
38
|
+
`create_refresh` class method that creates a new refresh token.
|
|
39
|
+
token_max_age_seconds
|
|
40
|
+
The maximum age of a token in seconds, by default the equivalent of
|
|
41
|
+
7 days in seconds
|
|
42
|
+
token_length
|
|
43
|
+
The length of the generated token string, by default 32 characters
|
|
44
|
+
"""
|
|
45
|
+
self._database_connector = database_connector
|
|
46
|
+
self._token_model = token_model
|
|
47
|
+
self._token_max_age_seconds = token_max_age_seconds
|
|
48
|
+
self._token_length = token_length
|
|
49
|
+
|
|
50
|
+
def get(self, token: str) -> Token:
|
|
51
|
+
"""Get a token by its value.
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
token
|
|
56
|
+
The value of the token to retrieve.
|
|
57
|
+
|
|
58
|
+
Returns
|
|
59
|
+
-------
|
|
60
|
+
Token
|
|
61
|
+
The token object corresponding to the given value.
|
|
62
|
+
|
|
63
|
+
Raises
|
|
64
|
+
------
|
|
65
|
+
NotFoundException
|
|
66
|
+
If the token is not found in the database.
|
|
67
|
+
"""
|
|
68
|
+
with self._database_connector.get_session() as session:
|
|
69
|
+
result = (
|
|
70
|
+
session.query(self._token_model)
|
|
71
|
+
.filter_by(value=token)
|
|
72
|
+
.one_or_none()
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if result is None:
|
|
76
|
+
raise exceptions.NotFoundException("Refresh token not found")
|
|
77
|
+
|
|
78
|
+
return result
|
|
79
|
+
|
|
80
|
+
def create(self, subject: str) -> Token:
|
|
81
|
+
"""Create a new token for a given subject.
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
subject
|
|
86
|
+
The subject for which to create the token.
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
Token
|
|
91
|
+
The newly created token object.
|
|
92
|
+
"""
|
|
93
|
+
token = self._token_model.create_refresh(
|
|
94
|
+
subject=subject,
|
|
95
|
+
max_age_seconds=self._token_max_age_seconds,
|
|
96
|
+
token_length=self._token_length,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
with self._database_connector.get_session() as session:
|
|
100
|
+
session.add(token)
|
|
101
|
+
session.commit()
|
|
102
|
+
session.refresh(token)
|
|
103
|
+
return token
|
|
104
|
+
|
|
105
|
+
def delete(self, token: str) -> None:
|
|
106
|
+
"""Delete a token by its value.
|
|
107
|
+
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
token
|
|
111
|
+
The value of the token to delete.
|
|
112
|
+
|
|
113
|
+
Raises
|
|
114
|
+
------
|
|
115
|
+
NotFoundException
|
|
116
|
+
If the token is not found in the database.
|
|
117
|
+
"""
|
|
118
|
+
with self._database_connector.get_session() as session:
|
|
119
|
+
token_obj = (
|
|
120
|
+
session.query(self._token_model)
|
|
121
|
+
.filter_by(value=token)
|
|
122
|
+
.one_or_none()
|
|
123
|
+
)
|
|
124
|
+
if token_obj is None:
|
|
125
|
+
raise exceptions.NotFoundException("Refresh token not found")
|
|
126
|
+
session.delete(token_obj)
|
|
127
|
+
session.commit()
|
|
128
|
+
|
|
129
|
+
def delete_all(self, subject: str) -> None:
|
|
130
|
+
"""Delete all tokens for a given subject.
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
subject
|
|
135
|
+
The subject for which to delete all tokens.
|
|
136
|
+
"""
|
|
137
|
+
with self._database_connector.get_session() as session:
|
|
138
|
+
tokens = (
|
|
139
|
+
session.query(self._token_model)
|
|
140
|
+
.filter_by(subject=subject)
|
|
141
|
+
.all()
|
|
142
|
+
)
|
|
143
|
+
for token in tokens:
|
|
144
|
+
session.delete(token)
|
|
145
|
+
session.commit()
|