From 89dffd1c6a50992250a4c31b9b6264caa78af02d Mon Sep 17 00:00:00 2001 From: dal Date: Mon, 24 Mar 2025 13:45:59 -0600 Subject: [PATCH] data source and supabase create client --- api/libs/database/src/supabase/client.rs | 4 +- api/libs/query_engine/src/credentials.rs | 13 +++--- .../sharing/src/create_asset_permission.rs | 44 ++++++++++++++----- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/api/libs/database/src/supabase/client.rs b/api/libs/database/src/supabase/client.rs index c637db664..a699d6309 100644 --- a/api/libs/database/src/supabase/client.rs +++ b/api/libs/database/src/supabase/client.rs @@ -1,6 +1,5 @@ use std::env; -use dotenv::dotenv; use reqwest::{Client, Error}; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -50,8 +49,6 @@ pub struct SupabaseClient { impl SupabaseClient { // Initialize the client with env variables pub fn new() -> Result { - dotenv().ok(); // Load .env file - let url = env::var("SUPABASE_URL")?; let service_role_key = env::var("SUPABASE_SERVICE_ROLE_KEY")?; @@ -146,6 +143,7 @@ mod tests { #[tokio::test] async fn test_supabase_client() { + dotenv::dotenv().ok(); let client = SupabaseClient::new().expect("Failed to initialize client"); // 1. Create a user diff --git a/api/libs/query_engine/src/credentials.rs b/api/libs/query_engine/src/credentials.rs index 7617ea2ec..629d8c241 100644 --- a/api/libs/query_engine/src/credentials.rs +++ b/api/libs/query_engine/src/credentials.rs @@ -33,7 +33,7 @@ pub struct DatabricksCredentials { pub api_key: String, pub warehouse_id: String, pub default_catalog: String, - pub default_schema: String, + pub default_schema: Option, } // can get rid of catalog_name @@ -76,13 +76,13 @@ pub struct PostgresCredentials { pub jump_host: Option, pub ssh_username: Option, pub ssh_private_key: Option, + #[serde(alias = "database")] pub default_database: String, - pub default_schema: String, + pub default_schema: Option, } // can get rid of database and schema -// Deprecated: REDSHIFT just uses postgres credentials #[derive(Serialize, Deserialize, Debug, Clone)] pub struct RedshiftCredentials { pub host: String, @@ -90,7 +90,7 @@ pub struct RedshiftCredentials { pub username: String, pub password: String, pub default_database: String, - pub default_schema: String, + pub default_schema: Option, } // can get rid of database and schemas @@ -102,8 +102,9 @@ pub struct SnowflakeCredentials { pub username: String, pub password: String, pub role: Option, + #[serde(alias = "database")] pub default_database: String, - pub default_schema: String, + pub default_schema: Option, } // can get rid of schemas and database id @@ -118,7 +119,7 @@ pub struct SqlServerCredentials { pub ssh_username: Option, pub ssh_private_key: Option, pub default_database: String, - pub default_schema: String, + pub default_schema: Option, } // can get rid of schemas and diff --git a/api/libs/sharing/src/create_asset_permission.rs b/api/libs/sharing/src/create_asset_permission.rs index 01e56adb5..5f2d36afd 100644 --- a/api/libs/sharing/src/create_asset_permission.rs +++ b/api/libs/sharing/src/create_asset_permission.rs @@ -1,10 +1,7 @@ use anyhow::{Context, Result}; use chrono::{DateTime, Utc}; use database::{ - enums::{AssetPermissionRole, AssetType, IdentityType}, - models::AssetPermission, - pool::get_pg_pool, - schema::asset_permissions, + client::SupabaseClient, enums::{AssetPermissionRole, AssetType, IdentityType}, models::AssetPermission, pool::get_pg_pool, schema::asset_permissions }; use diesel::{prelude::*, upsert::excluded}; use diesel_async::RunQueryDsl; @@ -101,9 +98,33 @@ pub async fn create_share_by_email( } // Find the user by email - let user = find_user_by_email(email) - .await? - .ok_or_else(|| SharingError::UserNotFound(email.to_string()))?; + let user = match find_user_by_email(email).await? { + Some(user) => user, + None => { + // User doesn't exist, create a new user in Supabase Auth + // This will automatically create the user in the database through triggers + let user_id = Uuid::new_v4(); + let supabase_client = SupabaseClient::new() + .context("Failed to initialize Supabase client")?; + + // Create user in Supabase Auth + supabase_client + .create_user(user_id, email) + .await + .context("Failed to create user in Supabase Auth")?; + + // Wait for a moment to allow the database trigger to create the user + tokio::time::sleep(tokio::time::Duration::from_millis(500)).await; + + // Try to find the user again after creation + find_user_by_email(email).await?.ok_or_else(|| { + SharingError::UserNotFound(format!( + "User was created in Auth but not found in database: {}", + email + )) + })? + } + }; // Create the share for the user create_share( @@ -129,7 +150,10 @@ pub async fn create_shares_bulk( .iter() .any(|s| matches!(s.asset_type, AssetType::Dashboard | AssetType::Thread)) { - return Err(SharingError::DeprecatedAssetType("Cannot create permissions for deprecated asset types".to_string()).into()); + return Err(SharingError::DeprecatedAssetType( + "Cannot create permissions for deprecated asset types".to_string(), + ) + .into()); } let permissions: Vec = shares @@ -173,7 +197,7 @@ pub async fn create_shares_bulk( #[cfg(test)] mod tests { use super::*; - + use database::enums::{AssetPermissionRole, AssetType}; use uuid::Uuid; @@ -187,7 +211,7 @@ mod tests { AssetPermissionRole::Viewer, Uuid::new_v4(), )); - + assert!(result.is_err()); let err = result.unwrap_err().to_string(); assert!(err.contains("Invalid email"));