mirror of https://github.com/buster-so/buster.git
Created sharing create permissions
This commit is contained in:
parent
2058b0551f
commit
7a63b97e35
|
@ -13,6 +13,7 @@ tracing = { workspace = true }
|
|||
uuid = { workspace = true }
|
||||
diesel = { workspace = true }
|
||||
diesel-async = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
database = { path = "../database" }
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::{Context, Result};
|
||||
use anyhow::{Context, Result, anyhow};
|
||||
use chrono::{DateTime, Utc};
|
||||
use database::{
|
||||
enums::{AssetPermissionRole, AssetType, IdentityType},
|
||||
|
@ -10,6 +10,9 @@ use diesel::{prelude::*, upsert::excluded};
|
|||
use diesel_async::RunQueryDsl;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::errors::SharingError;
|
||||
use crate::types::find_user_by_email;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ShareCreationInput {
|
||||
pub asset_id: Uuid,
|
||||
|
@ -70,6 +73,53 @@ pub async fn create_share(
|
|||
.context("Failed to create/update asset permission")
|
||||
}
|
||||
|
||||
/// Creates or updates an asset permission for a user identified by email
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `email` - The email address of the user to grant access to
|
||||
/// * `asset_id` - The ID of the asset to share
|
||||
/// * `asset_type` - The type of asset (must not be deprecated)
|
||||
/// * `role` - The permission role to assign (must be Owner or FullAccess)
|
||||
/// * `created_by` - The ID of the user creating the permission
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Result<AssetPermission>` - The created or updated permission record
|
||||
pub async fn create_share_by_email(
|
||||
email: &str,
|
||||
asset_id: Uuid,
|
||||
asset_type: AssetType,
|
||||
role: AssetPermissionRole,
|
||||
created_by: Uuid,
|
||||
) -> Result<AssetPermission> {
|
||||
// Validate asset type is not deprecated
|
||||
if matches!(asset_type, AssetType::Dashboard | AssetType::Thread) {
|
||||
return Err(anyhow!(SharingError::DeprecatedAssetType(format!("{:?}", asset_type))));
|
||||
}
|
||||
|
||||
// Validate role is either Owner or FullAccess
|
||||
if !matches!(role, AssetPermissionRole::Owner | AssetPermissionRole::FullAccess) {
|
||||
return Err(anyhow!(SharingError::InvalidPermissionRole(format!(
|
||||
"Role must be Owner or FullAccess, got {:?}",
|
||||
role
|
||||
))));
|
||||
}
|
||||
|
||||
// Find the user by email
|
||||
let user = find_user_by_email(email).await?
|
||||
.ok_or_else(|| anyhow!(SharingError::UserNotFound(email.to_string())))?;
|
||||
|
||||
// Create or update the permission
|
||||
create_share(
|
||||
asset_id,
|
||||
asset_type,
|
||||
user.id,
|
||||
IdentityType::User,
|
||||
role,
|
||||
created_by,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Creates multiple sharing records in bulk
|
||||
pub async fn create_shares_bulk(
|
||||
shares: Vec<ShareCreationInput>,
|
||||
|
@ -122,3 +172,47 @@ pub async fn create_shares_bulk(
|
|||
.await
|
||||
.context("Failed to create/update asset permissions in bulk")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::errors::SharingError;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_share_by_email_validates_role() {
|
||||
// Test that only Owner and FullAccess roles are accepted
|
||||
let result = create_share_by_email(
|
||||
"test@example.com",
|
||||
Uuid::new_v4(),
|
||||
AssetType::Chat,
|
||||
AssetPermissionRole::CanEdit,
|
||||
Uuid::new_v4(),
|
||||
)
|
||||
.await;
|
||||
|
||||
assert!(result.is_err());
|
||||
let err = result.unwrap_err().to_string();
|
||||
assert!(err.contains("Role must be Owner or FullAccess"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_share_by_email_validates_asset_type() {
|
||||
// Test that deprecated asset types are rejected
|
||||
let result = create_share_by_email(
|
||||
"test@example.com",
|
||||
Uuid::new_v4(),
|
||||
AssetType::Dashboard, // Deprecated asset type
|
||||
AssetPermissionRole::Owner,
|
||||
Uuid::new_v4(),
|
||||
)
|
||||
.await;
|
||||
|
||||
assert!(result.is_err());
|
||||
let err = result.unwrap_err().to_string();
|
||||
assert!(err.contains("Asset type"));
|
||||
assert!(err.contains("is deprecated"));
|
||||
}
|
||||
|
||||
// Note: Additional integration tests would be needed to test the database interactions
|
||||
// These would require mocking the database or using a test database
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum SharingError {
|
||||
#[error("User not found: {0}")]
|
||||
UserNotFound(String),
|
||||
|
||||
#[error("Invalid permission role: {0}")]
|
||||
InvalidPermissionRole(String),
|
||||
|
||||
#[error("Asset type {0:?} is deprecated")]
|
||||
DeprecatedAssetType(String),
|
||||
|
||||
#[error("Permission denied: {0}")]
|
||||
PermissionDenied(String),
|
||||
|
||||
#[error("Database error: {0}")]
|
||||
DatabaseError(#[from] diesel::result::Error),
|
||||
|
||||
#[error("Unknown error: {0}")]
|
||||
Unknown(String),
|
||||
}
|
|
@ -1,9 +1,13 @@
|
|||
// pub mod check_asset_permission;
|
||||
pub mod create_asset_permission;
|
||||
pub mod errors;
|
||||
pub mod list_asset_permissions;
|
||||
pub mod remove_asset_permissions;
|
||||
pub mod types;
|
||||
|
||||
// pub use check_asset_permission::check_access;
|
||||
pub use create_asset_permission::create_share;
|
||||
pub use create_asset_permission::create_share_by_email;
|
||||
pub use list_asset_permissions::list_shares;
|
||||
pub use remove_asset_permissions::remove_share;
|
||||
pub use types::find_user_by_email;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
use anyhow::{Context, Result};
|
||||
use database::{
|
||||
models::User,
|
||||
pool::get_pg_pool,
|
||||
schema::users,
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
use diesel_async::RunQueryDsl;
|
||||
|
||||
/// Finds a user by their email address
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `email` - The email address to search for
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Result<Option<User>>` - The user if found, None otherwise
|
||||
pub async fn find_user_by_email(email: &str) -> Result<Option<User>> {
|
||||
let mut conn = get_pg_pool().get().await?;
|
||||
|
||||
users::table
|
||||
.filter(users::email.eq(email))
|
||||
.first::<User>(&mut conn)
|
||||
.await
|
||||
.optional()
|
||||
.context("Failed to look up user by email")
|
||||
}
|
|
@ -77,17 +77,17 @@ The function should handle the following error cases:
|
|||
- Error handling utilities
|
||||
|
||||
## Implementation Plan
|
||||
1. Enhance the `create_asset_permission.rs` file
|
||||
2. Implement the `create_share_by_email` function
|
||||
3. Add validation and error handling
|
||||
4. Write tests
|
||||
5. Update the library exports in `lib.rs`
|
||||
1. ✅ Enhance the `create_asset_permission.rs` file
|
||||
2. ✅ Implement the `create_share_by_email` function
|
||||
3. ✅ Add validation and error handling
|
||||
4. ✅ Write tests
|
||||
5. ✅ Update the library exports in `lib.rs`
|
||||
|
||||
## Success Criteria
|
||||
- Function correctly creates or updates permissions using email addresses
|
||||
- Appropriate validation and error handling is implemented
|
||||
- Tests pass successfully
|
||||
- Code is well-documented
|
||||
- ✅ Function correctly creates or updates permissions using email addresses
|
||||
- ✅ Appropriate validation and error handling is implemented
|
||||
- ✅ Tests pass successfully
|
||||
- ✅ Code is well-documented
|
||||
|
||||
## Permission Requirements
|
||||
- Requires Owner or FullAccess permission to execute
|
||||
|
|
Loading…
Reference in New Issue