diff --git a/docs/installation/requirements.md b/docs/installation/requirements.md index 132ac31ed31..7297aee90b2 100644 --- a/docs/installation/requirements.md +++ b/docs/installation/requirements.md @@ -6,7 +6,9 @@ Invoke runs on Windows 10+, macOS 14+ and Linux (Ubuntu 20.04+ is well-tested). Hardware requirements vary significantly depending on model and image output size. -The requirements below are rough guidelines for best performance. GPUs with less VRAM typically still work, if a bit slower. Follow the [Low-VRAM mode guide](./features/low-vram.md) to optimize performance. +The requirements below are rough guidelines for best performance. GPUs +with less VRAM typically still work, if a bit slower. Follow the +[Low-VRAM mode guide](../features/low-vram.md) to optimize performance. - All Apple Silicon (M1, M2, etc) Macs work, but 16GB+ memory is recommended. - AMD GPUs are supported on Linux only. The VRAM requirements are the same as Nvidia GPUs. diff --git a/docs/multiuser/EXECUTIVE_SUMMARY.md b/docs/multiuser/EXECUTIVE_SUMMARY.md deleted file mode 100644 index 2ef67d60770..00000000000 --- a/docs/multiuser/EXECUTIVE_SUMMARY.md +++ /dev/null @@ -1,454 +0,0 @@ -# Multi-User Support - Executive Summary - -## 🎯 Overview - -This PR provides a **comprehensive specification and implementation plan** for adding multi-user support to InvokeAI. The feature enables multiple isolated users to share a single InvokeAI instance while maintaining security, privacy, and administrative control. - -## πŸ“¦ What's Included - -This PR includes **THREE detailed planning documents** totaling over **65,000 words**: - -1. **multiuser_specification.md** (27KB) - Complete technical specification -2. **multiuser_implementation_plan.md** (28KB) - Step-by-step implementation guide -3. **MULTIUSER_README.md** (10KB) - Overview and quick reference - -**Note**: This PR contains **documentation only** - no code implementation yet. This is intentional to allow for thorough review and feedback before development begins. - -## 🎨 High-Level Architecture - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ INVOKEAI FRONTEND β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ Login Page β”‚ β”‚ User Menu β”‚ β”‚ Admin Panel β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ β”‚ β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ Auth State Mgmt β”‚ β”‚ -β”‚ β”‚ (Redux/JWT) β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ API Gateway β”‚ - β”‚ (Auth Middleware) β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ β”‚ β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Auth Service β”‚ β”‚ User β”‚ β”‚ Board/Image β”‚ - β”‚ - Password β”‚ β”‚ Service β”‚ β”‚ Services β”‚ - β”‚ - JWT Tokens β”‚ β”‚ - CRUD β”‚ β”‚ (Filtered by β”‚ - β”‚ - Sessions β”‚ β”‚ - Auth β”‚ β”‚ user_id) β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ β”‚ β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ SQLite Database β”‚ - β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ - β”‚ β”‚ users β”‚ β”‚ - β”‚ β”‚ user_sessions β”‚ β”‚ - β”‚ β”‚ boards (+ uid) β”‚ β”‚ - β”‚ β”‚ images (+ uid) β”‚ β”‚ - β”‚ β”‚ workflows β”‚ β”‚ - β”‚ β”‚ shared_boards β”‚ β”‚ - β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -## πŸ”‘ Key Features - -### For Regular Users -- βœ… Secure login with email/password -- βœ… Personal isolated workspace (boards, images, workflows) -- βœ… Own generation queue -- βœ… Custom UI preferences -- βœ… Access to shared collaborative boards - -### For Administrators -- βœ… All regular user capabilities -- βœ… Full model management -- βœ… User account management (create, edit, delete) -- βœ… View and manage all user queues -- βœ… Create shared boards with permissions -- βœ… System configuration access - -## πŸ›‘οΈ Security Design - -### Authentication -``` -Password Storage: bcrypt/Argon2 hashing -Session Management: JWT tokens (24h default, 7 days with "remember me") -API Protection: Bearer token authentication on all endpoints -Rate Limiting: Login attempt throttling -``` - -### Authorization -``` -Role-Based: Admin vs Regular User -Data Isolation: Database-level user_id filtering -Permission Checks: Middleware validation on every request -Shared Resources: Granular permissions (read/write/admin) -``` - -### Best Practices -- βœ… No plain-text passwords -- βœ… Parameterized SQL queries (injection prevention) -- βœ… Input validation and sanitization -- βœ… CSRF protection -- βœ… Secure session management -- βœ… HTTPS enforcement (recommended) - -## πŸ“Š Database Schema Changes - -### New Tables (4 total) -```sql -users -- User accounts -user_sessions -- Active sessions -user_invitations -- One-time setup links -shared_boards -- Board sharing permissions -``` - -### Modified Tables (5 total) -```sql -boards -- Add user_id, is_shared -images -- Add user_id -workflows -- Add user_id, is_public -session_queue -- Add user_id -style_presets -- Add user_id, is_public -``` - -**Migration Strategy**: -- New migration file: `migration_25.py` -- Creates 'system' user for backward compatibility -- Assigns existing data to 'system' or new admin -- Rollback support for safety - -## 🎯 API Changes - -### New Endpoints (15+) -``` -POST /api/v1/auth/setup -- Initial admin setup -POST /api/v1/auth/login -- User login -POST /api/v1/auth/logout -- User logout -GET /api/v1/auth/me -- Current user info -POST /api/v1/auth/change-password -- Password change - -GET /api/v1/users -- List users (admin) -POST /api/v1/users -- Create user (admin) -GET /api/v1/users/{id} -- Get user (admin) -PATCH /api/v1/users/{id} -- Update user (admin) -DELETE /api/v1/users/{id} -- Delete user (admin) -POST /api/v1/users/{id}/reset-password -- Reset password (admin) - -POST /api/v1/boards/{id}/share -- Share board -GET /api/v1/boards/{id}/shares -- List shares -DELETE /api/v1/boards/{id}/share/{uid} -- Remove share -``` - -### Modified Endpoints (13+ existing) -All existing endpoints get: -- Authentication requirement (except setup/login) -- User context filtering -- Permission enforcement - -Example: -```python -@boards_router.get("/") -async def list_boards( - current_user: CurrentUser, # NEW: Auth dependency - # ... other params ... -): - return boards_service.get_many( - user_id=current_user.user_id, # NEW: Filter by user - # ... other params ... - ) -``` - -## πŸ’» Frontend Changes - -### New Components (8+) -``` -LoginPage -- Email/password form -AdministratorSetup -- First-time setup modal -ProtectedRoute -- Route authentication wrapper -UserMenu -- Profile and logout -UserManagementPage -- Admin user CRUD (admin only) -UserProfilePage -- User settings -BoardSharingDialog -- Share board with users -``` - -### Modified Components (10+) -``` -App -- Add auth check and routing -Navigation -- Add user menu -ModelManagerTab -- Hide for non-admin -QueuePanel -- Filter by current user -BoardsPanel -- Show personal + shared boards -``` - -### State Management -```typescript -// New Redux slices -authSlice -- user, token, isAuthenticated -usersSlice -- user list for admin -sharingSlice -- board sharing state - -// Updated slices -boardsSlice -- add ownership, shared boards -queueSlice -- add user filtering -workflowsSlice -- add public/private -``` - -## πŸ“… Implementation Timeline - -``` -PHASE 1: Database Schema [Weeks 1-2] βœ… SPECIFICATION COMPLETE - └─ Migration file, schema changes, tests - -PHASE 2: Authentication Service [Weeks 3-4] - └─ Password utils, JWT, user service - -PHASE 3: Backend API [Weeks 5-6] - └─ Auth endpoints, middleware, update routers - -PHASE 4: Multi-tenancy [Weeks 7-9] - └─ Update all services for user isolation - -PHASE 5: Frontend Auth [Weeks 10-11] - └─ Login page, auth state, route protection - -PHASE 6: Frontend UI [Week 12] - └─ User menu, admin pages, UI updates - -PHASE 7: Testing & Documentation [Week 13] - └─ Comprehensive tests, docs, migration guide - -PHASE 8: Security Review & Beta [Week 14+] - └─ Security audit, beta testing, release -``` - -**Total Estimated Time**: 14 weeks - -## βœ… Testing Strategy - -### Unit Tests (Target: >90% coverage) -- Password hashing and validation -- Token generation and verification -- User service CRUD operations -- Authorization logic -- Data isolation queries - -### Integration Tests -- Complete authentication flows -- User registration and invitation -- Multi-user data isolation -- Shared board access -- Admin operations - -### Security Tests -- SQL injection prevention -- XSS vulnerability testing -- CSRF protection -- Authorization bypass attempts -- Session hijacking prevention -- Brute force protection - -### Performance Tests -- Authentication overhead (<10% target) -- Query performance with user filters -- Concurrent user sessions -- Database scalability - -## πŸ”„ Migration Path - -### For New Installations -``` -1. First launch shows setup dialog -2. Create administrator account -3. Proceed to login screen -4. Start using InvokeAI -``` - -### For Existing Installations -``` -1. Update InvokeAI -2. Database auto-migrates -3. Setup dialog appears for admin -4. Existing data assigned to admin user -5. Continue using InvokeAI -``` - -### Backward Compatibility -```yaml -# invokeai.yaml -auth_enabled: false # Disable multi-user for legacy mode -``` - -## πŸ“š Documentation Plan - -### User Documentation -- Getting Started with Multi-User InvokeAI -- Login and Account Management -- Understanding Roles and Permissions -- Using Shared Boards -- Troubleshooting Authentication - -### Administrator Documentation -- Initial Setup Guide -- User Management Guide -- Creating and Managing Shared Boards -- Email Configuration (optional) -- Security Best Practices -- Backup and Restore - -### Developer Documentation -- Authentication Architecture -- Adding Auth to New Endpoints -- Database Schema Reference -- Testing Multi-User Features -- Migration Guide - -## 🎨 Design Decisions & Rationale - -### Why JWT Tokens? -- **Stateless**: No server-side session storage needed -- **Scalable**: Works with multiple server instances -- **Standard**: Well-understood, mature libraries -- **Flexible**: Can add claims as needed - -### Why SQLite? -- **Consistency**: Already used by InvokeAI -- **Simple**: No external dependencies -- **Sufficient**: Handles multi-user workload fine -- **Portable**: Easy backup and migration - -### Why bcrypt? -- **Battle-tested**: Industry standard for passwords -- **Adaptive**: Adjustable work factor for future-proofing -- **Secure**: Resistant to rainbow tables and brute force -- **Compatible**: Works across all platforms - -### Why Two Roles Initially? -- **Simplicity**: Easy to understand and implement -- **Sufficient**: Covers 95% of use cases -- **Extensible**: Can add more roles later -- **Clean**: Reduces complexity in initial release - -## ⚠️ Risks and Mitigation - -| Risk | Impact | Probability | Mitigation | -|------|--------|-------------|------------| -| Database migration failures | High | Low | Extensive testing, backup requirements, rollback procedures | -| Performance degradation | Medium | Low | Index optimization, query profiling, benchmarking | -| Security vulnerabilities | High | Low | Security review, penetration testing, CodeQL scans | -| User adoption friction | Medium | Medium | Clear docs, smooth migration, optional auth | -| Implementation complexity | Medium | Medium | Phased approach, regular testing, clear plan | - -## πŸ“ˆ Success Metrics - -### Functional -- [ ] All acceptance criteria met -- [ ] All tests passing (unit, integration, security) -- [ ] Zero unauthorized data access -- [ ] Migration success rate >99% - -### Performance -- [ ] Authentication overhead <10% -- [ ] Login time <2 seconds -- [ ] API response time maintained -- [ ] Database query performance acceptable - -### Security -- [ ] Zero critical vulnerabilities -- [ ] CodeQL scan passes -- [ ] Penetration testing completed (if done) -- [ ] Security best practices followed - -### Usability -- [ ] Setup time <2 minutes -- [ ] Clear error messages -- [ ] Positive user feedback -- [ ] Documentation complete - -## πŸš€ Next Steps - -### Immediate Actions -1. **Review** these specification documents -2. **Discuss** design decisions and approach -3. **Provide feedback** on any concerns -4. **Approve** to begin implementation - -### πŸŽͺ Review Decisions - -The following design decisions have been approved: - -1. **OAuth2 Priority**: OAuth2/OpenID Connect will be a **future enhancement** to keep initial scope manageable. - -2. **Email Requirement**: Email/SMTP configuration is **optional**. Many administrators will not have ready access to an outgoing SMTP server. System will provide fallback (showing setup links in admin UI). - -3. **Data Migration**: During migration, administrator can **specify an arbitrary user account** to hold legacy data (can be admin account or separate user). - -4. **API Compatibility**: Authentication **required on all APIs**, but not required if multi-user support is disabled (`auth_enabled: false`). - -5. **Session Storage**: **JWT tokens with optional server-side session tracking**. - -6. **Audit Logging**: **Log authentication events and admin actions** for accountability and security monitoring. - -### After Approval - -1. Begin Phase 2: Database Schema Design -2. Create migration_25.py -3. Implement and test schema changes -4. Report progress and continue to Phase 3 - -## πŸ’‘ Future Enhancements (Post-Initial Release) - -### Phase 2 Features -- **OAuth2/OpenID Connect integration** (deferred from initial release) -- Two-factor authentication (2FA) -- API keys for programmatic access -- Enhanced team/group management -- Advanced permission system - -### Phase 3 Features -- SSO integration (SAML, LDAP) -- User quotas and resource limits -- Usage tracking and analytics -- Real-time collaboration -- Template library with permissions -- Model access controls per user - -## πŸ“ž Contact & Support - -- **Questions**: GitHub Discussions -- **Issues**: GitHub Issues (use "multi-user" label) -- **Security**: security@invoke.ai (private disclosure) -- **Community**: Discord #dev-chat - -## πŸ“„ Document Links - -- πŸ“˜ [Complete Specification](./multiuser_specification.md) - 27KB, 20+ pages -- πŸ“— [Implementation Plan](./multiuser_implementation_plan.md) - 28KB, 28+ pages -- πŸ“™ [Quick Reference](./MULTIUSER_README.md) - 10KB overview - ---- - -## Summary for Reviewers - -This PR provides **complete planning documents** for multi-user support in InvokeAI. The design is: - -βœ… **Comprehensive** - Covers all aspects from database to UI -βœ… **Secure** - Following industry best practices -βœ… **Practical** - Based on proven patterns and libraries -βœ… **Incremental** - Phased implementation reduces risk -βœ… **Tested** - Detailed testing strategy included -βœ… **Documented** - Extensive documentation plan - -**This is a specification PR only** - no code changes yet. This allows thorough review before beginning the estimated 14-week implementation. - -**Ready for Review** ✨ diff --git a/docs/multiuser/README.md b/docs/multiuser/README.md deleted file mode 100644 index 25d8cc4f886..00000000000 --- a/docs/multiuser/README.md +++ /dev/null @@ -1,343 +0,0 @@ -# Multi-User Support for InvokeAI - -This directory contains the detailed specification and implementation plan for adding multi-user support to InvokeAI. - -## πŸ“„ Documents - -### 1. [Detailed Specification](./multiuser_specification.md) -Comprehensive technical specification covering: -- User roles and permissions -- Authentication system design -- Database schema changes -- API endpoint specifications -- Frontend component requirements -- Security considerations -- Email integration (optional) -- Testing requirements -- Documentation requirements -- Future enhancements -- Risk assessment -- Success criteria - -### 2. [Implementation Plan](./multiuser_implementation_plan.md) -Step-by-step development guide covering: -- Phase-by-phase implementation timeline -- Code examples for each component -- File-by-file changes required -- Testing strategy -- Migration approach -- Rollout strategy -- Maintenance plan -- Quick reference guide - -## 🎯 Quick Overview - -### What This Feature Adds - -**For Regular Users:** -- Secure login with email/password -- Personal image boards and workflows -- Isolated generation queue -- Custom UI preferences -- Access to shared collaborative boards - -**For Administrators:** -- Full system management capabilities -- User account management -- Model management (add/remove/configure) -- Create and manage shared boards -- View and manage all user queues -- System configuration access - -### Key Features - -βœ… **Secure Authentication** -- Password hashing with bcrypt/Argon2 -- JWT token-based sessions -- Configurable session timeouts -- Rate limiting on login attempts - -βœ… **Data Isolation** -- Each user has separate boards, images, and workflows -- Database-level enforcement of data ownership -- Shared boards with granular permissions - -βœ… **Role-Based Access Control** -- Administrator role with full access -- Regular user role with restricted access -- Future support for custom roles - -βœ… **Backward Compatibility** -- Optional authentication (can be disabled) -- Smooth migration from single-user installations -- Minimal impact on existing deployments - -## πŸ“Š Implementation Status - -### Phase Status -- [x] Phase 1: Specification & Documentation βœ… -- [ ] Phase 2: Database Schema Design -- [ ] Phase 3: Backend - Authentication Service -- [ ] Phase 4: Backend - Multi-tenancy Updates -- [ ] Phase 5: Backend - API Updates -- [ ] Phase 6: Frontend - Authentication UI -- [ ] Phase 7: Frontend - UI Updates -- [ ] Phase 8: Testing & Documentation -- [ ] Phase 9: Security Review - -**Current Status**: Specification Complete - Ready for Review - -## πŸš€ Getting Started (For Developers) - -### Prerequisites -```bash -# Install dependencies -pip install -e ".[dev]" - -# Additional dependencies for multi-user support -pip install passlib[bcrypt] python-jose[cryptography] email-validator -``` - -### Development Workflow - -1. **Review Specification** - - Read [multiuser_specification.md](./multiuser_specification.md) - - Understand the requirements and architecture - -2. **Follow Implementation Plan** - - Reference [multiuser_implementation_plan.md](./multiuser_implementation_plan.md) - - Implement phase by phase - - Test each phase thoroughly - -3. **Testing** - ```bash - # Run all tests - pytest tests/ -v - - # Run with coverage - pytest tests/ --cov=invokeai.app --cov-report=html - ``` - -4. **Local Development** - ```bash - # Start with in-memory database for testing - python -m invokeai.app.run_app --use_memory_db --dev_reload - ``` - -## πŸ“‹ Technical Architecture - -### Backend Components - -``` -invokeai/app/ -β”œβ”€β”€ services/ -β”‚ β”œβ”€β”€ auth/ # Authentication utilities -β”‚ β”‚ β”œβ”€β”€ password_utils.py # Password hashing -β”‚ β”‚ └── token_service.py # JWT token management -β”‚ β”œβ”€β”€ users/ # User management service -β”‚ β”‚ β”œβ”€β”€ users_base.py # Abstract interface -β”‚ β”‚ β”œβ”€β”€ users_default.py # SQLite implementation -β”‚ β”‚ └── users_common.py # DTOs and types -β”‚ └── shared/ -β”‚ └── sqlite_migrator/ -β”‚ └── migrations/ -β”‚ └── migration_25.py # Multi-user schema -β”œβ”€β”€ api/ -β”‚ β”œβ”€β”€ auth_dependencies.py # FastAPI auth dependencies -β”‚ └── routers/ -β”‚ └── auth.py # Authentication endpoints -``` - -### Frontend Components - -``` -frontend/web/src/ -β”œβ”€β”€ features/ -β”‚ β”œβ”€β”€ auth/ -β”‚ β”‚ β”œβ”€β”€ store/ -β”‚ β”‚ β”‚ └── authSlice.ts # Auth state management -β”‚ β”‚ β”œβ”€β”€ components/ -β”‚ β”‚ β”‚ β”œβ”€β”€ LoginPage.tsx # Login UI -β”‚ β”‚ β”‚ β”œβ”€β”€ ProtectedRoute.tsx # Route protection -β”‚ β”‚ β”‚ └── UserMenu.tsx # User menu component -β”‚ β”‚ └── api/ -β”‚ β”‚ └── authApi.ts # Auth API endpoints -``` - -### Database Schema - -``` -users # User accounts -β”œβ”€β”€ user_id (PK) -β”œβ”€β”€ email (UNIQUE) -β”œβ”€β”€ password_hash -β”œβ”€β”€ is_admin -└── is_active - -user_sessions # Active sessions -β”œβ”€β”€ session_id (PK) -β”œβ”€β”€ user_id (FK) -β”œβ”€β”€ token_hash -└── expires_at - -boards # Modified for multi-user -β”œβ”€β”€ board_id (PK) -β”œβ”€β”€ user_id (FK) # NEW: Owner -β”œβ”€β”€ is_shared # NEW: Sharing flag -└── ... - -shared_boards # NEW: Board sharing -β”œβ”€β”€ board_id (FK) -β”œβ”€β”€ user_id (FK) -└── permission -``` - -## πŸ”’ Security Considerations - -### Critical Security Features - -1. **Password Security** - - Bcrypt hashing with appropriate work factor - - No plain-text password storage - - Password strength validation - -2. **Session Management** - - Secure JWT token generation - - Token expiration and refresh - - Server-side session tracking (optional) - -3. **Authorization** - - Role-based access control - - Database-level data isolation - - API endpoint protection - -4. **Input Validation** - - Email validation - - SQL injection prevention - - XSS prevention - -### Security Testing Requirements - -- [ ] SQL injection testing -- [ ] XSS vulnerability testing -- [ ] CSRF protection verification -- [ ] Authorization bypass testing -- [ ] Session hijacking prevention -- [ ] CodeQL security scan -- [ ] Penetration testing (recommended) - -## πŸ“– Documentation - -### For Users -- Getting Started Guide (to be created) -- Login and Account Management (to be created) -- Understanding Roles and Permissions (to be created) -- Using Shared Boards (to be created) - -### For Administrators -- Administrator Setup Guide (to be created) -- User Management Guide (to be created) -- Security Best Practices (to be created) -- Backup and Recovery (to be created) - -### For Developers -- [Detailed Specification](./multiuser_specification.md) βœ… -- [Implementation Plan](./multiuser_implementation_plan.md) βœ… -- API Documentation (to be generated) -- Testing Guide (to be created) - -## 🎯 Timeline - -### Estimated Timeline: 14 weeks - -- **Weeks 1-2**: Database schema and migration -- **Weeks 3-4**: Backend authentication service -- **Weeks 5-6**: Frontend authentication UI -- **Weeks 7-9**: Multi-tenancy updates -- **Weeks 10-11**: Admin interface and features -- **Weeks 12-13**: Testing and polish -- **Week 14+**: Beta testing and release - -## 🀝 Contributing - -### How to Contribute - -1. **Review Phase** - - Review the specification document - - Provide feedback on the design - - Suggest improvements or alternatives - -2. **Implementation Phase** - - Pick a phase from the implementation plan - - Follow the coding standards - - Write tests for your code - - Submit PR with documentation - -3. **Testing Phase** - - Test beta releases - - Report bugs and issues - - Suggest UX improvements - -### Code Review Checklist - -- [ ] Follows implementation plan -- [ ] Includes unit tests -- [ ] Includes integration tests (if applicable) -- [ ] Updates documentation -- [ ] No security vulnerabilities -- [ ] Backward compatible (or migration provided) -- [ ] Performance acceptable -- [ ] Code follows project style guide - -## ❓ FAQ - -### Q: Will this break my existing installation? -A: No. The feature includes a migration path and can be disabled for single-user mode. - -### Q: Is OAuth2/OpenID Connect supported? -A: Not in the initial release, but it's planned for a future enhancement. - -### Q: Can I run this in production? -A: After the initial release and security review, yes. Follow the security best practices in the documentation. - -### Q: How do I reset the administrator password? -A: Edit the config file to remove the admin credentials, then restart the application to trigger the setup flow again. - -### Q: Can users collaborate in real-time? -A: Not in the initial release. Shared boards allow asynchronous collaboration. - -### Q: Will this affect performance? -A: Minimal impact expected (<10% overhead). Performance testing will verify this. - -## πŸ“ž Support - -### Getting Help - -- **Development Questions**: GitHub Discussions -- **Bug Reports**: GitHub Issues (use "multi-user" label) -- **Security Issues**: security@invoke.ai (do not file public issues) -- **General Support**: Discord #support channel - -### Reporting Issues - -When reporting issues, include: -- InvokeAI version -- Operating system -- Authentication enabled/disabled -- Steps to reproduce -- Expected vs actual behavior -- Relevant logs (remove sensitive data) - -## πŸ“œ License - -This feature is part of InvokeAI and is licensed under the same terms as the main project. - -## πŸ™ Acknowledgments - -This feature addresses requirements from the community and replaces functionality that was previously available in the enterprise edition. Thanks to all community members who provided feedback and requirements. - ---- - -**Status**: Specification Complete - Awaiting Review -**Last Updated**: January 4, 2026 -**Next Steps**: Review and feedback on specification, begin Phase 2 implementation diff --git a/docs/multiuser/add_user_guide.md b/docs/multiuser/add_user_guide.md deleted file mode 100644 index 194693b7917..00000000000 --- a/docs/multiuser/add_user_guide.md +++ /dev/null @@ -1,108 +0,0 @@ -# User Management Utility - -This directory contains the `add_user.py` script for managing InvokeAI users during development and testing. - -## Quick Start - -### Add a Regular User - -```bash -python scripts/add_user.py --email testuser@test.local --password TestPass123 --name "Test User" -``` - -### Add an Admin User - -```bash -python scripts/add_user.py --email admin@test.local --password AdminPass123 --name "Admin User" --admin -``` - -### Interactive Mode - -Run without arguments to be prompted for details: - -```bash -python scripts/add_user.py -``` - -## Password Requirements - -Passwords must meet the following requirements: -- At least 8 characters long -- Contains at least one uppercase letter -- Contains at least one lowercase letter -- Contains at least one number - -## Examples - -```bash -# Add a regular user with display name -python scripts/add_user.py \ - --email alice@test.local \ - --password SecurePass123 \ - --name "Alice Johnson" - -# Add an administrator -python scripts/add_user.py \ - --email admin@invokeai.local \ - --password AdminSecure456 \ - --name "System Administrator" \ - --admin - -# Interactive mode (prompts for all details) -python scripts/add_user.py -``` - -## Testing Email Addresses - -The script supports testing domains like `.local`, `.test`, and `.localhost` which are useful for development: - -- `user@test.local` -- `admin@localhost` -- `testuser@invokeai.test` - -## Troubleshooting - -### "User with email already exists" - -The email address is already in the database. Use a different email or remove the existing user first. - -### "Password must be at least 8 characters long" - -The password doesn't meet the minimum length requirement. Use a longer password. - -### "Password must contain uppercase, lowercase, and numbers" - -The password doesn't meet complexity requirements. Include at least: -- One uppercase letter (A-Z) -- One lowercase letter (a-z) -- One digit (0-9) - -## Database Location - -The script uses the database path configured in your InvokeAI configuration. To find your database location: - -```bash -python -c "from invokeai.app.services.config import get_config; print(get_config().db_path)" -``` - -## For Developers - -The script can also be imported and used programmatically: - -```python -from scripts.add_user import add_user_cli - -# Add a user -success = add_user_cli( - email="developer@test.local", - password="DevPass123", - display_name="Developer User", - is_admin=False -) -``` - -## See Also - -- Phase 6 Testing Guide: `docs/multiuser/phase6_testing.md` -- User Service Implementation: `invokeai/app/services/users/` -- Multiuser Specification: `docs/multiuser/specification.md` diff --git a/docs/multiuser/admin_guide.md b/docs/multiuser/admin_guide.md new file mode 100644 index 00000000000..0406dbe8e6c --- /dev/null +++ b/docs/multiuser/admin_guide.md @@ -0,0 +1,910 @@ +# InvokeAI Multi-User Administrator Guide + +## Overview + +This guide is for administrators managing a multi-user InvokeAI installation. It covers initial setup, user management, security best practices, and troubleshooting. + +## Prerequisites + +Before enabling multi-user support, ensure you have: + +- InvokeAI installed and running +- Access to the server filesystem (for initial setup) +- Understanding of your deployment environment +- Backup of your existing data (recommended) + +## Initial Setup + +### First Administrator Account + +When InvokeAI starts for the first time in multi-user mode, you'll see the **Administrator Setup** dialog. + +**Setup Steps:** + +1. **Email Address**: Enter a valid email address (this becomes your username) + - Example: `admin@example.com` or `admin@localhost` for testing + - Must be a valid email format + - Cannot be changed later without database access + +2. **Display Name**: Enter a friendly name + - Example: "System Administrator" or your real name + - Can be changed later in your profile + - Visible to other users in shared contexts + +3. **Password**: Create a strong administrator password + - **Minimum requirements:** + - At least 8 characters long + - Contains uppercase letters (A-Z) + - Contains lowercase letters (a-z) + - Contains numbers (0-9) + - **Recommended:** + - Use 12+ characters + - Include special characters (!@#$%^&*) + - Use a password manager to generate and store + - Don't reuse passwords from other services + +4. **Confirm Password**: Re-enter the password + +5. Click **Create Administrator Account** + +!!! warning "Important" + Store these credentials securely! The first administrator account has full system access. + +### Configuration + +InvokeAI can run in single-user or multi-user mode, controlled by the `multiuser` configuration option in `invokeai.yaml`: + +```yaml +# Enable/disable multi-user mode +multiuser: true # Enable multi-user mode (requires authentication) +# multiuser: false # Single-user mode (no authentication required) +# If the multiuser option is absent, single-user mode is used + +# Database configuration +use_memory_db: false # Use persistent database +db_path: databases/invokeai.db # Database location + +# Session configuration (multi-user mode only) +jwt_secret_key: "your-secret-key-here" # Auto-generated if not specified +jwt_token_expiry_hours: 24 # Default session timeout +jwt_remember_me_days: 7 # "Remember me" duration +``` + +**Single-User Mode** (`multiuser: false` or option absent): +- No authentication required +- All functionality enabled by default +- All boards and images visible in unified view +- Ideal for personal use or trusted environments + +**Multi-User Mode** (`multiuser: true`): +- Authentication required for access +- User isolation for boards, images, and workflows +- Role-based permissions enforced +- Ideal for shared servers or team environments + +!!! warning "Mode Switching Behavior" + **Switching to Single-User Mode:** If boards or images were created in multi-user mode, they will all be combined into a single unified view when switching to single-user mode. + + **Switching to Multi-User Mode:** Legacy boards and images created under single-user mode will be owned by an internal user named "system." Only the Administrator will have access to these legacy assets. A utility to migrate these legacy assets to another user will be part of a future release. + +### Migration from Single-User + +When upgrading from a single-user installation or switching modes: + +1. **Automatic Migration**: The database will automatically migrate to multi-user schema when multi-user mode is first enabled +2. **Legacy Data Ownership**: Existing data (boards, images, workflows) created in single-user mode is assigned to an internal user named "system" +3. **Administrator Access**: Only administrators will have access to legacy "system"-owned assets when in multi-user mode +4. **No Data Loss**: All existing content is preserved + +**Migration Process:** + +```bash +# Backup your database first +cp databases/invokeai.db databases/invokeai.db.backup + +# Enable multi-user mode in invokeai.yaml +# multiuser: true + +# Start InvokeAI (migration happens automatically) +invokeai-web + +# Complete the administrator setup dialog +# Legacy data will be owned by "system" user +``` + +!!! note "Legacy Asset Migration" + A utility to migrate legacy "system"-owned assets to specific user accounts will be available in a future release. Until then, administrators can access and manage all legacy content. + +## User Management + +### Creating Users + +**Via Web Interface (Coming Soon):** + +!!! info "Web UI for User Management" + A web-based user interface that allows administrators to manage users is coming in a future release. Until then, use the command-line scripts described below. + +**Via Command Line Scripts:** + +InvokeAI provides several command-line scripts in the `scripts/` directory for user management: + +**useradd.py** - Add a new user: + +```bash +# Interactive mode (prompts for details) +python scripts/useradd.py + +# Create a regular user +python scripts/useradd.py \ + --email user@example.com \ + --password TempPass123 \ + --name "User Name" + +# Create an administrator +python scripts/useradd.py \ + --email admin@example.com \ + --password AdminPass123 \ + --name "Admin Name" \ + --admin +``` + +**userlist.py** - List all users: + +```bash +# List all users +python scripts/userlist.py + +# Show detailed information +python scripts/userlist.py --verbose +``` + +**usermod.py** - Modify an existing user: + +```bash +# Change display name +python scripts/usermod.py --email user@example.com --name "New Name" + +# Promote to administrator +python scripts/usermod.py --email user@example.com --admin + +# Demote from administrator +python scripts/usermod.py --email user@example.com --no-admin + +# Deactivate account +python scripts/usermod.py --email user@example.com --deactivate + +# Reactivate account +python scripts/usermod.py --email user@example.com --activate + +# Change password +python scripts/usermod.py --email user@example.com --password NewPassword123 +``` + +**userdel.py** - Delete a user: + +```bash +# Delete a user (prompts for confirmation) +python scripts/userdel.py --email user@example.com + +# Delete without confirmation +python scripts/userdel.py --email user@example.com --force +``` + +!!! tip "Script Usage" + Run any script with `--help` to see all available options: + ```bash + python scripts/useradd.py --help + ``` + +!!! warning "Command Line Management" + - These scripts directly modify the database + - Always backup your database before making changes + - Changes take effect immediately (users may need to log in again) + - Deleting a user permanently removes all their content + +### Editing Users + +**Via Command Line:** + +Use `usermod.py` as described above to modify user properties. + +!!! warning "Last Administrator" + You cannot remove admin privileges from the last remaining administrator account. + +### Resetting User Passwords + +**Via Web Interface (Coming Soon):** + +Web-based password reset functionality for administrators is coming in a future release. + +**Via Command Line:** + +```bash +# Reset a user's password +python scripts/usermod.py --email user@example.com --password NewTempPassword123 +``` + +**Security Note:** Never send passwords via email or unsecured channels. Use secure communication methods. + +### Deactivating Users + +**Via Command Line:** + +```bash +# Deactivate a user account +python scripts/usermod.py --email user@example.com --deactivate + +# Reactivate a user account +python scripts/usermod.py --email user@example.com --activate +``` + +**Effects:** + +- User cannot log in when deactivated +- Existing sessions are immediately invalidated +- User's data is preserved +- Can be reactivated at any time + +### Deleting Users + +**Via Command Line:** + +```bash +# Delete a user (prompts for confirmation) +python scripts/userdel.py --email user@example.com + +# Delete without confirmation prompt +python scripts/userdel.py --email user@example.com --force +``` + +**Important:** + +- ⚠️ This action is **permanent** +- User's boards, images, and workflows are deleted +- Cannot be undone +- Consider deactivating instead of deleting + +!!! warning "Data Loss" + Deleting a user permanently removes all their content. Back up the database first if recovery might be needed. + +### Viewing User Activity + +**Queue Management:** + +1. Navigate to **Admin** β†’ **Queue Overview** +2. View all users' active and pending generations +3. Filter by user +4. Cancel stuck or problematic tasks + +**User Statistics:** + +- Number of boards created +- Number of images generated +- Storage usage (if enabled) +- Last login time + +## Model Management + +As an administrator, you have full access to model management. + +### Adding Models + +**Via Model Manager UI:** + +1. Go to **Models** tab +2. Click **Add Model** +3. Choose installation method: + - **From URL**: Provide HuggingFace repo or download URL + - **From Local Path**: Scan local directories + - **Import**: Import model from filesystem + +**Supported Model Types:** + +- Main models (Stable Diffusion, SDXL, FLUX) +- LoRA models +- ControlNet models +- VAE models +- Textual Inversions +- IP-Adapters + +### Configuring Models + +**Model Settings:** + +- Display name +- Description +- Default generation settings (CFG, steps, scheduler) +- Variant selection (fp16/fp32) +- Model thumbnail image + +**Default Settings:** + +Set default parameters that users will start with: + +1. Select a model +2. Go to **Default Settings** tab +3. Configure: + - CFG Scale + - Steps + - Scheduler + - VAE selection +4. Save settings + +### Removing Models + +1. Go to **Models** tab +2. Select model(s) to remove +3. Click **Delete** +4. Confirm deletion + +!!! warning "Impact" + Removing a model affects all users who may be using it in workflows or saved settings. + +## Shared Boards + +Shared boards enable collaboration between users while maintaining control. + +### Creating Shared Boards + +1. Log in as administrator +2. Create a new board (or use existing board) +3. Right-click the board β†’ **Share Board** +4. Add users and set permissions +5. Click **Save Sharing Settings** + +### Permission Levels + +| Level | View | Add Images | Edit/Delete | Manage Sharing | +|-------|------|------------|-------------|----------------| +| **Read** | βœ… | ❌ | ❌ | ❌ | +| **Write** | βœ… | βœ… | βœ… | ❌ | +| **Admin** | βœ… | βœ… | βœ… | βœ… | + +**Permission Recommendations:** + +- **Read**: For viewers who should see but not modify content +- **Write**: For active collaborators who add and organize images +- **Admin**: For trusted users who help manage the shared board + +### Managing Shared Boards + +**Add Users to Shared Board:** + +1. Right-click shared board β†’ **Manage Sharing** +2. Click **Add User** +3. Select user from dropdown +4. Choose permission level +5. Save changes + +**Remove Users from Shared Board:** + +1. Right-click shared board β†’ **Manage Sharing** +2. Find user in list +3. Click **Remove** +4. Confirm removal + +**Change User Permissions:** + +1. Right-click shared board β†’ **Manage Sharing** +2. Find user in list +3. Change permission dropdown +4. Save changes + +### Shared Board Best Practices + +- Give meaningful names to shared boards +- Document the board's purpose in the description +- Assign minimum necessary permissions +- Regularly audit access lists +- Remove users who no longer need access + +## Security + +### Password Policies + +**Enforced Requirements:** + +- Minimum 8 characters +- Must contain uppercase letters +- Must contain lowercase letters +- Must contain numbers + +**Recommended Policies:** + +- Require 12+ character passwords +- Include special characters +- Implement password rotation every 90 days +- Prevent password reuse +- Use multi-factor authentication (when available) + +### Session Management + +**Session Configuration:** + +```yaml +# invokeai.yaml +jwt_token_expiry_hours: 24 # Default session duration +jwt_remember_me_days: 7 # Extended session with "remember me" +``` + +**Session Security:** + +- Sessions use JWT tokens with HMAC signatures +- Tokens are stateless (validated by signature) +- Expired tokens are automatically rejected +- Deactivating a user invalidates their token + +**Token Management:** + +- Tokens are stored in browser localStorage +- Logging out clears the token +- No server-side session storage required +- Tokens include user ID, email, and admin status + +### Secret Key Management + +**Important:** The JWT secret key must be kept confidential. + +**Setting Custom Secret Key:** + +```yaml +# invokeai.yaml +jwt_secret_key: "your-very-long-random-secret-key-here" +``` + +**Generating a Secure Key:** + +```bash +# Python +python -c "import secrets; print(secrets.token_urlsafe(32))" + +# OpenSSL +openssl rand -base64 32 +``` + +**Key Rotation:** + +If you need to rotate the secret key: + +1. All users will be logged out +2. Update `jwt_secret_key` in configuration +3. Restart InvokeAI +4. Notify users to log in again + +### Access Control Best Practices + +1. **Principle of Least Privilege**: Give users minimum necessary permissions +2. **Regular Audits**: Review user list and permissions quarterly +3. **Deactivate Unused Accounts**: Disable accounts for users who no longer need access +4. **Monitor Access**: Review administrator action logs +5. **Separate Duties**: Don't use admin account for regular work + +### Network Security + +**HTTPS Configuration:** + +For production deployments, always use HTTPS: + +```yaml +# Use a reverse proxy like nginx or Traefik +# Example nginx configuration: + +server { + listen 443 ssl http2; + server_name invoke.example.com; + + ssl_certificate /path/to/cert.pem; + ssl_certificate_key /path/to/key.pem; + + location / { + proxy_pass http://localhost:9090; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } +} +``` + +**Firewall Rules:** + +- Restrict access to trusted networks +- Use VPN for remote access +- Rate limit authentication endpoints +- Block repeated failed login attempts + +## Backup and Recovery + +### Database Backup + +**Manual Backup:** + +```bash +# Stop InvokeAI +# Copy database file +cp databases/invokeai.db databases/invokeai.db.$(date +%Y%m%d) + +# Or create compressed backup +tar -czf invokeai_backup_$(date +%Y%m%d).tar.gz databases/ +``` + +**Automated Backup Script:** + +```bash +#!/bin/bash +# backup_invokeai.sh + +BACKUP_DIR="/path/to/backups" +DB_PATH="databases/invokeai.db" +DATE=$(date +%Y%m%d_%H%M%S) + +# Create backup directory +mkdir -p "$BACKUP_DIR" + +# Copy database +cp "$DB_PATH" "$BACKUP_DIR/invokeai_$DATE.db" + +# Keep only last 30 days +find "$BACKUP_DIR" -name "invokeai_*.db" -mtime +30 -delete + +echo "Backup completed: invokeai_$DATE.db" +``` + +**Schedule with cron:** + +```bash +# Edit crontab +crontab -e + +# Add daily backup at 2 AM +0 2 * * * /path/to/backup_invokeai.sh +``` + +### Restoring from Backup + +**To restore a backup:** + +```bash +# Stop InvokeAI +# Replace current database with backup +cp databases/invokeai.db databases/invokeai.db.old # Save current +cp databases/invokeai_backup.db databases/invokeai.db + +# Restart InvokeAI +invokeai-web +``` + +### Disaster Recovery + +**Complete System Backup:** + +Include these directories/files: + +- `databases/` - All database files +- `models/` - Installed models (if locally stored) +- `outputs/` - Generated images +- `invokeai.yaml` - Configuration file +- Any custom scripts or modifications + +**Recovery Process:** + +1. Install InvokeAI on new system +2. Restore configuration file +3. Restore database directory +4. Restore models and outputs +5. Verify file permissions +6. Start InvokeAI and test + +## System Monitoring + +### Health Checks + +**Regular Checks:** + +- Database size and growth +- Available disk space +- User count and active sessions +- Generation queue length +- Model storage usage +- Error logs + +**Monitoring Commands:** + +```bash +# Check database size +du -h databases/invokeai.db + +# Check disk space +df -h + +# View recent logs +tail -f logs/invokeai.log + +# Count active users (if session tracking enabled) +sqlite3 databases/invokeai.db "SELECT COUNT(*) FROM users WHERE is_active = 1;" +``` + +### Performance Optimization + +**Database Maintenance:** + +```bash +# Compact database (reduces file size) +sqlite3 databases/invokeai.db "VACUUM;" + +# Analyze query performance +sqlite3 databases/invokeai.db "ANALYZE;" +``` + +**Resource Allocation:** + +- Monitor GPU memory usage +- Adjust concurrent generation limits +- Configure queue priorities if needed +- Consider dedicated hardware for multi-user loads + +## Troubleshooting + +### User Cannot Login + +**Symptom:** User reports unable to log in + +**Diagnosis:** + +1. Verify account exists and is active + ```bash + sqlite3 databases/invokeai.db "SELECT * FROM users WHERE email = 'user@example.com';" + ``` + +2. Check password (have user try resetting) +3. Verify account is active (`is_active = 1`) +4. Check for account lockout (if implemented) + +**Solutions:** + +- Reset user password +- Reactivate disabled account +- Verify email address is correct +- Check system logs for auth errors + +### Database Locked Errors + +**Symptom:** "Database is locked" errors + +**Causes:** + +- Concurrent write operations +- Long-running transactions +- Backup process accessing database +- File system issues + +**Solutions:** + +```bash +# Check for locks +fuser databases/invokeai.db + +# Increase timeout (in config) +# Or switch to WAL mode: +sqlite3 databases/invokeai.db "PRAGMA journal_mode=WAL;" +``` + +### Forgotten Admin Password + +**Recovery Process:** + +1. Stop InvokeAI +2. Direct database access: + ```bash + sqlite3 databases/invokeai.db + ``` + +3. Reset admin password (requires password hash): + ```sql + -- Generate hash first using Python: + -- from passlib.context import CryptContext + -- pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") + -- print(pwd_context.hash("NewPassword123")) + + UPDATE users + SET password_hash = '$2b$12$...' + WHERE email = 'admin@example.com'; + ``` + +4. Restart InvokeAI + +**Alternative:** Remove `jwt_secret_key` from config to trigger setup wizard (will create new admin). + +### Performance Issues + +**Symptom:** Slow generation or UI + +**Diagnosis:** + +1. Check active generation count +2. Review resource usage (CPU/GPU/RAM) +3. Check database size and performance +4. Review network latency + +**Solutions:** + +- Limit concurrent generations +- Increase hardware resources +- Optimize database (`VACUUM`, `ANALYZE`) +- Add indexes for slow queries +- Consider load balancing + +### Migration Failures + +**Symptom:** Database migration fails on upgrade + +**Prevention:** + +- Always backup before upgrading +- Test migration on copy of database +- Review migration logs + +**Recovery:** + +```bash +# Restore backup +cp databases/invokeai.db.backup databases/invokeai.db + +# Try migration again with verbose logging +invokeai-web --log-level DEBUG +``` + +## Configuration Reference + +### Complete Configuration Example + +```yaml +# invokeai.yaml - Multi-user configuration + +# Authentication +auth_enabled: true +jwt_secret_key: "your-secret-key-here" +jwt_token_expiry_hours: 24 +jwt_remember_me_days: 7 + +# Database +use_memory_db: false +db_path: databases/invokeai.db + +# Server +host: "0.0.0.0" +port: 9090 + +# Paths +models_dir: models/ +outputs_dir: outputs/ + +# Performance +ram: 16 +vram: 8 +allow_model_caching: true + +# Features +scan_models_on_startup: true +``` + +### Environment Variables + +```bash +# Override configuration with environment variables +export INVOKEAI_AUTH_ENABLED=true +export INVOKEAI_JWT_SECRET_KEY="your-secret" +export INVOKEAI_DB_PATH="databases/invokeai.db" +export INVOKEAI_HOST="0.0.0.0" +export INVOKEAI_PORT=9090 +``` + +## Best Practices Summary + +### User Management + +- βœ… Create users with temporary passwords +- βœ… Require password changes on first login +- βœ… Deactivate instead of deleting when possible +- βœ… Regular audit of user accounts +- βœ… Document user roles and responsibilities + +### Security + +- βœ… Use strong, unique JWT secret key +- βœ… Enable HTTPS in production +- βœ… Regular password rotation +- βœ… Monitor failed login attempts +- βœ… Keep InvokeAI updated + +### Operations + +- βœ… Daily automated backups +- βœ… Test restore procedures regularly +- βœ… Monitor disk space and performance +- βœ… Keep database optimized (VACUUM) +- βœ… Review logs for errors + +### Support + +- βœ… Document procedures for common tasks +- βœ… Provide user guide to all users +- βœ… Establish support channels +- βœ… Track and resolve issues promptly +- βœ… Communicate maintenance windows + +## Frequently Asked Questions + +### How many users can InvokeAI support? + +The SQLite-based system can handle dozens of concurrent users comfortably. For very large deployments (100+ users), consider: + +- Dedicated server hardware +- SSD storage +- Database optimization +- Load balancing (future feature) + +### Can I integrate with existing authentication systems? + +OAuth2/OpenID Connect support is planned for a future release. Currently, InvokeAI uses its own authentication system. + +### How do I audit user actions? + +Full audit logging is planned for a future release. Currently, you can: + +- Monitor the generation queue +- Review database changes +- Check application logs + +### Can users have different model access? + +Not in the current release. All users can view and use all installed models. Per-user model access is a planned enhancement. + +### How do I handle user data when they leave? + +Best practice: + +1. Deactivate the account first +2. Transfer ownership of shared boards +3. After transition period, delete the account +4. Or keep the account deactivated for audit purposes + +### What's the licensing impact of multi-user mode? + +InvokeAI remains under its existing license. Multi-user mode does not change licensing terms. + +## Getting Help + +### Support Resources + +- **Documentation**: [InvokeAI Docs](https://invoke-ai.github.io/InvokeAI/) +- **Discord**: [Join Community](https://discord.gg/ZmtBAhwWhy) +- **GitHub Issues**: [Report Problems](https://github.com/invoke-ai/InvokeAI/issues) +- **User Guide**: [For Users](user_guide.md) +- **API Guide**: [For Developers](api_guide.md) + +### Reporting Issues + +When reporting administrator issues, include: + +- InvokeAI version +- Operating system and version +- Database size and user count +- Relevant log excerpts +- Steps to reproduce +- Expected vs actual behavior + +## Additional Resources + +- [User Guide](user_guide.md) - For end users +- [API Guide](api_guide.md) - For API consumers +- [Multiuser Specification](specification.md) - Technical details + +--- + +**Need additional assistance?** Visit the [InvokeAI Discord](https://discord.gg/ZmtBAhwWhy) or file an issue on [GitHub](https://github.com/invoke-ai/InvokeAI/issues). diff --git a/docs/multiuser/api_guide.md b/docs/multiuser/api_guide.md new file mode 100644 index 00000000000..e521e881e77 --- /dev/null +++ b/docs/multiuser/api_guide.md @@ -0,0 +1,1224 @@ +# InvokeAI Multi-User API Guide + +## Overview + +This guide explains how to interact with InvokeAI's API in both single-user and multi-user modes. The API behavior depends on the `multiuser` configuration setting. + +### Single-User vs Multi-User Mode + +**Single-User Mode** (`multiuser: false` or option absent): +- No authentication required +- All API endpoints accessible without tokens +- Direct API access like previous InvokeAI versions +- All content visible in unified view + +**Multi-User Mode** (`multiuser: true`): +- JWT token authentication required +- User-scoped access to resources +- Role-based authorization (admin vs regular user) +- Data isolation between users + +## Authentication (Multi-User Mode Only) + +### Authentication Flow + +When multi-user mode is enabled, all API endpoints (except `/api/v1/auth/setup` and `/api/v1/auth/login`) require authentication using JWT (JSON Web Token) bearer tokens. + +**Authentication Process:** + +1. **Obtain Token**: POST credentials to `/api/v1/auth/login` +2. **Store Token**: Save the JWT token securely +3. **Use Token**: Include token in `Authorization` header for all requests +4. **Refresh**: Re-authenticate when token expires + +!!! note "Single-User Mode" + When running in single-user mode (`multiuser: false`), authentication endpoints are not available and authentication headers are not required. + +### Login Endpoint + +**Endpoint:** `POST /api/v1/auth/login` + +**Request:** + +```json +{ + "email": "user@example.com", + "password": "SecurePassword123", + "remember_me": false +} +``` + +**Response (Success):** + +```json +{ + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "user": { + "user_id": "abc123", + "email": "user@example.com", + "display_name": "John Doe", + "is_admin": false, + "is_active": true, + "created_at": "2024-01-15T10:00:00Z" + }, + "expires_in": 86400 +} +``` + +**Response (Error):** + +```json +{ + "detail": "Incorrect email or password" +} +``` + +**Status Codes:** + +- `200 OK` - Authentication successful +- `401 Unauthorized` - Invalid credentials +- `403 Forbidden` - Account disabled +- `422 Unprocessable Entity` - Invalid request format + +### Using the Token + +Include the JWT token in the `Authorization` header with the `Bearer` scheme: + +**HTTP Header:** + +``` +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +**Example HTTP Request:** + +```http +GET /api/v1/boards HTTP/1.1 +Host: localhost:9090 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +Content-Type: application/json +``` + +### Token Expiration + +Tokens have a limited lifetime: + +- **Default**: 24 hours (86400 seconds) +- **Remember Me**: 7 days (604800 seconds) + +**Handling Expiration:** + +```python +import requests +import time + +def api_request(url, token, max_retries=1): + headers = {"Authorization": f"Bearer {token}"} + response = requests.get(url, headers=headers) + + if response.status_code == 401: # Token expired + # Re-authenticate and retry + new_token = login() + headers = {"Authorization": f"Bearer {new_token}"} + response = requests.get(url, headers=headers) + + return response +``` + +### Logout Endpoint + +**Endpoint:** `POST /api/v1/auth/logout` + +**Request:** + +```http +POST /api/v1/auth/logout HTTP/1.1 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +**Response:** + +```json +{ + "success": true +} +``` + +**Note:** With JWT tokens, logout is primarily client-side (delete token). Server-side session invalidation may be added in future releases. + +## Code Examples + +### Python + +**Using `requests` library:** + +```python +import requests +import json + +class InvokeAIClient: + def __init__(self, base_url="http://localhost:9090"): + self.base_url = base_url + self.token = None + + def login(self, email, password, remember_me=False): + """Authenticate and store token.""" + url = f"{self.base_url}/api/v1/auth/login" + payload = { + "email": email, + "password": password, + "remember_me": remember_me + } + + response = requests.post(url, json=payload) + response.raise_for_status() + + data = response.json() + self.token = data["token"] + return data["user"] + + def _get_headers(self): + """Get headers with authentication token.""" + if not self.token: + raise Exception("Not authenticated. Call login() first.") + + return { + "Authorization": f"Bearer {self.token}", + "Content-Type": "application/json" + } + + def get_boards(self): + """Get user's boards.""" + url = f"{self.base_url}/api/v1/boards/" + response = requests.get(url, headers=self._get_headers()) + response.raise_for_status() + return response.json() + + def create_board(self, board_name): + """Create a new board.""" + url = f"{self.base_url}/api/v1/boards/" + payload = {"board_name": board_name} + + response = requests.post( + url, + json=payload, + headers=self._get_headers() + ) + response.raise_for_status() + return response.json() + + def logout(self): + """Logout and clear token.""" + url = f"{self.base_url}/api/v1/auth/logout" + response = requests.post(url, headers=self._get_headers()) + self.token = None + return response.json() + +# Usage +client = InvokeAIClient() +user = client.login("user@example.com", "SecurePassword123") +print(f"Logged in as: {user['display_name']}") + +boards = client.get_boards() +print(f"User has {len(boards['items'])} boards") + +new_board = client.create_board("My New Board") +print(f"Created board: {new_board['board_name']}") + +client.logout() +``` + +**Error Handling:** + +```python +import requests +from requests.exceptions import HTTPError + +def safe_api_call(client, method, *args, **kwargs): + """Make API call with error handling.""" + try: + func = getattr(client, method) + return func(*args, **kwargs) + + except HTTPError as e: + if e.response.status_code == 401: + print("Authentication failed or token expired") + # Re-authenticate + client.login(email, password) + # Retry + return func(*args, **kwargs) + elif e.response.status_code == 403: + print("Permission denied") + elif e.response.status_code == 404: + print("Resource not found") + else: + print(f"API error: {e.response.status_code}") + print(e.response.text) + + raise + +# Usage +try: + boards = safe_api_call(client, "get_boards") +except Exception as e: + print(f"Failed to get boards: {e}") +``` + +### JavaScript/TypeScript + +**Using `fetch` API:** + +```javascript +class InvokeAIClient { + constructor(baseUrl = 'http://localhost:9090') { + this.baseUrl = baseUrl; + this.token = null; + } + + async login(email, password, rememberMe = false) { + const response = await fetch(`${this.baseUrl}/api/v1/auth/login`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + email, + password, + remember_me: rememberMe, + }), + }); + + if (!response.ok) { + throw new Error(`Login failed: ${response.statusText}`); + } + + const data = await response.json(); + this.token = data.token; + + // Store token in localStorage + localStorage.setItem('invokeai_token', data.token); + + return data.user; + } + + getHeaders() { + if (!this.token) { + throw new Error('Not authenticated. Call login() first.'); + } + + return { + 'Authorization': `Bearer ${this.token}`, + 'Content-Type': 'application/json', + }; + } + + async getBoards() { + const response = await fetch(`${this.baseUrl}/api/v1/boards/`, { + headers: this.getHeaders(), + }); + + if (!response.ok) { + throw new Error(`Failed to get boards: ${response.statusText}`); + } + + return response.json(); + } + + async createBoard(boardName) { + const response = await fetch(`${this.baseUrl}/api/v1/boards/`, { + method: 'POST', + headers: this.getHeaders(), + body: JSON.stringify({ board_name: boardName }), + }); + + if (!response.ok) { + throw new Error(`Failed to create board: ${response.statusText}`); + } + + return response.json(); + } + + async logout() { + const response = await fetch(`${this.baseUrl}/api/v1/auth/logout`, { + method: 'POST', + headers: this.getHeaders(), + }); + + this.token = null; + localStorage.removeItem('invokeai_token'); + + return response.json(); + } +} + +// Usage +(async () => { + const client = new InvokeAIClient(); + + try { + const user = await client.login('user@example.com', 'SecurePassword123'); + console.log(`Logged in as: ${user.display_name}`); + + const boards = await client.getBoards(); + console.log(`User has ${boards.items.length} boards`); + + const newBoard = await client.createBoard('My New Board'); + console.log(`Created board: ${newBoard.board_name}`); + + await client.logout(); + } catch (error) { + console.error('Error:', error.message); + } +})(); +``` + +**TypeScript with Types:** + +```typescript +interface LoginRequest { + email: string; + password: string; + remember_me?: boolean; +} + +interface User { + user_id: string; + email: string; + display_name: string; + is_admin: boolean; + is_active: boolean; + created_at: string; +} + +interface LoginResponse { + token: string; + user: User; + expires_in: number; +} + +interface Board { + board_id: string; + board_name: string; + created_at: string; + updated_at: string; + deleted_at?: string; + cover_image_name?: string; +} + +class InvokeAIClient { + private baseUrl: string; + private token: string | null = null; + + constructor(baseUrl: string = 'http://localhost:9090') { + this.baseUrl = baseUrl; + } + + async login( + email: string, + password: string, + rememberMe: boolean = false + ): Promise { + const response = await fetch(`${this.baseUrl}/api/v1/auth/login`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email, password, remember_me: rememberMe }), + }); + + if (!response.ok) { + const error = await response.json(); + throw new Error(error.detail || 'Login failed'); + } + + const data: LoginResponse = await response.json(); + this.token = data.token; + return data.user; + } + + private getHeaders(): HeadersInit { + if (!this.token) { + throw new Error('Not authenticated'); + } + return { + 'Authorization': `Bearer ${this.token}`, + 'Content-Type': 'application/json', + }; + } + + async getBoards(): Promise<{ items: Board[] }> { + const response = await fetch(`${this.baseUrl}/api/v1/boards/`, { + headers: this.getHeaders(), + }); + + if (!response.ok) { + throw new Error('Failed to get boards'); + } + + return response.json(); + } +} +``` + +### cURL + +**Login:** + +```bash +# Login and extract token +TOKEN=$(curl -X POST http://localhost:9090/api/v1/auth/login \ + -H "Content-Type: application/json" \ + -d '{ + "email": "user@example.com", + "password": "SecurePassword123", + "remember_me": false + }' | jq -r '.token') + +echo "Token: $TOKEN" +``` + +**Get Boards:** + +```bash +curl -X GET http://localhost:9090/api/v1/boards/ \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" +``` + +**Create Board:** + +```bash +curl -X POST http://localhost:9090/api/v1/boards/ \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "board_name": "My API Board" + }' +``` + +**Generate Image:** + +```bash +curl -X POST http://localhost:9090/api/v1/sessions/ \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "A beautiful landscape", + "width": 512, + "height": 512, + "steps": 30 + }' +``` + +## API Endpoint Changes + +### Authentication Required + +All endpoints now require authentication except: + +- `POST /api/v1/auth/setup` - Initial admin setup +- `POST /api/v1/auth/login` - User login + +### User-Scoped Resources + +Resources are now filtered by the authenticated user: + +**Boards:** + +```python +# Before (single-user) +GET /api/v1/boards/ # Returns all boards + +# After (multi-user) +GET /api/v1/boards/ # Returns only current user's boards +``` + +**Images:** + +```python +# Images are filtered by board ownership +GET /api/v1/images/ # Only shows images on user's boards +``` + +**Workflows:** + +```python +# Returns user's workflows + public workflows +GET /api/v1/workflows/ +``` + +**Queue:** + +```python +# Regular users see only their queue items +GET /api/v1/queue/ # User's queue items + +# Administrators see all queue items +GET /api/v1/queue/ # All users' queue items +``` + +### Administrator Endpoints + +Some endpoints require administrator privileges: + +**User Management:** + +```python +GET /api/v1/users # List users (admin only) +POST /api/v1/users # Create user (admin only) +GET /api/v1/users/{id} # Get user (admin only) +PATCH /api/v1/users/{id} # Update user (admin only) +DELETE /api/v1/users/{id} # Delete user (admin only) +``` + +**Model Management (Write Operations):** + +```python +POST /api/v1/models/install # Install model (admin only) +DELETE /api/v1/models/i/{key} # Delete model (admin only) +PATCH /api/v1/models/i/{key} # Update model (admin only) +PUT /api/v1/models/convert/{key} # Convert model (admin only) +``` + +**Model Management (Read Operations):** + +```python +GET /api/v1/models/ # List models (all users) +GET /api/v1/models/i/{key} # Get model details (all users) +``` + +### Error Responses + +**401 Unauthorized:** + +```json +{ + "detail": "Invalid authentication credentials" +} +``` + +Occurs when: + +- Token is missing +- Token is invalid +- Token is expired +- Token signature is invalid + +**403 Forbidden:** + +```json +{ + "detail": "Admin privileges required" +} +``` + +Occurs when: + +- User attempts admin-only operation +- Account is disabled +- Insufficient permissions + +**404 Not Found:** + +```json +{ + "detail": "Resource not found" +} +``` + +Occurs when: + +- Resource doesn't exist +- User doesn't have access to resource + +## New API Endpoints + +### Authentication Endpoints + +#### Setup Administrator + +**Endpoint:** `POST /api/v1/auth/setup` + +**Description:** Create initial administrator account (only works if no admin exists) + +**Request:** + +```json +{ + "email": "admin@example.com", + "display_name": "Administrator", + "password": "SecureAdminPass123" +} +``` + +**Response:** + +```json +{ + "success": true, + "user": { + "user_id": "abc123", + "email": "admin@example.com", + "display_name": "Administrator", + "is_admin": true, + "is_active": true + } +} +``` + +#### Get Current User + +**Endpoint:** `GET /api/v1/auth/me` + +**Description:** Get currently authenticated user's information + +**Request:** + +```http +GET /api/v1/auth/me +Authorization: Bearer +``` + +**Response:** + +```json +{ + "user_id": "abc123", + "email": "user@example.com", + "display_name": "John Doe", + "is_admin": false, + "is_active": true, + "created_at": "2024-01-15T10:00:00Z", + "updated_at": "2024-01-15T10:00:00Z", + "last_login_at": "2024-01-15T15:30:00Z" +} +``` + +#### Change Password + +**Endpoint:** `POST /api/v1/auth/change-password` + +**Description:** Change current user's password + +**Request:** + +```json +{ + "current_password": "OldPassword123", + "new_password": "NewPassword456" +} +``` + +**Response:** + +```json +{ + "success": true +} +``` + +### User Management Endpoints (Admin Only) + +#### List Users + +**Endpoint:** `GET /api/v1/users` + +**Request:** + +```http +GET /api/v1/users?page=1&per_page=20 +Authorization: Bearer +``` + +**Response:** + +```json +{ + "items": [ + { + "user_id": "abc123", + "email": "user@example.com", + "display_name": "John Doe", + "is_admin": false, + "is_active": true, + "created_at": "2024-01-15T10:00:00Z", + "last_login_at": "2024-01-15T15:30:00Z" + } + ], + "page": 1, + "pages": 1, + "per_page": 20, + "total": 5 +} +``` + +#### Create User + +**Endpoint:** `POST /api/v1/users` + +**Request:** + +```json +{ + "email": "newuser@example.com", + "display_name": "New User", + "password": "TempPassword123", + "is_admin": false +} +``` + +**Response:** + +```json +{ + "user_id": "xyz789", + "email": "newuser@example.com", + "display_name": "New User", + "is_admin": false, + "is_active": true, + "created_at": "2024-01-15T16:00:00Z" +} +``` + +#### Update User + +**Endpoint:** `PATCH /api/v1/users/{user_id}` + +**Request:** + +```json +{ + "display_name": "Updated Name", + "is_active": true, + "is_admin": false +} +``` + +**Response:** + +```json +{ + "user_id": "xyz789", + "email": "newuser@example.com", + "display_name": "Updated Name", + "is_admin": false, + "is_active": true +} +``` + +#### Delete User + +**Endpoint:** `DELETE /api/v1/users/{user_id}` + +**Response:** + +```json +{ + "success": true +} +``` + +#### Reset User Password + +**Endpoint:** `POST /api/v1/users/{user_id}/reset-password` + +**Request:** + +```json +{ + "new_password": "NewTempPass123" +} +``` + +**Response:** + +```json +{ + "success": true +} +``` + +### Board Sharing Endpoints + +#### Share Board + +**Endpoint:** `POST /api/v1/boards/{board_id}/share` + +**Request:** + +```json +{ + "user_id": "user123", + "permission": "write" +} +``` + +**Response:** + +```json +{ + "success": true, + "share": { + "board_id": "board456", + "user_id": "user123", + "permission": "write", + "shared_at": "2024-01-15T16:00:00Z" + } +} +``` + +#### List Board Shares + +**Endpoint:** `GET /api/v1/boards/{board_id}/shares` + +**Response:** + +```json +{ + "items": [ + { + "user_id": "user123", + "display_name": "John Doe", + "permission": "write", + "shared_at": "2024-01-15T16:00:00Z" + } + ] +} +``` + +#### Remove Board Share + +**Endpoint:** `DELETE /api/v1/boards/{board_id}/share/{user_id}` + +**Response:** + +```json +{ + "success": true +} +``` + +## Best Practices + +### Token Storage + +**Do:** + +- Store tokens securely (keychain, secure storage) +- Use HTTPS to transmit tokens +- Clear tokens on logout +- Handle token expiration gracefully + +**Don't:** + +- Store tokens in URL parameters +- Log tokens in plain text +- Share tokens between users +- Store tokens in version control + +### Error Handling + +Always handle authentication errors: + +```python +def make_request(client, func, *args, **kwargs): + max_retries = 3 + retry_count = 0 + + while retry_count < max_retries: + try: + return func(*args, **kwargs) + except AuthenticationError: + if retry_count >= max_retries - 1: + raise + # Re-authenticate + client.login(email, password) + retry_count += 1 + except Exception as e: + logger.error(f"Request failed: {e}") + raise +``` + +### Rate Limiting + +Be mindful of API rate limits: + +- Implement exponential backoff for retries +- Cache frequently accessed data +- Batch requests when possible +- Don't hammer the login endpoint + +### Connection Management + +```python +import requests +from requests.adapters import HTTPAdapter +from urllib3.util.retry import Retry + +def create_session(): + """Create session with retry logic.""" + session = requests.Session() + + retry = Retry( + total=3, + backoff_factor=0.3, + status_forcelist=[500, 502, 503, 504], + ) + + adapter = HTTPAdapter(max_retries=retry) + session.mount('http://', adapter) + session.mount('https://', adapter) + + return session +``` + +## Migration Guide + +### Updating Existing Code + +**Before (single-user mode):** + +```python +import requests + +def get_boards(): + response = requests.get("http://localhost:9090/api/v1/boards/") + return response.json() +``` + +**After (multi-user mode):** + +```python +import requests + +class APIClient: + def __init__(self): + self.token = None + + def login(self, email, password): + response = requests.post( + "http://localhost:9090/api/v1/auth/login", + json={"email": email, "password": password} + ) + self.token = response.json()["token"] + + def get_boards(self): + headers = {"Authorization": f"Bearer {self.token}"} + response = requests.get( + "http://localhost:9090/api/v1/boards/", + headers=headers + ) + return response.json() + +# Usage +client = APIClient() +client.login("user@example.com", "password") +boards = client.get_boards() +``` + +### Backward Compatibility + +InvokeAI supports both single-user and multi-user modes via the `multiuser` configuration option. + +**Configuration:** + +```yaml +# invokeai.yaml + +# Single-user mode (no authentication) +multiuser: false # or omit the option entirely + +# Multi-user mode (authentication required) +multiuser: true +``` + +**Checking Mode Programmatically:** + +```python +def is_multiuser_enabled(base_url): + """Check if multi-user mode is enabled (authentication required).""" + response = requests.get(f"{base_url}/api/v1/boards/") + return response.status_code == 401 # 401 = auth required + +# Example usage +base_url = "http://localhost:9090" +if is_multiuser_enabled(base_url): + print("Multi-user mode: authentication required") + # Use authenticated API calls +else: + print("Single-user mode: no authentication needed") + # Use direct API calls +``` + +**Adaptive Client:** + +```python +class AdaptiveInvokeAIClient: + def __init__(self, base_url="http://localhost:9090"): + self.base_url = base_url + self.token = None + self.multiuser_mode = self._check_multiuser_mode() + + def _check_multiuser_mode(self): + """Detect if multi-user mode is enabled.""" + try: + response = requests.get(f"{self.base_url}/api/v1/boards/") + return response.status_code == 401 + except: + return False + + def login(self, email, password): + """Login (only needed in multi-user mode).""" + if not self.multiuser_mode: + print("Single-user mode: login not required") + return + + response = requests.post( + f"{self.base_url}/api/v1/auth/login", + json={"email": email, "password": password} + ) + self.token = response.json()["token"] + + def _get_headers(self): + """Get headers (with auth token if in multi-user mode).""" + if self.multiuser_mode and self.token: + return {"Authorization": f"Bearer {self.token}"} + return {} + + def get_boards(self): + """Get boards (works in both modes).""" + response = requests.get( + f"{self.base_url}/api/v1/boards/", + headers=self._get_headers() + ) + return response.json() +``` + +## OpenAPI/Swagger Documentation + +InvokeAI provides OpenAPI documentation for all endpoints. + +**Access Swagger UI:** + +``` +http://localhost:9090/docs +``` + +**Download OpenAPI Schema:** + +```bash +curl http://localhost:9090/openapi.json > invokeai_openapi.json +``` + +**Generate Client Code:** + +Use tools like `openapi-generator` to generate client libraries: + +```bash +# Generate Python client +openapi-generator generate \ + -i http://localhost:9090/openapi.json \ + -g python \ + -o ./invokeai-client + +# Generate TypeScript client +openapi-generator generate \ + -i http://localhost:9090/openapi.json \ + -g typescript-fetch \ + -o ./invokeai-client-ts +``` + +## Security Considerations + +### HTTPS + +Always use HTTPS in production: + +```python +# Development +client = InvokeAIClient("http://localhost:9090") + +# Production +client = InvokeAIClient("https://invoke.example.com") +``` + +### Token Security + +Protect JWT tokens: + +```python +# Never log tokens +logger.info(f"User logged in") # Good +logger.info(f"Token: {token}") # Bad! + +# Use environment variables for credentials +import os +email = os.environ.get("INVOKEAI_EMAIL") +password = os.environ.get("INVOKEAI_PASSWORD") +``` + +### Input Validation + +Always validate user input: + +```python +import re + +def validate_email(email): + pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' + return re.match(pattern, email) is not None + +def validate_password(password): + """Check password meets requirements.""" + if len(password) < 8: + return False, "Password must be at least 8 characters" + if not any(c.isupper() for c in password): + return False, "Password must contain uppercase letters" + if not any(c.islower() for c in password): + return False, "Password must contain lowercase letters" + if not any(c.isdigit() for c in password): + return False, "Password must contain numbers" + return True, "" +``` + +## Troubleshooting + +### Common Issues + +**Issue: "Invalid authentication credentials"** + +- Token expired - re-authenticate +- Token malformed - check token string +- Token signature invalid - check secret key hasn't changed + +**Issue: "Admin privileges required"** + +- User is not an administrator +- Use admin account for this operation + +**Issue: Token not being sent** + +- Check `Authorization` header is present +- Verify `Bearer` prefix is included +- Check token isn't truncated + +**Issue: CORS errors** + +Configure CORS in InvokeAI: + +```yaml +# invokeai.yaml +cors_origins: + - "http://localhost:3000" + - "https://myapp.example.com" +``` + +## Additional Resources + +- [User Guide](user_guide.md) - For end users +- [Administrator Guide](admin_guide.md) - For administrators +- [Multiuser Specification](specification.md) - Technical details +- [OpenAPI Documentation](http://localhost:9090/docs) - Interactive API docs +- [GitHub Repository](https://github.com/invoke-ai/InvokeAI) - Source code + +--- + +**Questions?** Visit the [InvokeAI Discord](https://discord.gg/ZmtBAhwWhy) or check the [FAQ](../faq.md). diff --git a/docs/multiuser/board_isolation_issue.md b/docs/multiuser/board_isolation_issue.md deleted file mode 100644 index 260552a2070..00000000000 --- a/docs/multiuser/board_isolation_issue.md +++ /dev/null @@ -1,145 +0,0 @@ -# Board Isolation Issues in Multiuser Implementation - -## Problem Description - -After implementing multiuser support (Phases 1-6), there are several board isolation issues that need to be addressed: - -### 1. Board List Not Updating When Switching Users -**Issue:** In the Web UI, when a user logs out and logs back in as a different user, the board list is not updated unless the window is refreshed. - -**Expected Behavior:** Board list should automatically update to show only the new user's boards when switching users. - -**Current Behavior:** Old user's boards remain visible until manual page refresh. - -**Root Cause:** Frontend Redux state is not being cleared on logout, leading to stale board data. - -### 2. "Uncategorized" Board Shared Among Users -**Issue:** The default "Uncategorized" board appears to be shared among all users instead of being user-specific. - -**Expected Behavior:** Each user should have their own isolated "Uncategorized" board for images not assigned to any board. - -**Current Behavior:** All users see and share the same "Uncategorized" board. - -**Root Cause:** The special "none" board_id (representing uncategorized images) is not being filtered by user_id in queries. - -### 3. Admin Cannot Access All Users' Boards -**Issue:** Administrator users should be able to view and manage all users' boards, but currently cannot. - -**Expected Behavior:** -- Admin users should see all boards from all users -- Board names should be labeled with the owner's username for clarity (e.g., "Floral Images (Lincoln Stein)") -- Admin should have appropriate permissions to manage boards - -**Current Behavior:** Admin users only see their own boards like regular users. - -**Root Cause:** Board queries filter by current user's user_id without special handling for admin role. - -## Technical Details - -### Database Schema -The migration_25 already adds: -- `user_id` column to `boards` table with default 'system' -- `is_public` column to `boards` table -- `shared_boards` table for board sharing -- Indexes on user_id and is_public - -### Areas Requiring Changes - -#### Backend (Python) -1. **Board Records Service** (`invokeai/app/services/board_records/`) - - Update queries to handle admin users specially - - Ensure proper user_id filtering for regular users - - Handle "uncategorized" (none board_id) per-user isolation - -2. **Board Service** (`invokeai/app/services/boards/`) - - Add admin check in `get_many()` method - - Update board DTOs to include owner information for admin view - - Ensure all board operations respect user ownership - -3. **API Endpoints** (`invokeai/app/api/routers/boards.py`) - - Update endpoints to check for admin role - - Add owner username to board responses for admin users - - Ensure proper authorization checks - -#### Frontend (TypeScript/React) -1. **Redux State** (`invokeai/frontend/web/src/features/gallery/store/`) - - Clear board state on logout - - Refresh board list on login - - Handle board ownership display - -2. **Board Components** - - Update board display to show owner for admin users - - Add visual indicators for owned vs. other users' boards - - Update board selection logic - -3. **Auth Flow** - - Ensure state cleanup on logout - - Trigger board list refresh after login - -## Implementation Plan - -### Phase 1: Backend Board Isolation -1. Update board record queries to filter by user_id (except for admins) -2. Add admin role check to bypass user_id filtering -3. Handle "uncategorized" board per-user isolation -4. Add owner information to board DTOs for admin users - -### Phase 2: Frontend State Management -1. Add logout action to clear all board state -2. Add login success action to refresh board list -3. Update board selectors to handle admin view - -### Phase 3: UI Updates -1. Display owner username for admin users -2. Add visual distinction between own and others' boards -3. Update board creation/management permissions - -### Phase 4: Testing -1. Test board isolation for regular users -2. Test admin can see all boards -3. Test uncategorized board per-user isolation -4. Test state cleanup on logout/login -5. Test board sharing functionality - -## Acceptance Criteria - -- [ ] Regular users only see their own boards and shared boards -- [ ] Each user has their own "Uncategorized" board -- [ ] Admin users see all boards from all users -- [ ] Board names show owner for admin view (e.g., "Board Name (Username)") -- [ ] Logging out and logging in as different user updates board list immediately -- [ ] No stale board data persists after user switch -- [ ] Board sharing works correctly -- [ ] All board operations respect user ownership -- [ ] Tests validate board isolation for all scenarios - -## Related Files - -### Backend -- `invokeai/app/services/board_records/board_records_sqlite.py` -- `invokeai/app/services/board_records/board_records_base.py` -- `invokeai/app/services/boards/boards_default.py` -- `invokeai/app/services/boards/boards_base.py` -- `invokeai/app/api/routers/boards.py` - -### Frontend -- `invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts` -- `invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList.tsx` -- `invokeai/frontend/web/src/features/auth/store/authSlice.ts` - -### Tests -- `tests/app/services/boards/test_boards_multiuser.py` (needs expansion) -- Frontend tests (to be added) - -## Priority -**High** - These issues affect the core multiuser functionality and user experience. - -## Dependencies -- Phases 1-6 of multiuser implementation (completed) -- Migration 25 (completed) - -## Recommended Approach - -Create a new GitHub issue with title: `[enhancement]: Fix board isolation in multiuser implementation` - -Then create a new PR that addresses all three issues together since they are closely related and affect the same subsystems (board service, API, and frontend state management). diff --git a/docs/multiuser/implementation_plan.md b/docs/multiuser/implementation_plan.md deleted file mode 100644 index c23be1a3538..00000000000 --- a/docs/multiuser/implementation_plan.md +++ /dev/null @@ -1,1040 +0,0 @@ -# InvokeAI Multi-User Support - Implementation Plan - -## 1. Overview - -This document provides a detailed, step-by-step implementation plan for adding multi-user support to InvokeAI. It is designed to guide developers through the implementation process while maintaining code quality and minimizing disruption to existing functionality. - -## 2. Implementation Approach - -### 2.1 Principles -- **Minimal Changes**: Make surgical changes to existing code -- **Backward Compatibility**: Support existing single-user installations -- **Security First**: Implement security best practices from the start -- **Incremental Development**: Build and test in small, verifiable steps -- **Test Coverage**: Add tests for all new functionality - -### 2.2 Development Strategy - -1. Start with backend database and services -2. Build authentication layer -3. Update existing services for multi-tenancy -4. Develop frontend authentication -5. Update UI for multi-user features -6. Integration testing and security review - -## 3. Prerequisites - -### 3.1 Dependencies to Add - -Add to `pyproject.toml`: -```toml -dependencies = [ - # ... existing dependencies ... - "passlib[bcrypt]>=1.7.4", # Password hashing - "python-jose[cryptography]>=3.3.0", # JWT tokens - "python-multipart>=0.0.6", # Form data parsing (already present) - "email-validator>=2.0.0", # Email validation -] -``` - -### 3.2 Development Environment Setup -```bash -# Install development dependencies -pip install -e ".[dev]" - -# Run tests to ensure baseline -pytest tests/ - -# Start development server -python -m invokeai.app.run_app --dev_reload -``` - -## 4. Phase 1: Database Schema (Week 1) - -### 4.1 Create Migration File - -**File**: `invokeai/app/services/shared/sqlite_migrator/migrations/migration_25.py` - -```python -import sqlite3 -from invokeai.app.services.shared.sqlite_migrator.sqlite_migrator_common import Migration - -class Migration25Callback: - """Migration to add multi-user support.""" - - def __call__(self, cursor: sqlite3.Cursor) -> None: - self._create_users_table(cursor) - self._create_user_sessions_table(cursor) - self._create_user_invitations_table(cursor) - self._create_shared_boards_table(cursor) - self._update_boards_table(cursor) - self._update_images_table(cursor) - self._update_workflows_table(cursor) - self._update_session_queue_table(cursor) - self._update_style_presets_table(cursor) - self._create_system_user(cursor) - - def _create_users_table(self, cursor: sqlite3.Cursor) -> None: - """Create users table.""" - cursor.execute(""" - CREATE TABLE IF NOT EXISTS users ( - user_id TEXT NOT NULL PRIMARY KEY, - email TEXT NOT NULL UNIQUE, - display_name TEXT, - password_hash TEXT NOT NULL, - is_admin BOOLEAN NOT NULL DEFAULT FALSE, - is_active BOOLEAN NOT NULL DEFAULT TRUE, - created_at DATETIME NOT NULL DEFAULT(STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), - updated_at DATETIME NOT NULL DEFAULT(STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), - last_login_at DATETIME - ); - """) - - cursor.execute("CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);") - cursor.execute("CREATE INDEX IF NOT EXISTS idx_users_is_admin ON users(is_admin);") - cursor.execute("CREATE INDEX IF NOT EXISTS idx_users_is_active ON users(is_active);") - - cursor.execute(""" - CREATE TRIGGER IF NOT EXISTS tg_users_updated_at - AFTER UPDATE ON users FOR EACH ROW - BEGIN - UPDATE users SET updated_at = STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') - WHERE user_id = old.user_id; - END; - """) - - # ... implement other methods ... - - def _create_system_user(self, cursor: sqlite3.Cursor) -> None: - """Create system user for backward compatibility.""" - cursor.execute(""" - INSERT OR IGNORE INTO users (user_id, email, display_name, password_hash, is_admin, is_active) - VALUES ('system', 'system@invokeai.local', 'System', '', TRUE, TRUE); - """) - -def build_migration_25() -> Migration: - """Build migration 25: Multi-user support.""" - return Migration( - from_version=24, - to_version=25, - callback=Migration25Callback(), - ) -``` - -### 4.2 Update Migration Registry - -**File**: `invokeai/app/services/shared/sqlite_migrator/migrations/__init__.py` - -```python -from .migration_25 import build_migration_25 - -# Add to migrations list -def build_migrations() -> list[Migration]: - return [ - # ... existing migrations ... - build_migration_25(), - ] -``` - -### 4.3 Testing -```bash -# Test migration -pytest tests/test_sqlite_migrator.py -v - -# Manually test migration -python -m invokeai.app.run_app --use_memory_db -# Verify tables created -``` - -## 5. Phase 2: Authentication Service (Week 2) - -### 5.1 Create Password Utilities - -**File**: `invokeai/app/services/auth/password_utils.py` - -```python -"""Password hashing and validation utilities.""" -from passlib.context import CryptContext -from typing import Tuple - -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") - -def hash_password(password: str) -> str: - """Hash a password using bcrypt.""" - return pwd_context.hash(password) - -def verify_password(plain_password: str, hashed_password: str) -> bool: - """Verify a password against a hash.""" - return pwd_context.verify(plain_password, hashed_password) - -def validate_password_strength(password: str) -> Tuple[bool, str]: - """Validate password meets requirements.""" - if len(password) < 8: - return False, "Password must be at least 8 characters long" - - has_upper = any(c.isupper() for c in password) - has_lower = any(c.islower() for c in password) - has_digit = any(c.isdigit() for c in password) - - if not (has_upper and has_lower and has_digit): - return False, "Password must contain uppercase, lowercase, and numbers" - - return True, "" -``` - -### 5.2 Create Token Service - -**File**: `invokeai/app/services/auth/token_service.py` - -```python -"""JWT token generation and validation.""" -from datetime import datetime, timedelta -from jose import JWTError, jwt -from typing import Optional -from pydantic import BaseModel - -SECRET_KEY = "your-secret-key-should-be-in-config" # TODO: Move to config -ALGORITHM = "HS256" - -class TokenData(BaseModel): - user_id: str - email: str - is_admin: bool - -def create_access_token(data: TokenData, expires_delta: Optional[timedelta] = None) -> str: - """Create a JWT access token.""" - to_encode = data.model_dump() - expire = datetime.utcnow() + (expires_delta or timedelta(hours=24)) - to_encode.update({"exp": expire}) - return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) - -def verify_token(token: str) -> Optional[TokenData]: - """Verify and decode a JWT token.""" - try: - payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - return TokenData(**payload) - except JWTError: - return None -``` - -### 5.3 Create User Service Base - -**File**: `invokeai/app/services/users/users_base.py` - -```python -"""Abstract base class for user service.""" -from abc import ABC, abstractmethod -from typing import Optional -from .users_common import UserDTO, UserCreateRequest, UserUpdateRequest - -class UserServiceABC(ABC): - """High-level service for user management.""" - - @abstractmethod - def create(self, user_data: UserCreateRequest) -> UserDTO: - """Create a new user.""" - pass - - @abstractmethod - def get(self, user_id: str) -> Optional[UserDTO]: - """Get user by ID.""" - pass - - @abstractmethod - def get_by_email(self, email: str) -> Optional[UserDTO]: - """Get user by email.""" - pass - - @abstractmethod - def update(self, user_id: str, changes: UserUpdateRequest) -> UserDTO: - """Update user.""" - pass - - @abstractmethod - def delete(self, user_id: str) -> None: - """Delete user.""" - pass - - @abstractmethod - def authenticate(self, email: str, password: str) -> Optional[UserDTO]: - """Authenticate user credentials.""" - pass -``` - -### 5.4 Create User Service Implementation - -**File**: `invokeai/app/services/users/users_default.py` - -```python -"""Default implementation of user service.""" -from uuid import uuid4 -from .users_base import UserServiceABC -from .users_common import UserDTO, UserCreateRequest, UserUpdateRequest -from ..auth.password_utils import hash_password, verify_password -from ..shared.sqlite.sqlite_database import SqliteDatabase - -class UserService(UserServiceABC): - """SQLite-based user service.""" - - def __init__(self, db: SqliteDatabase): - self._db = db - - def create(self, user_data: UserCreateRequest) -> UserDTO: - """Create a new user.""" - user_id = str(uuid4()) - password_hash = hash_password(user_data.password) - - with self._db.transaction() as cursor: - cursor.execute( - """ - INSERT INTO users (user_id, email, display_name, password_hash, is_admin) - VALUES (?, ?, ?, ?, ?) - """, - (user_id, user_data.email, user_data.display_name, - password_hash, user_data.is_admin) - ) - - return self.get(user_id) - - # ... implement other methods ... -``` - -### 5.5 Testing -```bash -# Create test file -# tests/app/services/users/test_user_service.py - -pytest tests/app/services/users/ -v -``` - -## 6. Phase 3: Authentication Middleware (Week 3) - -### 6.1 Create Auth Dependencies - -**File**: `invokeai/app/api/auth_dependencies.py` - -```python -"""FastAPI dependencies for authentication.""" -from fastapi import Depends, HTTPException, status -from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials -from typing import Annotated -from ..services.auth.token_service import verify_token, TokenData -from ..services.users.users_common import UserDTO - -security = HTTPBearer() - -async def get_current_user( - credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)] -) -> TokenData: - """Get current authenticated user from token.""" - token = credentials.credentials - token_data = verify_token(token) - - if token_data is None: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Invalid authentication credentials", - headers={"WWW-Authenticate": "Bearer"}, - ) - - return token_data - -async def require_admin( - current_user: Annotated[TokenData, Depends(get_current_user)] -) -> TokenData: - """Require admin role.""" - if not current_user.is_admin: - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail="Admin privileges required" - ) - return current_user - -# Type aliases for route dependencies -CurrentUser = Annotated[TokenData, Depends(get_current_user)] -AdminUser = Annotated[TokenData, Depends(require_admin)] -``` - -### 6.2 Create Authentication Router - -**File**: `invokeai/app/api/routers/auth.py` - -```python -"""Authentication endpoints.""" -from fastapi import APIRouter, Depends, HTTPException, status -from pydantic import BaseModel, EmailStr -from typing import Optional -from datetime import timedelta -from ..auth_dependencies import CurrentUser -from ..dependencies import ApiDependencies -from ...services.auth.token_service import create_access_token, TokenData - -auth_router = APIRouter(prefix="/v1/auth", tags=["authentication"]) - -class LoginRequest(BaseModel): - email: EmailStr - password: str - remember_me: bool = False - -class LoginResponse(BaseModel): - token: str - user: dict - expires_in: int - -class SetupRequest(BaseModel): - email: EmailStr - display_name: str - password: str - -@auth_router.post("/login", response_model=LoginResponse) -async def login(request: LoginRequest): - """Authenticate user and return token.""" - user_service = ApiDependencies.invoker.services.users - user = user_service.authenticate(request.email, request.password) - - if not user: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Incorrect email or password" - ) - - if not user.is_active: - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail="User account is disabled" - ) - - # Create token - expires_delta = timedelta(days=7 if request.remember_me else 1) - token_data = TokenData( - user_id=user.user_id, - email=user.email, - is_admin=user.is_admin - ) - token = create_access_token(token_data, expires_delta) - - return LoginResponse( - token=token, - user=user.model_dump(), - expires_in=int(expires_delta.total_seconds()) - ) - -@auth_router.post("/logout") -async def logout(current_user: CurrentUser): - """Logout current user.""" - # TODO: Implement token invalidation if using server-side sessions - return {"success": True} - -@auth_router.get("/me") -async def get_current_user_info(current_user: CurrentUser): - """Get current user information.""" - user_service = ApiDependencies.invoker.services.users - user = user_service.get(current_user.user_id) - return user - -@auth_router.post("/setup") -async def setup_admin(request: SetupRequest): - """Set up initial administrator account.""" - user_service = ApiDependencies.invoker.services.users - - # Check if any admin exists - # TODO: Implement count_admins method - if user_service.has_admin(): - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Administrator already configured" - ) - - # Create admin user - # TODO: Implement user creation with admin flag - user = user_service.create_admin(request) - - return {"success": True, "user": user.model_dump()} -``` - -### 6.3 Register Auth Router - -**File**: `invokeai/app/api_app.py` (modify) - -```python -# Add import -from invokeai.app.api.routers import auth - -# Add router registration (around line 135) -app.include_router(auth.auth_router, prefix="/api") -``` - -### 6.4 Testing -```bash -# Test authentication endpoints -pytest tests/app/routers/test_auth.py -v - -# Manual testing with curl -curl -X POST http://localhost:9090/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{"email":"admin@test.com","password":"test123"}' -``` - -## 7. Phase 4: Update Services for Multi-tenancy (Weeks 4-5) - -### 7.1 Update Boards Service - -**File**: `invokeai/app/services/boards/boards_default.py` (modify) - -```python -# Add user_id parameter to methods -def create(self, board_name: str, user_id: str) -> BoardDTO: - """Creates a board for a specific user.""" - # Add user_id to INSERT - pass - -def get_many( - self, - user_id: str, # Add this parameter - order_by: BoardRecordOrderBy, - direction: SQLiteDirection, - offset: int = 0, - limit: int = 10, - include_archived: bool = False, -) -> OffsetPaginatedResults[BoardDTO]: - """Gets many boards for a specific user.""" - # Add WHERE user_id = ? OR is_shared = TRUE - pass -``` - -**File**: `invokeai/app/api/routers/boards.py` (modify) - -```python -from ..auth_dependencies import CurrentUser - -@boards_router.get("/", response_model=OffsetPaginatedResults[BoardDTO]) -async def list_boards( - current_user: CurrentUser, # Add this dependency - # ... existing parameters ... -) -> OffsetPaginatedResults[BoardDTO]: - """Gets a list of boards for the current user.""" - return ApiDependencies.invoker.services.boards.get_many( - user_id=current_user.user_id, # Add user filter - # ... existing parameters ... - ) -``` - -### 7.2 Update Images Service - -**File**: `invokeai/app/services/images/images_default.py` (modify) - -Similar changes as boards - add user_id filtering to all queries. - -### 7.3 Update Workflows Service - -**File**: `invokeai/app/services/workflow_records/workflow_records_sqlite.py` (modify) - -Add user_id and is_public filtering. - -### 7.4 Update Session Queue Service - -**File**: `invokeai/app/services/session_queue/session_queue_default.py` (modify) - -Add user_id to queue items and filter by user unless admin. - -### 7.5 Testing -```bash -# Test each updated service -pytest tests/app/services/boards/test_boards_multiuser.py -v -pytest tests/app/services/images/test_images_multiuser.py -v -pytest tests/app/services/workflows/test_workflows_multiuser.py -v -``` - -## 8. Phase 5: Frontend Authentication (Week 6) - -### 8.1 Create Auth Slice - -**File**: `invokeai/frontend/web/src/features/auth/store/authSlice.ts` - -```typescript -import { createSlice, PayloadAction } from '@reduxjs/toolkit'; - -interface User { - user_id: string; - email: string; - display_name: string; - is_admin: boolean; -} - -interface AuthState { - isAuthenticated: boolean; - token: string | null; - user: User | null; - isLoading: boolean; -} - -const initialState: AuthState = { - isAuthenticated: false, - token: localStorage.getItem('auth_token'), - user: null, - isLoading: false, -}; - -const authSlice = createSlice({ - name: 'auth', - initialState, - reducers: { - setCredentials: (state, action: PayloadAction<{ token: string; user: User }>) => { - state.token = action.payload.token; - state.user = action.payload.user; - state.isAuthenticated = true; - localStorage.setItem('auth_token', action.payload.token); - }, - logout: (state) => { - state.token = null; - state.user = null; - state.isAuthenticated = false; - localStorage.removeItem('auth_token'); - }, - }, -}); - -export const { setCredentials, logout } = authSlice.actions; -export default authSlice.reducer; -``` - -### 8.2 Create Login Page Component - -**File**: `invokeai/frontend/web/src/features/auth/components/LoginPage.tsx` - -```typescript -import { useState } from 'react'; -import { useLoginMutation } from '../api/authApi'; -import { useAppDispatch } from '@/app/store'; -import { setCredentials } from '../store/authSlice'; - -export const LoginPage = () => { - const [email, setEmail] = useState(''); - const [password, setPassword] = useState(''); - const [rememberMe, setRememberMe] = useState(false); - const [login, { isLoading, error }] = useLoginMutation(); - const dispatch = useAppDispatch(); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - try { - const result = await login({ email, password, remember_me: rememberMe }).unwrap(); - dispatch(setCredentials({ token: result.token, user: result.user })); - } catch (err) { - // Error handled by RTK Query - } - }; - - return ( -
-
-

Sign In to InvokeAI

- - setEmail(e.target.value)} - placeholder="Email" - required - /> - - setPassword(e.target.value)} - placeholder="Password" - required - /> - - - - - - {error &&
Login failed. Please check your credentials.
} -
-
- ); -}; -``` - -### 8.3 Create Protected Route Wrapper - -**File**: `invokeai/frontend/web/src/features/auth/components/ProtectedRoute.tsx` - -```typescript -import { Navigate } from 'react-router-dom'; -import { useAppSelector } from '@/app/store'; - -interface ProtectedRouteProps { - children: React.ReactNode; - requireAdmin?: boolean; -} - -export const ProtectedRoute = ({ children, requireAdmin = false }: ProtectedRouteProps) => { - const { isAuthenticated, user } = useAppSelector((state) => state.auth); - - if (!isAuthenticated) { - return ; - } - - if (requireAdmin && !user?.is_admin) { - return ; - } - - return <>{children}; -}; -``` - -### 8.4 Update API Configuration - -**File**: `invokeai/frontend/web/src/services/api/index.ts` (modify) - -```typescript -// Add auth header to all requests -import { createApi } from '@reduxjs/toolkit/query/react'; - -const baseQuery = fetchBaseQuery({ - baseUrl: '/api', - prepareHeaders: (headers, { getState }) => { - const token = (getState() as RootState).auth.token; - if (token) { - headers.set('Authorization', `Bearer ${token}`); - } - return headers; - }, -}); -``` - -## 9. Phase 6: Frontend UI Updates (Week 7) - -### 9.1 Update App Root - -**File**: `invokeai/frontend/web/src/main.tsx` (modify) - -```typescript -import { LoginPage } from './features/auth/components/LoginPage'; -import { ProtectedRoute } from './features/auth/components/ProtectedRoute'; - -// Wrap main app in ProtectedRoute - - - } /> - - - - } /> - - -``` - -### 9.2 Add User Menu - -**File**: `invokeai/frontend/web/src/features/ui/components/UserMenu.tsx` - -```typescript -import { useAppSelector, useAppDispatch } from '@/app/store'; -import { logout } from '@/features/auth/store/authSlice'; -import { useNavigate } from 'react-router-dom'; - -export const UserMenu = () => { - const user = useAppSelector((state) => state.auth.user); - const dispatch = useAppDispatch(); - const navigate = useNavigate(); - - const handleLogout = () => { - dispatch(logout()); - navigate('/login'); - }; - - return ( -
- {user?.display_name || user?.email} - {user?.is_admin && Admin} - -
- ); -}; -``` - -### 9.3 Read-Only Model Manager for Non-Admin - -**Updated Design**: Non-admin users now have read-only access to the Model Manager instead of no access. - -**Files Modified**: -- `invokeai/frontend/web/src/features/ui/components/tabs/ModelManagerTab.tsx` -- `invokeai/frontend/web/src/features/ui/components/VerticalNavBar.tsx` -- `invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelManager.tsx` -- `invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPane.tsx` -- `invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelView.tsx` -- `invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ModelHeader.tsx` -- `invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings.tsx` -- `invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/LoRAModelDefaultSettings/LoRAModelDefaultSettings.tsx` -- `invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/ControlAdapterModelDefaultSettings/ControlAdapterModelDefaultSettings.tsx` -- `invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelManagerPanel/ModelListBulkActions.tsx` -- `invokeai/app/api/routers/model_manager.py` - -**Frontend Changes**: - -1. **Model Tab Visibility**: Models tab is visible to all users (not just admins) -2. **Add Models Button**: Hidden for non-admin users -3. **Model Details View**: Non-admin users can view but not modify: - - Edit, Delete, Reidentify, Convert buttons hidden - - Model image upload hidden - - Default settings Save button hidden - - All model metadata and settings displayed (read-only) -4. **Bulk Actions**: Delete action in bulk menu hidden for non-admin users -5. **Install Panel**: Hidden for non-admin users (empty state shown instead) - -**Backend Authorization** (`invokeai/app/api/routers/model_manager.py`): - -All write operations now require `AdminUser` dependency: -- `reidentify_model` - POST `/i/{key}/reidentify` -- `update_model_record` - PATCH `/i/{key}` -- `update_model_image` - PATCH `/i/{key}/image` -- `delete_model` - DELETE `/i/{key}` -- `bulk_delete_models` - POST `/i/bulk_delete` -- `delete_model_image` - DELETE `/i/{key}/image` -- `install_model` - POST `/install` -- `install_hugging_face_model` - GET `/i/huggingface` -- `cancel_model_install_job` - DELETE `/install/{id}` -- `prune_model_install_jobs` - DELETE `/install` -- `convert_model` - PUT `/convert/{key}` -- `empty_model_cache` - POST `/empty_model_cache` -- `do_hf_login` - POST `/hf_login` -- `reset_hf_token` - DELETE `/hf_login` - -**Read Operations** (remain accessible to all authenticated users): -- `list_model_records` - GET `/i/` -- `get_model_record` - GET `/i/{key}` -- `get_model_image` - GET `/i/{key}/image` -- `scan_folder` - GET `/scan_folder` -- `get_model_metadata` - POST `/get_metadata` -- `get_model_install_jobs` - GET `/install` -- `get_model_install_job` - GET `/install/{id}` -- `get_starter_models` - GET `/starter_models` -- `get_hf_login_status` - GET `/hf_login` - -**Benefits**: -- Non-admin users can browse available models -- Users can see model configurations and default settings -- Better transparency about what models are available -- Reduces admin burden for answering "what models do we have?" questions -- Maintains security through backend authorization - -## 10. Phase 7: Testing & Security (Weeks 8-9) - -### 10.1 Unit Tests - -Create comprehensive tests for: -- Password hashing and validation -- Token generation and verification -- User service methods -- Authorization checks -- Data isolation queries - -### 10.2 Integration Tests - -Test complete flows: -- User registration and login -- Password reset -- Multi-user data isolation -- Shared board access -- Admin operations - -### 10.3 Security Testing - -- SQL injection tests -- XSS prevention tests -- CSRF protection -- Authorization bypass attempts -- Session hijacking prevention - -### 10.4 Performance Testing - -- Authentication overhead -- Query performance with user filters -- Concurrent user sessions - -## 11. Phase 8: Documentation (Week 10) - -### 11.1 User Documentation -- Getting started guide -- Login and account management -- Using shared boards -- Understanding permissions - -### 11.2 Administrator Documentation -- Setup guide -- User management -- Security best practices -- Backup and restore - -### 11.3 API Documentation -- Update OpenAPI schema -- Add authentication examples -- Document new endpoints - -## 12. Phase 9: Migration Support (Week 11) - -### 12.1 Migration Wizard - -Create CLI tool to assist with migration: - -```bash -python -m invokeai.app.migrate_to_multiuser -``` - -Features: -- Detect existing installation -- Prompt for admin credentials -- Migrate existing data -- Validate migration -- Rollback on error - -### 12.2 Backward Compatibility - -Add config option to disable auth: - -```yaml -# invokeai.yaml -auth_enabled: false # Legacy single-user mode -``` - -## 13. Rollout Strategy - -### 13.1 Beta Testing - -1. Internal testing with core team (1 week) -2. Closed beta with selected users (2 weeks) -3. Open beta announcement (2 weeks) -4. Stable release - -### 13.2 Communication Plan -- Blog post announcing feature -- Documentation updates -- Migration guide -- FAQ and troubleshooting -- Discord announcement - -### 13.3 Support Plan -- Monitor Discord for issues -- Create GitHub issues template for auth bugs -- Provide migration assistance -- Collect feedback for improvements - -## 14. Success Criteria - -- [ ] All unit tests pass (>90% coverage for new code) -- [ ] All integration tests pass -- [ ] Security review completed with no critical findings -- [ ] Performance benchmarks met (no more than 10% overhead) -- [ ] Documentation complete and reviewed -- [ ] Beta testing completed successfully -- [ ] Migration from single-user tested and verified -- [ ] Zero data loss incidents -- [ ] Positive feedback from beta users - -## 15. Risk Mitigation - -### 15.1 Technical Risks - -| Risk | Mitigation | -|------|------------| -| Database migration failures | Extensive testing, backup requirements, rollback procedures | -| Performance degradation | Index optimization, query profiling, load testing | -| Security vulnerabilities | Security review, penetration testing, CodeQL scans | -| Authentication bugs | Comprehensive testing, beta period, gradual rollout | - -### 15.2 User Experience Risks - -| Risk | Mitigation | -|------|------------| -| Migration confusion | Clear documentation, migration wizard, support channels | -| Login friction | Long session timeout, remember me option, clear messaging | -| Feature discoverability | Updated UI, tooltips, onboarding flow | - -## 16. Maintenance Plan - -### 16.1 Ongoing Support -- Monitor error logs for auth failures -- Regular security updates -- Password policy reviews -- Session management optimization - -### 16.2 Future Enhancements -- OAuth2/OpenID Connect -- Two-factor authentication -- Advanced permission system -- Team/group management -- Audit logging - -## 17. Conclusion - -This implementation plan provides a structured approach to adding multi-user support to InvokeAI. The phased approach allows for: - -1. **Incremental Development**: Build and test in small steps -2. **Early Validation**: Test core functionality early -3. **Risk Mitigation**: Identify issues before they become problems -4. **Quality Assurance**: Comprehensive testing at each phase -5. **User Focus**: Beta testing and feedback incorporation - -By following this plan, the development team can deliver a robust, secure, and user-friendly multi-user system while maintaining the quality and reliability that InvokeAI users expect. - -## 18. Quick Reference - -### Key Files to Create -- `migration_25.py` - Database migration -- `password_utils.py` - Password hashing -- `token_service.py` - JWT token management -- `users_base.py` - User service interface -- `users_default.py` - User service implementation -- `auth_dependencies.py` - FastAPI auth dependencies -- `routers/auth.py` - Authentication endpoints -- `authSlice.ts` - Frontend auth state -- `LoginPage.tsx` - Login UI component -- `ProtectedRoute.tsx` - Route protection - -### Key Files to Modify -- `api_app.py` - Register auth router -- `config_default.py` - Add auth config options -- `boards_default.py` - Add user filtering -- `images_default.py` - Add user filtering -- `main.tsx` - Add route protection -- All existing routers - Add auth dependencies - -### Commands -```bash -# Run tests -pytest tests/ -v - -# Run specific test suite -pytest tests/app/services/users/ -v - -# Run with coverage -pytest tests/ --cov=invokeai.app.services --cov-report=html - -# Run development server -python -m invokeai.app.run_app --dev_reload - -# Run database migration -python -m invokeai.app.migrate - -# Create new migration -python -m invokeai.app.create_migration "Add multi-user support" -``` - -### Useful Links -- [FastAPI Security Docs](https://fastapi.tiangolo.com/tutorial/security/) -- [JWT.io](https://jwt.io/) -- [OWASP Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html) -- [SQLite Foreign Keys](https://www.sqlite.org/foreignkeys.html) diff --git a/docs/multiuser/phase3_testing.md b/docs/multiuser/phase3_testing.md deleted file mode 100644 index 81bb0aa500b..00000000000 --- a/docs/multiuser/phase3_testing.md +++ /dev/null @@ -1,462 +0,0 @@ -# Phase 3: Authentication Middleware - Functional Testing Guide - -## Overview - -Phase 3 of the multiuser implementation adds authentication middleware and endpoints to InvokeAI. This document provides comprehensive testing instructions to validate the implementation. - -## Prerequisites - -1. **Development Environment Setup** - ```bash - # Install development dependencies - pip install -e ".[dev,test]" - ``` - -2. **Start InvokeAI in Development Mode** - ```bash - python -m invokeai.app.run_app --dev_reload - ``` - The server should start on `http://localhost:9090` - -## Automated Testing - -### Running Unit Tests - -The Phase 3 implementation includes comprehensive integration tests for all authentication endpoints. - -```bash -# Run all auth router tests -pytest tests/app/routers/test_auth.py -v - -# Run specific test -pytest tests/app/routers/test_auth.py::test_login_success -v - -# Run with coverage -pytest tests/app/routers/test_auth.py --cov=invokeai.app.api.routers.auth --cov-report=html -``` - -### Test Coverage - -The test suite covers: -- βœ… User login with valid credentials -- βœ… User login with "remember me" flag (7-day token expiration) -- βœ… Login failure with invalid password -- βœ… Login failure with nonexistent user -- βœ… Login failure with inactive user account -- βœ… User logout (stateless JWT) -- βœ… Getting current user information -- βœ… Initial admin setup -- βœ… Admin setup validation (prevents duplicate admins) -- βœ… Password strength validation -- βœ… Token validation and authentication -- βœ… Admin flag in JWT tokens - -## Manual Testing - -### 1. Testing Initial Admin Setup - -**Test Case:** Create the first admin user - -1. **Ensure no admin exists** (fresh database recommended) - -2. **Call the setup endpoint:** - ```bash - curl -X POST http://localhost:9090/api/v1/auth/setup \ - -H "Content-Type: application/json" \ - -d '{ - "email": "admin@invokeai.local", - "display_name": "Admin User", - "password": "AdminPass123" - }' - ``` - -3. **Expected Response (200 OK):** - ```json - { - "success": true, - "user": { - "user_id": "some-uuid", - "email": "admin@invokeai.local", - "display_name": "Admin User", - "is_admin": true, - "is_active": true, - "created_at": "2026-01-08T...", - "updated_at": "2026-01-08T...", - "last_login_at": null - } - } - ``` - -4. **Verify admin cannot be created again:** - ```bash - curl -X POST http://localhost:9090/api/v1/auth/setup \ - -H "Content-Type: application/json" \ - -d '{ - "email": "admin2@invokeai.local", - "display_name": "Second Admin", - "password": "AdminPass123" - }' - ``` - -5. **Expected Response (400 Bad Request):** - ```json - { - "detail": "Administrator account already configured" - } - ``` - -### 2. Testing User Login - -**Test Case:** Authenticate with valid credentials - -1. **Login with valid credentials:** - ```bash - curl -X POST http://localhost:9090/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{ - "email": "admin@invokeai.local", - "password": "AdminPass123", - "remember_me": false - }' - ``` - -2. **Expected Response (200 OK):** - ```json - { - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", - "user": { - "user_id": "some-uuid", - "email": "admin@invokeai.local", - "display_name": "Admin User", - "is_admin": true, - "is_active": true, - ... - }, - "expires_in": 86400 - } - ``` - -3. **Save the token** for subsequent requests (replace `YOUR_TOKEN` below) - -### 3. Testing Token Validation - -**Test Case:** Access protected endpoints with token - -1. **Get current user information:** - ```bash - curl -X GET http://localhost:9090/api/v1/auth/me \ - -H "Authorization: Bearer YOUR_TOKEN" - ``` - -2. **Expected Response (200 OK):** - ```json - { - "user_id": "some-uuid", - "email": "admin@invokeai.local", - "display_name": "Admin User", - "is_admin": true, - "is_active": true, - ... - } - ``` - -3. **Test without token (should fail):** - ```bash - curl -X GET http://localhost:9090/api/v1/auth/me - ``` - -4. **Expected Response (401 Unauthorized):** - ```json - { - "detail": "Missing authentication credentials" - } - ``` - -### 4. Testing Invalid Credentials - -**Test Case:** Login with wrong password - -1. **Attempt login with wrong password:** - ```bash - curl -X POST http://localhost:9090/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{ - "email": "admin@invokeai.local", - "password": "WrongPassword", - "remember_me": false - }' - ``` - -2. **Expected Response (401 Unauthorized):** - ```json - { - "detail": "Incorrect email or password" - } - ``` - -### 5. Testing "Remember Me" Feature - -**Test Case:** Verify extended token expiration - -1. **Login with remember_me=true:** - ```bash - curl -X POST http://localhost:9090/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{ - "email": "admin@invokeai.local", - "password": "AdminPass123", - "remember_me": true - }' - ``` - -2. **Verify expires_in is 604800 (7 days):** - ```json - { - "token": "...", - "user": {...}, - "expires_in": 604800 - } - ``` - -### 6. Testing Logout - -**Test Case:** User logout (stateless, client-side operation) - -1. **Call logout endpoint:** - ```bash - curl -X POST http://localhost:9090/api/v1/auth/logout \ - -H "Authorization: Bearer YOUR_TOKEN" - ``` - -2. **Expected Response (200 OK):** - ```json - { - "success": true - } - ``` - - **Note:** Since we use stateless JWT tokens, logout is currently a no-op on the server side. The client should discard the token. Future implementations may add token blacklisting. - -### 7. Testing Password Validation - -**Test Case:** Weak password should be rejected - -1. **Attempt setup with weak password:** - ```bash - curl -X POST http://localhost:9090/api/v1/auth/setup \ - -H "Content-Type: application/json" \ - -d '{ - "email": "admin@invokeai.local", - "display_name": "Admin User", - "password": "weak" - }' - ``` - -2. **Expected Response (400 Bad Request):** - ```json - { - "detail": "Password must be at least 8 characters long" - } - ``` - -## Testing with OpenAPI/Swagger UI - -InvokeAI includes interactive API documentation that can be used for testing: - -1. **Open Swagger UI:** - Navigate to `http://localhost:9090/docs` - -2. **Test the setup endpoint:** - - Find `POST /api/v1/auth/setup` in the API list - - Click "Try it out" - - Enter the request body and execute - - Review the response - -3. **Test authentication flow:** - - Call `POST /api/v1/auth/login` - - Copy the returned token - - Click "Authorize" button (πŸ”“ icon at top) - - Enter: `Bearer YOUR_TOKEN` - - Now you can test protected endpoints like `GET /api/v1/auth/me` - -## Security Testing - -### 1. Token Expiration - -**Test Case:** Verify tokens expire correctly - -1. Generate a token with short expiration (modify `TOKEN_EXPIRATION_NORMAL` in code for testing) -2. Wait for expiration time to pass -3. Attempt to use expired token -4. Expected: 401 Unauthorized with "Invalid or expired authentication token" - -### 2. Invalid Token Format - -**Test Case:** Malformed tokens should be rejected - -```bash -curl -X GET http://localhost:9090/api/v1/auth/me \ - -H "Authorization: Bearer invalid_token_format" -``` - -Expected: 401 Unauthorized - -### 3. SQL Injection Prevention - -**Test Case:** Malicious input should be sanitized - -```bash -curl -X POST http://localhost:9090/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{ - "email": "admin@invokeai.local OR 1=1--", - "password": "anything", - "remember_me": false - }' -``` - -Expected: 401 Unauthorized (not SQL error) - -## Database Verification - -### Verify Users Table Created - -```bash -# Connect to SQLite database -sqlite3 invokeai.db - -# Check users table structure -.schema users - -# List all users -SELECT user_id, email, display_name, is_admin, is_active FROM users; - -# Exit -.quit -``` - -### Expected Schema - -```sql -CREATE TABLE users ( - user_id TEXT NOT NULL PRIMARY KEY, - email TEXT NOT NULL UNIQUE, - display_name TEXT, - password_hash TEXT NOT NULL, - is_admin BOOLEAN NOT NULL DEFAULT FALSE, - is_active BOOLEAN NOT NULL DEFAULT TRUE, - created_at DATETIME NOT NULL DEFAULT(STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), - updated_at DATETIME NOT NULL DEFAULT(STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), - last_login_at DATETIME -); -``` - -## Common Issues and Troubleshooting - -### Issue: "No module named 'passlib'" - -**Solution:** Install authentication dependencies -```bash -pip install passlib[bcrypt] python-jose[cryptography] -``` - -### Issue: "users service not found" - -**Solution:** Ensure the users service is registered in the invoker. Check `api/dependencies.py` initialization. - -### Issue: Migration fails - -**Solution:** Check migration 25 is registered in `sqlite_util.py` and run: -```bash -python -m invokeai.app.migrate -``` - -### Issue: Token always returns 401 - -**Solution:** -1. Verify SECRET_KEY is consistent between token creation and validation -2. Check system time is correct (JWT uses timestamp validation) -3. Verify token isn't expired - -## Test Results Checklist - -Use this checklist to verify Phase 3 implementation: - -- [ ] Migration 25 creates users table successfully -- [ ] Initial admin setup works (POST /api/v1/auth/setup) -- [ ] Cannot create second admin via setup endpoint -- [ ] User login works with valid credentials -- [ ] User login fails with invalid credentials -- [ ] User login fails with nonexistent user -- [ ] Token includes correct user information -- [ ] Remember me provides 7-day expiration -- [ ] Normal login provides 1-day expiration -- [ ] Protected endpoints require Bearer token -- [ ] GET /api/v1/auth/me returns current user -- [ ] Logout endpoint responds successfully -- [ ] Invalid tokens are rejected (401) -- [ ] Missing tokens are rejected (401) -- [ ] Password validation enforces strength requirements -- [ ] Admin flag is correctly stored and returned -- [ ] All automated tests pass - -## Performance Testing - -### Token Generation Performance - -```bash -# Time multiple token generations -time for i in {1..100}; do - curl -s -X POST http://localhost:9090/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{"email":"admin@invokeai.local","password":"AdminPass123","remember_me":false}' \ - > /dev/null -done -``` - -Expected: < 5 seconds for 100 logins (avg ~50ms per login) - -### Token Validation Performance - -```bash -# Get a token first -TOKEN=$(curl -s -X POST http://localhost:9090/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{"email":"admin@invokeai.local","password":"AdminPass123","remember_me":false}' | jq -r .token) - -# Time multiple validations -time for i in {1..100}; do - curl -s -X GET http://localhost:9090/api/v1/auth/me \ - -H "Authorization: Bearer $TOKEN" \ - > /dev/null -done -``` - -Expected: < 3 seconds for 100 validations (avg ~30ms per validation) - -## Success Criteria - -Phase 3 is complete when: - -βœ… All automated tests pass -βœ… All manual test cases succeed -βœ… Security tests show no vulnerabilities -βœ… Performance meets targets -βœ… Database schema is correct -βœ… API documentation is accurate -βœ… No regressions in existing functionality - -## Next Steps - -After Phase 3 is validated: - -1. **Phase 4:** Update existing services for multi-tenancy (boards, images, workflows) -2. **Phase 5:** Frontend authentication integration -3. **Phase 6:** UI updates for multi-user features - -## Support - -For issues or questions about Phase 3 implementation: -- Check the [Implementation Plan](implementation_plan.md) -- Review the [Specification](specification.md) -- Create a GitHub issue with the `multiuser` label diff --git a/docs/multiuser/phase3_verification.md b/docs/multiuser/phase3_verification.md deleted file mode 100644 index 2121f62dbe7..00000000000 --- a/docs/multiuser/phase3_verification.md +++ /dev/null @@ -1,470 +0,0 @@ -# Phase 3 Implementation Verification Report - -## Executive Summary - -**Status:** βœ… COMPLETE - -Phase 3 of the InvokeAI multiuser implementation (Authentication Middleware) has been successfully completed. All components specified in the implementation plan have been implemented, tested, and verified. - -**Implementation Date:** January 8, 2026 -**Implementation Branch:** `copilot/implement-phase-3-multiuser` - ---- - -## Implementation Checklist - -### Core Components - -#### 1. Auth Dependencies Module βœ… - -**File:** `invokeai/app/api/auth_dependencies.py` - -**Status:** Implemented and functional - -**Features:** -- βœ… `get_current_user()` - Extracts and validates Bearer token -- βœ… `require_admin()` - Enforces admin-only access -- βœ… Type aliases `CurrentUser` and `AdminUser` for route dependencies -- βœ… Proper error handling with appropriate HTTP status codes -- βœ… User account validation (checks is_active status) - -**Code Quality:** -- Well-documented with comprehensive docstrings -- Follows FastAPI dependency injection pattern -- Proper use of type hints -- Appropriate error messages - -#### 2. Authentication Router βœ… - -**File:** `invokeai/app/api/routers/auth.py` - -**Status:** Implemented and functional - -**Endpoints:** -- βœ… `POST /v1/auth/login` - User authentication with email/password -- βœ… `POST /v1/auth/logout` - User logout (stateless JWT) -- βœ… `GET /v1/auth/me` - Get current user information -- βœ… `POST /v1/auth/setup` - Initial administrator setup - -**Features:** -- βœ… JWT token generation with configurable expiration -- βœ… "Remember me" functionality (1 day vs 7 days) -- βœ… Password strength validation -- βœ… Admin setup protection (one-time only) -- βœ… Comprehensive request/response models with Pydantic -- βœ… Email validation with special domain support - -**Code Quality:** -- All endpoints have proper type hints -- Comprehensive docstrings explaining functionality -- Appropriate HTTP status codes for all scenarios -- Clear error messages - -#### 3. Router Registration βœ… - -**File:** `invokeai/app/api_app.py` - -**Status:** Correctly registered - -**Verification:** -- βœ… Auth router imported in line 20 -- βœ… Router registered in line 126 with `/api` prefix -- βœ… Registered before other protected routes -- βœ… Comment explains purpose - -#### 4. Integration Tests βœ… - -**File:** `tests/app/routers/test_auth.py` - -**Status:** Comprehensive test coverage - -**Test Cases Implemented:** -1. βœ… `test_login_success` - Valid credentials authentication -2. βœ… `test_login_with_remember_me` - Extended token expiration -3. βœ… `test_login_invalid_password` - Invalid password handling -4. βœ… `test_login_nonexistent_user` - Nonexistent user handling -5. βœ… `test_login_inactive_user` - Inactive account handling -6. βœ… `test_logout` - Logout with valid token -7. βœ… `test_logout_without_token` - Logout without auth -8. βœ… `test_get_current_user_info` - Get user info with token -9. βœ… `test_get_current_user_info_without_token` - Requires auth -10. βœ… `test_get_current_user_info_invalid_token` - Invalid token handling -11. βœ… `test_setup_admin_first_time` - Initial admin creation -12. βœ… `test_setup_admin_already_exists` - Duplicate admin prevention -13. βœ… `test_setup_admin_weak_password` - Password validation -14. βœ… `test_admin_user_token_has_admin_flag` - Admin flag in token - -**Test Quality:** -- Uses proper pytest fixtures -- Follows existing test patterns in the codebase -- Includes helper functions for test data setup -- Tests both success and failure scenarios -- Validates HTTP status codes and response structure - -#### 5. Test Fixtures Update βœ… - -**File:** `tests/conftest.py` - -**Status:** Updated successfully - -**Changes:** -- βœ… Added import for `UserService` -- βœ… Added `users=UserService(db)` to `mock_services` fixture -- βœ… Ensures users table is created via migration 25 -- βœ… Maintains compatibility with existing tests - ---- - -## Prerequisites Verification - -### Dependencies βœ… - -All required dependencies from implementation plan are available: - -- βœ… `passlib[bcrypt]>=1.7.4` - Password hashing -- βœ… `python-jose[cryptography]>=3.3.0` - JWT tokens -- βœ… `email-validator>=2.0.0` - Email validation -- βœ… `python-multipart>=0.0.6` - Form data parsing - -**Location:** Specified in `pyproject.toml` - -### Phase 1 & 2 Dependencies βœ… - -Phase 3 correctly depends on completed Phase 1 and Phase 2 components: - -**Phase 1 (Database Schema):** -- βœ… Migration 25 creates users table -- βœ… Migration registered in `sqlite_util.py` -- βœ… Table includes all required fields - -**Phase 2 (Authentication Service):** -- βœ… `password_utils.py` - Password hashing and validation -- βœ… `token_service.py` - JWT token management -- βœ… `users_base.py` - User service interface -- βœ… `users_default.py` - User service implementation -- βœ… `users_common.py` - Shared DTOs and types - ---- - -## Code Quality Assessment - -### Style Compliance βœ… - -**Python Code:** -- βœ… Follows InvokeAI style guidelines -- βœ… Uses type hints throughout -- βœ… Line length within limits (120 chars) -- βœ… Absolute imports only -- βœ… Comprehensive docstrings - -**Test Code:** -- βœ… Follows pytest conventions -- βœ… Clear test names describing purpose -- βœ… Uses fixtures appropriately -- βœ… Consistent with existing test patterns - -### Security Considerations βœ… - -- βœ… Passwords are hashed with bcrypt -- βœ… JWT tokens use HMAC-SHA256 -- βœ… Password strength validation enforced -- βœ… Token expiration implemented -- βœ… SQL injection prevented (parameterized queries) -- βœ… Proper authentication error messages (no info leakage) - -**Security Notes:** -- ⚠️ SECRET_KEY is currently a placeholder (documented as TODO) -- ⚠️ Token invalidation not implemented (stateless JWT limitation noted in code) - -### Documentation βœ… - -- βœ… All functions have docstrings -- βœ… Complex logic is explained -- βœ… TODOs are marked for future improvements -- βœ… Security considerations documented -- βœ… API endpoints documented with Pydantic models - ---- - -## Testing Summary - -### Automated Tests - -**Location:** `tests/app/routers/test_auth.py` - -**Coverage:** 14 comprehensive test cases - -**Test Scenarios:** -- βœ… Success paths (login, logout, user info, setup) -- βœ… Failure paths (invalid credentials, missing tokens, weak passwords) -- βœ… Edge cases (duplicate admin, inactive users) -- βœ… Security (token validation, authentication requirements) - -**Expected Results:** All tests should pass (requires full environment setup) - -### Manual Testing - -**Documentation:** `docs/multiuser/phase3_testing.md` - -Provides comprehensive manual testing guide including: -- βœ… cURL examples for all endpoints -- βœ… Expected request/response formats -- βœ… Database verification steps -- βœ… Security testing scenarios -- βœ… Performance testing guidelines -- βœ… Troubleshooting guide - ---- - -## Alignment with Implementation Plan - -### Completed Items from Plan - -**Section 6: Phase 3 - Authentication Middleware (Week 3)** - -| Item | Plan Reference | Status | -|------|---------------|--------| -| Create Auth Dependencies | Section 6.1 | βœ… Complete | -| Create Authentication Router | Section 6.2 | βœ… Complete | -| Register Auth Router | Section 6.3 | βœ… Complete | -| Testing | Section 6.4 | βœ… Complete | - -### Deviations from Plan - -**None.** Implementation follows the plan exactly. - -**Enhancements beyond plan:** -- Added comprehensive integration test suite (14 tests) -- Created detailed functional testing documentation -- Enhanced error messages and validation -- Added type hints throughout - ---- - -## Integration Points - -### Existing Services βœ… - -Phase 3 correctly integrates with: - -- βœ… `ApiDependencies` - Uses invoker services pattern -- βœ… `UserService` - Authentication operations -- βœ… `SqliteDatabase` - Via migration system -- βœ… FastAPI routing - Properly registered -- βœ… OpenAPI schema - Endpoints auto-documented - -### Future Phases - -Phase 3 provides foundation for: - -- **Phase 4:** Multi-tenancy updates (CurrentUser dependency available) -- **Phase 5:** Frontend authentication (token-based auth ready) -- **Phase 6:** UI updates (admin flag in tokens) - ---- - -## Known Limitations - -### Documented in Code - -1. **Stateless JWT Tokens** - - Logout is client-side operation only - - No server-side token invalidation - - Future enhancement: token blacklist or session storage - -2. **SECRET_KEY Configuration** - - Currently a placeholder string - - TODO: Move to secure configuration system - - Not suitable for production without change - -3. **Token Expiration** - - Fixed to 1 or 7 days - - Not configurable at runtime - - Future enhancement: configurable expiration - -### Not Implemented (Out of Scope for Phase 3) - -- ❌ Password reset functionality (future enhancement) -- ❌ Two-factor authentication (future enhancement) -- ❌ OAuth2/OpenID Connect (future enhancement) -- ❌ Session management (future enhancement) -- ❌ Audit logging (future enhancement) - ---- - -## Deployment Considerations - -### Database Migration - -Migration 25 will run automatically on startup: -- Creates users table with proper schema -- Adds indexes for performance -- Creates triggers for updated_at -- Creates system user for backward compatibility - -### Backward Compatibility - -Phase 3 maintains backward compatibility: -- Existing endpoints continue to work -- No breaking changes to API -- Auth is added, not enforced on all routes (yet) -- System user created for legacy operations - -### Configuration - -No new configuration required for Phase 3: -- Uses existing database configuration -- Uses existing app configuration -- Auth endpoints available immediately - ---- - -## Recommendations - -### Before Merge - -1. **Update SECRET_KEY** - - Generate secure random key - - Add to configuration system - - Document key generation process - -2. **Run Full Test Suite** - - Ensure no regressions - - Verify all Phase 3 tests pass - - Check coverage meets targets - -3. **Security Review** - - Review JWT implementation - - Verify password hashing - - Check token validation logic - -### After Merge - -1. **Monitor Auth Endpoints** - - Track login failures - - Monitor token generation - - Watch for unusual patterns - -2. **Performance Testing** - - Benchmark auth endpoints - - Test concurrent users - - Verify database performance - -3. **Documentation Updates** - - Update API documentation - - Create user guide - - Document admin setup process - ---- - -## Conclusion - -Phase 3 (Authentication Middleware) is **COMPLETE** and ready for the next phase. - -**Achievements:** -- βœ… All planned components implemented -- βœ… Comprehensive test coverage -- βœ… Detailed documentation -- βœ… Security best practices followed -- βœ… Code quality standards met -- βœ… Integration with existing codebase -- βœ… Backward compatibility maintained - -**Ready for:** -- βœ… Code review -- βœ… Merge to main branch -- βœ… Phase 4 development - -**Blockers:** -- None - ---- - -## Sign-off - -**Implementation:** Complete -**Testing:** Complete -**Documentation:** Complete -**Quality:** Meets standards -**Security:** Acceptable with noted TODOs - -**Phase 3 Status:** βœ… READY FOR MERGE - ---- - -## Appendix A: File Listing - -### New Files Created - -1. `tests/app/routers/test_auth.py` - Integration tests (322 lines) -2. `docs/multiuser/phase3_testing.md` - Testing documentation -3. `docs/multiuser/phase3_verification.md` - This document - -### Files Modified - -1. `tests/conftest.py` - Added UserService to fixtures (2 lines added) - -### Existing Files from Previous Phases - -**Phase 1 Files (Database):** -- `invokeai/app/services/shared/sqlite_migrator/migrations/migration_25.py` - -**Phase 2 Files (Services):** -- `invokeai/app/services/auth/password_utils.py` -- `invokeai/app/services/auth/token_service.py` -- `invokeai/app/services/users/users_base.py` -- `invokeai/app/services/users/users_default.py` -- `invokeai/app/services/users/users_common.py` - -**Phase 3 Files (Middleware):** -- `invokeai/app/api/auth_dependencies.py` -- `invokeai/app/api/routers/auth.py` -- `invokeai/app/api_app.py` (modified - router registration) - ---- - -## Appendix B: Test Coverage Details - -### Test File Statistics - -- **Total Tests:** 14 -- **Lines of Code:** 322 -- **Helper Functions:** 2 -- **Test Fixtures Used:** 3 (client, mock_invoker, monkeypatch) - -### Coverage by Endpoint - -| Endpoint | Tests | Coverage | -|----------|-------|----------| -| POST /v1/auth/login | 5 | Success, remember_me, invalid_password, nonexistent_user, inactive_user | -| POST /v1/auth/logout | 2 | Success, without_token | -| GET /v1/auth/me | 3 | Success, without_token, invalid_token | -| POST /v1/auth/setup | 3 | First_time, already_exists, weak_password | -| Token validation | 1 | Admin flag verification | - -**Total Coverage:** 14 distinct test scenarios - ---- - -## Appendix C: API Endpoints Summary - -### Authentication Endpoints - -**Base Path:** `/api/v1/auth` - -| Method | Path | Auth Required | Admin Required | Description | -|--------|------|---------------|----------------|-------------| -| POST | `/login` | No | No | Authenticate user and get JWT token | -| POST | `/logout` | Yes | No | Logout current user (client-side) | -| GET | `/me` | Yes | No | Get current user information | -| POST | `/setup` | No | No | Create first admin user (one-time) | - -**Authentication Type:** Bearer Token (JWT) - -**Token Format:** `Authorization: Bearer ` - ---- - -*Document Version: 1.0* -*Last Updated: January 8, 2026* -*Author: GitHub Copilot* diff --git a/docs/multiuser/phase4_summary.md b/docs/multiuser/phase4_summary.md deleted file mode 100644 index fd526962704..00000000000 --- a/docs/multiuser/phase4_summary.md +++ /dev/null @@ -1,216 +0,0 @@ -# Phase 4 Implementation Summary - -## Overview - -Phase 4 of the InvokeAI multiuser support adds multi-tenancy to the core services, ensuring that users can only access their own data and data that has been explicitly shared with them. - -## Implementation Date - -January 8, 2026 - -## Changes Made - -### 1. Boards Service - -#### Updated Files -- `invokeai/app/services/board_records/board_records_base.py` -- `invokeai/app/services/board_records/board_records_sqlite.py` -- `invokeai/app/services/boards/boards_base.py` -- `invokeai/app/services/boards/boards_default.py` -- `invokeai/app/api/routers/boards.py` - -#### Key Changes -- Added `user_id` parameter to `save()`, `get_many()`, and `get_all()` methods -- Updated SQL queries to filter boards by user ownership, shared access, or public status -- Queries now use LEFT JOIN with `shared_boards` table to include boards shared with the user -- Added `CurrentUser` dependency to all board API endpoints -- Board creation now associates boards with the creating user -- Board listing returns only boards the user owns, boards shared with them, or public boards - -#### SQL Query Pattern -```sql -SELECT DISTINCT boards.* -FROM boards -LEFT JOIN shared_boards ON boards.board_id = shared_boards.board_id -WHERE (boards.user_id = ? OR shared_boards.user_id = ? OR boards.is_public = 1) -AND boards.archived = 0 -ORDER BY created_at DESC -``` - -### 2. Session Queue Service - -#### Updated Files -- `invokeai/app/services/session_queue/session_queue_common.py` -- `invokeai/app/services/session_queue/session_queue_base.py` -- `invokeai/app/services/session_queue/session_queue_sqlite.py` -- `invokeai/app/api/routers/session_queue.py` - -#### Key Changes -- Added `user_id` field to `SessionQueueItem` model -- Updated `ValueToInsertTuple` type alias to include `user_id` -- Modified `prepare_values_to_insert()` to accept and include `user_id` -- Updated `enqueue_batch()` method signature to accept `user_id` parameter -- Modified SQL INSERT statements to include `user_id` column -- Updated `retry_items_by_id()` to preserve `user_id` when retrying failed items -- Added `CurrentUser` dependency to `enqueue_batch` API endpoint - -### 3. Invocation Context - -#### Updated Files -- `invokeai/app/services/shared/invocation_context.py` - -#### Key Changes -- Updated `BoardsInterface.create()` to extract `user_id` from queue item and pass to boards service -- Updated `BoardsInterface.get_all()` to extract `user_id` from queue item and pass to boards service -- Invocations now automatically respect user ownership when creating or listing boards - -### 4. Images, Workflows, and Style Presets Routers - -#### Updated Files -- `invokeai/app/api/routers/images.py` -- `invokeai/app/api/routers/workflows.py` -- `invokeai/app/api/routers/style_presets.py` - -#### Key Changes -- Added `CurrentUser` import to all three routers -- Updated `upload_image` endpoint to require authentication -- Prepared routers for full multi-user filtering (to be completed in follow-up work) - -## Data Flow - -### Board Creation via API -1. User makes authenticated request to `POST /v1/boards/` -2. `CurrentUser` dependency extracts user_id from JWT token -3. Boards service creates board with `user_id` -4. Board is stored in database with user ownership - -### Board Creation via Invocation -1. User enqueues a batch with authenticated request -2. Session queue item is created with `user_id` from token -3. Invocation executes and calls `context.boards.create()` -4. Invocation context extracts `user_id` from queue item -5. Board is created with correct user ownership - -### Board Listing -1. User makes authenticated request to `GET /v1/boards/` -2. `CurrentUser` dependency provides user_id -3. SQL query returns: - - Boards owned by the user (`boards.user_id = user_id`) - - Boards shared with the user (`shared_boards.user_id = user_id`) - - Public boards (`boards.is_public = 1`) -4. Results are returned to user - -## Security Considerations - -### Access Control -- All board operations now require authentication -- Users can only see boards they own, boards shared with them, or public boards -- Board creation automatically associates with the creating user -- Session queue items track which user created them - -### Data Isolation -- Database queries use parameterized statements to prevent SQL injection -- User IDs are extracted from verified JWT tokens -- No board data leaks between users unless explicitly shared - -### Backward Compatibility -- Default `user_id` is "system" for backward compatibility -- Existing data from before multiuser support is owned by "system" user -- Migration 25 added user_id columns with default value of "system" - -## Testing - -### Test Coverage -- Created `tests/app/routers/test_boards_multiuser.py` -- Tests verify authentication requirements for board operations -- Tests verify board creation and listing with authentication -- Tests include isolation verification (placeholder for full implementation) - -### Manual Testing -To test manually: - -1. Setup admin user: -```bash -curl -X POST http://localhost:9090/api/v1/auth/setup \ - -H "Content-Type: application/json" \ - -d '{ - "email": "admin@test.com", - "display_name": "Admin", - "password": "TestPass123" - }' -``` - -2. Get authentication token: -```bash -curl -X POST http://localhost:9090/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{ - "email": "admin@test.com", - "password": "TestPass123" - }' -``` - -3. Create a board: -```bash -curl -X POST "http://localhost:9090/api/v1/boards/?board_name=My+Board" \ - -H "Authorization: Bearer " -``` - -4. List boards: -```bash -curl -X GET "http://localhost:9090/api/v1/boards/?all=true" \ - -H "Authorization: Bearer " -``` - -## Known Limitations - -### Not Yet Implemented -1. **User-based filtering for images**: While images are created through sessions (which now have user_id), direct image queries don't yet filter by user -2. **Workflow filtering**: Workflows need user_id and is_public filtering -3. **Style preset filtering**: Style presets need user_id and is_public filtering -4. **Admin bypass**: Admins should be able to see all data, not just their own - -### Future Enhancements -1. **Board sharing management**: API endpoints to share/unshare boards -2. **Permission levels**: Different access levels (read-only vs. edit) -3. **Bulk operations**: Update or delete multiple boards at once -4. **Audit logging**: Track who accessed or modified what - -## Migration Impact - -### Database -- Migration 25 (completed in Phase 1) added necessary columns -- No additional migrations needed for Phase 4 -- Existing data is accessible via "system" user - -### API Compatibility -- **Breaking Change**: All board operations now require authentication -- **Breaking Change**: Session queue enqueue now requires authentication -- Frontend will need to include auth tokens in all requests -- Existing scripts/tools must be updated to authenticate - -### Performance -- LEFT JOIN adds minor overhead to board queries -- Indexes on user_id columns provide good query performance -- No significant performance degradation expected - -## Next Steps - -### Immediate -1. Complete image filtering implementation -2. Complete workflow filtering implementation -3. Complete style preset filtering implementation -4. Add admin bypass for all operations -5. Expand test coverage - -### Future Phases -- Phase 5: Frontend authentication UI -- Phase 6: User management UI -- Phase 7: Board sharing UI -- Phase 8: Permission management - -## References - -- Implementation Plan: `docs/multiuser/implementation_plan.md` -- Database Migration: `invokeai/app/services/shared/sqlite_migrator/migrations/migration_25.py` -- Phase 3 Verification: `docs/multiuser/phase3_verification.md` diff --git a/docs/multiuser/phase4_verification.md b/docs/multiuser/phase4_verification.md deleted file mode 100644 index 5d4f593c055..00000000000 --- a/docs/multiuser/phase4_verification.md +++ /dev/null @@ -1,514 +0,0 @@ -# Phase 4 Implementation Verification Report - -## Executive Summary - -**Status:** βœ… COMPLETE - -Phase 4 of the InvokeAI multiuser implementation (Update Services for Multi-tenancy) has been successfully completed, tested, and verified. All components specified in the implementation plan have been implemented with surgical, minimal changes while maintaining backward compatibility. - -**Implementation Date:** January 8, 2026 -**Implementation Branch:** `copilot/implement-phase-4-multiuser` -**Status:** Ready for merge to `lstein-master` - ---- - -## Implementation Checklist - -### Core Services - -#### 1. Boards Service βœ… COMPLETE - -**Storage Layer:** -- βœ… Updated `BoardRecordStorageBase` interface with `user_id` parameters -- βœ… Implemented user filtering in `SqliteBoardRecordStorage` -- βœ… Added support for owned, shared, and public boards -- βœ… SQL queries use LEFT JOIN with `shared_boards` table - -**Service Layer:** -- βœ… Updated `BoardServiceABC` interface with `user_id` parameters -- βœ… Updated `BoardService` implementation to pass `user_id` through -- βœ… Maintained compatibility with existing callers - -**API Layer:** -- βœ… Added `CurrentUser` dependency to ALL board endpoints: - - βœ… `POST /v1/boards/` (create) - - βœ… `GET /v1/boards/{board_id}` (get) - - βœ… `PATCH /v1/boards/{board_id}` (update) - - βœ… `DELETE /v1/boards/{board_id}` (delete) - - βœ… `GET /v1/boards/` (list) - -**Invocation Context:** -- βœ… Updated `BoardsInterface.create()` to use queue item's `user_id` -- βœ… Updated `BoardsInterface.get_all()` to use queue item's `user_id` - -#### 2. Session Queue Service βœ… COMPLETE - -**Data Model:** -- βœ… Added `user_id` field to `SessionQueueItem` -- βœ… Updated `ValueToInsertTuple` type to include `user_id` -- βœ… Default value of "system" for backward compatibility - -**Service Layer:** -- βœ… Updated `SessionQueueBase.enqueue_batch()` signature -- βœ… Updated `prepare_values_to_insert()` to accept `user_id` -- βœ… Modified `SqliteSessionQueue.enqueue_batch()` implementation -- βœ… Updated `retry_items_by_id()` to preserve `user_id` - -**SQL:** -- βœ… Updated INSERT statements to include `user_id` column -- βœ… Both enqueue and retry operations include `user_id` - -**API Layer:** -- βœ… Added `CurrentUser` dependency to `enqueue_batch` endpoint -- βœ… `user_id` extracted from authenticated user - -#### 3. Router Updates βœ… PARTIAL - -**Images Router:** -- βœ… Added `CurrentUser` import -- βœ… Updated `upload_image` endpoint to require authentication -- ⚠️ Full filtering deferred to follow-up work - -**Workflows Router:** -- βœ… Added `CurrentUser` import -- ⚠️ Full filtering deferred to follow-up work - -**Style Presets Router:** -- βœ… Added `CurrentUser` import -- ⚠️ Full filtering deferred to follow-up work - ---- - -## Code Quality Assessment - -### Style Compliance βœ… - -**Python Code:** -- βœ… Follows InvokeAI style guidelines -- βœ… Uses type hints throughout -- βœ… Line length within limits (120 chars) -- βœ… Absolute imports only -- βœ… Comprehensive docstrings - -**SQL Queries:** -- βœ… Parameterized statements prevent SQL injection -- βœ… Clear formatting with inline comments -- βœ… Proper use of LEFT JOIN for shared boards - -### Security Assessment βœ… - -**Authentication:** -- βœ… All board endpoints require authentication -- βœ… Session queue enqueue requires authentication -- βœ… JWT tokens verified before extracting user_id -- βœ… User existence and active status checked - -**Data Isolation:** -- βœ… SQL queries filter by user_id -- βœ… Shared boards support via LEFT JOIN -- βœ… Public boards support via is_public flag -- βœ… No data leakage between users - -**Code Review:** -- βœ… Initial review completed -- βœ… Security issues addressed (added auth to all board endpoints) -- βœ… Final review passed with no issues - -**Security Scan:** -- βœ… CodeQL scan passed -- βœ… 0 vulnerabilities found -- βœ… No SQL injection risks -- βœ… No authentication bypass risks - -### Documentation βœ… - -**Code Documentation:** -- βœ… All functions have docstrings -- βœ… Complex logic explained -- βœ… Breaking changes noted in docstrings - -**External Documentation:** -- βœ… `docs/multiuser/phase4_summary.md` created -- βœ… Implementation details documented -- βœ… SQL query patterns explained -- βœ… Security considerations listed -- βœ… Known limitations documented - ---- - -## Testing Summary - -### Automated Tests βœ… - -**Test File:** `tests/app/routers/test_boards_multiuser.py` - -**Test Coverage:** -1. βœ… `test_create_board_requires_auth` - Verify auth requirement for creation -2. βœ… `test_list_boards_requires_auth` - Verify auth requirement for listing -3. βœ… `test_create_board_with_auth` - Verify authenticated creation works -4. βœ… `test_list_boards_with_auth` - Verify authenticated listing works -5. βœ… `test_user_boards_are_isolated` - Verify board isolation (structure) -6. βœ… `test_enqueue_batch_requires_auth` - Verify queue auth requirement - -**Test Quality:** -- Uses standard pytest patterns -- Fixtures for test client and auth tokens -- Tests both success and failure scenarios -- Validates HTTP status codes - -### Manual Testing βœ… - -**Verified Scenarios:** -1. βœ… Admin user setup via `/auth/setup` -2. βœ… User login via `/auth/login` -3. βœ… Board creation requires auth token -4. βœ… Board listing requires auth token -5. βœ… Unauthenticated requests return 401 -6. βœ… Authenticated requests return correct data - ---- - -## Alignment with Implementation Plan - -### Completed from Plan βœ… - -**Section 7: Phase 4 - Update Services for Multi-tenancy** - -| Item | Plan Reference | Status | -|------|---------------|--------| -| Update Boards Service | Section 7.1 | βœ… Complete | -| Update Session Queue | Section 7.4 | βœ… Complete | -| Add user_id to methods | Throughout | βœ… Complete | -| SQL filtering by user | Throughout | βœ… Complete | -| API authentication | Throughout | βœ… Complete | -| Testing | Section 7.5 | βœ… Complete | - -### Deferred Items ⚠️ - -The following items are **intentionally deferred** to follow-up work to keep changes minimal: - -1. **Images Service Full Filtering** (Section 7.2) - - Authentication added to upload endpoint - - Full filtering deferred - -2. **Workflows Service Full Filtering** (Section 7.3) - - Authentication import added - - Full filtering deferred - -3. **Style Presets Filtering** (implied in Section 7) - - Authentication import added - - Full filtering deferred - -4. **Admin Bypass** - - Not yet implemented - - Admins currently see only their own data - -5. **Ownership Verification** - - Endpoints require auth but don't verify ownership yet - - Users can potentially access any board ID if they know it - -**Rationale for Deferral:** -- Keep Phase 4 focused and surgical -- Reduce risk of breaking changes -- Allow for incremental testing and rollout -- Foundation is in place for follow-up work - ---- - -## Data Flow Verification - -### Board Creation via API βœ… - -``` -User β†’ POST /v1/boards/ with Bearer token - β†’ CurrentUser dependency extracts user_id from JWT - β†’ boards.create(board_name, user_id) - β†’ BoardService.create() - β†’ board_records.save(board_name, user_id) - β†’ INSERT INTO boards (board_id, board_name, user_id) VALUES (?, ?, ?) - β†’ Board created with user ownership -``` - -### Board Creation via Invocation βœ… - -``` -User β†’ POST /v1/queue/{queue_id}/enqueue_batch with Bearer token - β†’ CurrentUser extracts user_id - β†’ session_queue.enqueue_batch(queue_id, batch, prepend, user_id) - β†’ INSERT INTO session_queue (..., user_id) VALUES (..., ?) - β†’ Invocation executes - β†’ context.boards.create(board_name) - β†’ BoardsInterface extracts user_id from queue_item - β†’ boards.create(board_name, user_id) - β†’ Board created with correct ownership -``` - -### Board Listing βœ… - -``` -User β†’ GET /v1/boards/?all=true with Bearer token - β†’ CurrentUser extracts user_id - β†’ boards.get_all(user_id, order_by, direction) - β†’ SQL: SELECT DISTINCT boards.* - FROM boards - LEFT JOIN shared_boards ON boards.board_id = shared_boards.board_id - WHERE (boards.user_id = ? OR shared_boards.user_id = ? OR boards.is_public = 1) - β†’ Returns owned + shared + public boards -``` - ---- - -## Breaking Changes - -### API Changes ⚠️ - -**All board endpoints now require authentication:** -- `POST /v1/boards/` - Create board -- `GET /v1/boards/` - List boards -- `GET /v1/boards/{board_id}` - Get board -- `PATCH /v1/boards/{board_id}` - Update board -- `DELETE /v1/boards/{board_id}` - Delete board - -**Session queue changes:** -- `POST /v1/queue/{queue_id}/enqueue_batch` - Requires authentication - -**Images changes:** -- `POST /v1/images/upload` - Requires authentication - -### Migration Impact - -**Database:** -- No additional migrations needed (Migration 25 from Phase 1 sufficient) -- Existing data owned by "system" user -- New data owned by creating user - -**Frontend:** -- Must include `Authorization: Bearer ` in all requests -- Must handle 401 Unauthorized responses -- Should implement login flow before accessing boards - -**API Clients:** -- Must authenticate before making requests -- Must store and include JWT tokens -- Must handle token expiration - ---- - -## Performance Considerations - -### Query Performance βœ… - -**Boards Listing:** -- LEFT JOIN adds minimal overhead -- Indexes on `user_id` columns provide good performance -- DISTINCT handles duplicate rows from JOIN efficiently - -**Measured Impact:** -- No significant performance degradation expected -- Indexes ensure sub-millisecond query times for typical datasets -- Concurrent user support via database connection pooling - -### Memory Impact βœ… - -- SessionQueueItem size increased by 1 string field (user_id) -- ValueToInsertTuple increased by 1 element -- Minimal memory overhead overall - ---- - -## Known Issues and Limitations - -### Current Limitations - -1. **No Ownership Verification** - - Endpoints require auth but don't verify ownership - - Users could access boards if they know the ID - - **Impact**: Medium security concern - - **Mitigation**: Will be addressed in follow-up PR - -2. **No Admin Bypass** - - Admins see only their own data - - No way to view/manage all users' data - - **Impact**: Limits admin capabilities - - **Mitigation**: Will be added in follow-up PR - -3. **Incomplete Service Filtering** - - Images, workflows, style presets not fully filtered - - Only authentication requirements added - - **Impact**: Minimal (accessed through boards typically) - - **Mitigation**: Will be completed in follow-up PR - -4. **No Board Sharing UI** - - Database supports sharing but no API endpoints - - Cannot share boards between users yet - - **Impact**: Feature incomplete - - **Mitigation**: Planned for Phase 7 - -### Non-Issues - -βœ… **Not a Bug - System User:** -- "system" user is intentional for backward compatibility -- Existing data remains accessible -- New installations create admin during setup - -βœ… **Not a Bug - Default user_id:** -- Default "system" ensures backward compatibility -- Prevents null values in database -- Allows gradual migration - ---- - -## Security Analysis - -### Threat Model - -**Threats Mitigated:** -- βœ… Unauthorized board access prevented by auth requirement -- βœ… SQL injection prevented by parameterized queries -- βœ… Cross-user data leakage prevented by filtering -- βœ… Token forgery prevented by JWT signature verification - -**Remaining Risks:** -- ⚠️ Board ID enumeration possible (no ownership check) -- ⚠️ Shared board permissions not enforced -- ⚠️ No rate limiting on API endpoints -- ⚠️ No audit logging of access - -**Risk Assessment:** -- Current implementation: Medium-Low risk -- After follow-up work: Low risk -- For intended use case: Acceptable - ---- - -## Recommendations - -### Before Merge βœ… - -1. βœ… Code review completed -2. βœ… Security scan completed -3. βœ… Tests created -4. βœ… Documentation written -5. βœ… Breaking changes documented - -### After Merge - -1. **Immediate Follow-up:** - - Add ownership verification to board endpoints - - Add admin bypass functionality - - Complete image/workflow/style preset filtering - -2. **Short-term:** - - Implement board sharing APIs - - Add audit logging - - Add rate limiting - -3. **Long-term:** - - Frontend authentication UI (Phase 5) - - User management UI (Phase 6) - - Board sharing UI (Phase 7) - ---- - -## Conclusion - -Phase 4 (Update Services for Multi-tenancy) is **COMPLETE** and **READY FOR MERGE**. - -**Achievements:** -- βœ… All planned Phase 4 features implemented -- βœ… Surgical, minimal changes to codebase -- βœ… Backward compatibility maintained -- βœ… Security best practices followed -- βœ… Comprehensive testing and documentation -- βœ… Code review passed -- βœ… Security scan passed (0 vulnerabilities) - -**Ready for:** -- βœ… Merge to `lstein-master` branch -- βœ… Phase 5 development (Frontend authentication) -- βœ… Production deployment (with frontend updates) - -**Blockers:** -- None - ---- - -## Sign-off - -**Implementation:** βœ… Complete -**Testing:** βœ… Complete -**Documentation:** βœ… Complete -**Code Review:** βœ… Passed -**Security Scan:** βœ… Passed (0 vulnerabilities) -**Quality:** βœ… Meets standards - -**Phase 4 Status:** βœ… READY FOR MERGE - ---- - -## Appendix A: SQL Queries - -### Board Listing Query - -```sql -SELECT DISTINCT boards.* -FROM boards -LEFT JOIN shared_boards ON boards.board_id = shared_boards.board_id -WHERE (boards.user_id = ? OR shared_boards.user_id = ? OR boards.is_public = 1) -AND boards.archived = 0 -ORDER BY created_at DESC -LIMIT ? OFFSET ? -``` - -### Board Count Query - -```sql -SELECT COUNT(DISTINCT boards.board_id) -FROM boards -LEFT JOIN shared_boards ON boards.board_id = shared_boards.board_id -WHERE (boards.user_id = ? OR shared_boards.user_id = ? OR boards.is_public = 1) -AND boards.archived = 0 -``` - -### Queue Item Insert - -```sql -INSERT INTO session_queue ( - queue_id, session, session_id, batch_id, field_values, - priority, workflow, origin, destination, retried_from_item_id, user_id -) -VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) -``` - ---- - -## Appendix B: File Changes Summary - -**Total Files Changed:** 15 - -**Services (8):** -1. `board_records_base.py` - Added user_id to interface -2. `board_records_sqlite.py` - Implemented user filtering -3. `boards_base.py` - Added user_id to interface -4. `boards_default.py` - Pass user_id through -5. `session_queue_common.py` - Added user_id field and updated tuple -6. `session_queue_base.py` - Added user_id to enqueue signature -7. `session_queue_sqlite.py` - Implemented user tracking -8. `invocation_context.py` - Extract user_id from queue items - -**Routers (5):** -1. `boards.py` - All endpoints secured -2. `session_queue.py` - Enqueue secured -3. `images.py` - Upload secured -4. `workflows.py` - Auth import added -5. `style_presets.py` - Auth import added - -**Tests & Docs (2):** -1. `test_boards_multiuser.py` - New test suite -2. `phase4_summary.md` - Implementation documentation - ---- - -*Document Version: 1.0* -*Last Updated: January 8, 2026* -*Author: GitHub Copilot* diff --git a/docs/multiuser/phase5_testing.md b/docs/multiuser/phase5_testing.md deleted file mode 100644 index a0fa6bbef11..00000000000 --- a/docs/multiuser/phase5_testing.md +++ /dev/null @@ -1,475 +0,0 @@ -# Phase 5: Frontend Authentication Testing Guide - -## Overview - -This document provides comprehensive testing instructions for Phase 5 of the multiuser implementation - Frontend Authentication. - -**Status**: βœ… COMPLETE -**Implementation Date**: January 10, 2026 -**Implementation Branch**: `copilot/implement-phase-5-multiuser` - ---- - -## Components Implemented - -### 1. Redux State Management -- **Auth Slice** (`features/auth/store/authSlice.ts`) - - Manages authentication state (token, user, loading status) - - Persists token to localStorage - - Provides selectors for authentication status - -### 2. API Endpoints -- **Auth API** (`services/api/endpoints/auth.ts`) - - `POST /api/v1/auth/login` - User authentication - - `POST /api/v1/auth/logout` - User logout - - `GET /api/v1/auth/me` - Get current user info - - `POST /api/v1/auth/setup` - Initial administrator setup - -### 3. UI Components -- **LoginPage** - User authentication interface -- **AdministratorSetup** - Initial admin account creation -- **ProtectedRoute** - Route wrapper for authentication checking - -### 4. Routing -- Integrated react-router-dom -- `/login` - Login page -- `/setup` - Administrator setup -- `/*` - Protected application routes - ---- - -## Prerequisites - -### Backend Setup -Ensure Phases 1-4 are complete and the backend is running: -1. Backend must have migration 25 applied (users table exists) -2. Auth endpoints must be available at `/api/v1/auth/*` -3. Backend should be running on `localhost:9090` (default) - -### Frontend Setup -```bash -cd invokeai/frontend/web -pnpm install -pnpm build -``` - ---- - -## Manual Testing Scenarios - -### Scenario 1: Initial Setup Flow - -**Objective**: Verify administrator account creation on first launch. - -**Steps**: -1. Ensure no admin exists in database (fresh install or reset database) -2. Navigate to `http://localhost:5173/` (dev mode) or `http://localhost:9090/` (production) -3. Application should redirect to `/setup` -4. Fill in the administrator setup form: - - Email: `admin@test.com` - - Display Name: `Test Administrator` - - Password: `TestPassword123` (meets complexity requirements) - - Confirm Password: `TestPassword123` -5. Click "Create Administrator Account" - -**Expected Results**: -- Form validates password strength (8+ chars, uppercase, lowercase, numbers) -- Passwords must match -- On success, redirects to `/login` -- Admin account is created in database - -**Verification**: -```bash -# Check database for admin user -sqlite3 invokeai.db "SELECT user_id, email, display_name, is_admin FROM users WHERE email='admin@test.com';" -``` - ---- - -### Scenario 2: Login Flow - -**Objective**: Verify user can authenticate successfully. - -**Steps**: -1. Navigate to `http://localhost:5173/login` (or get redirected from main app) -2. Enter credentials: - - Email: `admin@test.com` - - Password: `TestPassword123` -3. Optional: Check "Remember me for 7 days" -4. Click "Sign In" - -**Expected Results**: -- Successful login redirects to main application (`/`) -- Token is stored in localStorage (key: `auth_token`) -- Redux state is updated with user information -- Authorization header is added to subsequent API requests - -**Verification**: -```javascript -// In browser console: -localStorage.getItem('auth_token') // Should return JWT token -``` - ---- - -### Scenario 3: Protected Routes - -**Objective**: Verify unauthenticated users cannot access the main application. - -**Steps**: -1. Clear localStorage: `localStorage.clear()` -2. Navigate to `http://localhost:5173/` - -**Expected Results**: -- Application redirects to `/login` -- Main application content is not displayed -- User cannot bypass authentication - ---- - -### Scenario 4: Token Persistence - -**Objective**: Verify token persists across browser sessions. - -**Steps**: -1. Login with "Remember me" checked -2. Close browser tab -3. Open new tab and navigate to application -4. Check if user is still authenticated - -**Expected Results**: -- User remains logged in -- No redirect to login page -- Application loads normally - ---- - -### Scenario 5: Logout Flow - -**Objective**: Verify user can logout successfully. - -**Steps**: -1. Login to application -2. Click logout button (to be implemented in Phase 6) -3. OR manually call logout: `dispatch(logout())` in browser console - -**Expected Results**: -- Token is removed from localStorage -- Redux state is cleared -- User is redirected to `/login` -- Cannot access protected routes without re-authenticating - -**Verification**: -```javascript -// In browser console: -localStorage.getItem('auth_token') // Should return null -``` - ---- - -### Scenario 6: Invalid Credentials - -**Objective**: Verify proper error handling for invalid credentials. - -**Steps**: -1. Navigate to login page -2. Enter invalid credentials: - - Email: `admin@test.com` - - Password: `WrongPassword` -3. Click "Sign In" - -**Expected Results**: -- Error message displayed: "Login failed. Please check your credentials." -- User remains on login page -- No token stored -- No navigation occurs - ---- - -### Scenario 7: Weak Password Validation (Setup) - -**Objective**: Verify password strength requirements are enforced. - -**Steps**: -1. Navigate to `/setup` -2. Try various weak passwords: - - `short` - Too short - - `alllowercase123` - No uppercase - - `ALLUPPERCASE123` - No lowercase - - `NoNumbers` - No digits - -**Expected Results**: -- Form validation prevents submission -- Appropriate error message displayed for each case -- "Create Administrator Account" button disabled when password is invalid - ---- - -### Scenario 8: API Authorization Headers - -**Objective**: Verify Authorization header is added to API requests. - -**Steps**: -1. Login successfully -2. Open browser DevTools β†’ Network tab -3. Perform any action that makes an API call (e.g., list boards) -4. Inspect request headers - -**Expected Results**: -- All API requests (except `/auth/login` and `/auth/setup`) include: - ``` - Authorization: Bearer - ``` -- Token matches value in localStorage - ---- - -## Automated Testing - -### Running Tests - -```bash -cd invokeai/frontend/web - -# Run all frontend tests -pnpm test:no-watch - -# Run with UI -pnpm test:ui - -# Run with coverage -pnpm test:no-watch --coverage -``` - -**Note**: Automated tests for Phase 5 components should be added in follow-up work. Current focus is on integration and manual testing. - ---- - -## Integration with Backend - -### Test with Running Backend - -1. Start backend server: -```bash -# From repository root -python -m invokeai.app.run_app -``` - -2. Start frontend dev server: -```bash -cd invokeai/frontend/web -pnpm dev -``` - -3. Navigate to `http://localhost:5173/` -4. Follow manual testing scenarios above - -### API Endpoint Testing - -Use cURL or Postman to test endpoints directly: - -```bash -# Setup admin -curl -X POST http://localhost:9090/api/v1/auth/setup \ - -H "Content-Type: application/json" \ - -d '{ - "email": "admin@test.com", - "display_name": "Administrator", - "password": "TestPassword123" - }' - -# Login -curl -X POST http://localhost:9090/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{ - "email": "admin@test.com", - "password": "TestPassword123", - "remember_me": true - }' - -# Get current user (requires token) -curl -X GET http://localhost:9090/api/v1/auth/me \ - -H "Authorization: Bearer " -``` - ---- - -## Known Limitations - -### Phase 5 Scope - -1. **No User Menu Yet**: Logout button and user menu UI are planned for Phase 6 -2. **No Session Expiration UI**: Token expires silently; user must refresh to see login page -3. **No "Forgot Password"**: Password reset is a future enhancement -4. **No Admin User Management UI**: User CRUD operations are planned for Phase 6 - -### Workarounds for Testing - -**Manual Logout**: -```javascript -// In browser console -localStorage.removeItem('auth_token'); -window.location.href = '/login'; -``` - -**Manual User Creation** (for testing multiple users): -```bash -# Use backend API directly -curl -X POST http://localhost:9090/api/v1/users \ - -H "Authorization: Bearer " \ - -H "Content-Type: application/json" \ - -d '{ - "email": "user@test.com", - "display_name": "Test User", - "is_admin": false - }' -``` - ---- - -## Troubleshooting - -### Issue: Redirect Loop - -**Symptoms**: Page keeps redirecting between `/` and `/login` - -**Solutions**: -1. Check if token exists but is invalid: - ```javascript - localStorage.removeItem('auth_token'); - ``` -2. Verify backend auth endpoints are accessible -3. Check browser console for errors - -### Issue: Token Not Persisting - -**Symptoms**: User logged out after page refresh - -**Solutions**: -1. Verify localStorage is enabled in browser -2. Check browser privacy settings (localStorage may be disabled) -3. Ensure token is being saved: - ```javascript - localStorage.getItem('auth_token') - ``` - -### Issue: CORS Errors - -**Symptoms**: API requests fail with CORS errors - -**Solutions**: -1. Ensure backend CORS is configured for `http://localhost:5173` -2. Check backend logs for CORS-related errors -3. Verify `api_app.py` has proper CORS middleware - -### Issue: 401 Unauthorized After Login - -**Symptoms**: API requests return 401 even after successful login - -**Solutions**: -1. Verify token is in Authorization header: - - Open DevTools β†’ Network β†’ Select request β†’ Headers -2. Check token is valid (not expired) -3. Ensure backend secret key matches between login and subsequent requests - ---- - -## Success Criteria - -Phase 5 is considered successful when: - -- βœ… Frontend builds without errors -- βœ… All TypeScript checks pass -- βœ… All ESLint checks pass -- βœ… All Prettier checks pass -- βœ… No circular dependencies detected -- βœ… Administrator setup flow works end-to-end -- βœ… Login flow works end-to-end -- βœ… Token persistence works across sessions -- βœ… Protected routes redirect to login when unauthenticated -- βœ… Authorization headers are added to API requests -- βœ… Password validation works correctly -- βœ… Error handling displays appropriate messages - ---- - -## Next Steps (Phase 6) - -Phase 6 will implement frontend UI updates including: -- User menu with logout button -- Admin indicators in UI -- Model management access control -- Queue filtering by user -- Session expiration handling -- Toast notifications for auth events - ---- - -## Appendix A: Component API Reference - -### AuthSlice - -**State Shape**: -```typescript -interface AuthState { - isAuthenticated: boolean; - token: string | null; - user: User | null; - isLoading: boolean; -} -``` - -**Actions**: -- `setCredentials({ token, user })` - Store auth credentials -- `logout()` - Clear auth credentials -- `setLoading(boolean)` - Update loading state - -**Selectors**: -- `selectIsAuthenticated(state)` - Get authentication status -- `selectCurrentUser(state)` - Get current user -- `selectAuthToken(state)` - Get token -- `selectIsAuthLoading(state)` - Get loading state - -### Auth API Hooks - -```typescript -// Login -const [login, { isLoading, error }] = useLoginMutation(); -await login({ email, password, remember_me }).unwrap(); - -// Logout -const [logout] = useLogoutMutation(); -await logout().unwrap(); - -// Get current user -const { data: user, isLoading, error } = useGetCurrentUserQuery(); - -// Setup -const [setup, { isLoading, error }] = useSetupMutation(); -await setup({ email, display_name, password }).unwrap(); -``` - ---- - -## Appendix B: File Locations - -### Frontend Files Created -- `src/features/auth/store/authSlice.ts` - Redux slice -- `src/features/auth/components/LoginPage.tsx` - Login UI -- `src/features/auth/components/AdministratorSetup.tsx` - Setup UI -- `src/features/auth/components/ProtectedRoute.tsx` - Route wrapper -- `src/services/api/endpoints/auth.ts` - API endpoints - -### Frontend Files Modified -- `src/app/components/InvokeAIUI.tsx` - Added BrowserRouter -- `src/app/components/App.tsx` - Added routing -- `src/app/store/store.ts` - Registered auth slice -- `src/services/api/index.ts` - Added auth headers -- `package.json` - Added react-router-dom -- `knip.ts` - Added auth files to ignore list - ---- - -*Document Version: 1.0* -*Last Updated: January 10, 2026* -*Author: GitHub Copilot* diff --git a/docs/multiuser/phase5_verification.md b/docs/multiuser/phase5_verification.md deleted file mode 100644 index fa699b776dc..00000000000 --- a/docs/multiuser/phase5_verification.md +++ /dev/null @@ -1,578 +0,0 @@ -# Phase 5 Implementation Verification Report - -## Executive Summary - -**Status:** βœ… COMPLETE - -Phase 5 of the InvokeAI multiuser implementation (Frontend Authentication) has been successfully completed. All components specified in the implementation plan have been implemented, tested, and verified. - -**Implementation Date:** January 10, 2026 -**Implementation Branch:** `copilot/implement-phase-5-multiuser` - ---- - -## Implementation Checklist - -### Core Components - -#### 1. Auth Slice βœ… - -**File:** `invokeai/frontend/web/src/features/auth/store/authSlice.ts` - -**Status:** Implemented and functional - -**Features:** -- βœ… Redux state management for authentication -- βœ… User interface with all required fields -- βœ… Token storage in localStorage -- βœ… `setCredentials` action for login -- βœ… `logout` action for clearing state -- βœ… `setLoading` action for loading states -- βœ… Zod schema for state validation -- βœ… Proper slice configuration with persist support -- βœ… Exported selectors for state access - -**Code Quality:** -- Well-documented with TypeScript types -- Follows Redux Toolkit patterns -- Proper use of slice configuration -- Clean state management - -#### 2. Auth API Endpoints βœ… - -**File:** `invokeai/frontend/web/src/services/api/endpoints/auth.ts` - -**Status:** Implemented and functional - -**Endpoints:** -- βœ… `useLoginMutation` - User authentication -- βœ… `useLogoutMutation` - User logout -- βœ… `useGetCurrentUserQuery` - Fetch current user -- βœ… `useSetupMutation` - Initial administrator setup - -**Features:** -- βœ… Proper request/response types -- βœ… Integration with RTK Query -- βœ… Error handling via RTK Query -- βœ… Type-safe API calls - -**Code Quality:** -- Clean API definitions -- Proper TypeScript typing -- Uses OpenAPI schema types -- Follows RTK Query patterns - -#### 3. Login Page Component βœ… - -**File:** `invokeai/frontend/web/src/features/auth/components/LoginPage.tsx` - -**Status:** Implemented and functional - -**Features:** -- βœ… Email/password input fields -- βœ… "Remember me" checkbox -- βœ… Form validation -- βœ… Loading states -- βœ… Error message display -- βœ… Dispatches credentials to Redux -- βœ… Uses Chakra UI components - -**Code Quality:** -- Proper use of React hooks -- Clean component structure -- Accessibility considerations (autoFocus, autoComplete) -- Error handling -- No arrow functions in JSX (uses useCallback) - -#### 4. Administrator Setup Component βœ… - -**File:** `invokeai/frontend/web/src/features/auth/components/AdministratorSetup.tsx` - -**Status:** Implemented and functional - -**Features:** -- βœ… Email, display name, password, confirm password fields -- βœ… Password strength validation -- βœ… Password match validation -- βœ… Form validation with error messages -- βœ… Helper text for requirements -- βœ… Loading states -- βœ… Redirects to login after success - -**Code Quality:** -- Comprehensive password validation -- Clear user feedback -- Proper form handling -- Error state management -- No arrow functions in JSX (uses useCallback) - -#### 5. Protected Route Component βœ… - -**File:** `invokeai/frontend/web/src/features/auth/components/ProtectedRoute.tsx` - -**Status:** Implemented and functional - -**Features:** -- βœ… Checks authentication status -- βœ… Redirects to login if not authenticated -- βœ… Supports admin-only routes (optional prop) -- βœ… Loading spinner during auth check -- βœ… Uses React Router for navigation - -**Code Quality:** -- Clean routing logic -- Proper use of useEffect -- Type-safe props -- Handles loading states - -#### 6. API Authorization Configuration βœ… - -**File:** `invokeai/frontend/web/src/services/api/index.ts` - -**Status:** Updated successfully - -**Changes:** -- βœ… Added `prepareHeaders` function to base query -- βœ… Extracts token from localStorage -- βœ… Adds Authorization header to all requests -- βœ… Excludes auth endpoints from authorization -- βœ… Uses Bearer token format - -**Code Quality:** -- Surgical changes -- Proper header management -- Conditional header addition -- No breaking changes to existing code - -#### 7. Routing Integration βœ… - -**Files Modified:** -- `invokeai/frontend/web/src/app/components/InvokeAIUI.tsx` -- `invokeai/frontend/web/src/app/components/App.tsx` - -**Status:** Implemented successfully - -**Features:** -- βœ… Installed react-router-dom (v7.12.0) -- βœ… BrowserRouter wraps application -- βœ… Routes defined for `/login`, `/setup`, `/*` -- βœ… Main app wrapped in ProtectedRoute -- βœ… Maintains existing error boundary -- βœ… Preserves global hooks and modals - -**Code Quality:** -- Minimal changes to existing structure -- Proper route hierarchy -- Maintains app architecture -- Clean routing setup - -#### 8. Store Configuration βœ… - -**File:** `invokeai/frontend/web/src/app/store/store.ts` - -**Status:** Updated successfully - -**Changes:** -- βœ… Imported authSliceConfig -- βœ… Added to SLICE_CONFIGS object -- βœ… Added to ALL_REDUCERS object -- βœ… Proper slice ordering (alphabetical) -- βœ… Redux state includes auth slice - -**Code Quality:** -- Follows existing patterns -- Proper configuration -- Type-safe integration -- No breaking changes - ---- - -## Code Quality Assessment - -### Style Compliance βœ… - -**TypeScript:** -- βœ… All files use strict TypeScript -- βœ… Proper type definitions -- βœ… No `any` types used -- βœ… Zod schemas for runtime validation - -**React:** -- βœ… Functional components with hooks -- βœ… Proper use of memo, useCallback, useState -- βœ… No arrow functions in JSX props -- βœ… Event handlers extracted to useCallback - -**Imports:** -- βœ… Sorted imports (ESLint simple-import-sort) -- βœ… Proper import grouping -- βœ… Type-only imports where appropriate - -### Linting & Build βœ… - -**ESLint:** -- βœ… Zero errors -- βœ… Zero warnings -- βœ… All rules passing - -**Prettier:** -- βœ… All files formatted correctly -- βœ… Consistent code style - -**TypeScript Compiler:** -- βœ… Zero errors -- βœ… Strict mode enabled -- βœ… All types properly defined - -**Knip (Unused Code Detection):** -- βœ… Auth files added to ignore list (exports will be used in follow-up) -- βœ… No critical unused code issues - -**Build:** -- βœ… Vite build succeeds -- βœ… No circular dependencies -- βœ… Bundle size reasonable -- βœ… All assets generated correctly - -### Security Considerations βœ… - -- βœ… Tokens stored in localStorage (acceptable for SPA) -- βœ… Authorization headers properly formatted -- βœ… Password validation enforces strong passwords -- βœ… No sensitive data in source code -- βœ… Proper error handling (no information leakage) -- βœ… HTTPS recommended for production (documented) - ---- - -## Testing Summary - -### Automated Tests - -**Status:** Framework ready, tests to be added in follow-up - -- Test infrastructure: Vitest configured -- Test colocations: Supported -- Coverage reporting: Available -- UI testing: Not yet implemented - -**Recommendation:** Add unit tests for auth slice actions and selectors in follow-up PR. - -### Manual Testing - -**Documentation:** `docs/multiuser/phase5_testing.md` - -Comprehensive manual testing guide created covering: -- βœ… Administrator setup flow -- βœ… Login flow -- βœ… Protected routes -- βœ… Token persistence -- βœ… Logout flow (manual) -- βœ… Invalid credentials -- βœ… Password validation -- βœ… API authorization headers - -**Test Environment:** -- Frontend dev server: `pnpm dev` β†’ http://localhost:5173 -- Backend server: `python -m invokeai.app.run_app` β†’ http://localhost:9090 -- Integration testing: Verified API connectivity - ---- - -## Alignment with Implementation Plan - -### Completed Items from Plan - -**Section 8: Phase 5 - Frontend Authentication (Week 6)** - -| Item | Plan Reference | Status | -|------|---------------|--------| -| Create Auth Slice | Section 8.1 | βœ… Complete | -| Create Login Page | Section 8.2 | βœ… Complete | -| Create Protected Route | Section 8.3 | βœ… Complete | -| Update API Configuration | Section 8.4 | βœ… Complete | -| Install react-router-dom | Implicit | βœ… Complete | -| Add routing to App | Implicit | βœ… Complete | - -### Enhancements Beyond Plan - -- Added Administrator Setup component (planned but not detailed) -- Created comprehensive testing documentation -- Added Zod schemas for runtime validation -- Proper TypeScript type safety throughout -- Knip configuration for unused code detection -- Proper event handler extraction (no JSX arrow functions) - -### Deviations from Plan - -**None.** Implementation follows the plan closely with appropriate enhancements. - ---- - -## Integration Points - -### Backend Integration βœ… - -Phase 5 frontend correctly integrates with: - -- βœ… Phase 1: Database schema (users table) -- βœ… Phase 2: Authentication service (password utils, token service) -- βœ… Phase 3: Authentication middleware (auth endpoints) -- βœ… Phase 4: Multi-tenancy services (user_id in requests) - -### Frontend Architecture βœ… - -- βœ… Redux store properly configured -- βœ… RTK Query for API calls -- βœ… React Router for navigation -- βœ… Chakra UI for components -- βœ… Consistent with existing patterns - -### Future Phases - -Phase 5 provides foundation for: - -- **Phase 6:** Frontend UI updates - - User menu with logout button - - Admin-only features UI - - Session expiration handling -- **Phase 7:** Board sharing UI - - Share dialog components - - Permission management UI - ---- - -## Known Limitations - -### Phase 5 Scope - -1. **No Logout Button in UI** - - Logout action exists but no UI button - - Planned for Phase 6 (user menu) - - Workaround: Manual logout via console - -2. **No Session Expiration Handling** - - Token expires silently - - No refresh mechanism - - No user notification - - Planned enhancement - -3. **No "Forgot Password" Flow** - - Future enhancement - - Not in Phase 5 scope - -4. **No OAuth2/SSO** - - Future enhancement - - Username/password only for now - -### Technical Limitations - -1. **LocalStorage Token Storage** - - Acceptable for SPA - - Vulnerable to XSS if site is compromised - - Mitigated by proper CSP headers (backend) - -2. **No Token Refresh** - - Tokens expire and user must re-login - - Refresh token flow is future enhancement - -3. **No Rate Limiting in UI** - - Backend should handle rate limiting - - Frontend shows generic errors - ---- - -## Dependencies - -### New Dependencies Added - -**react-router-dom v7.12.0:** -- Purpose: Client-side routing -- License: MIT -- Bundle impact: ~50kB (gzipped) -- Stable and well-maintained - -**No vulnerabilities detected** in new dependencies. - ---- - -## Performance Considerations - -### Bundle Size - -**Before Phase 5:** -- Main bundle: ~2.4MB (minified) -- ~700kB gzipped - -**After Phase 5:** -- Main bundle: ~2.484MB (minified) -- ~700.54kB gzipped -- **Impact:** +0.04kB gzipped (negligible) - -**Auth Components:** -- LoginPage: ~4kB -- AdministratorSetup: ~6kB -- ProtectedRoute: ~1.5kB -- Auth Slice: ~2kB -- Auth API: ~1.5kB - -Total auth code: ~15kB (before tree-shaking and gzip) - -### Runtime Performance - -- Auth check on route change: <1ms -- LocalStorage operations: <1ms -- No performance regressions detected - ---- - -## Recommendations - -### Before Merge βœ… - -1. βœ… Code review completed (self-review) -2. βœ… Build succeeds -3. βœ… All linters pass -4. βœ… Documentation created -5. βœ… Testing guide created - -### After Merge - -1. **Manual Testing Required:** - - Test with running backend - - Verify all flows end-to-end - - Test across browsers (Chrome, Firefox, Safari) - - Test responsive design (mobile, tablet, desktop) - -2. **Future Work:** - - Add unit tests for auth slice - - Add integration tests for auth flows - - Implement logout button (Phase 6) - - Add session expiration handling (Phase 6) - - Add user menu with profile (Phase 6) - -3. **Documentation:** - - Update user documentation - - Add screenshots to testing guide - - Create video walkthrough (optional) - ---- - -## Conclusion - -Phase 5 (Frontend Authentication) is **COMPLETE** and **READY FOR TESTING**. - -**Achievements:** -- βœ… All planned Phase 5 features implemented -- βœ… Clean, maintainable code -- βœ… Follows project conventions -- βœ… Zero linting/build errors -- βœ… Comprehensive documentation -- βœ… Ready for integration testing - -**Ready for:** -- βœ… Manual testing with backend -- βœ… Integration with Phase 4 backend -- βœ… Phase 6 development (UI updates) - -**Blockers:** -- None - ---- - -## Sign-off - -**Implementation:** βœ… Complete -**Build:** βœ… Passing -**Linting:** βœ… Passing -**Documentation:** βœ… Complete -**Quality:** βœ… Meets standards - -**Phase 5 Status:** βœ… READY FOR TESTING - ---- - -## Appendix A: File Summary - -### Files Created (11 total) - -**Frontend:** -1. `src/features/auth/store/authSlice.ts` - Redux state management (68 lines) -2. `src/features/auth/components/LoginPage.tsx` - Login UI (132 lines) -3. `src/features/auth/components/AdministratorSetup.tsx` - Setup UI (191 lines) -4. `src/features/auth/components/ProtectedRoute.tsx` - Route protection (46 lines) -5. `src/services/api/endpoints/auth.ts` - API endpoints (61 lines) - -**Documentation:** -6. `docs/multiuser/phase5_testing.md` - Testing guide -7. `docs/multiuser/phase5_verification.md` - This document - -### Files Modified (6 total) - -**Frontend:** -1. `src/app/components/InvokeAIUI.tsx` - Added BrowserRouter -2. `src/app/components/App.tsx` - Added routing logic -3. `src/app/store/store.ts` - Registered auth slice -4. `src/services/api/index.ts` - Added auth headers -5. `package.json` - Added react-router-dom dependency -6. `knip.ts` - Added auth files to ignore list - -### Package Changes - -**Added:** -- react-router-dom@7.12.0 - -**Updated:** -- pnpm-lock.yaml - ---- - -## Appendix B: Code Statistics - -**Lines of Code (LOC):** -- Auth slice: 68 lines -- Login page: 132 lines -- Setup page: 191 lines -- Protected route: 46 lines -- Auth API: 61 lines -- **Total new code:** ~498 lines - -**Files Modified:** -- InvokeAIUI: +2 lines -- App: +28 lines -- Store: +5 lines -- API index: +13 lines -- Knip: +2 lines - -**Test Coverage:** -- Unit tests: 0 (to be added) -- Integration tests: 0 (to be added) -- Manual test scenarios: 8 - ---- - -## Appendix C: Browser Compatibility - -### Tested Browsers - -**Recommended for testing:** -- Chrome 120+ βœ… -- Firefox 120+ βœ… -- Safari 17+ βœ… -- Edge 120+ βœ… - -**LocalStorage Support:** -- Required for token persistence -- Supported in all modern browsers -- May be disabled in private/incognito mode - -**React Router Support:** -- History API required -- Supported in all modern browsers -- No IE11 support (as expected) - ---- - -*Document Version: 1.0* -*Last Updated: January 10, 2026* -*Author: GitHub Copilot* diff --git a/docs/multiuser/phase6_summary.md b/docs/multiuser/phase6_summary.md deleted file mode 100644 index da73d999057..00000000000 --- a/docs/multiuser/phase6_summary.md +++ /dev/null @@ -1,222 +0,0 @@ -# Phase 6 Summary - Frontend UI Updates - -## Overview - -Phase 6 of the multiuser implementation adds essential UI components for user management and admin role restrictions. This phase implements the frontend interface changes specified in the multiuser implementation plan. - -## What Was Implemented - -### 1. UserMenu Component -A new dropdown menu component in the vertical navigation bar that displays: -- Current user's display name or email -- User's email address -- Admin badge (for administrator users only) -- Logout button with proper navigation - -**Location:** `invokeai/frontend/web/src/features/auth/components/UserMenu.tsx` - -**Key Features:** -- Integrates with Redux auth state -- Calls logout API endpoint -- Handles logout errors gracefully -- Navigates to login page after logout -- Clears local authentication state - -### 2. Model Manager Access Restrictions -Model Manager tab is now restricted to administrator users only: -- **Navigation Bar:** Models tab button only visible to admins -- **Tab Component:** Shows access denied message for non-admin users who navigate directly - -**Modified Files:** -- `invokeai/frontend/web/src/features/ui/components/VerticalNavBar.tsx` -- `invokeai/frontend/web/src/features/ui/components/tabs/ModelManagerTab.tsx` - -### 3. Translation Keys -Added internationalization support for new UI elements: -- `auth.userMenu` - User menu tooltip -- `auth.admin` - Admin badge text -- `auth.logout` - Logout button text -- `auth.adminOnlyFeature` - Access denied message - -**Modified File:** `invokeai/frontend/web/public/locales/en.json` - -## Technical Details - -### Implementation Approach -- **Minimal Changes:** Only modified necessary files -- **Surgical Updates:** Small, focused changes to existing components -- **Defense in Depth:** Frontend restrictions complement backend authorization -- **User Experience:** Clear feedback for access restrictions - -### Code Quality -- βœ… All linters pass (ESLint, Prettier, TypeScript, Knip, DPDM) -- βœ… Production build succeeds -- βœ… Zero errors or warnings -- βœ… Bundle size impact: +0.97kB gzipped (negligible) -- βœ… Follows project conventions (React hooks, TypeScript, no JSX arrow functions) - -### Integration -Phase 6 builds on previous phases: -- **Phase 5:** Uses auth slice, login/logout flow, protected routes -- **Phase 3-4:** Calls logout API endpoint, respects backend authorization -- **Phase 1-2:** Uses user data from database, validates auth tokens - -## Files Changed - -### Created (3 files) -1. `invokeai/frontend/web/src/features/auth/components/UserMenu.tsx` (77 lines) -2. `docs/multiuser/phase6_testing.md` (testing guide with 20 test scenarios) -3. `docs/multiuser/phase6_verification.md` (implementation verification report) - -### Modified (3 files) -1. `invokeai/frontend/web/src/features/ui/components/VerticalNavBar.tsx` (+4 lines) -2. `invokeai/frontend/web/src/features/ui/components/tabs/ModelManagerTab.tsx` (+15 lines) -3. `invokeai/frontend/web/public/locales/en.json` (+4 lines) - -**Total Code Changes:** ~100 lines (excluding documentation) - -## Testing - -### Automated Testing -- βœ… ESLint: 0 errors, 0 warnings -- βœ… Prettier: All files formatted -- βœ… TypeScript: 0 errors -- βœ… Build: Successful -- βœ… No circular dependencies - -### Manual Testing Required -Comprehensive testing guide created with 20 test scenarios covering: -- UserMenu display and functionality -- Admin badge appearance -- Logout flow -- Model Manager access restrictions -- Browser compatibility -- Accessibility -- Performance -- Security - -**Test Documentation:** `docs/multiuser/phase6_testing.md` - -## User Experience - -### For Admin Users -1. See user icon in navigation bar -2. Click to view user menu with admin badge -3. Can access Model Manager tab -4. Can logout via user menu - -### For Regular Users -1. See user icon in navigation bar -2. Click to view user menu (no admin badge) -3. Model Manager tab is hidden from navigation -4. Attempting direct URL access shows access denied message -5. Can logout via user menu - -## Security Considerations - -### Frontend Restrictions -- Models tab hidden for non-admin users -- Access denied message for direct URL access -- Logout clears all local authentication state - -### Backend Enforcement -- Backend authorization remains primary security layer -- Frontend restrictions are UX enhancements -- All model management endpoints require admin role on backend - -## Browser Compatibility - -Tested and supported browsers: -- Chrome 120+ -- Firefox 120+ -- Safari 17+ -- Edge 120+ - -## Performance Impact - -- Bundle size increase: +0.97kB gzipped (negligible) -- UserMenu render time: <1ms -- Logout action: <100ms (network dependent) -- No performance regressions detected - -## Known Limitations - -Not included in Phase 6 (planned for future phases): -- User profile editing -- Password change functionality -- User management UI (admin panel) -- Session expiration warnings -- Token refresh mechanism -- Multiple device session management - -## Next Steps - -### Immediate -1. Manual testing with running backend -2. Cross-browser testing -3. User acceptance testing - -### Phase 7 (Next) -1. User management UI (admin panel) -2. User CRUD operations -3. User role management -4. Board sharing interface - -## Dependencies - -**No new dependencies added.** Phase 6 uses existing packages: -- @invoke-ai/ui-library (Chakra UI) -- react-router-dom (navigation) -- react-i18next (translations) -- @reduxjs/toolkit (state management) - -## Migration Notes - -### For Existing Installations -- No database changes required (uses Phase 1-4 schema) -- No configuration changes needed -- Frontend changes are backwards compatible -- Users will see new UI elements after update - -### For Developers -- Follow existing patterns for adding user-specific features -- Use `selectCurrentUser` selector to access current user -- Use `user?.is_admin` for admin-only features -- Add translation keys for all user-facing text - -## Verification - -See detailed verification report: `docs/multiuser/phase6_verification.md` - -**Status:** βœ… COMPLETE and READY FOR TESTING - ---- - -## Quick Start for Testing - -1. **Start Backend:** - ```bash - python -m invokeai.app.run_app - ``` - -2. **Start Frontend:** - ```bash - cd invokeai/frontend/web - pnpm install - pnpm dev - ``` - -3. **Test Scenarios:** - - Log in as admin β†’ See admin badge, access Model Manager - - Log in as regular user β†’ No admin badge, no Model Manager access - - Test logout functionality - - Test navigation and UI responsiveness - -4. **Reference:** - - Testing guide: `docs/multiuser/phase6_testing.md` - - Verification report: `docs/multiuser/phase6_verification.md` - ---- - -*Implementation completed: January 12, 2026* -*Phase 6 of the multiuser implementation plan* diff --git a/docs/multiuser/phase6_testing.md b/docs/multiuser/phase6_testing.md deleted file mode 100644 index f12d46e73e9..00000000000 --- a/docs/multiuser/phase6_testing.md +++ /dev/null @@ -1,736 +0,0 @@ -# Phase 6 Testing Guide - Frontend UI Updates - -## Overview - -This document provides comprehensive testing instructions for Phase 6 of the multiuser implementation, which includes: -1. UserMenu component with logout functionality -2. Admin badge display -3. Model Manager access restrictions for non-admin users - -## Prerequisites - -### Backend Setup -1. Ensure the backend server is running with Phase 1-4 multiuser features: - ```bash - cd /path/to/InvokeAI - python -m invokeai.app.run_app - ``` - -2. Backend should be accessible at: `http://localhost:9090` - -### Test User Setup - -You'll need at least one admin user and one regular (non-admin) user for testing. - -**Option 1: Use the provided script (Recommended)** - -Add a regular user: -```bash -cd /path/to/InvokeAI -python scripts/add_user.py --email testuser@test.local --password TestPass123 --name "Test User" -``` - -Add an admin user: -```bash -python scripts/add_user.py --email admin@test.local --password AdminPass123 --name "Admin User" --admin -``` - -Interactive mode (prompts for details): -```bash -python scripts/add_user.py -``` - -**Option 2: Direct SQL (Advanced)** - -If you need to add a user directly to the database: -```bash -# Find your database file -python -c "from invokeai.app.services.config import InvokeAIAppConfig; print(InvokeAIAppConfig.get_config().db_path)" - -# Use sqlite3 to add a user (requires password hash) -sqlite3 /path/to/invokeai.db -``` - -Note: The script in Option 1 handles password hashing and validation automatically. - -### Frontend Setup -1. Install dependencies: - ```bash - cd invokeai/frontend/web - pnpm install - ``` - -2. Start the development server: - ```bash - pnpm dev - ``` - -3. Frontend should be accessible at: `http://localhost:5173` - -## Test Scenarios - -### Test 1: UserMenu Display for Admin User - -**Objective:** Verify UserMenu displays correctly for administrator users - -**Steps:** -1. Log in as an administrator user -2. Look at the vertical navigation bar on the left side -3. Locate the user icon button (above the bell icon) - -**Expected Results:** -- βœ… User icon button is visible in the vertical navigation bar -- βœ… User icon is positioned above the Notifications icon -- βœ… User icon has a tooltip showing "User Menu" - -**Test Data:** -- Admin email: (use your administrator account) -- Admin password: (use your administrator password) - ---- - -### Test 2: UserMenu Contents for Admin User - -**Objective:** Verify UserMenu dropdown shows correct information for admin users - -**Steps:** -1. Log in as an administrator user -2. Click the user icon in the vertical navigation bar -3. Inspect the dropdown menu contents - -**Expected Results:** -- βœ… Dropdown menu appears below the user icon -- βœ… User's display name is shown (or email if no display name) -- βœ… User's email is shown below the display name -- βœ… "Admin" badge is visible with yellow/gold color scheme -- βœ… "Logout" menu item is present with a sign-out icon - -**Screenshot Location:** `docs/multiuser/screenshots/phase6_usermenu_admin.png` - ---- - -### Test 3: UserMenu Contents for Regular User - -**Objective:** Verify UserMenu dropdown shows correct information for non-admin users - -**Steps:** -1. Create a regular (non-admin) user account via admin panel -2. Log out of admin account -3. Log in as the regular user -4. Click the user icon in the vertical navigation bar -5. Inspect the dropdown menu contents - -**Expected Results:** -- βœ… Dropdown menu appears below the user icon -- βœ… User's display name is shown (or email if no display name) -- βœ… User's email is shown below the display name -- βœ… "Admin" badge is NOT visible -- βœ… "Logout" menu item is present with a sign-out icon - -**Screenshot Location:** `docs/multiuser/screenshots/phase6_usermenu_regular.png` - ---- - -### Test 4: Logout Functionality - -**Objective:** Verify logout button correctly logs out the user - -**Steps:** -1. Log in as any user (admin or regular) -2. Click the user icon in the vertical navigation bar -3. Click the "Logout" menu item -4. Observe the behavior - -**Expected Results:** -- βœ… Backend logout API is called (`POST /api/v1/auth/logout`) -- βœ… User is redirected to the login page (`/login`) -- βœ… Auth token is removed from localStorage -- βœ… User cannot access protected routes without logging in again -- βœ… Attempting to navigate to `/` redirects to `/login` - -**Verification Commands (Browser Console):** -```javascript -// Before logout -console.log(localStorage.getItem('auth_token')); // Should show token - -// After logout -console.log(localStorage.getItem('auth_token')); // Should be null -``` - ---- - -### Test 5: Model Manager Tab - Admin Access - -**Objective:** Verify admin users can access and fully manage models in the Model Manager tab - -**Steps:** -1. Log in as an administrator user -2. Look at the vertical navigation bar -3. Locate the cube icon (Model Manager tab button) -4. Click the cube icon -5. Select a model from the list -6. Observe all available actions and UI elements - -**Expected Results:** -- βœ… Model Manager tab button (cube icon) is visible in the navigation bar -- βœ… Model Manager tab button is positioned above the Queue tab -- βœ… Clicking the button switches to the Model Manager tab -- βœ… Model Manager interface is displayed with: - - Model list panel on the left - - Model details panel on the right - - "Add Models" button when a model is selected - - Edit, Delete, Reidentify, Convert buttons visible - - Model image upload icon visible - - Save button visible for default settings - - Bulk delete action available in actions menu - -**Screenshot Location:** `docs/multiuser/screenshots/phase6_models_admin.png` - ---- - -### Test 6: Model Manager Tab - Non-Admin Read-Only Access - -**Objective:** Verify non-admin users have read-only access to browse and view models - -**Steps:** -1. Log in as a regular (non-admin) user -2. Look at the vertical navigation bar -3. Locate the cube icon (Model Manager tab button) -4. Click the cube icon -5. Browse through the model list -6. Select various models -7. Observe the UI elements and try to find any edit/delete actions - -**Expected Results:** -- βœ… Model Manager tab button (cube icon) IS visible -- βœ… Navigation shows Models tab for all users -- βœ… Model list is accessible and browsable -- βœ… Model details are viewable (name, description, path, settings) -- βœ… When a model is selected: - - Model metadata displayed correctly - - Default settings displayed (read-only) - - "Add Models" button is NOT visible - - Edit, Delete, Reidentify, Convert buttons are NOT visible - - Model image upload is NOT visible - - Save button for default settings is NOT visible - - Bulk actions menu is NOT visible (or shows no delete option) -- βœ… When no model is selected: - - Empty state message: "Select a model to view its details" - - Install Models panel is NOT shown - -**Screenshot Location:** `docs/multiuser/screenshots/phase6_models_readonly.png` - ---- - -### Test 7: Model Manager API - Backend Authorization - -**Objective:** Verify backend enforces admin-only access for model write operations - -**Steps:** -1. Log in as a regular (non-admin) user -2. Open browser DevTools β†’ Network tab -3. Try to interact with model management features (if buttons were somehow visible) -4. Or manually craft API requests to test backend authorization: - ```bash - # Get the auth token from localStorage - TOKEN=$(grep -o '"auth_token":"[^"]*"' ~/.cache/... | cut -d'"' -f4) - - # Try to update a model (should fail with 403) - curl -X PATCH http://localhost:9090/api/v1/model_manager/i/{model_key} \ - -H "Authorization: ******" \ - -H "Content-Type: application/json" \ - -d '{"name": "Modified Name"}' - - # Try to delete a model (should fail with 403) - curl -X DELETE http://localhost:9090/api/v1/model_manager/i/{model_key} \ - -H "Authorization: ******" - - # Try to read model details (should succeed with 200) - curl -X GET http://localhost:9090/api/v1/model_manager/i/{model_key} \ - -H "Authorization: ******" - ``` - -**Expected Results:** -- βœ… All write operations (PATCH, POST, PUT, DELETE) return 403 Forbidden -- βœ… Error message: "Admin privileges required" -- βœ… Read operations (GET) succeed with 200 OK -- βœ… Models are not modified despite API attempts -- βœ… Backend logs show authorization failures for non-admin write attempts - -**Note:** This verifies defense-in-depth security - even if frontend is bypassed, backend prevents unauthorized changes. - ---- - -### Test 8: Logout Persistence After Browser Refresh - -**Objective:** Verify logout state persists across browser refresh - -**Steps:** -1. Log in as any user -2. Click logout -3. Verify you're on the login page -4. Press browser refresh (F5 or Cmd+R) - -**Expected Results:** -- βœ… User remains on the login page -- βœ… No automatic login occurs -- βœ… User must re-enter credentials to access the app - ---- - -### Test 9: UserMenu Styling and Responsiveness - -**Objective:** Verify UserMenu UI elements are properly styled - -**Steps:** -1. Log in as any user -2. Click the user icon -3. Inspect the visual appearance of the menu - -**Expected Results:** -- βœ… User icon button has hover effect -- βœ… Dropdown menu has proper padding and spacing -- βœ… Text is legible and properly aligned -- βœ… Admin badge uses invokeYellow color scheme -- βœ… Logout menu item has hover effect -- βœ… Menu closes when clicking outside - -**Visual Checks:** -- Font sizes are appropriate (display name: sm, email: xs) -- Colors match the app theme -- Admin badge is noticeable but not overwhelming -- Icons are properly sized and aligned - ---- - -### Test 10: Accessibility Testing - -**Objective:** Verify UserMenu is accessible via keyboard - -**Steps:** -1. Log in as any user -2. Press Tab repeatedly to navigate through the interface -3. When user icon is focused, press Enter -4. Use arrow keys to navigate menu items -5. Press Enter on Logout - -**Expected Results:** -- βœ… User icon can be focused with Tab key -- βœ… User icon has visible focus indicator -- βœ… Enter key opens the menu -- βœ… Arrow keys navigate menu items -- βœ… Enter key on Logout logs out the user -- βœ… Escape key closes the menu -- βœ… All interactive elements have aria-label attributes - ---- - -## Browser Compatibility Testing - -Test the following scenarios in multiple browsers: - -### Supported Browsers -- Chrome 120+ -- Firefox 120+ -- Safari 17+ -- Edge 120+ - -### Key Features to Verify -1. UserMenu dropdown appearance and positioning -2. Logout functionality -3. Model Manager access restrictions -4. Smooth navigation transitions - ---- - -## Automated Testing - -### Running Frontend Linters - -```bash -cd invokeai/frontend/web - -# Run all linters -pnpm lint - -# Run individual linters -pnpm lint:eslint # ESLint checks -pnpm lint:prettier # Code formatting -pnpm lint:tsc # TypeScript type checks -pnpm lint:knip # Unused code detection -pnpm lint:dpdm # Circular dependency detection -``` - -**Expected Results:** -- βœ… All linters pass with no errors -- βœ… No warnings (eslint uses --max-warnings=0) -- βœ… No circular dependencies - -### Building the Frontend - -```bash -cd invokeai/frontend/web -pnpm build -``` - -**Expected Results:** -- βœ… Build completes successfully -- βœ… No TypeScript errors -- βœ… Assets are generated in `dist/` directory -- βœ… Bundle size is reasonable (~700kB gzipped for main bundle) - ---- - -## Integration Testing - -### Test 11: Multi-Tab Session Management - -**Objective:** Verify logout in one tab affects other tabs - -**Steps:** -1. Log in as any user -2. Open the app in a second browser tab -3. In Tab 1, click logout -4. Switch to Tab 2 and try to perform an action - -**Expected Results:** -- βœ… Tab 1 redirects to login page -- βœ… Tab 2's API calls fail with 401 Unauthorized -- βœ… Tab 2 should redirect to login page on next navigation - ---- - -### Test 12: Rapid Logout Clicks - -**Objective:** Verify logout handles rapid clicks gracefully - -**Steps:** -1. Log in as any user -2. Open UserMenu -3. Click Logout button multiple times rapidly - -**Expected Results:** -- βœ… No JavaScript errors in console -- βœ… Single logout API call is made (or duplicates are handled) -- βœ… User is redirected to login page only once -- βœ… No visual glitches or stuck states - ---- - -## Performance Testing - -### Test 13: UserMenu Performance - -**Objective:** Verify UserMenu doesn't impact performance - -**Checks:** -- βœ… UserMenu icon renders without delay -- βœ… Dropdown opens instantly (<100ms) -- βœ… Logout action is responsive -- βœ… No memory leaks (check with browser DevTools) - -**Browser DevTools:** -1. Open Performance tab -2. Record a session including: - - Opening UserMenu - - Closing UserMenu - - Logout -3. Check for: - - No long tasks (>50ms) - - No layout thrashing - - Proper cleanup after logout - ---- - -## Error Scenarios - -### Test 14: Backend Logout Failure - -**Objective:** Verify app handles backend logout errors gracefully - -**Steps:** -1. Log in as any user -2. Stop the backend server -3. Click logout in the UserMenu - -**Expected Results:** -- βœ… Frontend still removes token from localStorage -- βœ… User is redirected to login page -- βœ… No error dialogs or crashes -- βœ… Clean logout state - -**Rationale:** Client-side logout should succeed even if backend is unavailable. - ---- - -### Test 15: Missing User Data - -**Objective:** Verify UserMenu handles edge cases - -**Scenario 1: User with no display name** -- βœ… Shows email as primary text -- βœ… Still shows email as secondary text (duplicate is acceptable) - -**Scenario 2: User with very long email** -- βœ… Text truncates with ellipsis (noOfLines={1}) -- βœ… Dropdown width accommodates reasonably long text -- βœ… No horizontal scrolling - ---- - -## Regression Testing - -Verify that Phase 6 changes don't break existing functionality: - -### Test 16: Other Navigation Elements - -**Objective:** Verify other navigation buttons still work - -**Steps:** -1. Log in as any user -2. Test all navigation buttons in order: - - Generate tab - - Canvas tab - - Upscaling tab - - Workflows tab - - Queue tab - - (Models tab - if admin) - - Status indicator - - Notifications - - Videos modal - - Settings menu - -**Expected Results:** -- βœ… All buttons respond correctly -- βœ… All tabs load properly -- βœ… No layout shifts or overlapping elements -- βœ… Proper tab highlighting (active state) - ---- - -### Test 17: Settings Menu Functionality - -**Objective:** Verify Settings menu still works after adding UserMenu - -**Steps:** -1. Log in as any user -2. Click the Settings (gear) icon -3. Navigate through settings panels -4. Make a settings change -5. Close settings modal - -**Expected Results:** -- βœ… Settings modal opens correctly -- βœ… All settings panels are accessible -- βœ… Settings changes are saved -- βœ… No conflicts with UserMenu - ---- - -## Security Testing - -### Test 18: Direct Model Manager Access - -**Objective:** Verify backend enforces admin-only model operations - -**Steps:** -1. Log in as a regular user -2. Open browser DevTools β†’ Network tab -3. Try to access Model Manager tab (should see access denied) -4. Manually craft an API request to backend model endpoints: - ```javascript - // In browser console - fetch('/api/v1/models', { - headers: { - 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` - } - }).then(r => r.json()).then(console.log) - ``` - -**Expected Results:** -- βœ… Backend returns 403 Forbidden for model management endpoints -- βœ… Frontend cannot bypass restrictions via direct API calls -- βœ… Regular users cannot list, add, or delete models - -**Note:** Backend authorization is the primary security layer; frontend restrictions are UX enhancements. - ---- - -### Test 19: Token Removal on Logout - -**Objective:** Verify no auth tokens remain after logout - -**Steps:** -1. Log in as any user -2. Open DevTools β†’ Application β†’ Local Storage -3. Note the `auth_token` value -4. Click logout -5. Check Local Storage again - -**Expected Results:** -- βœ… `auth_token` is removed from localStorage -- βœ… No other auth-related data persists -- βœ… Redux state is cleared (if persisted) - ---- - -## Translation Testing - -### Test 20: Localization Keys - -**Objective:** Verify all UI text uses translation keys - -**Translation Keys Used:** -- `auth.userMenu` - User Menu tooltip -- `auth.admin` - Admin badge -- `auth.logout` - Logout button -- `auth.adminOnlyFeature` - Access denied message -- `modelManager.modelManager` - Model Manager heading -- `ui.tabs.models` - Models tab label - -**Steps:** -1. Verify all keys exist in `public/locales/en.json` -2. (Optional) Test with a different locale if available - -**Expected Results:** -- βœ… All translation keys are defined -- βœ… Text displays correctly in the UI -- βœ… No missing translation warnings in console - ---- - -## Known Issues and Limitations - -### Phase 6 Scope - -**Not Included in Phase 6:** -1. User profile editing -2. Password change functionality -3. Session expiration warnings -4. Multiple device session management -5. Admin user management UI - -**Planned for Future Phases:** -- Phase 7: User management and board sharing UI -- Phase 8: Enhanced session management -- Phase 9: Audit logging UI - ---- - -## Troubleshooting - -### Issue: UserMenu Not Appearing - -**Possible Causes:** -1. User not authenticated -2. Frontend not connected to backend -3. Auth token invalid or expired - -**Resolution:** -- Check browser console for errors -- Verify backend is running -- Try logging out and back in - ---- - -### Issue: Model Manager Tab Still Visible for Non-Admin - -**Possible Causes:** -1. User object not loaded in Redux state -2. Cached admin status from previous session -3. Frontend code not updated - -**Resolution:** -- Hard refresh (Ctrl+Shift+R) -- Clear browser cache and localStorage -- Verify `user.is_admin` value in Redux DevTools - ---- - -### Issue: Logout Doesn't Redirect to Login - -**Possible Causes:** -1. React Router not properly configured -2. Navigation hooks not working -3. JavaScript error preventing navigation - -**Resolution:** -- Check browser console for errors -- Verify React Router is installed and configured -- Check that `useNavigate` hook is working - ---- - -## Success Criteria - -Phase 6 is considered complete when: - -- βœ… UserMenu component displays correctly for all users -- βœ… Admin badge shows only for administrator users -- βœ… Logout functionality works reliably -- βœ… Model Manager tab is hidden for non-admin users -- βœ… Model Manager tab shows access denied for non-admin direct access -- βœ… All linters pass without errors -- βœ… Frontend builds successfully -- βœ… No visual regressions in existing UI -- βœ… All manual tests pass -- βœ… No critical accessibility issues - ---- - -## Documentation - -### Phase 6 Summary Document - -Create `phase6_verification.md` with: -- Implementation checklist -- Code quality assessment -- Test results summary -- Known limitations -- Integration points with other phases - ---- - -## Next Steps - -After Phase 6 completion: -1. Begin Phase 7: User Management UI (Admin panel) -2. Implement board sharing UI -3. Add user profile editing -4. Enhance session management - ---- - -## Appendix: API Endpoints Used - -### Logout -``` -POST /api/v1/auth/logout -Authorization: Bearer - -Response: -{ - "success": true -} -``` - -### Get Current User -``` -GET /api/v1/auth/me -Authorization: Bearer - -Response: -{ - "user_id": "...", - "email": "...", - "display_name": "...", - "is_admin": true/false, - "is_active": true/false -} -``` - ---- - -*Document Version: 1.0* -*Last Updated: January 12, 2026* -*Phase: 6 (Frontend UI Updates)* diff --git a/docs/multiuser/phase6_verification.md b/docs/multiuser/phase6_verification.md deleted file mode 100644 index 6e3b50ebc93..00000000000 --- a/docs/multiuser/phase6_verification.md +++ /dev/null @@ -1,637 +0,0 @@ -# Phase 6 Implementation Verification Report - -## Executive Summary - -**Status:** βœ… COMPLETE - -Phase 6 of the InvokeAI multiuser implementation (Frontend UI Updates) has been successfully completed. All components specified in the implementation plan have been implemented, tested, and verified. - -**Implementation Date:** January 12, 2026 -**Implementation Branch:** `copilot/implement-phase-6-multiuser` - ---- - -## Implementation Checklist - -### Core Components - -#### 1. UserMenu Component βœ… - -**File:** `invokeai/frontend/web/src/features/auth/components/UserMenu.tsx` - -**Status:** Implemented and functional - -**Features:** -- βœ… User icon button in vertical navigation bar -- βœ… Dropdown menu with user information -- βœ… Display name or email as primary text -- βœ… Email address as secondary text -- βœ… Admin badge for administrator users (yellow color scheme) -- βœ… Logout menu item with icon -- βœ… Proper tooltip on user icon -- βœ… Integration with Redux auth state -- βœ… Logout mutation with backend API call -- βœ… Navigation to login page after logout -- βœ… Local state cleanup on logout - -**Code Quality:** -- Well-documented with TypeScript types -- Uses React hooks (useCallback, memo) -- Proper error handling for logout -- No arrow functions in JSX props -- Clean component structure -- Accessibility attributes present - -**Key Implementation Details:** -```typescript -- Uses useLogoutMutation from RTK Query -- Dispatches logout action to clear Redux state -- Navigates to /login using React Router -- Cleans up localStorage token -- Shows different content based on user.is_admin -- Uses Chakra UI components for styling -``` - ---- - -#### 2. VerticalNavBar Integration βœ… - -**File:** `invokeai/frontend/web/src/features/ui/components/VerticalNavBar.tsx` - -**Status:** Updated successfully - -**Changes:** -- βœ… Imported UserMenu component -- βœ… Imported selectCurrentUser selector from auth slice -- βœ… Added useAppSelector hook to access current user -- βœ… Added UserMenu component to navigation bar -- βœ… Positioned UserMenu above Notifications -- βœ… Conditional rendering of Models tab based on user.is_admin -- βœ… Maintained existing layout and functionality - -**Code Quality:** -- Minimal changes to existing code -- Proper import organization -- Clean conditional rendering -- No breaking changes to other components - -**Visual Hierarchy (Bottom to Top):** -``` -SettingsMenu -VideosModalButton -Notifications -UserMenu (NEW) ---- -Divider ---- -Queue Tab -Models Tab (Admin Only - MODIFIED) -StatusIndicator -``` - ---- - -#### 3. Model Manager Access Restriction βœ… - -**File:** `invokeai/frontend/web/src/features/ui/components/tabs/ModelManagerTab.tsx` - -**Status:** Updated successfully - -**Changes:** -- βœ… Added useAppSelector hook to access current user -- βœ… Added conditional rendering based on user.is_admin -- βœ… Access denied message for non-admin users -- βœ… Proper heading and explanation text -- βœ… Maintains existing model manager UI for admin users - -**Access Denied UI:** -- Centered layout -- Large heading "Model Manager" -- Explanatory text: "This feature is only available to administrators." -- Proper spacing and styling -- Uses translation keys - -**Code Quality:** -- Clean conditional rendering -- Proper TypeScript types -- Uses useTranslation hook -- Maintains existing functionality for admins -- No breaking changes - ---- - -#### 4. Translation Keys βœ… - -**File:** `invokeai/frontend/web/public/locales/en.json` - -**Status:** Updated successfully - -**New Keys Added:** -```json -{ - "auth": { - "userMenu": "User Menu", - "admin": "Admin", - "logout": "Logout", - "adminOnlyFeature": "This feature is only available to administrators." - } -} -``` - -**Integration:** -- βœ… All keys used in components -- βœ… Proper translation paths -- βœ… Consistent with existing translation structure -- βœ… Ready for localization to other languages - ---- - -## Code Quality Assessment - -### Style Compliance βœ… - -**TypeScript:** -- βœ… All files use strict TypeScript -- βœ… Proper type definitions -- βœ… No `any` types used -- βœ… Proper imports from schemas - -**React:** -- βœ… Functional components with hooks -- βœ… Proper use of memo, useCallback -- βœ… No arrow functions in JSX props -- βœ… Event handlers extracted to useCallback - -**Imports:** -- βœ… Sorted imports (ESLint simple-import-sort) -- βœ… Proper import grouping -- βœ… Type-only imports where appropriate - -### Linting & Build βœ… - -**ESLint:** -- βœ… Zero errors -- βœ… Zero warnings -- βœ… All rules passing - -**Prettier:** -- βœ… All files formatted correctly -- βœ… Consistent code style - -**TypeScript Compiler:** -- βœ… Zero errors -- βœ… Strict mode enabled -- βœ… All types properly defined - -**Knip (Unused Code Detection):** -- βœ… No critical unused code issues -- βœ… One minor tag issue (pre-existing) - -**DPDM (Circular Dependencies):** -- βœ… No circular dependencies -- βœ… Clean dependency graph - -**Build:** -- βœ… Vite build succeeds -- βœ… No TypeScript errors -- βœ… Bundle size reasonable (~701kB gzipped for main bundle) -- βœ… All assets generated correctly - -### Security Considerations βœ… - -- βœ… Admin check on both frontend and backend (defense in depth) -- βœ… Frontend restrictions prevent UI confusion -- βœ… Backend authorization enforces security -- βœ… No sensitive data in source code -- βœ… Proper error handling (no information leakage) -- βœ… Logout clears all local state - ---- - -## Alignment with Implementation Plan - -### Completed Items from Plan - -**Section 9: Phase 6 - Frontend UI Updates (Week 7)** - -| Item | Plan Reference | Status | -|------|---------------|--------| -| Update App Root | Section 9.1 | N/A (Already done in Phase 5) | -| Add User Menu | Section 9.2 | βœ… Complete | -| Hide Model Manager for Non-Admin | Section 9.3 | βœ… Complete | -| Translation Keys | Implicit | βœ… Complete | - -### Enhancements Beyond Plan - -- Added UserMenu to VerticalNavBar (better UX than original plan) -- Added access denied message in ModelManagerTab (not just hiding) -- Proper logout API call with error handling -- Admin badge with appropriate color scheme -- Comprehensive testing documentation - -### Deviations from Plan - -**Placement of UserMenu:** -- Plan suggested updating App Root -- Implementation: Added to VerticalNavBar (better placement) -- Rationale: Keeps user controls in navigation area - -**Access Restriction:** -- Plan: Just hide/disable -- Implementation: Hide button + show access denied message -- Rationale: Defense in depth, better UX for direct URL access - ---- - -## Integration Points - -### Backend Integration βœ… - -Phase 6 frontend correctly integrates with: - -- βœ… Phase 2: Authentication service (logout endpoint) -- βœ… Phase 3: Authentication middleware (auth token validation) -- βœ… Phase 4: Multi-tenancy services (user_id in auth state) -- βœ… Phase 5: Frontend auth (auth slice, login/logout flow) - -### Frontend Architecture βœ… - -- βœ… Redux store properly accessed -- βœ… RTK Query for logout API call -- βœ… React Router for navigation -- βœ… Chakra UI for components -- βœ… Consistent with existing patterns - -### Future Phases - -Phase 6 provides foundation for: - -- **Phase 7:** User management UI - - Admin panel for user CRUD operations - - User list with search and filtering - - User role management -- **Phase 8:** Board sharing UI - - Share dialog components - - Permission management UI - - Shared board indicators - ---- - -## Testing Summary - -### Automated Tests - -**Linting:** -- βœ… ESLint: 0 errors, 0 warnings -- βœ… Prettier: All files formatted -- βœ… TypeScript: 0 errors -- βœ… Knip: No critical issues -- βœ… DPDM: No circular dependencies - -**Build:** -- βœ… Production build succeeds -- βœ… Bundle size: ~701kB gzipped (minimal increase) -- βœ… All assets generated - -### Manual Testing - -**Documentation:** `docs/multiuser/phase6_testing.md` - -Comprehensive manual testing guide created covering: -- βœ… UserMenu display for admin users -- βœ… UserMenu display for regular users -- βœ… Admin badge appearance -- βœ… Logout functionality -- βœ… Model Manager tab visibility -- βœ… Model Manager access denial -- βœ… Navigation bar layout -- βœ… Translation keys -- βœ… Accessibility -- βœ… Browser compatibility - -**Test Scenarios:** 20 comprehensive test cases - -**Coverage:** -- Functional testing -- UI/UX testing -- Security testing -- Performance testing -- Accessibility testing -- Error handling -- Regression testing - ---- - -## Known Limitations - -### Phase 6 Scope - -**Not Included in Phase 6:** -1. User profile editing -2. Password change functionality -3. User management UI (admin panel) -4. Session expiration warnings -5. Token refresh mechanism -6. Multiple device session management - -**Planned for Future Phases:** -- Phase 7: User management and board sharing UI -- Phase 8+: Enhanced session management, profile editing - -### Technical Limitations - -1. **No Token Refresh:** - - Tokens expire and user must re-login - - Refresh token flow is future enhancement - -2. **No Session Expiration UI:** - - Token expires silently - - No user notification - - Planned enhancement - -3. **No Multi-Device Logout:** - - Logout only affects current browser - - Server-side session tracking needed for multi-device logout - ---- - -## Performance Considerations - -### Bundle Size - -**Before Phase 6:** -- Main bundle: ~2.484MB (minified) -- ~700.54kB gzipped - -**After Phase 6:** -- Main bundle: ~2.488MB (minified) -- ~701.51kB gzipped -- **Impact:** +0.97kB gzipped (negligible) - -**Phase 6 Components:** -- UserMenu: ~2kB -- VerticalNavBar changes: ~0.5kB -- ModelManagerTab changes: ~0.5kB -- Translation keys: ~0.1kB - -Total Phase 6 code: ~3kB (before tree-shaking and gzip) - -### Runtime Performance - -- UserMenu render: <1ms -- Dropdown open: <50ms -- Logout action: <100ms (network dependent) -- No performance regressions detected -- No memory leaks - ---- - -## Recommendations - -### Before Merge βœ… - -1. βœ… Code review completed (self-review) -2. βœ… Build succeeds -3. βœ… All linters pass -4. βœ… Documentation created -5. βœ… Testing guide created - -### After Merge - -1. **Manual Testing Required:** - - Test with running backend - - Verify all flows end-to-end - - Test across browsers (Chrome, Firefox, Safari) - - Test responsive design (mobile, tablet, desktop) - - Verify admin vs regular user experiences - -2. **Integration Testing:** - - Test with real user accounts - - Verify logout across multiple tabs - - Test rapid logout clicks - - Verify Model Manager restrictions - -3. **User Acceptance Testing:** - - Get feedback from beta users - - Verify UX is intuitive - - Collect suggestions for improvements - -4. **Future Work:** - - Add unit tests for UserMenu component - - Add integration tests for logout flow - - Implement session expiration warnings (Phase 7+) - - Add user profile editing (Phase 7+) - - Enhance admin UI (Phase 7) - ---- - -## Conclusion - -Phase 6 (Frontend UI Updates) is **COMPLETE** and **READY FOR TESTING**. - -**Achievements:** -- βœ… All planned Phase 6 features implemented -- βœ… Clean, maintainable code -- βœ… Follows project conventions -- βœ… Zero linting/build errors -- βœ… Comprehensive documentation -- βœ… Ready for integration testing - -**Ready for:** -- βœ… Manual testing with backend -- βœ… Integration with Phase 1-5 backend -- βœ… User acceptance testing -- βœ… Phase 7 development (User Management UI) - -**Blockers:** -- None - ---- - -## Sign-off - -**Implementation:** βœ… Complete -**Build:** βœ… Passing -**Linting:** βœ… Passing -**Documentation:** βœ… Complete -**Quality:** βœ… Meets standards - -**Phase 6 Status:** βœ… READY FOR TESTING - ---- - -## Appendix A: File Summary - -### Files Created (3 total) - -**Frontend:** -1. `src/features/auth/components/UserMenu.tsx` - User menu component (77 lines) - -**Documentation:** -2. `docs/multiuser/phase6_testing.md` - Testing guide -3. `docs/multiuser/phase6_verification.md` - This document - -### Files Modified (3 total) - -**Frontend:** -1. `src/features/ui/components/VerticalNavBar.tsx` - Added UserMenu, conditional Models tab -2. `src/features/ui/components/tabs/ModelManagerTab.tsx` - Added access restriction -3. `public/locales/en.json` - Added translation keys - -### Package Changes - -**No new dependencies added** - Used existing packages: -- @invoke-ai/ui-library (Chakra UI components) -- react-router-dom (navigation) -- react-i18next (translations) -- Redux Toolkit (state management) - ---- - -## Appendix B: Code Statistics - -**Lines of Code (LOC):** -- UserMenu component: 77 lines -- VerticalNavBar changes: +4 lines -- ModelManagerTab changes: +15 lines -- Translation keys: +4 lines -- **Total new/modified code:** ~100 lines - -**Test Coverage:** -- Unit tests: 0 (to be added) -- Integration tests: 0 (to be added) -- Manual test scenarios: 20 - ---- - -## Appendix C: Implementation Timeline - -**Planning:** 30 minutes -- Reviewed implementation plan -- Analyzed existing code structure -- Identified integration points - -**Implementation:** 60 minutes -- Created UserMenu component (20 min) -- Updated VerticalNavBar (15 min) -- Updated ModelManagerTab (15 min) -- Added translation keys (5 min) -- Linting and testing (15 min) - -**Documentation:** 90 minutes -- Created testing guide (60 min) -- Created verification document (30 min) - -**Total Time:** ~3 hours - ---- - -## Appendix D: Browser Compatibility - -### Tested Browsers - -**Recommended for testing:** -- Chrome 120+ βœ… -- Firefox 120+ βœ… -- Safari 17+ βœ… -- Edge 120+ βœ… - -**Dependencies:** -- React Router: History API required -- LocalStorage: Required for token persistence -- Modern JavaScript: ES2020+ - -**Not Supported:** -- Internet Explorer (as expected) -- Older browsers without ES2020 support - ---- - -## Appendix E: Screenshots (To Be Added) - -Screenshots to be captured during manual testing: - -1. `phase6_usermenu_admin.png` - UserMenu dropdown for admin user -2. `phase6_usermenu_regular.png` - UserMenu dropdown for regular user -3. `phase6_models_admin.png` - Model Manager for admin user -4. `phase6_navbar_regular.png` - Navigation bar without Models tab (regular user) -5. `phase6_models_denied.png` - Access denied message for regular user - ---- - -## Appendix F: API Endpoints Used - -### Logout Endpoint -``` -POST /api/v1/auth/logout -Authorization: Bearer - -Response: 200 OK -{ - "success": true -} -``` - -**Error Handling:** -- Frontend handles failures gracefully -- Local state cleared regardless of backend response -- User redirected to login even if API call fails - ---- - -## Appendix G: Redux State Integration - -### Auth Slice (Existing) -```typescript -interface AuthState { - isAuthenticated: boolean; - token: string | null; - user: User | null; - isLoading: boolean; -} - -interface User { - user_id: string; - email: string; - display_name: string | null; - is_admin: boolean; - is_active: boolean; -} -``` - -### Selectors Used -- `selectCurrentUser` - Get current user object -- Used in UserMenu to display user info -- Used in VerticalNavBar to show/hide Models tab -- Used in ModelManagerTab to check admin status - ---- - -## Appendix H: Translation Keys Reference - -### New Keys in en.json - -```json -{ - "auth": { - "userMenu": "User Menu", - "admin": "Admin", - "logout": "Logout", - "adminOnlyFeature": "This feature is only available to administrators." - } -} -``` - -### Usage -- `auth.userMenu` β†’ UserMenu tooltip -- `auth.admin` β†’ Admin badge text -- `auth.logout` β†’ Logout menu item -- `auth.adminOnlyFeature` β†’ Access denied message -- `modelManager.modelManager` β†’ Model Manager heading (existing) -- `ui.tabs.models` β†’ Models tab label (existing) - ---- - -*Document Version: 1.0* -*Last Updated: January 12, 2026* -*Author: GitHub Copilot* diff --git a/docs/multiuser/phase7_summary.md b/docs/multiuser/phase7_summary.md deleted file mode 100644 index e197a79a1df..00000000000 --- a/docs/multiuser/phase7_summary.md +++ /dev/null @@ -1,413 +0,0 @@ -# Phase 7 Summary - Testing & Security - -## Executive Summary - -Phase 7 of the multiuser implementation successfully delivers comprehensive test coverage and security validation for the authentication system. This phase implements the testing requirements specified in the multiuser implementation plan at `docs/multiuser/implementation_plan.md` (Phase 7, lines 834-867). - -**Status:** βœ… **COMPLETE** - -## What Was Implemented - -### Comprehensive Test Suite (88 Tests) - -Phase 7 adds four new test modules with extensive coverage: - -1. **Password Utilities Tests** (`test_password_utils.py`) - 31 tests - - Password hashing with bcrypt - - Password verification - - Password strength validation - - Security properties (timing attacks, salt randomization) - -2. **Token Service Tests** (`test_token_service.py`) - 20 tests - - JWT token creation and verification - - Token expiration handling - - Token security (forgery prevention) - - Admin privilege preservation - -3. **Security Tests** (`test_security.py`) - 13 tests - - SQL injection prevention - - Authorization bypass prevention - - Session security - - Input validation (XSS, path traversal) - -4. **Data Isolation Tests** (`test_data_isolation.py`) - 11 tests - - Board isolation between users - - Queue item isolation - - Admin authorization - - Data integrity - -5. **Performance Tests** (`test_performance.py`) - 13 tests - - Authentication overhead measurement - - Concurrent user session handling - - Scalability benchmarks - -### Security Validation - -All major security attack vectors tested and verified as prevented: - -| Attack Vector | Result | Status | -|--------------|--------|--------| -| SQL Injection | βœ… Prevented | Parameterized queries | -| Token Forgery | βœ… Prevented | HMAC signature | -| Admin Escalation | βœ… Prevented | Token validation | -| XSS Attacks | βœ… Prevented | Safe data storage | -| Path Traversal | βœ… Prevented | Input validation | -| Auth Bypass | βœ… Prevented | Token verification | - -### Performance Benchmarks - -All performance targets met: - -| Metric | Target | Achieved | Status | -|--------|--------|----------|--------| -| Token Create | < 1ms | ~0.3ms | βœ… | -| Token Verify | < 1ms | ~0.2ms | βœ… | -| Password Hash | 50-100ms | ~75ms | βœ… | -| Login Flow | < 500ms | ~150ms | βœ… | -| Token Ops/Sec | > 1000 | ~3000 | βœ… | - -### Documentation - -Two comprehensive documentation files created: - -1. **Testing Guide** (`phase7_testing.md`) - 410 lines - - Test organization and structure - - Running tests (all, specific, individual) - - Manual testing procedures - - Troubleshooting guide - - Security checklist - -2. **Verification Report** (`phase7_verification.md`) - 540 lines - - Implementation summary - - Test coverage analysis - - Security validation results - - Performance benchmarks - - Known limitations - -## Test Coverage Details - -### Unit Tests (51 tests) - -**Password Utilities (31 tests):** -- βœ… Hash generation with different salts -- βœ… Special characters and Unicode support -- βœ… Empty and very long passwords -- βœ… Verification correctness and security -- βœ… Password strength requirements -- βœ… Timing attack resistance -- βœ… bcrypt format compliance - -**Token Service (20 tests):** -- βœ… Token creation with various expirations -- βœ… Valid and invalid token verification -- βœ… Expired token detection -- βœ… Modified payload rejection -- βœ… Admin status preservation -- βœ… Token security properties - -### Security Tests (13 tests) - -- βœ… SQL injection in email field -- βœ… SQL injection in password field -- βœ… SQL injection in service calls -- βœ… Access without token -- βœ… Access with invalid token -- βœ… Token forgery attempts -- βœ… Admin privilege escalation -- βœ… Token expiration enforcement -- βœ… Session invalidation -- βœ… Email validation -- βœ… XSS prevention -- βœ… Path traversal prevention -- βœ… Rate limiting (documented for future) - -### Integration Tests (11 tests) - -- βœ… Board isolation between users -- βœ… Cannot access other user's boards -- βœ… Admin board visibility -- βœ… Image isolation (documented) -- βœ… Workflow isolation (documented) -- βœ… Queue isolation (documented) -- βœ… Shared boards (prepared for future) -- βœ… Admin creation restrictions -- βœ… User listing authorization -- βœ… User deletion cascades -- βœ… Concurrent operation isolation - -### Performance Tests (13 tests) - -- βœ… Password hashing performance -- βœ… Password verification performance -- βœ… Concurrent password operations -- βœ… Token creation performance -- βœ… Token verification performance -- βœ… Concurrent token operations -- βœ… Complete login flow timing -- βœ… Token verification overhead -- βœ… User creation performance -- βœ… User lookup performance -- βœ… User listing performance -- βœ… Concurrent login handling -- βœ… Scalability under load (marked slow) - -## Implementation Highlights - -### Code Quality - -- **Comprehensive:** 88 tests covering all aspects -- **Isolated:** Each test is independent -- **Repeatable:** Consistent results -- **Documented:** Clear docstrings and comments -- **Edge Cases:** Boundary conditions tested - -### Security Focus - -- **Attack Vectors:** All major threats tested -- **Prevention:** Parameterized queries, HMAC tokens -- **Validation:** Input validation at all layers -- **Isolation:** Multi-user data separation verified - -### Performance Focus - -- **Baselines:** Performance metrics established -- **Optimization:** bcrypt intentionally slow (50-100ms) -- **Scalability:** > 1000 token ops/sec -- **Overhead:** < 0.1ms per request - -## Files Changed - -### Created (8 files, ~3,250 lines total) - -**Test Files:** -1. `tests/app/services/auth/__init__.py` (1 line) -2. `tests/app/services/auth/test_password_utils.py` (346 lines) -3. `tests/app/services/auth/test_token_service.py` (380 lines) -4. `tests/app/services/auth/test_security.py` (534 lines) -5. `tests/app/services/auth/test_data_isolation.py` (496 lines) -6. `tests/app/services/auth/test_performance.py` (544 lines) - -**Documentation Files:** -7. `docs/multiuser/phase7_testing.md` (410 lines) -8. `docs/multiuser/phase7_verification.md` (540 lines) - -**Total New Code:** -- Test code: ~2,300 lines -- Documentation: ~950 lines -- Total: ~3,250 lines - -### Modified (2 files) -- `tests/app/services/auth/test_token_service.py` (timing improvements) -- `tests/app/services/auth/test_security.py` (timing improvements) - -## Integration with Previous Phases - -Phase 7 complements existing test infrastructure: - -| Phase | Focus | Tests | Integration | -|-------|-------|-------|-------------| -| Phase 3 | Auth API | 16 | Endpoint testing | -| Phase 4 | User Service | 13 | CRUD operations | -| Phase 6 | Frontend UI | Manual | UI restrictions | -| **Phase 7** | **Security** | **88** | **Comprehensive validation** | - -All phases work together to provide complete authentication coverage. - -## Technical Details - -### Test Technologies - -- **Framework:** pytest -- **Database:** In-memory SQLite -- **Concurrency:** ThreadPoolExecutor -- **Time:** timedelta for expiration -- **Security:** bcrypt, PyJWT - -### Test Patterns - -- **Fixtures:** Reusable test setup -- **Parametrization:** Multiple test cases -- **Mocking:** API dependencies -- **Assertions:** Clear expectations -- **Skip/Mark:** Future features marked - -## Known Limitations - -1. **JWT Stateless Nature** - - Tokens valid until expiration - - Server-side session tracking for future - - Documented in tests - -2. **Rate Limiting** - - Not currently implemented - - Test framework prepared - - Marked as skipped - -3. **Secret Key Management** - - Placeholder key with warning - - Production deployment needs config - - Clearly documented - -4. **Shared Boards** - - Feature not yet complete - - Tests prepared and skipped - - Ready for future implementation - -## Future Enhancements - -Phase 7 prepares for future features: - -1. **Rate Limiting Tests** - - Framework ready in `test_security.py` - - Marked with `@pytest.mark.skip` - - Implementation notes included - -2. **Server-Side Sessions** - - JWT limitations documented - - Migration path clear - - Tests prepared - -3. **Shared Board Tests** - - Test structure in place - - Marked as skipped - - Ready for implementation - -## Verification Checklist - -### Implementation -- [x] Password utilities tests (31) -- [x] Token service tests (20) -- [x] Security tests (13) -- [x] Data isolation tests (11) -- [x] Performance tests (13) -- [x] Testing documentation -- [x] Verification report - -### Security -- [x] SQL injection prevention -- [x] Authorization bypass prevention -- [x] Token forgery prevention -- [x] XSS prevention -- [x] Path traversal prevention -- [x] Password security -- [x] Data isolation - -### Performance -- [x] Password operations measured -- [x] Token operations measured -- [x] Authentication overhead measured -- [x] User service performance measured -- [x] Concurrent sessions tested -- [x] Scalability benchmarked - -### Documentation -- [x] Testing guide complete -- [x] Verification report complete -- [x] Manual testing procedures -- [x] Security checklist -- [x] Troubleshooting guide - -## Success Metrics - -βœ… **Test Coverage:** 88 comprehensive tests -βœ… **Security:** All attack vectors prevented -βœ… **Performance:** All targets met -βœ… **Documentation:** Complete guides -βœ… **Code Quality:** Reviewed and improved - -## Running the Tests - -### Quick Start - -```bash -# Install dependencies -pip install -e ".[dev,test]" - -# Run all Phase 7 tests -pytest tests/app/services/auth/ -v - -# Run specific category -pytest tests/app/services/auth/test_security.py -v - -# Run with coverage -pytest tests/app/services/auth/ --cov=invokeai.app.services.auth --cov-report=html -``` - -### Expected Results - -All 88 tests should pass: -- Password utilities: 31/31 βœ… -- Token service: 20/20 βœ… -- Security: 13/13 βœ… -- Data isolation: 11/11 βœ… -- Performance: 13/13 βœ… - -Performance should meet benchmarks: -- Token ops: < 1ms βœ… -- Login flow: < 500ms βœ… -- Concurrent: > 1000 ops/sec βœ… - -## Conclusion - -Phase 7 successfully delivers: - -1. **Comprehensive Testing:** 88 tests covering all authentication aspects -2. **Security Validation:** All major attack vectors tested and prevented -3. **Performance Benchmarks:** Metrics established and targets met -4. **Complete Documentation:** Testing guides and verification reports -5. **Code Quality:** Reviewed and improved based on feedback - -### Test Summary - -| Category | Tests | Status | -|----------|-------|--------| -| Unit Tests | 51 | βœ… PASS | -| Security Tests | 13 | βœ… PASS | -| Integration Tests | 11 | βœ… PASS | -| Performance Tests | 13 | βœ… PASS | -| **Total** | **88** | βœ… **ALL PASS** | - -### Security Summary - -| Assessment | Result | -|-----------|--------| -| SQL Injection | βœ… PREVENTED | -| XSS Attacks | βœ… PREVENTED | -| Authorization Bypass | βœ… PREVENTED | -| Token Forgery | βœ… PREVENTED | -| Password Security | βœ… STRONG | -| Data Isolation | βœ… ENFORCED | - -**Phase 7 Status:** βœ… **COMPLETE AND VERIFIED** - -## Next Steps - -With Phase 7 complete, the multiuser authentication system has: - -- βœ… Comprehensive test coverage (88 tests) -- βœ… Security validation (all threats tested) -- βœ… Performance benchmarks (all targets met) -- βœ… Complete documentation (testing + verification) - -The system is now ready for: -- Phase 8: Documentation (user guides, admin guides) -- Phase 9: Migration Support (migration wizard, backward compatibility) -- Production deployment (with proper secret key configuration) - -## References - -- Implementation Plan: `docs/multiuser/implementation_plan.md` (Phase 7: Lines 834-867) -- Specification: `docs/multiuser/specification.md` -- Testing Guide: `docs/multiuser/phase7_testing.md` -- Verification Report: `docs/multiuser/phase7_verification.md` -- Previous Phases: - - Phase 3: `docs/multiuser/phase3_testing.md` - - Phase 4: `docs/multiuser/phase4_verification.md` - - Phase 5: `docs/multiuser/phase5_verification.md` - - Phase 6: `docs/multiuser/phase6_verification.md` - ---- - -*Phase 7 Implementation Completed: January 12, 2026* -*Total Contribution: 88 tests, 3,250+ lines of code and documentation* -*Status: Ready for deployment and further phases* diff --git a/docs/multiuser/phase7_testing.md b/docs/multiuser/phase7_testing.md deleted file mode 100644 index 56cb4a017ce..00000000000 --- a/docs/multiuser/phase7_testing.md +++ /dev/null @@ -1,440 +0,0 @@ -# Phase 7 Testing Guide - Multiuser Authentication System - -## Overview - -This guide provides comprehensive testing instructions for Phase 7 of the multiuser implementation, which focuses on testing and security validation of the authentication system. - -## Test Suite Organization - -The Phase 7 test suite is organized into four main categories: - -### 1. Unit Tests (`tests/app/services/auth/`) - -#### Password Utilities Tests (`test_password_utils.py`) -- **Password Hashing Tests** (7 tests) - - Hash generation with different salts - - Special characters and Unicode support - - Empty and very long passwords - - Newline handling - -- **Password Verification Tests** (9 tests) - - Correct and incorrect password verification - - Case sensitivity - - Whitespace sensitivity - - Special characters and Unicode - - Invalid hash format handling - -- **Password Strength Validation Tests** (12 tests) - - Minimum length requirements - - Uppercase, lowercase, and digit requirements - - Special character handling - - Unicode support - - Edge cases (empty, very long) - -- **Security Properties Tests** (3 tests) - - Timing attack resistance - - Hash randomization (salt uniqueness) - - bcrypt format validation - -**Total: 31 tests** - -#### Token Service Tests (`test_token_service.py`) -- **Token Creation Tests** (5 tests) - - Basic token creation - - Custom expiration handling - - Admin user tokens - - Data preservation - - Token uniqueness - -- **Token Verification Tests** (6 tests) - - Valid token verification - - Invalid and malformed tokens - - Expired token handling - - Modified payload detection - - Admin status preservation - -- **Token Expiration Tests** (3 tests) - - Fresh token validity - - Long expiration periods - - Short but valid expiration - -- **Token Data Model Tests** (3 tests) - - TokenData creation - - Admin user handling - - Model serialization - -- **Token Security Tests** (3 tests) - - Signature verification - - Admin privilege forgery prevention - - Algorithm security (HS256) - -**Total: 20 tests** - -### 2. Security Tests (`test_security.py`) - -#### SQL Injection Prevention Tests (3 tests) -- Email field injection attempts -- Password field injection attempts -- User service injection protection - -#### Authorization Bypass Tests (4 tests) -- Protected endpoint access without token -- Invalid token rejection -- Token forgery prevention -- Regular user privilege escalation prevention - -#### Session Security Tests (2 tests) -- Token expiration validation -- Logout session invalidation - -#### Input Validation Tests (3 tests) -- Email format validation -- XSS prevention in user data -- Path traversal prevention - -#### Rate Limiting Tests (1 test, skipped) -- Login attempt rate limiting (documented for future implementation) - -**Total: 13 tests** - -### 3. Integration Tests (`test_data_isolation.py`) - -#### Board Data Isolation Tests (3 tests) -- User can only see own boards -- Cannot access other user's boards -- Admin can see all boards - -#### Image Data Isolation Tests (1 test) -- User image isolation (documented) - -#### Workflow Data Isolation Tests (1 test) -- User workflow isolation (documented) - -#### Queue Data Isolation Tests (1 test) -- User queue item isolation (documented) - -#### Shared Board Tests (1 test, skipped) -- Shared board access (for future implementation) - -#### Admin Authorization Tests (2 tests) -- Regular user cannot create admin -- Regular user cannot list all users - -#### Data Integrity Tests (2 tests) -- User deletion cascades to owned data -- Concurrent operations maintain isolation - -**Total: 11 tests** - -### 4. Performance Tests (`test_performance.py`) - -#### Password Performance Tests (3 tests) -- Hashing performance (10-500ms per hash) -- Verification performance (10-500ms per verification) -- Concurrent password operations - -#### Token Performance Tests (3 tests) -- Creation performance (< 1ms per token) -- Verification performance (< 1ms per verification) -- Concurrent token operations (> 1000 ops/sec) - -#### Authentication Overhead Tests (2 tests) -- Complete login flow performance (< 500ms) -- Token verification overhead (< 0.1ms per request) - -#### User Service Performance Tests (3 tests) -- User creation performance (< 500ms) -- User lookup performance (< 5ms) -- User listing performance (< 50ms for 50 users) - -#### Concurrent Sessions Tests (1 test) -- Multiple concurrent logins (< 10s for 20 users) - -#### Scalability Benchmarks (1 test, marked slow) -- Authentication under sustained load (> 95% success rate) - -**Total: 13 tests (1 marked slow)** - -## Running the Tests - -### Prerequisites - -Ensure you have the development environment set up: - -```bash -# Install dependencies -pip install -e ".[dev,test]" -``` - -### Running All Phase 7 Tests - -```bash -# Run all auth service tests -pytest tests/app/services/auth/ -v - -# Run with coverage -pytest tests/app/services/auth/ --cov=invokeai.app.services.auth --cov-report=html -``` - -### Running Specific Test Categories - -```bash -# Unit tests only -pytest tests/app/services/auth/test_password_utils.py -v -pytest tests/app/services/auth/test_token_service.py -v - -# Security tests -pytest tests/app/services/auth/test_security.py -v - -# Integration tests -pytest tests/app/services/auth/test_data_isolation.py -v - -# Performance tests (fast only) -pytest tests/app/services/auth/test_performance.py -v - -# Performance tests (including slow benchmarks) -pytest tests/app/services/auth/test_performance.py -v -m slow -``` - -### Running Individual Tests - -```bash -# Run a specific test class -pytest tests/app/services/auth/test_password_utils.py::TestPasswordHashing -v - -# Run a specific test method -pytest tests/app/services/auth/test_password_utils.py::TestPasswordHashing::test_hash_password_returns_different_hash_each_time -v -``` - -## Expected Test Results - -### Test Coverage Goals - -- **Password utilities**: 100% coverage -- **Token service**: 100% coverage -- **Security tests**: Comprehensive attack vector coverage -- **Integration tests**: Core isolation scenarios covered -- **Performance tests**: Baseline metrics established - -### Performance Benchmarks - -Expected performance metrics on modern hardware: - -| Operation | Expected Performance | -|-----------|---------------------| -| Password hashing | 50-100ms per hash | -| Password verification | 50-100ms per verification | -| Token creation | < 1ms per token | -| Token verification | < 1ms per verification | -| Complete login flow | < 500ms | -| User lookup | < 5ms | -| Token verification overhead | < 0.1ms per request | -| Concurrent token ops | > 1000 ops/second | - -### Security Test Expectations - -All security tests should pass with no vulnerabilities detected: - -βœ… SQL injection prevented (parameterized queries) -βœ… Authorization bypass prevented (token signature verification) -βœ… XSS prevented (proper data escaping) -βœ… Path traversal prevented (input validation) -βœ… Token forgery prevented (HMAC signature) -βœ… Admin privilege escalation prevented (token validation) - -## Manual Testing Procedures - -### 1. SQL Injection Testing - -**Manual Test Cases:** - -```bash -# Test login with SQL injection in email field -curl -X POST http://localhost:9090/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{"email":"'\'' OR '\''1'\''='\''1","password":"test","remember_me":false}' - -# Expected: 401 Unauthorized (not 500 or 200) -``` - -### 2. Token Security Testing - -**Manual Test Cases:** - -```bash -# 1. Try accessing protected endpoint without token -curl http://localhost:9090/api/v1/auth/me -# Expected: 401 Unauthorized - -# 2. Try accessing with invalid token -curl -H "Authorization: Bearer invalid_token" \ - http://localhost:9090/api/v1/auth/me -# Expected: 401 Unauthorized - -# 3. Try modifying token payload -# (Modify a character in the token string) -curl -H "Authorization: Bearer eyJhbGc...modified..." \ - http://localhost:9090/api/v1/auth/me -# Expected: 401 Unauthorized -``` - -### 3. Password Security Testing - -**Manual Test Cases:** - -1. **Weak Password Rejection:** - ```bash - # Try creating user with weak password - curl -X POST http://localhost:9090/api/v1/auth/setup \ - -H "Content-Type: application/json" \ - -d '{"email":"admin@test.com","display_name":"Admin","password":"weak"}' - # Expected: 400 Bad Request with password requirement message - ``` - -2. **Special Characters:** - ```bash - # Try password with special characters - curl -X POST http://localhost:9090/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{"email":"test@test.com","password":"Test!@#$%123","remember_me":false}' - # Expected: 200 OK if user exists with this password - ``` - -### 4. Data Isolation Testing - -**Manual Test Cases:** - -1. **Board Isolation:** - - Login as User A, create a board, note the board_id - - Login as User B, try to list boards - - Verify User B cannot see User A's board - -2. **Token Isolation:** - - Login as User A, save token - - Login as User B, save token - - Try using User A's token to access data - should only see User A's data - - Try using User B's token to access data - should only see User B's data - -### 5. Performance Testing - -**Manual Benchmarking:** - -```bash -# Use Apache Bench or similar tool to test login performance -ab -n 100 -c 10 -p login.json -T "application/json" \ - http://localhost:9090/api/v1/auth/login - -# Where login.json contains: -# {"email":"test@example.com","password":"TestPass123","remember_me":false} -``` - -## Troubleshooting - -### Common Issues - -#### 1. Tests Fail Due to Missing Dependencies - -```bash -# Solution: Install test dependencies -pip install -e ".[dev,test]" -``` - -#### 2. Database Lock Errors - -```bash -# Solution: Use in-memory database for tests -# Tests are already configured to use in-memory SQLite -``` - -#### 3. Slow Password Tests - -```bash -# This is expected - bcrypt is intentionally slow (50-100ms) -# If tests are timing out, increase timeout values -pytest tests/app/services/auth/ --timeout=30 -``` - -#### 4. Performance Tests Fail on Slow Hardware - -```bash -# Performance expectations may need adjustment for different hardware -# Check actual times in test output and adjust assertions if needed -``` - -## Security Checklist - -Before completing Phase 7, verify: - -- [ ] All SQL injection tests pass -- [ ] All authorization bypass tests pass -- [ ] Token forgery prevention works -- [ ] Password hashing uses bcrypt with proper salt -- [ ] Tokens use HMAC signature with secure algorithm (HS256) -- [ ] Password strength validation enforces requirements -- [ ] Data isolation tests confirm user separation -- [ ] No sensitive data in logs or error messages -- [ ] Token expiration is properly enforced -- [ ] All security tests pass with no failures - -## Coverage Report - -To generate a coverage report: - -```bash -# Generate HTML coverage report -pytest tests/app/services/auth/ --cov=invokeai.app.services.auth --cov-report=html - -# Open the report -open htmlcov/index.html -``` - -Target coverage: **> 90%** for all auth modules - -## Integration with Existing Tests - -Phase 7 tests complement existing tests: - -- **Phase 3 tests** (`test_auth.py`): API endpoint integration tests -- **Phase 4 tests** (`test_user_service.py`): User service unit tests -- **Phase 6 tests** (`test_boards_multiuser.py`): Board multiuser tests - -All tests should pass together: - -```bash -# Run all auth-related tests -pytest tests/app/routers/test_auth.py \ - tests/app/services/users/ \ - tests/app/services/auth/ \ - tests/app/routers/test_boards_multiuser.py \ - -v -``` - -## Next Steps - -After Phase 7 testing is complete: - -1. **Review test results** and address any failures -2. **Generate coverage report** and improve coverage if needed -3. **Run security audit** using findings from security tests -4. **Document any discovered issues** in the issue tracker -5. **Prepare for Phase 8** (Documentation) or Phase 9 (Migration Support) - -## Test Summary - -| Category | Test Count | Status | -|----------|-----------|--------| -| Password Utils | 31 | βœ… Comprehensive | -| Token Service | 20 | βœ… Comprehensive | -| Security | 13 | βœ… Comprehensive | -| Data Isolation | 11 | βœ… Core scenarios | -| Performance | 13 | βœ… Benchmarks set | -| **Total** | **88** | βœ… **Phase 7 Complete** | - -## References - -- Implementation Plan: `docs/multiuser/implementation_plan.md` -- Specification: `docs/multiuser/specification.md` -- Phase 3 Testing: `docs/multiuser/phase3_testing.md` -- Phase 4 Testing: `docs/multiuser/phase4_verification.md` -- Phase 5 Testing: `docs/multiuser/phase5_testing.md` -- Phase 6 Testing: `docs/multiuser/phase6_testing.md` diff --git a/docs/multiuser/phase7_verification.md b/docs/multiuser/phase7_verification.md deleted file mode 100644 index 90a4b31a2d3..00000000000 --- a/docs/multiuser/phase7_verification.md +++ /dev/null @@ -1,483 +0,0 @@ -# Phase 7 Verification Report - Testing & Security - -## Executive Summary - -Phase 7 of the multiuser implementation has been completed successfully. This phase focused on creating comprehensive test coverage and security validation for the authentication system. A total of **88 new tests** have been implemented across four test modules, providing extensive coverage of password handling, token management, security vulnerabilities, data isolation, and performance characteristics. - -**Status:** βœ… **COMPLETE** - -## Implementation Summary - -### Tests Created - -| Test Module | Tests | Lines of Code | Purpose | -|-------------|-------|---------------|---------| -| `test_password_utils.py` | 31 | 346 | Password hashing, verification, and validation | -| `test_token_service.py` | 20 | 380 | JWT token creation, verification, and security | -| `test_security.py` | 13 | 534 | SQL injection, XSS, auth bypass prevention | -| `test_data_isolation.py` | 11 | 496 | Multi-user data isolation verification | -| `test_performance.py` | 13 | 544 | Performance benchmarking and scalability | -| **Total** | **88** | **2,300** | **Comprehensive test coverage** | - -### Documentation Created - -| Document | Purpose | Lines | -|----------|---------|-------| -| `phase7_testing.md` | Comprehensive testing guide | 410 | -| `phase7_verification.md` | This verification report | - | - -## Test Coverage Analysis - -### Unit Tests (51 tests) - -#### Password Utilities (31 tests) -βœ… **Hash Generation** -- Different salts for same password -- Special characters (!, @, #, $, etc.) -- Unicode characters (δΈ­ζ–‡, ζ—₯本θͺž) -- Empty strings -- Very long passwords (> 72 bytes, bcrypt limit) -- Passwords with newlines - -βœ… **Password Verification** -- Correct password matching -- Incorrect password rejection -- Case sensitivity enforcement -- Whitespace sensitivity -- Special character handling -- Unicode support -- Empty password edge cases -- Invalid hash format handling - -βœ… **Password Strength Validation** -- Minimum 8 character requirement -- Uppercase letter requirement -- Lowercase letter requirement -- Digit requirement -- Special characters (optional) -- Unicode characters -- Edge cases (empty, very long) - -βœ… **Security Properties** -- Timing attack resistance (< 50% variance) -- Salt randomization (unique hashes) -- bcrypt format compliance (60 chars, $2 prefix) - -#### Token Service (20 tests) -βœ… **Token Creation** -- Basic token generation -- Custom expiration periods -- Admin user token handling -- Data field preservation -- Token uniqueness verification - -βœ… **Token Verification** -- Valid token acceptance -- Invalid token rejection -- Malformed token handling -- Expired token detection -- Modified payload rejection -- Admin flag preservation - -βœ… **Token Expiration** -- Fresh token validity -- Long expiration (7 days) -- Short expiration (seconds) - -βœ… **Token Data Model** -- Pydantic model creation -- Admin user representation -- Model serialization - -βœ… **Token Security** -- HMAC signature verification -- Admin privilege forgery prevention -- HS256 algorithm validation - -### Security Tests (13 tests) - -βœ… **SQL Injection Prevention (3 tests)** -- Email field injection (`' OR '1'='1`, `admin' --`, etc.) -- Password field injection -- User service query protection -- **Result:** All attempts properly rejected (401 status) - -βœ… **Authorization Bypass Prevention (4 tests)** -- Access without token β†’ 401 -- Access with invalid token β†’ 401 -- Token forgery attempt β†’ 401 (signature fails) -- Privilege escalation prevention β†’ ValueError - -βœ… **Session Security (2 tests)** -- Token expiration enforcement -- Logout session handling (JWT limitations documented) - -βœ… **Input Validation (3 tests)** -- Email format validation (422 or 401) -- XSS prevention (data stored safely) -- Path traversal prevention (literal string storage) - -βœ… **Rate Limiting (1 test - documented)** -- Future implementation documented -- Test marked as skipped with clear rationale - -### Integration Tests (11 tests) - -βœ… **Board Data Isolation (3 tests)** -- Users see only their own boards -- Cannot access other user's boards by ID -- Admin visibility (behavior documented) - -βœ… **Image Data Isolation (1 test - documented)** -- Expected behavior specified -- Requires actual image creation (out of scope) - -βœ… **Workflow Data Isolation (1 test - documented)** -- Private/public workflow separation -- Expected behavior specified - -βœ… **Queue Data Isolation (1 test - documented)** -- User-specific queue item filtering -- Admin can see all items - -βœ… **Shared Board Access (1 test - skipped)** -- Future feature implementation -- Test framework prepared - -βœ… **Admin Authorization (2 tests)** -- Regular users cannot create admins -- User listing authorization (API level enforcement) - -βœ… **Data Integrity (2 tests)** -- User deletion cascades to owned data -- Concurrent operations maintain isolation - -### Performance Tests (13 tests) - -βœ… **Password Performance (3 tests)** -- Hashing: 50-100ms per hash (bcrypt design) -- Verification: 50-100ms per verification -- Concurrent operations: Thread-safe - -βœ… **Token Performance (3 tests)** -- Creation: < 1ms per token -- Verification: < 1ms per token -- Throughput: > 1000 ops/second - -βœ… **Authentication Overhead (2 tests)** -- Complete login flow: < 500ms -- Token verification: < 0.1ms per request - -βœ… **User Service Performance (3 tests)** -- User creation: < 500ms (includes password hashing) -- User lookup: < 5ms (with indexing) -- User listing: < 50ms for 50 users - -βœ… **Concurrent Sessions (1 test)** -- 20 concurrent logins: < 10 seconds -- All operations succeed - -βœ… **Scalability Benchmark (1 test - marked slow)** -- 50 users Γ— 5 requests = 250 total requests -- Success rate: > 95% -- Throughput: > 5 req/sec (bcrypt limited) - -## Security Validation - -### Vulnerability Testing Results - -| Attack Vector | Test Method | Result | Status | -|--------------|-------------|--------|--------| -| SQL Injection (Email) | `' OR '1'='1`, `admin' --` | 401 Rejected | βœ… PASS | -| SQL Injection (Password) | `' OR 1=1 --` | 401 Rejected | βœ… PASS | -| SQL Injection (Service) | Direct service calls | None returned | βœ… PASS | -| Token Forgery | Modified payload | 401 Rejected | βœ… PASS | -| Token Signature Bypass | Modified signature | 401 Rejected | βœ… PASS | -| Admin Privilege Escalation | Token modification | Signature fails | βœ… PASS | -| XSS in User Data | `` | Safely stored | βœ… PASS | -| Path Traversal | `../../../etc/passwd` | Literal storage | βœ… PASS | -| Authorization Bypass | No token/invalid token | 401 Rejected | βœ… PASS | -| Expired Token Use | Expired JWT | 401 Rejected | βœ… PASS | - -### Security Best Practices Verification - -βœ… **Password Security** -- bcrypt hashing with automatic salt generation -- 72-byte limit handling (truncation with UTF-8 safety) -- Timing attack resistance (< 50% variance in tests) -- Strong password requirements enforced - -βœ… **Token Security** -- HMAC-SHA256 signature -- Expiration time enforcement -- No sensitive data in token payload (only IDs and flags) -- Token signature prevents forgery - -βœ… **Data Protection** -- Parameterized SQL queries prevent injection -- User input validation at API layer -- Data isolation enforced at query level -- Proper error handling (no information leakage) - -βœ… **Session Management** -- JWT tokens with expiration -- Remember me: 7 days, regular: 24 hours -- Logout documented (JWT limitations noted) - -### Known Security Considerations - -πŸ“ **JWT Stateless Nature** -- Current implementation uses stateless JWT -- Tokens remain valid until expiration even after logout -- For true session invalidation, server-side tracking needed -- **Documented in:** `test_security.py::test_logout_invalidates_session` - -πŸ“ **Rate Limiting** -- Not currently implemented -- Test framework prepared for future implementation -- **Documented in:** `test_security.py::TestRateLimiting` - -πŸ“ **Secret Key Management** -- Currently uses placeholder key -- Production deployment requires secure key generation -- **Warning in:** `invokeai/app/services/auth/token_service.py` - -## Performance Benchmarks - -### Authentication Operations - -| Operation | Target | Achieved | Status | -|-----------|--------|----------|--------| -| Password Hash | 50-100ms | ~75ms avg | βœ… PASS | -| Password Verify | 50-100ms | ~75ms avg | βœ… PASS | -| Token Create | < 1ms | ~0.3ms | βœ… PASS | -| Token Verify | < 1ms | ~0.2ms | βœ… PASS | -| Login Flow | < 500ms | ~150ms | βœ… PASS | -| User Lookup | < 5ms | ~1ms | βœ… PASS | -| User List (50) | < 50ms | ~5ms | βœ… PASS | - -### Throughput Benchmarks - -| Metric | Target | Achieved | Status | -|--------|--------|----------|--------| -| Token Ops/Second | > 1000 | ~3000 | βœ… PASS | -| Concurrent Logins (20) | < 10s | ~3s | βœ… PASS | -| Auth Success Rate | > 95% | ~99% | βœ… PASS | - -**Note:** Actual performance varies by hardware. bcrypt is intentionally slow (50-100ms) for security. Token operations are fast (< 1ms) as expected. - -## Test Quality Metrics - -### Coverage - -- **Password utilities:** Comprehensive (31 tests) -- **Token service:** Comprehensive (20 tests) -- **Security:** Major attack vectors covered (13 tests) -- **Integration:** Core scenarios covered (11 tests) -- **Performance:** Baseline established (13 tests) - -### Test Characteristics - -βœ… **Isolation** -- Each test is independent -- Uses in-memory databases -- No shared state between tests - -βœ… **Repeatability** -- Tests produce consistent results -- No reliance on external services -- Deterministic outcomes - -βœ… **Documentation** -- Clear test names and docstrings -- Expected behavior documented -- Future enhancements marked with skip - -βœ… **Edge Cases** -- Empty strings, very long strings -- Unicode characters, special characters -- Concurrent operations -- Boundary conditions - -## Integration with Existing Tests - -Phase 7 tests complement previous phases: - -| Phase | Test File | Tests | Integration | -|-------|-----------|-------|-------------| -| Phase 3 | `test_auth.py` | 16 | API endpoint testing | -| Phase 4 | `test_user_service.py` | 13 | User service CRUD | -| Phase 6 | `test_boards_multiuser.py` | 6 | Board isolation | -| **Phase 7** | **4 new files** | **88** | **Security & performance** | -| **Total** | **7 files** | **123** | **Comprehensive coverage** | - -All tests work together: -```bash -pytest tests/app/routers/test_auth.py \ - tests/app/services/users/ \ - tests/app/services/auth/ \ - -v -``` - -## Files Changed - -### Created (6 files) - -1. **`tests/app/services/auth/__init__.py`** (1 line) - - Test module initialization - -2. **`tests/app/services/auth/test_password_utils.py`** (346 lines) - - 31 tests for password hashing, verification, validation - - Security property tests - -3. **`tests/app/services/auth/test_token_service.py`** (380 lines) - - 20 tests for JWT token operations - - Security and expiration tests - -4. **`tests/app/services/auth/test_security.py`** (534 lines) - - 13 tests for security vulnerabilities - - SQL injection, XSS, authorization bypass - -5. **`tests/app/services/auth/test_data_isolation.py`** (496 lines) - - 11 tests for multi-user data isolation - - Board, image, workflow, queue isolation - -6. **`tests/app/services/auth/test_performance.py`** (544 lines) - - 13 tests for performance benchmarking - - Password, token, and authentication performance - -### Documentation Created (2 files) - -7. **`docs/multiuser/phase7_testing.md`** (410 lines) - - Comprehensive testing guide - - Manual testing procedures - - Troubleshooting guide - -8. **`docs/multiuser/phase7_verification.md`** (this file) - - Implementation verification - - Test results and metrics - - Security validation - -**Total New Code:** ~2,300 lines of tests + ~700 lines of documentation - -## Verification Checklist - -### Test Implementation -- [x] Password utilities tests (31 tests) -- [x] Token service tests (20 tests) -- [x] Security tests (13 tests) -- [x] Data isolation tests (11 tests) -- [x] Performance tests (13 tests) -- [x] Test documentation complete - -### Security Validation -- [x] SQL injection prevention verified -- [x] Authorization bypass prevention verified -- [x] Token forgery prevention verified -- [x] XSS prevention verified -- [x] Path traversal prevention verified -- [x] Password security best practices verified -- [x] Token security best practices verified - -### Performance Validation -- [x] Password hashing performance measured -- [x] Token performance measured -- [x] Authentication overhead measured -- [x] User service performance measured -- [x] Concurrent session handling tested -- [x] Scalability benchmarks established - -### Documentation -- [x] Testing guide created -- [x] Verification report created -- [x] Manual testing procedures documented -- [x] Security checklist provided -- [x] Troubleshooting guide included - -## Known Limitations - -1. **JWT Stateless Tokens** - - Tokens valid until expiration (no server-side revocation) - - Documented for future server-side session tracking - -2. **Rate Limiting** - - Not implemented (test framework prepared) - - Future enhancement documented - -3. **Secret Key Management** - - Uses placeholder key (production warning in code) - - Requires configuration system integration - -4. **Shared Board Tests** - - Feature not yet fully implemented - - Tests prepared and marked as skipped - -5. **Image/Workflow Integration** - - Some tests document expected behavior only - - Actual image creation out of scope for Phase 7 - -## Recommendations - -### Immediate Actions -1. βœ… All security tests pass - no action needed -2. βœ… Performance benchmarks meet requirements -3. βœ… Test coverage is comprehensive - -### Future Enhancements -1. **Rate Limiting:** Implement brute force protection - - Tests prepared in `test_security.py` - - Marked as skipped with clear documentation - -2. **Server-Side Sessions:** For token revocation - - Current JWT approach documented - - Migration path clear - -3. **Secret Key Rotation:** Production key management - - Warning present in `token_service.py` - - Configuration system integration needed - -## Conclusion - -Phase 7 has successfully delivered comprehensive test coverage for the multiuser authentication system: - -- βœ… **88 new tests** across 4 test modules -- βœ… **Security vulnerabilities** tested and prevented -- βœ… **Performance benchmarks** established and met -- βœ… **Data isolation** verified for multi-user scenarios -- βœ… **Documentation** complete and comprehensive - -### Test Summary - -| Category | Tests | Status | -|----------|-------|--------| -| Unit Tests | 51 | βœ… PASS | -| Security Tests | 13 | βœ… PASS | -| Integration Tests | 11 | βœ… PASS | -| Performance Tests | 13 | βœ… PASS | -| **Total** | **88** | βœ… **ALL PASS** | - -### Security Summary - -| Assessment | Result | -|-----------|--------| -| SQL Injection | βœ… PREVENTED | -| XSS Attacks | βœ… PREVENTED | -| Authorization Bypass | βœ… PREVENTED | -| Token Forgery | βœ… PREVENTED | -| Password Security | βœ… STRONG | -| Data Isolation | βœ… ENFORCED | - -**Phase 7 Status:** βœ… **COMPLETE AND VERIFIED** - -## References - -- Implementation Plan: `docs/multiuser/implementation_plan.md` (Phase 7: Lines 834-867) -- Specification: `docs/multiuser/specification.md` -- Testing Guide: `docs/multiuser/phase7_testing.md` -- Previous Phase: `docs/multiuser/phase6_verification.md` - ---- - -*Phase 7 Implementation Completed: January 12, 2026* -*Total Test Coverage: 88 tests, 2,300+ lines of test code* -*Security Validation: All major attack vectors tested and prevented* diff --git a/docs/multiuser/testing_token_expiration.md b/docs/multiuser/testing_token_expiration.md deleted file mode 100644 index 8a320f54043..00000000000 --- a/docs/multiuser/testing_token_expiration.md +++ /dev/null @@ -1,161 +0,0 @@ -# Testing Token Expiration - -This guide explains how to test JWT token expiration without waiting for the full expiration period (7 days for "Remember me" tokens). - -## Methods for Testing Token Expiration - -### Method 1: Modify Backend Token Expiration (Recommended) - -The backend JWT token expiration is configured in the authentication service. You can temporarily modify the expiration time for testing purposes. - -**Location**: `invokeai/app/services/auth/auth_service.py` (or similar auth configuration file) - -**Steps**: -1. Find the JWT token expiration configuration in the backend code -2. Change the expiration time from 7 days to a shorter period (e.g., 2 minutes): - ```python - # For remember_me=True tokens - expires_delta = timedelta(minutes=2) # Instead of days=7 - - # For regular tokens - expires_delta = timedelta(minutes=1) # Instead of minutes=30 - ``` -3. Restart the backend server -4. Log in with "Remember me" checked -5. Wait 2 minutes and verify that: - - The token expires and you're redirected to login - - API requests return 401 Unauthorized - - The app handles expiration gracefully - -**Remember to revert these changes after testing!** - -### Method 2: Manually Expire Token in Browser - -You can manually test token expiration by modifying or deleting the token from localStorage: - -**Steps**: -1. Log in to the application -2. Open browser DevTools (F12) -3. Go to Application/Storage β†’ Local Storage β†’ `http://localhost:5173` -4. Find the `auth_token` key -5. **Option A**: Delete the token completely - - Click on `auth_token` and press Delete - - Refresh the page - - You should be redirected to login -6. **Option B**: Replace with an expired/invalid token - - Edit the `auth_token` value to invalid characters (e.g., "invalid-token") - - Refresh the page - - The app should detect invalid token and redirect to login - -### Method 3: Use Backend Admin Tools - -If the backend provides admin tools or API endpoints to invalidate tokens: - -1. Log in and note your token (from localStorage) -2. Use admin API to invalidate/blacklist the token -3. Try to make an authenticated request -4. Verify the app handles the invalid token gracefully - -### Method 4: Modify Token Payload (Advanced) - -For testing JWT token structure issues: - -1. Copy the token from localStorage -2. Decode it using a JWT debugger (jwt.io) -3. Modify the `exp` (expiration) claim to a past timestamp -4. Re-encode the token (note: this requires the secret key, so this only works if you control the backend) -5. Replace the token in localStorage -6. Test the application behavior - -## Expected Behavior on Token Expiration - -When a token expires, the application should: - -1. **On API Request**: Return 401 Unauthorized error -2. **Frontend Handling**: - - The `ProtectedRoute` component detects the error - - Calls `logout()` to clear auth state - - Removes token from localStorage - - Redirects user to `/login` -3. **Websocket**: Connection should fail with auth error -4. **User Experience**: Clean redirect to login page with no data loss (draft workflow, settings, etc. should persist) - -## Testing Checklist - -- [ ] Token expires after configured time period -- [ ] Expired token is detected on next page load -- [ ] Expired token is detected during API requests -- [ ] User is redirected to login page gracefully -- [ ] No infinite redirect loops occur -- [ ] Auth state is properly cleared -- [ ] Token is removed from localStorage -- [ ] User can log in again successfully -- [ ] Websocket connection fails appropriately with expired token -- [ ] Error messages are user-friendly - -## Configuration Reference - -The token expiration is controlled by these JWT settings in the backend: - -```python -# Standard login token (30 minutes) -ACCESS_TOKEN_EXPIRE_MINUTES = 30 - -# "Remember me" token (7 days) -REMEMBER_ME_TOKEN_EXPIRE_DAYS = 7 -``` - -For testing, you can create environment variables or configuration options: -```bash -# .env file for testing -AUTH_TOKEN_EXPIRE_MINUTES=2 # Short expiration for testing -``` - -## Debugging Tips - -### Check Token in DevTools -```javascript -// In browser console -const token = localStorage.getItem('auth_token'); -console.log('Token:', token); - -// Decode token (without verification) -const parts = token.split('.'); -const payload = JSON.parse(atob(parts[1])); -console.log('Payload:', payload); -console.log('Expires:', new Date(payload.exp * 1000)); -console.log('Is Expired:', Date.now() > payload.exp * 1000); -``` - -### Watch for Token Expiration -You can add a temporary debug script to monitor token status: -```javascript -// In browser console -setInterval(() => { - const token = localStorage.getItem('auth_token'); - if (token) { - const parts = token.split('.'); - const payload = JSON.parse(atob(parts[1])); - const expiresIn = Math.floor((payload.exp * 1000 - Date.now()) / 1000); - console.log(`Token expires in ${expiresIn} seconds`); - } -}, 10000); // Check every 10 seconds -``` - -### Backend Logs -Monitor backend logs for authentication failures: -```bash -# Look for JWT decode errors, expired token errors, etc. -tail -f invokeai.log | grep -i "auth\|token\|jwt" -``` - -## Conclusion - -For routine testing, **Method 1** (modifying backend expiration time) is the most realistic and thorough approach. For quick smoke tests, **Method 2** (manually deleting/modifying localStorage) is fastest. - -Always test the complete flow: -1. Login β†’ Token stored -2. Use app β†’ API calls succeed -3. Token expires β†’ API calls fail with 401 -4. Frontend detects β†’ Redirect to login -5. Login again β†’ New token, full functionality restored diff --git a/docs/multiuser/user_guide.md b/docs/multiuser/user_guide.md new file mode 100644 index 00000000000..19aa6683e34 --- /dev/null +++ b/docs/multiuser/user_guide.md @@ -0,0 +1,464 @@ +# InvokeAI Multi-User Guide + +## Overview + +InvokeAI supports both single-user and multi-user modes. In single-user mode, no login is required and you have access to all features. In multi-user mode, multiple people can use the same InvokeAI instance while keeping their work private and organized. + +### Single-User vs Multi-User Mode + +**Single-User Mode:** + +- No login required - direct access to InvokeAI +- All functionality enabled by default +- All boards and images visible in a unified view +- Ideal for personal use or trusted environments +- Enabled when `multiuser: false` in config or option is absent + +**Multi-User Mode:** + +- Secure login required for access +- User isolation for boards, images, and workflows +- Role-based permissions (Administrator vs Regular User) +- Ideal for shared servers or team environments +- Enabled when `multiuser: true` in config + +!!! note "Mode Switching" + If you switch from multi-user mode to single-user mode, all boards and images from different users will be combined into a single unified view. When switching back to multi-user mode, they will be separated again by user ownership. + +## Getting Started + +### Accessing InvokeAI + +**In Single-User Mode:** + +1. Navigate to your InvokeAI URL (e.g., `http://localhost:9090`) +2. You'll go directly to the InvokeAI interface +3. No login required - start creating immediately! + +**In Multi-User Mode:** + +1. Navigate to your InvokeAI URL (e.g., `http://localhost:9090`) +2. You'll see the login screen +3. Enter your email address and password provided by your administrator +4. Click **Sign In** + +!!! tip "Remember Me" + In multi-user mode, check the "Remember me" box to stay logged in for 7 days. Otherwise, your session will expire after 24 hours. + +### Initial Setup (First Time in Multi-User Mode) + +If you're the first person to access a fresh InvokeAI installation in multi-user mode, you'll see the **Administrator Setup** dialog: + +1. Enter your email address (this will be your username) +2. Create a display name +3. Choose a strong password that meets the requirements: + - At least 8 characters long + - Contains uppercase letters + - Contains lowercase letters + - Contains numbers +4. Confirm your password +5. Click **Create Administrator Account** + +You'll be automatically logged in as the administrator. + +## Understanding User Roles (Multi-User Mode Only) + +In single-user mode, you have access to all features without restrictions. In multi-user mode, InvokeAI has two user roles: + +### Regular User + +As a regular user, you can: + +- βœ… Create and manage your own image boards +- βœ… Generate images using all AI tools (Linear, Canvas, Upscale, Workflows) +- βœ… Create, save, and load your own workflows +- βœ… Access workflows marked as public +- βœ… View your own generation queue +- βœ… Customize your UI preferences (theme, hotkeys, etc.) +- βœ… Access shared boards (based on permissions granted to you) This is a FUTURE FEATURE +- βœ… **View available models** (read-only access to Model Manager) + +You cannot: + +- ❌ Add, delete, or modify models +- ❌ View or modify other users' boards, images, or workflows +- ❌ Manage user accounts +- ❌ Access system configuration +- ❌ View or cancel other users' generation tasks + +### Administrator + +Administrators have all regular user capabilities, plus: + +- βœ… Full model management (add, delete, configure models) +- βœ… Create and manage user accounts +- βœ… View and manage all users' generation queues +- βœ… Create and manage shared boards (FUTURE FEATURE) +- βœ… Access system configuration +- βœ… Grant or revoke admin privileges + +## Working with Your Content + +### Image Boards + +Image boards help organize your generated images. Each user has their own private boards. + +**Creating a Board:** + +1. Click the **+** button in the Boards panel +2. Enter a board name +3. Press Enter or click Create + +**Managing Boards:** + +- Click a board to select it +- Generated images will automatically be added to the selected board +- Right-click a board for options (rename, delete, archive) +- Drag images between boards to reorganize + +**Board Visibility:** + +- Your boards are private by default +- Only administrators can create shared boards (FUTURE FEATURE) +- You'll see shared boards you have access to in a separate section + +### Workflows + +Workflows are reusable generation templates that you create in the Workflow Editor. + +**Creating a Workflow:** + +1. Go to the **Workflows** tab +2. Build your workflow using nodes +3. Click **Save** and give it a name +4. Your workflow is saved to your personal library + +**Workflow Privacy:** + +- Your workflows are private by default +- Only you can see and edit your workflows +- Administrators can mark workflows as "public" for all users to access +- Public workflows appear in everyone's workflow library but remain read-only + +### Your Generation Queue + +The queue shows your pending and running generation tasks. + +**Queue Features:** + +- View your current and completed generations +- Cancel pending tasks +- Re-run previous generations +- Monitor progress in real-time + +**Queue Isolation:** + +- You will see your own queue items, as well as the items generated by + either users, but the generation parameters (e.g. prompts) for other + users' are hidden for privacy reasons. +- Administrators can view all queues for troubleshooting +- Your generations won't interfere with other users' tasks + +## Using Shared Boards (FUTURE) + +Shared boards are a feature that will be added in a future +release. Administrators will able to designate certain boards as being +accessible to multiple users, allowing for collaboration among users +while maintaining security. + +### Accessing Shared Boards + +Shared boards appear in your Boards panel marked with a sharing icon. You can: + +- View images on shared boards (if you have read access) +- Add images to shared boards (if you have write access) +- Use shared boards like your personal boards + +### Permission Levels + +Shared boards have three permission levels: + +| Permission | View Images | Add Images | Edit/Delete | Manage Sharing | +|------------|-------------|------------|-------------|----------------| +| **Read** | βœ… | ❌ | ❌ | ❌ | +| **Write** | βœ… | βœ… | βœ… | ❌ | +| **Admin** | βœ… | βœ… | βœ… | βœ… | + +!!! note Only administrators will be able to create shared boards and + assign initial permissions. + +## Viewing Models (Read-Only) + +Regular users have read-only access to the Model Manager, allowing you to: + +**What You Can View:** + +- βœ… Browse all available models +- βœ… See model details and configurations +- βœ… View default settings for each model +- βœ… Check model metadata and descriptions +- βœ… See which models are installed + +**What You Cannot Do:** + +- ❌ Install new models +- ❌ Delete or modify existing models +- ❌ Change model configurations +- ❌ Upload or change model images +- ❌ Convert models between formats + +**Accessing the Model Manager:** + +1. Click on the **Models** tab in the navigation +2. Browse available models +3. Click on any model to view its details + +!!! tip "Need a New Model?" + If you need a model that isn't installed, ask your administrator to add it. + +## Customizing Your Experience + +### Personal Preferences + +Your UI preferences are saved to your account: + +- **Theme**: Choose between light and dark modes +- **Hotkeys**: Customize keyboard shortcuts +- **Canvas Settings**: Default zoom, grid visibility, etc. +- **Generation Defaults**: Default values for width, height, steps, etc. + +These settings are stored per-user and won't affect other users. + +### Profile Settings (Multi-User Mode) + +In multi-user mode, access your profile by clicking your name in the top-right corner: + +**Display Name:** Update how your name appears throughout the UI + +**Change Password:** + +!!! info "Password Changes" + A web-based interface for users to change their own passwords is coming in a future release. Until then, contact your administrator to reset your password if needed. + +## Security Best Practices + +### Password Security + +- Use a strong, unique password +- Don't share your password with others +- Change your password regularly +- Use a password manager to store complex passwords + +### Session Security + +- Log out when using a shared computer +- Be aware of your session timeout (24 hours or 7 days with "remember me") +- Your session will automatically expire for security +- You'll need to log in again after the session expires + +### Data Privacy + +- Your boards, images, and workflows are private by default +- Other users cannot access your content unless explicitly shared +- Only administrators can see all users' content for management purposes + +## Troubleshooting + +### Cannot Log In + +**Issue:** Login fails with "Incorrect email or password" + +**Solutions:** + +- Verify you're entering the correct email address +- Check that Caps Lock is off +- Try typing the password slowly to avoid mistakes +- Contact your administrator if you've forgotten your password + +**Issue:** Login fails with "Account is disabled" + +**Solution:** Contact your administrator to reactivate your account + +### Session Expired + +**Issue:** You're suddenly logged out and see "Session expired" + +**Explanation:** Sessions expire after 24 hours (or 7 days with "remember me") + +**Solution:** Simply log in again with your credentials + +### Cannot Access Features + +**Issue:** Features like Model Manager show "Admin privileges required" + +**Explanation:** Some features are restricted to administrators + +**Solution:** + +- For model viewing: You can view but not modify models +- For user management: Contact an administrator +- For system configuration: Contact an administrator + +### Missing Boards or Images + +**Issue:** Boards or images you created are not visible + +**Possible Causes:** + +1. **Filter Applied:** Check if a filter is hiding content +2. **Wrong User:** Ensure you're logged in with the correct account +3. **Archived Board:** Check the "Show Archived" option + +**Solution:** + +- Clear any active filters +- Verify you're logged in as the right user +- Check archived items + +### Slow Performance + +**Issue:** Generation or UI feels slower than expected + +**Possible Causes:** + +- Other users generating images simultaneously +- Server resource limits +- Network latency + +**Solutions:** + +- Check the queue to see if others are generating +- Wait for current generations to complete +- Contact administrator if persistent + +### Generation Stuck in Queue + +**Issue:** Your generation is queued but not starting + +**Possible Causes:** + +- Server is processing other users' generations +- Server resources are fully utilized +- Technical issue with the server + +**Solutions:** + +- Wait for your turn in the queue +- Check if your generation is paused +- Contact administrator if stuck for extended period + +## Common Tasks + +### Changing Your Password + +!!! note This is a FUTURE FEATURE. For now, the Administrator must change/reset a user's password using command-line tools. + +1. Click your display name (top-right corner) +2. Select **Change Password** +3. Enter current password +4. Enter new password (8+ characters, mixed case, numbers) +5. Confirm new password +6. Click **Update Password** + +### Creating a New Board + +1. Navigate to the Gallery or Canvas tab +2. Find the Boards panel (usually on the left) +3. Click the **+ New Board** button +4. Type a descriptive name +5. Press Enter + +### Saving a Workflow + +1. Create or edit a workflow in the Workflows tab +2. Click **Save** in the top bar +3. Enter a workflow name +4. Optionally add a description +5. Click **Save Workflow** + +### Finding a Public Workflow + +!!! note Sharing of workflows is a FUTURE FEATURE, not yet implemented + +1. Go to the **Workflows** tab +2. Open the workflow library +3. Public workflows are marked with a 🌐 icon +4. Click to load and use the workflow + +### Logging Out + +1. Click your display name (top-right corner) +2. Select **Logout** +3. You'll be redirected to the login screen + +## Frequently Asked Questions + +### Can other users see my images? + +No, unless you add them to a shared board (FUTURE FEATURE). All your personal boards and images are private. + +### Can I share my workflows with others? + +Not directly. Ask your administrator to mark workflows as public if you want to share them. + +### How long do sessions last? + +- 24 hours by default +- 7 days if you check "Remember me" during login + +### Can I use the API with multi-user mode? + +Yes, but you'll need to authenticate with a JWT token. See the [API Guide](api_guide.md) for details. + +### What happens if I forget my password? + +Contact your administrator. They can reset your password for you. + +### Can I have multiple sessions? + +Yes, you can log in from multiple devices or browsers simultaneously. All sessions will use the same account and see the same content. + +### Why can't I see the Model Manager "Add Models" tab? + +Regular users can see the Models tab but with read-only access. Check that you're logged in and try refreshing the page. + +### How do I know if I'm an administrator? + +Administrators see an "Admin" badge next to their name in the top-right corner and have access to additional features like User Management. + +### Can I request admin privileges? + +Yes, ask your current administrator to grant you admin +privileges. Admin privileges will give you the ability to see all +other user's boards and images, as well as to add models and change +various server-wide settings. + +## Getting Help + +### Support Channels + +- **Administrator:** Contact your system administrator for account issues +- **Documentation:** Check the [FAQ](../faq.md) for common issues +- **Community:** Join the [Discord](https://discord.gg/ZmtBAhwWhy) for help +- **Bug Reports:** File issues on [GitHub](https://github.com/invoke-ai/InvokeAI/issues) + +### Reporting Issues + +When reporting an issue, include: + +- Your role (regular user or administrator) +- What you were trying to do +- What happened instead +- Any error messages you saw +- Your browser and operating system + +## Additional Resources + +- [Administrator Guide](admin_guide.md) - For administrators managing users and the system +- [API Guide](api_guide.md) - For developers using the InvokeAI API +- [Multiuser Specification](specification.md) - Technical details about the feature +- [InvokeAI Documentation](../index.md) - Main documentation hub + +--- + +**Need more help?** Contact your administrator or visit the [InvokeAI Discord](https://discord.gg/ZmtBAhwWhy). diff --git a/mkdocs.yml b/mkdocs.yml index f4ec69340a1..4c6d3039cf2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -124,7 +124,6 @@ nav: - Docker: 'installation/docker.md' - PatchMatch: 'installation/patchmatch.md' - Models: 'installation/models.md' - - Legacy Scripts: 'installation/legacy_scripts.md' - Workflows & Nodes: - Nodes Overview: 'nodes/overview.md' - Workflow Editor Basics: 'nodes/NODES.md' @@ -137,9 +136,16 @@ nav: - Invocation API: 'nodes/invocation-api.md' - Configuration: 'configuration.md' - Features: + - New to InvokeAI?: 'help/gettingStartedWithAI.md' - Low VRAM mode: 'features/low-vram.md' - Database: 'features/database.md' - - New to InvokeAI?: 'help/gettingStartedWithAI.md' + - Gallery: 'features/gallery.md' + - Hot Keys: 'features/hotkeys.md' + - Multi-User Mode: + - User Guide: 'multiuser/user_guide.md' + - Administrator Guide: 'multiuser/admin_guide.md' + - API Guide: 'multiuser/api_guide.md' + - Specification: 'multiuser/specification.md' - Contributing: - Overview: 'contributing/index.md' - Code of Conduct: 'CODE_OF_CONDUCT.md' @@ -150,6 +156,8 @@ nav: - Model Manager v2: 'contributing/MODEL_MANAGER.md' - Multiuser Mode: 'multiuser/specification.md' - Local Development: 'contributing/LOCAL_DEVELOPMENT.md' + - System Architecture: 'contributing/ARCHITECTURE.md' + - Hotkeys: 'contributing/HOTKEYS.md' - Testing: 'contributing/TESTS.md' - Frontend: - Overview: 'contributing/frontend/index.md'