diff --git a/.gitignore b/.gitignore index 6b4b2c7..f24efde 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ Rocket.toml frontend/node_modules/* /static/ /data-ergo/ +usage.txt diff --git a/Rocket.toml b/Rocket.toml index 6f5e652..b20da06 100644 --- a/Rocket.toml +++ b/Rocket.toml @@ -3,3 +3,4 @@ secret_key = "/NtVGizglEoyoxBLzsRDWTy4oAG1qDw4J4O+CWJSv+fypD7W9sam8hUY4j90EZsbZk rss_key = "rss-key-for-ci" limits = { file = "10 MiB", data-form = "10 MiB"} smtp_pw = "8kIjlLH79Ky6D3jQ" +usage_log_path = "./usage.txt" diff --git a/src/tera/mod.rs b/src/tera/mod.rs index 9836226..3b12831 100644 --- a/src/tera/mod.rs +++ b/src/tera/mod.rs @@ -1,6 +1,9 @@ +use std::{fs::OpenOptions, io::Write}; + +use chrono::Local; use rocket::{ catch, catchers, - fairing::AdHoc, + fairing::{AdHoc, Fairing, Info, Kind}, form::Form, fs::FileServer, get, @@ -10,7 +13,7 @@ use rocket::{ response::{Flash, Redirect}, routes, time::{Duration, OffsetDateTime}, - Build, FromForm, Request, Rocket, State, + Build, Data, FromForm, Request, Rocket, State, }; use rocket_dyn_templates::Template; use serde::Deserialize; @@ -100,11 +103,61 @@ fn forbidden_error() -> Flash { 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.") } +struct Usage { + data: Vec, +} + +#[rocket::async_trait] +impl Fairing for Usage { + fn info(&self) -> Info { + Info { + name: "Usage stats of website", + kind: Kind::Request, + } + } + + // Increment the counter for `GET` and `POST` requests. + async fn on_request(&self, req: &mut Request<'_>, _: &mut Data<'_>) { + let timestamp = Local::now().format("%Y-%m-%dT%H:%M:%S"); + + let user = match req.cookies().get_private("loggedin_user") { + Some(user_id) => match user_id.value().parse::() { + Ok(user_id) => { + let db = req.rocket().state::().unwrap(); + if let Some(user) = User::find_by_id(db, user_id).await { + user.name + } else { + format!("USER ID {user_id} NOT EXISTS") + } + } + Err(_) => format!("INVALID USER ID ({user_id})"), + }, + None => "NOT LOGGED IN".to_string(), + }; + + let uri = req.uri().to_string(); + + if !uri.ends_with(".css") && !uri.ends_with(".js") { + let config = req.rocket().state::().unwrap(); + let mut file = OpenOptions::new() + .write(true) + .append(true) + .open(config.usage_log_path.clone()) + .unwrap(); + + if let Err(e) = writeln!(file, "{timestamp};{user};{uri}") { + eprintln!("Couldn't write to file: {}", e); + } + } + } +} + #[derive(Deserialize)] #[serde(crate = "rocket::serde")] pub struct Config { rss_key: String, smtp_pw: String, + usage_log_path: String, } pub fn config(rocket: Rocket) -> Rocket { @@ -127,6 +180,7 @@ pub fn config(rocket: Rocket) -> Rocket { .register("/", catchers![unauthorized_error, forbidden_error]) .attach(Template::fairing()) .attach(AdHoc::config::()) + .attach(Usage { data: Vec::new() }) } #[cfg(test)]