Skip to main content

rustbasic_core/
session.rs

1use axum_session::{SessionConfig, SessionStore, Key};
2use crate::Config;
3use crate::session_manager::RustBasicSessionStore;
4use sha2::{Sha512, Digest};
5use sqlx::AnyPool;
6use sea_orm::{ConnectionTrait, Database, sea_query, Iden};
7use sea_query::{Table, ColumnDef};
8
9#[derive(Iden)]
10enum Sessions {
11    Table,
12    Id,
13    Payload,
14    LastActivity,
15    IpAddress,
16}
17
18pub async fn setup_session(cfg: &Config) -> SessionStore<RustBasicSessionStore> {
19    // 1. Decode APP_KEY
20    let key_bytes = if cfg.app_key.starts_with("base64:") {
21        use base64::{Engine as _, engine::general_purpose};
22        general_purpose::STANDARD.decode(&cfg.app_key[7..]).unwrap_or_else(|_| cfg.app_key.as_bytes().to_vec())
23    } else {
24        cfg.app_key.as_bytes().to_vec()
25    };
26    
27    // 2. Derive 64-byte key using Sha512
28    let mut hasher = Sha512::new();
29    hasher.update(&key_bytes);
30    let final_key = hasher.finalize();
31    let session_key = Key::from(&final_key);
32
33    // 3. Setup Session Config
34    let session_config = SessionConfig::default()
35        .with_table_name("sessions")
36        .with_key(session_key);
37
38    // 4. Determine Session DB URL
39    let session_db_url = if cfg.session_driver == "file" {
40        "sqlite:database/sessions.sqlite?mode=rwc".to_string()
41    } else if cfg.db_connection == "mysql" {
42        format!(
43            "mysql://{}:{}@{}:{}/{}",
44            cfg.db_username, cfg.db_password, cfg.db_host, cfg.db_port, cfg.db_database
45        )
46    } else {
47        format!("sqlite:database/{}.sqlite?mode=rwc", cfg.db_database)
48    };
49
50    // 5. Connect and Create Store
51    sqlx::any::install_default_drivers();
52    let session_pool = match AnyPool::connect(&session_db_url).await {
53        Ok(pool) => pool,
54        Err(e) => {
55            let err_msg = e.to_string();
56            if (err_msg.contains("1049") || err_msg.contains("Unknown database")) && cfg.db_connection == "mysql" {
57                let root_url = format!("mysql://{}:{}@{}:{}", cfg.db_username, cfg.db_password, cfg.db_host, cfg.db_port);
58                if let Ok(root_pool) = sqlx::MySqlPool::connect(&root_url).await {
59                    let _ = sqlx::query(&format!("CREATE DATABASE IF NOT EXISTS `{}`", cfg.db_database)).execute(&root_pool).await;
60                    AnyPool::connect(&session_db_url).await.expect("Gagal terhubung setelah membuat DB session")
61                } else {
62                    panic!("Gagal membuat database session otomatis: {:?}", e);
63                }
64            } else {
65                panic!("Gagal terhubung ke database session: {:?}", e);
66            }
67        }
68    };
69    
70    SessionStore::<RustBasicSessionStore>::new(
71        Some(RustBasicSessionStore::new(session_pool)), 
72        session_config
73    ).await.expect("Gagal menginisialisasi SessionStore")
74}
75
76pub async fn init_sessions(cfg: &Config) {
77    let db_url = if cfg.session_driver == "file" {
78        "sqlite:database/sessions.sqlite?mode=rwc".to_string()
79    } else if cfg.db_connection == "mysql" {
80        format!(
81            "mysql://{}:{}@{}:{}/{}",
82            cfg.db_username, cfg.db_password, cfg.db_host, cfg.db_port, cfg.db_database
83        )
84    } else {
85        format!("sqlite:database/{}.sqlite?mode=rwc", cfg.db_database)
86    };
87
88    let db = Database::connect(&db_url).await.expect("Gagal terhubung ke database session");
89    let builder = db.get_database_backend();
90
91    // 2. Auto-Create Table Sessions jika belum ada menggunakan Sea-ORM
92    let table = Table::create()
93        .table(Sessions::Table)
94        .if_not_exists()
95        .col(ColumnDef::new(Sessions::Id).string_len(255).primary_key())
96        .col(ColumnDef::new(Sessions::Payload).text().not_null())
97        .col(ColumnDef::new(Sessions::LastActivity).big_integer().not_null())
98        .col(ColumnDef::new(Sessions::IpAddress).string_len(45))
99        .to_owned();
100
101    db.execute(builder.build(&table))
102        .await
103        .expect("Gagal membuat tabel session otomatis");
104}