feat(rust): Store API endpoint per account for better environment isolation
- Add endpoint field to accounts database table with default to production API - Update Account model to include endpoint field - Add --endpoint flag to account add command only - Remove ENTE_ENDPOINT environment variable support - Update account list to display endpoints in readable format - Each account now maintains its own endpoint, preventing confusion between test and production environments Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,10 @@ pub enum AccountSubcommands {
|
||||
#[arg(long, default_value = "photos")]
|
||||
app: String,
|
||||
|
||||
/// API endpoint (defaults to https://api.ente.io)
|
||||
#[arg(long, default_value = "https://api.ente.io")]
|
||||
endpoint: String,
|
||||
|
||||
/// Export directory path
|
||||
#[arg(long)]
|
||||
export_dir: Option<String>,
|
||||
|
||||
@@ -18,8 +18,9 @@ pub async fn handle_account_command(cmd: AccountCommand, storage: &Storage) -> R
|
||||
email,
|
||||
password,
|
||||
app,
|
||||
endpoint,
|
||||
export_dir,
|
||||
} => add_account(storage, email, password, app, export_dir).await,
|
||||
} => add_account(storage, email, password, app, endpoint, export_dir).await,
|
||||
AccountSubcommands::Update { email, dir, app } => {
|
||||
update_account(storage, &email, &dir, &app).await
|
||||
}
|
||||
@@ -36,14 +37,24 @@ async fn list_accounts(storage: &Storage) -> Result<()> {
|
||||
}
|
||||
|
||||
println!("\nConfigured accounts:\n");
|
||||
println!("{:<30} {:<10} {:<40}", "Email", "App", "Export Directory");
|
||||
println!("{}", "-".repeat(80));
|
||||
println!("{:<30} {:<10} {:<30} {:<40}", "Email", "App", "Endpoint", "Export Directory");
|
||||
println!("{}", "-".repeat(110));
|
||||
|
||||
for account in accounts {
|
||||
// Shorten endpoint display for better readability
|
||||
let endpoint_display = if account.endpoint == "https://api.ente.io" {
|
||||
"api.ente.io (prod)".to_string()
|
||||
} else if account.endpoint.starts_with("http://localhost") {
|
||||
format!("localhost:{}", account.endpoint.split(':').last().unwrap_or(""))
|
||||
} else {
|
||||
account.endpoint.clone()
|
||||
};
|
||||
|
||||
println!(
|
||||
"{:<30} {:<10} {:<40}",
|
||||
"{:<30} {:<10} {:<30} {:<40}",
|
||||
account.email,
|
||||
format!("{:?}", account.app).to_lowercase(),
|
||||
endpoint_display,
|
||||
account.export_dir.as_deref().unwrap_or("Not configured")
|
||||
);
|
||||
}
|
||||
@@ -56,6 +67,7 @@ async fn add_account(
|
||||
email_arg: Option<String>,
|
||||
password_arg: Option<String>,
|
||||
app_arg: String,
|
||||
endpoint: String,
|
||||
export_dir_arg: Option<String>,
|
||||
) -> Result<()> {
|
||||
println!("\n=== Add Ente Account ===\n");
|
||||
@@ -132,12 +144,9 @@ async fn add_account(
|
||||
std::fs::create_dir_all(&export_path).map_err(crate::models::error::Error::Io)?;
|
||||
}
|
||||
|
||||
// Initialize API client (use ENTE_ENDPOINT env var if set, otherwise default to production)
|
||||
let api_endpoint = std::env::var("ENTE_ENDPOINT").ok();
|
||||
if let Some(ref endpoint) = api_endpoint {
|
||||
log::debug!("Using custom API endpoint: {endpoint}");
|
||||
}
|
||||
let api_client = ApiClient::new(api_endpoint)?;
|
||||
// Initialize API client with the specified endpoint
|
||||
log::info!("Using API endpoint: {}", endpoint);
|
||||
let api_client = ApiClient::new(Some(endpoint.clone()))?;
|
||||
let auth_client = AuthClient::new(&api_client);
|
||||
|
||||
println!("\nAuthenticating with Ente servers...");
|
||||
@@ -231,6 +240,7 @@ async fn add_account(
|
||||
email: email.clone(),
|
||||
user_id: auth_response.id,
|
||||
app,
|
||||
endpoint: endpoint.clone(),
|
||||
export_dir: Some(export_dir.clone()),
|
||||
};
|
||||
|
||||
@@ -249,6 +259,7 @@ async fn add_account(
|
||||
println!("\n✅ Account added successfully!");
|
||||
println!(" Email: {email}");
|
||||
println!(" App: {app:?}");
|
||||
println!(" Endpoint: {endpoint}");
|
||||
println!(" Export directory: {export_dir}");
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -10,6 +10,7 @@ pub struct Account {
|
||||
pub email: String,
|
||||
pub user_id: i64,
|
||||
pub app: App,
|
||||
pub endpoint: String,
|
||||
pub export_dir: Option<String>,
|
||||
}
|
||||
|
||||
|
||||
@@ -21,12 +21,13 @@ impl<'a> AccountStore<'a> {
|
||||
let now = current_timestamp();
|
||||
|
||||
self.conn.execute(
|
||||
"INSERT INTO accounts (email, user_id, app, export_dir, created_at, updated_at)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6)",
|
||||
"INSERT INTO accounts (email, user_id, app, endpoint, export_dir, created_at, updated_at)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
|
||||
params![
|
||||
account.email,
|
||||
account.user_id,
|
||||
format!("{:?}", account.app).to_lowercase(),
|
||||
account.endpoint,
|
||||
account.export_dir,
|
||||
now,
|
||||
now
|
||||
@@ -39,7 +40,7 @@ impl<'a> AccountStore<'a> {
|
||||
/// Get an account by email and app
|
||||
pub fn get(&self, email: &str, app: App) -> Result<Option<Account>> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
"SELECT id, email, user_id, app, export_dir FROM accounts
|
||||
"SELECT id, email, user_id, app, endpoint, export_dir FROM accounts
|
||||
WHERE email = ?1 AND app = ?2",
|
||||
)?;
|
||||
|
||||
@@ -55,7 +56,7 @@ impl<'a> AccountStore<'a> {
|
||||
/// List all accounts
|
||||
pub fn list(&self) -> Result<Vec<Account>> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
"SELECT id, email, user_id, app, export_dir FROM accounts
|
||||
"SELECT id, email, user_id, app, endpoint, export_dir FROM accounts
|
||||
ORDER BY email, app",
|
||||
)?;
|
||||
|
||||
@@ -143,7 +144,8 @@ fn row_to_account(row: &Row) -> rusqlite::Result<Account> {
|
||||
email: row.get(1)?,
|
||||
user_id: row.get(2)?,
|
||||
app,
|
||||
export_dir: row.get(4)?,
|
||||
endpoint: row.get(4)?,
|
||||
export_dir: row.get(5)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,11 @@ pub fn create_tables(conn: &Connection) -> Result<()> {
|
||||
email TEXT NOT NULL,
|
||||
user_id INTEGER NOT NULL,
|
||||
app TEXT NOT NULL,
|
||||
endpoint TEXT NOT NULL DEFAULT 'https://api.ente.io',
|
||||
export_dir TEXT,
|
||||
created_at INTEGER NOT NULL,
|
||||
updated_at INTEGER NOT NULL,
|
||||
UNIQUE(email, app)
|
||||
UNIQUE(email, app, endpoint)
|
||||
)",
|
||||
[],
|
||||
)?;
|
||||
|
||||
Reference in New Issue
Block a user