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 let Ok(url) = std::env::var("DATABASE_URL") {
45        url
46    } else if cfg.session_driver == "file" {
47        "sqlite:database/sessions.sqlite?mode=rwc".to_string()
48    } else if cfg.db_connection == "mysql" {
49        format!(
50            "mysql://{}:{}@{}:{}/{}",
51            cfg.db_username, cfg.db_password, cfg.db_host, cfg.db_port, cfg.db_database
52        )
53    } else {
54        format!("sqlite:database/{}.sqlite?mode=rwc", cfg.db_database)
55    };
56
57    sql::any::install_default_drivers();
58    let session_pool = match AnyPool::connect(&session_db_url).await {
59        Ok(pool) => pool,
60        Err(e) => {
61            #[cfg(feature = "mysql")]
62            {
63                let err_msg = e.to_string();
64                if (err_msg.contains("1049") || err_msg.contains("Unknown database")) && cfg.db_connection == "mysql" {
65                    let root_url = format!("mysql://{}:{}@{}:{}", cfg.db_username, cfg.db_password, cfg.db_host, cfg.db_port);
66                    if let Ok(root_pool) = sql::MySqlPool::connect(&root_url).await {
67                        let _ = sql::query(&format!("CREATE DATABASE IF NOT EXISTS `{}`", cfg.db_database)).execute(&root_pool).await;
68                        AnyPool::connect(&session_db_url).await.expect("Gagal terhubung setelah membuat DB session")
69                    } else {
70                        panic!("Gagal membuat database session otomatis: {:?}", e);
71                    }
72                } else {
73                    panic!("Gagal terhubung ke database session: {:?}", e);
74                }
75            }
76            #[cfg(not(feature = "mysql"))]
77            panic!("Gagal terhubung ke database session: {:?}", e);
78        }
79    };
80    
81    RustBasicSessionStore::new(session_pool)
82}
83
84pub async fn init_sessions(cfg: &Config) {
85    let db_url = if let Ok(url) = std::env::var("DATABASE_URL") {
86        url
87    } else if cfg.session_driver == "file" {
88        "sqlite:database/sessions.sqlite?mode=rwc".to_string()
89    } else if cfg.db_connection == "mysql" {
90        format!(
91            "mysql://{}:{}@{}:{}/{}",
92            cfg.db_username, cfg.db_password, cfg.db_host, cfg.db_port, cfg.db_database
93        )
94    } else {
95        format!("sqlite:database/{}.sqlite?mode=rwc", cfg.db_database)
96    };
97
98    sql::any::install_default_drivers();
99    let pool = AnyPool::connect(&db_url).await.expect("Gagal terhubung ke database session");
100
101    let sql = if cfg.db_connection == "mysql" {
102        "CREATE TABLE IF NOT EXISTS sessions (
103            id VARCHAR(255) PRIMARY KEY,
104            payload VARCHAR(8000) NOT NULL,
105            last_activity BIGINT NOT NULL,
106            ip_address VARCHAR(45)
107        )"
108    } else {
109        "CREATE TABLE IF NOT EXISTS sessions (
110            id VARCHAR(255) PRIMARY KEY,
111            payload TEXT NOT NULL,
112            last_activity BIGINT NOT NULL,
113            ip_address VARCHAR(45)
114        )"
115    };
116
117    sql::query(sql).execute(&pool).await.expect("Gagal membuat tabel session otomatis");
118}