flams_router_login/
server_fns.rs1use flams_database::{LoginError, UserData};
2use flams_router_base::LoginState;
3use leptos::prelude::*;
4
5#[server(prefix = "/api", endpoint = "login")]
6pub async fn login(
7 admin_pwd: Option<String>,
8) -> Result<Option<LoginState>, ServerFnError<LoginError>> {
9 ssr::login(admin_pwd).await
10}
11
12#[server(prefix = "/api", endpoint = "logout")]
13pub async fn logout() -> Result<(), ServerFnError<LoginError>> {
14 ssr::logout().await
15}
16
17#[server(LoginStateFn, prefix = "/api", endpoint = "login_state")]
18#[allow(clippy::unused_async)]
19pub async fn login_state() -> Result<LoginState, ServerFnError<String>> {
20 Ok(LoginState::get_server())
21}
22
23#[server(prefix = "/api", endpoint = "get_users")]
24pub async fn get_users() -> Result<Vec<UserData>, ServerFnError<LoginError>> {
25 ssr::get_users().await
26}
27
28#[server(prefix = "/api", endpoint = "set_admin")]
29pub async fn set_admin(user_id: i64, is_admin: bool) -> Result<(), ServerFnError<LoginError>> {
30 ssr::set_admin(user_id, is_admin).await
31}
32
33#[cfg(feature = "ssr")]
34mod ssr {
35 use flams_database::{DBBackend, LoginError, UserData};
36 use flams_git::gl::auth::GitLabOAuth;
37 use flams_router_base::LoginState;
38 use leptos::prelude::*;
39
40 pub(super) async fn login(
41 admin_pwd: Option<String>,
42 ) -> Result<Option<LoginState>, ServerFnError<LoginError>> {
43 let Some(session) = use_context::<axum_login::AuthSession<DBBackend>>() else {
44 return Ok(Some(LoginState::None));
45 };
46 if session.backend.admin.is_none() {
47 return Ok(Some(LoginState::NoAccounts));
48 }
49 if let Some(password) = admin_pwd {
50 return if DBBackend::login_as_admin(&password, session).await.is_ok() {
51 Ok(Some(LoginState::Admin))
52 } else {
53 Err(LoginError::WrongUsernameOrPassword.into())
54 };
55 }
56 let oauth: Option<GitLabOAuth> = expect_context();
57 if let Some(oauth) = oauth.as_ref() {
58 leptos_axum::redirect(oauth.login_url().as_str());
59 } else {
60 leptos_axum::redirect("/dashboard");
61 }
62 Ok(None)
63 }
64
65 pub async fn logout() -> Result<(), ServerFnError<LoginError>> {
66 let Some(mut session) = use_context::<axum_login::AuthSession<DBBackend>>() else {
67 return Ok(());
68 };
69 let _ = session.logout().await;
70 leptos_axum::redirect("/dashboard");
71 Ok(())
72 }
73
74 pub(super) async fn get_users() -> Result<Vec<UserData>, ServerFnError<LoginError>> {
75 match LoginState::get_server() {
76 LoginState::Admin | LoginState::NoAccounts => (),
77 _ => return Err(ServerFnError::WrappedServerError(LoginError::NotLoggedIn)),
78 }
79 let Some(session) = use_context::<axum_login::AuthSession<DBBackend>>() else {
80 return Ok(Vec::new());
81 };
82 let users = session
83 .backend
84 .all_users()
85 .await
86 .map_err(|_| ServerFnError::WrappedServerError(LoginError::NotLoggedIn))?;
87 let mut users: Vec<_> = users.into_iter().map(UserData::from).collect();
88 users.sort_by_key(|e| e.id);
89 Ok(users)
90 }
91
92 pub async fn set_admin(user_id: i64, is_admin: bool) -> Result<(), ServerFnError<LoginError>> {
93 match LoginState::get_server() {
94 LoginState::Admin | LoginState::NoAccounts => (),
95 _ => return Err(ServerFnError::WrappedServerError(LoginError::NotLoggedIn)),
96 }
97 let Some(session) = use_context::<axum_login::AuthSession<DBBackend>>() else {
98 return Ok(());
99 };
100 session
101 .backend
102 .set_admin(user_id, is_admin)
103 .await
104 .map_err(|_| ServerFnError::WrappedServerError(LoginError::NotLoggedIn))?;
105 Ok(())
106 }
107}