diff --git a/src/api/tracker.rs b/src/api/tracker.rs index aaf5f45..6d540db 100644 --- a/src/api/tracker.rs +++ b/src/api/tracker.rs @@ -1,8 +1,9 @@ use crate::auth::Authenticated; +use crate::dtos::hit::HitDTO; use crate::dtos::tracker::{NewTrackerDTO, TrackerDTO}; use crate::models::AppState; use crate::models::tracker::Tracker; -use crate::schema::hits::dsl as hits; +use crate::schema::hits; use crate::schema::trackers; use crate::schema::trackers::dsl; use chrono::Utc; @@ -61,6 +62,30 @@ pub fn get( } } +#[get("//hits")] +pub fn get_hits( + id: &str, + _auth: Authenticated, + state: &State, +) -> Result>, Status> { + let mut db = state.db.lock().unwrap(); + + let id = match Uuid::parse_str(id).ok() { + Some(id) => id, + None => return Err(Status::BadRequest), + }; + + let result = hits::dsl::hits + .filter(hits::tracker_id.eq(id)) + .load(&mut *db) + .ok(); + + match result { + Some(results) => Ok(Json(results.iter().map(HitDTO::from).collect())), + None => Err(Status::NotFound), + } +} + #[post("/", format = "json", data = "")] pub fn create( data: Json, @@ -108,7 +133,7 @@ pub fn delete( if delete_hits { let hit_count = - diesel::delete(hits::hits.filter(hits::tracker_id.eq(id))).execute(&mut *db); + diesel::delete(hits::dsl::hits.filter(hits::tracker_id.eq(id))).execute(&mut *db); if let Err(err) = hit_count { error!("Failed to delete associated hits: {}", err) } diff --git a/src/main.rs b/src/main.rs index 0379b48..ebf22f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -67,6 +67,7 @@ fn rocket() -> _ { routes![ tracker::index, tracker::get, + tracker::get_hits, tracker::create, tracker::delete ], diff --git a/static/index.html b/static/index.html index 14711ad..cb926ae 100644 --- a/static/index.html +++ b/static/index.html @@ -118,11 +118,44 @@ width: 15rem; } - #tracker-table td, #tracker-table th { + #tracker-table td:nth-child(4) { + width: 10rem; + } + + #tracker-table td, #tracker-table th, #hit-table td, #hit-table th { margin: 0; - padding: 0; + padding: 0.2rem 0; border-bottom: 1px solid black; } + + #hit-title { + font-size: 1.15rem; + width: 100%; + margin-top: 2rem; + margin-bottom: 0; + } + + #hit-table { + width: 100%; + overflow: auto; + font-size: 1.10rem; + } + + #hit-table th:nth-child(1) { + width: 20rem; + } + + #hit-table th:nth-child(2) { + width: 10rem; + } + + #hit-table th:nth-child(4) { + width: 8rem; + } + + #hit-table th:nth-child(5) { + width: 15rem; + } @@ -141,7 +174,18 @@ ID Name Created at - Hits + + + + +

No tracker selected

+ + + + + + +
IDIPAgentLanguageCreated at
@@ -184,21 +228,68 @@ } }).then((res) => { res.json().then((trackers) => { - console.log(trackers); trackers.forEach((tracker) => { document.getElementById("tracker-table").innerHTML += ` ${tracker.id} ${tracker.name} ${tracker.created_at} - ${tracker.hits} - - `; - }) + + + + + + `; + }); }).catch((err) => alert(`Couldn't unwrap json: ${err}`)) }).catch((err) => alert(`Couldn't fetch trackers: ${err}`)); } + function loadTrigger(id) { + const apiKey = localStorage.getItem("api-key"); + if (!apiKey) { + return; + } + + fetch(`http://localhost:8000/tracker/${id}/hits`, { + method: "GET", + headers: { + Authorization: apiKey, + } + }).then((res) => { + res.json().then((hits) => { + document.getElementById("hit-title").innerHTML = `${hits.length} hit(s) for tracker ${id}`; + document.getElementById("hit-table").innerHTML = ` + + ID + IP + Agent + Language + Created at + `; + + hits.forEach((hit) => { + document.getElementById("hit-table").innerHTML += ` + + ${hit.id} + ${hit.ip} + ${hit.agent} + ${hit.language} + ${hit.created_at} + `; + }); + }).catch((err) => alert(`Couldn't unwrap json: ${err}`)); + }).catch((err) => alert(`Couldn't fetch hits: ${err}`)); + } + + function copyLink(id) { + navigator.clipboard.writeText(`http://localhost:8000/image/${id}`).catch((err) => alert(`Couldn't copy: ${err}`)); + } + init();