diff --git a/src/db/app.rs b/src/db/app.rs index 017b693..6c30cf8 100644 --- a/src/db/app.rs +++ b/src/db/app.rs @@ -233,6 +233,12 @@ pub struct ActiveAppWithNode { } impl ActiveAppWithNode { + pub async fn get_by_uuid(db: &Surreal, uuid: &str) -> Result, Error> { + let contract: Option = + db.query(format!("select * from {ACTIVE_APP}:{uuid} fetch out;")).await?.take(0)?; + Ok(contract) + } + pub async fn list_by_node(db: &Surreal, node_pubkey: &str) -> Result, Error> { let mut query_result = db .query(format!( @@ -244,10 +250,38 @@ impl ActiveAppWithNode { Ok(contract) } - pub async fn get_by_uuid(db: &Surreal, uuid: &str) -> Result, Error> { - let contract: Option = - db.query(format!("select * from {ACTIVE_APP}:{uuid} fetch out;")).await?.take(0)?; - Ok(contract) + pub async fn list_by_admin(db: &Surreal, admin: &str) -> Result, Error> { + let mut query_result = db + .query(format!("select * from {ACTIVE_APP} where in = {ACCOUNT}:{admin} fetch out;")) + .await?; + + let app_contracts: Vec = query_result.take(0)?; + + Ok(app_contracts) + } + + pub async fn list_by_operator( + db: &Surreal, + operator: &str, + ) -> Result, Error> { + let mut query_result = db + .query(format!( + "select + (select * from ->operator->app_node<-{ACTIVE_APP} fetch out) + as app_contracts + from {ACCOUNT}:{operator}" + )) + .await?; + #[derive(Deserialize)] + struct Wrapper { + app_contracts: Vec, + } + + let c: Option = query_result.take(0)?; + match c { + Some(contracts_wrapper) => Ok(contracts_wrapper.app_contracts), + None => Ok(vec![]), + } } } diff --git a/src/grpc/app.rs b/src/grpc/app.rs index 5000721..10c69d0 100644 --- a/src/grpc/app.rs +++ b/src/grpc/app.rs @@ -210,7 +210,36 @@ impl BrainAppCli for AppCliServer { let req = check_sig_from_req(req)?; info!("list_app_contracts process starting for {:?}", req); - todo!() + let mut app_contracts = Vec::new(); + + if !req.uuid.is_empty() { + if let Some(app_contract) = + db::ActiveAppWithNode::get_by_uuid(&self.db, &req.uuid).await? + { + if app_contract.admin.key().to_string() == req.admin_pubkey { + app_contracts.push(app_contract); + } + // TODO: allow operator to inspect contracts + } + } else if req.as_operator { + app_contracts.append( + &mut db::ActiveAppWithNode::list_by_operator(&self.db, &req.admin_pubkey).await?, + ); + } else { + app_contracts.append( + &mut db::ActiveAppWithNode::list_by_admin(&self.db, &req.admin_pubkey).await?, + ); + } + + let (tx, rx) = mpsc::channel(6); + tokio::spawn(async move { + for app_contract in app_contracts { + let _ = tx.send(Ok(app_contract.into())).await; + } + }); + + let resp_stream = ReceiverStream::new(rx); + Ok(Response::new(Box::pin(resp_stream))) } async fn list_app_nodes(