data source and supabase create client

This commit is contained in:
dal 2025-03-24 13:45:59 -06:00
parent 04bc75526e
commit 89dffd1c6a
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
3 changed files with 42 additions and 19 deletions

View File

@ -1,6 +1,5 @@
use std::env; use std::env;
use dotenv::dotenv;
use reqwest::{Client, Error}; use reqwest::{Client, Error};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uuid::Uuid; use uuid::Uuid;
@ -50,8 +49,6 @@ pub struct SupabaseClient {
impl SupabaseClient { impl SupabaseClient {
// Initialize the client with env variables // Initialize the client with env variables
pub fn new() -> Result<Self, env::VarError> { pub fn new() -> Result<Self, env::VarError> {
dotenv().ok(); // Load .env file
let url = env::var("SUPABASE_URL")?; let url = env::var("SUPABASE_URL")?;
let service_role_key = env::var("SUPABASE_SERVICE_ROLE_KEY")?; let service_role_key = env::var("SUPABASE_SERVICE_ROLE_KEY")?;
@ -146,6 +143,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_supabase_client() { async fn test_supabase_client() {
dotenv::dotenv().ok();
let client = SupabaseClient::new().expect("Failed to initialize client"); let client = SupabaseClient::new().expect("Failed to initialize client");
// 1. Create a user // 1. Create a user

View File

@ -33,7 +33,7 @@ pub struct DatabricksCredentials {
pub api_key: String, pub api_key: String,
pub warehouse_id: String, pub warehouse_id: String,
pub default_catalog: String, pub default_catalog: String,
pub default_schema: String, pub default_schema: Option<String>,
} }
// can get rid of catalog_name // can get rid of catalog_name
@ -76,13 +76,13 @@ pub struct PostgresCredentials {
pub jump_host: Option<String>, pub jump_host: Option<String>,
pub ssh_username: Option<String>, pub ssh_username: Option<String>,
pub ssh_private_key: Option<String>, pub ssh_private_key: Option<String>,
#[serde(alias = "database")]
pub default_database: String, pub default_database: String,
pub default_schema: String, pub default_schema: Option<String>,
} }
// can get rid of database and schema // can get rid of database and schema
// Deprecated: REDSHIFT just uses postgres credentials
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RedshiftCredentials { pub struct RedshiftCredentials {
pub host: String, pub host: String,
@ -90,7 +90,7 @@ pub struct RedshiftCredentials {
pub username: String, pub username: String,
pub password: String, pub password: String,
pub default_database: String, pub default_database: String,
pub default_schema: String, pub default_schema: Option<String>,
} }
// can get rid of database and schemas // can get rid of database and schemas
@ -102,8 +102,9 @@ pub struct SnowflakeCredentials {
pub username: String, pub username: String,
pub password: String, pub password: String,
pub role: Option<String>, pub role: Option<String>,
#[serde(alias = "database")]
pub default_database: String, pub default_database: String,
pub default_schema: String, pub default_schema: Option<String>,
} }
// can get rid of schemas and database id // can get rid of schemas and database id
@ -118,7 +119,7 @@ pub struct SqlServerCredentials {
pub ssh_username: Option<String>, pub ssh_username: Option<String>,
pub ssh_private_key: Option<String>, pub ssh_private_key: Option<String>,
pub default_database: String, pub default_database: String,
pub default_schema: String, pub default_schema: Option<String>,
} }
// can get rid of schemas and // can get rid of schemas and

View File

@ -1,10 +1,7 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use database::{ use database::{
enums::{AssetPermissionRole, AssetType, IdentityType}, client::SupabaseClient, enums::{AssetPermissionRole, AssetType, IdentityType}, models::AssetPermission, pool::get_pg_pool, schema::asset_permissions
models::AssetPermission,
pool::get_pg_pool,
schema::asset_permissions,
}; };
use diesel::{prelude::*, upsert::excluded}; use diesel::{prelude::*, upsert::excluded};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
@ -101,9 +98,33 @@ pub async fn create_share_by_email(
} }
// Find the user by email // Find the user by email
let user = find_user_by_email(email) let user = match find_user_by_email(email).await? {
.await? Some(user) => user,
.ok_or_else(|| SharingError::UserNotFound(email.to_string()))?; 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 the share for the user
create_share( create_share(
@ -129,7 +150,10 @@ pub async fn create_shares_bulk(
.iter() .iter()
.any(|s| matches!(s.asset_type, AssetType::Dashboard | AssetType::Thread)) .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<AssetPermission> = shares let permissions: Vec<AssetPermission> = shares