mirror of
https://github.com/n08i40k/schedule-parser-rusted.git
synced 2025-12-06 09:47:50 +03:00
Тесты JWT
Имплементация PartialEq для utils::jwt::VerifyError Замена устаревшего changeset_options на diesel Удалена проверка на ошибку создания токена, так как вероятность её появления близка к нулю
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
use diesel::prelude::*;
|
||||
use diesel::{AsExpression, FromSqlRow};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(diesel_derive_enum::DbEnum, Serialize, Debug, Clone, Copy, PartialEq)]
|
||||
@@ -14,7 +13,7 @@ pub enum UserRole {
|
||||
|
||||
#[derive(Identifiable, AsChangeset, Queryable, Selectable, Serialize)]
|
||||
#[diesel(table_name = crate::database::schema::users)]
|
||||
#[changeset_options(treat_none_as_null = "true")]
|
||||
#[diesel(treat_none_as_null = true)]
|
||||
pub struct User {
|
||||
pub id: String,
|
||||
pub username: String,
|
||||
|
||||
@@ -16,12 +16,11 @@ pub async fn sign_in(data: Json<SignInDto>, app_state: web::Data<AppState>) -> J
|
||||
let mut lock = app_state.connection();
|
||||
let conn = lock.deref_mut();
|
||||
|
||||
user.access_token =
|
||||
utility::jwt::encode(&user.id).expect("Failed to generate jet token");
|
||||
user.access_token = utility::jwt::encode(&user.id);
|
||||
|
||||
user.save_changes::<User>(conn)
|
||||
.expect("Failed to update user");
|
||||
|
||||
|
||||
SignInResult::ok(&user)
|
||||
}
|
||||
Ok(false) | Err(_) => SignInResult::err(IncorrectCredentials),
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
use chrono::DateTime;
|
||||
use chrono::Duration;
|
||||
use chrono::TimeZone;
|
||||
use chrono::Utc;
|
||||
use hmac::{Hmac, Mac};
|
||||
use jwt::{SignWithKey, Token, VerifyWithKey};
|
||||
use sha2::Sha256;
|
||||
use std::collections::BTreeMap;
|
||||
use std::env;
|
||||
use std::mem::discriminant;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
static JWT_SECRET: LazyLock<Hmac<Sha256>> = LazyLock::new(|| {
|
||||
@@ -16,9 +20,14 @@ static JWT_SECRET: LazyLock<Hmac<Sha256>> = LazyLock::new(|| {
|
||||
pub enum VerifyError {
|
||||
JwtError(jwt::Error),
|
||||
InvalidSignature,
|
||||
NoExpirationTag,
|
||||
InvalidToken,
|
||||
Expired,
|
||||
NoId,
|
||||
}
|
||||
|
||||
impl PartialEq for VerifyError {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
discriminant(self) == discriminant(other)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_and_decode(token: &String) -> Result<String, VerifyError> {
|
||||
@@ -27,31 +36,29 @@ pub fn verify_and_decode(token: &String) -> Result<String, VerifyError> {
|
||||
let result: Result<BTreeMap<String, String>, jwt::Error> = token.verify_with_key(jwt);
|
||||
|
||||
match result {
|
||||
Ok(claims) => match claims.get("exp") {
|
||||
None => Err(VerifyError::NoExpirationTag),
|
||||
Some(exp) => {
|
||||
let exp_date = DateTime::from_timestamp(exp.parse::<i64>().unwrap(), 0)
|
||||
.expect("Failed to parse expiration time");
|
||||
Ok(claims) => {
|
||||
let exp = claims.get("exp").unwrap();
|
||||
let exp_date = DateTime::from_timestamp(exp.parse::<i64>().unwrap(), 0)
|
||||
.expect("Failed to parse expiration time");
|
||||
|
||||
if Utc::now() > exp_date {
|
||||
return Err(VerifyError::Expired);
|
||||
}
|
||||
|
||||
match claims.get("id").cloned() {
|
||||
None => Err(VerifyError::NoId),
|
||||
Some(id) => Ok(id),
|
||||
}
|
||||
if Utc::now() > exp_date {
|
||||
return Err(VerifyError::Expired);
|
||||
}
|
||||
},
|
||||
|
||||
Ok(claims.get("id").cloned().unwrap())
|
||||
}
|
||||
Err(err) => Err(match err {
|
||||
jwt::Error::InvalidSignature => VerifyError::InvalidSignature,
|
||||
jwt::Error::Format | jwt::Error::Base64(_) | jwt::Error::NoClaimsComponent => {
|
||||
VerifyError::InvalidToken
|
||||
}
|
||||
|
||||
_ => VerifyError::JwtError(err),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode(id: &String) -> Result<String, jwt::Error> {
|
||||
pub fn encode(id: &String) -> String {
|
||||
let header = jwt::Header {
|
||||
type_: Some(jwt::header::HeaderType::JsonWebToken),
|
||||
..Default::default()
|
||||
@@ -69,8 +76,65 @@ pub fn encode(id: &String) -> Result<String, jwt::Error> {
|
||||
claims.insert("iat", iat_str.as_str());
|
||||
claims.insert("exp", exp_str.as_str());
|
||||
|
||||
match Token::new(header, claims).sign_with_key(&*JWT_SECRET) {
|
||||
Ok(token) => Ok(token.as_str().to_string()),
|
||||
Err(err) => Err(err),
|
||||
Token::new(header, claims)
|
||||
.sign_with_key(&*JWT_SECRET)
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use dotenvy::dotenv;
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
dotenv().unwrap();
|
||||
|
||||
assert_eq!(encode(&"test".to_string()).is_empty(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_invalid_token() {
|
||||
dotenv().unwrap();
|
||||
|
||||
let token = "".to_string();
|
||||
let result = verify_and_decode(&token);
|
||||
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.err().unwrap(), VerifyError::InvalidToken);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_invalid_signature() {
|
||||
dotenv().unwrap();
|
||||
|
||||
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxODY4ODEyOTI4IiwiaWF0IjoiMTc0MjY2ODkyOCIsImlkIjoiNjdkY2M5YTk1MDdiMDAwMDc3Mjc0NGEyIn0.DQYFYF-3DoJgCLOVdAWa47nUaCJAh16DXj-ChNSSmWz".to_string();
|
||||
let result = verify_and_decode(&token);
|
||||
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.err().unwrap(), VerifyError::InvalidToken);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_expired() {
|
||||
dotenv().unwrap();
|
||||
|
||||
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxNjE2NTI2Mzc2IiwiaWF0IjoiMTQ5MDM4MjM3NiIsImlkIjoiNjdkY2M5YTk1MDdiMDAwMDc3Mjc0NGEyIn0.Qc2LbMJTvl2hWzDM2XyQv4m9lIqR84COAESQAieUxz8".to_string();
|
||||
let result = verify_and_decode(&token);
|
||||
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.err().unwrap(), VerifyError::Expired);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_ok() {
|
||||
dotenv().unwrap();
|
||||
|
||||
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxODY4ODEyOTI4IiwiaWF0IjoiMTc0MjY2ODkyOCIsImlkIjoiNjdkY2M5YTk1MDdiMDAwMDc3Mjc0NGEyIn0.DQYFYF-3DoJgCLOVdAWa47nUaCJAh16DXj-ChNSSmWw".to_string();
|
||||
let result = verify_and_decode(&token);
|
||||
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user