Files
disknext/tests/unit/utils/test_password.py
于小丘 209cb24ab4 feat: add models for physical files, policies, and user management
- Implement PhysicalFile model to manage physical file references and reference counting.
- Create Policy model with associated options and group links for storage policies.
- Introduce Redeem and Report models for handling redeem codes and reports.
- Add Settings model for site configuration and user settings management.
- Develop Share model for sharing objects with unique codes and associated metadata.
- Implement SourceLink model for managing download links associated with objects.
- Create StoragePack model for managing user storage packages.
- Add Tag model for user-defined tags with manual and automatic types.
- Implement Task model for managing background tasks with status tracking.
- Develop User model with comprehensive user management features including authentication.
- Introduce UserAuthn model for managing WebAuthn credentials.
- Create WebDAV model for managing WebDAV accounts associated with users.
2026-02-10 19:07:48 +08:00

139 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Password 工具类的单元测试
"""
import pytest
from utils.password.pwd import Password, PasswordStatus
def test_password_generate_default_length():
"""测试默认长度生成密码"""
password = Password.generate()
# 默认长度为 8token_hex 生成的是16进制字符串长度是原始长度的2倍
assert len(password) == 16
assert isinstance(password, str)
def test_password_generate_custom_length():
"""测试自定义长度生成密码"""
length = 12
password = Password.generate(length=length)
assert len(password) == length * 2
assert isinstance(password, str)
def test_password_hash():
"""测试密码哈希"""
plain_password = "my_secure_password_123"
hashed = Password.hash(plain_password)
assert hashed != plain_password
assert isinstance(hashed, str)
# Argon2 哈希以 $argon2 开头
assert hashed.startswith("$argon2")
def test_password_verify_valid():
"""测试正确密码验证"""
plain_password = "correct_password"
hashed = Password.hash(plain_password)
status = Password.verify(hashed, plain_password)
assert status == PasswordStatus.VALID
def test_password_verify_invalid():
"""测试错误密码验证"""
plain_password = "correct_password"
wrong_password = "wrong_password"
hashed = Password.hash(plain_password)
status = Password.verify(hashed, wrong_password)
assert status == PasswordStatus.INVALID
def test_password_verify_expired():
"""测试密码哈希过期检测"""
# 注意: 实际检测需要修改 Argon2 参数,这里只是测试接口
# 在真实场景中,当哈希参数过时时会返回 EXPIRED
plain_password = "password"
hashed = Password.hash(plain_password)
status = Password.verify(hashed, plain_password)
# 新生成的哈希应该是 VALID
assert status in [PasswordStatus.VALID, PasswordStatus.EXPIRED]
@pytest.mark.asyncio
async def test_totp_generate():
"""测试 TOTP 密钥生成"""
email = "testuser@test.local"
response = await Password.generate_totp(email)
assert response.setup_token is not None
assert response.uri is not None
assert isinstance(response.setup_token, str)
assert isinstance(response.uri, str)
# TOTP URI 格式: otpauth://totp/...
assert response.uri.startswith("otpauth://totp/")
assert email in response.uri
def test_totp_verify_valid():
"""测试 TOTP 验证正确"""
import pyotp
# 生成密钥
secret = pyotp.random_base32()
# 生成当前有效的验证码
totp = pyotp.TOTP(secret)
valid_code = totp.now()
# 验证
status = Password.verify_totp(secret, valid_code)
assert status == PasswordStatus.VALID
def test_totp_verify_invalid():
"""测试 TOTP 验证错误"""
import pyotp
secret = pyotp.random_base32()
invalid_code = "000000" # 几乎不可能是当前有效码
status = Password.verify_totp(secret, invalid_code)
# 注意: 极小概率 000000 恰好是有效码,但实际测试中基本不会发生
assert status == PasswordStatus.INVALID
def test_password_hash_consistency():
"""测试相同密码多次哈希结果不同(盐随机)"""
password = "test_password"
hash1 = Password.hash(password)
hash2 = Password.hash(password)
# 由于盐是随机的,两次哈希结果应该不同
assert hash1 != hash2
# 但都应该能通过验证
assert Password.verify(hash1, password) == PasswordStatus.VALID
assert Password.verify(hash2, password) == PasswordStatus.VALID
def test_password_generate_uniqueness():
"""测试生成的密码唯一性"""
passwords = [Password.generate() for _ in range(100)]
# 100个密码应该都不相同
assert len(set(passwords)) == 100