diff --git a/interim_tables.surql b/interim_tables.surql index 87301d3..5adedfb 100644 --- a/interim_tables.surql +++ b/interim_tables.surql @@ -75,7 +75,7 @@ DEFINE FIELD reason ON TABLE kick TYPE string; DEFINE FIELD contract ON TABLE kick TYPE record; DEFINE TABLE report TYPE RELATION FROM account TO vm_node|app_node; -DEFINE FIELD created_at ON TABLE ban TYPE datetime; -DEFINE FIELD reason ON TABLE ban TYPE string; +DEFINE FIELD created_at ON TABLE report TYPE datetime; +DEFINE FIELD reason ON TABLE report TYPE string; DEFINE TABLE operator TYPE RELATION FROM account TO vm_node|app_node; diff --git a/src/db.rs b/src/db.rs index 341b7c6..d076fe6 100644 --- a/src/db.rs +++ b/src/db.rs @@ -100,6 +100,26 @@ pub struct VmNode { pub offline_minutes: u64, } +#[derive(Debug, Serialize, Deserialize)] +pub struct VmNodeExtended { + pub id: RecordId, + pub country: String, + pub region: String, + pub city: String, + pub ip: String, + pub avail_mem_mb: u32, + pub avail_vcpus: u32, + pub avail_storage_gbs: u32, + pub avail_ipv4: u32, + pub avail_ipv6: u32, + pub avail_ports: u32, + pub max_ports_per_vm: u32, + pub price: u64, + pub offline_minutes: u64, + pub reports: Vec, + pub operator: RecordId, +} + #[derive(Debug, Serialize, Deserialize)] pub struct VmContract { pub id: RecordId, @@ -221,18 +241,36 @@ impl VmContractWithNode { #[derive(Debug, Serialize, Deserialize)] pub struct AppNode { - id: RecordId, - country: String, - region: String, - city: String, - ip: String, - avail_mem_mb: u32, - avail_vcpus: u32, - avail_storage_gbs: u32, - avail_ports: u32, - max_ports_per_app: u32, - price: u64, - offline_minutes: u64, + pub id: RecordId, + pub country: String, + pub region: String, + pub city: String, + pub ip: String, + pub avail_mem_mb: u32, + pub avail_vcpus: u32, + pub avail_storage_gbs: u32, + pub avail_ports: u32, + pub max_ports_per_app: u32, + pub price: u64, + pub offline_minutes: u64, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct AppNodeExtended { + pub id: RecordId, + pub country: String, + pub region: String, + pub city: String, + pub ip: String, + pub avail_mem_mb: u32, + pub avail_vcpus: u32, + pub avail_storage_gbs: u32, + pub avail_ports: u32, + pub max_ports_per_app: u32, + pub price: u64, + pub offline_minutes: u64, + pub reports: Vec, + pub operator: RecordId, } #[derive(Debug, Serialize, Deserialize)] @@ -288,12 +326,16 @@ pub struct Report { #[serde(rename = "out")] to_node: RecordId, created_at: Datetime, - reason: String, + pub reason: String, } impl Report { // TODO: test this functionality and remove this comment - pub async fn create(from_account: RecordId, to_node: RecordId, reason: String) -> Result<(), Error> { + pub async fn create( + from_account: RecordId, + to_node: RecordId, + reason: String, + ) -> Result<(), Error> { let _: Vec = DB .insert("report") .relation(Report { from_account, to_node, created_at: Datetime::default(), reason }) @@ -350,6 +392,45 @@ impl Operator { let operators: Vec = result.take(0)?; Ok(operators) } + + pub async fn inspect_nodes( + account: &str, + ) -> Result<(Option, Vec, Vec), Error> { + let mut result = DB + .query(format!( + "select *, + in as account, + <-account.email[0] as email, + <-account.escrow[0] as escrow, + count(->vm_node) as vm_nodes, + count(->app_node) as app_nodes, + (select in from <-account->operator->vm_node<-report).len() + + (select in from <-account->operator->app_node<-report).len() + as reports + from operator where in = account:{account} group by account;" + )) + .query(format!( + "select *, + (<-operator<-account)[0].id as operator, + <-report.* as reports + from vm_node + where (<-operator<-account)[0].id = account:{account};" + )) + .query(format!( + "select *, + (<-operator<-account)[0].id as operator, + <-report.* as reports + from app_node + where (<-operator<-account)[0].id = account:{account};" + )) + .await?; + + let operator: Option = result.take(0)?; + let vm_nodes: Vec = result.take(1)?; + let app_nodes: Vec = result.take(2)?; + + Ok((operator, vm_nodes, app_nodes)) + } } // TODO: delete all of these From implementation after migration 0 gets executed diff --git a/src/grpc.rs b/src/grpc.rs index d7f1cd0..8db2cc8 100644 --- a/src/grpc.rs +++ b/src/grpc.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] use crate::db; -use detee_shared::app_proto::AppContract; +use detee_shared::app_proto::{AppContract, AppNodeListResp}; use detee_shared::{ common_proto::{Empty, Pubkey}, general_proto::{ @@ -84,6 +84,36 @@ impl From for ListOperatorsResp { } } +impl From for VmNodeListResp { + fn from(vm_node: db::VmNodeExtended) -> Self { + Self { + operator: vm_node.operator.key().to_string(), + node_pubkey: vm_node.id.key().to_string(), + country: vm_node.country, + region: vm_node.region, + city: vm_node.city, + ip: vm_node.ip, + reports: vm_node.reports.iter().map(|n| n.reason.clone()).collect(), + price: vm_node.price, + } + } +} + +impl From for AppNodeListResp { + fn from(app_node: db::AppNodeExtended) -> Self { + Self { + operator: app_node.operator.key().to_string(), + node_pubkey: app_node.id.key().to_string(), + country: app_node.country, + region: app_node.region, + city: app_node.city, + ip: app_node.ip, + reports: app_node.reports.iter().map(|n| n.reason.clone()).collect(), + price: app_node.price, + } + } +} + #[tonic::async_trait] impl BrainGeneralCli for BrainGeneralCliMock { type ListAccountsStream = Pin> + Send>>; @@ -134,13 +164,16 @@ impl BrainGeneralCli for BrainGeneralCliMock { async fn inspect_operator( &self, - _req: Request, + req: Request, ) -> Result, Status> { - todo!(); - // match self.data.inspect_operator(&req.into_inner().pubkey) { - // Some(op) => Ok(Response::new(op.into())), - // None => Err(Status::not_found("The wallet you specified is not an operator")), - // } + match db::Operator::inspect_nodes(&req.into_inner().pubkey).await? { + (Some(op), vm_nodes, app_nodes) => Ok(Response::new(InspectOperatorResp { + operator: Some(op.into()), + vm_nodes: vm_nodes.into_iter().map(|n| n.into()).collect(), + app_nodes: app_nodes.into_iter().map(|n| n.into()).collect(), + })), + (None, _, _) => Err(Status::not_found("The wallet you specified is not an operator")), + } } async fn register_operator(