Skip to main content

rustbasic_core/
session.rs

1use crate::Config;
2use crate::session_manager::RustBasicSessionStore;
3use crate::sql::{self, AnyPool};
4use std::sync::Arc;
5use std::sync::Mutex;
6use serde_json::Value;
7
8#[derive(Clone)]
9pub struct Session {
10    pub(crate) id: String,
11    pub(crate) data: Arc<Mutex<serde_json::Map<String, Value>>>,
12}
13
14impl Session {
15    pub fn new(id: String) -> Self {
16        Self {
17            id,
18            data: Arc::new(Mutex::new(serde_json::Map::new())),
19        }
20    }
21
22    pub fn get<T: serde::de::DeserializeOwned>(&self, key: &str) -> Option<T> {
23        let guard = self.data.lock().unwrap();
24        let val = guard.get(key)?;
25        serde_json::from_value(val.clone()).ok()
26    }
27
28    pub fn set<T: serde::Serialize>(&self, key: &str, value: T) {
29        if let Ok(val) = serde_json::to_value(value) {
30            self.data.lock().unwrap().insert(key.to_string(), val);
31        }
32    }
33
34    pub fn remove(&self, key: &str) -> Option<Value> {
35        self.data.lock().unwrap().remove(key)
36    }
37
38    pub fn id(&self) -> &str {
39        &self.id
40    }
41}
42
43pub async fn setup_session(cfg: &Config) -> RustBasicSessionStore {
44    let session_db_url = if cfg.session_driver == "file" {
45        "sqlite:database/sessions.sqlite?mode=rwc".to_string()
46    } else if cfg.db_connection == "mysql" {
47        format!(
48            "mysql://{}:{}@{}:{}/{}",
49            cfg.db_username, cfg.db_password, cfg.db_host, cfg.db_port, cfg.db_database
50        )
51    } else {
52        format!("sqlite:database/{}.sqlite?mode=rwc", cfg.db_database)
53    };
54
55    sql::any::install_default_drivers();
56    let session_pool = match AnyPool::connect(&session_db_url).await {
57        Ok(pool) => pool,
58        Err(e) => {
59            #[cfg(feature = "mysql")]
60            {
61                let err_msg = e.to_string();
62                if (err_msg.contains("1049") || err_msg.contains("Unknown database")) && cfg.db_connection == "mysql" {
63                    let root_url = format!("mysql://{}:{}@{}:{}", cfg.db_username, cfg.db_password, cfg.db_host, cfg.db_port);
64                    if let Ok(root_pool) = sql::MySqlPool::connect(&root_url).await {
65                        let _ = sql::query(&format!("CREATE DATABASE IF NOT EXISTS `{}`", cfg.db_database)).execute(&root_pool).await;
66                        AnyPool::connect(&session_db_url).await.expect("Gagal terhubung setelah membuat DB session")
67                    } else {
68                        panic!("Gagal membuat database session otomatis: {:?}", e);
69                    }
70                } else {
71                    panic!("Gagal terhubung ke database session: {:?}", e);
72                }
73            }
74            #[cfg(not(feature = "mysql"))]
75            panic!("Gagal terhubung ke database session: {:?}", e);
76        }
77    };
78    
79    RustBasicSessionStore::new(session_pool)
80}
81
82pub async fn init_sessions(cfg: &Config) {
83    let db_url = if cfg.session_driver == "file" {
84        "sqlite:database/sessions.sqlite?mode=rwc".to_string()
85    } else if cfg.db_connection == "mysql" {
86        format!(
87            "mysql://{}:{}@{}:{}/{}",
88            cfg.db_username, cfg.db_password, cfg.db_host, cfg.db_port, cfg.db_database
89        )
90    } else {
91        format!("sqlite:database/{}.sqlite?mode=rwc", cfg.db_database)
92    };
93
94    sql::any::install_default_drivers();
95    let pool = AnyPool::connect(&db_url).await.expect("Gagal terhubung ke database session");
96
97    let sql = if cfg.db_connection == "mysql" {
98        "CREATE TABLE IF NOT EXISTS sessions (
99            id VARCHAR(255) PRIMARY KEY,
100            payload VARCHAR(8000) NOT NULL,
101            last_activity BIGINT NOT NULL,
102            ip_address VARCHAR(45)
103        )"
104    } else {
105        "CREATE TABLE IF NOT EXISTS sessions (
106            id VARCHAR(255) PRIMARY KEY,
107            payload TEXT NOT NULL,
108            last_activity BIGINT NOT NULL,
109            ip_address VARCHAR(45)
110        )"
111    };
112
113    sql::query(sql).execute(&pool).await.expect("Gagal membuat tabel session otomatis");
114}