Files
ImageApi/src/auth.rs
Cameron Cordes 7863990c68 Run clippy
2023-03-25 20:59:32 -04:00

119 lines
3.3 KiB
Rust

use actix_web::Responder;
use actix_web::{
web::{self, Json},
HttpResponse,
};
use chrono::{Duration, Utc};
use jsonwebtoken::{encode, EncodingKey, Header};
use log::{error, info};
use std::sync::Mutex;
use crate::{
data::{secret_key, Claims, CreateAccountRequest, LoginRequest, Token},
database::UserDao,
};
#[allow(dead_code)]
async fn register<D: UserDao>(
user: Json<CreateAccountRequest>,
user_dao: web::Data<Mutex<D>>,
) -> impl Responder {
if !user.username.is_empty() && user.password.len() > 5 && user.password == user.confirmation {
let mut dao = user_dao.lock().expect("Unable to get UserDao");
if dao.user_exists(&user.username) {
HttpResponse::BadRequest()
} else if let Some(_user) = dao.create_user(&user.username, &user.password) {
HttpResponse::Ok()
} else {
HttpResponse::InternalServerError()
}
} else {
HttpResponse::BadRequest()
}
}
pub async fn login<D: UserDao>(
creds: Json<LoginRequest>,
user_dao: web::Data<Mutex<D>>,
) -> HttpResponse {
info!("Logging in: {}", creds.username);
let mut user_dao = user_dao.lock().expect("Unable to get UserDao");
if let Some(user) = user_dao.get_user(&creds.username, &creds.password) {
let claims = Claims {
sub: user.id.to_string(),
exp: (Utc::now() + Duration::days(5)).timestamp(),
};
let token = encode(
&Header::default(),
&claims,
&EncodingKey::from_secret(secret_key().as_bytes()),
)
.unwrap();
HttpResponse::Ok().json(Token { token: &token })
} else {
error!(
"User not found during login or incorrect password: '{}'",
creds.username
);
HttpResponse::NotFound().finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::testhelpers::{BodyReader, TestUserDao};
#[actix_rt::test]
async fn test_login_reports_200_when_user_exists() {
let mut dao = TestUserDao::new();
dao.create_user("user", "pass");
let j = Json(LoginRequest {
username: "user".to_string(),
password: "pass".to_string(),
});
let response = login::<TestUserDao>(j, web::Data::new(Mutex::new(dao))).await;
assert_eq!(response.status(), 200);
}
#[actix_rt::test]
async fn test_login_returns_token_on_success() {
let mut dao = TestUserDao::new();
dao.create_user("user", "password");
let j = Json(LoginRequest {
username: "user".to_string(),
password: "password".to_string(),
});
let response = login::<TestUserDao>(j, web::Data::new(Mutex::new(dao))).await;
assert_eq!(response.status(), 200);
let response_text: String = response.read_to_str();
assert!(response_text.contains("\"token\""));
}
#[actix_rt::test]
async fn test_login_reports_404_when_user_does_not_exist() {
let mut dao = TestUserDao::new();
dao.create_user("user", "password");
let j = Json(LoginRequest {
username: "doesnotexist".to_string(),
password: "password".to_string(),
});
let response = login::<TestUserDao>(j, web::Data::new(Mutex::new(dao))).await;
assert_eq!(response.status(), 404);
}
}