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(()) |     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)] | #[derive(Debug, Serialize, Deserialize)] | ||||||
| pub struct Account { | pub struct Account { | ||||||
|     pub id: RecordId, |     pub id: RecordId, | ||||||
| @ -90,6 +60,28 @@ pub struct Account { | |||||||
|     pub email: String, |     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)] | #[derive(Debug, Serialize, Deserialize)] | ||||||
| pub struct VmNode { | pub struct VmNode { | ||||||
|     pub id: RecordId, |     pub id: RecordId, | ||||||
| @ -291,7 +283,6 @@ pub struct Kick { | |||||||
| 
 | 
 | ||||||
| #[derive(Debug, Serialize, Deserialize)] | #[derive(Debug, Serialize, Deserialize)] | ||||||
| pub struct Report { | pub struct Report { | ||||||
|     id: RecordId, |  | ||||||
|     #[serde(rename = "in")] |     #[serde(rename = "in")] | ||||||
|     from_account: RecordId, |     from_account: RecordId, | ||||||
|     #[serde(rename = "out")] |     #[serde(rename = "out")] | ||||||
| @ -300,6 +291,17 @@ pub struct Report { | |||||||
|     reason: String, |     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)] | #[derive(Debug, Serialize, Deserialize)] | ||||||
| pub struct OperatorRelation { | pub struct OperatorRelation { | ||||||
|     #[serde(rename = "in")] |     #[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> { |     async fn get_balance(&self, req: Request<Pubkey>) -> Result<Response<AccountBalance>, Status> { | ||||||
|         let req = check_sig_from_req(req)?; |         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> { |     async fn report_node(&self, req: Request<ReportNodeReq>) -> Result<Response<Empty>, Status> { | ||||||
|         let _req = check_sig_from_req(req)?; |         let req = check_sig_from_req(req)?; | ||||||
|         todo!(); |         let (account, node) = match db::VmContractWithNode::get_by_uuid(&req.contract).await? { | ||||||
|         // match self.data.find_any_contract_by_uuid(&req.contract) {
 |             Some(vm_contract) | ||||||
|         //     Ok((Some(vm_contract), _))
 |                 if vm_contract.admin.key().to_string() == req.admin_pubkey | ||||||
|         //         if vm_contract.admin_pubkey == req.admin_pubkey
 |                     && vm_contract.vm_node.id.key().to_string() == req.node_pubkey => | ||||||
|         //             && vm_contract.node_pubkey == req.node_pubkey =>
 |             { | ||||||
|         //     {
 |                 (vm_contract.admin, vm_contract.vm_node.id) | ||||||
|         //         ()
 |             } | ||||||
|         //     }
 |             _ => { | ||||||
|         //     Ok((_, Some(app_contract)))
 |                 // TODO: Hey, Noor! Please add app contract here.
 | ||||||
|         //         if app_contract.admin_pubkey == req.admin_pubkey
 |                 return Err(Status::unauthenticated("No contract found by this ID.")); | ||||||
|         //             && app_contract.node_pubkey == req.node_pubkey =>
 |             } | ||||||
|         //     {
 |         }; | ||||||
|         //         ()
 |         db::Report::create(account, node, req.reason).await?; | ||||||
|         //     }
 |         Ok(Response::new(Empty {})) | ||||||
|         //     _ => 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 {}))
 |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async fn list_operators( |     async fn list_operators( | ||||||
| @ -178,12 +174,11 @@ impl BrainGeneralCli for BrainGeneralCliMock { | |||||||
| 
 | 
 | ||||||
|     // admin commands
 |     // admin commands
 | ||||||
| 
 | 
 | ||||||
|     async fn airdrop(&self, _req: Request<AirdropReq>) -> Result<Response<Empty>, Status> { |     async fn airdrop(&self, req: Request<AirdropReq>) -> Result<Response<Empty>, Status> { | ||||||
|         todo!(); |         check_admin_key(&req)?; | ||||||
|         // check_admin_key(&req)?;
 |         let req = check_sig_from_req(req)?; | ||||||
|         // let req = check_sig_from_req(req)?;
 |         db::Account::airdrop(&req.pubkey, req.tokens).await?; | ||||||
|         // self.data.give_airdrop(&req.pubkey, req.tokens);
 |         Ok(Response::new(Empty {})) | ||||||
|         // Ok(Response::new(Empty {}))
 |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async fn slash(&self, _req: Request<SlashReq>) -> Result<Response<Empty>, Status> { |     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!(Pubkey, pubkey); | ||||||
| impl_pubkey_getter!(NewVmReq, admin_pubkey); | impl_pubkey_getter!(NewVmReq, admin_pubkey); | ||||||
| impl_pubkey_getter!(DeleteVmReq, admin_pubkey); | impl_pubkey_getter!(DeleteVmReq, admin_pubkey); | ||||||
| impl_pubkey_getter!(ReportNodeReq, admin_pubkey); |  | ||||||
| impl_pubkey_getter!(UpdateVmReq, admin_pubkey); | impl_pubkey_getter!(UpdateVmReq, admin_pubkey); | ||||||
| impl_pubkey_getter!(ExtendVmReq, admin_pubkey); | impl_pubkey_getter!(ExtendVmReq, admin_pubkey); | ||||||
|  | impl_pubkey_getter!(ReportNodeReq, admin_pubkey); | ||||||
| impl_pubkey_getter!(ListVmContractsReq, wallet); | impl_pubkey_getter!(ListVmContractsReq, wallet); | ||||||
| impl_pubkey_getter!(RegisterVmNodeReq, node_pubkey); | 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!(VmNodeFilters); | ||||||
| impl_pubkey_getter!(Empty); | 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> { | fn check_sig_from_req<T: std::fmt::Debug + PubkeyGetter>(req: Request<T>) -> Result<T, Status> { | ||||||
|     let time = match req.metadata().get("timestamp") { |     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) |     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