codoseo_web/routes/
account.rs1use askama::Template;
5use axum::extract::State;
6use axum::response::{IntoResponse, Redirect, Response};
7use axum::routing::{get, post};
8use axum::{Form, Router};
9use serde::Deserialize;
10
11use crate::auth::CurrentUser;
12use crate::config::Mode;
13use crate::error::AppError;
14use crate::layout::{Screen, Shell};
15use crate::render::html;
16use crate::state::AppState;
17
18pub fn routes() -> Router<AppState> {
19 Router::new()
20 .route("/account", get(page))
21 .route("/account/signups", post(set_signups))
22}
23
24#[derive(Template)]
25#[template(path = "account/index.html")]
26pub struct AccountPage {
27 pub shell: Shell,
28 pub email: String,
29 pub plan: String,
30 pub self_hosted: bool,
31 pub billing: bool,
32 pub is_owner: bool,
33 pub signups_open: bool,
34 pub is_admin: bool,
35}
36
37async fn page(State(state): State<AppState>, user: CurrentUser) -> Result<Response, AppError> {
38 let shell = Shell::load(&state, &user, None, Screen::Account).await?;
39 let signups_open = codoseo_store::accounts::signups_open(&state.pool).await?;
40 Ok(html(&AccountPage {
41 plan: shell.user.plan_label.clone(),
42 shell,
43 email: user.account.email.clone(),
44 self_hosted: state.config.mode == Mode::SelfHost,
45 billing: state.config.mode == Mode::Cloud,
46 is_owner: user.account.is_owner,
47 signups_open,
48 is_admin: super::admin::is_admin(&state, &user.account),
49 })?
50 .into_response())
51}
52
53#[derive(Deserialize)]
54struct SignupsForm {
55 open: String,
56}
57
58async fn set_signups(
59 State(state): State<AppState>,
60 user: CurrentUser,
61 Form(form): Form<SignupsForm>,
62) -> Result<Response, AppError> {
63 if state.config.mode != Mode::SelfHost || !user.account.is_owner {
64 return Err(AppError::Forbidden(
65 "Only the instance owner can change signups.".to_owned(),
66 ));
67 }
68 codoseo_store::accounts::set_signups_open(&state.pool, form.open == "true").await?;
69 Ok(Redirect::to("/account").into_response())
70}