From e122a4e238f185690b3e5770d60f105ad8974530 Mon Sep 17 00:00:00 2001 From: Noor Date: Sun, 25 May 2025 17:37:18 +0530 Subject: [PATCH] Feat: list all accounts admin can list all accounts tests for list accounts --- src/db/general.rs | 5 +++++ src/grpc/general.rs | 25 ++++++++++++------------- src/grpc/types.rs | 12 +++++++++++- tests/common/vm_cli_utils.rs | 24 +++++++++++++++++++++++- tests/grpc_general_test.rs | 23 ++++++++++++++++++++++- 5 files changed, 73 insertions(+), 16 deletions(-) diff --git a/src/db/general.rs b/src/db/general.rs index b6d8061..3830803 100644 --- a/src/db/general.rs +++ b/src/db/general.rs @@ -107,6 +107,11 @@ impl Account { } Ok(()) } + + pub async fn list_accounts(db: &Surreal) -> Result, Error> { + let accounts: Vec = db.select(ACCOUNT).await?; + Ok(accounts) + } } impl Account { diff --git a/src/grpc/general.rs b/src/grpc/general.rs index 8c048ed..6f1fe00 100644 --- a/src/grpc/general.rs +++ b/src/grpc/general.rs @@ -178,20 +178,19 @@ impl BrainGeneralCli for GeneralCliServer { async fn list_accounts( &self, - _req: Request, + req: Request, ) -> Result, Status> { - todo!(); - // check_admin_key(&req)?; - // let _ = check_sig_from_req(req)?; - // let accounts = self.data.list_accounts(); - // let (tx, rx) = mpsc::channel(6); - // tokio::spawn(async move { - // for account in accounts { - // let _ = tx.send(Ok(account.into())).await; - // } - // }); - // let output_stream = ReceiverStream::new(rx); - // Ok(Response::new(Box::pin(output_stream) as Self::ListAccountsStream)) + check_admin_key(&req)?; + check_sig_from_req(req)?; + let accounts = db::Account::list_accounts(&self.db).await?; + let (tx, rx) = mpsc::channel(6); + tokio::spawn(async move { + for account in accounts { + let _ = tx.send(Ok(account.into())).await; + } + }); + let output_stream = ReceiverStream::new(rx); + Ok(Response::new(Box::pin(output_stream) as Self::ListAccountsStream)) } async fn list_all_vm_contracts( diff --git a/src/grpc/types.rs b/src/grpc/types.rs index ee7e716..900df5a 100644 --- a/src/grpc/types.rs +++ b/src/grpc/types.rs @@ -2,7 +2,7 @@ use crate::constants::{ACCOUNT, APP_NODE, ID_ALPHABET, NEW_APP_REQ, NEW_VM_REQ, use crate::db::prelude as db; use detee_shared::app_proto::AppNodeListResp; use detee_shared::common_proto::MappedPort; -use detee_shared::general_proto::{AccountBalance, ListOperatorsResp}; +use detee_shared::general_proto::{Account, AccountBalance, ListOperatorsResp}; use detee_shared::{app_proto::*, vm_proto::*}; use nanoid::nanoid; @@ -14,6 +14,16 @@ impl From for AccountBalance { } } +impl From for Account { + fn from(account: db::Account) -> Self { + Account { + pubkey: account.id.to_string(), + balance: account.balance, + tmp_locked: account.tmp_locked, + } + } +} + impl From for db::NewVmReq { fn from(new_vm_req: NewVmReq) -> Self { Self { diff --git a/tests/common/vm_cli_utils.rs b/tests/common/vm_cli_utils.rs index e106462..68251b6 100644 --- a/tests/common/vm_cli_utils.rs +++ b/tests/common/vm_cli_utils.rs @@ -2,9 +2,10 @@ use super::test_utils::{admin_keys, Key}; use anyhow::{anyhow, Result}; use detee_shared::common_proto::Empty; use detee_shared::general_proto::brain_general_cli_client::BrainGeneralCliClient; -use detee_shared::general_proto::{AirdropReq, RegOperatorReq, ReportNodeReq}; +use detee_shared::general_proto::{Account, AirdropReq, RegOperatorReq, ReportNodeReq}; use detee_shared::vm_proto; use detee_shared::vm_proto::brain_vm_cli_client::BrainVmCliClient; +use futures::StreamExt; use surreal_brain::constants::{ACTIVE_VM, NEW_VM_REQ}; use surreal_brain::db::prelude as db; use surrealdb::engine::remote::ws::Client; @@ -86,3 +87,24 @@ pub async fn register_operator(brain_channel: &Channel, key: &Key, escrow: u64) cli_client.register_operator(key.sign_request(reg_req.clone()).unwrap()).await?; Ok(()) } + +pub async fn list_accounts(brain_channel: &Channel, admin_key: &Key) -> Result> { + let mut cli_client = BrainGeneralCliClient::new(brain_channel.clone()); + let mut stream = + cli_client.list_accounts(admin_key.sign_request(Empty {}).unwrap()).await?.into_inner(); + + let mut accounts = Vec::new(); + + while let Some(stream_data) = stream.next().await { + match stream_data { + Ok(account) => { + accounts.push(account); + } + Err(e) => { + panic!("Error while listing accounts: {e:?}"); + } + } + } + + Ok(accounts) +} diff --git a/tests/grpc_general_test.rs b/tests/grpc_general_test.rs index aecc728..0a65c5b 100644 --- a/tests/grpc_general_test.rs +++ b/tests/grpc_general_test.rs @@ -2,7 +2,7 @@ use common::prepare_test_env::{ prepare_test_db, run_service_for_stream, run_service_in_background, }; use common::test_utils::{admin_keys, Key}; -use common::vm_cli_utils::{airdrop, create_new_vm, register_operator, report_node}; +use common::vm_cli_utils::{airdrop, create_new_vm, list_accounts, register_operator, report_node}; use common::vm_daemon_utils::{mock_vm_daemon, register_vm_node}; use detee_shared::common_proto::{Empty, Pubkey}; use detee_shared::general_proto::brain_general_cli_client::BrainGeneralCliClient; @@ -376,3 +376,24 @@ async fn test_slash_operator() { let account = operator_account.unwrap(); assert_eq!(account.escrow, (escrew - slash_amt) * TOKEN_DECIMAL); } + +#[tokio::test] +async fn test_admin_list_account() { + let db_conn = prepare_test_db().await.unwrap(); + let brain_channel = run_service_for_stream().await.unwrap(); + + let admin_key = admin_keys()[0].clone(); + + let unauthenticated = list_accounts(&brain_channel, &Key::new()).await.err().unwrap(); + assert!(unauthenticated.to_string().contains("reserved to admin accounts")); + + let accounts = list_accounts(&brain_channel, &admin_key).await.unwrap(); + assert_eq!(accounts.len(), 19); + + airdrop(&brain_channel, &Key::new().pubkey, 10).await.unwrap(); + + let acc_in_db = db_conn.select::>(ACCOUNT).await.unwrap(); + + let accounts = list_accounts(&brain_channel, &admin_key).await.unwrap(); + assert_eq!(accounts.len(), acc_in_db.len()); +}