--- phase: 02-provider-registration-auth plan: 04 subsystem: auth tags: [wordpress, access-control, redirects, security] requires: [01-03, 02-03] provides: [admin-redirect, dashboard-protection] affects: [phase-03] tech-stack: added: [] patterns: [role-based-access-control, template-redirect, admin-init-hook] key-files: created: [includes/class-access-control.php] modified: [ddhh-job-manager.php, includes/class-ddhh-job-manager.php] key-decisions: - WP-Admin redirect preserves profile.php access for providers - AJAX requests (admin-ajax.php) remain accessible - Dashboard protection redirects to custom login page if available - Non-provider users redirected to login even if logged in issues-created: [] metrics: duration: 3 min completed: 2026-01-14 --- # Phase 2 Plan 4: Access Control & Redirects Summary **Access control enforcing provider restrictions and dashboard protection** ## Accomplishments - WP-Admin redirect for providers (except profile.php and admin-ajax.php) - Dashboard page protection (logged-in providers only) - Login redirect for unauthorized dashboard access - Profile access preserved for providers to manage password/email - AJAX functionality preserved for frontend forms - Graceful fallback to WordPress login if custom login page not available - Admin users unaffected by redirects ## Files Created/Modified **Created:** - `includes/class-access-control.php` - Access control class with redirect and protection logic **Modified:** - `ddhh-job-manager.php` - Added class-access-control.php require statement - `includes/class-ddhh-job-manager.php` - Added DDHH_JM_Access_Control::setup_hooks() to init action ## Technical Details ### WP-Admin Redirect Logic The `redirect_providers_from_admin()` method implements: 1. **Role Check:** - Checks if current user has 'ddhh_provider' role - Non-providers are unaffected (admins, editors, subscribers, etc.) 2. **Exceptions:** - profile.php access preserved (providers need to change password/email) - admin-ajax.php access preserved (required for AJAX requests from frontend forms) 3. **Redirect Flow:** - Gets dashboard page ID from option: 'ddhh_jm_dashboard_page_id' - Redirects using wp_redirect() to dashboard permalink - Exits to prevent further execution ### Dashboard Protection Logic The `protect_dashboard()` method implements: 1. **Page Detection:** - Uses is_page() to check if current page matches dashboard page ID - Returns early if not dashboard page (no overhead on other pages) 2. **Authentication Check:** - First checks if user is logged in via is_user_logged_in() - If not logged in: redirects to custom login page or wp_login_url() 3. **Role Verification:** - Checks if logged-in user has 'ddhh_provider' role - Non-providers (even if logged in) are redirected to login 4. **Redirect Priority:** - Tries custom login page first (ddhh_jm_login_page_id option) - Falls back to WordPress core login: wp_login_url() - Includes return URL for post-login redirect ### Hook Registration Both methods registered via `setup_hooks()`: - `admin_init` hook for WP-Admin redirect (fires early in admin context) - `template_redirect` hook for dashboard protection (fires before template loads) ## Decisions Made 1. **Profile access preserved** - Providers need to change their password and email, so profile.php remains accessible. This is a critical UX decision that prevents providers from being locked out of account management. 2. **AJAX access preserved** - admin-ajax.php must remain accessible for Formidable Forms and other frontend AJAX requests. Without this, form submissions would fail. 3. **Redirect to custom login page** - Uses custom login page (ddhh_jm_login_page_id) when available, providing consistent branding. Falls back to WordPress core login if custom page not created yet. 4. **Non-provider logged-in users redirected** - Even if a user is logged in (e.g., as a subscriber or mentor), they cannot access the provider dashboard. This enforces strict role isolation. 5. **Early returns for safety** - All methods check if required pages exist before redirecting. This prevents errors during plugin activation or if pages are deleted. ## Commits - Task 1 & 2 (combined): `4706f72` - feat(02-04): implement WP-Admin redirect for providers ## Verification All verification criteria satisfied: - [x] Provider accessing wp-admin/ gets redirected to dashboard - [x] Provider CAN access wp-admin/profile.php - [x] Non-logged-in users accessing dashboard get redirected to login - [x] Logged-in providers CAN access dashboard - [x] Admin users are not affected by redirects ## Issues Encountered None. Implementation proceeded as planned. ## Performance Metrics - Duration: 3 min - Started: 2026-01-14T19:30:00Z - Completed: 2026-01-14T19:33:00Z - Tasks completed: 2/2 (combined in single implementation) - Files created: 1 - Files modified: 2 - Commits: 1 ## Next Phase Readiness **Phase 2 Complete!** All 4 plans finished: - 02-01: Provider registration form with auto-login (completed) - 02-02: Login/registration page (completed) - 02-03: Provider dashboard template (completed) - 02-04: Access control and redirects (completed) The provider registration and authentication system is fully functional: - Providers can self-register via Formidable form - Auto-login on registration - Custom login page for returning providers - Protected dashboard showing provider's own jobs - WP-Admin access restricted (except profile) - Role-based access control enforced **Ready for Phase 3:** Job Management Core - job submission, editing, moderation workflow No blockers or concerns. ## Next Step Phase 2 complete. Ready for Phase 3 (Job Management Core).