Add wait_for_event route & update deps

This commit is contained in:
2021-04-22 14:21:25 +02:00
parent 5c43bb409e
commit e39cffa3f6
9 changed files with 583 additions and 552 deletions

1037
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -16,11 +16,15 @@ futures = "0.3"
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
sled = "0.34" sled = "0.34"
semver = "0.11" semver = "0.11"
uuid = { version = "0.7", features = ["serde", "v4"] } uuid = { version = "0.8", features = ["serde", "v4"] }
duplicate = "0.2" duplicate = "0.2"
bincode = "1" bincode = "1"
handlebars = "3" handlebars = "3"
[dependencies.tokio]
version = "1"
features = ["sync", "time"]
[dependencies.rocket] [dependencies.rocket]
#version = "0.4" #version = "0.4"
git = "https://github.com/SergioBenitez/Rocket" git = "https://github.com/SergioBenitez/Rocket"

View File

@ -1,9 +1,10 @@
use crate::routes::pages; use crate::routes::pages;
use rocket::{ use rocket::{
catch, catch,
form::{Form, FromForm},
http::{Cookie, CookieJar, Status}, http::{Cookie, CookieJar, Status},
post, post,
request::{Form, FromForm, FromRequest, Outcome, Request}, request::{FromRequest, Outcome, Request},
response::Redirect, response::Redirect,
uri, State, uri, State,
}; };
@ -26,10 +27,10 @@ pub struct Authorized;
pub struct Unauthorized; pub struct Unauthorized;
#[rocket::async_trait] #[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for Authorized { impl<'a> FromRequest<'a> for Authorized {
type Error = Unauthorized; type Error = Unauthorized;
async fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'a Request<'_>) -> Outcome<Self, Self::Error> {
let cookies = request.cookies(); let cookies = request.cookies();
match cookies.get_private(AUTH_COOKIE_KEY) { match cookies.get_private(AUTH_COOKIE_KEY) {

View File

@ -1,10 +0,0 @@
use std::collections::HashMap;
use crate::database::v2;
pub fn get_category() -> () {
todo!()
}
pub fn get_all_categories() -> Result<HashMap< {
todo!()
}

View File

@ -3,11 +3,13 @@ mod database;
mod handlebars_util; mod handlebars_util;
mod routes; mod routes;
mod status_json; mod status_json;
mod util;
use crate::auth::MasterPassword; use crate::auth::MasterPassword;
use crate::database::migrations::migrate; use crate::database::migrations::migrate;
use crate::database::unversioned::global::schema_version; use crate::database::unversioned::global::schema_version;
use crate::database::SCHEMA_VERSION; use crate::database::SCHEMA_VERSION;
use crate::util::EventNotifier;
use bincode::{deserialize, serialize}; use bincode::{deserialize, serialize};
use dotenv::dotenv; use dotenv::dotenv;
use rocket_contrib::serve::StaticFiles; use rocket_contrib::serve::StaticFiles;
@ -46,12 +48,13 @@ async fn main() -> io::Result<()> {
} }
} }
let rocket = rocket::ignite() let rocket = rocket::build()
.attach(Template::custom(|engines| { .attach(Template::custom(|engines| {
handlebars_util::register_helpers(engines) handlebars_util::register_helpers(engines)
})) }))
.manage(sled) .manage(sled)
.manage(master_pass) .manage(master_pass)
.manage(EventNotifier::new())
.mount("/static", StaticFiles::from("static")) .mount("/static", StaticFiles::from("static"))
.mount( .mount(
"/", "/",
@ -73,10 +76,11 @@ async fn main() -> io::Result<()> {
routes::api::end_session, routes::api::end_session,
routes::api::bump_session, routes::api::bump_session,
routes::api::delete_session, routes::api::delete_session,
routes::api::wait_for_event,
auth::login, auth::login,
], ],
) )
.register(rocket::catchers![auth::login_page,]); .register("/", rocket::catchers![auth::login_page,]);
rocket.launch().await.expect("rocket failed to launch"); rocket.launch().await.expect("rocket failed to launch");

View File

@ -3,14 +3,16 @@ use crate::database::latest::trees::{categories, sessions};
use crate::database::util::category::get_all_categories; use crate::database::util::category::get_all_categories;
use crate::routes::pages; use crate::routes::pages;
use crate::status_json::StatusJson; use crate::status_json::StatusJson;
use crate::util::EventNotifier;
use bincode::{deserialize, serialize}; use bincode::{deserialize, serialize};
use chrono::{Duration, Local, NaiveDateTime, TimeZone}; use chrono::{Duration, Local, NaiveDateTime, TimeZone};
use rocket::form::{Form, FromForm};
use rocket::http::Status; use rocket::http::Status;
use rocket::request::{Form, FromForm};
use rocket::response::Redirect; use rocket::response::Redirect;
use rocket::{get, post, uri, State}; use rocket::{get, post, uri, State};
use rocket_contrib::json::Json; use rocket_contrib::json::Json;
use rocket_contrib::uuid::Uuid; use rocket_contrib::uuid::Uuid;
use serde::Serialize;
use sled::Transactional; use sled::Transactional;
use std::collections::HashMap; use std::collections::HashMap;
@ -101,23 +103,26 @@ pub fn bump_session(
pub fn start_session( pub fn start_session(
_auth: Authorized, _auth: Authorized,
category_uuid: Uuid, category_uuid: Uuid,
event_notifier: State<'_, EventNotifier>,
db: State<'_, sled::Db>, db: State<'_, sled::Db>,
) -> Result<StatusJson, StatusJson> { ) -> Result<StatusJson, StatusJson> {
toggle_category_session(category_uuid, true, db) toggle_category_session(category_uuid, true, event_notifier, db)
} }
#[post("/category/<category_uuid>/end_session")] #[post("/category/<category_uuid>/end_session")]
pub fn end_session( pub fn end_session(
_auth: Authorized, _auth: Authorized,
category_uuid: Uuid, category_uuid: Uuid,
event_notifier: State<'_, EventNotifier>,
db: State<'_, sled::Db>, db: State<'_, sled::Db>,
) -> Result<StatusJson, StatusJson> { ) -> Result<StatusJson, StatusJson> {
toggle_category_session(category_uuid, false, db) toggle_category_session(category_uuid, false, event_notifier, db)
} }
pub fn toggle_category_session( pub fn toggle_category_session(
category_uuid: Uuid, category_uuid: Uuid,
set_active: bool, set_active: bool,
event_notifier: State<'_, EventNotifier>,
db: State<'_, sled::Db>, db: State<'_, sled::Db>,
) -> Result<StatusJson, StatusJson> { ) -> Result<StatusJson, StatusJson> {
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?); let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?);
@ -158,6 +163,7 @@ pub fn toggle_category_session(
} }
tx_categories.insert(&category_uuid_s, serialize(&category).unwrap())?; tx_categories.insert(&category_uuid_s, serialize(&category).unwrap())?;
event_notifier.notify_event();
} }
} }
@ -241,3 +247,26 @@ pub fn delete_session(
// Ok(Ok(Redirect::to(uri!(pages::history)))) // Ok(Ok(Redirect::to(uri!(pages::history))))
// })??) // })??)
} }
#[derive(Serialize)]
pub struct WaitForEvent {
timeout: bool,
}
#[get("/wait_for_event?<timeout>")]
pub async fn wait_for_event(
_auth: Authorized,
timeout: Option<u64>,
event_notifier: State<'_, EventNotifier>,
) -> Json<WaitForEvent> {
use std::time::Duration;
match tokio::time::timeout(
Duration::from_secs(timeout.unwrap_or(30)),
event_notifier.wait_for_event(),
)
.await
{
Ok(_) => Json(WaitForEvent { timeout: false }),
Err(_) => Json(WaitForEvent { timeout: true }),
}
}

View File

@ -1,7 +1,8 @@
use crate::auth::Authorized; use crate::auth::Authorized;
use crate::database::latest::trees::{categories, sessions}; use crate::database::latest::trees::{categories, sessions};
use crate::database::util::category::get_category;
use crate::status_json::StatusJson; use crate::status_json::StatusJson;
use bincode::{deserialize, serialize}; use bincode::deserialize;
use chrono::{DateTime, Local, Timelike}; use chrono::{DateTime, Local, Timelike};
use rocket::http::Status; use rocket::http::Status;
use rocket::{get, State}; use rocket::{get, State};
@ -38,15 +39,11 @@ pub fn single_stats(
category_uuid: Uuid, category_uuid: Uuid,
db: State<'_, sled::Db>, db: State<'_, sled::Db>,
) -> Result<Template, StatusJson> { ) -> Result<Template, StatusJson> {
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?);
let categories_tree = db.open_tree(categories::NAME)?; let categories_tree = db.open_tree(categories::NAME)?;
let sessions_tree = db.open_tree(sessions::NAME)?; let sessions_tree = db.open_tree(sessions::NAME)?;
let category: categories::V = match categories_tree.get(category_uuid_s)? { let category: categories::V =
None => Err(Status::NotFound)?, get_category(&categories_tree, &category_uuid)?.ok_or(Status::NotFound)?;
Some(data) => deserialize(&data).unwrap(),
};
let sessions: HashMap<sessions::K, sessions::V> = sessions_tree let sessions: HashMap<sessions::K, sessions::V> = sessions_tree
.iter() .iter()

21
src/util.rs Normal file
View File

@ -0,0 +1,21 @@
use tokio::sync::Notify;
pub struct EventNotifier {
notify: Notify,
}
impl EventNotifier {
pub fn new() -> Self {
EventNotifier {
notify: Notify::new(),
}
}
pub async fn wait_for_event(&self) {
self.notify.notified().await;
}
pub fn notify_event(&self) {
self.notify.notify_waiters();
}
}