docs: update README with current project features and architecture

- Updated features list with navigation bar, HR notifications, and security features
- Added navigation and HR features sections with usage examples
- Updated file structure to show modular app/ package
- Changed running instructions from app.py to run.py
- Added mailcatcher as default SMTP configuration
- Included testing instructions and architecture documentation
- Updated data.yaml example with status and submitted_at fields
- Added comprehensive Security Features section (CSRF, rate limiting)
- Added Architecture section explaining factory pattern and modular structure
- Enhanced Troubleshooting section with mailcatcher, testing, and navigation issues
- Updated technology stack with all dependencies and versions
This commit is contained in:
2025-12-27 23:15:55 +01:00
parent ef5ccc18f7
commit 8294f89956
+313 -41
View File
@@ -1,17 +1,23 @@
# Job Application System
A simple, accessible Flask web application for job applications with email-based resume functionality and file uploads.
A professional, accessible Flask web application for job applications with email-based resume functionality, file uploads, and HR notifications.
## Features
- **Multi-step application process**: 5-page workflow from email capture to confirmation
- **Multi-step application process**: 5-page workflow with progress navigation
- **Progress navigation bar**: Visual indicator with backward navigation to edit previous pages
- **Email-based resume**: Applicants receive a unique link to resume their application
- **HR notifications**: Automated email alerts to HR when applications are submitted
- **Application review page**: Dedicated HR interface to view applications and download attachments
- **Stateful sessions**: Applications can be paused and resumed at any time
- **File uploads**: Support for CV, cover letter, and other documents (up to 3 files, 4 MB each)
- **German interface**: All user-facing content in German
- **File-based storage**: No database required - uses YAML for data serialization
- **Security features**: CSRF protection and rate limiting (5-second cooldown)
- **Modular architecture**: Clean separation of concerns with application factory pattern
- **Accessible design**: Minimal CSS, no JavaScript required, keyboard-friendly
- **Validation**: Comprehensive server-side validation for all inputs
- **Full test coverage**: 102 automated tests with 100% pass rate
## Application Workflow
@@ -21,12 +27,29 @@ A simple, accessible Flask web application for job applications with email-based
4. **Document Upload**: Upload up to 3 documents (CV, cover letter, etc.)
5. **Confirmation**: Success message with next steps
### Navigation Features
- **Progress bar**: Visual indicator shows current step and completion status
- **Backward navigation**: Users can click on completed steps to return and edit data
- **Sequential progression**: Users must complete pages in order (cannot skip ahead)
- **Data preservation**: All entered information is automatically saved when navigating
### HR Features
- **Email notifications**: HR receives an email when an application is submitted
- **Review interface**: Access applications at `/application/{session-id}/`
- **Download attachments**: HR can download all uploaded documents
- **Complete data view**: See all applicant information in one place
## Technology Stack
- Python 3
- Flask 3.0.0
- PyYAML for data serialization
- Flask-Mail for email sending
- **Python** 3.8+
- **Flask** 3.0.0 (with application factory pattern)
- **Flask-WTF** 1.2.1 (CSRF protection)
- **Flask-Mail** 0.9.1 (email sending)
- **PyYAML** 6.0.1 (data serialization)
- **Werkzeug** 3.0.1 (file handling)
- **pytest** 7.4.3 (testing framework)
- Minimal CSS for styling
- No JavaScript required
@@ -60,18 +83,44 @@ A simple, accessible Flask web application for job applications with email-based
- Edit `.env` and configure your settings:
```
SECRET_KEY=your-secret-key-here
MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587
MAIL_USE_TLS=True
MAIL_USERNAME=your-email@example.com
MAIL_PASSWORD=your-app-password
MAIL_DEFAULT_SENDER=noreply@example.com
COMPANY_NAME=Your Company Name
HR_EMAIL=hr@example.com
APPLICATION_URL_BASE=http://localhost:5000
```
### Email Configuration
For **Gmail**, you need to:
The application defaults to **mailcatcher** for development (localhost:1025, no authentication required).
#### For Development (Mailcatcher)
1. **Install mailcatcher**:
```bash
gem install mailcatcher
```
2. **Run mailcatcher**:
```bash
mailcatcher
```
3. **View emails**: Open http://localhost:1080 in your browser
4. **No .env changes needed** - the application uses mailcatcher by default
#### For Production (Real SMTP)
Add to your `.env` file:
```
MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587
MAIL_USE_TLS=True
MAIL_USERNAME=your-email@example.com
MAIL_PASSWORD=your-app-password
```
For **Gmail**:
1. Enable 2-factor authentication on your Google account
2. Generate an "App Password" at https://myaccount.google.com/apppasswords
3. Use the app password (not your regular password) in `MAIL_PASSWORD`
@@ -83,11 +132,32 @@ For **other email providers**, adjust `MAIL_SERVER` and `MAIL_PORT` accordingly.
### Development Mode
```bash
python app.py
python run.py
```
Or using Flask CLI:
```bash
flask run
```
The application will run at `http://127.0.0.1:5000`
### Running Tests
The application includes a comprehensive test suite with 102 tests:
```bash
# Run all tests
pytest tests/ -v
# Run with coverage report
pytest tests/ --cov=app --cov-report=html
# Run specific test file
pytest tests/test_routes.py -v
```
### Production Deployment
For production, use a WSGI server like Gunicorn:
@@ -99,11 +169,18 @@ For production, use a WSGI server like Gunicorn:
2. **Run with Gunicorn**:
```bash
gunicorn -w 4 -b 0.0.0.0:8000 app:app
gunicorn -w 4 -b 0.0.0.0:8000 "app:create_app()"
```
3. **Use a reverse proxy** (e.g., Nginx) in front of Gunicorn
4. **Update production settings** in `.env`:
```
WTF_CSRF_SSL_STRICT=True
SESSION_COOKIE_SECURE=True
MAIL_SERVER=your-production-smtp-server
```
## Usage
### Linking from Job Postings
@@ -130,24 +207,44 @@ This link allows them to resume their application at any time.
```
.
├── app.py # Main Flask application
├── config.py # Configuration settings
├── requirements.txt # Python dependencies
├── .env.example # Example environment variables
├── README.md # This file
├── templates/ # HTML templates
│ ├── base.html
│ ├── page1_email.html
│ ├── page2_personal.html
│ ├── page3_motivation.html
│ ├── page4_upload.html
│ └── page5_confirmation.html
├── static/ # Static files
── style.css
└── applications/ # Application data (created automatically)
├── run.py # Application entry point
├── config.py # Configuration settings
├── requirements.txt # Python dependencies
├── .env.example # Example environment variables
├── README.md # This file
├── app/ # Main application package
│ ├── __init__.py # Application factory
│ ├── routes.py # Route handlers (all endpoints)
│ ├── models.py # Data persistence layer
│ ├── validators.py # Input validation functions
│ ├── email_service.py # Email sending functions
│ └── utils.py # Utility functions
├── templates/ # HTML templates
── base.html # Base template with navigation
│ ├── _navigation.html # Progress bar component
│ ├── page1_email.html # Email capture page
│ ├── page2_personal.html # Personal information page
│ ├── page3_motivation.html # Motivation questions page
│ ├── page4_upload.html # Document upload page
│ ├── page5_confirmation.html # Confirmation page
│ └── application_view.html # HR application review page
├── static/ # Static files
│ └── style.css # Styles (including navigation)
├── tests/ # Test suite (102 tests)
│ ├── conftest.py # Test configuration and fixtures
│ ├── test_routes.py # Route handler tests
│ ├── test_validation.py # Validation function tests
│ ├── test_email.py # Email functionality tests
│ ├── test_storage.py # Data persistence tests
│ ├── test_uploads.py # File upload tests
│ ├── test_integration.py # End-to-end workflow tests
│ ├── test_hr_notifications.py # HR email notification tests
│ ├── test_application_view.py # Application review page tests
│ └── test_config.py # Configuration tests
└── applications/ # Application data (created automatically)
└── {session-id}/
├── data.yaml
└── attachments/
├── data.yaml # Application data
└── attachments/ # Uploaded files
```
## Data Storage
@@ -163,9 +260,11 @@ Each application is stored in its own folder under `./applications/{session-id}/
session_id: "abc123-def456-..."
email: "applicant@example.com"
job_name: "Junior Marketing Assistant"
current_page: 4
current_page: 5
status: "submitted"
created_at: "2025-01-15T10:30:00"
updated_at: "2025-01-15T11:45:00"
submitted_at: "2025-01-15T11:45:00"
personal_info:
name: "Müller"
firstname: "Anna"
@@ -211,13 +310,93 @@ uploaded_files:
- Maximum 4 MB per file
- Allowed formats: PDF, DOC, DOCX, TXT, JPG, JPEG, PNG
## Security Considerations
## Security Features
- Session IDs use cryptographically secure UUIDs
- File uploads are validated for size and type
- Filenames are sanitized to prevent path traversal
- All validation is server-side
- Email configuration uses environment variables
### CSRF Protection
All forms are protected against Cross-Site Request Forgery (CSRF) attacks using Flask-WTF:
- CSRF tokens required on all POST requests
- Tokens included automatically in all forms
- No token expiration (users can take time filling forms)
- Configurable for production HTTPS environments
### Rate Limiting
Built-in rate limiting prevents form spam and abuse:
- 5-second cooldown between form submissions (configurable)
- Session-based tracking
- Customizable in `config.py`: `RATE_LIMIT_SECONDS = 5`
### Data Security
- **Session IDs**: Cryptographically secure UUIDs (not guessable)
- **File uploads**: Validated for size, type, and sanitized filenames
- **Path traversal protection**: Secure filename handling prevents directory attacks
- **Server-side validation**: All input validated on the server
- **Environment variables**: Sensitive configuration kept in `.env` file
- **No SQL injection**: File-based storage eliminates SQL vulnerabilities
### Production Security Checklist
When deploying to production, update `.env`:
```
SECRET_KEY=<strong-random-secret-key>
WTF_CSRF_SSL_STRICT=True
SESSION_COOKIE_SECURE=True
SESSION_COOKIE_HTTPONLY=True
SESSION_COOKIE_SAMESITE=Lax
```
## HR Features
### Accessing Applications
HR staff can review applications using the direct URL:
```
https://your-domain.com/application/{session-id}/
```
The session ID is included in the HR notification email sent when an application is submitted.
### HR Notification Emails
Configure HR email notifications in `.env`:
```
HR_EMAIL=hr@example.com
APPLICATION_URL_BASE=https://your-domain.com
```
When an applicant submits their application (page 4), an email is automatically sent to the HR email address containing:
- Applicant name and email
- Position applied for
- Submission timestamp
- Number of uploaded documents
- Direct link to the application review page
### Application Review Page
The review page (`/application/{session-id}/`) displays:
- Complete applicant information (all form fields)
- All uploaded documents with download links
- Submission timestamp and metadata
- Professional formatting for easy review
### Downloading Attachments
HR can download individual files directly from the review page:
```
https://your-domain.com/application/{session-id}/download/{filename}
```
Security: Only files listed in the application's uploaded_files list can be downloaded (prevents unauthorized access).
## Customization
@@ -244,26 +423,119 @@ ALLOWED_EXTENSIONS = {'pdf', 'doc', 'docx', 'txt', 'jpg', 'jpeg', 'png'}
Edit all templates in `./templates/` - they contain German text that can be translated.
## Architecture
### Application Factory Pattern
The application uses Flask's application factory pattern for better testability and flexibility:
- `app/__init__.py` contains the `create_app()` function
- Extensions (Flask-Mail, CSRF) are initialized within the factory
- Multiple app instances can be created (useful for testing)
- Configuration can be passed as a parameter
### Modular Structure
Code is organized by responsibility:
- **routes.py** (473 lines): All route handlers and request processing
- **models.py** (41 lines): Data persistence layer (YAML operations)
- **validators.py** (48 lines): Input validation functions
- **email_service.py** (85 lines): Email sending logic
- **utils.py** (30 lines): Utility functions (rate limiting, etc.)
Benefits:
- Easy to test individual modules in isolation
- Clear separation of concerns
- Easier to navigate and maintain
- Supports team collaboration
### Testing Strategy
The application includes 102 automated tests organized by functionality:
- **test_routes.py**: Route handler behavior
- **test_validation.py**: Input validation logic
- **test_email.py**: Email sending functionality
- **test_storage.py**: YAML data persistence
- **test_uploads.py**: File upload handling
- **test_integration.py**: End-to-end workflows
- **test_hr_notifications.py**: HR email notifications
- **test_application_view.py**: Application review page
- **test_config.py**: Configuration settings
Run tests frequently during development to catch regressions early.
## Troubleshooting
### Email not sending
### Email not sending in development
**Using Mailcatcher (recommended for development):**
1. Verify mailcatcher is running:
```bash
mailcatcher
```
2. Check mailcatcher web interface at http://localhost:1080
3. Verify application is configured for mailcatcher:
- Default settings work out of the box (localhost:1025)
- No `.env` email configuration needed for development
**Using real SMTP:**
- Check your email credentials in `.env`
- For Gmail, ensure you're using an app password, not your regular password
- Check that `MAIL_USE_TLS` is set correctly for your email provider
- Check application logs for error messages
### Tests failing
If tests fail after making changes:
```bash
# Run specific test file to identify the issue
pytest tests/test_routes.py -v
# Run with detailed output
pytest tests/ -vv
# Check test coverage
pytest tests/ --cov=app --cov-report=term-missing
```
Common issues:
- Import errors: Check module structure in `app/` package
- Template errors: Verify templates exist in `templates/` directory
- CSRF errors: Tests disable CSRF in `conftest.py`
### File upload errors
- Ensure the `./applications/` folder is writable
- Ensure the `./applications/` folder exists and is writable
- Check file size limits in your web server configuration
- Verify allowed file extensions in `config.py`
- Check that storage path is correct in config
### Session not resuming
- Check that the `./applications/{session-id}/` folder exists
- Verify that `data.yaml` is valid YAML format
- Check application logs for errors
- Ensure session ID in URL is correct (UUID format)
### Navigation not working
- Verify `current_page` is being passed to templates
- Check that navigation component is included in `base.html`
- Ensure session data contains valid `current_page` value
- Check browser console for CSS/styling issues
### Rate limiting preventing form submission
- Check `RATE_LIMIT_SECONDS` in `config.py` (default: 5 seconds)
- Wait the specified time between submissions
- For testing, set to 0 in `.env`: `RATE_LIMIT_SECONDS=0`
## License