Implement a complete client portal feature that allows clients to access their projects, invoices, and time entries through a dedicated portal with separate authentication. Includes password setup via email with secure token-based authentication. Client Portal Features: - Client-based authentication (separate from user accounts) - Portal access can be enabled/disabled per client - Clients can view their projects, invoices, and time entries - Clean, minimal UI without main app navigation elements - Login page styled to match main app design Password Setup Email: - Admin can send password setup emails to clients - Secure token-based password setup (24-hour expiration) - Email template with professional styling - Password setup page matching app login design - Token validation and automatic cleanup after use Email Configuration: - Email settings from admin menu are now used for sending - Database email settings persist between restarts and updates - Automatic reload of email configuration when sending emails - Database settings take precedence over environment variables - Improved error messages for email configuration issues Database Changes: - Add portal_enabled, portal_username, portal_password_hash to clients - Add password_setup_token and password_setup_token_expires to clients - Migration 047: Add client portal fields to users (legacy) - Migration 048: Add client portal credentials to clients - Migration 049: Add password setup token fields New Files: - app/routes/client_portal.py - Client portal routes and authentication - app/templates/client_portal/ - Portal templates (base, login, dashboard, etc.) - app/templates/email/client_portal_password_setup.html - Email template - migrations/versions/047-049 - Database migrations - tests/test_client_portal.py - Portal tests - docs/CLIENT_PORTAL.md - Portal documentation Modified Files: - app/models/client.py - Add portal fields and password token methods - app/routes/clients.py - Add send password email route - app/routes/client_portal.py - Portal routes with redirect handling - app/utils/email.py - Use database settings, add password setup email - app/templates/clients/edit.html - Add send email button - app/templates/components/ui.html - Support client portal breadcrumbs Security: - Secure token generation using secrets.token_urlsafe() - Password hashing with werkzeug.security - Token expiration (24 hours default) - Token cleared after successful password setup - CSRF protection on all forms
5.4 KiB
Client Portal Feature
Overview
The Client Portal provides a simplified, read-only interface for client users to view their projects, invoices, and time entries. This feature allows you to grant clients access to view their own data without exposing internal system functionality or other clients' information.
Features
- Dashboard: Overview of projects, invoices, and time entries
- Projects View: List of all active projects with statistics
- Invoices View: List of invoices with filtering options (all, paid, unpaid, overdue)
- Invoice Details: Detailed view of individual invoices
- Time Entries: View time entries for projects with filtering capabilities
Enabling Client Portal Access
For Administrators
- Navigate to Admin → Users
- Click Edit on the user you want to grant portal access to
- Scroll to the Client Portal Access section
- Check Enable Client Portal
- Select the Client from the dropdown
- Click Save
The user will now have access to the client portal at /client-portal.
User Requirements
For a user to access the client portal:
client_portal_enabledmust beTrueclient_idmust be set to a valid client ID- The user must be active (
is_active = True)
Access Control
- Client portal users can only see data for their assigned client
- They cannot access:
- Other clients' data
- Internal admin functions
- User management
- System settings
- All portal routes require authentication and portal access verification
Portal Routes
Dashboard
- URL:
/client-portalor/client-portal/dashboard - Description: Overview page showing statistics and recent activity
Projects
- URL:
/client-portal/projects - Description: List of all active projects for the client
Invoices
- URL:
/client-portal/invoices - Query Parameters:
status: Filter by status (all,paid,unpaid,overdue)
- Description: List of invoices with filtering options
Invoice Detail
- URL:
/client-portal/invoices/<invoice_id> - Description: Detailed view of a specific invoice
Time Entries
- URL:
/client-portal/time-entries - Query Parameters:
project_id: Filter by projectdate_from: Filter entries from this date (YYYY-MM-DD)date_to: Filter entries to this date (YYYY-MM-DD)
- Description: List of time entries with filtering capabilities
Database Schema
User Model Changes
Two new fields were added to the users table:
client_portal_enabled BOOLEAN NOT NULL DEFAULT 0
client_id INTEGER REFERENCES clients(id) ON DELETE SET NULL
Migration
The migration 047_add_client_portal_fields.py adds these fields. Run:
alembic upgrade head
User Model Methods
is_client_portal_user (property)
Returns True if the user has client portal access enabled and a client assigned.
if user.is_client_portal_user:
# User has portal access
get_client_portal_data()
Returns a dictionary containing all portal data for the user's assigned client:
data = user.get_client_portal_data()
# Returns:
# {
# 'client': Client object,
# 'projects': [list of active projects],
# 'invoices': [list of invoices],
# 'time_entries': [list of time entries]
# }
Returns None if portal access is not enabled or no client is assigned.
Admin Interface
User List
The user list now displays a "Portal" badge for users with client portal access enabled, showing which client they're assigned to.
User Edit Form
The user edit form includes a new Client Portal Access section with:
- Checkbox to enable/disable portal access
- Dropdown to select the assigned client
- Validation to ensure a client is selected when enabling portal access
Security Considerations
-
Access Control: All portal routes verify that:
- User is authenticated
- User has
client_portal_enabled = True - User has a valid
client_id
-
Data Isolation: Portal users can only see:
- Projects belonging to their assigned client
- Invoices for their assigned client
- Time entries for projects belonging to their assigned client
-
Read-Only Access: The portal is read-only - users cannot modify any data
-
Invoice Access: Users can only view invoices that belong to their assigned client
Testing
Comprehensive tests are available in tests/test_client_portal.py:
- Model tests for user portal properties
- Route tests for access control
- Admin interface tests for enabling/disabling portal access
- Smoke tests for basic functionality
Run tests with:
pytest tests/test_client_portal.py -v
Troubleshooting
User Cannot Access Portal
- Verify
client_portal_enabledisTruein the database - Verify
client_idis set to a valid client ID - Verify the user is active (
is_active = True) - Check that the client exists and is active
Portal Shows No Data
- Verify the client has active projects
- Check that invoices exist for the client
- Verify time entries exist for the client's projects
Admin Cannot Enable Portal
- Ensure a client is selected when enabling portal access
- Verify the client exists and is active
- Check for database errors in server logs
Future Enhancements
Potential future improvements:
- Email notifications for new invoices
- PDF invoice downloads
- Export time entries to CSV
- Project status updates
- Comments/notes on projects
- Custom branding per client