li7y/src/frontend/auth.rs

85 lines
2.3 KiB
Rust

// SPDX-FileCopyrightText: 2024 Simon Bruder <simon@sbruder.de>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
use actix_identity::Identity;
use actix_web::{error, get, post, web, HttpMessage, HttpRequest, HttpResponse, Responder};
use maud::html;
use serde::Deserialize;
use super::templates;
pub fn config(cfg: &mut web::ServiceConfig) {
cfg.service(login_form).service(login).service(logout);
}
#[get("/login")]
async fn login_form(req: HttpRequest, user: Option<Identity>) -> HttpResponse {
if user.is_some() {
return web::Redirect::to("/")
.see_other()
.respond_to(&req)
.map_into_boxed_body();
}
templates::base(
templates::TemplateConfig {
path: "/login",
title: Some("Login"),
page_title: Some(Box::new("Login")),
user,
..Default::default()
},
html! {
form .w-25.mb-4 method="POST" {
div .mb-3 {
label .form-label for="password" { "Password" };
input .form-control type="password" id="password" name="password";
}
button .btn.btn-primary type="submit" { "Login" }
}
},
)
.respond_to(&req)
.map_into_boxed_body()
}
#[derive(Deserialize)]
struct LoginForm {
password: String,
}
#[derive(Deserialize)]
struct LoginQuery {
redirect_to: Option<String>,
}
#[post("/login")]
async fn login(
req: HttpRequest,
form: web::Form<LoginForm>,
query: web::Query<LoginQuery>,
) -> Result<impl Responder, error::Error> {
// Very basic authentication for now (only password, hardcoded in environment variable)
if form.password
== std::env::var("SUPERUSER_PASSWORD")
.map_err(|_| error::ErrorInternalServerError("login disabled (no password set)"))?
{
Identity::login(&req.extensions(), "superuser".into())
.map_err(error::ErrorInternalServerError)?;
Ok(
web::Redirect::to(query.into_inner().redirect_to.unwrap_or("/".to_string()))
.see_other(),
)
} else {
Ok(web::Redirect::to(req.uri().to_string()).see_other())
}
}
#[post("/logout")]
async fn logout(user: Identity) -> impl Responder {
user.logout();
web::Redirect::to("/login".to_owned()).see_other()
}