diff options
author | Yigit Sever | 2021-04-11 21:39:18 +0300 |
---|---|---|
committer | Yigit Sever | 2021-04-12 00:03:23 +0300 |
commit | 518a99a132707ba0e2572b24ca18f6b9606d7334 (patch) | |
tree | c7cbe183f088b286903389f58743b1e5688119c5 /src/handlers.rs | |
parent | 217398c52c68b3b73454d3e9f66c85b5a1638f3f (diff) | |
download | gradecoin-518a99a132707ba0e2572b24ca18f6b9606d7334.tar.gz gradecoin-518a99a132707ba0e2572b24ca18f6b9606d7334.tar.bz2 gradecoin-518a99a132707ba0e2572b24ca18f6b9606d7334.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.rs | 83 |
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 |
2 | use log::debug; // this is more useful than debug! learn how to use this | 2 | use log::debug; |
3 | use parking_lot::RwLockUpgradableReadGuard; | 3 | use parking_lot::RwLockUpgradableReadGuard; |
4 | use serde_json; | ||
4 | use std::convert::Infallible; | 5 | use std::convert::Infallible; |
5 | use warp::{http::StatusCode, reply}; | 6 | use warp::{http::Response, http::StatusCode, reply}; |
6 | 7 | ||
7 | use crate::schema::{Block, Db, Transaction}; | 8 | use std::fs; |
9 | |||
10 | use 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 | ||
15 | pub 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 |
30 | pub async fn list_blocks(db: Db) -> Result<impl warp::Reply, Infallible> { | 82 | pub 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(); |