Add wait_for_event route & update deps
This commit is contained in:
1037
Cargo.lock
generated
1037
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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"
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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!()
|
|
||||||
}
|
|
||||||
@ -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");
|
||||||
|
|
||||||
|
|||||||
@ -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 }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -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
21
src/util.rs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user