More work on todo list

This commit is contained in:
jude
2024-04-09 21:21:46 +01:00
parent e128b9848f
commit 4063334953
7 changed files with 242 additions and 49 deletions

View File

@ -7,26 +7,38 @@ use rocket::{
State,
};
use serde::{Deserialize, Serialize};
use serenity::prelude::Context;
use serenity::{
all::{ChannelId, GuildId},
prelude::Context,
};
use crate::web::{
check_authorization, guards::transaction::Transaction, routes::JsonResult, string_opt,
check_authorization,
guards::transaction::Transaction,
routes::{dashboard::check_channel_matches_guild, JsonResult},
string_opt,
};
#[derive(Deserialize)]
pub struct CreateTodo {
#[serde(with = "string_opt")]
channel_id: Option<u64>,
value: String,
}
#[derive(Serialize)]
struct GetTodo {
pub struct GetTodo {
id: u32,
#[serde(with = "string_opt")]
channel_id: Option<u64>,
value: String,
}
#[derive(Deserialize)]
pub struct UpdateTodo {
value: String,
}
#[post("/api/guild/<id>/todos", data = "<todo>")]
pub async fn create_todo(
id: u64,
@ -37,6 +49,67 @@ pub async fn create_todo(
) -> JsonResult {
check_authorization(cookies, ctx.inner(), id).await?;
let guild_id = GuildId::new(id);
if todo.value.len() > 2000 {
return json_err!("Value too long");
}
match todo.channel_id {
Some(channel_id) => {
if !check_channel_matches_guild(ctx, ChannelId::new(channel_id), guild_id) {
warn!("Channel {} not found for guild {}", channel_id, guild_id);
return json_err!("Channel not found");
}
sqlx::query!(
"
INSERT INTO todos (guild_id, channel_id, value)
VALUES (
(SELECT id FROM guilds WHERE guild = ?),
(SELECT id FROM channels WHERE channel = ?),
?
)
",
id,
channel_id,
todo.value
)
.execute(transaction.executor())
.await
.map_err(|e| {
warn!("Error creating todo: {:?}", e);
json!({"errors": vec!["Unknown error"]})
})?;
}
None => {
sqlx::query!(
"
INSERT INTO todos (guild_id, channel_id, value)
VALUES (
(SELECT id FROM guilds WHERE guild = ?),
NULL,
?
)
",
id,
todo.value
)
.execute(transaction.executor())
.await
.map_err(|e| {
warn!("Error creating todo: {:?}", e);
json!({"errors": vec!["Unknown error"]})
})?;
}
}
if let Err(e) = transaction.commit().await {
warn!("Couldn't commit transaction: {:?}", e);
return json_err!("Couldn't commit transaction.");
}
Ok(json!({}))
}
@ -75,26 +148,67 @@ pub async fn get_todo(
Ok(json!(todos))
}
#[patch("/api/guild/<id>/todos")]
#[patch("/api/guild/<guild_id>/todos/<todo_id>", data = "<todo>")]
pub async fn update_todo(
id: u64,
guild_id: u64,
todo_id: u64,
todo: Json<UpdateTodo>,
cookies: &CookieJar<'_>,
ctx: &State<Context>,
mut transaction: Transaction<'_>,
) -> JsonResult {
check_authorization(cookies, ctx.inner(), id).await?;
check_authorization(cookies, ctx.inner(), guild_id).await?;
if todo.value.len() > 2000 {
return json_err!("Value too long");
}
sqlx::query!(
"
UPDATE todos
SET value = ?
WHERE guild_id = ?
AND id = ?
",
todo.value,
guild_id,
todo_id,
)
.execute(transaction.executor())
.await
.map_err(|e| {
warn!("Error updating todo: {:?}", e);
json!({"errors": vec!["Unknown error"]})
})?;
Ok(json!({}))
}
#[delete("/api/guild/<id>/todos")]
#[delete("/api/guild/<guild_id>/todos/<todo_id>")]
pub async fn delete_todo(
id: u64,
guild_id: u64,
todo_id: u64,
cookies: &CookieJar<'_>,
ctx: &State<Context>,
mut transaction: Transaction<'_>,
) -> JsonResult {
check_authorization(cookies, ctx.inner(), id).await?;
check_authorization(cookies, ctx.inner(), guild_id).await?;
sqlx::query!(
"
DELETE FROM todos
WHERE guild_id = ?
AND id = ?
",
guild_id,
todo_id,
)
.execute(transaction.executor())
.await
.map_err(|e| {
warn!("Error deleting todo: {:?}", e);
json!({"errors": vec!["Unknown error"]})
})?;
Ok(json!({}))
}