2018-12-09 15:55:36 +00:00
|
|
|
use bcrypt::{hash, DEFAULT_COST};
|
|
|
|
use chrono::{Duration, Local};
|
2019-03-29 13:43:03 -07:00
|
|
|
use jsonwebtoken::{decode, encode, Header, Validation};
|
|
|
|
|
|
|
|
use crate::errors::ServiceError;
|
|
|
|
use crate::models::SlimUser;
|
2018-12-09 15:55:36 +00:00
|
|
|
|
|
|
|
pub fn hash_password(plain: &str) -> Result<String, ServiceError> {
|
|
|
|
// get the hashing cost from the env variable or use default
|
2019-03-29 13:43:03 -07:00
|
|
|
let hashing_cost: u32 = match std::env::var("HASH_ROUNDS") {
|
2018-12-09 15:55:36 +00:00
|
|
|
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<Claims> for SlimUser {
|
|
|
|
fn from(claims: Claims) -> Self {
|
|
|
|
SlimUser {
|
|
|
|
email: claims.email,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn create_token(data: &SlimUser) -> Result<String, ServiceError> {
|
|
|
|
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<SlimUser, ServiceError> {
|
|
|
|
decode::<Claims>(token, get_secret().as_ref(), &Validation::default())
|
|
|
|
.map(|data| Ok(data.claims.into()))
|
|
|
|
.map_err(|_err| ServiceError::Unauthorized)?
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_secret() -> String {
|
2019-03-29 13:43:03 -07:00
|
|
|
std::env::var("JWT_SECRET").unwrap_or_else(|_| "my secret".into())
|
2018-12-09 15:55:36 +00:00
|
|
|
}
|