use bcrypt::{hash, DEFAULT_COST}; use chrono::{Duration, Local}; use errors::ServiceError; use jwt::{decode, encode, Header, Validation}; use models::SlimUser; use std::convert::From; use std::env; pub fn hash_password(plain: &str) -> Result { // get the hashing cost from the env variable or use default let hashing_cost: u32 = match env::var("HASH_ROUNDS") { Ok(cost) => cost.parse().unwrap_or(DEFAULT_COST), _ => DEFAULT_COST, }; println!("{}", &hashing_cost); hash(plain, hashing_cost).map_err(|_| ServiceError::InternalServerError) } #[derive(Debug, Serialize, Deserialize)] struct Claims { // issuer iss: String, // subject sub: String, //issued at iat: i64, // expiry exp: i64, // user email email: String, } // struct to get converted to token and back impl Claims { fn with_email(email: &str) -> Self { Claims { iss: "localhost".into(), sub: "auth".into(), email: email.to_owned(), iat: Local::now().timestamp(), exp: (Local::now() + Duration::hours(24)).timestamp(), } } } impl From for SlimUser { fn from(claims: Claims) -> Self { SlimUser { email: claims.email, } } } pub fn create_token(data: &SlimUser) -> Result { let claims = Claims::with_email(data.email.as_str()); encode(&Header::default(), &claims, get_secret().as_ref()) .map_err(|_err| ServiceError::InternalServerError) } pub fn decode_token(token: &str) -> Result { decode::(token, get_secret().as_ref(), &Validation::default()) .map(|data| Ok(data.claims.into())) .map_err(|_err| ServiceError::Unauthorized)? } fn get_secret() -> String { env::var("JWT_SECRET").unwrap_or_else(|_| "my secret".into()) }