matrix_ui_serializable/init/
login.rs1use matrix_sdk::{Client, sliding_sync::VersionBuilder};
2
3use std::path::PathBuf;
4
5use rand::{Rng, distr::Alphanumeric, rng};
6use serde::{Deserialize, Serialize};
7
8use crate::init::singletons::CLIENT;
9
10use super::session::ClientSession;
11
12#[derive(Debug, Clone, Deserialize, Serialize)]
14pub struct MatrixClientConfig {
15 username: String,
16 password: String,
17 homeserver_url: String,
18 client_name: String,
19}
20
21impl MatrixClientConfig {
22 pub fn new(
23 username: String,
24 password: String,
25 homeserver_url: String,
26 client_name: String,
27 ) -> Self {
28 MatrixClientConfig {
29 username,
30 password,
31 homeserver_url,
32 client_name,
33 }
34 }
35}
36
37pub enum LoginRequest {
39 LoginByPassword(MatrixClientConfig),
40}
41
42pub async fn get_client_from_new_session(
43 login_request: LoginRequest,
44 app_data_dir: PathBuf,
45) -> anyhow::Result<(Client, String)> {
46 let matrix_config = match login_request {
47 LoginRequest::LoginByPassword(config) => config,
48 };
50
51 let client_initial_state = login_and_persist_session(&matrix_config, app_data_dir).await?;
52
53 CLIENT
54 .set(client_initial_state.0.clone())
55 .expect("BUG: CLIENT already set!");
56
57 Ok(client_initial_state)
58}
59
60async fn login_and_persist_session(
61 config: &MatrixClientConfig,
62 app_data_dir: PathBuf,
63) -> anyhow::Result<(Client, String)> {
64 let (client, client_session) = build_client(config, app_data_dir).await?;
65
66 let matrix_auth = client.matrix_auth();
67
68 matrix_auth
69 .login_username(&config.username, &config.password)
70 .initial_device_display_name(&config.client_name)
71 .await?;
72
73 let user_session = matrix_auth
74 .session()
75 .expect("Should have session after login");
76
77 let full = super::session::FullMatrixSession::new(client_session, user_session);
78 let serialized = serde_json::to_string(&full)?;
79
80 Ok((client, serialized))
81}
82
83async fn build_client(
84 config: &MatrixClientConfig,
85 app_data_dir: PathBuf,
86) -> anyhow::Result<(Client, ClientSession)> {
87 let db_subfolder: String = rng()
88 .sample_iter(Alphanumeric)
89 .take(7)
90 .map(char::from)
91 .collect();
92 let db_path = app_data_dir.join("matrix-db").join(db_subfolder);
93
94 std::fs::create_dir_all(&db_path)?;
95
96 let passphrase: String = rng()
97 .sample_iter(Alphanumeric)
98 .take(32)
99 .map(char::from)
100 .collect();
101
102 let client = Client::builder()
103 .homeserver_url(&config.homeserver_url)
104 .sqlite_store(&db_path, Some(&passphrase))
105 .sliding_sync_version_builder(VersionBuilder::DiscoverNative) .handle_refresh_tokens()
107 .build()
108 .await?;
109
110 let client_session = ClientSession::new(config.homeserver_url.clone(), db_path, passphrase);
111
112 Ok((client, client_session))
113}