alpha-python 0.7.5__tar.gz → 0.7.7__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.7.5 → alpha_python-0.7.7}/PKG-INFO +2 -2
- {alpha_python-0.7.5 → alpha_python-0.7.7}/pyproject.toml +2 -2
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/__init__.py +2 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/domain/__init__.py +2 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/domain/models/__init__.py +2 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/domain/models/group.py +41 -1
- alpha_python-0.7.7/src/alpha/domain/models/permission.py +110 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/domain/models/user.py +66 -2
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/mixins/jwt_provider.py +4 -1
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/providers/database_provider.py +8 -2
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/providers/ldap_provider.py +7 -1
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/providers/models/identity.py +9 -6
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/providers/oidc_provider.py +10 -2
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/services/authentication_service.py +7 -2
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha_python.egg-info/PKG-INFO +2 -2
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha_python.egg-info/SOURCES.txt +1 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/LICENSE +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/README.md +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/setup.cfg +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/adapters/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/adapters/rest_api_unit_of_work.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/adapters/sqla_unit_of_work.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/cli.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/containers/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/containers/container.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/domain/models/base_model.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/domain/models/life_cycle_base.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/domain/models/role.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/encoder.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/exceptions.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/_type_conversion_matrix.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/_type_mapping.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/class_factories.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/default_field_factory.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/field_iterator.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/jwt_factory.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/logging_handler_factory.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/model_class_factory.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/models/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/models/factory_classes.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/password_factory.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/request_factory.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/response_factory.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/factories/type_factories.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/api_generate_handler.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/api_run_handler.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/base_handler.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/gen-code.sh +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/models/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/models/argument.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/models/command.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/models/section.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/models/subparser.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/run-api.sh +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/Dockerfile.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/README.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/__init__model.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/__init__test.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/__main__.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/base_model.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/controller.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/controller_test.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/dockerignore.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/encoder.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/git_push.sh.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/gitignore.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/model.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/openapi.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/param_type.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/requirements.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/security_controller_.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/setup.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/test-requirements.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/tox.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/travis.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/typing_utils.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/util.mustache +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/connectors/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/connectors/ldap_connector.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/connectors/oidc_connector.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/connectors/sql_alchemy.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/databases/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/databases/sql_alchemy.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/models/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/models/filter_operators.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/models/json_patch.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/models/order_by.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/models/query_clause.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/infra/models/search_filter.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/api_repository.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/attrs_instance.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/dataclass_instance.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/factories.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/handler.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/http_client.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/openapi_model.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/patchable.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/providers.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/pydantic_instance.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/refresh_repository.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/sql_database.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/sql_mapper.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/sql_repository.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/token_factory.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/unit_of_work.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/interfaces/updatable.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/mixins/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/mixins/group_lifecycle.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/mixins/user_lifecycle.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/providers/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/providers/api_key_provider.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/providers/models/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/providers/models/credentials.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/providers/models/token.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/py.typed +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/models/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/models/repository_model.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/refresh/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/refresh/cache_repository.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/refresh/database_repository.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/refresh/file_repository.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/refresh/memory_repository.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/rest_api_repository.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/sql_alchemy_repository.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/services/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/services/models/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/services/models/cookie.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/services/user_lifecycle_management.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/_http_codes.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/cookie.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/is_attrs.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/is_pydantic.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/logging_configurator.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/logging_level_checker.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/openapi_test/__init__.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/openapi_test/container.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/openapi_test/exceptions.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/openapi_test/models.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/openapi_test/orm.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/openapi_test/response.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/openapi_test/service.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/request_headers.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/response_object.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/secret_generator.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/verify_identity.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/utils/version_checker.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha_python.egg-info/dependency_links.txt +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha_python.egg-info/entry_points.txt +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha_python.egg-info/requires.txt +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha_python.egg-info/top_level.txt +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/tests/test_cli.py +0 -0
- {alpha_python-0.7.5 → alpha_python-0.7.7}/tests/test_encoder.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: alpha-python
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.7
|
|
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
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
-
Requires-Python:
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
22
|
Requires-Dist: attrs>=25.4.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "alpha-python"
|
|
3
|
-
version = "0.7.
|
|
3
|
+
version = "0.7.7"
|
|
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 = [
|
|
@@ -18,7 +18,7 @@ classifiers = [
|
|
|
18
18
|
]
|
|
19
19
|
license = "MIT"
|
|
20
20
|
license-files = ['LICENSE']
|
|
21
|
-
requires-python = ">=3.11
|
|
21
|
+
requires-python = ">=3.11"
|
|
22
22
|
dependencies = [
|
|
23
23
|
"attrs>=25.4.0",
|
|
24
24
|
"gunicorn>=23.0.0",
|
|
@@ -7,6 +7,7 @@ from alpha.factories.logging_handler_factory import LoggingHandlerFactory
|
|
|
7
7
|
from alpha.factories.model_class_factory import ModelClassFactory
|
|
8
8
|
from alpha.domain.models.user import User
|
|
9
9
|
from alpha.domain.models.group import Group
|
|
10
|
+
from alpha.domain.models.permission import Permission
|
|
10
11
|
from alpha.domain.models.role import Role
|
|
11
12
|
from alpha.domain.models.base_model import (
|
|
12
13
|
BaseDomainModel,
|
|
@@ -123,6 +124,7 @@ __all__ = [
|
|
|
123
124
|
"LifeCycleBase",
|
|
124
125
|
"User",
|
|
125
126
|
"Group",
|
|
127
|
+
"Permission",
|
|
126
128
|
"Role",
|
|
127
129
|
"OIDCConnector",
|
|
128
130
|
"KeyCloakOIDCConnector",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from alpha.domain.models.user import User
|
|
2
2
|
from alpha.domain.models.group import Group
|
|
3
|
+
from alpha.domain.models.permission import Permission
|
|
3
4
|
from alpha.domain.models.role import Role
|
|
4
5
|
from alpha.domain.models.base_model import (
|
|
5
6
|
BaseDomainModel,
|
|
@@ -17,5 +18,6 @@ __all__ = [
|
|
|
17
18
|
"LifeCycleBase",
|
|
18
19
|
"User",
|
|
19
20
|
"Group",
|
|
21
|
+
"Permission",
|
|
20
22
|
"Role",
|
|
21
23
|
]
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from alpha.domain.models.user import User
|
|
2
2
|
from alpha.domain.models.group import Group
|
|
3
|
+
from alpha.domain.models.permission import Permission
|
|
3
4
|
from alpha.domain.models.role import Role
|
|
4
5
|
from alpha.domain.models.base_model import (
|
|
5
6
|
BaseDomainModel,
|
|
@@ -17,5 +18,6 @@ __all__ = [
|
|
|
17
18
|
"LifeCycleBase",
|
|
18
19
|
"User",
|
|
19
20
|
"Group",
|
|
21
|
+
"Permission",
|
|
20
22
|
"Role",
|
|
21
23
|
]
|
|
@@ -39,6 +39,20 @@ class Group(LifeCycleBase, BaseDomainModel):
|
|
|
39
39
|
permissions: list[str] = field(default_factory=list) # type: ignore
|
|
40
40
|
is_active: bool = True
|
|
41
41
|
|
|
42
|
+
def __str__(self) -> str:
|
|
43
|
+
"""Return the name-based representation of the Group instance."""
|
|
44
|
+
return self.name or ""
|
|
45
|
+
|
|
46
|
+
def __repr__(self) -> str:
|
|
47
|
+
"""Return the official string representation of the Group instance."""
|
|
48
|
+
return (
|
|
49
|
+
"Group("
|
|
50
|
+
f"id={self.id!r}, "
|
|
51
|
+
f"name={self.name!r}, "
|
|
52
|
+
f"description={self.description!r}"
|
|
53
|
+
")"
|
|
54
|
+
)
|
|
55
|
+
|
|
42
56
|
def to_dict(self) -> dict[str, Any]:
|
|
43
57
|
"""Convert the Group instance to a dictionary.
|
|
44
58
|
|
|
@@ -47,12 +61,38 @@ class Group(LifeCycleBase, BaseDomainModel):
|
|
|
47
61
|
dict[str, Any]
|
|
48
62
|
A dictionary representation of the Group instance.
|
|
49
63
|
"""
|
|
64
|
+
permissions = cast(
|
|
65
|
+
list[str | dict[str, Any]],
|
|
66
|
+
[
|
|
67
|
+
p.to_dict() if hasattr(p, "to_dict") else p # type: ignore
|
|
68
|
+
for p in self.permissions
|
|
69
|
+
],
|
|
70
|
+
)
|
|
71
|
+
created_at = (
|
|
72
|
+
self.created_at.isoformat()
|
|
73
|
+
if hasattr(self, "created_at") and self.created_at is not None
|
|
74
|
+
else None
|
|
75
|
+
)
|
|
76
|
+
modified_at = (
|
|
77
|
+
self.modified_at.isoformat()
|
|
78
|
+
if hasattr(self, "modified_at") and self.modified_at is not None
|
|
79
|
+
else None
|
|
80
|
+
)
|
|
81
|
+
|
|
50
82
|
return {
|
|
51
83
|
"id": self.id,
|
|
52
84
|
"name": self.name,
|
|
53
85
|
"description": self.description,
|
|
54
|
-
"permissions":
|
|
86
|
+
"permissions": permissions,
|
|
55
87
|
"is_active": self.is_active,
|
|
88
|
+
"created_by": self.created_by
|
|
89
|
+
if hasattr(self, "created_by") and self.created_by is not None
|
|
90
|
+
else None,
|
|
91
|
+
"created_at": created_at,
|
|
92
|
+
"modified_by": self.modified_by
|
|
93
|
+
if hasattr(self, "modified_by") and self.modified_by is not None
|
|
94
|
+
else None,
|
|
95
|
+
"modified_at": modified_at,
|
|
56
96
|
}
|
|
57
97
|
|
|
58
98
|
def update(self, obj: DomainModel) -> DomainModel:
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
|
+
from typing import Any, cast
|
|
4
|
+
from uuid import UUID
|
|
5
|
+
|
|
6
|
+
from alpha.domain.models.base_model import BaseDomainModel, DomainModel
|
|
7
|
+
from alpha.domain.models.life_cycle_base import LifeCycleBase
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(kw_only=True)
|
|
11
|
+
class Permission(LifeCycleBase, BaseDomainModel):
|
|
12
|
+
"""Permission class representing a system permission. This class is used to
|
|
13
|
+
define and manage permissions. User and group permissions are handled
|
|
14
|
+
through this class.
|
|
15
|
+
|
|
16
|
+
Attributes
|
|
17
|
+
----------
|
|
18
|
+
id
|
|
19
|
+
Unique identifier for the permission. Can be a UUID, integer, or
|
|
20
|
+
string.
|
|
21
|
+
name
|
|
22
|
+
Name of the permission.
|
|
23
|
+
description
|
|
24
|
+
Description for the purpose of the permission.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
id: UUID | int | str | None = None
|
|
28
|
+
name: str | None = None
|
|
29
|
+
description: str = ""
|
|
30
|
+
|
|
31
|
+
def __str__(self) -> str:
|
|
32
|
+
"""Return the name of the permission.
|
|
33
|
+
|
|
34
|
+
Returns
|
|
35
|
+
-------
|
|
36
|
+
self.name value
|
|
37
|
+
"""
|
|
38
|
+
return self.name or ""
|
|
39
|
+
|
|
40
|
+
def __repr__(self) -> str:
|
|
41
|
+
"""Return the official string representation of the object.
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
A string representing the Permission instance.
|
|
46
|
+
"""
|
|
47
|
+
return (
|
|
48
|
+
f"Permission(name={self.name!r}, description={self.description!r})"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def to_dict(self) -> dict[str, Any]:
|
|
52
|
+
"""Convert the Permission instance to a dictionary.
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
dict[str, Any]
|
|
57
|
+
A dictionary representation of the Permission instance.
|
|
58
|
+
"""
|
|
59
|
+
created_at = (
|
|
60
|
+
self.created_at.isoformat()
|
|
61
|
+
if hasattr(self, "created_at") and self.created_at is not None
|
|
62
|
+
else None
|
|
63
|
+
)
|
|
64
|
+
modified_at = (
|
|
65
|
+
self.modified_at.isoformat()
|
|
66
|
+
if hasattr(self, "modified_at") and self.modified_at is not None
|
|
67
|
+
else None
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
"id": self.id,
|
|
72
|
+
"name": self.name,
|
|
73
|
+
"description": self.description,
|
|
74
|
+
"created_by": self.created_by
|
|
75
|
+
if hasattr(self, "created_by") and self.created_by is not None
|
|
76
|
+
else None,
|
|
77
|
+
"created_at": created_at,
|
|
78
|
+
"modified_by": self.modified_by
|
|
79
|
+
if hasattr(self, "modified_by") and self.modified_by is not None
|
|
80
|
+
else None,
|
|
81
|
+
"modified_at": modified_at,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
def update(self, obj: DomainModel) -> DomainModel:
|
|
85
|
+
"""Update the Permission instance with data from another Permission
|
|
86
|
+
instance.
|
|
87
|
+
|
|
88
|
+
Parameters
|
|
89
|
+
----------
|
|
90
|
+
obj
|
|
91
|
+
Permission object to update from.
|
|
92
|
+
|
|
93
|
+
Returns
|
|
94
|
+
-------
|
|
95
|
+
DomainModel
|
|
96
|
+
The updated instance of the Permission.
|
|
97
|
+
|
|
98
|
+
Raises
|
|
99
|
+
------
|
|
100
|
+
TypeError
|
|
101
|
+
If the provided object is not a Permission instance.
|
|
102
|
+
"""
|
|
103
|
+
if not isinstance(obj, Permission):
|
|
104
|
+
raise TypeError("Permission.update expects a Permission instance.")
|
|
105
|
+
|
|
106
|
+
self.name = obj.name
|
|
107
|
+
self.description = obj.description
|
|
108
|
+
self.modified_at = datetime.now(tz=timezone.utc)
|
|
109
|
+
|
|
110
|
+
return cast(DomainModel, self)
|
|
@@ -72,6 +72,32 @@ class User(LifeCycleBase, BaseDomainModel):
|
|
|
72
72
|
is_active: bool = True
|
|
73
73
|
admin: bool = False
|
|
74
74
|
|
|
75
|
+
def __str__(self) -> str:
|
|
76
|
+
"""Return the username of the user.
|
|
77
|
+
|
|
78
|
+
Returns
|
|
79
|
+
-------
|
|
80
|
+
self.username value
|
|
81
|
+
"""
|
|
82
|
+
return self.username or ""
|
|
83
|
+
|
|
84
|
+
def __repr__(self) -> str:
|
|
85
|
+
"""Return the official string representation of the object.
|
|
86
|
+
|
|
87
|
+
Returns
|
|
88
|
+
-------
|
|
89
|
+
A string representing the User instance.
|
|
90
|
+
"""
|
|
91
|
+
return (
|
|
92
|
+
"User("
|
|
93
|
+
f"id={self.id}, "
|
|
94
|
+
f"username={self.username!r}, "
|
|
95
|
+
f"display_name={self.display_name!r}, "
|
|
96
|
+
f"permissions={self.permissions!r}, "
|
|
97
|
+
f"groups={self.groups!r}"
|
|
98
|
+
")"
|
|
99
|
+
)
|
|
100
|
+
|
|
75
101
|
@classmethod
|
|
76
102
|
def from_identity(cls, identity: Identity) -> Self:
|
|
77
103
|
"""Create a User instance from an Identity instance.
|
|
@@ -101,6 +127,35 @@ class User(LifeCycleBase, BaseDomainModel):
|
|
|
101
127
|
dict[str, Any]
|
|
102
128
|
A dictionary representation of the User instance.
|
|
103
129
|
"""
|
|
130
|
+
permissions = cast(
|
|
131
|
+
list[str | dict[str, Any]],
|
|
132
|
+
[
|
|
133
|
+
permission.to_dict() # type: ignore
|
|
134
|
+
if hasattr(permission, "to_dict")
|
|
135
|
+
else permission
|
|
136
|
+
for permission in self.permissions
|
|
137
|
+
],
|
|
138
|
+
)
|
|
139
|
+
groups = cast(
|
|
140
|
+
list[str | dict[str, Any]],
|
|
141
|
+
[
|
|
142
|
+
group.to_dict() # type: ignore
|
|
143
|
+
if hasattr(group, "to_dict")
|
|
144
|
+
else group
|
|
145
|
+
for group in self.groups
|
|
146
|
+
],
|
|
147
|
+
)
|
|
148
|
+
created_at = (
|
|
149
|
+
self.created_at.isoformat()
|
|
150
|
+
if hasattr(self, "created_at") and self.created_at is not None
|
|
151
|
+
else None
|
|
152
|
+
)
|
|
153
|
+
modified_at = (
|
|
154
|
+
self.modified_at.isoformat()
|
|
155
|
+
if hasattr(self, "modified_at") and self.modified_at is not None
|
|
156
|
+
else None
|
|
157
|
+
)
|
|
158
|
+
|
|
104
159
|
return {
|
|
105
160
|
"id": self.id,
|
|
106
161
|
"username": self.username,
|
|
@@ -109,10 +164,18 @@ class User(LifeCycleBase, BaseDomainModel):
|
|
|
109
164
|
"email": self.email,
|
|
110
165
|
"phone": self.phone,
|
|
111
166
|
"display_name": self.display_name,
|
|
112
|
-
"permissions":
|
|
113
|
-
"groups":
|
|
167
|
+
"permissions": permissions,
|
|
168
|
+
"groups": groups,
|
|
114
169
|
"is_active": self.is_active,
|
|
115
170
|
"admin": self.admin,
|
|
171
|
+
"created_by": self.created_by
|
|
172
|
+
if hasattr(self, "created_by") and self.created_by is not None
|
|
173
|
+
else None,
|
|
174
|
+
"created_at": created_at,
|
|
175
|
+
"modified_by": self.modified_by
|
|
176
|
+
if hasattr(self, "modified_by") and self.modified_by is not None
|
|
177
|
+
else None,
|
|
178
|
+
"modified_at": modified_at,
|
|
116
179
|
}
|
|
117
180
|
|
|
118
181
|
def update(self, obj: DomainModel) -> DomainModel:
|
|
@@ -140,4 +203,5 @@ class User(LifeCycleBase, BaseDomainModel):
|
|
|
140
203
|
self.modified_at = datetime.now(tz=timezone.utc)
|
|
141
204
|
self.is_active = obj.is_active
|
|
142
205
|
self.admin = obj.admin
|
|
206
|
+
|
|
143
207
|
return cast(DomainModel, self)
|
|
@@ -12,6 +12,7 @@ class JWTProviderMixin:
|
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
token_factory: TokenFactory | None = None
|
|
15
|
+
_identity_model: type[Identity] = Identity
|
|
15
16
|
|
|
16
17
|
def validate(self, token: Token) -> Identity:
|
|
17
18
|
"""Validate a token and return the associated identity
|
|
@@ -43,7 +44,7 @@ class JWTProviderMixin:
|
|
|
43
44
|
"Token payload does not contain mandatory 'subject' field"
|
|
44
45
|
)
|
|
45
46
|
|
|
46
|
-
return
|
|
47
|
+
return self._identity_model.from_dict(payload)
|
|
47
48
|
|
|
48
49
|
def issue_token(self, identity: Identity) -> Token:
|
|
49
50
|
"""Issue a token for the given identity
|
|
@@ -57,6 +58,8 @@ class JWTProviderMixin:
|
|
|
57
58
|
-------
|
|
58
59
|
Token object
|
|
59
60
|
"""
|
|
61
|
+
identity = self._identity_model.from_dict(identity.to_dict())
|
|
62
|
+
|
|
60
63
|
if not self.token_factory:
|
|
61
64
|
raise exceptions.MissingDependencyException(
|
|
62
65
|
"Token factory is not configured"
|
|
@@ -18,12 +18,14 @@ class DatabaseProvider(JWTProviderMixin):
|
|
|
18
18
|
|
|
19
19
|
protocol = "database"
|
|
20
20
|
token_factory: TokenFactory | None = None
|
|
21
|
+
_identity_model: type[Identity] = Identity
|
|
21
22
|
|
|
22
23
|
def __init__(
|
|
23
24
|
self,
|
|
24
25
|
uow: UnitOfWork,
|
|
25
26
|
token_factory: TokenFactory | None = None,
|
|
26
27
|
password_factory: PasswordFactory | None = None,
|
|
28
|
+
identity_model: type[Identity] = Identity,
|
|
27
29
|
user_name_attribute: str = "username",
|
|
28
30
|
users_repository_name: str = "users",
|
|
29
31
|
) -> None:
|
|
@@ -42,6 +44,9 @@ class DatabaseProvider(JWTProviderMixin):
|
|
|
42
44
|
Password factory instance to handle password hashing and
|
|
43
45
|
verification, by default None. If None, a default PasswordFactory
|
|
44
46
|
will be used.
|
|
47
|
+
identity_model
|
|
48
|
+
Identity model class to use for representing users, by default
|
|
49
|
+
Identity
|
|
45
50
|
user_name_attribute
|
|
46
51
|
Attribute name to identify the user, by default "username"
|
|
47
52
|
users_repository_name
|
|
@@ -52,6 +57,7 @@ class DatabaseProvider(JWTProviderMixin):
|
|
|
52
57
|
self._password_factory = password_factory or PasswordFactory()
|
|
53
58
|
self._user_name_attribute = user_name_attribute
|
|
54
59
|
self._users_repository_name = users_repository_name
|
|
60
|
+
self._identity_model = identity_model
|
|
55
61
|
|
|
56
62
|
def authenticate(self, credentials: PasswordCredentials) -> Identity:
|
|
57
63
|
"""Authenticate a user using their credentials.
|
|
@@ -73,7 +79,7 @@ class DatabaseProvider(JWTProviderMixin):
|
|
|
73
79
|
credentials=credentials, user_repository=users
|
|
74
80
|
)
|
|
75
81
|
|
|
76
|
-
return
|
|
82
|
+
return self._identity_model.from_user(user)
|
|
77
83
|
|
|
78
84
|
def get_user(self, subject: str) -> Identity:
|
|
79
85
|
"""Retrieve a user by their subject identifier.
|
|
@@ -95,7 +101,7 @@ class DatabaseProvider(JWTProviderMixin):
|
|
|
95
101
|
username=subject, user_repository=users, attribute_name="id"
|
|
96
102
|
)
|
|
97
103
|
|
|
98
|
-
return
|
|
104
|
+
return self._identity_model.from_user(user)
|
|
99
105
|
|
|
100
106
|
def change_password(
|
|
101
107
|
self, credentials: PasswordCredentials, new_password: str
|
|
@@ -33,6 +33,7 @@ class LDAPProvider(JWTProviderMixin):
|
|
|
33
33
|
|
|
34
34
|
protocol = "ldap"
|
|
35
35
|
token_factory: TokenFactory | None = None
|
|
36
|
+
_identity_model: type[Identity] = Identity
|
|
36
37
|
|
|
37
38
|
def __init__(
|
|
38
39
|
self,
|
|
@@ -48,6 +49,7 @@ class LDAPProvider(JWTProviderMixin):
|
|
|
48
49
|
flatten_claims: bool = True,
|
|
49
50
|
auto_connect: bool = True,
|
|
50
51
|
change_password_supported: bool = False,
|
|
52
|
+
identity_model: type[Identity] = Identity,
|
|
51
53
|
additional_connector_params: dict[str, Any] | None = None,
|
|
52
54
|
) -> None:
|
|
53
55
|
"""Initialize LDAPProvider.
|
|
@@ -80,6 +82,9 @@ class LDAPProvider(JWTProviderMixin):
|
|
|
80
82
|
True
|
|
81
83
|
change_password_supported
|
|
82
84
|
Whether the provider supports changing passwords, by default False
|
|
85
|
+
identity_model
|
|
86
|
+
Identity model class to use for representing users, by default
|
|
87
|
+
Identity
|
|
83
88
|
additional_connector_params
|
|
84
89
|
Additional parameters to pass to the LDAP connection, by default
|
|
85
90
|
{"receive_timeout": 5}
|
|
@@ -96,6 +101,7 @@ class LDAPProvider(JWTProviderMixin):
|
|
|
96
101
|
self._flatten_claims = flatten_claims
|
|
97
102
|
self._auto_connect = auto_connect
|
|
98
103
|
self._change_password_supported = change_password_supported
|
|
104
|
+
self._identity_model = identity_model
|
|
99
105
|
self._additional_connector_params = additional_connector_params or {
|
|
100
106
|
"receive_timeout": 5
|
|
101
107
|
}
|
|
@@ -296,7 +302,7 @@ class LDAPProvider(JWTProviderMixin):
|
|
|
296
302
|
Identity object
|
|
297
303
|
"""
|
|
298
304
|
entry_dict = cast(dict[str, Any], entry.entry_attributes_as_dict) # type: ignore
|
|
299
|
-
identity =
|
|
305
|
+
identity = self._identity_model.from_ldap_dict(
|
|
300
306
|
entry=entry_dict,
|
|
301
307
|
mappings=self._identity_mappings,
|
|
302
308
|
populate_claims=self._populate_claims,
|
|
@@ -125,7 +125,7 @@ class Identity:
|
|
|
125
125
|
username: str | None
|
|
126
126
|
email: str | None
|
|
127
127
|
display_name: str | None
|
|
128
|
-
groups: Sequence[str
|
|
128
|
+
groups: Sequence[str]
|
|
129
129
|
permissions: Sequence[str]
|
|
130
130
|
claims: Mapping[str, Any]
|
|
131
131
|
issued_at: datetime
|
|
@@ -274,13 +274,16 @@ class Identity:
|
|
|
274
274
|
An Identity instance populated with data from the User object.
|
|
275
275
|
"""
|
|
276
276
|
subject = str(user.id) if user.id else user.username
|
|
277
|
+
|
|
277
278
|
return cls(
|
|
278
279
|
subject=subject, # type: ignore
|
|
279
280
|
username=user.username,
|
|
280
281
|
email=user.email,
|
|
281
282
|
display_name=user.display_name,
|
|
282
|
-
groups=user.groups or [],
|
|
283
|
-
permissions=
|
|
283
|
+
groups=[str(group) for group in user.groups or []],
|
|
284
|
+
permissions=[
|
|
285
|
+
str(permission) for permission in user.permissions or []
|
|
286
|
+
],
|
|
284
287
|
claims={},
|
|
285
288
|
issued_at=datetime.now(tz=timezone.utc),
|
|
286
289
|
role=user.role, # type: ignore
|
|
@@ -324,10 +327,10 @@ class Identity:
|
|
|
324
327
|
self.display_name = user.display_name
|
|
325
328
|
for permission in user.permissions or []:
|
|
326
329
|
self.permissions = self._append_on_sequence(
|
|
327
|
-
self.permissions, permission
|
|
330
|
+
self.permissions, str(permission)
|
|
328
331
|
)
|
|
329
332
|
for group in user.groups or []:
|
|
330
|
-
self.groups = self._append_on_sequence(self.groups, group)
|
|
333
|
+
self.groups = self._append_on_sequence(self.groups, str(group))
|
|
331
334
|
self.role = user.role # type: ignore
|
|
332
335
|
self.admin = user.admin
|
|
333
336
|
|
|
@@ -343,7 +346,7 @@ class Identity:
|
|
|
343
346
|
for group in groups:
|
|
344
347
|
for permission in group.permissions or []:
|
|
345
348
|
self.permissions = self._append_on_sequence(
|
|
346
|
-
self.permissions, permission
|
|
349
|
+
self.permissions, str(permission)
|
|
347
350
|
)
|
|
348
351
|
|
|
349
352
|
def to_dict(self) -> dict[str, Any]:
|
|
@@ -48,6 +48,7 @@ class OIDCProvider(JWTProviderMixin):
|
|
|
48
48
|
|
|
49
49
|
protocol = "oidc"
|
|
50
50
|
token_factory: TokenFactory | None = None
|
|
51
|
+
_identity_model: type[Identity] = Identity
|
|
51
52
|
|
|
52
53
|
def __init__(
|
|
53
54
|
self,
|
|
@@ -58,6 +59,7 @@ class OIDCProvider(JWTProviderMixin):
|
|
|
58
59
|
populate_permissions: bool = False,
|
|
59
60
|
populate_claims: bool = False,
|
|
60
61
|
flatten_claims: bool = True,
|
|
62
|
+
identity_model: type[Identity] = Identity,
|
|
61
63
|
change_password_supported: bool = False,
|
|
62
64
|
) -> None:
|
|
63
65
|
"""Initialize OIDCProvider.
|
|
@@ -80,6 +82,11 @@ class OIDCProvider(JWTProviderMixin):
|
|
|
80
82
|
Whether to populate permissions on the Identity.
|
|
81
83
|
populate_claims
|
|
82
84
|
Whether to include raw claims on the Identity.
|
|
85
|
+
flatten_claims
|
|
86
|
+
Whether to flatten single-value claims in the Identity.
|
|
87
|
+
identity_model
|
|
88
|
+
Identity model class to use for representing users, by default
|
|
89
|
+
Identity
|
|
83
90
|
change_password_supported
|
|
84
91
|
Whether this provider supports changing passwords.
|
|
85
92
|
"""
|
|
@@ -92,6 +99,7 @@ class OIDCProvider(JWTProviderMixin):
|
|
|
92
99
|
self._populate_permissions = populate_permissions
|
|
93
100
|
self._populate_claims = populate_claims
|
|
94
101
|
self._flatten_claims = flatten_claims
|
|
102
|
+
self._identity_model = identity_model
|
|
95
103
|
self._change_password_supported = change_password_supported
|
|
96
104
|
|
|
97
105
|
def authenticate(self, credentials: PasswordCredentials) -> Identity:
|
|
@@ -240,9 +248,9 @@ class OIDCProvider(JWTProviderMixin):
|
|
|
240
248
|
audience = self._extract_audience(claims)
|
|
241
249
|
|
|
242
250
|
if self._populate_claims and self._flatten_claims:
|
|
243
|
-
claims =
|
|
251
|
+
claims = self._identity_model.flatten_single_value_claims(claims)
|
|
244
252
|
|
|
245
|
-
identity =
|
|
253
|
+
identity = self._identity_model(
|
|
246
254
|
subject=str(subject),
|
|
247
255
|
username=username,
|
|
248
256
|
email=self._get_claim(claims, "email"),
|
|
@@ -74,6 +74,7 @@ class AuthenticationService:
|
|
|
74
74
|
user_model: type[User] = User,
|
|
75
75
|
group_model: type[Group] = Group,
|
|
76
76
|
token_model: type[Token] = Token,
|
|
77
|
+
identity_model: type[Identity] = Identity,
|
|
77
78
|
users_repository_name: str = "users",
|
|
78
79
|
groups_repository_name: str = "groups",
|
|
79
80
|
refresh_repository: RefreshRepository | None = None,
|
|
@@ -147,6 +148,9 @@ class AuthenticationService:
|
|
|
147
148
|
Group model class to use for database operations, by default Group
|
|
148
149
|
token_model
|
|
149
150
|
Token model class to use for database operations, by default Token
|
|
151
|
+
identity_model
|
|
152
|
+
Identity model class to use for object creation and manipulation,
|
|
153
|
+
by default Identity
|
|
150
154
|
users_repository_name
|
|
151
155
|
Name of the user repository in the UnitOfWork, by default "users"
|
|
152
156
|
groups_repository_name
|
|
@@ -206,6 +210,7 @@ class AuthenticationService:
|
|
|
206
210
|
self._user_model = user_model
|
|
207
211
|
self._group_model = group_model
|
|
208
212
|
self._token_model = token_model
|
|
213
|
+
self._identity_model = identity_model
|
|
209
214
|
self._users_repository_name = users_repository_name
|
|
210
215
|
self._groups_repository_name = groups_repository_name
|
|
211
216
|
self._refresh_repository = (
|
|
@@ -265,7 +270,7 @@ class AuthenticationService:
|
|
|
265
270
|
and credentials.username == self._static_user.username
|
|
266
271
|
and credentials.password == self._static_user.password
|
|
267
272
|
):
|
|
268
|
-
identity =
|
|
273
|
+
identity = self._identity_model.from_user(self._static_user)
|
|
269
274
|
|
|
270
275
|
# Use the identity provider to authenticate the user and retrieve their
|
|
271
276
|
# identity
|
|
@@ -464,7 +469,7 @@ class AuthenticationService:
|
|
|
464
469
|
payload = self._identity_provider.token_factory.get_payload(
|
|
465
470
|
token=auth_token, options={"verify_exp": False}
|
|
466
471
|
)
|
|
467
|
-
identity =
|
|
472
|
+
identity = self._identity_model.from_dict(payload)
|
|
468
473
|
except Exception:
|
|
469
474
|
identity = None
|
|
470
475
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: alpha-python
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.7
|
|
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
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
-
Requires-Python:
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
22
|
Requires-Dist: attrs>=25.4.0
|
|
@@ -16,6 +16,7 @@ src/alpha/domain/models/__init__.py
|
|
|
16
16
|
src/alpha/domain/models/base_model.py
|
|
17
17
|
src/alpha/domain/models/group.py
|
|
18
18
|
src/alpha/domain/models/life_cycle_base.py
|
|
19
|
+
src/alpha/domain/models/permission.py
|
|
19
20
|
src/alpha/domain/models/role.py
|
|
20
21
|
src/alpha/domain/models/user.py
|
|
21
22
|
src/alpha/factories/__init__.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/README.mustache
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/encoder.mustache
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/model.mustache
RENAMED
|
File without changes
|
{alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/openapi.mustache
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/setup.mustache
RENAMED
|
File without changes
|
|
File without changes
|
{alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/tox.mustache
RENAMED
|
File without changes
|
{alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/travis.mustache
RENAMED
|
File without changes
|
|
File without changes
|
{alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/handlers/templates/python-flask/util.mustache
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/refresh/cache_repository.py
RENAMED
|
File without changes
|
{alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/refresh/database_repository.py
RENAMED
|
File without changes
|
|
File without changes
|
{alpha_python-0.7.5 → alpha_python-0.7.7}/src/alpha/repositories/refresh/memory_repository.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|