1
use std::sync::Arc;
2

            
3
use axum::{
4
    Router, middleware,
5
    routing::{get, post},
6
};
7

            
8
#[cfg(feature = "scripting")]
9
use crate::pages::script;
10
use crate::{
11
    AppState,
12
    files::download_file,
13
    handler::{
14
        get_home_link, get_logout_link, get_me_handler, get_version, login_form_handler,
15
        login_user_handler, logout_handler, refresh_access_token_handler, register_user_handler,
16
    },
17
    jwt_auth::{admin, auth},
18
    pages::{account, commodity, file_table, report, tag},
19
    redirect_middleware::redirect_on_auth_error,
20
};
21

            
22
1
pub fn create_pages_router(app_state: Arc<AppState>) -> Router<Arc<AppState>> {
23
1
    Router::new()
24
1
        .route(
25
1
            "/commodity/create",
26
1
            get(crate::pages::commodity::create::submit::commodity_create_page),
27
        )
28
1
        .route(
29
1
            "/commodity/list",
30
1
            get(crate::pages::commodity::list::commodity_list_page),
31
        )
32
1
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
33
1
        .route_layer(middleware::from_fn(redirect_on_auth_error))
34
1
        .with_state(app_state.clone())
35
1
}
36

            
37
1
pub fn create_accounts_router(app_state: Arc<AppState>) -> Router<Arc<AppState>> {
38
1
    Router::new()
39
1
        .route(
40
1
            "/account/create",
41
1
            get(crate::pages::account::create::submit::account_create_page),
42
        )
43
1
        .route(
44
1
            "/account/list",
45
1
            get(crate::pages::account::list::account_list_page),
46
        )
47
1
        .route(
48
1
            "/account/manage",
49
1
            get(crate::pages::account::manage::account_manage_page),
50
        )
51
1
        .route(
52
1
            "/account/ssh-key",
53
1
            get(crate::pages::account::ssh_key::ssh_key_page),
54
        )
55
1
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
56
1
        .route_layer(middleware::from_fn(redirect_on_auth_error))
57
1
        .with_state(app_state.clone())
58
1
}
59

            
60
1
pub fn create_transactions_router(app_state: Arc<AppState>) -> Router<Arc<AppState>> {
61
1
    Router::new()
62
1
        .route(
63
1
            "/transaction/create",
64
1
            get(crate::pages::transaction::create::submit::transaction_create_page),
65
        )
66
1
        .route(
67
1
            "/transaction/list",
68
1
            get(crate::pages::transaction::list::transaction_list_page),
69
        )
70
1
        .route(
71
1
            "/transaction/edit/{id}",
72
1
            get(crate::pages::transaction::edit::submit::transaction_edit_page),
73
        )
74
1
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
75
1
        .route_layer(middleware::from_fn(redirect_on_auth_error))
76
1
        .with_state(app_state.clone())
77
1
}
78

            
79
pub fn create_tags_router(app_state: Arc<AppState>) -> Router<Arc<AppState>> {
80
    Router::new()
81
        .route(
82
            "/tag/create",
83
            get(crate::pages::tag::create::tag_create_page),
84
        )
85
        .route("/tag/list", get(crate::pages::tag::list::tag_list_page))
86
        .route(
87
            "/tag/edit/{id}",
88
            get(crate::pages::tag::edit::tag_edit_page),
89
        )
90
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
91
        .route_layer(middleware::from_fn(redirect_on_auth_error))
92
        .with_state(app_state.clone())
93
}
94

            
95
#[cfg(feature = "scripting")]
96
pub fn create_scripts_router(app_state: Arc<AppState>) -> Router<Arc<AppState>> {
97
    Router::new()
98
        .route("/script/create", get(script::edit::script_create_page))
99
        .route("/script/list", get(script::list::script_list_page))
100
        .route("/script/edit/{id}", get(script::edit::script_edit_page))
101
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
102
        .route_layer(middleware::from_fn(redirect_on_auth_error))
103
        .with_state(app_state.clone())
104
}
105

            
106
pub fn create_reports_router(app_state: Arc<AppState>) -> Router<Arc<AppState>> {
107
    Router::new()
108
        .route("/report/balance", get(report::balance::balance_report_page))
109
        .route(
110
            "/report/activity",
111
            get(report::activity::activity_report_page),
112
        )
113
        .route(
114
            "/report/category-breakdown",
115
            get(report::category_breakdown::category_breakdown_report_page),
116
        )
117
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
118
        .route_layer(middleware::from_fn(redirect_on_auth_error))
119
        .with_state(app_state.clone())
120
}
121

            
122
3
pub fn create_api_router(app_state: Arc<AppState>) -> Router<Arc<AppState>> {
123
3
    let public_router = Router::new()
124
3
        .route("/auth/login", post(login_form_handler))
125
3
        .route("/auth/login/json", post(login_user_handler))
126
3
        .route("/version", get(get_version));
127

            
128
3
    let auth_router = Router::new()
129
3
        .route("/auth/refresh", get(refresh_access_token_handler))
130
3
        .route("/files/list", get(file_table))
131
3
        .route("/files/download/{file_name}", get(download_file))
132
3
        .route("/auth/logout", get(logout_handler))
133
3
        .route("/users/me", get(get_me_handler))
134
3
        .route("/htmx/logoutlink", get(get_logout_link))
135
3
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
136
3
        .with_state(app_state.clone());
137

            
138
3
    let account_router = Router::new()
139
3
        .route("/account/list", get(account::list::account_table))
140
3
        .route("/account/info", get(account::list::account_info))
141
3
        .route("/account/tree", get(account::manage::account_tree))
142
3
        .route(
143
3
            "/account/manage/view",
144
3
            get(account::manage::account_manage_view),
145
        )
146
3
        .route(
147
3
            "/account/manage/details",
148
3
            get(account::manage::account_manage_details),
149
        )
150
3
        .route(
151
3
            "/account/manage/tag",
152
3
            post(account::manage::account_manage_set_tag),
153
        )
154
3
        .route(
155
3
            "/account/manage/tag/submit",
156
3
            post(account::manage::account_manage_set_tag_submit),
157
        )
158
3
        .route(
159
3
            "/account/manage/tag/delete/{tag_id}",
160
3
            post(account::manage::account_manage_delete_tag_submit),
161
        )
162
3
        .route("/account/search", post(account::search::search_accounts))
163
3
        .route(
164
3
            "/account/create/submit",
165
3
            post(account::create::submit::create_account),
166
        )
167
3
        .route(
168
3
            "/account/create/validate/name",
169
3
            post(account::create::validate::validate_name),
170
        )
171
3
        .route("/account/rename", post(account::edit::rename_account))
172
3
        .route(
173
3
            "/account/{id}/tags/submit",
174
3
            post(account::edit::account_tags_submit),
175
        )
176
3
        .route("/account/ssh-key/add", post(account::ssh_key::ssh_key_add))
177
3
        .route(
178
3
            "/account/ssh-key/remove",
179
3
            post(account::ssh_key::ssh_key_remove),
180
        )
181
3
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
182
3
        .with_state(app_state.clone());
183

            
184
3
    let nav_router = Router::new()
185
3
        .route("/nav/home", get(get_home_link))
186
3
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
187
3
        .with_state(app_state.clone());
188

            
189
3
    let commodity_router = Router::new()
190
3
        .route("/commodity/list", get(commodity::list::commodity_table))
191
3
        .route(
192
3
            "/commodity/search",
193
3
            post(commodity::search::search_commodities),
194
        )
195
3
        .route(
196
3
            "/commodity/create/submit",
197
3
            post(commodity::create::submit::commodity_submit),
198
        )
199
3
        .route(
200
3
            "/commodity/create/validate/symbol",
201
3
            post(commodity::create::validate::validate_symbol),
202
        )
203
3
        .route(
204
3
            "/commodity/create/validate/name",
205
3
            post(commodity::create::validate::validate_name),
206
        )
207
3
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
208
3
        .with_state(app_state.clone());
209

            
210
3
    let transaction_router = Router::new()
211
3
        .route(
212
3
            "/transaction/list",
213
3
            get(crate::pages::transaction::list::transaction_table),
214
        )
215
3
        .route(
216
3
            "/transaction/split/create",
217
3
            get(crate::pages::transaction::create::split::split_create_handler),
218
        )
219
3
        .route(
220
3
            "/transaction/create/submit",
221
3
            post(crate::pages::transaction::create::submit::transaction_submit),
222
        )
223
3
        .route(
224
3
            "/transaction/create/validate/amount",
225
3
            post(crate::pages::transaction::validate::validate_amount_html),
226
        )
227
3
        .route(
228
3
            "/transaction/create/validate/from_account",
229
3
            post(crate::pages::transaction::validate::validate_from_account_html),
230
        )
231
3
        .route(
232
3
            "/transaction/create/validate/to_account",
233
3
            post(crate::pages::transaction::validate::validate_to_account_html),
234
        )
235
3
        .route(
236
3
            "/transaction/create/validate/note",
237
3
            post(crate::pages::transaction::validate::validate_note_html),
238
        )
239
3
        .route(
240
3
            "/transaction/edit/submit",
241
3
            post(crate::pages::transaction::edit::submit::transaction_edit_submit),
242
        )
243
3
        .route(
244
3
            "/transaction/edit/validate/amount",
245
3
            post(crate::pages::transaction::validate::validate_amount_json),
246
        )
247
3
        .route(
248
3
            "/transaction/edit/validate/from_account",
249
3
            post(crate::pages::transaction::validate::validate_from_account_json),
250
        )
251
3
        .route(
252
3
            "/transaction/edit/validate/to_account",
253
3
            post(crate::pages::transaction::validate::validate_to_account_json),
254
        )
255
3
        .route(
256
3
            "/transaction/edit/validate/note",
257
3
            post(crate::pages::transaction::validate::validate_note_json),
258
        )
259
3
        .route(
260
3
            "/transaction/delete/{id}",
261
3
            post(crate::pages::transaction::delete::submit::transaction_delete_submit),
262
        )
263
3
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
264
3
        .with_state(app_state.clone());
265

            
266
3
    let tag_router = Router::new()
267
3
        .route("/tag/list", get(tag::list::tag_table))
268
3
        .route("/tag/create/submit", post(tag::create::create_tag))
269
3
        .route(
270
3
            "/transaction/{id}/tag/create/submit",
271
3
            post(tag::create::create_transaction_tag),
272
        )
273
3
        .route(
274
3
            "/split/{id}/tag/create/submit",
275
3
            post(tag::create::create_split_tag),
276
        )
277
3
        .route(
278
3
            "/account/{id}/tag/create/submit",
279
3
            post(tag::create::create_account_tag),
280
        )
281
3
        .route("/tag/edit/submit", post(tag::edit::edit_tag))
282
3
        .route("/tag/delete/{id}", post(tag::edit::delete_tag))
283
3
        .route(
284
3
            "/tags/transaction/names",
285
3
            get(tag::autocomplete::transaction_tag_names),
286
        )
287
3
        .route(
288
3
            "/tags/transaction/values",
289
3
            get(tag::autocomplete::transaction_tag_values),
290
        )
291
3
        .route("/tags/split/names", get(tag::autocomplete::split_tag_names))
292
3
        .route(
293
3
            "/tags/split/values",
294
3
            get(tag::autocomplete::split_tag_values),
295
        )
296
3
        .route(
297
3
            "/tags/account/names",
298
3
            get(tag::autocomplete::account_tag_names),
299
        )
300
3
        .route(
301
3
            "/tags/account/values",
302
3
            get(tag::autocomplete::account_tag_values),
303
        )
304
3
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
305
3
        .with_state(app_state.clone());
306

            
307
    #[cfg(feature = "scripting")]
308
3
    let script_router = Router::new()
309
3
        .route("/script/list", get(script::list::script_table))
310
3
        .route("/script/create/submit", post(script::edit::create_script))
311
3
        .route("/script/edit/submit", post(script::edit::edit_script))
312
3
        .route(
313
3
            "/script/bytecode/{id}",
314
3
            post(script::edit::upload_script_bytecode),
315
        )
316
3
        .route("/script/delete/{id}", post(script::edit::delete_script))
317
3
        .route(
318
3
            "/account/{account_id}/script/run/{script_id}",
319
3
            post(account::edit::run_account_script),
320
        )
321
3
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
322
3
        .with_state(app_state.clone());
323

            
324
3
    let report_router = Router::new()
325
3
        .route(
326
3
            "/report/balance",
327
3
            get(report::balance::balance_report_table),
328
        )
329
3
        .route(
330
3
            "/report/balance/chart.svg",
331
3
            get(report::balance::balance_report_chart_svg),
332
        )
333
3
        .route(
334
3
            "/report/balance/chart.json",
335
3
            get(report::balance::balance_report_chart_json),
336
        )
337
3
        .route(
338
3
            "/report/activity",
339
3
            get(report::activity::activity_report_table),
340
        )
341
3
        .route(
342
3
            "/report/activity/chart.svg",
343
3
            get(report::activity::activity_report_chart_svg),
344
        )
345
3
        .route(
346
3
            "/report/activity/chart.json",
347
3
            get(report::activity::activity_report_chart_json),
348
        )
349
3
        .route(
350
3
            "/report/category-breakdown",
351
3
            get(report::category_breakdown::category_breakdown_report_table),
352
        )
353
3
        .route(
354
3
            "/report/category-breakdown/chart.svg",
355
3
            get(report::category_breakdown::category_breakdown_report_chart_svg),
356
        )
357
3
        .route(
358
3
            "/report/category-breakdown/chart.json",
359
3
            get(report::category_breakdown::category_breakdown_report_chart_json),
360
        )
361
3
        .route_layer(middleware::from_fn_with_state(app_state.clone(), auth))
362
3
        .with_state(app_state.clone());
363

            
364
3
    let admin_router = Router::new()
365
3
        .route("/auth/register", post(register_user_handler))
366
3
        .route_layer(middleware::from_fn_with_state(app_state.clone(), admin))
367
3
        .route_layer(middleware::from_fn_with_state(app_state, auth));
368

            
369
3
    let router = Router::new()
370
3
        .merge(public_router)
371
3
        .merge(nav_router)
372
3
        .merge(auth_router)
373
3
        .merge(account_router)
374
3
        .merge(commodity_router)
375
3
        .merge(transaction_router)
376
3
        .merge(tag_router)
377
3
        .merge(report_router)
378
3
        .merge(admin_router);
379

            
380
    #[cfg(feature = "scripting")]
381
3
    let router = router.merge(script_router);
382

            
383
3
    router
384
3
}