diff options
| -rw-r--r-- | src/channel/repo.rs | 22 | ||||
| -rw-r--r-- | src/channel/routes.rs | 20 | ||||
| -rw-r--r-- | src/id.rs | 3 | ||||
| -rw-r--r-- | src/index.rs | 16 |
4 files changed, 54 insertions, 7 deletions
diff --git a/src/channel/repo.rs b/src/channel/repo.rs index e6a5e5c..bb39d6e 100644 --- a/src/channel/repo.rs +++ b/src/channel/repo.rs @@ -82,11 +82,31 @@ impl<'c> Channels<'c> { Ok(channels) } + + /// Unenrol a login from a channel. + pub async fn leave(&mut self, channel: &Id, login: &LoginId) -> Result<(), BoxedError> { + sqlx::query_scalar!( + r#" + delete + from channel_member + where channel = $1 + and login = $2 + returning 1 as "deleted: bool" + "#, + channel, + login, + ) + .fetch_one(&mut *self.0) + .await?; + + Ok(()) + } } /// Stable identifier for a [Channel]. Prefixed with `C`. -#[derive(Debug, sqlx::Type)] +#[derive(Debug, sqlx::Type, serde::Deserialize)] #[sqlx(transparent)] +#[serde(transparent)] pub struct Id(BaseId); impl From<BaseId> for Id { diff --git a/src/channel/routes.rs b/src/channel/routes.rs index c8d6c3f..4453a1e 100644 --- a/src/channel/routes.rs +++ b/src/channel/routes.rs @@ -1,16 +1,18 @@ use axum::{ - extract::{Form, State}, + extract::{Form, Path, State}, response::{IntoResponse, Redirect}, routing::post, Router, }; use sqlx::sqlite::SqlitePool; -use super::repo::Provider as _; +use super::repo::{Id as ChannelId, Provider as _}; use crate::{error::InternalError, login::repo::logins::Login}; pub fn router() -> Router<SqlitePool> { - Router::new().route("/create", post(on_create)) + Router::new() + .route("/create", post(on_create)) + .route("/:channel/leave", post(on_leave)) } #[derive(serde::Deserialize)] @@ -30,3 +32,15 @@ async fn on_create( Ok(Redirect::to("/")) } + +async fn on_leave( + State(db): State<SqlitePool>, + login: Login, + Path(channel): Path<ChannelId>, +) -> Result<impl IntoResponse, InternalError> { + let mut tx = db.begin().await?; + tx.channels().leave(&channel, &login.id).await?; + tx.commit().await?; + + Ok(Redirect::to("/")) +} @@ -27,8 +27,9 @@ pub const ID_SIZE: usize = 15; // // By convention, the prefix should be UPPERCASE - note that the alphabet for this // is entirely lowercase. -#[derive(Debug, Hash, PartialEq, Eq, sqlx::Type)] +#[derive(Debug, Hash, PartialEq, Eq, sqlx::Type, serde::Deserialize)] #[sqlx(transparent)] +#[serde(transparent)] pub struct Id(String); impl fmt::Display for Id { diff --git a/src/index.rs b/src/index.rs index 8ff9f7e..605d9f6 100644 --- a/src/index.rs +++ b/src/index.rs @@ -56,8 +56,20 @@ mod templates { html! { ul { @for channel in channels { - li { - (channel.name) "(" (channel.id) ")" + (channel_entry(&channel)) + } + } + } + } + + fn channel_entry(channel: &Channel) -> Markup { + let leave_url = format!("/{}/leave", channel.id); + html! { + li { + (channel.name) "(" (channel.id) ")" + form action=(leave_url) method="post" { + button { + "leave" } } } |
