forked from Roflin/gamenight
61 lines
1.8 KiB
Rust
61 lines
1.8 KiB
Rust
use std::future::{Ready, ready};
|
|
|
|
use actix_web::{FromRequest, http, HttpRequest, dev::Payload, web::Data};
|
|
use chrono::Utc;
|
|
use jsonwebtoken::{encode, Header, EncodingKey, decode, DecodingKey, Validation};
|
|
use serde::{Serialize, Deserialize};
|
|
use uuid::Uuid;
|
|
|
|
use crate::{schema::user::{User, get_user}, DbPool};
|
|
|
|
use super::error::ApiError;
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct Claims {
|
|
exp: i64,
|
|
uid: Uuid
|
|
}
|
|
|
|
fn get_claims(req: &HttpRequest) -> Result<Claims, ApiError> {
|
|
let token = req.headers()
|
|
.get(http::header::AUTHORIZATION)
|
|
.map(|h| h.to_str().unwrap().split_at(7).1.to_string());
|
|
|
|
let token = token.ok_or(ApiError{
|
|
status: 400,
|
|
message: "JWT-token was not specified in the Authorization header as Bearer: token".to_string()
|
|
})?;
|
|
|
|
let secret = "secret";
|
|
Ok(decode::<Claims>(token.as_str(), &DecodingKey::from_secret(secret.as_bytes()), &Validation::default())?.claims)
|
|
}
|
|
|
|
pub fn get_token(user: &User) -> Result<String, ApiError> {
|
|
let claims = Claims {
|
|
exp: Utc::now().timestamp() + chrono::Duration::days(7).num_seconds(),
|
|
uid: user.id,
|
|
};
|
|
|
|
let secret = "secret";
|
|
Ok(encode(
|
|
&Header::default(),
|
|
&claims,
|
|
&EncodingKey::from_secret(secret.as_bytes()))?)
|
|
}
|
|
|
|
impl FromRequest for User {
|
|
type Error = ApiError;
|
|
type Future = Ready<Result<Self, Self::Error>>;
|
|
|
|
fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future {
|
|
ready(
|
|
(|| -> Result<User, ApiError>{
|
|
let pool = req.app_data::<Data<DbPool>>().expect("No database configured");
|
|
let mut conn = pool.get().expect("couldn't get db connection from pool");
|
|
let uid = get_claims(req)?.uid;
|
|
|
|
Ok(get_user(&mut conn, uid)?)
|
|
})()
|
|
)
|
|
}
|
|
} |