- Implement secure user registration and login - Add password hashing with PBKDF2 and random salts - Create session-based authentication with secure tokens - Support user deactivation and session management - Include comprehensive unit tests for authentication - Integrate authentication demo into main application 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
141 lines
6.0 KiB
Python
141 lines
6.0 KiB
Python
import pytest
|
|
import sys
|
|
import os
|
|
import time
|
|
|
|
# Add src directory to path for imports
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'src'))
|
|
|
|
from auth import UserManager, AuthenticationError, User
|
|
|
|
class TestUserManager:
|
|
|
|
def setup_method(self):
|
|
"""Setup test fixtures"""
|
|
self.user_manager = UserManager()
|
|
|
|
def test_register_user_success(self):
|
|
"""Test successful user registration"""
|
|
result = self.user_manager.register_user("testuser", "test@example.com", "password123")
|
|
assert result is True
|
|
assert "testuser" in self.user_manager.users
|
|
|
|
user = self.user_manager.users["testuser"]
|
|
assert user.username == "testuser"
|
|
assert user.email == "test@example.com"
|
|
assert user.is_active is True
|
|
assert user.created_at is not None
|
|
|
|
def test_register_duplicate_username(self):
|
|
"""Test registration with duplicate username"""
|
|
self.user_manager.register_user("testuser", "test1@example.com", "password123")
|
|
|
|
with pytest.raises(ValueError, match="Username already exists"):
|
|
self.user_manager.register_user("testuser", "test2@example.com", "password456")
|
|
|
|
def test_register_weak_password(self):
|
|
"""Test registration with weak password"""
|
|
with pytest.raises(ValueError, match="Password must be at least 8 characters long"):
|
|
self.user_manager.register_user("testuser", "test@example.com", "123")
|
|
|
|
def test_authenticate_success(self):
|
|
"""Test successful authentication"""
|
|
self.user_manager.register_user("testuser", "test@example.com", "password123")
|
|
|
|
session_token = self.user_manager.authenticate("testuser", "password123")
|
|
|
|
assert session_token is not None
|
|
assert len(session_token) > 0
|
|
assert session_token in self.user_manager.sessions
|
|
assert self.user_manager.sessions[session_token] == "testuser"
|
|
|
|
def test_authenticate_invalid_username(self):
|
|
"""Test authentication with invalid username"""
|
|
with pytest.raises(AuthenticationError, match="Invalid username or password"):
|
|
self.user_manager.authenticate("nonexistent", "password123")
|
|
|
|
def test_authenticate_invalid_password(self):
|
|
"""Test authentication with invalid password"""
|
|
self.user_manager.register_user("testuser", "test@example.com", "password123")
|
|
|
|
with pytest.raises(AuthenticationError, match="Invalid username or password"):
|
|
self.user_manager.authenticate("testuser", "wrongpassword")
|
|
|
|
def test_authenticate_deactivated_user(self):
|
|
"""Test authentication with deactivated user"""
|
|
self.user_manager.register_user("testuser", "test@example.com", "password123")
|
|
self.user_manager.deactivate_user("testuser")
|
|
|
|
with pytest.raises(AuthenticationError, match="Account is deactivated"):
|
|
self.user_manager.authenticate("testuser", "password123")
|
|
|
|
def test_validate_session_success(self):
|
|
"""Test successful session validation"""
|
|
self.user_manager.register_user("testuser", "test@example.com", "password123")
|
|
session_token = self.user_manager.authenticate("testuser", "password123")
|
|
|
|
username = self.user_manager.validate_session(session_token)
|
|
assert username == "testuser"
|
|
|
|
def test_validate_session_invalid_token(self):
|
|
"""Test session validation with invalid token"""
|
|
username = self.user_manager.validate_session("invalid_token")
|
|
assert username is None
|
|
|
|
def test_logout_success(self):
|
|
"""Test successful logout"""
|
|
self.user_manager.register_user("testuser", "test@example.com", "password123")
|
|
session_token = self.user_manager.authenticate("testuser", "password123")
|
|
|
|
result = self.user_manager.logout(session_token)
|
|
assert result is True
|
|
assert session_token not in self.user_manager.sessions
|
|
|
|
def test_logout_invalid_token(self):
|
|
"""Test logout with invalid token"""
|
|
result = self.user_manager.logout("invalid_token")
|
|
assert result is False
|
|
|
|
def test_get_user_success(self):
|
|
"""Test getting user information"""
|
|
self.user_manager.register_user("testuser", "test@example.com", "password123")
|
|
|
|
user = self.user_manager.get_user("testuser")
|
|
assert user is not None
|
|
assert user.username == "testuser"
|
|
assert user.email == "test@example.com"
|
|
|
|
def test_get_user_nonexistent(self):
|
|
"""Test getting nonexistent user"""
|
|
user = self.user_manager.get_user("nonexistent")
|
|
assert user is None
|
|
|
|
def test_deactivate_user_success(self):
|
|
"""Test successful user deactivation"""
|
|
self.user_manager.register_user("testuser", "test@example.com", "password123")
|
|
session_token = self.user_manager.authenticate("testuser", "password123")
|
|
|
|
result = self.user_manager.deactivate_user("testuser")
|
|
assert result is True
|
|
assert self.user_manager.users["testuser"].is_active is False
|
|
assert session_token not in self.user_manager.sessions
|
|
|
|
def test_deactivate_user_nonexistent(self):
|
|
"""Test deactivating nonexistent user"""
|
|
result = self.user_manager.deactivate_user("nonexistent")
|
|
assert result is False
|
|
|
|
def test_password_hashing_security(self):
|
|
"""Test that passwords are properly hashed and salted"""
|
|
self.user_manager.register_user("user1", "user1@example.com", "password123")
|
|
self.user_manager.register_user("user2", "user2@example.com", "password123")
|
|
|
|
user1 = self.user_manager.users["user1"]
|
|
user2 = self.user_manager.users["user2"]
|
|
|
|
# Same password should have different hashes due to different salts
|
|
assert user1.password_hash != user2.password_hash
|
|
|
|
# Password hash should contain salt and hash separated by colon
|
|
assert ":" in user1.password_hash
|
|
assert ":" in user2.password_hash |