python-neva 0.5.0__tar.gz → 0.6.0.dev2__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.
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/PKG-INFO +1 -1
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/security/__init__.py +3 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/security/hashing/config.py +7 -7
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/security/hashing/hash_manager.py +3 -3
- python_neva-0.6.0.dev2/neva/security/tokens/__init__.py +5 -0
- python_neva-0.6.0.dev2/neva/security/tokens/token_hash.py +30 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/pyproject.toml +1 -1
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/uv.lock +1 -1
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/.envrc +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/.gitignore +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/.pre-commit-config.yaml +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/.python-version +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/README.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/arch/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/arch/app.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/arch/application.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/arch/config.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/arch/facade.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/arch/service_provider.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/config/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/config/base_providers.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/config/loader.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/config/provider.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/config/repository.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/console/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/console/kernel.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/console/runner.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/database/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/database/config.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/database/manager.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/database/provider.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/database/repository.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/events/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/events/dispatcher.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/events/event.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/events/event_registry.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/events/interface.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/events/listener.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/obs/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/obs/logging/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/obs/logging/manager.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/obs/logging/provider.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/obs/middleware/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/obs/middleware/correlation.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/obs/middleware/profiler.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/py.typed +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/security/encryption/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/security/encryption/encrypter.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/security/encryption/protocol.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/security/hashing/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/security/hashing/hashers/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/security/hashing/hashers/argon2.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/security/hashing/hashers/bcrypt.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/security/hashing/hashers/protocol.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/security/provider.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/accessors.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/facade/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/facade/app.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/facade/app.pyi +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/facade/config.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/facade/config.pyi +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/facade/crypt.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/facade/crypt.pyi +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/facade/hash.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/facade/hash.pyi +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/facade/log.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/facade/log.pyi +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/results.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/strategy.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/strconv.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/support/time.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/testing/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/testing/fixtures.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/testing/http.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/neva/testing/test_case.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/ruff.toml +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/specifications/future_ideas.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/specifications/security.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/tests/__init__.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/tests/conftest.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/tests/test_encrypter.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/tests/test_example_usage.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/tests/test_fixtures.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/tests/test_hash_manager.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/tests/test_scope.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/tests/test_test_case.py +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/architecture/01-overview.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/architecture/02-dependency-injection.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/architecture/03-service-providers.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/architecture/04-facades.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/architecture/05-application-lifecycle.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/architecture/06-result-option.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/configuration/01-overview.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/configuration/02-configuration-files.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/configuration/03-accessing-configuration.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/configuration/04-config-repository.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/configuration/05-loading-process.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/configuration/06-configuration-in-providers.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/testing/01-introduction.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/testing/02-test-case.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/testing/03-fixtures.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/testing/04-http-testing.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/testing/05-custom-configuration.md +0 -0
- {python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/testing/06-test-isolation.md +0 -0
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from neva.security.encryption import AesEncrypter, DecryptionError, Encrypter
|
|
4
4
|
from neva.security.hashing import Argon2Hasher, BcryptHasher, HashManager, Hasher
|
|
5
5
|
from neva.security.provider import SecurityProvider
|
|
6
|
+
from neva.security.tokens import hash_token, verify_token
|
|
6
7
|
|
|
7
8
|
__all__ = [
|
|
8
9
|
"AesEncrypter",
|
|
@@ -13,4 +14,6 @@ __all__ = [
|
|
|
13
14
|
"HashManager",
|
|
14
15
|
"Hasher",
|
|
15
16
|
"SecurityProvider",
|
|
17
|
+
"hash_token",
|
|
18
|
+
"verify_token",
|
|
16
19
|
]
|
|
@@ -6,18 +6,18 @@ from typing import Literal, NotRequired, TypedDict
|
|
|
6
6
|
class BcryptConfig(TypedDict):
|
|
7
7
|
"""Bcrypt hasher config."""
|
|
8
8
|
|
|
9
|
-
rounds: int
|
|
10
|
-
prefix:
|
|
9
|
+
rounds: NotRequired[int]
|
|
10
|
+
prefix: NotRequired[Literal["2a", "2b"]]
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class Argon2Config(TypedDict):
|
|
14
14
|
"""Argon2 hasher config."""
|
|
15
15
|
|
|
16
|
-
time_cost: int
|
|
17
|
-
memory_cost: int
|
|
18
|
-
parallelism: int
|
|
19
|
-
hash_len: int
|
|
20
|
-
salt_len: int
|
|
16
|
+
time_cost: NotRequired[int]
|
|
17
|
+
memory_cost: NotRequired[int]
|
|
18
|
+
parallelism: NotRequired[int]
|
|
19
|
+
hash_len: NotRequired[int]
|
|
20
|
+
salt_len: NotRequired[int]
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class HashingConfig(TypedDict):
|
|
@@ -22,15 +22,15 @@ class HashManager(StrategyResolver[Hasher]):
|
|
|
22
22
|
"""
|
|
23
23
|
super().__init__(app)
|
|
24
24
|
|
|
25
|
-
self.register("argon2", self._create_argon2_hasher)
|
|
26
|
-
self.register("bcrypt", self._create_bcrypt_hasher)
|
|
25
|
+
_ = self.register("argon2", self._create_argon2_hasher)
|
|
26
|
+
_ = self.register("bcrypt", self._create_bcrypt_hasher)
|
|
27
27
|
|
|
28
28
|
@override
|
|
29
29
|
def default(self) -> Option[str]:
|
|
30
30
|
"""Get the default hasher from configuration.
|
|
31
31
|
|
|
32
32
|
Returns:
|
|
33
|
-
Option containing the default hasher name
|
|
33
|
+
Option containing the default hasher name.
|
|
34
34
|
"""
|
|
35
35
|
config_result = self.app.make(ConfigRepository)
|
|
36
36
|
if config_result.is_err:
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Token hashing utilities."""
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import hmac
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def hash_token(token: str | bytes) -> str:
|
|
8
|
+
"""Hash a secure random token for storage.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
token: The token to hash.
|
|
12
|
+
|
|
13
|
+
Returns:
|
|
14
|
+
Hex-encoded hash of the token.
|
|
15
|
+
"""
|
|
16
|
+
data = token.encode() if isinstance(token, str) else token
|
|
17
|
+
return hashlib.sha256(data).hexdigest()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def verify_token(token: str | bytes, hashed: str) -> bool:
|
|
21
|
+
"""Verify a token against its stored hash.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
token: The plaintext token to verify.
|
|
25
|
+
hashed: The stored hash to verify against.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
True if the token matches, False otherwise.
|
|
29
|
+
"""
|
|
30
|
+
return hmac.compare_digest(hash_token(token), hashed)
|
|
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
|
|
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
|
{python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/configuration/03-accessing-configuration.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_neva-0.5.0 → python_neva-0.6.0.dev2}/wiki/configuration/06-configuration-in-providers.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|