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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
/*
This file is part of jellything (https://codeberg.org/metamuffin/jellything)
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
// pub mod settings;
pub mod settings;
use super::error::MyError;
use crate::{
auth::login, request_info::RequestInfo, ui::error::MyResult, ui_responder::UiResponse,
};
use anyhow::anyhow;
use jellycommon::{VIEW_ACCOUNT_LOGIN, VIEW_ACCOUNT_LOGOUT, jellyobject::Object, routes::u_home};
use rocket::{
FromForm,
form::{Contextual, Form},
get,
http::{Cookie, CookieJar},
post,
response::{Flash, Redirect},
};
use serde::{Deserialize, Serialize};
#[get("/account/login")]
pub async fn r_account_login(ri: RequestInfo<'_>) -> UiResponse {
ri.respond_ui(Object::EMPTY.insert(VIEW_ACCOUNT_LOGIN, ()))
}
#[get("/account/logout")]
pub fn r_account_logout(ri: RequestInfo<'_>) -> UiResponse {
ri.respond_ui(Object::EMPTY.insert(VIEW_ACCOUNT_LOGOUT, ()))
}
#[derive(FromForm, Serialize, Deserialize)]
pub struct LoginForm {
#[field(validate = len(4..32))]
pub username: String,
#[field(validate = len(..64))]
pub password: String,
#[field(default = 604800)] // one week
pub expire: u64,
}
#[post("/account/login", data = "<form>")]
pub fn r_account_login_post(
ri: RequestInfo<'_>,
jar: &CookieJar,
form: Form<Contextual<LoginForm>>,
) -> MyResult<Redirect> {
let form = match &form.value {
Some(v) => v,
None => return Err(MyError(anyhow!(format_form_error(form)))),
};
let session = login(&ri.state, &form.username, &form.password, None)?;
jar.add(Cookie::build(("session", session)).permanent().build());
Ok(Redirect::found(u_home()))
}
#[post("/account/logout")]
pub fn r_account_logout_post(jar: &CookieJar) -> MyResult<Flash<Redirect>> {
jar.remove(Cookie::build("session"));
Ok(Flash::new(
Redirect::found(u_home()),
"success",
"Logged out!",
))
}
pub fn format_form_error<T>(form: Form<Contextual<T>>) -> String {
let mut k = String::from("form validation failed:");
for e in form.context.errors() {
k += &format!(
"\n\t{}: {e}",
e.name
.as_ref()
.map(|e| e.to_string())
.unwrap_or("<unknown>".to_string())
)
}
k
}
|