#![allow(dead_code)] use std::{fs, path::Path, sync::Arc}; use anyhow::Result; use azure_identity::token_credentials::{AzureCliCredential, TokenCredential}; use http::Uri; use log::debug; use oauth2::AccessToken; use serde_json::json; use spotflow::{ProvisioningOperation, ProvisioningOperationDisplayHandler}; pub struct ProvisioningOperationApprovalHandler { instance_url: Uri, workspace_id: String, } impl ProvisioningOperationApprovalHandler { pub fn new(instance_url: Uri, workspace_id: String) -> Self { Self { instance_url, workspace_id, } } } impl ProvisioningOperationDisplayHandler for ProvisioningOperationApprovalHandler { fn display(&self, provisioning_operation: &ProvisioningOperation) -> Result<(), anyhow::Error> { let operation_id = &provisioning_operation.id; debug!("Approving the Provisioning Operation {}", operation_id); approve_provisioning(&self.instance_url, &self.workspace_id, operation_id) } } pub fn approve_provisioning( instance_url: &Uri, workspace_id: &str, operation_id: &str, ) -> Result<()> { let token = get_azure_token(instance_url, "device-provisioning"); let url = format!("{instance_url}workspaces/{workspace_id}/provisioning-operations/approve"); let auth_header = format!("Bearer {}", token.secret()); let connector = Arc::new(native_tls::TlsConnector::new().unwrap()); let agent = ureq::AgentBuilder::new().tls_connector(connector).build(); let data = json!({ "provisioningOperationId": operation_id, }); agent .put(&url) .set("Content-Type", "application/json") .set("Authorization", &auth_header) .send_json(data)?; Ok(()) } pub fn delete_device(instance_url: &Uri, workspace_id: &str, device_id: &str) -> Result<()> { let token = get_azure_token(instance_url, "device-management"); let url = format!("{instance_url}workspaces/{workspace_id}/devices/{device_id}/delete"); let auth_header = format!("Bearer {}", token.secret()); let connector = Arc::new(native_tls::TlsConnector::new().unwrap()); let agent = ureq::AgentBuilder::new().tls_connector(connector).build(); agent .delete(&url) .set("Content-Type", "application/json") .set("Authorization", &auth_header) .call()?; Ok(()) } pub fn get_azure_token(url: &Uri, service: &str) -> AccessToken { let rt = tokio::runtime::Builder::new_current_thread() .enable_all() .build() .unwrap(); let creds = AzureCliCredential {}; let resource = format!( "https://{service}.{}", url.host().expect("Invalid instance URL") ); let h = rt.spawn(async move { creds.get_token(&resource).await }); let token = rt .block_on(h) .expect("Unable to obtain azure token") .expect("Unable to obtain azure token") .token; rt.shutdown_background(); token } pub fn clear_db(path: &Path) { if path.exists() { log::info!("Removing old local database file"); fs::remove_file(path).expect("Unable to delete old local database file"); } }