changeset 28:25439f8c9114

Implement time window for index page
author Lewin Bormann <lbo@spheniscida.de>
date Thu, 14 Jul 2022 22:12:10 -0700
parents 792eb8ac3d93
children 8ad244c1b061
files Cargo.toml src/logsdb.rs src/main.rs
diffstat 3 files changed, 52 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/Cargo.toml	Thu Jul 14 20:35:35 2022 -0700
+++ b/Cargo.toml	Thu Jul 14 22:12:10 2022 -0700
@@ -10,12 +10,12 @@
 either = "1.7.0"
 env_logger = "0.9.0"
 log = "0.4.17"
-rocket = { version = "0.5.0-rc.2", features = ["secrets", "json",] }
+rocket = { version = "0.5.0-rc.2", features = ["secrets", "json"] }
 sqlx = { version = "0.5", features = ["macros"] }
 rocket_db_pools = { version = "0.1.0-rc.2", features = [ "sqlx_macros"] }
 rocket_dyn_templates = { version = "0.1.0-rc.2", features = ["handlebars"] }
 sha256 = "1.0.3"
-time = "0.3.11"
+time = { version = "0.3.11", features = ["serde", "serde-well-known"] }
 tokio = { version = "1.19.2", features = ["fs"] }
 
 [features]
--- a/src/logsdb.rs	Thu Jul 14 20:35:35 2022 -0700
+++ b/src/logsdb.rs	Thu Jul 14 22:12:10 2022 -0700
@@ -95,6 +95,7 @@
         domainpattern: Option<S>,
     ) -> Result<(Vec<String>, Vec<u32>, Vec<u32>), Error> {
         let domain = domainpattern.as_ref().map(AsRef::as_ref).unwrap_or("%");
+        let tz_offset = tz_offset.unwrap_or(0);
         let mut results = sqlx::query(
             r#"
 SELECT DATE(atime + ?, 'unixepoch') AS rqdate, COUNT(requestlog.id) AS rqcount, sesscount
@@ -103,14 +104,16 @@
     SELECT DATE(start + ?, 'unixepoch') AS sessdate, COUNT(*) AS sesscount
     FROM sessions WHERE sessions.domain LIKE ? GROUP BY sessdate)
 AS sc ON (rqdate = sessdate)
-WHERE atime > ? AND atime < ? AND requestlog.domain LIKE ?
+WHERE atime+? > ? AND atime+? < ? AND requestlog.domain LIKE ?
 GROUP BY rqdate
 ORDER BY rqdate ASC;"#,
         )
-        .bind(tz_offset.unwrap_or(0))
-        .bind(tz_offset.unwrap_or(0))
+        .bind(tz_offset)
+        .bind(tz_offset)
         .bind(domain)
+        .bind(tz_offset)
         .bind(from.unix_timestamp())
+        .bind(tz_offset)
         .bind(to.unix_timestamp())
         .bind(domain)
         .fetch(&mut *self.0);
--- a/src/main.rs	Thu Jul 14 20:35:35 2022 -0700
+++ b/src/main.rs	Thu Jul 14 22:12:10 2022 -0700
@@ -1,9 +1,9 @@
 mod configdb;
 mod db;
+mod fromparam;
+mod guards;
 mod logsdb;
 
-mod guards;
-
 use crate::configdb::{ConfigDB, ConfigDBSession};
 use crate::guards::{HeadersGuard, LoggedInGuard, USER_ID_COOKIE_KEY};
 use crate::logsdb::{LogsDB, LogsDBSession};
@@ -11,12 +11,12 @@
 use anyhow::{self, Context, Error};
 use either::Either;
 use log::{debug, error, info, warn, Level};
-use time::{Duration, OffsetDateTime};
+use time::{Date, Duration, OffsetDateTime};
 
 use rocket::form::Form;
 use rocket::fs::{relative, FileServer, NamedFile};
 use rocket::futures::StreamExt;
-use rocket::http::{Cookie, CookieJar, HeaderMap, Status};
+use rocket::http::{Cookie, CookieJar, HeaderMap, RawStr, Status};
 use rocket::request::{self, FlashMessage, FromRequest, Outcome, Request};
 use rocket::response::{self, Flash, Redirect, Responder};
 use rocket::serde::json::{json, Value};
@@ -30,8 +30,7 @@
 
 use std::collections::HashMap;
 use std::net::IpAddr;
-use std::path::{Path, PathBuf};
-use std::time::Instant;
+use std::path::Path;
 
 #[derive(Responder)]
 enum LoginResponse {
@@ -149,13 +148,30 @@
     inner
 }
 
-#[rocket::get("/?<domain>", rank = 1)]
+fn construct_index_querystring(
+    domain: Option<&str>,
+    from: OffsetDateTime,
+    duration: Duration,
+) -> String {
+    format!(
+        "?domain={}&from={}&duration={}",
+        domain.unwrap_or(""),
+        from.format(&time::format_description::well_known::Iso8601::DEFAULT)
+            .unwrap_or("".to_string()),
+        duration.whole_days()
+    )
+}
+
+/// Main analytics page for logged-in users.
+#[rocket::get("/?<domain>&<from>&<duration>", rank = 1)]
 async fn route_index_loggedin(
     mut conn: Connection<LogsDB>,
     mut config_conn: Connection<ConfigDB>,
     lig: LoggedInGuard,
     flash: Option<FlashMessage<'_>>,
     domain: Option<&str>,
+    from: Option<&str>,
+    duration: Option<&str>,
 ) -> Template {
     let f;
     if let Some(ref flash) = flash {
@@ -164,8 +180,29 @@
         f = None;
     }
 
+    // Parameter treatment
+    let duration = duration
+        .map(|d| i64::from_str_radix(d, 10).unwrap_or(30))
+        .map(|d| Duration::new(84600 * d, 0))
+        .unwrap_or(Duration::days(30));
+    let from = from
+        .map(|p| {
+            OffsetDateTime::parse(p, &time::format_description::well_known::Iso8601::PARSING)
+                .or(
+                    Date::parse(p, &time::format_description::well_known::Iso8601::PARSING)
+                        .map(|d| d.midnight().assume_utc()),
+                )
+                .unwrap_or(OffsetDateTime::now_utc() - duration)
+        })
+        .unwrap_or(OffsetDateTime::now_utc() - duration);
+    let begin = from;
+    let end = begin + duration;
+
+    // Chart rendering
+
     let mut charts = HashMap::<String, String>::new();
 
+    // in seconds for this user.
     let tz_offset = match ConfigDBSession(&mut config_conn)
         .get_user_details(&lig.0)
         .await
@@ -176,9 +213,6 @@
             0
         }
     };
-    // TODO: Make configurable
-    let begin = OffsetDateTime::now_utc() - Duration::days(30);
-    let end = OffsetDateTime::now_utc();
     match LogsDBSession(&mut conn)
         .query_visits_sessions_counts(begin, end, Some(tz_offset), domain)
         .await