diff --git a/backend/migrations/2020-09-13-154110_switches/up.sql b/backend/migrations/2020-09-13-154110_switches/up.sql index 556def1..238332c 100644 --- a/backend/migrations/2020-09-13-154110_switches/up.sql +++ b/backend/migrations/2020-09-13-154110_switches/up.sql @@ -11,7 +11,7 @@ CREATE TABLE IF NOT EXISTS switches , member_id INTEGER NOT NULL , started_at TIMESTAMP NOT NULL , ended_at TIMESTAMP - , duration INTEGER NOT NULL + , duration INTEGER , FOREIGN KEY (member_id) REFERENCES members(id) ); diff --git a/backend/src/api.rs b/backend/src/api.rs index 0dff548..fbfa7da 100644 --- a/backend/src/api.rs +++ b/backend/src/api.rs @@ -1,17 +1,18 @@ use crate::{models, schema, MainDatabase}; -use chrono::NaiveDateTime; +use chrono::prelude::*; use diesel::prelude::*; use rocket::{ data::{self, FromDataSimple}, - http::{ContentType, Status}, - request::{self, FromRequest, Request}, + http::Status, + request::Request, response::Responder, Data, Outcome::*, Response, }; use rocket_contrib::json::Json; -use std::io::Read; +use rusty_ulid::generate_ulid_string; +use std::{convert::TryInto, io::Read}; #[get("/members")] #[instrument(skip(conn), err)] @@ -30,7 +31,7 @@ pub struct FrontChange { pub who: String, // models::Member.name pub started_at: NaiveDateTime, pub ended_at: Option, - pub duration: i32, + pub duration: Option, } #[get("/switches?&")] @@ -96,18 +97,78 @@ pub fn get_current_front(conn: MainDatabase) -> Result> { #[post("/switches/switch", data = "")] #[instrument(skip(conn), err)] -pub fn make_switch(conn: MainDatabase, who: StringBody) -> Result { - info!("got here"); - Ok(()) +pub fn make_switch(conn: MainDatabase, who: StringBody) -> Result { + use schema::{members, switches}; + let who = who.unwrap(); + + let (last, member): (models::Switch, models::Member) = switches::table + .inner_join(members::table) + .order_by(switches::dsl::started_at.desc()) + .limit(1) + .load(&*conn) + .map_err(Error::Database)? + .pop() + .ok_or_else(|| Error::NotFound)?; + + let to: models::Member = members::dsl::members + .filter({ + use members::dsl::cmene; + cmene.eq(who) + }) + .limit(1) + .load::(&*conn) + .map_err(Error::Database)? + .pop() + .ok_or_else(|| Error::NotFound)?; + + let now = Utc::now().naive_utc(); + + let switch = models::NewSwitch { + id: generate_ulid_string(), + member_id: to.id, + started_at: now, + }; + + { + use schema::switches::dsl::*; + diesel::update(switches.find(last.id)) + .set(&models::UpdateSwitchTime { + ended_at: Some(now.clone()), + duration: Some( + now.clone() + .signed_duration_since(last.started_at) + .num_seconds() + .try_into() + .expect("don't expect a switch to last 30+ years"), + ), + }) + .execute(&*conn) + .map_err(Error::Database) + }?; + + diesel::insert_into(switches::table) + .values(&switch) + .execute(&*conn) + .map_err(Error::Database)?; + + info!(from = &member.cmene[..], to = &to.cmene[..], "switched"); + + Ok(to.cmene) } #[derive(Debug)] pub struct StringBody(String); +impl StringBody { + fn unwrap(self) -> String { + self.0 + } +} + impl FromDataSimple for StringBody { type Error = String; - fn from_data(req: &Request, data: Data) -> data::Outcome { + fn from_data(_req: &Request, data: Data) -> data::Outcome { let mut contents = String::new(); if let Err(e) = data.open().take(256).read_to_string(&mut contents) { diff --git a/backend/src/main.rs b/backend/src/main.rs index bf6e3fa..93187cf 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -37,7 +37,7 @@ fn main() -> Result<()> { .attach(SpaceHelmet::default()) .mount("/metrics", prometheus) .mount( - "/api", + "/", routes![ api::get_members, api::get_switches, diff --git a/backend/src/models.rs b/backend/src/models.rs index bc66bad..a7ab382 100644 --- a/backend/src/models.rs +++ b/backend/src/models.rs @@ -18,5 +18,20 @@ pub struct Switch { pub member_id: i32, pub started_at: NaiveDateTime, pub ended_at: Option, - pub duration: i32, + pub duration: Option, +} + +#[derive(Insertable)] +#[table_name = "switches"] +pub struct NewSwitch { + pub id: String, + pub member_id: i32, + pub started_at: NaiveDateTime, +} + +#[derive(AsChangeset)] +#[table_name = "switches"] +pub struct UpdateSwitchTime { + pub ended_at: Option, + pub duration: Option, } diff --git a/backend/src/schema.rs b/backend/src/schema.rs index 8051b3d..6e51b09 100644 --- a/backend/src/schema.rs +++ b/backend/src/schema.rs @@ -12,7 +12,7 @@ table! { member_id -> Integer, started_at -> Timestamp, ended_at -> Nullable, - duration -> Integer, + duration -> Nullable, } }