rustbasic_core/
session.rs1use 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 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 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 let session_config = SessionConfig::default()
35 .with_table_name("sessions")
36 .with_key(session_key);
37
38 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 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 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}