buster/api/prds/active/api_chats_sharing_delete.md

209 lines
6.7 KiB
Markdown
Raw Normal View History

2025-03-20 02:51:37 +08:00
# API Chats Sharing - Delete Endpoint PRD
## Problem Statement
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
Users need the ability to remove sharing permissions for chats through a REST API endpoint.
## Technical Design
### Endpoint Specification
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
- **Method**: DELETE
- **Path**: /chats/:id/sharing
- **Description**: Removes sharing permissions for a chat
- **Authentication**: Required
- **Authorization**: User must have Owner or FullAccess permission for the chat
### Request Structure
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
```rust
2025-03-20 04:32:16 +08:00
// Array of emails to remove sharing permissions for
pub type DeleteShareRequest = Vec<String>;
2025-03-20 02:51:37 +08:00
```
### Response Structure
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
```rust
// Success response is a simple message
// Error responses include appropriate status codes and error messages
```
### Implementation Details
#### New Files
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
1. `/src/routes/rest/routes/chats/sharing/delete_sharing.rs` - REST handler for deleting sharing permissions
2. `/libs/handlers/src/chats/sharing/delete_sharing_handler.rs` - Business logic for deleting sharing permissions
#### REST Handler Implementation
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
```rust
// delete_sharing.rs
pub async fn delete_chat_sharing_rest_handler(
Extension(user): Extension<AuthenticatedUser>,
Path(id): Path<Uuid>,
2025-03-20 04:32:16 +08:00
Json(emails): Json<Vec<String>>,
2025-03-20 02:51:37 +08:00
) -> Result<ApiResponse<String>, (StatusCode, String)> {
tracing::info!("Processing DELETE request for chat sharing with ID: {}, user_id: {}", id, user.id);
2025-03-20 04:32:16 +08:00
match delete_chat_sharing_handler(&id, &user.id, emails).await {
Ok(_) => Ok(ApiResponse::JsonData("Sharing permissions removed successfully".to_string())),
2025-03-20 02:51:37 +08:00
Err(e) => {
tracing::error!("Error removing sharing permissions: {}", e);
// Map specific errors to appropriate status codes
2025-03-20 04:32:16 +08:00
let error_message = e.to_string();
if error_message.contains("not found") {
2025-03-20 02:51:37 +08:00
return Err((StatusCode::NOT_FOUND, format!("Chat not found: {}", e)));
2025-03-20 04:32:16 +08:00
} else if error_message.contains("permission") {
2025-03-20 02:51:37 +08:00
return Err((StatusCode::FORBIDDEN, format!("Insufficient permissions: {}", e)));
2025-03-20 04:32:16 +08:00
} else if error_message.contains("Invalid email") {
2025-03-20 02:51:37 +08:00
return Err((StatusCode::BAD_REQUEST, format!("Invalid email: {}", e)));
}
Err((StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to remove sharing permissions: {}", e)))
}
}
}
```
#### Handler Implementation
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
```rust
// delete_sharing_handler.rs
pub async fn delete_chat_sharing_handler(
chat_id: &Uuid,
user_id: &Uuid,
emails: Vec<String>,
) -> Result<()> {
// 1. Validate the chat exists
let chat = match get_chat_by_id(chat_id).await {
Ok(Some(chat)) => chat,
Ok(None) => return Err(anyhow!("Chat not found")),
Err(e) => return Err(anyhow!("Error fetching chat: {}", e)),
};
2025-03-20 04:32:16 +08:00
// 2. Check if user has permission to delete sharing for the chat (Owner or FullAccess)
2025-03-20 02:51:37 +08:00
let has_permission = has_permission(
*chat_id,
AssetType::Chat,
*user_id,
IdentityType::User,
AssetPermissionRole::FullAccess, // Owner role implicitly has FullAccess permissions
).await?;
if !has_permission {
return Err(anyhow!("User does not have permission to remove sharing for this chat"));
}
// 3. Process each email and remove sharing permissions
for email in emails {
match remove_share_by_email(
&email,
*chat_id,
AssetType::Chat,
).await {
Ok(_) => {
tracing::info!("Removed sharing permission for email: {} on chat: {}", email, chat_id);
},
Err(e) => {
tracing::error!("Failed to remove sharing for email {}: {}", email, e);
return Err(anyhow!("Failed to remove sharing for email {}: {}", email, e));
}
}
}
Ok(())
}
```
### Sharing Library Integration
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
This endpoint leverages the following functions from the sharing library:
1. `has_permission` from `@[api/libs/sharing/src]/check_asset_permission.rs`:
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
```rust
pub async fn has_permission(
asset_id: Uuid,
asset_type: AssetType,
identity_id: Uuid,
identity_type: IdentityType,
required_role: AssetPermissionRole,
) -> Result<bool>
```
2025-03-20 04:32:16 +08:00
This function checks if a user has the required permission level for an asset. It's used to verify that the user has Owner or FullAccess permission to delete sharing for the chat.
2025-03-20 02:51:37 +08:00
2. `remove_share_by_email` from `@[api/libs/sharing/src]/remove_asset_permissions.rs`:
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
```rust
pub async fn remove_share_by_email(
email: &str,
asset_id: Uuid,
asset_type: AssetType,
) -> Result<()>
```
2025-03-20 04:32:16 +08:00
This function removes sharing permissions for a specific email on a specific asset.
2025-03-20 02:51:37 +08:00
### Error Handling
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
The handler will return appropriate error responses:
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
- 404 Not Found - If the chat doesn't exist
2025-03-20 04:32:16 +08:00
- 403 Forbidden - If the user doesn't have permission to delete sharing for the chat
2025-03-20 02:51:37 +08:00
- 400 Bad Request - For invalid email addresses
- 500 Internal Server Error - For database errors or other unexpected issues
### Input Validation
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
- Email addresses must be properly formatted (contains '@')
- The chat ID must be a valid UUID
### Testing Strategy
#### Unit Tests
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
- Test permission validation logic
- Test error handling for non-existent chats
- Test error handling for unauthorized users
- Test error handling for invalid emails
2025-03-20 04:32:16 +08:00
- Test successful sharing deletions
2025-03-20 02:51:37 +08:00
#### Integration Tests
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
- Test DELETE /chats/:id/sharing with valid ID, authorized user, and valid emails
- Test DELETE /chats/:id/sharing with valid ID, unauthorized user
- Test DELETE /chats/:id/sharing with non-existent chat ID
- Test DELETE /chats/:id/sharing with invalid email formats
- Test DELETE /chats/:id/sharing with non-existent user emails
#### Test Cases
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
1. Should remove sharing permissions for valid emails
2025-03-20 04:32:16 +08:00
1. Should return 403 when user doesn't have Owner or FullAccess permission
1. Should return 404 when chat doesn't exist
1. Should return 400 when email is invalid
1. Should handle gracefully when trying to remove sharing for a user that doesn't have access
2025-03-20 02:51:37 +08:00
### Performance Considerations
2025-03-20 04:32:16 +08:00
- For bulk deletions with many emails, consider implementing a background job for processing
- Monitor database performance for large batches of delete operations
2025-03-20 02:51:37 +08:00
### Security Considerations
2025-03-20 04:32:16 +08:00
- Ensure that only users with Owner or FullAccess permission can delete sharing
2025-03-20 02:51:37 +08:00
- Validate email addresses to prevent injection attacks
- Implement rate limiting to prevent abuse
2025-03-20 04:32:16 +08:00
- Consider implementing notifications for users whose permissions have been removed
2025-03-20 02:51:37 +08:00
### Monitoring
2025-03-20 04:32:16 +08:00
2025-03-20 02:51:37 +08:00
- Log all requests with appropriate context
- Track performance metrics for the endpoint
- Monitor error rates and types
2025-03-20 04:32:16 +08:00
- Track sharing deletion operations by user for audit purposes