1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
use axum::{
Router, middleware,
response::Redirect,
routing::{delete, get, post},
};
use crate::{app::App, boot, conversation, event, expire, invite, message, setup, ui, user};
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::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::handlers::index))
.route("/ch/{channel}", get(ui::handlers::conversation))
.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::handlers::setup));
// API routes that require the administrator to complete setup first.
let api_setup_required = Router::new()
.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/conversations", post(conversation::handlers::create))
.route(
"/api/conversations/{conversation}",
post(conversation::handlers::send),
)
.route(
"/api/conversations/{conversation}",
delete(conversation::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
// upside to re-checking expiry tens of times back-to-back like that; the API is accessed
// more regularly and with less of a traffic rush.
//
// This should, probably, be moved to a background job at some point.
.route_layer(middleware::from_fn_with_state(
app.clone(),
expire::middleware,
))
.route_layer(setup::Required(app.clone()));
[
ui_bootstrap,
ui_setup_required,
api_bootstrap,
api_setup_required,
]
.into_iter()
.fold(Router::default(), Router::merge)
}
|