froms and db
This commit is contained in:
parent
fc3a6fe2a0
commit
a1abfad8d6
6 changed files with 141 additions and 54 deletions
33
src/db.rs
33
src/db.rs
|
@ -2,7 +2,6 @@ use anyhow::{anyhow, Result};
|
|||
use sqlx::database::HasArguments;
|
||||
use std::convert::TryFrom;
|
||||
use std::net::IpAddr;
|
||||
|
||||
type QueryAs<'q, T> =
|
||||
sqlx::query::QueryAs<'q, sqlx::MySql, T, <sqlx::MySql as HasArguments<'q>>::Arguments>;
|
||||
type Query<'q> = sqlx::query::Query<'q, sqlx::MySql, <sqlx::MySql as HasArguments<'q>>::Arguments>;
|
||||
|
@ -45,7 +44,7 @@ SELECT DISTINCT
|
|||
IF(al.iplong, TRUE, FALSE) present
|
||||
FROM
|
||||
mac_to_nick mtn
|
||||
LEFT JOIN
|
||||
LEFT OUTER JOIN
|
||||
alive_hosts al
|
||||
ON
|
||||
mtn.macaddr = al.macaddr
|
||||
|
@ -95,6 +94,23 @@ WHERE
|
|||
.bind(&self.descr)
|
||||
.bind(id))
|
||||
}
|
||||
|
||||
pub fn delete(self) -> Result<Query<'q>> {
|
||||
let id = match self.id {
|
||||
Some(id) => id,
|
||||
None => return Err(anyhow!("selected device has no id")),
|
||||
};
|
||||
Ok(sqlx::query(
|
||||
"
|
||||
DELETE FROM
|
||||
mac_to_nick
|
||||
WHERE
|
||||
id = ?
|
||||
LIMIT 1
|
||||
",
|
||||
)
|
||||
.bind(id))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(sqlx::Type, Debug, Clone, Copy)]
|
||||
|
@ -108,10 +124,6 @@ pub enum PrivacyLevel {
|
|||
}
|
||||
|
||||
impl PrivacyLevel {
|
||||
pub fn as_u8(&self) -> u8 {
|
||||
*self as u8
|
||||
}
|
||||
|
||||
pub fn selected(&self, level: &PrivacyLevel) -> &'static str {
|
||||
if *self as u8 == *level as u8 {
|
||||
"selected"
|
||||
|
@ -149,16 +161,19 @@ impl<'q> AliveDevice {
|
|||
"
|
||||
SELECT DISTINCT
|
||||
al.macaddr macaddr,
|
||||
al.iplong iplong
|
||||
al.iplong iplong,
|
||||
mtn.nickname
|
||||
FROM
|
||||
alive_hosts al
|
||||
NATURAL LEFT JOIN
|
||||
LEFT OUTER JOIN
|
||||
mac_to_nick mtn
|
||||
ON
|
||||
al.macaddr = mtn.macaddr
|
||||
WHERE
|
||||
mtn.nickname IS NULL
|
||||
AND al.erfda > NOW() - INTERVAL 24 DAY
|
||||
ORDER BY
|
||||
al.erfda DESC
|
||||
;
|
||||
",
|
||||
)
|
||||
}
|
||||
|
|
39
src/forms.rs
39
src/forms.rs
|
@ -18,12 +18,11 @@ impl RegisterForm {
|
|||
Ok(privacy) => privacy,
|
||||
Err(_) => return (Level::Error, "unable to parse privacy level".to_string()),
|
||||
};
|
||||
|
||||
let dbresult = db::Device {
|
||||
id: None,
|
||||
macaddr: self.macaddr,
|
||||
nickname: USER.to_string(),
|
||||
descr: self.descr,
|
||||
descr: self.descr.clone(),
|
||||
privacy,
|
||||
present: false,
|
||||
};
|
||||
|
@ -33,7 +32,10 @@ impl RegisterForm {
|
|||
.execute(&request.state().pool)
|
||||
.await;
|
||||
return match dbresult {
|
||||
Ok(_) => (Level::Info, "assinged device".to_string()),
|
||||
Ok(_) => (
|
||||
Level::Info,
|
||||
format!("assinged device \"{}\" to {}", self.descr, USER),
|
||||
),
|
||||
Err(_) => (Level::Error, "unable to create device".to_string()),
|
||||
};
|
||||
}
|
||||
|
@ -76,3 +78,34 @@ impl UpdateForm {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct DeleteForm {
|
||||
macaddr: String,
|
||||
}
|
||||
|
||||
impl DeleteForm {
|
||||
pub async fn handle(self, request: &crate::Request) -> Message {
|
||||
let device = match db::Device::for_mac(&self.macaddr)
|
||||
.fetch_one(&request.state().pool)
|
||||
.await
|
||||
{
|
||||
Ok(device) => device,
|
||||
Err(_) => {
|
||||
return (
|
||||
Level::Error,
|
||||
"unable to load device from database".to_string(),
|
||||
)
|
||||
}
|
||||
};
|
||||
match device
|
||||
.delete()
|
||||
.unwrap()
|
||||
.execute(&request.state().pool)
|
||||
.await
|
||||
{
|
||||
Ok(_) => (Level::Info, "delete device".to_string()),
|
||||
Err(_) => (Level::Error, "unable to delete device".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
32
src/main.rs
32
src/main.rs
|
@ -6,8 +6,11 @@ use tide::sessions::{MemoryStore, SessionMiddleware};
|
|||
mod db;
|
||||
mod forms;
|
||||
mod routes;
|
||||
mod session;
|
||||
mod templates;
|
||||
|
||||
pub use session::AppSession as Session;
|
||||
|
||||
pub const USER: &str = "foosinn";
|
||||
|
||||
/// Configuration
|
||||
|
@ -43,34 +46,6 @@ pub enum Level {
|
|||
|
||||
pub type Message = (Level, String);
|
||||
|
||||
#[derive(Default, Deserialize, Serialize)]
|
||||
pub struct AppSession {
|
||||
messages: Vec<Message>,
|
||||
}
|
||||
|
||||
impl AppSession {
|
||||
pub fn add_message(mut self, message: Message) -> Self {
|
||||
self.messages.push(message);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn pop_messages(&mut self) -> Vec<Message> {
|
||||
let mut messages: Vec<Message> = Vec::new();
|
||||
std::mem::swap(&mut messages, &mut self.messages);
|
||||
messages
|
||||
}
|
||||
|
||||
pub fn commit(self, request: &mut Request) {
|
||||
request.session_mut().insert("app", self).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&mut Request> for AppSession {
|
||||
fn from(request: &mut Request) -> Self {
|
||||
request.session().get("app").unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
pub type Request = tide::Request<State>;
|
||||
|
||||
#[async_std::main]
|
||||
|
@ -89,6 +64,7 @@ async fn main() -> Result<(), io::Error> {
|
|||
app.at("/").get(routes::index);
|
||||
app.at("/register").post(routes::register);
|
||||
app.at("/update").post(routes::update);
|
||||
app.at("/delete").post(routes::delete);
|
||||
app.at("/healthz").get(routes::healthz);
|
||||
app.at("/static").serve_dir("static/")?;
|
||||
app.listen(config.listen).await
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::db;
|
||||
use crate::forms;
|
||||
use crate::templates;
|
||||
use crate::AppSession;
|
||||
use crate::Session;
|
||||
use crate::USER;
|
||||
use tide::Redirect;
|
||||
|
||||
|
@ -18,28 +18,27 @@ pub async fn index(mut request: crate::Request) -> tide::Result {
|
|||
.fetch_all(&request.state().pool)
|
||||
.await
|
||||
.map_err(|err| dbg!(err))?;
|
||||
|
||||
let mut session = AppSession::from(&mut request);
|
||||
let messages = session.pop_messages();
|
||||
session.commit(&mut request);
|
||||
|
||||
let messages = Session::from(&mut request).pop_messages();
|
||||
Ok(templates::IndexTemplate::new(my, unassinged, messages).into())
|
||||
}
|
||||
|
||||
pub async fn register(mut request: crate::Request) -> tide::Result {
|
||||
let form: forms::RegisterForm = request.body_form().await?;
|
||||
let message = form.handle(&request).await;
|
||||
AppSession::from(&mut request)
|
||||
.add_message(message)
|
||||
.commit(&mut request);
|
||||
Session::from(&mut request).add_message(message);
|
||||
Ok(Redirect::see_other("/").into())
|
||||
}
|
||||
|
||||
pub async fn update(mut request: crate::Request) -> tide::Result {
|
||||
let form: forms::UpdateForm = request.body_form().await?;
|
||||
let message = form.handle(&request).await;
|
||||
AppSession::from(&mut request)
|
||||
.add_message(message)
|
||||
.commit(&mut request);
|
||||
Session::from(&mut request).add_message(message);
|
||||
Ok(Redirect::see_other("/").into())
|
||||
}
|
||||
|
||||
pub async fn delete(mut request: crate::Request) -> tide::Result {
|
||||
let form: forms::DeleteForm = request.body_form().await?;
|
||||
let message = form.handle(&request).await;
|
||||
Session::from(&mut request).add_message(message);
|
||||
Ok(Redirect::see_other("/").into())
|
||||
}
|
||||
|
|
58
src/session.rs
Normal file
58
src/session.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
use crate::Message;
|
||||
use crate::Request;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub struct AppSession<'r> {
|
||||
request: &'r mut Request,
|
||||
session: Inner,
|
||||
}
|
||||
|
||||
impl<'r> AppSession<'r> {
|
||||
pub fn add_message(&mut self, message: Message) {
|
||||
self.session.add_message(message);
|
||||
}
|
||||
|
||||
pub fn pop_messages(&mut self) -> Vec<Message> {
|
||||
self.session.pop_messages()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> From<&'r mut Request> for AppSession<'r> {
|
||||
fn from(request: &'r mut Request) -> Self {
|
||||
let session = Inner::from(&*request);
|
||||
Self { request, session }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Drop for AppSession<'r> {
|
||||
fn drop(&mut self) {
|
||||
self.session.commit(self.request);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Serialize)]
|
||||
struct Inner {
|
||||
messages: Vec<Message>,
|
||||
}
|
||||
|
||||
impl Inner {
|
||||
pub fn add_message(&mut self, message: Message) {
|
||||
self.messages.push(message);
|
||||
}
|
||||
|
||||
pub fn pop_messages(&mut self) -> Vec<Message> {
|
||||
let mut messages: Vec<Message> = Vec::new();
|
||||
std::mem::swap(&mut messages, &mut self.messages);
|
||||
messages
|
||||
}
|
||||
|
||||
pub fn commit(&mut self, request: &mut Request) {
|
||||
request.session_mut().insert("app", self).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Request> for Inner {
|
||||
fn from(request: &Request) -> Self {
|
||||
request.session().get("app").unwrap_or_default()
|
||||
}
|
||||
}
|
|
@ -54,8 +54,14 @@
|
|||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<button class="rounded bg-gray-300 font-bold px-2 bg-green-500">Update</button>
|
||||
<button class="rounded bg-gray-300 font-bold px-2 bg-red-500">Delete</button>
|
||||
<button type="submit" name="action" value="update"
|
||||
class="rounded bg-gray-300 font-bold px-2 bg-green-500">
|
||||
Update
|
||||
</button>
|
||||
<button type="submit"name="action" value="update"
|
||||
class="rounded bg-gray-300 font-bold px-2 bg-red-500">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue