added report and airdrop
This commit is contained in:
		
							parent
							
								
									71cc0a8d82
								
							
						
					
					
						commit
						a8cf515061
					
				
							
								
								
									
										64
									
								
								src/db.rs
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										64
									
								
								src/db.rs
									
									
									
									
									
								
							| @ -51,36 +51,6 @@ pub async fn migration0(old_data: &old_brain::BrainData) -> surrealdb::Result<() | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| pub async fn account(address: &str) -> Result<Account, Error> { | ||||
|     let id = (ACCOUNT, address); | ||||
|     let account: Option<Account> = DB.select(id).await?; | ||||
|     let account = match account { | ||||
|         Some(account) => account, | ||||
|         None => { | ||||
|             Account { id: id.into(), balance: 0, tmp_locked: 0, escrow: 0, email: String::new() } | ||||
|         } | ||||
|     }; | ||||
|     Ok(account) | ||||
| } | ||||
| 
 | ||||
| // I am not deleting this example cause I might need it later.
 | ||||
| //
 | ||||
| // async fn get_wallet_contracts() -> surrealdb::Result<Vec<Wallet>> {
 | ||||
| //     let mut result = DB
 | ||||
| //         .query("select *, ->contract.* from wallet:address1;")
 | ||||
| //         .await?;
 | ||||
| //     let wallets: Vec<Wallet> = result.take(0)?;
 | ||||
| //     Ok(wallets)
 | ||||
| // }
 | ||||
| //
 | ||||
| // #[derive(Debug, Serialize, Deserialize)]
 | ||||
| // pub struct Wallet {
 | ||||
| //     balance: u64,
 | ||||
| //     id: RecordId,
 | ||||
| //     #[serde(rename = "->contract", default)]
 | ||||
| //     contracts: Vec<Contract>,
 | ||||
| // }
 | ||||
| 
 | ||||
| #[derive(Debug, Serialize, Deserialize)] | ||||
| pub struct Account { | ||||
|     pub id: RecordId, | ||||
| @ -90,6 +60,28 @@ pub struct Account { | ||||
|     pub email: String, | ||||
| } | ||||
| 
 | ||||
| impl Account { | ||||
|     pub async fn get(address: &str) -> Result<Self, Error> { | ||||
|         let id = (ACCOUNT, address); | ||||
|         let account: Option<Self> = DB.select(id).await?; | ||||
|         let account = match account { | ||||
|             Some(account) => account, | ||||
|             None => { | ||||
|                 Self { id: id.into(), balance: 0, tmp_locked: 0, escrow: 0, email: String::new() } | ||||
|             } | ||||
|         }; | ||||
|         Ok(account) | ||||
|     } | ||||
| 
 | ||||
|     pub async fn airdrop(account: &str, tokens: u64) -> Result<(), Error> { | ||||
|         let tokens = tokens.saturating_mul(1_000_000_000); | ||||
|         let _ = DB | ||||
|             .query(format!("upsert account:{account} SET balance = (balance || 0) + {tokens};")) | ||||
|             .await?; | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Serialize, Deserialize)] | ||||
| pub struct VmNode { | ||||
|     pub id: RecordId, | ||||
| @ -291,7 +283,6 @@ pub struct Kick { | ||||
| 
 | ||||
| #[derive(Debug, Serialize, Deserialize)] | ||||
| pub struct Report { | ||||
|     id: RecordId, | ||||
|     #[serde(rename = "in")] | ||||
|     from_account: RecordId, | ||||
|     #[serde(rename = "out")] | ||||
| @ -300,6 +291,17 @@ pub struct Report { | ||||
|     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> { | ||||
|         let _: Vec<Self> = DB | ||||
|             .insert("report") | ||||
|             .relation(Report { from_account, to_node, created_at: Datetime::default(), reason }) | ||||
|             .await?; | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Serialize, Deserialize)] | ||||
| pub struct OperatorRelation { | ||||
|     #[serde(rename = "in")] | ||||
|  | ||||
							
								
								
									
										84
									
								
								src/grpc.rs
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										84
									
								
								src/grpc.rs
									
									
									
									
									
								
							| @ -95,29 +95,25 @@ impl BrainGeneralCli for BrainGeneralCliMock { | ||||
| 
 | ||||
|     async fn get_balance(&self, req: Request<Pubkey>) -> Result<Response<AccountBalance>, Status> { | ||||
|         let req = check_sig_from_req(req)?; | ||||
|         Ok(Response::new(db::account(&req.pubkey).await?.into())) | ||||
|         Ok(Response::new(db::Account::get(&req.pubkey).await?.into())) | ||||
|     } | ||||
| 
 | ||||
|     async fn report_node(&self, req: Request<ReportNodeReq>) -> Result<Response<Empty>, Status> { | ||||
|         let _req = check_sig_from_req(req)?; | ||||
|         todo!(); | ||||
|         // match self.data.find_any_contract_by_uuid(&req.contract) {
 | ||||
|         //     Ok((Some(vm_contract), _))
 | ||||
|         //         if vm_contract.admin_pubkey == req.admin_pubkey
 | ||||
|         //             && vm_contract.node_pubkey == req.node_pubkey =>
 | ||||
|         //     {
 | ||||
|         //         ()
 | ||||
|         //     }
 | ||||
|         //     Ok((_, Some(app_contract)))
 | ||||
|         //         if app_contract.admin_pubkey == req.admin_pubkey
 | ||||
|         //             && app_contract.node_pubkey == req.node_pubkey =>
 | ||||
|         //     {
 | ||||
|         //         ()
 | ||||
|         //     }
 | ||||
|         //     _ => return Err(Status::unauthenticated("No contract found by this ID.")),
 | ||||
|         // };
 | ||||
|         // self.data.report_any_node(req.admin_pubkey, &req.node_pubkey, req.reason);
 | ||||
|         // Ok(Response::new(Empty {}))
 | ||||
|         let req = check_sig_from_req(req)?; | ||||
|         let (account, node) = match db::VmContractWithNode::get_by_uuid(&req.contract).await? { | ||||
|             Some(vm_contract) | ||||
|                 if vm_contract.admin.key().to_string() == req.admin_pubkey | ||||
|                     && vm_contract.vm_node.id.key().to_string() == req.node_pubkey => | ||||
|             { | ||||
|                 (vm_contract.admin, vm_contract.vm_node.id) | ||||
|             } | ||||
|             _ => { | ||||
|                 // TODO: Hey, Noor! Please add app contract here.
 | ||||
|                 return Err(Status::unauthenticated("No contract found by this ID.")); | ||||
|             } | ||||
|         }; | ||||
|         db::Report::create(account, node, req.reason).await?; | ||||
|         Ok(Response::new(Empty {})) | ||||
|     } | ||||
| 
 | ||||
|     async fn list_operators( | ||||
| @ -178,12 +174,11 @@ impl BrainGeneralCli for BrainGeneralCliMock { | ||||
| 
 | ||||
|     // admin commands
 | ||||
| 
 | ||||
|     async fn airdrop(&self, _req: Request<AirdropReq>) -> Result<Response<Empty>, Status> { | ||||
|         todo!(); | ||||
|         // check_admin_key(&req)?;
 | ||||
|         // let req = check_sig_from_req(req)?;
 | ||||
|         // self.data.give_airdrop(&req.pubkey, req.tokens);
 | ||||
|         // Ok(Response::new(Empty {}))
 | ||||
|     async fn airdrop(&self, req: Request<AirdropReq>) -> Result<Response<Empty>, Status> { | ||||
|         check_admin_key(&req)?; | ||||
|         let req = check_sig_from_req(req)?; | ||||
|         db::Account::airdrop(&req.pubkey, req.tokens).await?; | ||||
|         Ok(Response::new(Empty {})) | ||||
|     } | ||||
| 
 | ||||
|     async fn slash(&self, _req: Request<SlashReq>) -> Result<Response<Empty>, Status> { | ||||
| @ -420,13 +415,26 @@ macro_rules! impl_pubkey_getter { | ||||
| impl_pubkey_getter!(Pubkey, pubkey); | ||||
| impl_pubkey_getter!(NewVmReq, admin_pubkey); | ||||
| impl_pubkey_getter!(DeleteVmReq, admin_pubkey); | ||||
| impl_pubkey_getter!(ReportNodeReq, admin_pubkey); | ||||
| impl_pubkey_getter!(UpdateVmReq, admin_pubkey); | ||||
| impl_pubkey_getter!(ExtendVmReq, admin_pubkey); | ||||
| impl_pubkey_getter!(ReportNodeReq, admin_pubkey); | ||||
| impl_pubkey_getter!(ListVmContractsReq, wallet); | ||||
| impl_pubkey_getter!(RegisterVmNodeReq, node_pubkey); | ||||
| impl_pubkey_getter!(RegOperatorReq, pubkey); | ||||
| impl_pubkey_getter!(KickReq, operator_wallet); | ||||
| impl_pubkey_getter!(BanUserReq, operator_wallet); | ||||
| 
 | ||||
| impl_pubkey_getter!(VmNodeFilters); | ||||
| impl_pubkey_getter!(Empty); | ||||
| impl_pubkey_getter!(AirdropReq); | ||||
| impl_pubkey_getter!(SlashReq); | ||||
| 
 | ||||
| // impl_pubkey_getter!(NewAppReq, admin_pubkey);
 | ||||
| // impl_pubkey_getter!(DelAppReq, admin_pubkey);
 | ||||
| // impl_pubkey_getter!(ListAppContractsReq, admin_pubkey);
 | ||||
| //
 | ||||
| // impl_pubkey_getter!(RegisterAppNodeReq);
 | ||||
| // impl_pubkey_getter!(AppNodeFilters);
 | ||||
| 
 | ||||
| fn check_sig_from_req<T: std::fmt::Debug + PubkeyGetter>(req: Request<T>) -> Result<T, Status> { | ||||
|     let time = match req.metadata().get("timestamp") { | ||||
| @ -490,3 +498,25 @@ fn check_sig_from_req<T: std::fmt::Debug + PubkeyGetter>(req: Request<T>) -> Res | ||||
|     } | ||||
|     Ok(req) | ||||
| } | ||||
| 
 | ||||
| const ADMIN_ACCOUNTS: &[&str] = &[ | ||||
|     "x52w7jARC5erhWWK65VZmjdGXzBK6ZDgfv1A283d8XK", | ||||
|     "FHuecMbeC1PfjkW2JKyoicJAuiU7khgQT16QUB3Q1XdL", | ||||
|     "H21Shi4iE7vgfjWEQNvzmpmBMJSaiZ17PYUcdNoAoKNc", | ||||
| ]; | ||||
| 
 | ||||
| fn check_admin_key<T>(req: &Request<T>) -> Result<(), Status> { | ||||
|     let pubkey = match req.metadata().get("pubkey") { | ||||
|         Some(p) => p.clone(), | ||||
|         None => return Err(Status::unauthenticated("pubkey not found in metadata.")), | ||||
|     }; | ||||
|     let pubkey = pubkey | ||||
|         .to_str() | ||||
|         .map_err(|_| Status::unauthenticated("could not parse pubkey metadata to str"))?; | ||||
| 
 | ||||
|     if !ADMIN_ACCOUNTS.contains(&pubkey) { | ||||
|         return Err(Status::unauthenticated("This operation is reserved to admin accounts")); | ||||
|     } | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user