trilium/PR_COMMENT.md
Somoru 08f8a6c7ee feat: implement collaborative multi-user support with permission-aware sync
- Add database migration v234 for collaborative multi-user schema
- Implement permission system with granular access control (read/write/admin)
- Add group management for organizing users
- Implement permission-aware sync filtering (pull and push)
- Add automatic note ownership tracking via CLS
- Create 14 RESTful API endpoints for permissions and groups
- Update authentication for multi-user login
- Maintain backward compatibility with single-user mode
- Add comprehensive documentation

Addresses PR #7441 critical sync blocker issue.
All backend functionality complete and production-ready.
2025-10-22 21:28:22 +05:30

6.2 KiB

Comment for PR #7441

Addressing Review Feedback

Thank you for the detailed review. I've carefully considered all concerns raised, particularly the critical sync support issue. I'd like to present an alternative implementation approach that addresses these concerns.

The Critical Blocker: Sync Support

@eliandoran's concern:

"However, from your statement I also understand that syncing does not work when multi-user is enabled? This is critical as the core of Trilium is based on this, otherwise people will not be able to use the application on multiple devices."

I completely agree this is essential. I've implemented a different architectural approach that provides full sync support through permission-aware filtering.

Solution: Permission-Based Sync Filtering

The key is filtering sync data by user permissions rather than isolating users completely:

Pull Sync (Server → Client):

// apps/server/src/routes/api/sync.ts
async function getChanged(req: Request) {
    const userId = req.session.userId || 1;
    let entityChanges = syncService.getEntityChanges(lastSyncId);
    
    // Filter by user's accessible notes
    entityChanges = permissions.filterEntityChangesForUser(userId, entityChanges);
    
    return entityChanges;
}

Push Sync (Client → Server):

async function update(req: Request) {
    for (const entity of entities) {
        if (!permissions.checkNoteAccess(userId, noteId, 'write')) {
            throw new ValidationError('No write permission');
        }
    }
}

This approach:

  • Users can sync to multiple devices
  • Each user receives only notes they have permission to access
  • Shared notes sync to all permitted users
  • Authentication remains local per instance (security)

Collaborative Model vs. Isolated Users

Based on discussions in issue #4956, the requirement appears to be collaborative note sharing, not just isolated multi-tenancy. My implementation provides:

Database Schema:

  • users - User accounts with authentication
  • groups - User groups for easier permission management
  • note_ownership - Tracks who created each note
  • note_permissions - Granular access control (read/write/admin per note)

Example Use Case:

  1. Alice creates "Shopping List" note (auto-owned by Alice)
  2. Alice shares with Bob: POST /api/notes/shoppingList/share {"granteeType":"user","granteeId":2,"permission":"write"}
  3. Bob syncs to his devices → receives "Shopping List"
  4. Bob adds items on mobile → changes sync back
  5. Alice syncs her devices → receives Bob's updates

Implementation Details

Core Services:

  • permissions.ts (11 functions) - Access control and sync filtering
  • group_management.ts (14 functions) - Group lifecycle management
  • user_management_collaborative.ts (10 functions) - Secure authentication

API Endpoints (14 total):

  • 6 permission management endpoints
  • 8 group management endpoints

Integration:

  • Sync routes modified for permission filtering
  • Login updated for multi-user authentication
  • Note creation automatically tracks ownership via CLS
  • All routes registered and functional

Security:

  • scrypt password hashing with timing attack protection
  • Parameterized SQL queries
  • Input validation and sanitization
  • Role-based access control

Documentation

I've provided comprehensive documentation:

  • MULTI_USER_README.md - User guide with API examples
  • COLLABORATIVE_ARCHITECTURE.md - Technical architecture details
  • Complete API reference with curl examples
  • Migration documentation and troubleshooting guide

Addressing Specific Comments

@eliandoran: "Lacks actual functionality"

  • Complete user management, authentication, and permission system implemented
  • All API endpoints functional
  • Multi-user login working

@eliandoran: "No technical/user documentation"

  • 5 comprehensive documentation files provided
  • API reference with examples
  • Architecture documentation

@eliandoran: "How are users synchronized across instances?"

  • Users are NOT synchronized (authentication stays local per instance for security)
  • Content is synchronized with permission filtering
  • Each instance maintains its own user accounts

@rom1dep: "Consider simpler proxy approach"

  • Proxy approach doesn't enable collaborative note sharing
  • The bounty appears to require actual collaboration, not just isolated instances

Comparison

Aspect Original PR #7441 Alternative Implementation
Sync Support Not implemented Permission-aware filtering
Multi-Device Not functional Full support per user
Note Sharing Isolated users Granular permissions
Groups Not implemented Full group management
Documentation Basic Comprehensive

Testing

  • Zero TypeScript errors
  • Manual testing complete
  • Migration tested with existing data
  • Sync filtering validated
  • Backward compatible (single-user mode preserved)

Files Modified/Created

Core Implementation:

  • apps/server/src/migrations/0234__multi_user_support.ts
  • apps/server/src/services/permissions.ts
  • apps/server/src/services/group_management.ts
  • apps/server/src/services/user_management_collaborative.ts
  • apps/server/src/routes/api/permissions.ts
  • apps/server/src/routes/api/groups.ts

Integration:

  • apps/server/src/routes/api/sync.ts (permission filtering)
  • apps/server/src/routes/login.ts (multi-user auth)
  • apps/server/src/services/auth.ts (CLS integration)
  • apps/server/src/services/notes.ts (ownership tracking)
  • apps/server/src/routes/routes.ts (route registration)

Backward Compatibility

  • Single-user installations continue to work unchanged
  • Migration creates admin user from existing credentials
  • All existing notes assigned to admin (userId=1)
  • Session defaults to userId=1 for compatibility

Next Steps

I'm happy to:

  1. Discuss the architectural approach
  2. Demonstrate the sync functionality
  3. Make any adjustments based on feedback
  4. Provide additional documentation if needed

The implementation is available on branch feat/multi-user-support for review.


Note: This is an alternative implementation approach focused on collaborative multi-user with full sync support, as opposed to the isolated multi-tenancy approach in the original PR.