use anyhow::Result;
use clap::Args;
use surrealdb::engine::any::{self, connect};
use surrealdb::opt::Config;
use surrealdb::opt::capabilities::Capabilities;
use crate::cli::abstraction::auth::{CredentialsBuilder, CredentialsLevel};
use crate::cli::abstraction::{AuthArguments, DatabaseSelectionArguments};
#[derive(Args, Debug)]
pub struct DatabaseConnectionArguments {
#[arg(help = "Database endpoint to import to")]
#[arg(short = 'e', long = "endpoint")]
#[arg(default_value = "http://localhost:8000")]
#[arg(value_parser = super::validator::endpoint_valid)]
pub(crate) endpoint: String,
}
#[derive(Args, Debug)]
pub struct ImportCommandArguments {
#[arg(help = "Path to the SurrealQL file to import")]
#[arg(index = 1)]
file: String,
#[command(flatten)]
conn: DatabaseConnectionArguments,
#[command(flatten)]
auth: AuthArguments,
#[command(flatten)]
sel: DatabaseSelectionArguments,
}
pub async fn init(
ImportCommandArguments {
file,
conn: DatabaseConnectionArguments {
endpoint,
},
auth: AuthArguments {
username,
password,
token,
auth_level,
},
sel: DatabaseSelectionArguments {
namespace,
database,
},
}: ImportCommandArguments,
) -> Result<()> {
let config = Config::new().capabilities(Capabilities::all());
let is_local = any::__into_endpoint(&endpoint)?.parse_kind()?.is_local();
let client = if username.is_some() && password.is_some() && !is_local {
debug!("Connecting to the database engine with authentication");
let creds = CredentialsBuilder::default()
.with_username(username.clone())
.with_password(password.clone())
.with_namespace(namespace.clone())
.with_database(database.clone());
let client = connect(endpoint).await?;
debug!("Signing in to the database engine at '{:?}' level", auth_level);
match auth_level {
CredentialsLevel::Root => client.signin(creds.root()?).await?,
CredentialsLevel::Namespace => client.signin(creds.namespace()?).await?,
CredentialsLevel::Database => client.signin(creds.database()?).await?,
};
client
} else if token.is_some() && !is_local {
let client = connect(endpoint).await?;
if let Some(token) = token {
client.authenticate(token).await?;
}
client
} else {
debug!("Connecting to the database engine without authentication");
connect((endpoint, config)).await?
};
client.use_ns(namespace).use_db(database).await?;
client.import(file).await.inspect_err(|_| {
error!(
"Surreal import failed, import might only be partially completed or have failed entirely."
)
})?;
info!("Import executed with no errors");
Ok(())
}