gateway/docs/rbac_getrecordset_review.md
2025-12-07 22:00:55 +01:00

7.1 KiB

RBAC getRecordset() Review

Overview

Review of all getRecordset() calls in interfaceDbChatObjects.py and interfaceDbComponentObjects.py to determine which should be converted to getRecordsetWithRBAC().

Analysis Criteria

  • Convert to RBAC: User-facing data that should respect access control
  • Keep as-is: Internal/technical operations that don't need RBAC filtering

interfaceDbChatObjects.py

Summary: 14 calls found - ALL should be converted to getRecordsetWithRBAC()

All calls access user-facing data (ChatMessage, ChatDocument, ChatStat, ChatLog) and should respect RBAC even when:

  • Used in cascade delete operations (after parent access is verified)
  • Used to fetch child records (after parent access is verified)
  • Used for existence checks

Rationale: RBAC should be applied at every data access point to ensure consistent security and prevent potential bypass scenarios.

Detailed List:

  1. Line 760 - deleteWorkflow() - Cascade delete ChatStat

    • Action: Convert to getRecordsetWithRBAC(ChatStat, self.currentUser, recordFilter={"messageId": messageId})
    • Reason: Deleting related data should respect RBAC
  2. Line 765 - deleteWorkflow() - Cascade delete ChatDocument

    • Action: Convert to getRecordsetWithRBAC(ChatDocument, self.currentUser, recordFilter={"messageId": messageId})
    • Reason: Deleting related data should respect RBAC
  3. Line 773 - deleteWorkflow() - Cascade delete ChatStat (workflow level)

    • Action: Convert to getRecordsetWithRBAC(ChatStat, self.currentUser, recordFilter={"workflowId": workflowId})
    • Reason: Deleting related data should respect RBAC
  4. Line 778 - deleteWorkflow() - Cascade delete ChatLog

    • Action: Convert to getRecordsetWithRBAC(ChatLog, self.currentUser, recordFilter={"workflowId": workflowId})
    • Reason: Deleting related data should respect RBAC
  5. Line 821 - getMessages() - Fetch messages for workflow

    • Action: Convert to getRecordsetWithRBAC(ChatMessage, self.currentUser, recordFilter={"workflowId": workflowId})
    • Reason: Child records should still respect RBAC even if parent access is verified
  6. Line 1062 - updateMessage() - Check if message exists

    • Action: Convert to getRecordsetWithRBAC(ChatMessage, self.currentUser, recordFilter={"id": messageId})
    • Reason: Existence checks should respect RBAC
  7. Line 1167 - deleteMessage() - Cascade delete ChatStat

    • Action: Convert to getRecordsetWithRBAC(ChatStat, self.currentUser, recordFilter={"messageId": messageId})
    • Reason: Deleting related data should respect RBAC
  8. Line 1172 - deleteMessage() - Cascade delete ChatDocument

    • Action: Convert to getRecordsetWithRBAC(ChatDocument, self.currentUser, recordFilter={"messageId": messageId})
    • Reason: Deleting related data should respect RBAC
  9. Line 1199 - deleteFileFromMessage() - Get documents for message

    • Action: Convert to getRecordsetWithRBAC(ChatDocument, self.currentUser, recordFilter={"messageId": messageId})
    • Reason: Accessing related data should respect RBAC
  10. Line 1242 - getDocuments() - Get documents for message

    • Action: Convert to getRecordsetWithRBAC(ChatDocument, self.currentUser, recordFilter={"messageId": messageId})
    • Reason: Public method accessing user data should respect RBAC
  11. Line 1291 - getLogs() - Fetch logs for workflow

    • Action: Convert to getRecordsetWithRBAC(ChatLog, self.currentUser, recordFilter={"workflowId": workflowId})
    • Reason: Child records should still respect RBAC even if parent access is verified
  12. Line 1410 - getStats() - Fetch stats for workflow

    • Action: Convert to getRecordsetWithRBAC(ChatStat, self.currentUser, recordFilter={"workflowId": workflowId})
    • Reason: Child records should still respect RBAC even if parent access is verified
  13. Line 1460 - getUnifiedChatData() - Fetch messages for workflow

    • Action: Convert to getRecordsetWithRBAC(ChatMessage, self.currentUser, recordFilter={"workflowId": workflowId})
    • Reason: Child records should still respect RBAC even if parent access is verified
  14. Line 1501 - getUnifiedChatData() - Fetch logs for workflow

    • Action: Convert to getRecordsetWithRBAC(ChatLog, self.currentUser, recordFilter={"workflowId": workflowId})
    • Reason: Child records should still respect RBAC even if parent access is verified

interfaceDbComponentObjects.py

Summary: 3 calls found - 1 keep as-is, 2 should be converted

Detailed List:

  1. Line 149 - _initializeStandardPrompts() - Check if prompts exist

    • Action: KEEP AS-IS
    • Reason: This is initialization code that runs during bootstrap. It checks if any prompts exist to avoid re-initialization. Since this runs with root user context and is a system-level check, RBAC is not needed here.
  2. Line 947 - deleteFile() - Get FileData for deletion

    • Action: CONVERT to getRecordsetWithRBAC(FileData, self.currentUser, recordFilter={"id": fileId})
    • Reason: FileData stores binary data associated with FileItem. While it's a technical table, we should still respect RBAC for consistency and security. The file access was already checked via getFile(), but FileData access should also be RBAC-filtered.
  3. Line 1032 - getFileData() - Get FileData for reading

    • Action: CONVERT to getRecordsetWithRBAC(FileData, self.currentUser, recordFilter={"id": fileId})
    • Reason: FileData access should respect RBAC. The file access was already checked via getFile(), but FileData access should also be RBAC-filtered for consistency.

Note on FileData: FileData is a technical table storing binary file content. However, for consistency and security, RBAC should still be applied. If FileData doesn't have RBAC rules defined, the RBAC filter will effectively be a no-op (allowing access), but the pattern is consistent.


Implementation Priority

High Priority (User-facing data access)

  • All interfaceDbChatObjects.py calls (14 calls)
  • interfaceDbComponentObjects.py FileData calls (2 calls)

Low Priority (System initialization)

  • interfaceDbComponentObjects.py Prompt initialization check (1 call) - Keep as-is

Next Steps

  1. Convert all 14 calls in interfaceDbChatObjects.py to getRecordsetWithRBAC()
  2. Convert 2 FileData calls in interfaceDbComponentObjects.py to getRecordsetWithRBAC()
  3. Keep 1 Prompt initialization check as-is
  4. Test all changes to ensure RBAC filtering works correctly
  5. Verify cascade delete operations still work correctly with RBAC

Testing Checklist

After conversion, verify:

  • Workflow deletion still works (cascade deletes)
  • Message deletion still works (cascade deletes)
  • File deletion still works (FileData cleanup)
  • File reading still works (FileData access)
  • Child record access (messages, logs, stats, documents) respects RBAC
  • Users can only access data they have permission for
  • No performance degradation from RBAC filtering