initla code
This commit is contained in:
+19
@@ -0,0 +1,19 @@
|
||||
target/
|
||||
.DS_Store
|
||||
.env*
|
||||
*.pem
|
||||
*.key
|
||||
*.crt
|
||||
*.cer
|
||||
*.p12
|
||||
*.diagnostic
|
||||
*.log
|
||||
*.dump
|
||||
.idea/
|
||||
.vscode/
|
||||
postgres-test-data/
|
||||
local-test-data/
|
||||
diagnostics/
|
||||
release-archives/
|
||||
*.credential-test
|
||||
*.credentials-test
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
[package]
|
||||
name = "azure-database-tui"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
rust-version = "1.85"
|
||||
|
||||
[features]
|
||||
postgres-integration = []
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.43", features = ["fs", "io-util", "macros", "net", "process", "rt", "rt-multi-thread", "sync", "time"] }
|
||||
ratatui = "0.29"
|
||||
crossterm = "0.28"
|
||||
async-trait = "0.1"
|
||||
futures-util = "0.3"
|
||||
tokio-util = "0.7"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
uuid = { version = "1", features = ["serde", "v4"] }
|
||||
thiserror = "2"
|
||||
zeroize = "1"
|
||||
secrecy = "0.10"
|
||||
getrandom = "0.3"
|
||||
sha2 = "0.10"
|
||||
bytes = "1"
|
||||
directories = "6"
|
||||
rustls = "0.23"
|
||||
rustls-native-certs = "0.8"
|
||||
rustls-pemfile = "2"
|
||||
tokio-postgres = { version = "0.7", features = ["with-serde_json-1"] }
|
||||
tokio-postgres-rustls = "0.13"
|
||||
|
||||
[target.'cfg(any(target_os = "macos", target_os = "windows"))'.dependencies]
|
||||
keyring = "3"
|
||||
arboard = "3"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
@@ -0,0 +1,23 @@
|
||||
# Azure Database TUI
|
||||
|
||||
This repository contains a Rust TUI for administering Azure Database for
|
||||
PostgreSQL flexible servers. It discovers servers through the current Azure CLI
|
||||
tenant and connects to PostgreSQL using mandatory TLS.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Install Azure CLI and authenticate to the intended tenant. Network access to
|
||||
the server endpoint, including private endpoint, firewall, and DNS access, is
|
||||
required. Azure CLI visibility does not imply PostgreSQL authorization.
|
||||
|
||||
## Build and test
|
||||
|
||||
Use the pinned Rust toolchain with `cargo build`, `cargo test`, and the local
|
||||
integration helper documented in `docs/operations.md`.
|
||||
|
||||
Supported release targets are macOS ARM64 and Windows x86_64. Raw SQL is sent
|
||||
to PostgreSQL as entered; use it only when you understand its authority and
|
||||
effects.
|
||||
|
||||
See [security](docs/security.md), [operations](docs/operations.md), and
|
||||
[release](docs/release.md).
|
||||
@@ -0,0 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "1.85.0"
|
||||
components = ["rustfmt", "clippy"]
|
||||
@@ -0,0 +1,2 @@
|
||||
pub struct AzureDiscovery;
|
||||
pub struct AzureCliAdapter;
|
||||
@@ -0,0 +1 @@
|
||||
pub mod process; pub mod azure_cli; pub mod postgres;
|
||||
@@ -0,0 +1,5 @@
|
||||
pub struct PostgresConnector;
|
||||
pub struct SessionManager;
|
||||
pub struct SqlSession;
|
||||
pub struct GuidedSession;
|
||||
pub struct ConnectionRequest;
|
||||
@@ -0,0 +1,3 @@
|
||||
#[derive(Debug, Clone)] pub struct CommandSpec;
|
||||
pub trait CommandRunner {}
|
||||
pub struct TokioCommandRunner;
|
||||
@@ -0,0 +1,3 @@
|
||||
use crate::error::AppError;
|
||||
pub struct AppController;
|
||||
impl AppController { pub async fn new() -> Result<Self, AppError> { Err(AppError(crate::error::SafeError { kind: crate::error::ErrorKind::Internal, message: "Application unavailable", sqlstate: None, severity: crate::error::ErrorSeverity::Error, retryable: false, operation_id: None })) } pub async fn run(&mut self) -> Result<(), AppError> { Ok(()) } }
|
||||
@@ -0,0 +1,2 @@
|
||||
#[derive(Debug, Clone)] pub struct AppCommand;
|
||||
#[derive(Debug, Clone)] pub struct AppEvent;
|
||||
@@ -0,0 +1 @@
|
||||
pub mod controller; pub mod events; pub mod state;
|
||||
@@ -0,0 +1 @@
|
||||
#[derive(Debug, Clone)] pub struct AppState;
|
||||
@@ -0,0 +1,10 @@
|
||||
#[derive(Debug, Clone)] pub struct CatalogSnapshot;
|
||||
#[derive(Debug, Clone)] pub struct SchemaMeta;
|
||||
#[derive(Debug, Clone)] pub struct RelationMeta;
|
||||
#[derive(Debug, Clone)] pub struct ColumnMeta;
|
||||
#[derive(Debug, Clone)] pub struct KeysetDefinition;
|
||||
#[derive(Debug, Clone)] pub struct FunctionMeta;
|
||||
#[derive(Debug, Clone)] pub struct RoleMeta;
|
||||
#[derive(Debug, Clone)] pub struct PrivilegeObservation;
|
||||
#[derive(Debug, Clone)] pub struct DefaultPrivilegeObservation;
|
||||
#[derive(Debug, Clone)] pub struct ServerCapabilities;
|
||||
@@ -0,0 +1,9 @@
|
||||
use uuid::Uuid;
|
||||
|
||||
macro_rules! text_id { ($name:ident) => { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct $name(String); impl $name { pub fn new(value: impl Into<String>) -> Self { Self(value.into()) } pub fn as_str(&self) -> &str { &self.0 } } }; }
|
||||
text_id!(TenantId); text_id!(SubscriptionId); text_id!(AzureResourceId);
|
||||
text_id!(CatalogGeneration); text_id!(RoleOid); text_id!(RelationOid);
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ProfileId(Uuid);
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct OperationId(Uuid);
|
||||
impl ProfileId { pub fn new() -> Self { Self(Uuid::new_v4()) } }
|
||||
impl OperationId { pub fn new() -> Self { Self(Uuid::new_v4()) } }
|
||||
@@ -0,0 +1,7 @@
|
||||
#[derive(Debug, Clone)] pub struct Tenant;
|
||||
#[derive(Debug, Clone)] pub struct Subscription;
|
||||
#[derive(Debug, Clone)] pub struct FlexibleServer;
|
||||
#[derive(Debug, Clone)] pub struct DatabaseRef;
|
||||
#[derive(Debug, Clone)] pub struct DiscoveryFailure;
|
||||
#[derive(Debug, Clone)] pub struct DiscoveryReport;
|
||||
#[derive(Debug, Clone)] pub struct DiscoveryEvent;
|
||||
@@ -0,0 +1,6 @@
|
||||
pub mod catalog;
|
||||
pub mod ids;
|
||||
pub mod inventory;
|
||||
pub mod permissions;
|
||||
pub mod profile;
|
||||
pub mod sql;
|
||||
@@ -0,0 +1,8 @@
|
||||
#[derive(Debug, Clone)] pub struct DesiredPrivilegeProfile;
|
||||
#[derive(Debug, Clone)] pub struct PrivilegeScope;
|
||||
#[derive(Debug, Clone)] pub struct PrivilegeKind;
|
||||
#[derive(Debug, Clone)] pub struct RoleMembershipIntent;
|
||||
#[derive(Debug, Clone)] pub struct Grantability;
|
||||
#[derive(Debug, Clone)] pub struct PlanOperation;
|
||||
#[derive(Debug, Clone)] pub struct PermissionPlan;
|
||||
#[derive(Debug, Clone)] pub struct PlanResult;
|
||||
@@ -0,0 +1,6 @@
|
||||
#[derive(Debug, Clone)] pub struct ProfileFile;
|
||||
#[derive(Debug, Clone)] pub struct ConnectionProfile;
|
||||
#[derive(Debug, Clone)] pub struct SecretReference;
|
||||
#[derive(Debug, Clone)] pub struct TlsPolicy;
|
||||
#[derive(Debug, Clone)] pub struct ConnectionDraft;
|
||||
#[derive(Debug, Clone)] pub struct ProfileValidationError;
|
||||
@@ -0,0 +1,9 @@
|
||||
#[derive(Debug, Clone)] pub struct StatementRange;
|
||||
pub struct SqlSubmission;
|
||||
#[derive(Debug, Clone)] pub struct SqlRunRequest;
|
||||
#[derive(Debug, Clone)] pub struct SqlExecutionEvent;
|
||||
#[derive(Debug, Clone)] pub struct ResultSetMeta;
|
||||
pub struct DisplayCell;
|
||||
#[derive(Debug, Clone)] pub struct CopyDirection;
|
||||
#[derive(Debug, Clone)] pub struct TransactionState;
|
||||
#[derive(Debug, Clone)] pub struct SqlLexer;
|
||||
@@ -0,0 +1,48 @@
|
||||
use std::fmt;
|
||||
use crate::domain::ids::OperationId;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ErrorKind { Internal, Input, Network, Database, Process }
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ErrorSeverity { Info, Warning, Error }
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct SqlStateCode([u8; 5]);
|
||||
|
||||
impl SqlStateCode {
|
||||
pub fn parse(value: &str) -> Option<Self> {
|
||||
let bytes = value.as_bytes();
|
||||
if bytes.len() == 5 && bytes.iter().all(|b| b.is_ascii_uppercase() || b.is_ascii_digit()) {
|
||||
Some(Self(bytes.try_into().ok()?))
|
||||
} else { None }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SafeError {
|
||||
pub kind: ErrorKind,
|
||||
pub message: &'static str,
|
||||
pub sqlstate: Option<SqlStateCode>,
|
||||
pub severity: ErrorSeverity,
|
||||
pub retryable: bool,
|
||||
pub operation_id: Option<OperationId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AppError(pub SafeError);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SafeDiagnostic {
|
||||
pub error: SafeError,
|
||||
}
|
||||
|
||||
impl fmt::Display for AppError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.message.fmt(f) }
|
||||
}
|
||||
|
||||
impl std::error::Error for AppError {}
|
||||
|
||||
pub fn redact_sensitive_text(input: &str) -> String {
|
||||
if input.is_empty() { String::new() } else { "[diagnostic details omitted]".to_owned() }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
pub mod error;
|
||||
pub mod adapters;
|
||||
pub mod app;
|
||||
pub mod domain;
|
||||
pub mod platform;
|
||||
pub mod services;
|
||||
pub mod tui;
|
||||
@@ -0,0 +1,7 @@
|
||||
use azure_database_tui::app::controller::AppController;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), azure_database_tui::error::AppError> {
|
||||
let mut controller = AppController::new().await?;
|
||||
controller.run().await
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub trait ClipboardService {} pub struct SystemClipboardService;
|
||||
@@ -0,0 +1 @@
|
||||
pub trait Clock {} pub struct SystemClock;
|
||||
@@ -0,0 +1 @@
|
||||
pub trait SecretStore {} pub struct KeyringSecretStore; pub struct UnavailableSecretStore;
|
||||
@@ -0,0 +1 @@
|
||||
pub mod paths; pub mod clock; pub mod profile_file; pub mod keychain; pub mod clipboard; pub mod secret_input;
|
||||
@@ -0,0 +1,2 @@
|
||||
pub struct AppPaths;
|
||||
impl AppPaths { pub fn discover() -> Self { Self } }
|
||||
@@ -0,0 +1 @@
|
||||
pub struct ProfileFileStore;
|
||||
@@ -0,0 +1 @@
|
||||
pub struct SecretInputBuffer; pub struct SecretHandle; pub struct OneTimeSecret; pub struct SecretVault;
|
||||
@@ -0,0 +1 @@
|
||||
pub struct CatalogService;
|
||||
@@ -0,0 +1 @@
|
||||
pub struct DiscoveryService;
|
||||
@@ -0,0 +1 @@
|
||||
pub mod discovery; pub mod profiles; pub mod catalog; pub mod tables; pub mod roles; pub mod sql_executor;
|
||||
@@ -0,0 +1 @@
|
||||
pub struct ProfileService;
|
||||
@@ -0,0 +1 @@
|
||||
pub struct RoleService;
|
||||
@@ -0,0 +1 @@
|
||||
pub struct SqlExecutor;
|
||||
@@ -0,0 +1 @@
|
||||
pub struct TableService;
|
||||
@@ -0,0 +1 @@
|
||||
pub struct TerminalGuard;
|
||||
Reference in New Issue
Block a user