feat: The Other Dude v9.0.1 — full-featured email system
ci: add GitHub Pages deployment workflow for docs site Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
76
backend/tests/unit/test_api_key_service.py
Normal file
76
backend/tests/unit/test_api_key_service.py
Normal file
@@ -0,0 +1,76 @@
|
||||
"""Unit tests for API key service.
|
||||
|
||||
Tests cover:
|
||||
- Key generation format (mktp_ prefix, sufficient length)
|
||||
- Key hashing (SHA-256 hex digest, 64 chars)
|
||||
- Scope validation against allowed list
|
||||
- Key prefix extraction
|
||||
|
||||
These are pure function tests -- no database or async required.
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
|
||||
from app.services.api_key_service import (
|
||||
ALLOWED_SCOPES,
|
||||
generate_raw_key,
|
||||
hash_key,
|
||||
)
|
||||
|
||||
|
||||
class TestKeyGeneration:
|
||||
"""Tests for API key generation."""
|
||||
|
||||
def test_key_starts_with_prefix(self):
|
||||
key = generate_raw_key()
|
||||
assert key.startswith("mktp_")
|
||||
|
||||
def test_key_has_sufficient_length(self):
|
||||
"""Key should be mktp_ + at least 32 chars of randomness."""
|
||||
key = generate_raw_key()
|
||||
assert len(key) >= 37 # "mktp_" (5) + 32
|
||||
|
||||
def test_key_uniqueness(self):
|
||||
"""Two generated keys should never be the same."""
|
||||
key1 = generate_raw_key()
|
||||
key2 = generate_raw_key()
|
||||
assert key1 != key2
|
||||
|
||||
|
||||
class TestKeyHashing:
|
||||
"""Tests for SHA-256 key hashing."""
|
||||
|
||||
def test_hash_produces_64_char_hex(self):
|
||||
key = "mktp_test1234567890abcdef"
|
||||
h = hash_key(key)
|
||||
assert len(h) == 64
|
||||
assert all(c in "0123456789abcdef" for c in h)
|
||||
|
||||
def test_hash_is_sha256(self):
|
||||
key = "mktp_test1234567890abcdef"
|
||||
expected = hashlib.sha256(key.encode()).hexdigest()
|
||||
assert hash_key(key) == expected
|
||||
|
||||
def test_hash_deterministic(self):
|
||||
key = generate_raw_key()
|
||||
assert hash_key(key) == hash_key(key)
|
||||
|
||||
def test_different_keys_different_hashes(self):
|
||||
key1 = generate_raw_key()
|
||||
key2 = generate_raw_key()
|
||||
assert hash_key(key1) != hash_key(key2)
|
||||
|
||||
|
||||
class TestAllowedScopes:
|
||||
"""Tests for scope definitions."""
|
||||
|
||||
def test_allowed_scopes_contains_expected(self):
|
||||
expected = {
|
||||
"devices:read",
|
||||
"devices:write",
|
||||
"config:read",
|
||||
"config:write",
|
||||
"alerts:read",
|
||||
"firmware:write",
|
||||
}
|
||||
assert expected == ALLOWED_SCOPES
|
||||
Reference in New Issue
Block a user