# Tenant User Management Implementation ## Overview This document describes the implementation of tenant user management from the central admin interface. Central administrators can now view and create users for any tenant directly from the tenant detail page. ## Features ### 1. View Tenant Users - Related list on tenant detail page showing all users for that tenant - Displays: email, firstName, lastName, createdAt - Fetches data directly from the tenant's database ### 2. Create Tenant Users - Modal dialog for creating new users in a tenant - Form fields: - Email (required) - Password (required) - First Name (optional) - Last Name (optional) - Passwords are automatically hashed with bcrypt - Creates user directly in the tenant's database ## Architecture ### Backend Implementation **File:** `backend/src/tenant/central-admin.controller.ts` #### Get Tenant Users Endpoint ```typescript GET /central/tenants/:id/users ``` - Connects to the tenant's database using `TenantDatabaseService` - Queries the `users` table - Returns array of user records #### Create Tenant User Endpoint ```typescript POST /central/tenants/:id/users ``` - Accepts: `{ email, password, firstName?, lastName? }` - Hashes password with bcrypt (10 rounds) - Creates user in tenant database with timestamps - Returns created user record **Key Implementation Details:** - Uses `tenantDbService.getTenantKnex(tenantId)` to get tenant DB connection - Connection pooling ensures efficient database access - Password hashing is done server-side for security ### Frontend Implementation #### Components **File:** `frontend/components/TenantUserDialog.vue` - Reusable modal dialog for creating tenant users - Form validation (email and password required) - Loading states and error handling - Emits 'created' event on success for list refresh **Props:** - `open: boolean` - Dialog visibility state - `tenantId: string` - ID of tenant to create user for - `tenantName?: string` - Display name of tenant **Events:** - `update:open` - Sync dialog visibility - `created` - User successfully created #### Page Integration **File:** `frontend/pages/central/tenants/[[recordId]]/[[view]].vue` **Added State:** ```typescript const showTenantUserDialog = ref(false) const tenantUserDialogTenantId = ref('') ``` **Handler:** ```typescript const handleCreateRelated = (objectApiName: string, parentId: string) => { if (objectApiName.includes('tenants/:parentId/users')) { tenantUserDialogTenantId.value = parentId showTenantUserDialog.value = true return } // ... standard navigation for other related lists } ``` **Refresh Handler:** ```typescript const handleTenantUserCreated = async () => { // Refresh current record to update related lists if (recordId.value && recordId.value !== 'new') { await fetchRecord(recordId.value) } } ``` #### Configuration **File:** `frontend/composables/useCentralEntities.ts` Added to `tenantDetailConfig.relatedLists`: ```typescript { title: 'Tenant Users', relationName: 'users', objectApiName: 'tenants/:parentId/users', fields: [ { name: 'email', label: 'Email', type: 'TEXT', required: true }, { name: 'firstName', label: 'First Name', type: 'TEXT' }, { name: 'lastName', label: 'Last Name', type: 'TEXT' }, { name: 'createdAt', label: 'Created', type: 'DATE_TIME' } ], canCreate: true } ``` **Key Details:** - `objectApiName: 'tenants/:parentId/users'` - Special format for nested resource - `:parentId` placeholder is replaced with actual tenant ID at runtime - `canCreate: true` enables the "New" button in the related list #### Related List Component **File:** `frontend/components/RelatedList.vue` **Dynamic API Path Resolution:** ```typescript let apiPath = props.config.objectApiName.replace(':parentId', props.parentId) const response = await api.get(`/${apiPath}`, { params: { [parentField]: props.parentId } }) ``` This allows the component to handle nested resource paths like `tenants/:parentId/users`. ## User Flow ### Creating a Tenant User 1. Navigate to Central Admin → Tenants 2. Click on a tenant to view details 3. Scroll to "Tenant Users" related list 4. Click "New" button 5. Fill in the form: - Enter email address - Set password - Optionally add first and last name 6. Click "Create User" 7. Dialog closes and related list refreshes with new user ### Viewing Tenant Users 1. Navigate to Central Admin → Tenants 2. Click on a tenant to view details 3. Scroll to "Tenant Users" related list 4. View table with all users for that tenant 5. See email, name, and creation date for each user ## Security Considerations ### Password Handling - Passwords are sent over HTTPS - Backend hashes passwords with bcrypt (10 rounds) before storage - Passwords never stored in plain text - Hashing is done server-side, not client-side ### Access Control - Only central admin users can access these endpoints - Protected by authentication middleware - Tenant database connections use secure connection pooling ### Database Access - Central admin connects to tenant databases on-demand - Connections are cached but validated before use - No direct SQL injection risk (using Knex query builder) ## Database Schema ### Tenant User Table Structure ```sql CREATE TABLE users ( id VARCHAR(36) PRIMARY KEY, email VARCHAR(255) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, firstName VARCHAR(255), lastName VARCHAR(255), createdAt DATETIME, updatedAt DATETIME -- Additional fields may exist in actual schema ) ``` ## API Reference ### Get Tenant Users **Request:** ```http GET /api/central/tenants/{tenantId}/users Authorization: Bearer ``` **Response:** ```json [ { "id": "uuid", "email": "user@example.com", "firstName": "John", "lastName": "Doe", "createdAt": "2025-01-26T12:00:00Z", "updatedAt": "2025-01-26T12:00:00Z" } ] ``` ### Create Tenant User **Request:** ```http POST /api/central/tenants/{tenantId}/users Authorization: Bearer Content-Type: application/json { "email": "newuser@example.com", "password": "SecurePassword123!", "firstName": "Jane", "lastName": "Smith" } ``` **Response:** ```json { "id": "uuid", "email": "newuser@example.com", "firstName": "Jane", "lastName": "Smith", "createdAt": "2025-01-26T12:00:00Z", "updatedAt": "2025-01-26T12:00:00Z" } ``` ## Testing ### Manual Testing Steps 1. **Setup:** - Ensure Docker containers are running - Have at least one tenant created - Be logged in as central admin 2. **View Users:** - Navigate to /central/tenants - Click on a tenant - Verify "Tenant Users" related list appears - Verify existing users are displayed 3. **Create User:** - Click "New" in Tenant Users section - Verify dialog opens - Fill in required fields (email, password) - Click "Create User" - Verify success message - Verify dialog closes - Verify new user appears in list 4. **Error Handling:** - Try creating user without email - Try creating user without password - Try creating user with duplicate email - Verify appropriate error messages ### Automated Testing (Future) ```typescript describe('Tenant User Management', () => { it('should fetch tenant users', async () => { const response = await api.get('/central/tenants/tenant-id/users') expect(response).toBeInstanceOf(Array) }) it('should create tenant user', async () => { const newUser = { email: 'test@example.com', password: 'password123', firstName: 'Test', lastName: 'User' } const response = await api.post('/central/tenants/tenant-id/users', newUser) expect(response.email).toBe(newUser.email) expect(response.password).toBeUndefined() // Should not return password }) }) ``` ## Future Enhancements ### Planned Features 1. **Full CRUD Operations:** - Edit tenant user details - Delete tenant users - Update passwords 2. **Role Management:** - Assign roles to users during creation - View and edit user roles - Permission management 3. **User Navigation:** - Click on user to view details - Dedicated user detail page - Activity history 4. **Bulk Operations:** - Create multiple users via CSV import - Bulk role assignment - Bulk user activation/deactivation 5. **Password Management:** - Password reset functionality - Force password change on next login - Password strength indicators 6. **Audit Logging:** - Track user creation by central admin - Log user modifications - Export audit logs 7. **Search and Filter:** - Search users by email/name - Filter by role/status - Advanced filtering options ## Implementation Notes ### Design Decisions 1. **Modal vs Navigation:** - Chose modal dialog over page navigation - Reason: Keeps user in context of tenant detail page - Better UX for quick user creation 2. **Special API Path Format:** - Used `tenants/:parentId/users` format - Reason: Indicates nested resource structure - Clear relationship between tenant and users 3. **Separate Dialog Component:** - Created reusable TenantUserDialog component - Reason: Could be reused in other contexts - Easier to maintain and test 4. **Server-Side Password Hashing:** - Hash passwords in backend, not frontend - Reason: Security best practice - Consistent with authentication flow ### Known Limitations 1. **No Password Validation:** - Currently no minimum password requirements - Could add password strength validation 2. **No Email Validation:** - Basic email format check only - Could add email verification 3. **No User Status:** - Users are created as active by default - No activation/deactivation workflow 4. **No Role Assignment:** - Users created without specific roles - Role management to be added ## Related Documentation - [RELATED_LISTS_IMPLEMENTATION.md](RELATED_LISTS_IMPLEMENTATION.md) - Related lists feature - [CENTRAL_ADMIN_AUTH_GUIDE.md](CENTRAL_ADMIN_AUTH_GUIDE.md) - Central admin authentication - [MULTI_TENANT_IMPLEMENTATION.md](MULTI_TENANT_IMPLEMENTATION.md) - Multi-tenancy architecture - [TENANT_MIGRATION_GUIDE.md](TENANT_MIGRATION_GUIDE.md) - Tenant database setup ## Troubleshooting ### Common Issues **Issue: "Cannot GET /api/api/central/tenants/:id/users"** - Cause: Double API prefix - Solution: Check that baseUrl in useApi doesn't include /api prefix **Issue: "Dialog doesn't open"** - Check: showTenantUserDialog state is being set - Check: Dialog component is imported correctly - Check: v-model:open binding is correct **Issue: "User not appearing in list after creation"** - Check: handleTenantUserCreated is calling fetchRecord - Check: API returning correct data - Check: Related list config matches API response fields **Issue: "Cannot create user - validation error"** - Ensure email and password are filled - Check network tab for actual error from backend - Verify tenant database schema matches expected structure **Issue: "Password not hashing"** - Verify bcrypt is installed in backend - Check backend logs for hashing errors - Ensure password field is being passed to backend