summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/channel/repo.rs22
-rw-r--r--src/channel/routes.rs20
-rw-r--r--src/id.rs3
-rw-r--r--src/index.rs16
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("/"))
+}
diff --git a/src/id.rs b/src/id.rs
index 6dbdc30..4e12f2a 100644
--- a/src/id.rs
+++ b/src/id.rs
@@ -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"
}
}
}