Files
rss-reader/src/auth/processes.rs
T
2026-06-12 19:22:07 +02:00

110 lines
3.5 KiB
Rust
Executable File

use super::jwt;
use crate::database::establish_connection;
use crate::models::user::rss_user::User;
use crate::schema::users;
use actix_web::dev::ServiceRequest;
use diesel::prelude::*;
/// Decodes the token and confirms it hasn't been revoked, i.e. its `token_version`
/// still matches the one stored on the user (bumped on logout / password change).
pub fn check_token(token: String) -> Result<i32, &'static str> {
let decoded = jwt::JwtToken::decode(token)?;
let mut connection = establish_connection();
let user: User = users::table
.find(decoded.user_id)
.first(&mut connection)
.map_err(|_| "could not decode token")?;
if user.token_version != decoded.token_version {
return Err("token has been revoked");
}
Ok(decoded.user_id)
}
pub fn extract_header_token(request: &ServiceRequest) -> Result<String, &'static str> {
match request.headers().get("user-token") {
Some(token) => match token.to_str() {
Ok(processed_token) => Ok(String::from(processed_token)),
Err(_) => Err("there was an error processing token"),
},
None => Err("there is no token"),
}
}
#[cfg(test)]
mod processes_test {
use actix_web::test::TestRequest;
use diesel::prelude::*;
use crate::auth::jwt::JwtToken;
use crate::database::establish_connection;
use crate::test_helpers::{delete_user, insert_user};
use super::check_token;
#[test]
fn check_correct_token() {
let mut connection = establish_connection();
let user = insert_user(&mut connection, "secret");
let token: String = JwtToken::encode(user.id, user.token_version);
let result = check_token(token);
assert_eq!(Ok(user.id), result);
delete_user(&mut connection, user.id);
}
#[test]
fn revoked_token_is_rejected() {
let mut connection = establish_connection();
let user = insert_user(&mut connection, "secret");
// Token signed with the user's current version, then the version is bumped
// (as logout would do), which must invalidate the previously issued token.
let token: String = JwtToken::encode(user.id, user.token_version);
diesel::update(crate::schema::users::table.find(user.id))
.set(crate::schema::users::token_version.eq(user.token_version + 1))
.execute(&mut connection)
.unwrap();
assert_eq!(Err("token has been revoked"), check_token(token));
delete_user(&mut connection, user.id);
}
#[test]
fn incorrect_check_token() {
let token: String = String::from("test");
assert_eq!(Err("could not decode token"), check_token(token));
}
#[test]
fn successful_extract_header_token() {
let request = TestRequest::default()
.insert_header(("user-token", "token"))
.to_srv_request();
match super::extract_header_token(&request) {
Ok(processed_password) => assert_eq!("token", processed_password),
_ => panic!("failed extract_header_token"),
}
}
#[test]
fn failed_extract_header_token() {
let request = TestRequest::default()
.insert_header(("wrong", "bla"))
.to_srv_request();
match super::extract_header_token(&request) {
Err(processed_password) => assert_eq!("there is no token", processed_password),
_ => panic!("Extract header token should fail when not provided."),
}
}
}