diff options
-rw-r--r-- | src/bin/main.rs | 5 | ||||
-rw-r--r-- | src/custom_filters.rs | 2 | ||||
-rw-r--r-- | src/error.rs | 38 | ||||
-rw-r--r-- | src/handlers.rs | 197 | ||||
-rw-r--r-- | src/lib.rs | 1 |
5 files changed, 182 insertions, 61 deletions
diff --git a/src/bin/main.rs b/src/bin/main.rs index 598a2e1..8b61e5c 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | use std::env; | 1 | use std::env; |
2 | use warp::Filter; | 2 | use warp::Filter; |
3 | 3 | ||
4 | // use gradecoin::error; | ||
4 | use gradecoin::routes::consensus_routes; | 5 | use gradecoin::routes::consensus_routes; |
5 | use gradecoin::schema::create_database; | 6 | use gradecoin::schema::create_database; |
6 | 7 | ||
@@ -9,6 +10,7 @@ use gradecoin::schema::create_database; | |||
9 | #[tokio::main] | 10 | #[tokio::main] |
10 | async fn main() { | 11 | async fn main() { |
11 | // Show debug logs by default by setting `RUST_LOG=gradecoin=debug` | 12 | // Show debug logs by default by setting `RUST_LOG=gradecoin=debug` |
13 | // TODO: write logs to file? <13-04-21, yigit> // | ||
12 | if env::var_os("RUST_LOG").is_none() { | 14 | if env::var_os("RUST_LOG").is_none() { |
13 | env::set_var("RUST_LOG", "gradecoin=debug"); | 15 | env::set_var("RUST_LOG", "gradecoin=debug"); |
14 | } | 16 | } |
@@ -21,5 +23,6 @@ async fn main() { | |||
21 | let routes = api.with(warp::log("gradecoin")); | 23 | let routes = api.with(warp::log("gradecoin")); |
22 | 24 | ||
23 | // Start the server | 25 | // Start the server |
24 | warp::serve(routes).run(([127, 0, 0, 1], 8080)).await; | 26 | let point = ([127, 0, 0, 1], 8080); |
27 | warp::serve(routes).run(point).await; | ||
25 | } | 28 | } |
diff --git a/src/custom_filters.rs b/src/custom_filters.rs index dfdae04..ae8a56c 100644 --- a/src/custom_filters.rs +++ b/src/custom_filters.rs | |||
@@ -28,7 +28,7 @@ pub fn transaction_json_body() -> impl Filter<Extract = (Transaction,), Error = | |||
28 | /// Used in Authorization for `Block` and `Transaction` proposals | 28 | /// Used in Authorization for `Block` and `Transaction` proposals |
29 | /// Rejects the request if the Authorization header does not exist | 29 | /// Rejects the request if the Authorization header does not exist |
30 | pub fn auth_header() -> impl Filter<Extract = (String,), Error = Rejection> + Clone { | 30 | pub fn auth_header() -> impl Filter<Extract = (String,), Error = Rejection> + Clone { |
31 | warp::header::header::<String>("Authorization") | 31 | warp::header::<String>("Authorization") |
32 | } | 32 | } |
33 | 33 | ||
34 | /// Extracts an `Block` JSON body from the request | 34 | /// Extracts an `Block` JSON body from the request |
diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..7339a06 --- /dev/null +++ b/src/error.rs | |||
@@ -0,0 +1,38 @@ | |||
1 | use log::warn; | ||
2 | use serde::Serialize; | ||
3 | use std::convert::Infallible; | ||
4 | use warp::{http::StatusCode, Rejection, Reply}; | ||
5 | |||
6 | #[derive(Serialize)] | ||
7 | struct ErrorResponse { | ||
8 | message: String, | ||
9 | } | ||
10 | |||
11 | pub async fn handle_rejection(err: Rejection) -> std::result::Result<impl Reply, Infallible> { | ||
12 | let code; | ||
13 | let message; | ||
14 | |||
15 | if err.is_not_found() { | ||
16 | code = StatusCode::NOT_FOUND; | ||
17 | message = "Requested resource is not found"; | ||
18 | } else if let Some(_) = err.find::<warp::filters::body::BodyDeserializeError>() { | ||
19 | code = StatusCode::BAD_REQUEST; | ||
20 | message = "Error: JSON body is not formatted correctly, check your payload"; | ||
21 | } else if let Some(_) = err.find::<warp::reject::MissingHeader>() { | ||
22 | code = StatusCode::METHOD_NOT_ALLOWED; | ||
23 | message = "Error: Authorization header missing, cannot authorize"; | ||
24 | } else if let Some(_) = err.find::<warp::reject::MethodNotAllowed>() { | ||
25 | code = StatusCode::METHOD_NOT_ALLOWED; | ||
26 | message = "Error: method not allowed on this endpoint"; | ||
27 | } else { | ||
28 | warn!("unhandled error: {:?}", err); | ||
29 | code = StatusCode::INTERNAL_SERVER_ERROR; | ||
30 | message = "Internal Server Error"; | ||
31 | } | ||
32 | |||
33 | let json = warp::reply::json(&ErrorResponse { | ||
34 | message: message.to_owned(), | ||
35 | }); | ||
36 | |||
37 | Ok(warp::reply::with_status(json, code)) | ||
38 | } | ||
diff --git a/src/handlers.rs b/src/handlers.rs index beae999..1189b35 100644 --- a/src/handlers.rs +++ b/src/handlers.rs | |||
@@ -5,10 +5,23 @@ use jsonwebtoken::{decode, Algorithm, DecodingKey, TokenData, Validation}; | |||
5 | use log::{debug, warn}; | 5 | use log::{debug, warn}; |
6 | use md5::Md5; | 6 | use md5::Md5; |
7 | use parking_lot::RwLockUpgradableReadGuard; | 7 | use parking_lot::RwLockUpgradableReadGuard; |
8 | use serde::Serialize; | ||
8 | use serde_json; | 9 | use serde_json; |
9 | use std::convert::Infallible; | 10 | use std::convert::Infallible; |
10 | use std::fs; | 11 | use std::fs; |
11 | use warp::{http::Response, http::StatusCode, reply}; | 12 | use warp::{http::StatusCode, reply}; |
13 | |||
14 | #[derive(Serialize, Debug)] | ||
15 | struct GradeCoinResponse { | ||
16 | res: ResponseType, | ||
17 | message: String, | ||
18 | } | ||
19 | |||
20 | #[derive(Debug, Serialize)] | ||
21 | enum ResponseType { | ||
22 | Success, | ||
23 | Error, | ||
24 | } | ||
12 | 25 | ||
13 | use crate::schema::{AuthRequest, Block, Claims, Db, MetuId, NakedBlock, Transaction, User}; | 26 | use crate::schema::{AuthRequest, Block, Claims, Db, MetuId, NakedBlock, Transaction, User}; |
14 | 27 | ||
@@ -24,45 +37,52 @@ pub async fn authenticate_user( | |||
24 | db: Db, | 37 | db: Db, |
25 | ) -> Result<impl warp::Reply, warp::Rejection> { | 38 | ) -> Result<impl warp::Reply, warp::Rejection> { |
26 | debug!("POST request to /register, authenticate_user"); | 39 | debug!("POST request to /register, authenticate_user"); |
27 | let given_id = request.student_id.clone(); | 40 | let provided_id = request.student_id.clone(); |
28 | 41 | ||
29 | if let Some(priv_student_id) = MetuId::new(request.student_id) { | 42 | let priv_student_id = match MetuId::new(request.student_id) { |
30 | let userlist = db.users.upgradable_read(); | 43 | Some(id) => id, |
44 | None => { | ||
45 | let res_json = warp::reply::json(&GradeCoinResponse { | ||
46 | res: ResponseType::Error, | ||
47 | message: "This user cannot have a gradecoin account".to_owned(), | ||
48 | }); | ||
31 | 49 | ||
32 | if userlist.contains_key(&given_id) { | 50 | return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST)); |
33 | let res = Response::builder() | 51 | } |
34 | .status(StatusCode::BAD_REQUEST) | 52 | }; |
35 | .body("This user is already authenticated"); | ||
36 | 53 | ||
37 | Ok(res) | 54 | let userlist = db.users.upgradable_read(); |
38 | } else { | ||
39 | let new_user = User { | ||
40 | user_id: priv_student_id, | ||
41 | public_key: request.public_key, | ||
42 | balance: 0, | ||
43 | }; | ||
44 | 55 | ||
45 | let user_json = serde_json::to_string(&new_user).unwrap(); | 56 | if userlist.contains_key(&provided_id) { |
57 | let res_json = warp::reply::json(&GradeCoinResponse { | ||
58 | res: ResponseType::Error, | ||
59 | message: "This user is already authenticated".to_owned(), | ||
60 | }); | ||
46 | 61 | ||
47 | fs::write(format!("users/{}.guy", new_user.user_id), user_json).unwrap(); | 62 | return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST)); |
63 | } | ||
48 | 64 | ||
49 | let mut userlist = RwLockUpgradableReadGuard::upgrade(userlist); | 65 | // TODO: audit public key, is it valid? <13-04-21, yigit> // |
50 | userlist.insert(given_id, new_user); | 66 | let new_user = User { |
51 | // TODO: signature of the public key, please <11-04-21, yigit> // | 67 | user_id: priv_student_id, |
68 | public_key: request.public_key, | ||
69 | balance: 0, | ||
70 | }; | ||
52 | 71 | ||
53 | let res = Response::builder() | 72 | let user_json = serde_json::to_string(&new_user).unwrap(); |
54 | .status(StatusCode::CREATED) | ||
55 | .body("Ready to use Gradecoin"); | ||
56 | 73 | ||
57 | Ok(res) | 74 | fs::write(format!("users/{}.guy", new_user.user_id), user_json).unwrap(); |
58 | } | ||
59 | } else { | ||
60 | let res = Response::builder() | ||
61 | .status(StatusCode::BAD_REQUEST) | ||
62 | .body("This user cannot have a gradecoin account"); | ||
63 | 75 | ||
64 | Ok(res) | 76 | let mut userlist = RwLockUpgradableReadGuard::upgrade(userlist); |
65 | } | 77 | userlist.insert(provided_id, new_user); |
78 | // TODO: signature of the public key, please <11-04-21, yigit> // | ||
79 | |||
80 | let res_json = warp::reply::json(&GradeCoinResponse { | ||
81 | res: ResponseType::Success, | ||
82 | message: "User authenticated to use Gradecoin".to_owned(), | ||
83 | }); | ||
84 | |||
85 | Ok(warp::reply::with_status(res_json, StatusCode::CREATED)) | ||
66 | } | 86 | } |
67 | 87 | ||
68 | /// GET /transaction | 88 | /// GET /transaction |
@@ -106,11 +126,17 @@ pub async fn authorized_propose_block( | |||
106 | Some(existing_user) => existing_user, | 126 | Some(existing_user) => existing_user, |
107 | None => { | 127 | None => { |
108 | debug!( | 128 | debug!( |
109 | "A user with public key signature {:?} is not found in the database", | 129 | "User with public key signature {:?} is not found in the database", |
110 | new_block.transaction_list[0] | 130 | new_block.transaction_list[0] |
111 | ); | 131 | ); |
112 | // TODO: verbose error here <13-04-21, yigit> // | 132 | |
113 | return Ok(StatusCode::BAD_REQUEST); | 133 | let res_json = warp::reply::json(&GradeCoinResponse { |
134 | res: ResponseType::Error, | ||
135 | message: "User with the given public key signature is not found in the database" | ||
136 | .to_owned(), | ||
137 | }); | ||
138 | |||
139 | return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST)); | ||
114 | } | 140 | } |
115 | }; | 141 | }; |
116 | 142 | ||
@@ -120,7 +146,13 @@ pub async fn authorized_propose_block( | |||
120 | Ok(data) => data, | 146 | Ok(data) => data, |
121 | Err(below) => { | 147 | Err(below) => { |
122 | debug!("Something went wrong below {:?}", below); | 148 | debug!("Something went wrong below {:?}", below); |
123 | return Ok(StatusCode::BAD_REQUEST); | 149 | |
150 | let res_json = warp::reply::json(&GradeCoinResponse { | ||
151 | res: ResponseType::Error, | ||
152 | message: below, | ||
153 | }); | ||
154 | |||
155 | return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST)); | ||
124 | } | 156 | } |
125 | }; | 157 | }; |
126 | 158 | ||
@@ -131,7 +163,12 @@ pub async fn authorized_propose_block( | |||
131 | "The Hash of the block {:?} did not match the hash given in jwt {:?}", | 163 | "The Hash of the block {:?} did not match the hash given in jwt {:?}", |
132 | new_block.hash, token_payload.claims.tha | 164 | new_block.hash, token_payload.claims.tha |
133 | ); | 165 | ); |
134 | return Ok(StatusCode::BAD_REQUEST); | 166 | let res_json = warp::reply::json(&GradeCoinResponse { |
167 | res: ResponseType::Error, | ||
168 | message: "The hash of the block did not match the hash given in JWT".to_owned(), | ||
169 | }); | ||
170 | |||
171 | return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST)); | ||
135 | } | 172 | } |
136 | 173 | ||
137 | debug!("clear for block proposal"); | 174 | debug!("clear for block proposal"); |
@@ -140,7 +177,12 @@ pub async fn authorized_propose_block( | |||
140 | 177 | ||
141 | for transaction_hash in new_block.transaction_list.iter() { | 178 | for transaction_hash in new_block.transaction_list.iter() { |
142 | if !pending_transactions.contains_key(transaction_hash) { | 179 | if !pending_transactions.contains_key(transaction_hash) { |
143 | return Ok(StatusCode::BAD_REQUEST); | 180 | let res_json = warp::reply::json(&GradeCoinResponse { |
181 | res: ResponseType::Error, | ||
182 | message: "Block contains unknown transaction".to_owned(), | ||
183 | }); | ||
184 | |||
185 | return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST)); | ||
144 | } | 186 | } |
145 | } | 187 | } |
146 | 188 | ||
@@ -157,17 +199,28 @@ pub async fn authorized_propose_block( | |||
157 | 199 | ||
158 | // 6 rightmost bits are zero? | 200 | // 6 rightmost bits are zero? |
159 | let should_zero = hashvalue[31] as i32 + hashvalue[30] as i32 + hashvalue[29] as i32; | 201 | let should_zero = hashvalue[31] as i32 + hashvalue[30] as i32 + hashvalue[29] as i32; |
202 | // TODO: this can be offloaded to validator <13-04-21, yigit> // | ||
160 | 203 | ||
161 | if should_zero != 0 { | 204 | if should_zero != 0 { |
162 | debug!("the hash does not have 6 rightmost zero bits"); | 205 | debug!("the hash does not have 6 rightmost zero bits"); |
163 | return Ok(StatusCode::BAD_REQUEST); | 206 | let res_json = warp::reply::json(&GradeCoinResponse { |
207 | res: ResponseType::Error, | ||
208 | message: "Given block hash is larger than target value".to_owned(), | ||
209 | }); | ||
210 | |||
211 | return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST)); | ||
164 | } | 212 | } |
165 | 213 | ||
166 | // one last check to see if block is telling the truth | 214 | // one last check to see if block is telling the truth |
167 | if hash_string != new_block.hash { | 215 | if hash_string != new_block.hash { |
168 | debug!("request was not telling the truth, hash values do not match"); | 216 | debug!("request was not telling the truth, hash values do not match"); |
169 | // TODO: does this condition make more sense _before_ the hash 0s check? <13-04-21, yigit> // | 217 | // TODO: does this condition make more sense _before_ the hash 0s check? <13-04-21, yigit> // |
170 | return Ok(StatusCode::BAD_REQUEST); | 218 | let res_json = warp::reply::json(&GradeCoinResponse { |
219 | res: ResponseType::Error, | ||
220 | message: "Given hash value does not match the actual block hash".to_owned(), | ||
221 | }); | ||
222 | |||
223 | return Ok(warp::reply::with_status(res_json, StatusCode::BAD_REQUEST)); | ||
171 | } | 224 | } |
172 | 225 | ||
173 | let mut blockchain = RwLockUpgradableReadGuard::upgrade(blockchain); | 226 | let mut blockchain = RwLockUpgradableReadGuard::upgrade(blockchain); |
@@ -185,7 +238,13 @@ pub async fn authorized_propose_block( | |||
185 | let mut pending_transactions = RwLockUpgradableReadGuard::upgrade(pending_transactions); | 238 | let mut pending_transactions = RwLockUpgradableReadGuard::upgrade(pending_transactions); |
186 | pending_transactions.clear(); | 239 | pending_transactions.clear(); |
187 | 240 | ||
188 | Ok(StatusCode::CREATED) | 241 | Ok(warp::reply::with_status( |
242 | warp::reply::json(&GradeCoinResponse { | ||
243 | res: ResponseType::Success, | ||
244 | message: "Block accepted".to_owned(), | ||
245 | }), | ||
246 | StatusCode::CREATED, | ||
247 | )) | ||
189 | } | 248 | } |
190 | 249 | ||
191 | /// POST /transaction | 250 | /// POST /transaction |
@@ -213,11 +272,18 @@ pub async fn authorized_propose_transaction( | |||
213 | Some(existing_user) => existing_user, | 272 | Some(existing_user) => existing_user, |
214 | None => { | 273 | None => { |
215 | debug!( | 274 | debug!( |
216 | "A user with public key signature {:?} is not found in the database", | 275 | "User with public key signature {:?} is not found in the database", |
217 | new_transaction.by | 276 | new_transaction.by |
218 | ); | 277 | ); |
219 | // TODO: verbose error here <13-04-21, yigit> // | 278 | |
220 | return Ok(StatusCode::BAD_REQUEST); | 279 | return Ok(warp::reply::with_status( |
280 | warp::reply::json(&GradeCoinResponse { | ||
281 | res: ResponseType::Error, | ||
282 | message: "User with the given public key signature is not authorized" | ||
283 | .to_owned(), | ||
284 | }), | ||
285 | StatusCode::BAD_REQUEST, | ||
286 | )); | ||
221 | } | 287 | } |
222 | }; | 288 | }; |
223 | 289 | ||
@@ -231,7 +297,13 @@ pub async fn authorized_propose_transaction( | |||
231 | Ok(data) => data, | 297 | Ok(data) => data, |
232 | Err(below) => { | 298 | Err(below) => { |
233 | debug!("Something went wrong below {:?}", below); | 299 | debug!("Something went wrong below {:?}", below); |
234 | return Ok(StatusCode::BAD_REQUEST); | 300 | return Ok(warp::reply::with_status( |
301 | warp::reply::json(&GradeCoinResponse { | ||
302 | res: ResponseType::Error, | ||
303 | message: below, | ||
304 | }), | ||
305 | StatusCode::BAD_REQUEST, | ||
306 | )); | ||
235 | } | 307 | } |
236 | }; | 308 | }; |
237 | 309 | ||
@@ -246,14 +318,26 @@ pub async fn authorized_propose_transaction( | |||
246 | "the hash of the request {:x} did not match the hash given in jwt {:?}", | 318 | "the hash of the request {:x} did not match the hash given in jwt {:?}", |
247 | hashed_transaction, token_payload.claims.tha | 319 | hashed_transaction, token_payload.claims.tha |
248 | ); | 320 | ); |
249 | return Ok(StatusCode::BAD_REQUEST); | 321 | return Ok(warp::reply::with_status( |
322 | warp::reply::json(&GradeCoinResponse { | ||
323 | res: ResponseType::Error, | ||
324 | message: "The hash of the block did not match the hash given in JWT".to_owned(), | ||
325 | }), | ||
326 | StatusCode::BAD_REQUEST, | ||
327 | )); | ||
250 | } | 328 | } |
251 | 329 | ||
252 | debug!("clear for transaction proposal"); | 330 | debug!("clear for transaction proposal"); |
253 | 331 | ||
254 | let mut transactions = db.pending_transactions.write(); | 332 | let mut transactions = db.pending_transactions.write(); |
255 | transactions.insert(new_transaction.source.to_owned(), new_transaction); | 333 | transactions.insert(new_transaction.source.to_owned(), new_transaction); |
256 | Ok(StatusCode::CREATED) | 334 | Ok(warp::reply::with_status( |
335 | warp::reply::json(&GradeCoinResponse { | ||
336 | res: ResponseType::Success, | ||
337 | message: "Transaction accepted".to_owned(), | ||
338 | }), | ||
339 | StatusCode::CREATED, | ||
340 | )) | ||
257 | } | 341 | } |
258 | 342 | ||
259 | /// GET /block | 343 | /// GET /block |
@@ -273,15 +357,13 @@ pub async fn list_blocks(db: Db) -> Result<impl warp::Reply, Infallible> { | |||
273 | /// *[`jwt_token`]: The raw JWT token, "Bearer aaa.bbb.ccc" | 357 | /// *[`jwt_token`]: The raw JWT token, "Bearer aaa.bbb.ccc" |
274 | /// *[`user_pem`]: User Public Key, "BEGIN RSA" | 358 | /// *[`user_pem`]: User Public Key, "BEGIN RSA" |
275 | /// NOT async, might look into it if this becomes a bottleneck | 359 | /// NOT async, might look into it if this becomes a bottleneck |
276 | fn authorize_proposer( | 360 | fn authorize_proposer(jwt_token: String, user_pem: &String) -> Result<TokenData<Claims>, String> { |
277 | jwt_token: String, | ||
278 | user_pem: &String, | ||
279 | ) -> Result<TokenData<Claims>, jsonwebtoken::errors::Error> { | ||
280 | // Throw away the "Bearer " part | 361 | // Throw away the "Bearer " part |
281 | let raw_jwt = jwt_token.trim_start_matches(BEARER).to_owned(); | 362 | let raw_jwt = jwt_token.trim_start_matches(BEARER).to_owned(); |
282 | debug!("raw_jwt: {:?}", raw_jwt); | 363 | debug!("raw_jwt: {:?}", raw_jwt); |
283 | 364 | ||
284 | // Extract a jsonwebtoken compatible decoding_key from user's public key | 365 | // Extract a jsonwebtoken compatible decoding_key from user's public key |
366 | // TODO: just use this for reading users pem key <13-04-21, yigit> // | ||
285 | let decoding_key = match DecodingKey::from_rsa_pem(user_pem.as_bytes()) { | 367 | let decoding_key = match DecodingKey::from_rsa_pem(user_pem.as_bytes()) { |
286 | Ok(key) => key, | 368 | Ok(key) => key, |
287 | Err(j) => { | 369 | Err(j) => { |
@@ -289,7 +371,7 @@ fn authorize_proposer( | |||
289 | "user has invalid RSA key we should crash and burn here {:?}", | 371 | "user has invalid RSA key we should crash and burn here {:?}", |
290 | j | 372 | j |
291 | ); | 373 | ); |
292 | return Err(j); | 374 | return Err(String::from("This User's RSA key is invalid")); |
293 | } | 375 | } |
294 | }; | 376 | }; |
295 | 377 | ||
@@ -299,23 +381,20 @@ fn authorize_proposer( | |||
299 | Ok(decoded) => decoded, | 381 | Ok(decoded) => decoded, |
300 | Err(err) => match *err.kind() { | 382 | Err(err) => match *err.kind() { |
301 | ErrorKind::InvalidToken => { | 383 | ErrorKind::InvalidToken => { |
302 | // TODO: verbose error here <13-04-21, yigit> // | ||
303 | debug!("raw_jwt={:?} was malformed err={:?}", raw_jwt, err); | 384 | debug!("raw_jwt={:?} was malformed err={:?}", raw_jwt, err); |
304 | return Err(err); | 385 | return Err(String::from("Invalid Token")); |
305 | } | 386 | } |
306 | ErrorKind::InvalidRsaKey => { | 387 | ErrorKind::InvalidRsaKey => { |
307 | // TODO: verbose error here <13-04-21, yigit> // | 388 | debug!("The RSA key does not have a valid format, {:?}", err); |
308 | debug!("the RSA key does not have a valid format, {:?}", err); | 389 | return Err(String::from("The RSA key does not have a valid format")); |
309 | return Err(err); | ||
310 | } | 390 | } |
311 | ErrorKind::ExpiredSignature => { | 391 | ErrorKind::ExpiredSignature => { |
312 | // TODO: verbose error here <13-04-21, yigit> // | ||
313 | debug!("this token has expired {:?}", err); | 392 | debug!("this token has expired {:?}", err); |
314 | return Err(err); | 393 | return Err(String::from("This token has expired")); |
315 | } | 394 | } |
316 | _ => { | 395 | _ => { |
317 | warn!("AN UNSPECIFIED ERROR: {:?}", err); | 396 | warn!("AN UNSPECIFIED ERROR: {:?}", err); |
318 | return Err(err); | 397 | return Err(String::from("Unspecified error")); |
319 | } | 398 | } |
320 | }, | 399 | }, |
321 | }; | 400 | }; |
@@ -25,3 +25,4 @@ pub mod custom_filters; | |||
25 | pub mod handlers; | 25 | pub mod handlers; |
26 | pub mod routes; | 26 | pub mod routes; |
27 | pub mod schema; | 27 | pub mod schema; |
28 | pub mod error; | ||