169 lines
4.6 KiB
Rust
169 lines
4.6 KiB
Rust
use rocket::{
|
|
catch, catchers,
|
|
fairing::AdHoc,
|
|
form::Form,
|
|
fs::FileServer,
|
|
get,
|
|
http::Cookie,
|
|
post,
|
|
request::FlashMessage,
|
|
response::{Flash, Redirect},
|
|
routes,
|
|
time::{Duration, OffsetDateTime},
|
|
Build, FromForm, Request, Rocket, State,
|
|
};
|
|
use rocket_dyn_templates::Template;
|
|
use serde::Deserialize;
|
|
use sqlx::SqlitePool;
|
|
use tera::Context;
|
|
|
|
use crate::model::user::{User, UserWithRoles};
|
|
|
|
pub(crate) mod admin;
|
|
mod auth;
|
|
mod boatdamage;
|
|
mod cox;
|
|
mod ergo;
|
|
mod log;
|
|
mod misc;
|
|
mod planned;
|
|
mod stat;
|
|
|
|
#[derive(FromForm, Debug)]
|
|
struct LoginForm<'r> {
|
|
name: &'r str,
|
|
password: &'r str,
|
|
}
|
|
|
|
#[get("/")]
|
|
async fn index(db: &State<SqlitePool>, user: User, flash: Option<FlashMessage<'_>>) -> Template {
|
|
let mut context = Context::new();
|
|
if let Some(msg) = flash {
|
|
context.insert("flash", &msg.into_inner());
|
|
}
|
|
|
|
context.insert("loggedin_user", &UserWithRoles::from_user(user, db).await);
|
|
Template::render("index", context.into_json())
|
|
}
|
|
|
|
#[post("/", data = "<login>")]
|
|
async fn wikiauth(db: &State<SqlitePool>, login: Form<LoginForm<'_>>) -> String {
|
|
match User::login(db, login.name, login.password).await {
|
|
Ok(_) => "SUCC".into(),
|
|
Err(_) => "FAIL".into(),
|
|
}
|
|
}
|
|
|
|
#[catch(401)] //Unauthorized
|
|
fn unauthorized_error(req: &Request) -> Redirect {
|
|
// Save the URL the user tried to access, to be able to go there once logged in
|
|
let mut redirect_cookie = Cookie::new("redirect_url", format!("{}", req.uri()));
|
|
println!("{}", req.uri());
|
|
redirect_cookie.set_expires(OffsetDateTime::now_utc() + Duration::hours(1));
|
|
req.cookies().add_private(redirect_cookie);
|
|
|
|
Redirect::to("/auth")
|
|
}
|
|
|
|
#[catch(403)] //forbidden
|
|
fn forbidden_error() -> Flash<Redirect> {
|
|
Flash::error(Redirect::to("/"), "Keine Berechtigung für diese Aktion. Wenn du der Meinung bist, dass du das machen darfst, melde dich bitte bei it@rudernlinz.at.")
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
#[serde(crate = "rocket::serde")]
|
|
pub struct Config {
|
|
rss_key: String,
|
|
smtp_pw: String,
|
|
}
|
|
|
|
pub fn config(rocket: Rocket<Build>) -> Rocket<Build> {
|
|
rocket
|
|
.mount("/", routes![index])
|
|
.mount("/auth", auth::routes())
|
|
.mount("/wikiauth", routes![wikiauth])
|
|
.mount("/log", log::routes())
|
|
.mount("/planned", planned::routes())
|
|
.mount("/ergo", ergo::routes())
|
|
.mount("/stat", stat::routes())
|
|
.mount("/boatdamage", boatdamage::routes())
|
|
.mount("/cox", cox::routes())
|
|
.mount("/admin", admin::routes())
|
|
.mount("/", misc::routes())
|
|
.mount("/public", FileServer::from("static/"))
|
|
.register("/", catchers![unauthorized_error, forbidden_error])
|
|
.attach(Template::fairing())
|
|
.attach(AdHoc::config::<Config>())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use rocket::{
|
|
http::{ContentType, Status},
|
|
local::asynchronous::Client,
|
|
};
|
|
use sqlx::SqlitePool;
|
|
|
|
use crate::testdb;
|
|
|
|
#[sqlx::test]
|
|
fn test_index() {
|
|
let db = testdb!();
|
|
|
|
let rocket = rocket::build().manage(db.clone());
|
|
let rocket = crate::tera::config(rocket);
|
|
|
|
let client = Client::tracked(rocket).await.unwrap();
|
|
let login = client
|
|
.post("/auth")
|
|
.header(ContentType::Form) // Set the content type to form
|
|
.body("name=cox&password=cox"); // Add the form data to the request body;
|
|
login.dispatch().await;
|
|
|
|
let req = client.get("/");
|
|
let response = req.dispatch().await;
|
|
|
|
assert_eq!(response.status(), Status::Ok);
|
|
|
|
assert!(response
|
|
.into_string()
|
|
.await
|
|
.unwrap()
|
|
.contains("Ruderassistent"));
|
|
}
|
|
|
|
#[sqlx::test]
|
|
fn test_without_login() {
|
|
let db = testdb!();
|
|
|
|
let rocket = rocket::build().manage(db.clone());
|
|
let rocket = crate::tera::config(rocket);
|
|
|
|
let client = Client::tracked(rocket).await.unwrap();
|
|
|
|
let req = client.get("/");
|
|
let response = req.dispatch().await;
|
|
|
|
assert_eq!(response.status(), Status::SeeOther);
|
|
assert_eq!(response.headers().get("Location").next(), Some("/auth"));
|
|
}
|
|
|
|
#[sqlx::test]
|
|
fn test_public() {
|
|
let db = testdb!();
|
|
|
|
let rocket = rocket::build().manage(db.clone());
|
|
let rocket = crate::tera::config(rocket);
|
|
|
|
let client = Client::tracked(rocket).await.unwrap();
|
|
|
|
let req = client.get("/public/main.css");
|
|
let response = req.dispatch().await;
|
|
assert_eq!(response.status(), Status::Ok);
|
|
|
|
let req = client.get("/public/main.js");
|
|
let response = req.dispatch().await;
|
|
assert_eq!(response.status(), Status::Ok);
|
|
}
|
|
}
|