summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/boot/handlers/boot/mod.rs (renamed from src/boot/routes/get.rs)3
-rw-r--r--src/boot/handlers/boot/test.rs (renamed from src/boot/routes/test.rs)17
-rw-r--r--src/boot/handlers/mod.rs3
-rw-r--r--src/boot/mod.rs2
-rw-r--r--src/boot/routes/mod.rs3
-rw-r--r--src/channel/handlers/create/mod.rs (renamed from src/channel/routes/post.rs)3
-rw-r--r--src/channel/handlers/create/test.rs (renamed from src/channel/routes/test.rs)53
-rw-r--r--src/channel/handlers/delete/mod.rs (renamed from src/channel/routes/channel/delete.rs)7
-rw-r--r--src/channel/handlers/delete/test.rs (renamed from src/channel/routes/channel/test/delete.rs)17
-rw-r--r--src/channel/handlers/mod.rs9
-rw-r--r--src/channel/handlers/send/mod.rs (renamed from src/channel/routes/channel/post.rs)6
-rw-r--r--src/channel/handlers/send/test.rs (renamed from src/channel/routes/channel/test/post.rs)14
-rw-r--r--src/channel/mod.rs2
-rw-r--r--src/channel/routes/channel/mod.rs9
-rw-r--r--src/channel/routes/channel/test/mod.rs2
-rw-r--r--src/channel/routes/mod.rs5
-rw-r--r--src/event/handlers/mod.rs3
-rw-r--r--src/event/handlers/stream/mod.rs (renamed from src/event/routes/get.rs)3
-rw-r--r--src/event/handlers/stream/test/channel.rs (renamed from src/event/routes/test/channel.rs)33
-rw-r--r--src/event/handlers/stream/test/invite.rs (renamed from src/event/routes/test/invite.rs)13
-rw-r--r--src/event/handlers/stream/test/message.rs (renamed from src/event/routes/test/message.rs)41
-rw-r--r--src/event/handlers/stream/test/mod.rs (renamed from src/event/routes/test/mod.rs)2
-rw-r--r--src/event/handlers/stream/test/resume.rs (renamed from src/event/routes/test/resume.rs)22
-rw-r--r--src/event/handlers/stream/test/setup.rs (renamed from src/event/routes/test/setup.rs)9
-rw-r--r--src/event/handlers/stream/test/token.rs (renamed from src/event/routes/test/token.rs)17
-rw-r--r--src/event/mod.rs2
-rw-r--r--src/event/routes/mod.rs3
-rw-r--r--src/invite/handlers/accept/mod.rs (renamed from src/invite/routes/invite/post.rs)7
-rw-r--r--src/invite/handlers/accept/test.rs (renamed from src/invite/routes/invite/test/post.rs)30
-rw-r--r--src/invite/handlers/get/mod.rs (renamed from src/invite/routes/invite/get.rs)7
-rw-r--r--src/invite/handlers/get/test.rs (renamed from src/invite/routes/invite/test/get.rs)12
-rw-r--r--src/invite/handlers/issue/mod.rs (renamed from src/invite/routes/post.rs)3
-rw-r--r--src/invite/handlers/issue/test.rs (renamed from src/invite/routes/test.rs)5
-rw-r--r--src/invite/handlers/mod.rs9
-rw-r--r--src/invite/mod.rs2
-rw-r--r--src/invite/routes/invite/mod.rs6
-rw-r--r--src/invite/routes/invite/test/mod.rs2
-rw-r--r--src/invite/routes/mod.rs4
-rw-r--r--src/message/handlers/delete/mod.rs55
-rw-r--r--src/message/handlers/delete/test.rs (renamed from src/message/routes/message/test.rs)13
-rw-r--r--src/message/handlers/mod.rs3
-rw-r--r--src/message/mod.rs2
-rw-r--r--src/message/routes/message/mod.rs61
-rw-r--r--src/message/routes/mod.rs1
-rw-r--r--src/routes.rs61
-rw-r--r--src/setup/handlers/mod.rs3
-rw-r--r--src/setup/handlers/setup/mod.rs (renamed from src/setup/routes/post.rs)3
-rw-r--r--src/setup/handlers/setup/test.rs (renamed from src/setup/routes/test.rs)17
-rw-r--r--src/setup/mod.rs2
-rw-r--r--src/setup/routes/mod.rs3
-rw-r--r--src/ui/handlers/asset.rs7
-rw-r--r--src/ui/handlers/channel.rs58
-rw-r--r--src/ui/handlers/index.rs (renamed from src/ui/routes/get.rs)0
-rw-r--r--src/ui/handlers/invite.rs53
-rw-r--r--src/ui/handlers/login.rs8
-rw-r--r--src/ui/handlers/me.rs30
-rw-r--r--src/ui/handlers/mod.rs15
-rw-r--r--src/ui/handlers/setup.rs41
-rw-r--r--src/ui/mod.rs2
-rw-r--r--src/ui/routes/ch/channel.rs60
-rw-r--r--src/ui/routes/ch/mod.rs1
-rw-r--r--src/ui/routes/invite/invite.rs55
-rw-r--r--src/ui/routes/invite/mod.rs4
-rw-r--r--src/ui/routes/login.rs10
-rw-r--r--src/ui/routes/me.rs32
-rw-r--r--src/ui/routes/mod.rs7
-rw-r--r--src/ui/routes/path.rs9
-rw-r--r--src/ui/routes/setup.rs43
-rw-r--r--src/user/handlers/login/mod.rs (renamed from src/user/routes/login/post.rs)3
-rw-r--r--src/user/handlers/login/test.rs (renamed from src/user/routes/login/test.rs)21
-rw-r--r--src/user/handlers/logout/mod.rs (renamed from src/user/routes/logout/post.rs)3
-rw-r--r--src/user/handlers/logout/test.rs (renamed from src/user/routes/logout/test.rs)12
-rw-r--r--src/user/handlers/mod.rs7
-rw-r--r--src/user/handlers/password/mod.rs (renamed from src/user/routes/password/post.rs)3
-rw-r--r--src/user/handlers/password/test.rs (renamed from src/user/routes/password/test.rs)5
-rw-r--r--src/user/mod.rs2
-rw-r--r--src/user/routes/login/mod.rs4
-rw-r--r--src/user/routes/logout/mod.rs4
-rw-r--r--src/user/routes/mod.rs3
-rw-r--r--src/user/routes/password/mod.rs4
80 files changed, 541 insertions, 579 deletions
diff --git a/src/boot/routes/get.rs b/src/boot/handlers/boot/mod.rs
index 4873b7a..010f57b 100644
--- a/src/boot/routes/get.rs
+++ b/src/boot/handlers/boot/mod.rs
@@ -5,6 +5,9 @@ use axum::{
use crate::{app::App, boot::Snapshot, error::Internal, token::extract::Identity, user::User};
+#[cfg(test)]
+mod test;
+
pub async fn handler(State(app): State<App>, identity: Identity) -> Result<Response, Internal> {
let snapshot = app.boot().snapshot().await?;
Ok(Response {
diff --git a/src/boot/routes/test.rs b/src/boot/handlers/boot/test.rs
index 55802fe..0a7622b 100644
--- a/src/boot/routes/test.rs
+++ b/src/boot/handlers/boot/test.rs
@@ -1,6 +1,5 @@
use axum::extract::State;
-use super::get;
use crate::test::fixtures;
#[tokio::test]
@@ -8,7 +7,7 @@ async fn returns_identity() {
let app = fixtures::scratch_app().await;
let viewer = fixtures::identity::fictitious();
- let response = get::handler(State(app), viewer.clone())
+ let response = super::handler(State(app), viewer.clone())
.await
.expect("boot always succeeds");
@@ -21,7 +20,7 @@ async fn includes_logins() {
let spectator = fixtures::user::create(&app, &fixtures::now()).await;
let viewer = fixtures::identity::fictitious();
- let response = get::handler(State(app), viewer)
+ let response = super::handler(State(app), viewer)
.await
.expect("boot always succeeds");
@@ -34,7 +33,7 @@ async fn includes_channels() {
let channel = fixtures::channel::create(&app, &fixtures::now()).await;
let viewer = fixtures::identity::fictitious();
- let response = get::handler(State(app), viewer)
+ let response = super::handler(State(app), viewer)
.await
.expect("boot always succeeds");
@@ -49,7 +48,7 @@ async fn includes_messages() {
let message = fixtures::message::send(&app, &channel, &sender, &fixtures::now()).await;
let viewer = fixtures::identity::fictitious();
- let response = get::handler(State(app), viewer)
+ let response = super::handler(State(app), viewer)
.await
.expect("boot always succeeds");
@@ -70,7 +69,7 @@ async fn excludes_expired_messages() {
.expect("expiry never fails");
let viewer = fixtures::identity::fictitious();
- let response = get::handler(State(app), viewer)
+ let response = super::handler(State(app), viewer)
.await
.expect("boot always succeeds");
@@ -90,7 +89,7 @@ async fn excludes_deleted_messages() {
.expect("deleting valid message succeeds");
let viewer = fixtures::identity::fictitious();
- let response = get::handler(State(app), viewer)
+ let response = super::handler(State(app), viewer)
.await
.expect("boot always succeeds");
@@ -108,7 +107,7 @@ async fn excludes_expired_channels() {
.expect("expiry never fails");
let viewer = fixtures::identity::fictitious();
- let response = get::handler(State(app), viewer)
+ let response = super::handler(State(app), viewer)
.await
.expect("boot always succeeds");
@@ -126,7 +125,7 @@ async fn excludes_deleted_channels() {
.expect("deleting a valid channel succeeds");
let viewer = fixtures::identity::fictitious();
- let response = get::handler(State(app), viewer)
+ let response = super::handler(State(app), viewer)
.await
.expect("boot always succeeds");
diff --git a/src/boot/handlers/mod.rs b/src/boot/handlers/mod.rs
new file mode 100644
index 0000000..194c4a9
--- /dev/null
+++ b/src/boot/handlers/mod.rs
@@ -0,0 +1,3 @@
+mod boot;
+
+pub use boot::handler as boot;
diff --git a/src/boot/mod.rs b/src/boot/mod.rs
index 2b74de1..48da4f0 100644
--- a/src/boot/mod.rs
+++ b/src/boot/mod.rs
@@ -5,7 +5,7 @@ use serde::Serialize;
use crate::{channel::Channel, event::Sequence, message::Message, user::User};
pub mod app;
-pub mod routes;
+pub mod handlers;
#[derive(serde::Serialize)]
pub struct Snapshot {
diff --git a/src/boot/routes/mod.rs b/src/boot/routes/mod.rs
deleted file mode 100644
index 60ad5d8..0000000
--- a/src/boot/routes/mod.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub mod get;
-#[cfg(test)]
-mod test;
diff --git a/src/channel/routes/post.rs b/src/channel/handlers/create/mod.rs
index 6ea9b61..2c860fc 100644
--- a/src/channel/routes/post.rs
+++ b/src/channel/handlers/create/mod.rs
@@ -13,6 +13,9 @@ use crate::{
token::extract::Identity,
};
+#[cfg(test)]
+mod test;
+
pub async fn handler(
State(app): State<App>,
_: Identity, // requires auth, but doesn't actually care who you are
diff --git a/src/channel/routes/test.rs b/src/channel/handlers/create/test.rs
index cba8f2e..3c770cf 100644
--- a/src/channel/routes/test.rs
+++ b/src/channel/handlers/create/test.rs
@@ -3,7 +3,6 @@ use std::future;
use axum::extract::{Json, State};
use futures::stream::StreamExt as _;
-use super::post;
use crate::{
channel::app,
name::Name,
@@ -21,9 +20,9 @@ async fn new_channel() {
// Call the endpoint
let name = fixtures::channel::propose();
- let request = post::Request { name: name.clone() };
- let post::Response(response) =
- post::handler(State(app.clone()), creator, fixtures::now(), Json(request))
+ let request = super::Request { name: name.clone() };
+ let super::Response(response) =
+ super::handler(State(app.clone()), creator, fixtures::now(), Json(request))
.await
.expect("creating a channel in an empty app succeeds");
@@ -67,11 +66,11 @@ async fn duplicate_name() {
// Call the endpoint
- let request = post::Request {
+ let request = super::Request {
name: channel.name.clone(),
};
- let post::Error(error) =
- post::handler(State(app.clone()), creator, fixtures::now(), Json(request))
+ let super::Error(error) =
+ super::handler(State(app.clone()), creator, fixtures::now(), Json(request))
.await
.expect_err("duplicate channel name should fail the request");
@@ -100,11 +99,11 @@ async fn conflicting_canonical_name() {
// Call the endpoint
- let request = post::Request {
+ let request = super::Request {
name: conflicting_name.clone(),
};
- let post::Error(error) =
- post::handler(State(app.clone()), creator, fixtures::now(), Json(request))
+ let super::Error(error) =
+ super::handler(State(app.clone()), creator, fixtures::now(), Json(request))
.await
.expect_err("duplicate channel name should fail the request");
@@ -126,11 +125,15 @@ async fn invalid_name() {
// Call the endpoint
let name = fixtures::channel::propose_invalid_name();
- let request = post::Request { name: name.clone() };
- let post::Error(error) =
- post::handler(State(app.clone()), creator, fixtures::now(), Json(request))
- .await
- .expect_err("invalid channel name should fail the request");
+ let request = super::Request { name: name.clone() };
+ let super::Error(error) = crate::channel::handlers::create::handler(
+ State(app.clone()),
+ creator,
+ fixtures::now(),
+ Json(request),
+ )
+ .await
+ .expect_err("invalid channel name should fail the request");
// Verify the structure of the response
@@ -150,8 +153,8 @@ async fn name_reusable_after_delete() {
// Call the endpoint (first time)
- let request = post::Request { name: name.clone() };
- let post::Response(response) = post::handler(
+ let request = super::Request { name: name.clone() };
+ let super::Response(response) = super::handler(
State(app.clone()),
creator.clone(),
fixtures::now(),
@@ -169,9 +172,9 @@ async fn name_reusable_after_delete() {
// Call the endpoint (second time)
- let request = post::Request { name: name.clone() };
- let post::Response(response) =
- post::handler(State(app.clone()), creator, fixtures::now(), Json(request))
+ let request = super::Request { name: name.clone() };
+ let super::Response(response) =
+ super::handler(State(app.clone()), creator, fixtures::now(), Json(request))
.await
.expect("creation succeeds after original channel deleted");
@@ -199,8 +202,8 @@ async fn name_reusable_after_expiry() {
// Call the endpoint (first time)
- let request = post::Request { name: name.clone() };
- let post::Response(_) = post::handler(
+ let request = super::Request { name: name.clone() };
+ let super::Response(_) = super::handler(
State(app.clone()),
creator.clone(),
fixtures::ancient(),
@@ -218,9 +221,9 @@ async fn name_reusable_after_expiry() {
// Call the endpoint (second time)
- let request = post::Request { name: name.clone() };
- let post::Response(response) =
- post::handler(State(app.clone()), creator, fixtures::now(), Json(request))
+ let request = super::Request { name: name.clone() };
+ let super::Response(response) =
+ super::handler(State(app.clone()), creator, fixtures::now(), Json(request))
.await
.expect("creation succeeds after original channel expired");
diff --git a/src/channel/routes/channel/delete.rs b/src/channel/handlers/delete/mod.rs
index 3db7772..b986bec 100644
--- a/src/channel/routes/channel/delete.rs
+++ b/src/channel/handlers/delete/mod.rs
@@ -6,15 +6,18 @@ use axum::{
use crate::{
app::App,
- channel::{self, app},
+ channel::{self, app, handlers::PathInfo},
clock::RequestedAt,
error::{Internal, NotFound},
token::extract::Identity,
};
+#[cfg(test)]
+mod test;
+
pub async fn handler(
State(app): State<App>,
- Path(channel): Path<super::PathInfo>,
+ Path(channel): Path<PathInfo>,
RequestedAt(deleted_at): RequestedAt,
_: Identity,
) -> Result<Response, Error> {
diff --git a/src/channel/routes/channel/test/delete.rs b/src/channel/handlers/delete/test.rs
index bd9261d..b1e42ea 100644
--- a/src/channel/routes/channel/test/delete.rs
+++ b/src/channel/handlers/delete/test.rs
@@ -1,9 +1,6 @@
use axum::extract::{Path, State};
-use crate::{
- channel::{app, routes::channel::delete},
- test::fixtures,
-};
+use crate::{channel::app, test::fixtures};
#[tokio::test]
pub async fn valid_channel() {
@@ -15,7 +12,7 @@ pub async fn valid_channel() {
// Send the request
let deleter = fixtures::identity::create(&app, &fixtures::now()).await;
- let response = delete::handler(
+ let response = super::handler(
State(app.clone()),
Path(channel.id.clone()),
fixtures::now(),
@@ -44,7 +41,7 @@ pub async fn invalid_channel_id() {
let deleter = fixtures::identity::create(&app, &fixtures::now()).await;
let channel = fixtures::channel::fictitious();
- let delete::Error(error) = delete::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
Path(channel.clone()),
fixtures::now(),
@@ -73,7 +70,7 @@ pub async fn channel_deleted() {
// Send the request
let deleter = fixtures::identity::create(&app, &fixtures::now()).await;
- let delete::Error(error) = delete::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
Path(channel.id.clone()),
fixtures::now(),
@@ -102,7 +99,7 @@ pub async fn channel_expired() {
// Send the request
let deleter = fixtures::identity::create(&app, &fixtures::now()).await;
- let delete::Error(error) = delete::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
Path(channel.id.clone()),
fixtures::now(),
@@ -136,7 +133,7 @@ pub async fn channel_purged() {
// Send the request
let deleter = fixtures::identity::create(&app, &fixtures::now()).await;
- let delete::Error(error) = delete::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
Path(channel.id.clone()),
fixtures::now(),
@@ -162,7 +159,7 @@ pub async fn channel_not_empty() {
// Send the request
let deleter = fixtures::identity::create(&app, &fixtures::now()).await;
- let delete::Error(error) = delete::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
Path(channel.id.clone()),
fixtures::now(),
diff --git a/src/channel/handlers/mod.rs b/src/channel/handlers/mod.rs
new file mode 100644
index 0000000..f2ffd0d
--- /dev/null
+++ b/src/channel/handlers/mod.rs
@@ -0,0 +1,9 @@
+mod create;
+mod delete;
+mod send;
+
+pub use create::handler as create;
+pub use delete::handler as delete;
+pub use send::handler as send;
+
+type PathInfo = crate::channel::Id;
diff --git a/src/channel/routes/channel/post.rs b/src/channel/handlers/send/mod.rs
index 2547122..aa241e2 100644
--- a/src/channel/routes/channel/post.rs
+++ b/src/channel/handlers/send/mod.rs
@@ -4,6 +4,7 @@ use axum::{
response::{self, IntoResponse},
};
+use crate::channel::handlers::PathInfo;
use crate::{
app::App,
clock::RequestedAt,
@@ -12,9 +13,12 @@ use crate::{
token::extract::Identity,
};
+#[cfg(test)]
+mod test;
+
pub async fn handler(
State(app): State<App>,
- Path(channel): Path<super::PathInfo>,
+ Path(channel): Path<PathInfo>,
RequestedAt(sent_at): RequestedAt,
identity: Identity,
Json(request): Json<Request>,
diff --git a/src/channel/routes/channel/test/post.rs b/src/channel/handlers/send/test.rs
index d9527ac..f43f901 100644
--- a/src/channel/routes/channel/test/post.rs
+++ b/src/channel/handlers/send/test.rs
@@ -2,7 +2,7 @@ use axum::extract::{Json, Path, State};
use futures::stream::{self, StreamExt as _};
use crate::{
- channel::{self, routes::channel::post},
+ channel,
event::Sequenced,
message::app::SendError,
test::fixtures::{self, future::Expect as _},
@@ -25,9 +25,9 @@ async fn messages_in_order() {
];
for (sent_at, body) in &requests {
- let request = post::Request { body: body.clone() };
+ let request = super::Request { body: body.clone() };
- let _ = post::handler(
+ let _ = super::handler(
State(app.clone()),
Path(channel.id.clone()),
sent_at.clone(),
@@ -71,10 +71,10 @@ async fn nonexistent_channel() {
let sent_at = fixtures::now();
let channel = channel::Id::generate();
- let request = post::Request {
+ let request = super::Request {
body: fixtures::message::propose(),
};
- let post::Error(error) = post::handler(
+ let super::Error(error) = super::handler(
State(app),
Path(channel.clone()),
sent_at,
@@ -109,10 +109,10 @@ async fn deleted_channel() {
let sent_at = fixtures::now();
let channel = channel::Id::generate();
- let request = post::Request {
+ let request = super::Request {
body: fixtures::message::propose(),
};
- let post::Error(error) = post::handler(
+ let super::Error(error) = super::handler(
State(app),
Path(channel.clone()),
sent_at,
diff --git a/src/channel/mod.rs b/src/channel/mod.rs
index feb00a9..bbaf33e 100644
--- a/src/channel/mod.rs
+++ b/src/channel/mod.rs
@@ -1,9 +1,9 @@
pub mod app;
pub mod event;
+pub mod handlers;
mod history;
mod id;
pub mod repo;
-pub mod routes;
mod snapshot;
mod validate;
diff --git a/src/channel/routes/channel/mod.rs b/src/channel/routes/channel/mod.rs
deleted file mode 100644
index 31a9142..0000000
--- a/src/channel/routes/channel/mod.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use crate::channel::Id;
-
-pub mod delete;
-pub mod post;
-
-#[cfg(test)]
-mod test;
-
-type PathInfo = Id;
diff --git a/src/channel/routes/channel/test/mod.rs b/src/channel/routes/channel/test/mod.rs
deleted file mode 100644
index 78bf86e..0000000
--- a/src/channel/routes/channel/test/mod.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-mod delete;
-mod post;
diff --git a/src/channel/routes/mod.rs b/src/channel/routes/mod.rs
deleted file mode 100644
index bd90721..0000000
--- a/src/channel/routes/mod.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-pub mod channel;
-pub mod post;
-
-#[cfg(test)]
-mod test;
diff --git a/src/event/handlers/mod.rs b/src/event/handlers/mod.rs
new file mode 100644
index 0000000..22d988c
--- /dev/null
+++ b/src/event/handlers/mod.rs
@@ -0,0 +1,3 @@
+mod stream;
+
+pub use stream::handler as stream;
diff --git a/src/event/routes/get.rs b/src/event/handlers/stream/mod.rs
index f6c91fa..d0d3f08 100644
--- a/src/event/routes/get.rs
+++ b/src/event/handlers/stream/mod.rs
@@ -15,6 +15,9 @@ use crate::{
token::{app::ValidateError, extract::Identity},
};
+#[cfg(test)]
+mod test;
+
pub async fn handler(
State(app): State<App>,
identity: Identity,
diff --git a/src/event/routes/test/channel.rs b/src/event/handlers/stream/test/channel.rs
index 0695ab1..187c3c3 100644
--- a/src/event/routes/test/channel.rs
+++ b/src/event/handlers/stream/test/channel.rs
@@ -2,10 +2,7 @@ use axum::extract::State;
use axum_extra::extract::Query;
use futures::{future, stream::StreamExt as _};
-use crate::{
- event::routes::get,
- test::fixtures::{self, future::Expect as _},
-};
+use crate::test::fixtures::{self, future::Expect as _};
#[tokio::test]
async fn creating() {
@@ -17,11 +14,11 @@ async fn creating() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -65,11 +62,11 @@ async fn previously_created() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -96,11 +93,11 @@ async fn expiring() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -140,11 +137,11 @@ async fn previously_expired() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -170,11 +167,11 @@ async fn deleting() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -214,11 +211,11 @@ async fn previously_deleted() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -256,11 +253,11 @@ async fn previously_purged() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
diff --git a/src/event/routes/test/invite.rs b/src/event/handlers/stream/test/invite.rs
index 1d1bec6..c8e12fb 100644
--- a/src/event/routes/test/invite.rs
+++ b/src/event/handlers/stream/test/invite.rs
@@ -2,10 +2,7 @@ use axum::extract::State;
use axum_extra::extract::Query;
use futures::{future, stream::StreamExt as _};
-use crate::{
- event::routes::get,
- test::fixtures::{self, future::Expect as _},
-};
+use crate::test::fixtures::{self, future::Expect as _};
#[tokio::test]
async fn accepting_invite() {
@@ -19,11 +16,11 @@ async fn accepting_invite() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -69,11 +66,11 @@ async fn previously_accepted_invite() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
diff --git a/src/event/routes/test/message.rs b/src/event/handlers/stream/test/message.rs
index 84a3aec..a80c896 100644
--- a/src/event/routes/test/message.rs
+++ b/src/event/handlers/stream/test/message.rs
@@ -5,10 +5,7 @@ use futures::{
stream::{self, StreamExt as _},
};
-use crate::{
- event::routes::get,
- test::fixtures::{self, future::Expect as _},
-};
+use crate::test::fixtures::{self, future::Expect as _};
#[tokio::test]
async fn sending() {
@@ -21,11 +18,11 @@ async fn sending() {
// Call the endpoint
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -80,11 +77,11 @@ async fn previously_sent() {
// Call the endpoint
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -126,11 +123,11 @@ async fn sent_in_multiple_channels() {
// Call the endpoint
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -168,11 +165,11 @@ async fn sent_sequentially() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -207,11 +204,11 @@ async fn expiring() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -253,11 +250,11 @@ async fn previously_expired() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -285,11 +282,11 @@ async fn deleting() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -331,11 +328,11 @@ async fn previously_deleted() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -375,11 +372,11 @@ async fn previously_purged() {
// Subscribe
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
diff --git a/src/event/routes/test/mod.rs b/src/event/handlers/stream/test/mod.rs
index e7e35f1..df43deb 100644
--- a/src/event/routes/test/mod.rs
+++ b/src/event/handlers/stream/test/mod.rs
@@ -4,3 +4,5 @@ mod message;
mod resume;
mod setup;
mod token;
+
+use super::{QueryParams, Response, handler};
diff --git a/src/event/routes/test/resume.rs b/src/event/handlers/stream/test/resume.rs
index 633eae3..34fee4d 100644
--- a/src/event/routes/test/resume.rs
+++ b/src/event/handlers/stream/test/resume.rs
@@ -5,7 +5,7 @@ use axum_extra::extract::Query;
use futures::stream::{self, StreamExt as _};
use crate::{
- event::{Sequenced as _, routes::get},
+ event::Sequenced as _,
test::fixtures::{self, future::Expect as _},
};
@@ -31,11 +31,11 @@ async fn resume() {
let resume_at = {
// First subscription
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber.clone(),
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -52,11 +52,11 @@ async fn resume() {
};
// Resume after disconnect
- let get::Response(resumed) = get::handler(
+ let super::Response(resumed) = super::handler(
State(app),
subscriber,
Some(resume_at.into()),
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -113,11 +113,11 @@ async fn serial_resume() {
// First subscription
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber.clone(),
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -156,11 +156,11 @@ async fn serial_resume() {
];
// Second subscription
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber.clone(),
Some(resume_at.into()),
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -199,11 +199,11 @@ async fn serial_resume() {
];
// Third subscription
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber.clone(),
Some(resume_at.into()),
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
diff --git a/src/event/routes/test/setup.rs b/src/event/handlers/stream/test/setup.rs
index 1170fe4..5335055 100644
--- a/src/event/routes/test/setup.rs
+++ b/src/event/handlers/stream/test/setup.rs
@@ -2,10 +2,7 @@ use axum::extract::State;
use axum_extra::extract::Query;
use futures::{future, stream::StreamExt as _};
-use crate::{
- event::routes::get,
- test::fixtures::{self, future::Expect as _},
-};
+use crate::test::fixtures::{self, future::Expect as _};
// There's no test for this in subscribe-then-setup order because creating an
// identity to subscribe with also completes initial setup, preventing the
@@ -29,11 +26,11 @@ async fn previously_completed() {
// Subscribe to events
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
diff --git a/src/event/routes/test/token.rs b/src/event/handlers/stream/test/token.rs
index a467de5..2008323 100644
--- a/src/event/routes/test/token.rs
+++ b/src/event/handlers/stream/test/token.rs
@@ -2,10 +2,7 @@ use axum::extract::State;
use axum_extra::extract::Query;
use futures::{future, stream::StreamExt as _};
-use crate::{
- event::routes::get,
- test::fixtures::{self, future::Expect as _},
-};
+use crate::test::fixtures::{self, future::Expect as _};
#[tokio::test]
async fn terminates_on_token_expiry() {
@@ -22,11 +19,11 @@ async fn terminates_on_token_expiry() {
let subscriber =
fixtures::identity::logged_in(&app, &subscriber_creds, &fixtures::ancient()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber,
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -67,11 +64,11 @@ async fn terminates_on_logout() {
let subscriber = fixtures::identity::create(&app, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber.clone(),
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
@@ -115,11 +112,11 @@ async fn terminates_on_password_change() {
let cookie = fixtures::cookie::logged_in(&app, &creds, &fixtures::now()).await;
let subscriber = fixtures::identity::from_cookie(&app, &cookie, &fixtures::now()).await;
- let get::Response(events) = get::handler(
+ let super::Response(events) = super::handler(
State(app.clone()),
subscriber.clone(),
None,
- Query(get::QueryParams { resume_point }),
+ Query(super::QueryParams { resume_point }),
)
.await
.expect("subscribe never fails");
diff --git a/src/event/mod.rs b/src/event/mod.rs
index ff30dc7..6657243 100644
--- a/src/event/mod.rs
+++ b/src/event/mod.rs
@@ -7,8 +7,8 @@ use crate::{channel, message, user};
pub mod app;
mod broadcaster;
mod extract;
+pub mod handlers;
pub mod repo;
-pub mod routes;
mod sequence;
pub use self::{
diff --git a/src/event/routes/mod.rs b/src/event/routes/mod.rs
deleted file mode 100644
index 60ad5d8..0000000
--- a/src/event/routes/mod.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub mod get;
-#[cfg(test)]
-mod test;
diff --git a/src/invite/routes/invite/post.rs b/src/invite/handlers/accept/mod.rs
index 58d15c2..0d5f08a 100644
--- a/src/invite/routes/invite/post.rs
+++ b/src/invite/handlers/accept/mod.rs
@@ -8,17 +8,20 @@ use crate::{
app::App,
clock::RequestedAt,
error::{Internal, NotFound},
- invite::app,
+ invite::{app, handlers::PathInfo},
name::Name,
token::extract::IdentityCookie,
user::{Password, User},
};
+#[cfg(test)]
+mod test;
+
pub async fn handler(
State(app): State<App>,
RequestedAt(accepted_at): RequestedAt,
identity: IdentityCookie,
- Path(invite): Path<super::PathInfo>,
+ Path(invite): Path<PathInfo>,
Json(request): Json<Request>,
) -> Result<(IdentityCookie, Json<User>), Error> {
let (login, secret) = app
diff --git a/src/invite/routes/invite/test/post.rs b/src/invite/handlers/accept/test.rs
index b204b32..cb13900 100644
--- a/src/invite/routes/invite/test/post.rs
+++ b/src/invite/handlers/accept/test.rs
@@ -1,10 +1,6 @@
use axum::extract::{Json, Path, State};
-use crate::{
- invite::{app::AcceptError, routes::invite::post},
- name::Name,
- test::fixtures,
-};
+use crate::{invite::app::AcceptError, name::Name, test::fixtures};
#[tokio::test]
async fn valid_invite() {
@@ -18,11 +14,11 @@ async fn valid_invite() {
let (name, password) = fixtures::user::propose();
let identity = fixtures::cookie::not_logged_in();
- let request = post::Request {
+ let request = super::Request {
name: name.clone(),
password: password.clone(),
};
- let (identity, Json(response)) = post::handler(
+ let (identity, Json(response)) = super::handler(
State(app.clone()),
fixtures::now(),
identity,
@@ -70,11 +66,11 @@ async fn nonexistent_invite() {
let (name, password) = fixtures::user::propose();
let identity = fixtures::cookie::not_logged_in();
- let request = post::Request {
+ let request = super::Request {
name: name.clone(),
password: password.clone(),
};
- let post::Error(error) = post::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
fixtures::now(),
identity,
@@ -106,11 +102,11 @@ async fn expired_invite() {
let (name, password) = fixtures::user::propose();
let identity = fixtures::cookie::not_logged_in();
- let request = post::Request {
+ let request = super::Request {
name: name.clone(),
password: password.clone(),
};
- let post::Error(error) = post::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
fixtures::now(),
identity,
@@ -143,11 +139,11 @@ async fn accepted_invite() {
let (name, password) = fixtures::user::propose();
let identity = fixtures::cookie::not_logged_in();
- let request = post::Request {
+ let request = super::Request {
name: name.clone(),
password: password.clone(),
};
- let post::Error(error) = post::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
fixtures::now(),
identity,
@@ -186,11 +182,11 @@ async fn conflicting_name() {
let password = fixtures::user::propose_password();
let identity = fixtures::cookie::not_logged_in();
- let request = post::Request {
+ let request = super::Request {
name: conflicting_name.clone(),
password: password.clone(),
};
- let post::Error(error) = post::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
fixtures::now(),
identity,
@@ -220,11 +216,11 @@ async fn invalid_name() {
let name = fixtures::user::propose_invalid_name();
let password = fixtures::user::propose_password();
let identity = fixtures::cookie::not_logged_in();
- let request = post::Request {
+ let request = super::Request {
name: name.clone(),
password: password.clone(),
};
- let post::Error(error) = post::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
fixtures::now(),
identity,
diff --git a/src/invite/routes/invite/get.rs b/src/invite/handlers/get/mod.rs
index f862833..bb72586 100644
--- a/src/invite/routes/invite/get.rs
+++ b/src/invite/handlers/get/mod.rs
@@ -6,12 +6,15 @@ use axum::{
use crate::{
app::App,
error::{Internal, NotFound},
- invite::{Id, Summary},
+ invite::{Id, Summary, handlers::PathInfo},
};
+#[cfg(test)]
+mod test;
+
pub async fn handler(
State(app): State<App>,
- Path(invite): Path<super::PathInfo>,
+ Path(invite): Path<PathInfo>,
) -> Result<Json<Summary>, Error> {
app.invites()
.get(&invite)
diff --git a/src/invite/routes/invite/test/get.rs b/src/invite/handlers/get/test.rs
index 0dc8a79..0f2f725 100644
--- a/src/invite/routes/invite/test/get.rs
+++ b/src/invite/handlers/get/test.rs
@@ -1,6 +1,6 @@
use axum::extract::{Json, Path, State};
-use crate::{invite::routes::invite::get, test::fixtures};
+use crate::test::fixtures;
#[tokio::test]
async fn valid_invite() {
@@ -12,7 +12,7 @@ async fn valid_invite() {
// Call endpoint
- let Json(response) = get::handler(State(app), Path(invite.id))
+ let Json(response) = super::handler(State(app), Path(invite.id))
.await
.expect("get for an existing invite succeeds");
@@ -31,13 +31,13 @@ async fn nonexistent_invite() {
// Call endpoint
let invite = fixtures::invite::fictitious();
- let error = get::handler(State(app), Path(invite.clone()))
+ let error = super::handler(State(app), Path(invite.clone()))
.await
.expect_err("get for a nonexistent invite fails");
// Verify response
- assert!(matches!(error, get::Error::NotFound(error_id) if invite == error_id));
+ assert!(matches!(error, super::Error::NotFound(error_id) if invite == error_id));
}
#[tokio::test]
@@ -55,11 +55,11 @@ async fn expired_invite() {
// Call endpoint
- let error = get::handler(State(app), Path(invite.id.clone()))
+ let error = super::handler(State(app), Path(invite.id.clone()))
.await
.expect_err("get for an expired invite fails");
// Verify response
- assert!(matches!(error, get::Error::NotFound(error_id) if invite.id == error_id));
+ assert!(matches!(error, super::Error::NotFound(error_id) if invite.id == error_id));
}
diff --git a/src/invite/routes/post.rs b/src/invite/handlers/issue/mod.rs
index f7ca76c..6085f7a 100644
--- a/src/invite/routes/post.rs
+++ b/src/invite/handlers/issue/mod.rs
@@ -4,6 +4,9 @@ use crate::{
app::App, clock::RequestedAt, error::Internal, invite::Invite, token::extract::Identity,
};
+#[cfg(test)]
+mod test;
+
pub async fn handler(
State(app): State<App>,
RequestedAt(issued_at): RequestedAt,
diff --git a/src/invite/routes/test.rs b/src/invite/handlers/issue/test.rs
index 4ea8a3d..2bf5400 100644
--- a/src/invite/routes/test.rs
+++ b/src/invite/handlers/issue/test.rs
@@ -1,6 +1,5 @@
use axum::extract::{Json, State};
-use super::post;
use crate::test::fixtures;
#[tokio::test]
@@ -13,11 +12,11 @@ async fn create_invite() {
// Call the endpoint
- let Json(invite) = post::handler(
+ let Json(invite) = super::handler(
State(app),
issued_at.clone(),
issuer.clone(),
- Json(post::Request {}),
+ Json(super::Request {}),
)
.await
.expect("creating an invite always succeeds");
diff --git a/src/invite/handlers/mod.rs b/src/invite/handlers/mod.rs
new file mode 100644
index 0000000..07a2bbe
--- /dev/null
+++ b/src/invite/handlers/mod.rs
@@ -0,0 +1,9 @@
+mod accept;
+mod get;
+mod issue;
+
+type PathInfo = crate::invite::Id;
+
+pub use accept::handler as accept;
+pub use get::handler as get;
+pub use issue::handler as issue;
diff --git a/src/invite/mod.rs b/src/invite/mod.rs
index 3932eea..74b9ceb 100644
--- a/src/invite/mod.rs
+++ b/src/invite/mod.rs
@@ -1,9 +1,9 @@
use crate::{clock::DateTime, normalize::nfc, user};
pub mod app;
+pub mod handlers;
mod id;
mod repo;
-pub mod routes;
pub use self::id::Id;
diff --git a/src/invite/routes/invite/mod.rs b/src/invite/routes/invite/mod.rs
deleted file mode 100644
index c22029a..0000000
--- a/src/invite/routes/invite/mod.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-pub mod get;
-pub mod post;
-#[cfg(test)]
-pub mod test;
-
-type PathInfo = crate::invite::Id;
diff --git a/src/invite/routes/invite/test/mod.rs b/src/invite/routes/invite/test/mod.rs
deleted file mode 100644
index d6c1f06..0000000
--- a/src/invite/routes/invite/test/mod.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-mod get;
-mod post;
diff --git a/src/invite/routes/mod.rs b/src/invite/routes/mod.rs
deleted file mode 100644
index 8747a4e..0000000
--- a/src/invite/routes/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-pub mod invite;
-pub mod post;
-#[cfg(test)]
-mod test;
diff --git a/src/message/handlers/delete/mod.rs b/src/message/handlers/delete/mod.rs
new file mode 100644
index 0000000..5eac4eb
--- /dev/null
+++ b/src/message/handlers/delete/mod.rs
@@ -0,0 +1,55 @@
+use axum::{
+ extract::{Json, Path, State},
+ http::StatusCode,
+ response::{self, IntoResponse},
+};
+
+use crate::{
+ app::App,
+ clock::RequestedAt,
+ error::{Internal, NotFound},
+ message::{self, app::DeleteError},
+ token::extract::Identity,
+};
+
+#[cfg(test)]
+mod test;
+
+pub async fn handler(
+ State(app): State<App>,
+ Path(message): Path<message::Id>,
+ RequestedAt(deleted_at): RequestedAt,
+ identity: Identity,
+) -> Result<Response, Error> {
+ app.messages()
+ .delete(&identity.user, &message, &deleted_at)
+ .await?;
+
+ Ok(Response { id: message })
+}
+
+#[derive(Debug, serde::Serialize)]
+pub struct Response {
+ pub id: message::Id,
+}
+
+impl IntoResponse for Response {
+ fn into_response(self) -> response::Response {
+ (StatusCode::ACCEPTED, Json(self)).into_response()
+ }
+}
+
+#[derive(Debug, thiserror::Error)]
+#[error(transparent)]
+pub struct Error(#[from] pub DeleteError);
+
+impl IntoResponse for Error {
+ fn into_response(self) -> response::Response {
+ let Self(error) = self;
+ match error {
+ DeleteError::NotSender(_) => (StatusCode::FORBIDDEN, error.to_string()).into_response(),
+ DeleteError::NotFound(_) | DeleteError::Deleted(_) => NotFound(error).into_response(),
+ DeleteError::Database(_) => Internal::from(error).into_response(),
+ }
+ }
+}
diff --git a/src/message/routes/message/test.rs b/src/message/handlers/delete/test.rs
index 1888be7..15aa2c2 100644
--- a/src/message/routes/message/test.rs
+++ b/src/message/handlers/delete/test.rs
@@ -1,6 +1,5 @@
use axum::extract::{Path, State};
-use super::delete;
use crate::{message::app, test::fixtures};
#[tokio::test]
@@ -14,7 +13,7 @@ pub async fn delete_message() {
// Send the request
- let response = delete::handler(
+ let response = super::handler(
State(app.clone()),
Path(message.id.clone()),
fixtures::now(),
@@ -43,7 +42,7 @@ pub async fn delete_invalid_message_id() {
let deleter = fixtures::identity::create(&app, &fixtures::now()).await;
let message = fixtures::message::fictitious();
- let delete::Error(error) = delete::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
Path(message.clone()),
fixtures::now(),
@@ -74,7 +73,7 @@ pub async fn delete_deleted() {
// Send the request
let deleter = fixtures::identity::create(&app, &fixtures::now()).await;
- let delete::Error(error) = delete::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
Path(message.id.clone()),
fixtures::now(),
@@ -105,7 +104,7 @@ pub async fn delete_expired() {
// Send the request
let deleter = fixtures::identity::create(&app, &fixtures::now()).await;
- let delete::Error(error) = delete::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
Path(message.id.clone()),
fixtures::now(),
@@ -141,7 +140,7 @@ pub async fn delete_purged() {
// Send the request
let deleter = fixtures::identity::create(&app, &fixtures::now()).await;
- let delete::Error(error) = delete::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
Path(message.id.clone()),
fixtures::now(),
@@ -167,7 +166,7 @@ pub async fn delete_not_sender() {
// Send the request
let deleter = fixtures::identity::create(&app, &fixtures::now()).await;
- let delete::Error(error) = delete::handler(
+ let super::Error(error) = super::handler(
State(app.clone()),
Path(message.id.clone()),
fixtures::now(),
diff --git a/src/message/handlers/mod.rs b/src/message/handlers/mod.rs
new file mode 100644
index 0000000..7e78475
--- /dev/null
+++ b/src/message/handlers/mod.rs
@@ -0,0 +1,3 @@
+mod delete;
+
+pub use delete::handler as delete;
diff --git a/src/message/mod.rs b/src/message/mod.rs
index fbaa4a3..e1643e6 100644
--- a/src/message/mod.rs
+++ b/src/message/mod.rs
@@ -1,10 +1,10 @@
pub mod app;
mod body;
pub mod event;
+pub mod handlers;
mod history;
mod id;
pub mod repo;
-pub mod routes;
mod snapshot;
pub use self::{body::Body, event::Event, history::History, id::Id, snapshot::Message};
diff --git a/src/message/routes/message/mod.rs b/src/message/routes/message/mod.rs
deleted file mode 100644
index a05d344..0000000
--- a/src/message/routes/message/mod.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-#[cfg(test)]
-mod test;
-
-pub mod delete {
- use axum::{
- extract::{Json, Path, State},
- http::StatusCode,
- response::{self, IntoResponse},
- };
-
- use crate::{
- app::App,
- clock::RequestedAt,
- error::{Internal, NotFound},
- message::{self, app::DeleteError},
- token::extract::Identity,
- };
-
- pub async fn handler(
- State(app): State<App>,
- Path(message): Path<message::Id>,
- RequestedAt(deleted_at): RequestedAt,
- identity: Identity,
- ) -> Result<Response, Error> {
- app.messages()
- .delete(&identity.user, &message, &deleted_at)
- .await?;
-
- Ok(Response { id: message })
- }
-
- #[derive(Debug, serde::Serialize)]
- pub struct Response {
- pub id: message::Id,
- }
-
- impl IntoResponse for Response {
- fn into_response(self) -> response::Response {
- (StatusCode::ACCEPTED, Json(self)).into_response()
- }
- }
-
- #[derive(Debug, thiserror::Error)]
- #[error(transparent)]
- pub struct Error(#[from] pub DeleteError);
-
- impl IntoResponse for Error {
- fn into_response(self) -> response::Response {
- let Self(error) = self;
- match error {
- DeleteError::NotSender(_) => {
- (StatusCode::FORBIDDEN, error.to_string()).into_response()
- }
- DeleteError::NotFound(_) | DeleteError::Deleted(_) => {
- NotFound(error).into_response()
- }
- DeleteError::Database(_) => Internal::from(error).into_response(),
- }
- }
- }
-}
diff --git a/src/message/routes/mod.rs b/src/message/routes/mod.rs
deleted file mode 100644
index e216a50..0000000
--- a/src/message/routes/mod.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod message;
diff --git a/src/routes.rs b/src/routes.rs
index 5bb5f91..1e66582 100644
--- a/src/routes.rs
+++ b/src/routes.rs
@@ -9,56 +9,35 @@ use crate::{app::App, boot, channel, event, expire, invite, message, setup, ui,
pub fn routes(app: &App) -> Router<App> {
// UI routes that can be accessed before the administrator completes setup.
let ui_bootstrap = Router::new()
- .route("/{*path}", get(ui::routes::path::get::handler))
- .route("/setup", get(ui::routes::setup::get::handler));
+ .route("/{*path}", get(ui::handlers::asset))
+ .route("/setup", get(ui::handlers::setup));
// UI routes that require the administrator to complete setup first.
let ui_setup_required = Router::new()
- .route("/", get(ui::routes::get::handler))
- .route("/ch/{channel}", get(ui::routes::ch::channel::get::handler))
- .route(
- "/invite/{invite}",
- get(ui::routes::invite::invite::get::handler),
- )
- .route("/login", get(ui::routes::login::get::handler))
- .route("/me", get(ui::routes::me::get::handler))
+ .route("/", get(ui::handlers::index))
+ .route("/ch/{channel}", get(ui::handlers::channel))
+ .route("/invite/{invite}", get(ui::handlers::invite))
+ .route("/login", get(ui::handlers::login))
+ .route("/me", get(ui::handlers::me))
.route_layer(crate::setup::Required(app.clone()).with_fallback(Redirect::to("/setup")));
// API routes that can run before the administrator completes setup.
- let api_bootstrap = Router::new().route("/api/setup", post(setup::routes::post::handler));
+ let api_bootstrap = Router::new().route("/api/setup", post(setup::handlers::setup));
// API routes that require the administrator to complete setup first.
let api_setup_required = Router::new()
- .route("/api/auth/login", post(user::routes::login::post::handler))
- .route(
- "/api/auth/logout",
- post(user::routes::logout::post::handler),
- )
- .route("/api/boot", get(boot::routes::get::handler))
- .route("/api/channels", post(channel::routes::post::handler))
- .route(
- "/api/channels/{channel}",
- post(channel::routes::channel::post::handler),
- )
- .route(
- "/api/channels/{channel}",
- delete(channel::routes::channel::delete::handler),
- )
- .route("/api/events", get(event::routes::get::handler))
- .route("/api/invite", post(invite::routes::post::handler))
- .route(
- "/api/invite/{invite}",
- get(invite::routes::invite::get::handler),
- )
- .route(
- "/api/invite/{invite}",
- post(invite::routes::invite::post::handler),
- )
- .route(
- "/api/messages/{message}",
- delete(message::routes::message::delete::handler),
- )
- .route("/api/password", post(user::routes::password::post::handler))
+ .route("/api/auth/login", post(user::handlers::login))
+ .route("/api/auth/logout", post(user::handlers::logout))
+ .route("/api/boot", get(boot::handlers::boot))
+ .route("/api/channels", post(channel::handlers::create))
+ .route("/api/channels/{channel}", post(channel::handlers::send))
+ .route("/api/channels/{channel}", delete(channel::handlers::delete))
+ .route("/api/events", get(event::handlers::stream))
+ .route("/api/invite", post(invite::handlers::issue))
+ .route("/api/invite/{invite}", get(invite::handlers::get))
+ .route("/api/invite/{invite}", post(invite::handlers::accept))
+ .route("/api/messages/{message}", delete(message::handlers::delete))
+ .route("/api/password", post(user::handlers::change_password))
// Run expiry whenever someone accesses the API. This was previously a blanket middleware
// affecting the whole service, but loading the client makes a several requests before the
// client can completely load, each of which was triggering expiry. There is absolutely no
diff --git a/src/setup/handlers/mod.rs b/src/setup/handlers/mod.rs
new file mode 100644
index 0000000..3d4a4e6
--- /dev/null
+++ b/src/setup/handlers/mod.rs
@@ -0,0 +1,3 @@
+mod setup;
+
+pub use setup::handler as setup;
diff --git a/src/setup/routes/post.rs b/src/setup/handlers/setup/mod.rs
index 0ff5d69..cbb3072 100644
--- a/src/setup/routes/post.rs
+++ b/src/setup/handlers/setup/mod.rs
@@ -14,6 +14,9 @@ use crate::{
user::{Password, User},
};
+#[cfg(test)]
+mod test;
+
pub async fn handler(
State(app): State<App>,
RequestedAt(setup_at): RequestedAt,
diff --git a/src/setup/routes/test.rs b/src/setup/handlers/setup/test.rs
index e9f5cd6..8243ac3 100644
--- a/src/setup/routes/test.rs
+++ b/src/setup/handlers/setup/test.rs
@@ -1,6 +1,5 @@
use axum::extract::{Json, State};
-use super::post;
use crate::{setup::app, test::fixtures};
#[tokio::test]
@@ -12,12 +11,12 @@ async fn fresh_instance() {
// Call the endpoint
let identity = fixtures::cookie::not_logged_in();
let (name, password) = fixtures::user::propose();
- let request = post::Request {
+ let request = super::Request {
name: name.clone(),
password: password.clone(),
};
let (identity, Json(response)) =
- post::handler(State(app.clone()), fixtures::now(), identity, Json(request))
+ super::handler(State(app.clone()), fixtures::now(), identity, Json(request))
.await
.expect("setup in a fresh app succeeds");
@@ -57,9 +56,9 @@ async fn login_exists() {
// Call the endpoint
let identity = fixtures::cookie::not_logged_in();
let (name, password) = fixtures::user::propose();
- let request = post::Request { name, password };
- let post::Error(error) =
- post::handler(State(app.clone()), fixtures::now(), identity, Json(request))
+ let request = super::Request { name, password };
+ let super::Error(error) =
+ super::handler(State(app.clone()), fixtures::now(), identity, Json(request))
.await
.expect_err("setup in a populated app fails");
@@ -79,12 +78,12 @@ async fn invalid_name() {
let name = fixtures::user::propose_invalid_name();
let password = fixtures::user::propose_password();
let identity = fixtures::cookie::not_logged_in();
- let request = post::Request {
+ let request = super::Request {
name: name.clone(),
password: password.clone(),
};
- let post::Error(error) =
- post::handler(State(app.clone()), fixtures::now(), identity, Json(request))
+ let super::Error(error) =
+ super::handler(State(app.clone()), fixtures::now(), identity, Json(request))
.await
.expect_err("setup with an invalid name fails");
diff --git a/src/setup/mod.rs b/src/setup/mod.rs
index e741a60..f5d12df 100644
--- a/src/setup/mod.rs
+++ b/src/setup/mod.rs
@@ -1,6 +1,6 @@
pub mod app;
+pub mod handlers;
pub mod repo;
mod required;
-pub mod routes;
pub use self::required::Required;
diff --git a/src/setup/routes/mod.rs b/src/setup/routes/mod.rs
deleted file mode 100644
index e94a249..0000000
--- a/src/setup/routes/mod.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub mod post;
-#[cfg(test)]
-mod test;
diff --git a/src/ui/handlers/asset.rs b/src/ui/handlers/asset.rs
new file mode 100644
index 0000000..1d5b8be
--- /dev/null
+++ b/src/ui/handlers/asset.rs
@@ -0,0 +1,7 @@
+use axum::extract::Path;
+
+use crate::ui::assets::{Asset, Assets, Error};
+
+pub async fn handler(Path(path): Path<String>) -> Result<Asset, Error> {
+ Assets::load(path)
+}
diff --git a/src/ui/handlers/channel.rs b/src/ui/handlers/channel.rs
new file mode 100644
index 0000000..d3199dd
--- /dev/null
+++ b/src/ui/handlers/channel.rs
@@ -0,0 +1,58 @@
+use axum::{
+ extract::{Path, State},
+ response::{self, IntoResponse, Redirect},
+};
+
+use crate::{
+ app::App,
+ channel::{self, app},
+ error::Internal,
+ token::extract::Identity,
+ ui::{
+ assets::{Asset, Assets},
+ error::NotFound,
+ },
+};
+
+pub async fn handler(
+ State(app): State<App>,
+ identity: Option<Identity>,
+ Path(channel): Path<channel::Id>,
+) -> Result<Asset, Error> {
+ let _ = identity.ok_or(Error::NotLoggedIn)?;
+ app.channels().get(&channel).await.map_err(Error::from)?;
+
+ Assets::index().map_err(Error::Internal)
+}
+
+#[derive(Debug, thiserror::Error)]
+pub enum Error {
+ #[error("channel not found")]
+ NotFound,
+ #[error("not logged in")]
+ NotLoggedIn,
+ #[error("{0}")]
+ Internal(Internal),
+}
+
+impl From<app::Error> for Error {
+ fn from(error: app::Error) -> Self {
+ match error {
+ app::Error::NotFound(_) | app::Error::Deleted(_) => Self::NotFound,
+ other => Self::Internal(other.into()),
+ }
+ }
+}
+
+impl IntoResponse for Error {
+ fn into_response(self) -> response::Response {
+ match self {
+ Self::NotFound => match Assets::index() {
+ Ok(asset) => NotFound(asset).into_response(),
+ Err(internal) => internal.into_response(),
+ },
+ Self::NotLoggedIn => Redirect::temporary("/login").into_response(),
+ Self::Internal(error) => error.into_response(),
+ }
+ }
+}
diff --git a/src/ui/routes/get.rs b/src/ui/handlers/index.rs
index 2fcb51c..2fcb51c 100644
--- a/src/ui/routes/get.rs
+++ b/src/ui/handlers/index.rs
diff --git a/src/ui/handlers/invite.rs b/src/ui/handlers/invite.rs
new file mode 100644
index 0000000..0f9580a
--- /dev/null
+++ b/src/ui/handlers/invite.rs
@@ -0,0 +1,53 @@
+use axum::{
+ extract::{Path, State},
+ response::{self, IntoResponse},
+};
+
+use crate::{
+ app::App,
+ error::Internal,
+ invite,
+ ui::{
+ assets::{Asset, Assets},
+ error::NotFound,
+ },
+};
+
+pub async fn handler(
+ State(app): State<App>,
+ Path(invite): Path<invite::Id>,
+) -> Result<Asset, Error> {
+ app.invites()
+ .get(&invite)
+ .await
+ .map_err(Error::internal)?
+ .ok_or(Error::NotFound)?;
+
+ Assets::index().map_err(Error::Internal)
+}
+
+#[derive(Debug, thiserror::Error)]
+pub enum Error {
+ #[error("invite not found")]
+ NotFound,
+ #[error("{0}")]
+ Internal(Internal),
+}
+
+impl Error {
+ fn internal(err: impl Into<Internal>) -> Self {
+ Self::Internal(err.into())
+ }
+}
+
+impl IntoResponse for Error {
+ fn into_response(self) -> response::Response {
+ match self {
+ Self::NotFound => match Assets::index() {
+ Ok(asset) => NotFound(asset).into_response(),
+ Err(internal) => internal.into_response(),
+ },
+ Self::Internal(error) => error.into_response(),
+ }
+ }
+}
diff --git a/src/ui/handlers/login.rs b/src/ui/handlers/login.rs
new file mode 100644
index 0000000..4562b04
--- /dev/null
+++ b/src/ui/handlers/login.rs
@@ -0,0 +1,8 @@
+use crate::{
+ error::Internal,
+ ui::assets::{Asset, Assets},
+};
+
+pub async fn handler() -> Result<Asset, Internal> {
+ Assets::index()
+}
diff --git a/src/ui/handlers/me.rs b/src/ui/handlers/me.rs
new file mode 100644
index 0000000..2fcb51c
--- /dev/null
+++ b/src/ui/handlers/me.rs
@@ -0,0 +1,30 @@
+use axum::response::{self, IntoResponse, Redirect};
+
+use crate::{
+ error::Internal,
+ token::extract::Identity,
+ ui::assets::{Asset, Assets},
+};
+
+pub async fn handler(identity: Option<Identity>) -> Result<Asset, Error> {
+ let _ = identity.ok_or(Error::NotLoggedIn)?;
+
+ Assets::index().map_err(Error::Internal)
+}
+
+#[derive(Debug, thiserror::Error)]
+pub enum Error {
+ #[error("not logged in")]
+ NotLoggedIn,
+ #[error("{0}")]
+ Internal(Internal),
+}
+
+impl IntoResponse for Error {
+ fn into_response(self) -> response::Response {
+ match self {
+ Self::NotLoggedIn => Redirect::temporary("/login").into_response(),
+ Self::Internal(error) => error.into_response(),
+ }
+ }
+}
diff --git a/src/ui/handlers/mod.rs b/src/ui/handlers/mod.rs
new file mode 100644
index 0000000..5bfd0d6
--- /dev/null
+++ b/src/ui/handlers/mod.rs
@@ -0,0 +1,15 @@
+mod asset;
+mod channel;
+mod index;
+mod invite;
+mod login;
+mod me;
+mod setup;
+
+pub use asset::handler as asset;
+pub use channel::handler as channel;
+pub use index::handler as index;
+pub use invite::handler as invite;
+pub use login::handler as login;
+pub use me::handler as me;
+pub use setup::handler as setup;
diff --git a/src/ui/handlers/setup.rs b/src/ui/handlers/setup.rs
new file mode 100644
index 0000000..49821cf
--- /dev/null
+++ b/src/ui/handlers/setup.rs
@@ -0,0 +1,41 @@
+use axum::{
+ extract::State,
+ response::{self, IntoResponse, Redirect},
+};
+
+use crate::{
+ app::App,
+ error::Internal,
+ ui::assets::{Asset, Assets},
+};
+
+pub async fn handler(State(app): State<App>) -> Result<Asset, Error> {
+ if app
+ .setup()
+ .completed()
+ .await
+ .map_err(Internal::from)
+ .map_err(Error::Internal)?
+ {
+ Err(Error::SetupCompleted)
+ } else {
+ Assets::index().map_err(Error::Internal)
+ }
+}
+
+#[derive(Debug, thiserror::Error)]
+pub enum Error {
+ #[error("setup already completed")]
+ SetupCompleted,
+ #[error("{0}")]
+ Internal(Internal),
+}
+
+impl IntoResponse for Error {
+ fn into_response(self) -> response::Response {
+ match self {
+ Self::SetupCompleted => Redirect::to("/login").into_response(),
+ Self::Internal(error) => error.into_response(),
+ }
+ }
+}
diff --git a/src/ui/mod.rs b/src/ui/mod.rs
index eeaf27a..9668300 100644
--- a/src/ui/mod.rs
+++ b/src/ui/mod.rs
@@ -1,4 +1,4 @@
mod assets;
mod error;
+pub mod handlers;
mod mime;
-pub mod routes;
diff --git a/src/ui/routes/ch/channel.rs b/src/ui/routes/ch/channel.rs
deleted file mode 100644
index a854f14..0000000
--- a/src/ui/routes/ch/channel.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-pub mod get {
- use axum::{
- extract::{Path, State},
- response::{self, IntoResponse, Redirect},
- };
-
- use crate::{
- app::App,
- channel::{self, app},
- error::Internal,
- token::extract::Identity,
- ui::{
- assets::{Asset, Assets},
- error::NotFound,
- },
- };
-
- pub async fn handler(
- State(app): State<App>,
- identity: Option<Identity>,
- Path(channel): Path<channel::Id>,
- ) -> Result<Asset, Error> {
- let _ = identity.ok_or(Error::NotLoggedIn)?;
- app.channels().get(&channel).await.map_err(Error::from)?;
-
- Assets::index().map_err(Error::Internal)
- }
-
- #[derive(Debug, thiserror::Error)]
- pub enum Error {
- #[error("channel not found")]
- NotFound,
- #[error("not logged in")]
- NotLoggedIn,
- #[error("{0}")]
- Internal(Internal),
- }
-
- impl From<app::Error> for Error {
- fn from(error: app::Error) -> Self {
- match error {
- app::Error::NotFound(_) | app::Error::Deleted(_) => Self::NotFound,
- other => Self::Internal(other.into()),
- }
- }
- }
-
- impl IntoResponse for Error {
- fn into_response(self) -> response::Response {
- match self {
- Self::NotFound => match Assets::index() {
- Ok(asset) => NotFound(asset).into_response(),
- Err(internal) => internal.into_response(),
- },
- Self::NotLoggedIn => Redirect::temporary("/login").into_response(),
- Self::Internal(error) => error.into_response(),
- }
- }
- }
-}
diff --git a/src/ui/routes/ch/mod.rs b/src/ui/routes/ch/mod.rs
deleted file mode 100644
index ff02972..0000000
--- a/src/ui/routes/ch/mod.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod channel;
diff --git a/src/ui/routes/invite/invite.rs b/src/ui/routes/invite/invite.rs
deleted file mode 100644
index 06e5792..0000000
--- a/src/ui/routes/invite/invite.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-pub mod get {
- use axum::{
- extract::{Path, State},
- response::{self, IntoResponse},
- };
-
- use crate::{
- app::App,
- error::Internal,
- invite,
- ui::{
- assets::{Asset, Assets},
- error::NotFound,
- },
- };
-
- pub async fn handler(
- State(app): State<App>,
- Path(invite): Path<invite::Id>,
- ) -> Result<Asset, Error> {
- app.invites()
- .get(&invite)
- .await
- .map_err(Error::internal)?
- .ok_or(Error::NotFound)?;
-
- Assets::index().map_err(Error::Internal)
- }
-
- #[derive(Debug, thiserror::Error)]
- pub enum Error {
- #[error("invite not found")]
- NotFound,
- #[error("{0}")]
- Internal(Internal),
- }
-
- impl Error {
- fn internal(err: impl Into<Internal>) -> Self {
- Self::Internal(err.into())
- }
- }
-
- impl IntoResponse for Error {
- fn into_response(self) -> response::Response {
- match self {
- Self::NotFound => match Assets::index() {
- Ok(asset) => NotFound(asset).into_response(),
- Err(internal) => internal.into_response(),
- },
- Self::Internal(error) => error.into_response(),
- }
- }
- }
-}
diff --git a/src/ui/routes/invite/mod.rs b/src/ui/routes/invite/mod.rs
deleted file mode 100644
index 50af8be..0000000
--- a/src/ui/routes/invite/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-// In this case, the first redundant `invite` is a literal path segment, and the
-// second `invite` reflects a placeholder.
-#[allow(clippy::module_inception)]
-pub mod invite;
diff --git a/src/ui/routes/login.rs b/src/ui/routes/login.rs
deleted file mode 100644
index 39d45b9..0000000
--- a/src/ui/routes/login.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-pub mod get {
- use crate::{
- error::Internal,
- ui::assets::{Asset, Assets},
- };
-
- pub async fn handler() -> Result<Asset, Internal> {
- Assets::index()
- }
-}
diff --git a/src/ui/routes/me.rs b/src/ui/routes/me.rs
deleted file mode 100644
index f1f118f..0000000
--- a/src/ui/routes/me.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-pub mod get {
- use axum::response::{self, IntoResponse, Redirect};
-
- use crate::{
- error::Internal,
- token::extract::Identity,
- ui::assets::{Asset, Assets},
- };
-
- pub async fn handler(identity: Option<Identity>) -> Result<Asset, Error> {
- let _ = identity.ok_or(Error::NotLoggedIn)?;
-
- Assets::index().map_err(Error::Internal)
- }
-
- #[derive(Debug, thiserror::Error)]
- pub enum Error {
- #[error("not logged in")]
- NotLoggedIn,
- #[error("{0}")]
- Internal(Internal),
- }
-
- impl IntoResponse for Error {
- fn into_response(self) -> response::Response {
- match self {
- Self::NotLoggedIn => Redirect::temporary("/login").into_response(),
- Self::Internal(error) => error.into_response(),
- }
- }
- }
-}
diff --git a/src/ui/routes/mod.rs b/src/ui/routes/mod.rs
deleted file mode 100644
index 2390802..0000000
--- a/src/ui/routes/mod.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-pub mod ch;
-pub mod get;
-pub mod invite;
-pub mod login;
-pub mod me;
-pub mod path;
-pub mod setup;
diff --git a/src/ui/routes/path.rs b/src/ui/routes/path.rs
deleted file mode 100644
index a387552..0000000
--- a/src/ui/routes/path.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub mod get {
- use axum::extract::Path;
-
- use crate::ui::assets::{Asset, Assets, Error};
-
- pub async fn handler(Path(path): Path<String>) -> Result<Asset, Error> {
- Assets::load(path)
- }
-}
diff --git a/src/ui/routes/setup.rs b/src/ui/routes/setup.rs
deleted file mode 100644
index 649cc5f..0000000
--- a/src/ui/routes/setup.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-pub mod get {
- use axum::{
- extract::State,
- response::{self, IntoResponse, Redirect},
- };
-
- use crate::{
- app::App,
- error::Internal,
- ui::assets::{Asset, Assets},
- };
-
- pub async fn handler(State(app): State<App>) -> Result<Asset, Error> {
- if app
- .setup()
- .completed()
- .await
- .map_err(Internal::from)
- .map_err(Error::Internal)?
- {
- Err(Error::SetupCompleted)
- } else {
- Assets::index().map_err(Error::Internal)
- }
- }
-
- #[derive(Debug, thiserror::Error)]
- pub enum Error {
- #[error("setup already completed")]
- SetupCompleted,
- #[error("{0}")]
- Internal(Internal),
- }
-
- impl IntoResponse for Error {
- fn into_response(self) -> response::Response {
- match self {
- Self::SetupCompleted => Redirect::to("/login").into_response(),
- Self::Internal(error) => error.into_response(),
- }
- }
- }
-}
diff --git a/src/user/routes/login/post.rs b/src/user/handlers/login/mod.rs
index 39f9eea..e80377e 100644
--- a/src/user/routes/login/post.rs
+++ b/src/user/handlers/login/mod.rs
@@ -13,6 +13,9 @@ use crate::{
user::{Password, User},
};
+#[cfg(test)]
+mod test;
+
pub async fn handler(
State(app): State<App>,
RequestedAt(now): RequestedAt,
diff --git a/src/user/routes/login/test.rs b/src/user/handlers/login/test.rs
index d2e7ee2..b8f24f6 100644
--- a/src/user/routes/login/test.rs
+++ b/src/user/handlers/login/test.rs
@@ -1,6 +1,5 @@
use axum::extract::{Json, State};
-use super::post;
use crate::{test::fixtures, token::app};
#[tokio::test]
@@ -14,12 +13,12 @@ async fn correct_credentials() {
let identity = fixtures::cookie::not_logged_in();
let logged_in_at = fixtures::now();
- let request = post::Request {
+ let request = super::Request {
name: name.clone(),
password,
};
let (identity, Json(response)) =
- post::handler(State(app.clone()), logged_in_at, identity, Json(request))
+ super::handler(State(app.clone()), logged_in_at, identity, Json(request))
.await
.expect("logged in with valid credentials");
@@ -53,12 +52,12 @@ async fn invalid_name() {
let identity = fixtures::cookie::not_logged_in();
let logged_in_at = fixtures::now();
let (name, password) = fixtures::user::propose();
- let request = post::Request {
+ let request = super::Request {
name: name.clone(),
password,
};
- let post::Error(error) =
- post::handler(State(app.clone()), logged_in_at, identity, Json(request))
+ let super::Error(error) =
+ super::handler(State(app.clone()), logged_in_at, identity, Json(request))
.await
.expect_err("logged in with an incorrect password fails");
@@ -78,12 +77,12 @@ async fn incorrect_password() {
let logged_in_at = fixtures::now();
let identity = fixtures::cookie::not_logged_in();
- let request = post::Request {
+ let request = super::Request {
name: login.name,
password: fixtures::user::propose_password(),
};
- let post::Error(error) =
- post::handler(State(app.clone()), logged_in_at, identity, Json(request))
+ let super::Error(error) =
+ super::handler(State(app.clone()), logged_in_at, identity, Json(request))
.await
.expect_err("logged in with an incorrect password");
@@ -103,8 +102,8 @@ async fn token_expires() {
let logged_in_at = fixtures::ancient();
let identity = fixtures::cookie::not_logged_in();
- let request = post::Request { name, password };
- let (identity, _) = post::handler(State(app.clone()), logged_in_at, identity, Json(request))
+ let request = super::Request { name, password };
+ let (identity, _) = super::handler(State(app.clone()), logged_in_at, identity, Json(request))
.await
.expect("logged in with valid credentials");
let secret = identity.secret().expect("logged in with valid credentials");
diff --git a/src/user/routes/logout/post.rs b/src/user/handlers/logout/mod.rs
index 0ac663e..45a376a 100644
--- a/src/user/routes/logout/post.rs
+++ b/src/user/handlers/logout/mod.rs
@@ -11,6 +11,9 @@ use crate::{
token::{app, extract::IdentityCookie},
};
+#[cfg(test)]
+mod test;
+
pub async fn handler(
State(app): State<App>,
RequestedAt(now): RequestedAt,
diff --git a/src/user/routes/logout/test.rs b/src/user/handlers/logout/test.rs
index ce93760..8dc4636 100644
--- a/src/user/routes/logout/test.rs
+++ b/src/user/handlers/logout/test.rs
@@ -3,7 +3,6 @@ use axum::{
http::StatusCode,
};
-use super::post;
use crate::{test::fixtures, token::app};
#[tokio::test]
@@ -18,7 +17,7 @@ async fn successful() {
// Call the endpoint
- let (response_identity, response_status) = post::handler(
+ let (response_identity, response_status) = super::handler(
State(app.clone()),
fixtures::now(),
identity.clone(),
@@ -50,7 +49,7 @@ async fn no_identity() {
// Call the endpoint
let identity = fixtures::cookie::not_logged_in();
- let (identity, status) = post::handler(State(app), fixtures::now(), identity, Json::default())
+ let (identity, status) = super::handler(State(app), fixtures::now(), identity, Json::default())
.await
.expect("logged out with no token succeeds");
@@ -69,9 +68,10 @@ async fn invalid_token() {
// Call the endpoint
let identity = fixtures::cookie::fictitious();
- let post::Error(error) = post::handler(State(app), fixtures::now(), identity, Json::default())
- .await
- .expect_err("logged out with an invalid token fails");
+ let super::Error(error) =
+ super::handler(State(app), fixtures::now(), identity, Json::default())
+ .await
+ .expect_err("logged out with an invalid token fails");
// Verify the return value's basic structure
diff --git a/src/user/handlers/mod.rs b/src/user/handlers/mod.rs
new file mode 100644
index 0000000..5cadbb5
--- /dev/null
+++ b/src/user/handlers/mod.rs
@@ -0,0 +1,7 @@
+mod login;
+mod logout;
+mod password;
+
+pub use login::handler as login;
+pub use logout::handler as logout;
+pub use password::handler as change_password;
diff --git a/src/user/routes/password/post.rs b/src/user/handlers/password/mod.rs
index 296f6cd..9158325 100644
--- a/src/user/routes/password/post.rs
+++ b/src/user/handlers/password/mod.rs
@@ -15,6 +15,9 @@ use crate::{
user::{Password, User},
};
+#[cfg(test)]
+mod test;
+
pub async fn handler(
State(app): State<App>,
RequestedAt(now): RequestedAt,
diff --git a/src/user/routes/password/test.rs b/src/user/handlers/password/test.rs
index f977327..42e41d8 100644
--- a/src/user/routes/password/test.rs
+++ b/src/user/handlers/password/test.rs
@@ -1,6 +1,5 @@
use axum::extract::{Json, State};
-use super::post;
use crate::{
test::fixtures,
token::app::{LoginError, ValidateError},
@@ -17,11 +16,11 @@ async fn password_change() {
// Call the endpoint
let (name, password) = creds;
let to = fixtures::user::propose_password();
- let request = post::Request {
+ let request = super::Request {
password: password.clone(),
to: to.clone(),
};
- let (new_cookie, Json(response)) = post::handler(
+ let (new_cookie, Json(response)) = super::handler(
State(app.clone()),
fixtures::now(),
identity.clone(),
diff --git a/src/user/mod.rs b/src/user/mod.rs
index 7ea3d26..44e1633 100644
--- a/src/user/mod.rs
+++ b/src/user/mod.rs
@@ -2,11 +2,11 @@
pub mod app;
pub mod create;
pub mod event;
+pub mod handlers;
mod history;
mod id;
pub mod password;
pub mod repo;
-pub mod routes;
mod snapshot;
mod validate;
diff --git a/src/user/routes/login/mod.rs b/src/user/routes/login/mod.rs
deleted file mode 100644
index 36b384e..0000000
--- a/src/user/routes/login/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-pub mod post;
-
-#[cfg(test)]
-mod test;
diff --git a/src/user/routes/logout/mod.rs b/src/user/routes/logout/mod.rs
deleted file mode 100644
index 36b384e..0000000
--- a/src/user/routes/logout/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-pub mod post;
-
-#[cfg(test)]
-mod test;
diff --git a/src/user/routes/mod.rs b/src/user/routes/mod.rs
deleted file mode 100644
index f9bbed7..0000000
--- a/src/user/routes/mod.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub mod login;
-pub mod logout;
-pub mod password;
diff --git a/src/user/routes/password/mod.rs b/src/user/routes/password/mod.rs
deleted file mode 100644
index 36b384e..0000000
--- a/src/user/routes/password/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-pub mod post;
-
-#[cfg(test)]
-mod test;