Skip to main content

actix_web_admin/handlers/
auth.rs

1use actix_session::Session;
2use actix_web::{web, HttpResponse, Responder};
3use serde::Deserialize;
4use tera::{Context, Tera};
5use crate::resource::{AdminTitle, AdminPrefix};
6
7#[derive(Clone)]
8pub struct SimpleAuth {
9    pub username: String,
10    pub password: String,
11}
12
13impl SimpleAuth {
14    pub fn check(&self, username: &str, password: &str) -> bool {
15        self.username == username && self.password == password
16    }
17}
18
19#[derive(Deserialize)]
20pub struct LoginRequest {
21    pub username: String,
22    pub password: String,
23}
24
25pub async fn login_page(tmpl: web::Data<Tera>, title: web::Data<AdminTitle>, prefix: web::Data<AdminPrefix>) -> impl Responder {
26    let mut ctx = Context::new();
27    ctx.insert("title", &title.0);
28    ctx.insert("page_title", "Login");
29    ctx.insert("path_dashboard", &format!("/{}/", prefix.0));
30    ctx.insert("path_logout", &format!("/{}/logout", prefix.0));
31    ctx.insert("resources", &Vec::<crate::resource::ResourceInfo>::new());
32
33    match tmpl.render("login.html", &ctx) {
34        Ok(rendered) => HttpResponse::Ok().content_type("text/html").body(rendered),
35        Err(_) => HttpResponse::InternalServerError().finish(),
36    }
37}
38
39pub async fn login(
40    session: Session,
41    auth: web::Data<SimpleAuth>,
42    form: web::Form<LoginRequest>,
43    tmpl: web::Data<Tera>,
44    title: web::Data<AdminTitle>,
45    prefix: web::Data<AdminPrefix>,
46) -> impl Responder {
47    if auth.check(&form.username, &form.password) {
48        // Usamos un match para evitar el panic si el store de sesión falla
49        if let Err(_) = session.insert("admin_user", &form.username) {
50            return HttpResponse::InternalServerError().body("Session error");
51        }
52        return HttpResponse::Found()
53            .insert_header(("Location", "/admin/"))
54            .finish();
55    }
56
57    let mut ctx = Context::new();
58    ctx.insert("title", &title.0);
59    ctx.insert("page_title", "Login");
60    ctx.insert("path_dashboard", &format!("/{}/", prefix.0));
61    ctx.insert("path_logout", &format!("/{}/logout", prefix.0));
62    ctx.insert("resources", &Vec::<crate::resource::ResourceInfo>::new());
63    ctx.insert("error", "Invalid username or password");
64
65    match tmpl.render("login.html", &ctx) {
66        Ok(rendered) => HttpResponse::Unauthorized().content_type("text/html").body(rendered),
67        Err(_) => HttpResponse::InternalServerError().finish(),
68    }
69}
70
71pub async fn logout(session: Session, prefix: web::Data<AdminPrefix>) -> impl Responder {
72    session.purge();
73    HttpResponse::Found()
74        .insert_header(("Location", "/admin/login"))
75        .finish()
76}