Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
854 changes: 559 additions & 295 deletions Cargo.lock

Large diffs are not rendered by default.

18 changes: 10 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ path="src/main.rs"
[dependencies]
# async/concurrency
arc-swap="1.8"
tokio={version="1.49", default-features=false, features=["macros", "rt-multi-thread", "signal"]}
tokio={version="1.50", default-features=false, features=["macros", "rt-multi-thread", "signal"]}
tokio-util={version="0.7", features=["io"]}
futures-lite={version="2.6", default-features=false, features=["alloc"]}
quick_cache={version="0.6", features=["ahash"]}
Expand All @@ -27,18 +27,21 @@ hex={version="0.4"}
bs58="0.5"
serde={version="1.0", features=["derive"]}
serde_json={version="1.0"}
md5={package="md-5", version="0.10.6"}
md-5={version="0.11.0-rc.5"}
async-compression={version="0.4", default-features=false, features=["gzip", "tokio"]}
tokio-tar={package="astral-tokio-tar", version="0.5"}
sha3={version="0.10"}
argon2={version="0.5", features=["rand"]}
password-hash={version="0.5", features=["rand_core", "getrandom"]} # required for getrandom feature
blake3={version="1.8"}
argon2={version="0.6.0-rc.7", features=[]}
password-hash={version="0.6.0-rc.12", features=[
"rand_core",
"getrandom",
]} # required for getrandom feature
zstd={version="0.13", default-features=false}

# general
argh={version="0.1", default-features=false, features=["help"]}
anyhow={version="1.0"}
rand={version="0.9", default-features=false, features=["std", "thread_rng"]}
rand={version="0.10.0", default-features=false, features=["std", "thread_rng"]}
chrono={version="0.4", default-features=false, features=["std", "now", "serde"]}
figment={version="0.10", features=["toml", "env"]}
tracing={version="0.1", default-features=false, features=["std"]}
Expand Down Expand Up @@ -89,8 +92,7 @@ maxminddb={version="0.27", optional=true, features=["simdutf8"]}
figment={version="*", features=["test"]}
cookie={version="*", default-features=false}
tower={version="*", features=["util"]}
hyper={version="*", features=["full"]}
axum-test={version="18"}
axum-test={version="19"}

[features]
default=["geoip"]
Expand Down
1 change: 1 addition & 0 deletions about.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ accepted=[
"ISC",
"MPL-2.0",
"BSD-3-Clause",
"BSD-2-Clause",
"Unicode-DFS-2016",
"Unicode-3.0",
"OpenSSL",
Expand Down
2 changes: 1 addition & 1 deletion data/licenses-cargo.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion data/licenses-npm.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions data/spammers.txt
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ bowigosale.xyz
bpro1.top
bradleylive.xyz
brakehawk.com
brandnewtube.com
brateg.xyz
brauni.com.ua
bravica.biz
Expand Down Expand Up @@ -745,6 +746,7 @@ fartunabest.ru
fashiong.ru
fast-wordpress-start.com
fastgg.net
fatrizscae.online
favoritki-msk.ru
fazika.ru
fbdownloader.com
Expand Down
2 changes: 1 addition & 1 deletion data/ua_regexes.json

Large diffs are not rendered by default.

Binary file modified data/ua_regexes.json.zstd
Binary file not shown.
1 change: 0 additions & 1 deletion src/app/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pub mod events;
pub mod onboarding;
pub mod projects;
pub mod reports;
mod reports_cached;
pub mod sessions;
pub mod users;

Expand Down
4 changes: 2 additions & 2 deletions src/app/core/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ use std::sync::Arc;
use anyhow::{Result, bail};
use arc_swap::ArcSwap;
use chrono::{DateTime, Utc};
use rand::distr::{SampleString, StandardUniform};
use std::sync::mpsc::Receiver;

use crate::app::models::{Event, event_params};
use crate::app::{DuckDBPool, EVENT_BATCH_INTERVAL, SqlitePool};
use crate::utils::hash::generate_salt;

#[derive(Clone)]
pub struct LiwanEvents {
Expand All @@ -34,7 +34,7 @@ impl LiwanEvents {
// if the salt is older than 24 hours, replace it with a new one (utils::generate_salt)
if (Utc::now() - updated_at) > chrono::Duration::hours(24) {
tracing::debug!("Daily salt expired, generating a new one");
let new_salt = generate_salt();
let new_salt = StandardUniform.sample_string(&mut rand::rng(), 16);
let now = Utc::now();
let conn = self.sqlite.get()?;
conn.execute("update salts set salt = ?, updated_at = ? where id = 1", rusqlite::params![&new_salt, now])?;
Expand Down
19 changes: 14 additions & 5 deletions src/app/core/geoip.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(dead_code)]

use std::io::{self};
use std::io::{self, Read};
use std::net::IpAddr;
use std::path::{Path, PathBuf};
use std::sync::Arc;
Expand All @@ -11,7 +11,7 @@ use crate::app::SqlitePool;
use anyhow::{Context, Result, anyhow};
use arc_swap::ArcSwapOption;
use futures_lite::StreamExt;
use md5::{Digest, Md5};
use md5::Digest;
use tokio_tar::Archive;
use tokio_util::io::StreamReader;

Expand Down Expand Up @@ -232,9 +232,18 @@ async fn get_latest_md5(edition: &str, account_id: &str, license_key: &str) -> R
fn file_md5(path: &Path) -> Result<String> {
let file = std::fs::File::open(path)?;
let mut reader = std::io::BufReader::new(file);
let mut hasher = Md5::new();
std::io::copy(&mut reader, &mut hasher)?;
Ok(format!("{:x}", hasher.finalize()))
let mut hasher = md5::Md5::new();

let mut buffer = [0u8; 8192];
loop {
let n = reader.read(&mut buffer)?;
if n == 0 {
break;
}
hasher.update(&buffer[..n]);
}

Ok(hex::encode(hasher.finalize()))
}

async fn download_maxmind_db(edition: &str, account_id: &str, license_key: &str) -> Result<PathBuf> {
Expand Down
2 changes: 0 additions & 2 deletions src/app/core/reports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ use duckdb::params_from_iter;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

pub use super::reports_cached::*;

#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, Hash, PartialEq, Eq)]
pub struct DateRange {
pub start: DateTime<Utc>,
Expand Down
181 changes: 0 additions & 181 deletions src/app/core/reports_cached.rs

This file was deleted.

1 change: 1 addition & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ impl Config {
}

#[cfg(test)]
#[allow(clippy::result_large_err)]
mod test {
use super::*;
use figment::Jail;
Expand Down
31 changes: 12 additions & 19 deletions src/utils/hash.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,31 @@
use anyhow::Context;
use argon2::Argon2;
use argon2::PasswordVerifier;
use argon2::password_hash::{PasswordHasher, SaltString, rand_core};
use argon2::password_hash::PasswordHasher;

use anyhow::Result;
use rand::RngCore;
use sha3::Digest;
use rand::Rng;
use std::net::IpAddr;

pub fn hash_password(password: &str) -> Result<String> {
let salt = SaltString::generate(&mut rand_core::OsRng);
let hash = Argon2::default()
.hash_password(password.as_bytes(), &salt)
.map_err(|_| anyhow::anyhow!("Failed to hash password"))?;
let hash = Argon2::default().hash_password(password.as_bytes()).context("Failed to hash password")?;
Ok(hash.to_string())
}

pub fn verify_password(password: &str, hash: &str) -> Result<()> {
let hash = argon2::PasswordHash::new(hash).map_err(|_| anyhow::anyhow!("Invalid hash"))?;
let hash = argon2::PasswordHash::new(hash).context("Invalid hash")?;
let argon2 = Argon2::default();
argon2.verify_password(password.as_bytes(), &hash).map_err(|_| anyhow::anyhow!("Failed to verify password"))
}

pub fn generate_salt() -> String {
SaltString::generate(&mut rand_core::OsRng).to_string()
argon2.verify_password(password.as_bytes(), &hash).context("Failed to verify password")
}

pub fn hash_ip(ip: &IpAddr, user_agent: &str, daily_salt: &str, entity_id: &str) -> String {
let mut hasher = sha3::Sha3_256::new();
hasher.update(ip.to_string());
hasher.update(user_agent);
hasher.update(daily_salt);
hasher.update(entity_id);
let mut hasher = blake3::Hasher::new();
hasher.update(ip.to_string().as_bytes());
hasher.update(user_agent.as_bytes());
hasher.update(daily_salt.as_bytes());
hasher.update(entity_id.as_bytes());
let hash = hasher.finalize();
hex::encode(hash)[..32].to_string()
hex::encode(hash.as_bytes())[..32].to_string()
}

pub fn visitor_id() -> String {
Expand Down
5 changes: 2 additions & 3 deletions src/utils/seed.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use chrono::{DateTime, Duration, Utc};
use rand::Rng;

use crate::app::models::Event;
use chrono::{DateTime, Duration, Utc};
use rand::RngExt;

const PATHS: &[&str] = &["/", "/about", "/contact", "/pricing", "/blog", "/login", "/signup"];
const REFERRERS: &[&str] = &["", "google.com", "twitter.com", "liwan.dev", "example.com", "henrygressmann.de"];
Expand Down
Loading