diff options
| -rw-r--r-- | src/db.rs | 39 | ||||
| -rw-r--r-- | src/handlers.rs | 36 | ||||
| -rw-r--r-- | src/student.rs | 70 |
3 files changed, 56 insertions, 89 deletions
| @@ -14,13 +14,14 @@ use log::debug; | |||
| 14 | use parking_lot::RwLock; | 14 | use parking_lot::RwLock; |
| 15 | use std::{collections::HashMap, fs, io, path::PathBuf, sync::Arc}; | 15 | use std::{collections::HashMap, fs, io, path::PathBuf, sync::Arc}; |
| 16 | 16 | ||
| 17 | const PREAPPROVED_STU_FILENAME: &str = "students.csv"; | ||
| 18 | |||
| 17 | #[derive(Debug, Clone, Default)] | 19 | #[derive(Debug, Clone, Default)] |
| 18 | pub struct Db { | 20 | pub struct Db { |
| 19 | pub blockchain: Arc<RwLock<Block>>, | 21 | pub blockchain: Arc<RwLock<Block>>, |
| 20 | pub pending_transactions: Arc<RwLock<HashMap<Id, Transaction>>>, | 22 | pub pending_transactions: Arc<RwLock<HashMap<Id, Transaction>>>, |
| 21 | pub users: Arc<RwLock<HashMap<Fingerprint, User>>>, | 23 | pub users: Arc<RwLock<HashMap<Fingerprint, User>>>, |
| 22 | approved_users: Vec<MetuId>, | 24 | preapproved_users: Vec<MetuId>, |
| 23 | // TODO: metu_ids or approved_users or something, metu_id struct <11-04-22, yigit> // | ||
| 24 | } | 25 | } |
| 25 | 26 | ||
| 26 | impl Db { | 27 | impl Db { |
| @@ -37,13 +38,13 @@ impl Db { | |||
| 37 | } | 38 | } |
| 38 | 39 | ||
| 39 | let users: HashMap<Fingerprint, User> = get_friendly_users(); | 40 | let users: HashMap<Fingerprint, User> = get_friendly_users(); |
| 40 | let approved_users = read_approved_users(); | 41 | let preapproved_users = read_approved_users(); |
| 41 | 42 | ||
| 42 | Db { | 43 | Db { |
| 43 | blockchain: Arc::new(RwLock::new(Block::default())), | 44 | blockchain: Arc::new(RwLock::new(Block::default())), |
| 44 | pending_transactions: Arc::new(RwLock::new(HashMap::new())), | 45 | pending_transactions: Arc::new(RwLock::new(HashMap::new())), |
| 45 | users: Arc::new(RwLock::new(users)), | 46 | users: Arc::new(RwLock::new(users)), |
| 46 | approved_users, | 47 | preapproved_users, |
| 47 | } | 48 | } |
| 48 | } | 49 | } |
| 49 | 50 | ||
| @@ -69,6 +70,16 @@ impl Db { | |||
| 69 | } | 70 | } |
| 70 | } | 71 | } |
| 71 | } | 72 | } |
| 73 | |||
| 74 | pub fn is_user_preapproved(&self, id: &Id, passwd: &String) -> bool { | ||
| 75 | for user in &self.preapproved_users { | ||
| 76 | if *user.get_id() == *id && *user.get_passwd() == *passwd { | ||
| 77 | return true; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | false | ||
| 82 | } | ||
| 72 | } | 83 | } |
| 73 | 84 | ||
| 74 | fn last_block_content() -> Option<String> { | 85 | fn last_block_content() -> Option<String> { |
| @@ -122,7 +133,7 @@ fn get_friendly_users() -> HashMap<Fingerprint, User> { | |||
| 122 | users.insert( | 133 | users.insert( |
| 123 | "cde48537ca2c28084ff560826d0e6388b7c57a51497a6cb56f397289e52ff41b".to_owned(), | 134 | "cde48537ca2c28084ff560826d0e6388b7c57a51497a6cb56f397289e52ff41b".to_owned(), |
| 124 | User { | 135 | User { |
| 125 | user_id: MetuId::new("friend_1".to_owned(), "not_used".to_owned()).unwrap(), | 136 | user_id: MetuId::new("friend_1".to_owned(), "not_used".to_owned()), |
| 126 | public_key: "not_used".to_owned(), | 137 | public_key: "not_used".to_owned(), |
| 127 | balance: 70, | 138 | balance: 70, |
| 128 | is_bot: true, | 139 | is_bot: true, |
| @@ -132,7 +143,7 @@ fn get_friendly_users() -> HashMap<Fingerprint, User> { | |||
| 132 | users.insert( | 143 | users.insert( |
| 133 | "a1a38b5bae5866d7d998a9834229ec2f9db7a4fc8fb6f58b1115a96a446875ff".to_owned(), | 144 | "a1a38b5bae5866d7d998a9834229ec2f9db7a4fc8fb6f58b1115a96a446875ff".to_owned(), |
| 134 | User { | 145 | User { |
| 135 | user_id: MetuId::new("friend_2".to_owned(), "not_used".to_owned()).unwrap(), | 146 | user_id: MetuId::new("friend_2".to_owned(), "not_used".to_owned()), |
| 136 | public_key: "not_used".to_owned(), | 147 | public_key: "not_used".to_owned(), |
| 137 | balance: 20, | 148 | balance: 20, |
| 138 | is_bot: true, | 149 | is_bot: true, |
| @@ -142,7 +153,7 @@ fn get_friendly_users() -> HashMap<Fingerprint, User> { | |||
| 142 | users.insert( | 153 | users.insert( |
| 143 | "4e048fd2a62f1307866086e803e9be43f78a702d5df10831fbf434e7663ae0e7".to_owned(), | 154 | "4e048fd2a62f1307866086e803e9be43f78a702d5df10831fbf434e7663ae0e7".to_owned(), |
| 144 | User { | 155 | User { |
| 145 | user_id: MetuId::new("friend_4".to_owned(), "not_used".to_owned()).unwrap(), | 156 | user_id: MetuId::new("friend_4".to_owned(), "not_used".to_owned()), |
| 146 | public_key: "not_used".to_owned(), | 157 | public_key: "not_used".to_owned(), |
| 147 | balance: 120, | 158 | balance: 120, |
| 148 | is_bot: true, | 159 | is_bot: true, |
| @@ -152,7 +163,7 @@ fn get_friendly_users() -> HashMap<Fingerprint, User> { | |||
| 152 | users.insert( | 163 | users.insert( |
| 153 | "60e77101e76950a9b1830fa107fd2f8fc545255b3e0f14b6a7797cf9ee005f07".to_owned(), | 164 | "60e77101e76950a9b1830fa107fd2f8fc545255b3e0f14b6a7797cf9ee005f07".to_owned(), |
| 154 | User { | 165 | User { |
| 155 | user_id: MetuId::new("friend_4".to_owned(), "not_used".to_owned()).unwrap(), | 166 | user_id: MetuId::new("friend_4".to_owned(), "not_used".to_owned()), |
| 156 | public_key: "not_used".to_owned(), | 167 | public_key: "not_used".to_owned(), |
| 157 | balance: 40, | 168 | balance: 40, |
| 158 | is_bot: true, | 169 | is_bot: true, |
| @@ -163,11 +174,19 @@ fn get_friendly_users() -> HashMap<Fingerprint, User> { | |||
| 163 | 174 | ||
| 164 | fn read_approved_users() -> Vec<MetuId> { | 175 | fn read_approved_users() -> Vec<MetuId> { |
| 165 | let mut approved_students: Vec<MetuId> = Vec::new(); | 176 | let mut approved_students: Vec<MetuId> = Vec::new(); |
| 166 | let contents = fs::read_to_string("students.csv").unwrap(); | 177 | let contents = fs::read_to_string(PREAPPROVED_STU_FILENAME).unwrap_or_else(|_| { |
| 178 | panic!( | ||
| 179 | "{}", | ||
| 180 | format!( | ||
| 181 | "Expected {} to load preapproved students", | ||
| 182 | PREAPPROVED_STU_FILENAME | ||
| 183 | ) | ||
| 184 | ) | ||
| 185 | }); | ||
| 167 | let mut reader = csv::Reader::from_reader(contents.as_bytes()); | 186 | let mut reader = csv::Reader::from_reader(contents.as_bytes()); |
| 168 | for student in reader.records() { | 187 | for student in reader.records() { |
| 169 | let student = student.unwrap(); | 188 | let student = student.unwrap(); |
| 170 | approved_students.push(MetuId::_new(student[0].to_owned(), student[1].to_owned())); | 189 | approved_students.push(MetuId::new(student[0].to_owned(), student[1].to_owned())); |
| 171 | } | 190 | } |
| 172 | approved_students | 191 | approved_students |
| 173 | } | 192 | } |
diff --git a/src/handlers.rs b/src/handlers.rs index 96001ce..ca0608c 100644 --- a/src/handlers.rs +++ b/src/handlers.rs | |||
| @@ -220,7 +220,7 @@ pub async fn authenticate_user( | |||
| 220 | }; | 220 | }; |
| 221 | 221 | ||
| 222 | // c field was properly base64 encoded, now available in auth_packet | 222 | // c field was properly base64 encoded, now available in auth_packet |
| 223 | // decryptor was setup properly, with the correct lenght key | 223 | // decryptor was setup properly, with the correct length key |
| 224 | let mut buf = auth_packet; | 224 | let mut buf = auth_packet; |
| 225 | let auth_plaintext = match cipher.decrypt(&mut buf) { | 225 | let auth_plaintext = match cipher.decrypt(&mut buf) { |
| 226 | Ok(p) => p, | 226 | Ok(p) => p, |
| @@ -278,24 +278,22 @@ pub async fn authenticate_user( | |||
| 278 | }; | 278 | }; |
| 279 | 279 | ||
| 280 | // is the student in AuthRequest privileged? | 280 | // is the student in AuthRequest privileged? |
| 281 | // TODO: this is the only check for 'if metuid is approved' <15-04-22, yigit> // | 281 | let privileged_student_id = if db.is_user_preapproved(&request.student_id, &request.passwd) { |
| 282 | let privileged_student_id = | 282 | MetuId::new(request.student_id.clone(), request.passwd.clone()) |
| 283 | if let Some(id) = MetuId::new(request.student_id.clone(), request.passwd.clone()) { | 283 | } else { |
| 284 | id | 284 | debug!( |
| 285 | } else { | 285 | "Someone tried to auth with invalid credentials: {} {}", |
| 286 | debug!( | 286 | &request.student_id, &request.passwd |
| 287 | "Someone tried to auth with invalid credentials: {} {}", | 287 | ); |
| 288 | &request.student_id, &request.passwd | 288 | let res_json = warp::reply::json(&GradeCoinResponse { |
| 289 | ); | 289 | res: ResponseType::Error, |
| 290 | let res_json = warp::reply::json(&GradeCoinResponse { | 290 | message: |
| 291 | res: ResponseType::Error, | 291 | "The credentials given ('student_id', 'passwd') cannot hold a Gradecoin account" |
| 292 | message: | 292 | .to_owned(), |
| 293 | "The credentials given ('student_id', 'passwd') cannot hold a Gradecoin account" | 293 | }); |
| 294 | .to_owned(), | ||
| 295 | }); | ||
| 296 | 294 | ||
| 297 | return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST)); | 295 | return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST)); |
| 298 | }; | 296 | }; |
| 299 | 297 | ||
| 300 | // Students should be able to authenticate once | 298 | // Students should be able to authenticate once |
| 301 | { | 299 | { |
| @@ -382,7 +380,7 @@ pub async fn list_transactions(db: Db) -> Result<impl warp::Reply, Infallible> { | |||
| 382 | /// Proposes a new block for the next round. | 380 | /// Proposes a new block for the next round. |
| 383 | /// Can reject the block | 381 | /// Can reject the block |
| 384 | /// | 382 | /// |
| 385 | /// The proposer has to put their transaction as the first transaction of the transaction_list. | 383 | /// The proposer has to put their transaction as the first transaction of the `Block::transaction_list`. |
| 386 | /// This is the analogue of `coinbase` in Bitcoin works | 384 | /// This is the analogue of `coinbase` in Bitcoin works |
| 387 | /// | 385 | /// |
| 388 | /// The `coinbase` transaction also gets something for their efforts. | 386 | /// The `coinbase` transaction also gets something for their efforts. |
diff --git a/src/student.rs b/src/student.rs index 711eeeb..2b9c5bd 100644 --- a/src/student.rs +++ b/src/student.rs | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | use crate::Fingerprint; | 1 | use crate::{Fingerprint, Id}; |
| 2 | use lazy_static::lazy_static; | ||
| 3 | use serde::{Deserialize, Serialize}; | 2 | use serde::{Deserialize, Serialize}; |
| 4 | use std::{collections::HashSet, fmt}; | 3 | use std::fmt; |
| 5 | 4 | ||
| 6 | #[derive(Debug, Serialize, Deserialize, PartialEq)] | 5 | #[derive(Debug, Serialize, Deserialize, PartialEq)] |
| 7 | pub struct UserAtRest { | 6 | pub struct UserAtRest { |
| @@ -25,11 +24,9 @@ pub struct User { | |||
| 25 | pub is_bot: bool, | 24 | pub is_bot: bool, |
| 26 | } | 25 | } |
| 27 | 26 | ||
| 28 | /// The values are hard coded in [`static@OUR_STUDENTS`] so `MetuId::new`() can accept/reject values based on that | ||
| 29 | /// TODO update the statement above | ||
| 30 | #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] | 27 | #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] |
| 31 | pub struct MetuId { | 28 | pub struct MetuId { |
| 32 | id: String, | 29 | id: Id, |
| 33 | passwd: String, | 30 | passwd: String, |
| 34 | } | 31 | } |
| 35 | 32 | ||
| @@ -40,62 +37,15 @@ impl fmt::Display for MetuId { | |||
| 40 | } | 37 | } |
| 41 | 38 | ||
| 42 | impl MetuId { | 39 | impl MetuId { |
| 43 | pub fn new(id: String, pwd: String) -> Option<Self> { | 40 | pub fn new(id: String, passwd: String) -> Self { |
| 44 | if OUR_STUDENTS.contains(&(&*id, &*pwd)) { | 41 | MetuId { id, passwd } |
| 45 | Some(MetuId { id, passwd: pwd }) | ||
| 46 | } else { | ||
| 47 | None | ||
| 48 | } | ||
| 49 | } | 42 | } |
| 50 | 43 | ||
| 51 | // TODO: replace the function above with this <15-04-22, yigit> // | 44 | pub fn get_id(&self) -> &Id { |
| 52 | pub fn _new(id: String, passwd: String) -> Self { | 45 | &self.id |
| 53 | MetuId { id, passwd } | ||
| 54 | } | 46 | } |
| 55 | } | ||
| 56 | 47 | ||
| 57 | // TODO: remove this, read from a yaml or something, then MetuId::new gets a self <11-04-22, yigit> // | 48 | pub fn get_passwd(&self) -> &String { |
| 58 | // Students who are authorized to have Gradecoin accounts | 49 | &self.passwd |
| 59 | lazy_static! { | 50 | } |
| 60 | static ref OUR_STUDENTS: HashSet<(&'static str, &'static str)> = { | ||
| 61 | [ | ||
| 62 | ("e254275", "DtNX1qk4YF4saRH"), | ||
| 63 | ("e223687", "cvFEs4XLjuGBD1v"), | ||
| 64 | ("e211024", "voQAcxiKJmEXYRT"), | ||
| 65 | ("e209888", "O75dli6AQtz2tUi"), | ||
| 66 | ("e223725", "xXuTD3Y4tyrv2Jz"), | ||
| 67 | ("e209362", "N7wGm5XU5zVWOWu"), | ||
| 68 | ("e209898", "aKBFfB8fZMq8pVn"), | ||
| 69 | ("e230995", "TgcHGlqeFhQGx42"), | ||
| 70 | ("e223743", "YVWVSWuIHplJk9C"), | ||
| 71 | ("e223747", "8LAeHrsjnwXh59Q"), | ||
| 72 | ("e223749", "HMFeJqVOzwCPHbc"), | ||
| 73 | ("e223751", "NjMsxmtmy2VOwMW"), | ||
| 74 | ("e188126", "QibuPdV2gXfsVJW"), | ||
| 75 | ("e209913", "kMxJvl2vHSWCy4A"), | ||
| 76 | ("e203608", "mfkkR0MWurk6Rp1"), | ||
| 77 | ("e233013", "GCqHxdOaDj2pWXx"), | ||
| 78 | ("e216982", "2Z0xmgCStnj5qg5"), | ||
| 79 | ("e217185", "BcaZNlzlhPph7A3"), | ||
| 80 | ("e223780", "2KvVxKUQaA9H4sn"), | ||
| 81 | ("e194931", "hsC0Wb8PQ5vzwdQ"), | ||
| 82 | ("e223783", "ETUJA3kt1QYvJai"), | ||
| 83 | ("e254550", "rPRjX0A4NefvKWi"), | ||
| 84 | ("e217203", "lN3IWhGyCrGfkk5"), | ||
| 85 | ("e217477", "O9xlMaa7LanC82w"), | ||
| 86 | ("e223786", "UxI6czykJfp9T9N"), | ||
| 87 | ("e231060", "VJgziofQQPCoisH"), | ||
| 88 | ("e223795", "pmcTCKox99NFsqp"), | ||
| 89 | ("e223715", "1H5QuOYI1b2r9ET"), | ||
| 90 | ("e181932", "THANKYOUHAVEFUN"), | ||
| 91 | ("bank", "P7oxDm30g1jeIId"), | ||
| 92 | ("friend_1", "not_used"), | ||
| 93 | ("friend_2", "not_used"), | ||
| 94 | ("friend_3", "not_used"), | ||
| 95 | ("friend_4", "not_used"), | ||
| 96 | ] | ||
| 97 | .iter() | ||
| 98 | .copied() | ||
| 99 | .collect() | ||
| 100 | }; | ||
| 101 | } | 51 | } |
