Merge pull request 'log usage' (#380) from usage-stats into main
Some checks failed
CI/CD Pipeline / deploy-staging (push) Blocked by required conditions
CI/CD Pipeline / deploy-main (push) Blocked by required conditions
CI/CD Pipeline / test (push) Has been cancelled

Reviewed-on: #380
This commit is contained in:
philipp 2024-04-16 08:54:25 +02:00
commit e84547c8ca
3 changed files with 58 additions and 2 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ Rocket.toml
frontend/node_modules/*
/static/
/data-ergo/
usage.txt

View File

@ -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"

View File

@ -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<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.")
}
struct Usage {
data: Vec<String>,
}
#[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::<i32>() {
Ok(user_id) => {
let db = req.rocket().state::<SqlitePool>().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::<Config>().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<Build>) -> Rocket<Build> {
@ -127,6 +180,7 @@ pub fn config(rocket: Rocket<Build>) -> Rocket<Build> {
.register("/", catchers![unauthorized_error, forbidden_error])
.attach(Template::fairing())
.attach(AdHoc::config::<Config>())
.attach(Usage { data: Vec::new() })
}
#[cfg(test)]