From aa169ad1b3c277859f01413a945ea2d6f1375615 Mon Sep 17 00:00:00 2001 From: alpaylan Date: Mon, 12 Apr 2021 22:15:17 +0300 Subject: implement user authentication using jwt --- src/routes.rs | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 121 insertions(+), 11 deletions(-) (limited to 'src/routes.rs') diff --git a/src/routes.rs b/src/routes.rs index 03a2569..ed2acad 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -1,14 +1,14 @@ +use gradecoin::schema::Db; use warp::{Filter, Rejection, Reply}; use crate::custom_filters; use crate::handlers; -use gradecoin::schema::Db; /// Root, all routes combined pub fn consensus_routes(db: Db) -> impl Filter + Clone { transaction_list(db.clone()) .or(register_user(db.clone())) - .or(transaction_propose(db.clone())) + .or(auth_transaction_propose(db.clone())) .or(block_propose(db.clone())) .or(block_list(db.clone())) } @@ -47,6 +47,18 @@ pub fn transaction_propose(db: Db) -> impl Filter impl Filter + Clone { + warp::path!("transaction") + .and(warp::post()) + .and(custom_filters::transaction_json_body()) + .and(custom_filters::auth_header()) + .and(custom_filters::with_db(db)) + .and_then(handlers::auth_propose_transaction) +} + /// POST /block warp route pub fn block_propose(db: Db) -> impl Filter + Clone { warp::path!("block") @@ -58,22 +70,69 @@ pub fn block_propose(db: Db) -> impl Filter Db { let db = create_database(); + db.users.write().insert( + "mock_transaction_source".to_owned(), + User { + user_id: MetuId::new("e254275".to_owned()).unwrap(), + public_key: +"-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4nU0G4WjkmcQUx0hq6LQ +uV5Q+ACmUFL/OjoYMDwC/O/6pCd1UZgCfgHN2xEffDPznzcTn8OiFRxr4oWyBiny +rUpnY4mhy0SQUwoeCw7YkcHAyhCjNT74aR/ohX0MCj0qRRdbt5ZQXM/GC3HJuXE1 +ptSuhFgQxziItamn8maoJ6JUSVEXVO1NOrrjoM3r7Q+BK2B+sX4/bLZ+VG5g1q2n +EbFdTHS6pHqtZNHQndTmEKwRfh0RYtzEzOXuO6e1gQY42Tujkof40dhGCIU7TeIG +GHwdFxy1niLkXwtHNjV7lnIOkTbx6+sSPamRfQAlZqUWM2Lf5o+7h3qWP3ENB138 +sQIDAQAB +-----END PUBLIC KEY-----" + .to_owned(), + balance: 0, + }, + ); db.pending_transactions.write().insert( "hash_value".to_owned(), Transaction { + by: "source_account".to_owned(), source: "source_account".to_owned(), target: "target_account".to_owned(), amount: 20, @@ -95,6 +154,15 @@ mod tests { db } + fn mocked_jwt() -> String { + + let claims = Claims { + tha: "6692e774eba7fb92dc0fe6cf7347591e".to_owned(), + iat: 1516239022, + }; + let header = Header::new(Algorithm::RS256); + encode(&header, &claims, &EncodingKey::from_rsa_pem(private_key_pem.as_bytes()).unwrap()).unwrap() + } /// Create a mock user that is allowed to be in gradecoin to be used in tests fn priviliged_mocked_user() -> AuthRequest { AuthRequest { @@ -114,6 +182,7 @@ mod tests { /// Create a mock transaction to be used in tests fn mocked_transaction() -> Transaction { Transaction { + by: "mock_transaction_source".to_owned(), source: "mock_transaction_source".to_owned(), target: "mock_transaction_target".to_owned(), amount: 25, @@ -125,9 +194,9 @@ mod tests { fn mocked_block() -> Block { Block { transaction_list: vec!["hash_value".to_owned()], - nonce: 560108, + nonce: 3831993, timestamp: chrono::NaiveDate::from_ymd(2021, 04, 08).and_hms(12, 30, 30), - hash: "c7d053f3e5b056ba948db3f5c0d30408fb0c29a328a0c3c1cf435fb68d700000".to_owned(), + hash: "2b648ffab5d9af1d5d5fc052fc9e51b882fc4fb0c998608c99232f9282000000".to_owned(), } } @@ -158,7 +227,7 @@ mod tests { assert_eq!(res.status(), StatusCode::OK); - let expected_json_body = r#"[{"source":"source_account","target":"target_account","amount":20,"timestamp":"2021-04-09T01:30:30"}]"#; + let expected_json_body = r#"[{"by":"source_account","source":"source_account","target":"target_account","amount":20,"timestamp":"2021-04-09T01:30:30"}]"#; assert_eq!(res.body(), expected_json_body); } @@ -208,10 +277,30 @@ mod tests { async fn post_json_201() { let db = mocked_db(); let filter = consensus_routes(db.clone()); + let res = warp::test::request() + .method("POST") + .json(&mocked_transaction()) + .path("/transaction") + .reply(&filter) + .await; + + assert_eq!(res.status(), StatusCode::CREATED); + assert_eq!(db.pending_transactions.read().len(), 2); + } + + /// Test a POST request to /transaction, a resource that exists + /// https://tools.ietf.org/html/rfc7231#section-6.3.2 + /// Should accept the json request, create + /// the transaction and add it to pending transactions in the db + #[tokio::test] + async fn post_auth_json_201() { + let db = mocked_db(); + let filter = consensus_routes(db.clone()); let res = warp::test::request() .method("POST") .json(&mocked_transaction()) + .header("Authorization", format!("Bearer {}", &mocked_jwt())) .path("/transaction") .reply(&filter) .await; @@ -220,6 +309,27 @@ mod tests { assert_eq!(db.pending_transactions.read().len(), 2); } + /// Test a POST request to /transaction, a resource that exists + /// https://tools.ietf.org/html/rfc7231#section-6.3.2 + /// Should accept the json request, create + /// the transaction and add it to pending transactions in the db + #[tokio::test] + async fn post_auth_json_400() { + let db = mocked_db(); + let filter = consensus_routes(db.clone()); + + let res = warp::test::request() + .method("POST") + .json(&mocked_transaction()) + .header("Authorization", "Bearer aaaaaaaasdlkjaldkasljdaskjlaaaaaaaaaaaaaa") + .path("/transaction") + .reply(&filter) + .await; + + assert_eq!(res.status(), StatusCode::BAD_REQUEST); + assert_eq!(db.pending_transactions.read().len(), 1); + } + /// Test a POST request to /block, a resource that exists /// https://tools.ietf.org/html/rfc7231#section-6.3.2 /// Should accept the json request, create @@ -239,7 +349,7 @@ mod tests { assert_eq!(res.status(), StatusCode::CREATED); assert_eq!( *db.blockchain.read().hash, - "c7d053f3e5b056ba948db3f5c0d30408fb0c29a328a0c3c1cf435fb68d700000".to_owned() + "2b648ffab5d9af1d5d5fc052fc9e51b882fc4fb0c998608c99232f9282000000".to_owned() ); } @@ -279,7 +389,7 @@ mod tests { println!("{:?}", res.body()); assert_eq!(res.status(), StatusCode::CREATED); - assert_eq!(db.users.read().len(), 1); + assert_eq!(db.users.read().len(), 2); } /// Test a POST request to /transaction, an endpoint that exists @@ -299,7 +409,7 @@ mod tests { println!("{:?}", res.body()); assert_eq!(res.status(), StatusCode::BAD_REQUEST); - assert_eq!(db.users.read().len(), 0); + assert_eq!(db.users.read().len(), 1); } /// Test a POST request to /transaction, a resource that exists with a longer than expected -- cgit v1.2.3-70-g09d2