From 4563f221bf61123b15f9608bb14e8f46db05e4f6 Mon Sep 17 00:00:00 2001 From: Owen Jacobson Date: Wed, 11 Sep 2024 19:14:22 -0400 Subject: Remove the notion of "channel members." This came out of a conversation with Kit. Their position, loosely, was that seeing scrollback when you look at a channel is useful, and since message delivery isn't meaningfully tied to membership (or at least doesn't have to be), what the hell is membership even doing? (I may have added that last part.) My take, on top of that, is that membership increases the amount of concepts we're committed to. We don't need that commitment yet. --- ...8dcbc711af986a8ad2228c309c9c2d085cc23faf87.json | 26 -------- ...8a7cdbca5582dde4a67c06d2134f33efcde194dcfe.json | 20 ------ ...11a01d9a530898094b2cb7a1fa03ff2393e044cb1d.json | 12 ++++ ...3bbcf03ef4e3e8105580591fee89c9e26f4839c4d1.json | 12 ---- ...de63396990a8cadb7dd6ac84cfeb7fc8770f125190.json | 26 -------- ...2b3d9939d4edb10e0e654e2a1b19949c3427522a08.json | 26 ++++++++ ...d76f0c34c759006d269ccccd6299c66b672076449d.json | 26 -------- .../20240911230415_no_channel_membership.sql | 1 + src/channel/repo.rs | 76 ++-------------------- src/channel/routes.rs | 43 ++---------- src/index.rs | 47 +++---------- 11 files changed, 56 insertions(+), 259 deletions(-) delete mode 100644 .sqlx/query-0e1323c097df563e78e6758dcbc711af986a8ad2228c309c9c2d085cc23faf87.json delete mode 100644 .sqlx/query-18f5f8a76476205ec485398a7cdbca5582dde4a67c06d2134f33efcde194dcfe.json create mode 100644 .sqlx/query-2722ea4a4c5134c209771211a01d9a530898094b2cb7a1fa03ff2393e044cb1d.json delete mode 100644 .sqlx/query-77cd8ff4b3617d74cba5303bbcf03ef4e3e8105580591fee89c9e26f4839c4d1.json delete mode 100644 .sqlx/query-8be5e4fd9a27f27efc9a45de63396990a8cadb7dd6ac84cfeb7fc8770f125190.json create mode 100644 .sqlx/query-8c78f7bbfb5522afa15c412b3d9939d4edb10e0e654e2a1b19949c3427522a08.json delete mode 100644 .sqlx/query-dbe468d2a7f64a45e70dfbd76f0c34c759006d269ccccd6299c66b672076449d.json create mode 100644 migrations/20240911230415_no_channel_membership.sql diff --git a/.sqlx/query-0e1323c097df563e78e6758dcbc711af986a8ad2228c309c9c2d085cc23faf87.json b/.sqlx/query-0e1323c097df563e78e6758dcbc711af986a8ad2228c309c9c2d085cc23faf87.json deleted file mode 100644 index 8dcd39f..0000000 --- a/.sqlx/query-0e1323c097df563e78e6758dcbc711af986a8ad2228c309c9c2d085cc23faf87.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n select\n channel.id as \"id: Id\",\n channel.name\n from channel\n join channel_member\n on (channel.id = channel_member.channel)\n where channel_member.login = $1\n order by channel.name\n ", - "describe": { - "columns": [ - { - "name": "id: Id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "name", - "ordinal": 1, - "type_info": "Text" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false, - false - ] - }, - "hash": "0e1323c097df563e78e6758dcbc711af986a8ad2228c309c9c2d085cc23faf87" -} diff --git a/.sqlx/query-18f5f8a76476205ec485398a7cdbca5582dde4a67c06d2134f33efcde194dcfe.json b/.sqlx/query-18f5f8a76476205ec485398a7cdbca5582dde4a67c06d2134f33efcde194dcfe.json deleted file mode 100644 index 1411ea6..0000000 --- a/.sqlx/query-18f5f8a76476205ec485398a7cdbca5582dde4a67c06d2134f33efcde194dcfe.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n delete\n from channel_member\n where channel = $1\n and login = $2\n returning 1 as \"deleted: bool\"\n ", - "describe": { - "columns": [ - { - "name": "deleted: bool", - "ordinal": 0, - "type_info": "Null" - } - ], - "parameters": { - "Right": 2 - }, - "nullable": [ - null - ] - }, - "hash": "18f5f8a76476205ec485398a7cdbca5582dde4a67c06d2134f33efcde194dcfe" -} diff --git a/.sqlx/query-2722ea4a4c5134c209771211a01d9a530898094b2cb7a1fa03ff2393e044cb1d.json b/.sqlx/query-2722ea4a4c5134c209771211a01d9a530898094b2cb7a1fa03ff2393e044cb1d.json new file mode 100644 index 0000000..704e480 --- /dev/null +++ b/.sqlx/query-2722ea4a4c5134c209771211a01d9a530898094b2cb7a1fa03ff2393e044cb1d.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "\n insert\n into channel (id, name)\n values ($1, $2)\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "2722ea4a4c5134c209771211a01d9a530898094b2cb7a1fa03ff2393e044cb1d" +} diff --git a/.sqlx/query-77cd8ff4b3617d74cba5303bbcf03ef4e3e8105580591fee89c9e26f4839c4d1.json b/.sqlx/query-77cd8ff4b3617d74cba5303bbcf03ef4e3e8105580591fee89c9e26f4839c4d1.json deleted file mode 100644 index 925340d..0000000 --- a/.sqlx/query-77cd8ff4b3617d74cba5303bbcf03ef4e3e8105580591fee89c9e26f4839c4d1.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n insert\n into channel_member (channel, login)\n values ($1, $2)\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 2 - }, - "nullable": [] - }, - "hash": "77cd8ff4b3617d74cba5303bbcf03ef4e3e8105580591fee89c9e26f4839c4d1" -} diff --git a/.sqlx/query-8be5e4fd9a27f27efc9a45de63396990a8cadb7dd6ac84cfeb7fc8770f125190.json b/.sqlx/query-8be5e4fd9a27f27efc9a45de63396990a8cadb7dd6ac84cfeb7fc8770f125190.json deleted file mode 100644 index 9d75dac..0000000 --- a/.sqlx/query-8be5e4fd9a27f27efc9a45de63396990a8cadb7dd6ac84cfeb7fc8770f125190.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n select\n channel.id as \"id: Id\",\n channel.name\n from channel\n except\n select\n channel.id as \"id: Id\",\n channel.name\n from channel\n join channel_member\n on (channel.id = channel_member.channel)\n where channel_member.login = $1\n order by channel.name\n ", - "describe": { - "columns": [ - { - "name": "id: Id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "name", - "ordinal": 1, - "type_info": "Text" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false, - false - ] - }, - "hash": "8be5e4fd9a27f27efc9a45de63396990a8cadb7dd6ac84cfeb7fc8770f125190" -} diff --git a/.sqlx/query-8c78f7bbfb5522afa15c412b3d9939d4edb10e0e654e2a1b19949c3427522a08.json b/.sqlx/query-8c78f7bbfb5522afa15c412b3d9939d4edb10e0e654e2a1b19949c3427522a08.json new file mode 100644 index 0000000..4d9051d --- /dev/null +++ b/.sqlx/query-8c78f7bbfb5522afa15c412b3d9939d4edb10e0e654e2a1b19949c3427522a08.json @@ -0,0 +1,26 @@ +{ + "db_name": "SQLite", + "query": "\n select\n channel.id as \"id: Id\",\n channel.name\n from channel\n order by channel.name\n ", + "describe": { + "columns": [ + { + "name": "id: Id", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "name", + "ordinal": 1, + "type_info": "Text" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false, + false + ] + }, + "hash": "8c78f7bbfb5522afa15c412b3d9939d4edb10e0e654e2a1b19949c3427522a08" +} diff --git a/.sqlx/query-dbe468d2a7f64a45e70dfbd76f0c34c759006d269ccccd6299c66b672076449d.json b/.sqlx/query-dbe468d2a7f64a45e70dfbd76f0c34c759006d269ccccd6299c66b672076449d.json deleted file mode 100644 index 3db94ca..0000000 --- a/.sqlx/query-dbe468d2a7f64a45e70dfbd76f0c34c759006d269ccccd6299c66b672076449d.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n insert\n into channel (id, name)\n values ($1, $2)\n returning id as \"id: Id\", name\n ", - "describe": { - "columns": [ - { - "name": "id: Id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "name", - "ordinal": 1, - "type_info": "Text" - } - ], - "parameters": { - "Right": 2 - }, - "nullable": [ - false, - false - ] - }, - "hash": "dbe468d2a7f64a45e70dfbd76f0c34c759006d269ccccd6299c66b672076449d" -} diff --git a/migrations/20240911230415_no_channel_membership.sql b/migrations/20240911230415_no_channel_membership.sql new file mode 100644 index 0000000..db5a054 --- /dev/null +++ b/migrations/20240911230415_no_channel_membership.sql @@ -0,0 +1 @@ +drop table channel_member; diff --git a/src/channel/repo.rs b/src/channel/repo.rs index a255305..a04cac5 100644 --- a/src/channel/repo.rs +++ b/src/channel/repo.rs @@ -2,8 +2,8 @@ use std::fmt; use sqlx::{sqlite::Sqlite, SqliteConnection, Transaction}; +use crate::error::BoxedError; use crate::id::Id as BaseId; -use crate::{error::BoxedError, login::repo::logins::Id as LoginId}; pub trait Provider { fn channels(&mut self) -> Channels; @@ -25,65 +25,25 @@ pub struct Channel { impl<'c> Channels<'c> { /// Create a new channel. - pub async fn create(&mut self, name: &str) -> Result { + pub async fn create(&mut self, name: &str) -> Result<(), BoxedError> { let id = Id::generate(); - let channel = sqlx::query_as!( - Channel, + sqlx::query!( r#" insert into channel (id, name) values ($1, $2) - returning id as "id: Id", name "#, id, name, ) - .fetch_one(&mut *self.0) - .await?; - - Ok(channel) - } - - /// Enrol a login in a channel. - pub async fn join(&mut self, channel: &Id, login: &LoginId) -> Result<(), BoxedError> { - sqlx::query!( - r#" - insert - into channel_member (channel, login) - values ($1, $2) - "#, - channel, - login, - ) .execute(&mut *self.0) .await?; Ok(()) } - pub async fn joined(&mut self, login: &LoginId) -> Result, BoxedError> { - let channels = sqlx::query_as!( - Channel, - r#" - select - channel.id as "id: Id", - channel.name - from channel - join channel_member - on (channel.id = channel_member.channel) - where channel_member.login = $1 - order by channel.name - "#, - login, - ) - .fetch_all(&mut *self.0) - .await?; - - Ok(channels) - } - - pub async fn unjoined(&mut self, login: &LoginId) -> Result, BoxedError> { + pub async fn all(&mut self) -> Result, BoxedError> { let channels = sqlx::query_as!( Channel, r#" @@ -91,42 +51,14 @@ impl<'c> Channels<'c> { channel.id as "id: Id", channel.name from channel - except - select - channel.id as "id: Id", - channel.name - from channel - join channel_member - on (channel.id = channel_member.channel) - where channel_member.login = $1 order by channel.name "#, - login, ) .fetch_all(&mut *self.0) .await?; 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`. diff --git a/src/channel/routes.rs b/src/channel/routes.rs index 3dc2b1a..014a57b 100644 --- a/src/channel/routes.rs +++ b/src/channel/routes.rs @@ -1,19 +1,16 @@ use axum::{ - extract::{Form, Path, State}, + extract::{Form, State}, response::{IntoResponse, Redirect}, routing::post, Router, }; use sqlx::sqlite::SqlitePool; -use super::repo::{Id as ChannelId, Provider as _}; +use super::repo::Provider as _; use crate::{error::InternalError, login::repo::logins::Login}; pub fn router() -> Router { - Router::new() - .route("/create", post(on_create)) - .route("/join", post(on_join)) - .route("/:channel/leave", post(on_leave)) + Router::new().route("/create", post(on_create)) } #[derive(serde::Deserialize)] @@ -23,41 +20,11 @@ struct CreateRequest { async fn on_create( State(db): State, - login: Login, + _: Login, // requires auth, but doesn't actually care who you are Form(form): Form, ) -> Result { let mut tx = db.begin().await?; - let channel = tx.channels().create(&form.name).await?; - tx.channels().join(&channel.id, &login.id).await?; - tx.commit().await?; - - Ok(Redirect::to("/")) -} - -#[derive(serde::Deserialize)] -struct JoinRequest { - channel: ChannelId, -} - -async fn on_join( - State(db): State, - login: Login, - Form(req): Form, -) -> Result { - let mut tx = db.begin().await?; - tx.channels().join(&req.channel, &login.id).await?; - tx.commit().await?; - - Ok(Redirect::to("/")) -} - -async fn on_leave( - State(db): State, - login: Login, - Path(channel): Path, -) -> Result { - let mut tx = db.begin().await?; - tx.channels().leave(&channel, &login.id).await?; + tx.channels().create(&form.name).await?; tx.commit().await?; Ok(Redirect::to("/")) diff --git a/src/index.rs b/src/index.rs index 9de91d5..9efd7cc 100644 --- a/src/index.rs +++ b/src/index.rs @@ -16,15 +16,10 @@ async fn index( async fn index_authenticated(db: SqlitePool, login: Login) -> Result { let mut tx = db.begin().await?; - let joined_channels = tx.channels().joined(&login.id).await?; - let unjoined_channels = tx.channels().unjoined(&login.id).await?; + let channels = tx.channels().all().await?; tx.commit().await?; - Ok(templates::authenticated( - login, - &joined_channels, - &unjoined_channels, - )) + Ok(templates::authenticated(login, &channels)) } pub fn router() -> Router { @@ -38,8 +33,7 @@ mod templates { pub fn authenticated<'c>( login: Login, - joined_channels: impl IntoIterator, - unjoined_channels: impl IntoIterator, + channels: impl IntoIterator, ) -> Markup { html! { (DOCTYPE) @@ -48,8 +42,7 @@ mod templates { } body { section { - (channel_list(joined_channels)) - (join_channel(unjoined_channels)) + (channel_list(channels)) (create_channel()) } section { @@ -59,44 +52,20 @@ mod templates { } } - fn channel_list<'c>(joined_channels: impl IntoIterator) -> Markup { + fn channel_list<'c>(channels: impl IntoIterator) -> Markup { html! { ul { - @for channel in joined_channels { - (joined_channel_entry(&channel)) + @for channel in channels { + (channel_list_entry(&channel)) } } } } - fn joined_channel_entry(channel: &Channel) -> Markup { - let leave_url = format!("/{}/leave", channel.id); + fn channel_list_entry(channel: &Channel) -> Markup { html! { li { (channel.name) " (" (channel.id) ")" - form action=(leave_url) method="post" { - button { - "leave" - } - } - } - } - } - - fn join_channel<'c>(unjoined_channels: impl IntoIterator) -> Markup { - html! { - form action="join" method="post" { - select name="channel" required { - option value="" { "channel" } - @for channel in unjoined_channels { - option value=(channel.id) { - (channel.name) " (" (channel.id) ")" - } - } - } - button { - "join" - } } } } -- cgit v1.2.3