aboutsummaryrefslogtreecommitdiffstats
path: root/src/handlers.rs
diff options
context:
space:
mode:
authorYigit Sever2021-04-11 21:39:18 +0300
committerYigit Sever2021-04-12 00:03:23 +0300
commitd3889bd5945b2ffc63d20942b7730b5a1d0e3a42 (patch)
treea8b2dfcd416f308e7fae4baea95d6107a9871c43 /src/handlers.rs
parent11b498dc44a7d2ed8f1acc62d64be7f114adc336 (diff)
downloadgradecoin-d3889bd5945b2ffc63d20942b7730b5a1d0e3a42.tar.gz
gradecoin-d3889bd5945b2ffc63d20942b7730b5a1d0e3a42.tar.bz2
gradecoin-d3889bd5945b2ffc63d20942b7730b5a1d0e3a42.zip
Implement User handling and authentication
New struct: User, corresponds to a student Blocks and users are persistent (written to a text file) PostgreSQL would've been overkill, we have 30 students AuthRequest is the representation for incoming register requests and User is the inner representation Students who are enrolled to the class are hardcoded, only they can register new accounts There are two new tests, one checks if a priviliged (=enrolled) user can create an account and the other checks if a unpriviliged one cannot There are quick verbose error messages that I'm not married to, might move on to something better honestly There's nothing stopping a malicious user to pre-register everyone with mock public keys and effectively lock everyone out, what's a good secret we can use?
Diffstat (limited to 'src/handlers.rs')
-rw-r--r--src/handlers.rs83
1 files changed, 70 insertions, 13 deletions
diff --git a/src/handlers.rs b/src/handlers.rs
index 856970d..bfd57bc 100644
--- a/src/handlers.rs
+++ b/src/handlers.rs
@@ -1,10 +1,62 @@
1/// API handlers, the ends of each filter chain 1/// API handlers, the ends of each filter chain
2use log::debug; // this is more useful than debug! learn how to use this 2use log::debug;
3use parking_lot::RwLockUpgradableReadGuard; 3use parking_lot::RwLockUpgradableReadGuard;
4use serde_json;
4use std::convert::Infallible; 5use std::convert::Infallible;
5use warp::{http::StatusCode, reply}; 6use warp::{http::Response, http::StatusCode, reply};
6 7
7use crate::schema::{Block, Db, Transaction}; 8use std::fs;
9
10use crate::schema::{AuthRequest, Block, Db, MetuId, Transaction, User};
11
12/// POST /register
13/// Enables a student to introduce themselves to the system
14/// Can fail
15pub async fn authenticate_user(
16 request: AuthRequest,
17 db: Db,
18) -> Result<impl warp::Reply, warp::Rejection> {
19 let given_id = request.student_id.clone();
20
21 if let Some(priv_student_id) = MetuId::new(request.student_id) {
22 let userlist = db.users.upgradable_read();
23
24 if userlist.contains_key(&given_id) {
25
26 let res = Response::builder()
27 .status(StatusCode::BAD_REQUEST)
28 .body("This user is already authenticated");
29
30 Ok(res)
31 } else {
32 let new_user = User {
33 user_id: priv_student_id,
34 public_key: request.public_key,
35 balance: 0,
36 };
37
38 let user_json = serde_json::to_string(&new_user).unwrap();
39
40 fs::write(format!("users/{}.guy", new_user.user_id), user_json).unwrap();
41
42 let mut userlist = RwLockUpgradableReadGuard::upgrade(userlist);
43 userlist.insert(given_id, new_user);
44 // TODO: signature of the public key, please <11-04-21, yigit> //
45
46 let res = Response::builder()
47 .status(StatusCode::CREATED)
48 .body("Ready to use Gradecoin");
49
50 Ok(res)
51 }
52 } else {
53 let res = Response::builder()
54 .status(StatusCode::BAD_REQUEST)
55 .body("This user cannot have a gradecoin account");
56
57 Ok(res)
58 }
59}
8 60
9/// GET /transaction 61/// GET /transaction
10/// Returns JSON array of transactions 62/// Returns JSON array of transactions
@@ -28,16 +80,11 @@ pub async fn list_transactions(db: Db) -> Result<impl warp::Reply, Infallible> {
28/// Cannot fail 80/// Cannot fail
29/// Mostly around for debug purposes 81/// Mostly around for debug purposes
30pub async fn list_blocks(db: Db) -> Result<impl warp::Reply, Infallible> { 82pub async fn list_blocks(db: Db) -> Result<impl warp::Reply, Infallible> {
31 debug!("list all blocks"); 83 debug!("list all block");
32
33 let mut result = Vec::new();
34 let blocks = db.blockchain.read();
35 84
36 for block in blocks.iter() { 85 let block = db.blockchain.read();
37 result.push(block);
38 }
39 86
40 Ok(reply::with_status(reply::json(&result), StatusCode::OK)) 87 Ok(reply::with_status(reply::json(&*block), StatusCode::OK))
41} 88}
42 89
43/// POST /transaction 90/// POST /transaction
@@ -70,7 +117,7 @@ pub async fn propose_block(new_block: Block, db: Db) -> Result<impl warp::Reply,
70 let pending_transactions = db.pending_transactions.upgradable_read(); 117 let pending_transactions = db.pending_transactions.upgradable_read();
71 let blockchain = db.blockchain.upgradable_read(); 118 let blockchain = db.blockchain.upgradable_read();
72 119
73 // TODO: check 1, new_block.transaction_list from pending_transactions pool? <07-04-21, yigit> // 120 // check 1, new_block.transaction_list from pending_transactions pool? <07-04-21, yigit> //
74 for transaction_hash in new_block.transaction_list.iter() { 121 for transaction_hash in new_block.transaction_list.iter() {
75 if !pending_transactions.contains_key(transaction_hash) { 122 if !pending_transactions.contains_key(transaction_hash) {
76 return Ok(StatusCode::BAD_REQUEST); 123 return Ok(StatusCode::BAD_REQUEST);
@@ -81,7 +128,17 @@ pub async fn propose_block(new_block: Block, db: Db) -> Result<impl warp::Reply,
81 // assume it is for now 128 // assume it is for now
82 129
83 let mut blockchain = RwLockUpgradableReadGuard::upgrade(blockchain); 130 let mut blockchain = RwLockUpgradableReadGuard::upgrade(blockchain);
84 blockchain.push(new_block); 131
132 let block_json = serde_json::to_string(&new_block).unwrap();
133
134 // let mut file = File::create(format!("{}.block", new_block.timestamp.timestamp())).unwrap();
135 fs::write(
136 format!("blocks/{}.block", new_block.timestamp.timestamp()),
137 block_json,
138 )
139 .unwrap();
140
141 *blockchain = new_block;
85 142
86 let mut pending_transactions = RwLockUpgradableReadGuard::upgrade(pending_transactions); 143 let mut pending_transactions = RwLockUpgradableReadGuard::upgrade(pending_transactions);
87 pending_transactions.clear(); 144 pending_transactions.clear();