Mercurial > lbo > hg > analyrics
changeset 25:390a448dc8c7
Support timezones
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Wed, 13 Jul 2022 21:49:41 -0700 |
parents | 758a4f6c160f |
children | b1850e6f4d9a |
files | Cargo.toml config_schema_sqlite.sql src/main.rs |
diffstat | 3 files changed, 39 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/Cargo.toml Tue Jul 12 12:21:09 2022 -0700 +++ b/Cargo.toml Wed Jul 13 21:49:41 2022 -0700 @@ -10,8 +10,9 @@ either = "1.7.0" env_logger = "0.9.0" log = "0.4.17" -rocket = { version = "0.5.0-rc.2", features = ["secrets", "json"] } -rocket_db_pools = { version = "0.1.0-rc.2" } +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"
--- a/config_schema_sqlite.sql Tue Jul 12 12:21:09 2022 -0700 +++ b/config_schema_sqlite.sql Wed Jul 13 21:49:41 2022 -0700 @@ -2,10 +2,11 @@ DROP TABLE IF EXISTS users; CREATE TABLE users ( id INTEGER PRIMARY KEY, - username TEXT NOT NULL, + username TEXT NOT NULL UNIQUE, name TEXT, salt TEXT, - password_hash TEXT + password_hash TEXT, + tz_offset INTEGER, ); DROP TABLE IF EXISTS domainpermissions;
--- a/src/main.rs Tue Jul 12 12:21:09 2022 -0700 +++ b/src/main.rs Wed Jul 13 21:49:41 2022 -0700 @@ -12,8 +12,9 @@ use rocket::serde::json::{json, Value}; use rocket::serde::{self, Serialize}; -use rocket_db_pools::sqlx::{self, Executor, Row, Sqlite, SqlitePool}; +use rocket_db_pools::sqlx::{Executor, Row, Sqlite, SqlitePool}; use rocket_db_pools::{Connection, Database, Pool}; +use sqlx::prelude::FromRow; use rocket_dyn_templates::{context, Template}; @@ -40,6 +41,12 @@ #[database("sqlite_main")] struct ConfigDB(PoolType); +#[derive(Default, Clone, Debug, FromRow)] +struct UserRecord { + name: String, + tz_offset: i64, +} + struct ConfigDBSession<'p, DB: sqlx::Database>(&'p mut sqlx::pool::PoolConnection<DB>); impl<'p> ConfigDBSession<'p, Sqlite> { @@ -67,6 +74,14 @@ let result = self.0.fetch_all(q).await?; Ok(result.len() == 1) } + + async fn get_user_details(&mut self, user: &str) -> Result<UserRecord, Error> { + let entry = sqlx::query("SELECT name, tz_offset FROM users WHERE username = ? LIMIT 1") + .bind(user) + .fetch_one(&mut *self.0) + .await?; + Ok(UserRecord::from_row(&entry)?) + } } #[derive(Database)] @@ -151,21 +166,24 @@ &mut self, from: OffsetDateTime, to: OffsetDateTime, + tz_offset: Option<i64>, domainpattern: Option<S>, ) -> Result<(Vec<String>, Vec<u32>, Vec<u32>), Error> { let domain = domainpattern.as_ref().map(AsRef::as_ref).unwrap_or("%"); 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 ? GROUP BY sessdate) AS sc ON (rqdate = sessdate) 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(domain) .bind(from.unix_timestamp()) .bind(to.unix_timestamp()) @@ -344,6 +362,7 @@ #[rocket::get("/?<domain>", rank = 1)] async fn route_index_loggedin( mut conn: Connection<LogsDB>, + mut config_conn: Connection<ConfigDB>, lig: LoggedInGuard, flash: Option<FlashMessage<'_>>, domain: Option<&str>, @@ -357,11 +376,21 @@ let mut charts = HashMap::<String, String>::new(); + let tz_offset = match ConfigDBSession(&mut config_conn) + .get_user_details(&lig.0) + .await + { + Ok(ur) => ur.tz_offset, + Err(e) => { + error!("Couldn't obtain user details: {}", e); + 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, domain) + .query_visits_sessions_counts(begin, end, Some(tz_offset), domain) .await { Ok((dates, visits, sessions)) => { @@ -498,22 +527,6 @@ ) } -#[rocket::get("/static/<path>")] -async fn route_static( - cc: &rocket::State<CustomConfig>, - path: &str, -) -> Either<NamedFile, (Status, String)> { - match NamedFile::open(Path::new(&cc.asset_path).join(path)).await { - Ok(f) => Either::Left(f), - Err(e) => { - warn!("Static file not found: {}", path); - Either::Right(( - Status::NotFound, - format!("Error loading file at {}: {}", path, e), - )) - } - } -} #[derive(rocket::serde::Deserialize)] #[serde(crate = "rocket::serde")] struct CustomConfig {