summaryrefslogtreecommitdiff
path: root/src/channel/routes.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/channel/routes.rs')
-rw-r--r--src/channel/routes.rs68
1 files changed, 53 insertions, 15 deletions
diff --git a/src/channel/routes.rs b/src/channel/routes.rs
index 847e0b4..383ec58 100644
--- a/src/channel/routes.rs
+++ b/src/channel/routes.rs
@@ -1,23 +1,43 @@
use axum::{
- extract::{Form, Path, State},
+ extract::{Json, Path, State},
http::StatusCode,
- response::{IntoResponse, Redirect, Response},
- routing::post,
+ response::{IntoResponse, Response},
+ routing::{get, post},
Router,
};
-use super::app::EventsError;
+use super::app::{self, EventsError};
use crate::{
app::App,
clock::RequestedAt,
error::InternalError,
- repo::{channel, login::Login},
+ repo::{
+ channel::{self, Channel},
+ login::Login,
+ },
};
pub fn router() -> Router<App> {
Router::new()
- .route("/create", post(on_create))
- .route("/:channel/send", post(on_send))
+ .route("/api/channels", get(list_channels))
+ .route("/api/channels", post(on_create))
+ .route("/api/channels/:channel", post(on_send))
+}
+
+async fn list_channels(State(app): State<App>, _: Login) -> Result<Channels, InternalError> {
+ let channels = app.channels().all().await?;
+ let response = Channels(channels);
+
+ Ok(response)
+}
+
+struct Channels(Vec<Channel>);
+
+impl IntoResponse for Channels {
+ fn into_response(self) -> Response {
+ let Self(channels) = self;
+ Json(channels).into_response()
+ }
}
#[derive(serde::Deserialize)]
@@ -28,11 +48,29 @@ struct CreateRequest {
async fn on_create(
State(app): State<App>,
_: Login, // requires auth, but doesn't actually care who you are
- Form(form): Form<CreateRequest>,
-) -> Result<impl IntoResponse, InternalError> {
- app.channels().create(&form.name).await?;
+ Json(form): Json<CreateRequest>,
+) -> Result<Json<Channel>, CreateError> {
+ let channel = app
+ .channels()
+ .create(&form.name)
+ .await
+ .map_err(CreateError)?;
- Ok(Redirect::to("/"))
+ Ok(Json(channel))
+}
+
+struct CreateError(app::CreateError);
+
+impl IntoResponse for CreateError {
+ fn into_response(self) -> Response {
+ let Self(error) = self;
+ match error {
+ duplicate @ app::CreateError::DuplicateName(_) => {
+ (StatusCode::BAD_REQUEST, duplicate.to_string()).into_response()
+ }
+ other => InternalError::from(other).into_response(),
+ }
+ }
}
#[derive(serde::Deserialize)]
@@ -45,15 +83,15 @@ async fn on_send(
RequestedAt(sent_at): RequestedAt,
State(app): State<App>,
login: Login,
- Form(form): Form<SendRequest>,
-) -> Result<impl IntoResponse, ErrorResponse> {
+ Json(form): Json<SendRequest>,
+) -> Result<StatusCode, ErrorResponse> {
app.channels()
.send(&login, &channel, &form.message, &sent_at)
.await
// Could impl `From` here, but it's more code and this is used once.
.map_err(ErrorResponse)?;
- Ok(Redirect::to(&format!("/{}", channel)))
+ Ok(StatusCode::ACCEPTED)
}
struct ErrorResponse(EventsError);
@@ -65,7 +103,7 @@ impl IntoResponse for ErrorResponse {
not_found @ EventsError::ChannelNotFound(_) => {
(StatusCode::NOT_FOUND, not_found.to_string()).into_response()
}
- EventsError::DatabaseError(error) => InternalError::from(error).into_response(),
+ other => InternalError::from(other).into_response(),
}
}
}