rustbasic_cli/
database.rs1use std::fs;
2use rustbasic_core::Config;
3use rustbasic_core::database::connect;
4use base64::{Engine as _, engine::general_purpose};
5use rand::Rng;
6use regex::Regex;
7use colored::*;
8use sea_orm::ConnectionTrait;
9
10pub async fn clear_cache() {
11 println!("\n{}", "๐งน Cleaning Cache & Logs...".magenta().bold());
12
13 let log_dir = "storage/logs";
15 if let Ok(entries) = fs::read_dir(log_dir) {
16 let mut count = 0;
17 for entry in entries.flatten() {
18 let path = entry.path();
19 if path.is_file() {
20 let _ = fs::OpenOptions::new()
21 .write(true)
22 .truncate(true)
23 .open(&path);
24 count += 1;
25 }
26 }
27 println!(" {} Folder storage/logs telah dikosongkan. ({} file dibersihkan)", "โ
Logs:".green(), count);
28 } else {
29 println!(" {} Folder storage/logs tidak ditemukan.", "โ ๏ธ Logs:".yellow());
30 }
31
32 let cfg = Config::load();
34 let db = connect(&cfg).await;
35
36 let truncate_sql = if cfg.db_connection == "mysql" {
37 "TRUNCATE TABLE sessions"
38 } else {
39 "DELETE FROM sessions"
40 };
41
42 match db.execute(sea_orm::Statement::from_string(cfg.db_backend(), truncate_sql.to_string())).await {
43 Ok(_) => println!(" {} Tabel sessions telah dikosongkan.", "โ
Sessions:".green()),
44 Err(e) => println!(" {} Gagal membersihkan tabel sessions. ({})", "โ Error:".red(), e),
45 }
46
47 println!("\n{}", "โจ Cache berhasil dibersihkan!".green().bold());
48}
49
50pub fn generate_app_key() {
51 println!("\n{}", "๐ Generating Application Key...".magenta().bold());
52
53 let mut key = [0u8; 32];
54 rand::rng().fill_bytes(&mut key);
55
56 let encoded = general_purpose::STANDARD.encode(key);
57 let key_str = format!("base64:{}", encoded);
58
59 let env_path = ".env";
60 match fs::read_to_string(env_path) {
61 Ok(content) => {
62 let re = Regex::new(r"(?m)^APP_KEY=.*").unwrap();
63 let new_content = if re.is_match(&content) {
64 re.replace(&content, &format!("APP_KEY={}", key_str)).to_string()
65 } else {
66 format!("{}\nAPP_KEY={}", content.trim_end(), key_str)
67 };
68
69 if let Err(e) = fs::write(env_path, new_content) {
70 println!("{} Gagal menulis ke file .env: {}", "โ Error:".red(), e);
71 } else {
72 println!("{} {}", "โ
Application key set successfully:".green(), key_str.cyan());
73 println!("{}", "๐ก Pastikan untuk tidak membagikan APP_KEY ini ke publik!".dimmed());
74 }
75 }
76 Err(_) => {
77 println!("{} File .env tidak ditemukan.", "โ Error:".red());
78 }
79 }
80}
81
82pub async fn ensure_session() {
83 if !std::path::Path::new(".env").exists() {
84 return;
85 }
86
87 let _ = dotenvy::dotenv();
88 let cfg = Config::load();
89
90 let db_url = if cfg.db_connection == "mysql" {
92 format!(
93 "mysql://{}:{}@{}:{}/{}",
94 cfg.db_username, cfg.db_password, cfg.db_host, cfg.db_port, cfg.db_database
95 )
96 } else {
97 format!("sqlite:database/{}.sqlite?mode=rwc", cfg.db_database)
98 };
99
100 if cfg.db_connection != "mysql" {
102 let _ = std::fs::create_dir_all("database");
103 }
104
105 let mut opt = sea_orm::ConnectOptions::new(db_url);
106 opt.max_connections(5)
107 .connect_timeout(std::time::Duration::from_secs(3))
108 .sqlx_logging(false);
109
110 let db = match sea_orm::Database::connect(opt).await {
111 Ok(conn) => conn,
112 Err(_) => {
113 return;
115 }
116 };
117
118 let create_table_sql = if cfg.db_connection == "mysql" {
120 "CREATE TABLE IF NOT EXISTS sessions (
121 id VARCHAR(255) PRIMARY KEY,
122 payload TEXT NOT NULL,
123 last_activity BIGINT NOT NULL,
124 ip_address VARCHAR(45)
125 )"
126 } else {
127 "CREATE TABLE IF NOT EXISTS sessions (
128 id TEXT PRIMARY KEY,
129 payload TEXT NOT NULL,
130 last_activity BIGINT NOT NULL,
131 ip_address TEXT
132 )"
133 };
134
135 let stmt = sea_orm::Statement::from_string(db.get_database_backend(), create_table_sql.to_string());
136 if db.execute(stmt).await.is_err() {
137 return;
138 }
139
140 let session_file = ".rustbasic_session";
142 let mut session_id = String::new();
143 let mut need_to_write = false;
144
145 if let Ok(content) = fs::read_to_string(session_file) {
146 session_id = content.trim().to_string();
147 }
148
149 let mut session_exists = false;
150
151 if !session_id.is_empty() {
152 let check_sql = format!("SELECT id FROM sessions WHERE id = '{}'", session_id);
153 let stmt = sea_orm::Statement::from_string(db.get_database_backend(), check_sql);
154 if let Ok(Some(_)) = db.query_one(stmt).await {
155 session_exists = true;
156 }
157 }
158
159 if !session_exists {
160 let mut bytes = [0u8; 32];
161 rand::rng().fill_bytes(&mut bytes);
162 session_id = general_purpose::STANDARD.encode(bytes);
163 need_to_write = true;
164
165 let now = chrono::Utc::now().timestamp();
166 let insert_sql = format!(
167 "INSERT INTO sessions (id, payload, last_activity, ip_address) VALUES ('{}', '{}', {}, '{}')",
168 session_id, "{}", now, "127.0.0.1"
169 );
170 let stmt = sea_orm::Statement::from_string(db.get_database_backend(), insert_sql);
171 if db.execute(stmt).await.is_ok() {
172 println!("โจ {} ({})", "Session baru berhasil dibuat dan disimpan di database.".green().bold(), session_id.cyan());
173 }
174 } else {
175 let now = chrono::Utc::now().timestamp();
176 let update_sql = format!(
177 "UPDATE sessions SET last_activity = {} WHERE id = '{}'",
178 now, session_id
179 );
180 let stmt = sea_orm::Statement::from_string(db.get_database_backend(), update_sql);
181 let _ = db.execute(stmt).await;
182 }
183
184 if need_to_write {
185 let _ = fs::write(session_file, &session_id);
186 }
187}
188