A small command line application for registering and authenticating user accounts. Originally written as a first programming project in 2023-2024, this version has been rebuilt around a proper object oriented design.
- User registration with an auto generated username based on name initials and birth year, with automatic collision handling.
- Password policy enforcement (length, uppercase, lowercase, digit).
- Passwords are never stored in plain text. They are hashed with PBKDF2-HMAC-SHA256 using a unique random salt per user.
- Account lockout after repeated failed login attempts.
- User data persisted as JSON rather than pickle, avoiding the arbitrary code execution risk that comes with deserializing untrusted pickle files.
- A layered architecture that separates storage, business logic, and the command line interface, making each part independently testable.
employee_access_system/
models.py User data model
exceptions.py Application specific exceptions
security.py Password hashing and password policy
repository.py Storage abstraction and JSON implementation
auth_service.py Registration and authentication logic
cli.py Command line menu and user interaction
main.py Application entry point
tests/ Unit tests for each module
Requires Python 3.10 or newer (standard library only, no external dependencies).
python main.py
User accounts are stored in user_data.json in the working directory,
created automatically on first registration.
python -m unittest discover -s tests
The system follows a layered structure:
Useris a plain data model.UserRepositoryis an abstract interface for persistence, implemented byJsonUserRepository. This makes it straightforward to swap in a different storage backend (a database, for example) without touching business logic.AuthenticationServicecontains all registration and login rules (username generation, password policy, lockout behavior) and depends only on the repository abstraction.EmployeeAccessCLIhandles user interaction and delegates everything else to the authentication service.
This separation keeps each class focused on a single responsibility and allows the business logic to be unit tested without touching the file system or the terminal.