Ниже приведен инструмент создания токена, который я создал с помощью jsonwebtoken. Я хочу как-то принудительно применить ожидаемый тип токена, чтобы, если я передам строку токена и сообщу ей ожидаемый набор утверждений, он не вернет успешный результат.
Ниже приведены тестовые примеры с комментариями о том, где я думаюэтот сервис должен потерпеть неудачу, и комментарий в коде, где я думаю, что утверждение должно иметь место.
Как я могу применить эти типы утверждений, чтобы быть уверенным, что я получаю желаемый тип токена?
use jwt;
use jwt::{ Header, Validation };
use std::convert::AsRef;
use serde::de::DeserializeOwned;
use serde::Serialize;
#[derive(Debug, Serialize, Deserialize, PartialEq)]
enum TokenType {
User,
Reg,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct RegisterClaims {
typ:TokenType,
org_name:String,
name:String,
email:String,
exp: usize,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct UserClaims {
typ:TokenType,
usr_id:String,
sub:String,
exp: usize,
}
#[derive(Debug)]
pub struct InvalidToken {
cause: String,
}
pub struct TokenFactory {
secret:String,
}
impl TokenFactory {
pub fn new(secret:String) -> TokenFactory {
TokenFactory {
secret
}
}
pub fn validate<T: DeserializeOwned>(&self, raw_token:String) -> Result<T, InvalidToken> {
match jwt::decode::<T>(&raw_token, self.secret.as_ref(), &Validation::default()) {
Ok(tokendata) => {
/*
some how assert the type of T to match and return an Err if not matched
What
*/
Ok(tokendata.claims)
},
Err(err) => {
// todo: in the future check error kind and give better errors
Err(InvalidToken{
cause: err.to_string()
})
}
}
}
pub fn mint_token<T: Serialize>(&self, claims:&T) -> String {
jwt::encode(&Header::default(), claims, self.secret.as_ref()).unwrap()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::util;
use std::borrow::Borrow;
#[test]
fn test_valid() {
let usr = UserClaims {
typ: TokenType::User,
sub:"foobar@gmail.com".to_string(),
exp:util::current_time_secs()+1,
usr_id:"usr-1234".to_string(),
};
let tf = TokenFactory::new("my_sceret".to_string());
let token = tf.mint_token(usr.borrow());
let usr_claims: UserClaims = tf.validate(token).unwrap();
assert_eq!(usr.sub, usr_claims.sub);
}
#[test]
fn test_mixed() {
let reg = RegisterClaims {
typ:TokenType::Reg,
org_name:"foo".to_string(),
name:"bar".to_string(),
email:"foobar@inc".to_string(),
exp:util::current_time_secs()+1,
};
let tf = TokenFactory::new("my_sceret".to_string());
let token = tf.mint_token(reg.borrow());
let usr_claims: UserClaims = tf.validate(token).unwrap(); // want it to fail here
assert_eq!(reg, usr_claims); // fails here
}
}