changeset 71:eade8c0055bf

Fix timezone handling
author Lewin Bormann <lbo@spheniscida.de>
date Wed, 17 Aug 2022 17:46:40 +0200
parents e76d019d95d2
children b9d9b4508898
files assets/settings.html.hbs src/configdb.rs src/logsdb.rs src/main.rs
diffstat 4 files changed, 43 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/assets/settings.html.hbs	Mon Aug 01 09:45:39 2022 -0700
+++ b/assets/settings.html.hbs	Wed Aug 17 17:46:40 2022 +0200
@@ -41,5 +41,16 @@
         <input type="submit" value="Save" />
     </form>
 
+    {{ #if admin.active }}
+    <h2 style="color: darkred">Administration</h2>
+    <form id="pwform" action="{{thispath}}" method="GET">
+        <label for="configure_user">Manage user:</label>
+        <input type="text" name="configure_user" value="{{{admin.configure_user}}}" />
+        <input type="submit" value="Manage..." />
+    </form>
+
+
+    {{/if}}
+
     </body>
 </html>
--- a/src/configdb.rs	Mon Aug 01 09:45:39 2022 -0700
+++ b/src/configdb.rs	Wed Aug 17 17:46:40 2022 +0200
@@ -104,4 +104,12 @@
             .await?;
         Ok(())
     }
+
+    pub async fn is_admin<S0: AsRef<str>>(&mut self, user: S0) -> Result<bool, Error> {
+        Ok(sqlx::query("SELECT is_admin FROM users JOIN permissions ON (users.id = permissions.user_id) WHERE username = ?")
+            .bind(user.as_ref())
+            .fetch_one(&mut *self.0)
+            .await?
+            .get(0))
+    }
 }
--- a/src/logsdb.rs	Mon Aug 01 09:45:39 2022 -0700
+++ b/src/logsdb.rs	Wed Aug 17 17:46:40 2022 +0200
@@ -23,7 +23,6 @@
     pub domain: Option<String>,
     pub from: OffsetDateTime,
     pub to: OffsetDateTime,
-    pub tz_offset: i64,
     pub include_bots: bool,
 }
 
@@ -133,28 +132,23 @@
         ctx: &LogsQueryContext,
     ) -> Result<(Vec<String>, Vec<u32>, Vec<u32>), Error> {
         let domain = ctx.domain.as_ref().map(String::as_str).unwrap_or("%");
-        let tz_offset = ctx.tz_offset;
         let include_bots = if ctx.include_bots { 1 } else { 0 };
         let mut results = sqlx::query(
             r#"
-SELECT DATE(atime + ?, 'unixepoch') AS rqdate, COUNT(requestlog.id) AS rqcount, sesscount
+SELECT DATE(atime, 'unixepoch') AS rqdate, COUNT(requestlog.id) AS rqcount, sesscount
 FROM requestlog
 JOIN (
-    SELECT DATE(start + ?, 'unixepoch') AS sessdate, COUNT(*) AS sesscount
+    SELECT DATE(start, 'unixepoch') AS sessdate, COUNT(*) AS sesscount
     FROM sessions WHERE sessions.domain LIKE ? AND sessions.is_bot <= ? GROUP BY sessdate)
 AS sc ON (rqdate = sessdate)
 JOIN sessions ON (sessions.id = requestlog.session)
-WHERE atime+? > ? AND atime+? < ? AND requestlog.domain LIKE ? AND sessions.is_bot <= ?
+WHERE atime > ? AND atime < ? AND requestlog.domain LIKE ? AND sessions.is_bot <= ?
 GROUP BY rqdate
 ORDER BY rqdate ASC;"#,
         )
-        .bind(tz_offset)
-        .bind(tz_offset)
         .bind(domain)
         .bind(include_bots)
-        .bind(tz_offset)
         .bind(ctx.from.unix_timestamp())
-        .bind(tz_offset)
         .bind(ctx.to.unix_timestamp())
         .bind(domain)
         .bind(include_bots)
@@ -187,19 +181,16 @@
         &mut self,
         ctx: &LogsQueryContext,
     ) -> Result<Vec<(String, i64)>, Error> {
-        let tz_offset = ctx.tz_offset;
         let include_bots = if ctx.include_bots { 1 } else { 0 };
         let result = sqlx::query(
             r#"
 SELECT origin_country, COUNT(*) AS count
 FROM sessions
-WHERE start+? > ? AND start+? < ? AND domain LIKE ? AND is_bot <= ?
+WHERE start > ? AND start < ? AND domain LIKE ? AND is_bot <= ?
 GROUP BY origin_country
 ORDER BY count DESC;"#,
         )
-        .bind(tz_offset)
         .bind(ctx.from.unix_timestamp())
-        .bind(tz_offset)
         .bind(ctx.to.unix_timestamp())
         .bind(ctx.domain.as_ref().map(String::as_str).unwrap_or("%"))
         .bind(include_bots)
@@ -217,21 +208,18 @@
         ctx: &LogsQueryContext,
         n: i64,
     ) -> Result<Vec<(String, i64)>, Error> {
-        let tz_offset = ctx.tz_offset;
         let include_bots = if ctx.include_bots { 1 } else { 0 };
         let result = sqlx::query(
             r#"
 SELECT path, COUNT(*) AS pathcount
 FROM RequestLog
 JOIN Sessions ON (Sessions.id = Requestlog.session)
-WHERE atime+? > ? AND atime+? < ? AND RequestLog.domain LIKE ? AND Sessions.is_bot <= ?
+WHERE atime > ? AND atime < ? AND RequestLog.domain LIKE ? AND Sessions.is_bot <= ?
 GROUP BY path
 ORDER BY pathcount DESC
 LIMIT ?;"#,
         )
-        .bind(tz_offset)
         .bind(ctx.from.unix_timestamp())
-        .bind(tz_offset)
         .bind(ctx.to.unix_timestamp())
         .bind(ctx.domain.as_ref().map(String::as_str).unwrap_or("%"))
         .bind(include_bots)
@@ -257,38 +245,31 @@
         &mut self,
         ctx: &LogsQueryContext,
     ) -> Result<Vec<(String, f32)>, Error> {
-        let tz_offset = ctx.tz_offset;
         let include_bots = if ctx.include_bots { 1 } else { 0 };
         let result = sqlx::query(
             r#"
 SELECT d, CAST(nreq AS REAL)/nses
 FROM
-    (SELECT DATE(atime+?, 'unixepoch') AS d,
+    (SELECT DATE(atime, 'unixepoch') AS d,
             COUNT(*) AS nreq
     FROM RequestLog
     JOIN Sessions ON (Sessions.id = RequestLog.session)
-    WHERE atime+? > ? AND atime+? < ? AND RequestLog.domain LIKE ? AND is_bot <= ?
+    WHERE atime > ? AND atime < ? AND RequestLog.domain LIKE ? AND is_bot <= ?
     GROUP BY d)
 JOIN
-    (SELECT DATE(start+?, 'unixepoch') AS d2,
+    (SELECT DATE(start, 'unixepoch') AS d2,
             COUNT(*) as nses
      FROM Sessions
-     WHERE start+? > ? AND start+? < ? AND Sessions.domain LIKE ? AND is_bot <= ?
+     WHERE start > ? AND start < ? AND Sessions.domain LIKE ? AND is_bot <= ?
      GROUP BY d2)
 ON (d = d2)
 ORDER BY d ASC"#,
         )
-        .bind(tz_offset)
-        .bind(tz_offset)
         .bind(ctx.from.unix_timestamp())
-        .bind(tz_offset)
         .bind(ctx.to.unix_timestamp())
         .bind(ctx.domain.as_ref().map(String::as_str).unwrap_or("%"))
         .bind(include_bots)
-        .bind(tz_offset)
-        .bind(tz_offset)
         .bind(ctx.from.unix_timestamp())
-        .bind(tz_offset)
         .bind(ctx.to.unix_timestamp())
         .bind(ctx.domain.as_ref().map(String::as_str).unwrap_or("%"))
         .bind(include_bots)
@@ -316,7 +297,6 @@
         &mut self,
         ctx: &LogsQueryContext,
     ) -> Result<Vec<(String, i64)>, Error> {
-        let tz_offset = ctx.tz_offset;
         let include_bots = if ctx.include_bots { 1 } else { 0 };
         let result = sqlx::query(
             r#"
@@ -324,15 +304,13 @@
 FROM RequestLog
 JOIN Sessions ON (RequestLog.session = Sessions.id)
 WHERE instr(RequestLog.refer, RequestLog.domain) = 0 AND
-    RequestLog.atime+? > ? AND RequestLog.atime+? < ? AND
+    RequestLog.atime > ? AND RequestLog.atime < ? AND
     Sessions.is_bot <= ? AND
     RequestLog.domain LIKE ?
 GROUP BY refer;
 "#,
         )
-        .bind(tz_offset)
         .bind(ctx.from.unix_timestamp())
-        .bind(tz_offset)
         .bind(ctx.to.unix_timestamp())
         .bind(include_bots)
         .bind(ctx.domain.as_ref().map(String::as_str).unwrap_or("%"))
@@ -380,10 +358,10 @@
         ctx: &LogsQueryContext,
         n: i64,
     ) -> Result<Vec<RecentSessionsRow>, Error> {
-        let tz_offset = ctx.tz_offset;
         let include_bots = if ctx.include_bots { 1 } else { 0 };
         // Check later if this query possibly has bad scaling behavior due to no restrictions on
         // requesttags query.
+        log::warn!("from/to {}/{}", ctx.from, ctx.to);
         let result = sqlx::query(
             r#"
 SELECT Sessions.start AS start,
@@ -402,14 +380,12 @@
 		GROUP_CONCAT(IIF(value, PRINTF("%s=%s", IIF(key, key, ""), value), key)) AS tagstring
 	FROM RequestTags GROUP BY requestid) AS AccumTags
 	ON (RequestLog.id = AccumTags.requestid)
-WHERE atime+? >= ? AND atime+? <= ? AND Sessions.is_bot <= ?
+WHERE atime >= ? AND atime <= ? AND Sessions.is_bot <= ?
 GROUP BY Sessions.id
 ORDER BY Sessions.start DESC, RequestLog.atime DESC
-LIMIT 10;"#,
+LIMIT ?;"#,
         )
-        .bind(tz_offset)
         .bind(ctx.from.unix_timestamp())
-        .bind(tz_offset)
         .bind(ctx.to.unix_timestamp())
         .bind(include_bots)
         .bind(n)
--- a/src/main.rs	Mon Aug 01 09:45:39 2022 -0700
+++ b/src/main.rs	Wed Aug 17 17:46:40 2022 +0200
@@ -207,10 +207,8 @@
     }
 
     // Parameter treatment
-    let duration = duration
-        .map(|d| i64::from_str_radix(d, 10).unwrap_or(30))
-        .map(|d| Duration::new(86400 * d, 0))
-        .unwrap_or(Duration::days(30));
+    let duration = Duration::days(i64::from_str_radix(duration
+        .unwrap_or("30"), 10).unwrap_or(30));
     let from = from
         .map(|p| {
             OffsetDateTime::parse(p, &time::format_description::well_known::Iso8601::PARSING)
@@ -249,7 +247,6 @@
         domain: domain.clone(),
         from: begin,
         to: end,
-        tz_offset,
         include_bots: includebots,
     };
 
@@ -510,6 +507,7 @@
     tz_offset: Option<i64>,
 }
 
+/// Settings: Submit form
 #[rocket::post("/settings", data = "<settings>")]
 async fn route_settings_post(
     mut cdb: Connection<ConfigDB>,
@@ -560,12 +558,13 @@
     Flash::success(Redirect::to(settingspath), format!("Saved successfully!"))
 }
 
-#[rocket::get("/settings", rank = 1)]
+#[rocket::get("/settings?<configure_user>", rank = 1)]
 async fn route_settings(
     mut cdb: Connection<ConfigDB>,
     flash: Option<FlashMessage<'_>>,
     cc: &rocket::State<CustomConfig>,
     lig: LoggedInGuard,
+    configure_user: Option<String>,
 ) -> Template {
     let mut db = ConfigDBSession(&mut cdb);
     let user = match db.get_user_details(&lig.0).await {
@@ -590,6 +589,11 @@
         (None, None)
     };
 
+    let is_admin = match db.is_admin(&lig.0).await {
+        Ok(b) => b,
+        Err(e) => { error!("Couldn't query admin status: {}", e); false }
+    };
+
     Template::render(
         "settings",
         context![
@@ -598,6 +602,7 @@
             user: &user.name,
             error: error,
             flash: success,
+            admin: context![ active: is_admin, configure_user: configure_user ],
 
             tz_offset: format!("{:}", user.tz_offset / 3600),