diff options
author | KunoiSayami <[email protected]> | 2021-05-13 22:40:05 +0800 |
---|---|---|
committer | KunoiSayami <[email protected]> | 2021-05-13 22:40:05 +0800 |
commit | 49b8c334a35bbdd7762ceae93445a051084c31f0 (patch) | |
tree | 80f17666e55fb4ba026af3da9cc38801d4e16788 | |
parent | c1dbab94eb6b9f5a7e8ab6f1b1bf217de3e13819 (diff) |
feat(core): Use timestamp file to determined should copy or notv0.3.7
* feat(test): Test will check post response validity
-rw-r--r-- | .gitignore | 7 | ||||
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/datastructures.rs | 61 | ||||
-rw-r--r-- | src/main.rs | 42 |
5 files changed, 87 insertions, 27 deletions
@@ -7,6 +7,7 @@ target/ **/*.rs.bk .idea/ -data/* -!data/*.default -.vscode/
\ No newline at end of file +.vscode/ + +# generate by cargo test +test/
\ No newline at end of file @@ -377,7 +377,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cgit-simple-authentication" -version = "0.3.6" +version = "0.3.7" dependencies = [ "anyhow", "argon2", @@ -1,6 +1,6 @@ [package] name = "cgit-simple-authentication" -version = "0.3.6" +version = "0.3.7" authors = ["KunoiSayami <[email protected]>"] edition = "2018" diff --git a/src/datastructures.rs b/src/datastructures.rs index 0a2b9f1..4fa72ab 100644 --- a/src/datastructures.rs +++ b/src/datastructures.rs @@ -30,6 +30,7 @@ use std::borrow::Cow; use std::fmt::Formatter; use std::fs::read_to_string; use std::path::{Path, PathBuf}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; use url::form_urlencoded; const DEFAULT_CONFIG_LOCATION: &str = "/etc/cgitrc"; @@ -135,16 +136,6 @@ impl Config { self.database.as_str() } - /* pub fn get_secret_warning(&self) -> &str { - if self.secret.is_empty() { - r#"<span color="red">Warning: You should specify secret in your cgitrc file.</span>"# - } else if self.secret.len() < MINIMUM_SECRET_LENGTH { - r#"<span color="yellow">Warning: You should set key length more than MINIMUM_SECRET_LENGTH.</span>"# - } else { - "" - } - }*/ - pub fn get_copied_database_location(&self) -> PathBuf { if self.test { return PathBuf::from(self.database.as_str()); @@ -165,6 +156,56 @@ impl Config { test: true, } } + + async fn read_timestamp_from_file<P: AsRef<Path>>(path: P) -> Result<u64> { + let mut file = tokio::fs::File::open(path).await?; + let mut buffer = String::new(); + file.read_to_string(&mut buffer).await?; + Ok(buffer.trim().parse()?) + } + + pub async fn get_last_commit_timestamp(&self) -> Result<u64> { + Self::read_timestamp_from_file(format!( + "{}/COMMIT", + if self.test { "test" } else { CACHE_DIR } + )) + .await + } + + pub async fn get_last_copy_timestamp(&self) -> Result<u64> { + Self::read_timestamp_from_file(format!( + "{}/COPIED", + if self.test { "test" } else { CACHE_DIR } + )) + .await + } + + async fn write_current_timestamp_to_file<P: AsRef<Path>>(path: P) -> Result<()> { + let mut file = tokio::fs::OpenOptions::new() + .create(true) + .write(true) + .open(path) + .await?; + file.write_all(format!("{}", get_current_timestamp()).as_bytes()) + .await?; + Ok(()) + } + + pub async fn write_database_commit_timestamp(&self) -> Result<()> { + Self::write_current_timestamp_to_file(format!( + "{}/COMMIT", + if self.test { "test" } else { CACHE_DIR } + )) + .await + } + + pub async fn write_last_copy_timestamp(&self) -> Result<()> { + Self::write_current_timestamp_to_file(format!( + "{}/COPIED", + if self.test { "test" } else { CACHE_DIR } + )) + .await + } } #[derive(Debug, Clone, Default)] diff --git a/src/main.rs b/src/main.rs index 2537301..1400fd2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -163,17 +163,21 @@ async fn cmd_init(cfg: Config) -> Result<()> { println!("Initialize the database successfully"); drop(conn); + + cfg.write_database_commit_timestamp().await?; Ok(()) } async fn verify_login(cfg: &Config, data: &FormData, redis_conn: redis::Client) -> Result<bool> { - // TODO: use timestamp to mark file diff - // or copy in init process if !cfg.test { - std::fs::copy( - cfg.get_database_location(), - cfg.get_copied_database_location(), - )?; + let last_copied = cfg.get_last_copy_timestamp().await.unwrap_or(0); + if last_copied == 0 || cfg.get_last_commit_timestamp().await.unwrap_or(0) != last_copied { + std::fs::copy( + cfg.get_database_location(), + cfg.get_copied_database_location(), + )?; + cfg.write_last_copy_timestamp().await?; + } } let mut rd = redis_conn.get_async_connection().await?; @@ -272,6 +276,8 @@ async fn cmd_add_user(matches: &ArgMatches<'_>, cfg: Config) -> Result<()> { println!("Insert {} ({}) to database", user, uid); drop(conn); + + cfg.write_database_commit_timestamp().await?; Ok(()) } @@ -325,6 +331,7 @@ async fn cmd_delete_user(matches: &ArgMatches<'_>, cfg: Config) -> Result<()> { println!("Delete {} from database", user); + cfg.write_database_commit_timestamp().await?; Ok(()) } @@ -347,6 +354,7 @@ async fn cmd_reset_database(matches: &ArgMatches<'_>, cfg: Config) -> Result<()> println!("Reset database successfully"); + cfg.write_database_commit_timestamp().await?; Ok(()) } @@ -409,6 +417,7 @@ async fn cmd_upgrade_database(cfg: Config) -> Result<()> { drop(origin_conn); tmp_dir.close()?; + cfg.write_database_commit_timestamp().await?; Ok(()) } @@ -588,6 +597,7 @@ mod test { Argon2, }; use redis::AsyncCommands; + use std::io::Write; use std::path::Path; use std::path::PathBuf; use std::thread::sleep; @@ -639,8 +649,6 @@ mod test { .unwrap(); } - fn write_test_result_to_redis() {} - fn test_auth_post() -> String { let correct_input = br#"redirect=/&username=hunter2&password=hunter2"#; let matches = get_arg_matches(Some(vec![ @@ -682,7 +690,8 @@ mod test { #[test] fn test_1_auth_failure() { let out = test_auth_post(); - assert!(out.starts_with("Status: 403")) + assert!(out.starts_with("Status: 403")); + assert!(out.ends_with("\n\n")); } #[test] @@ -729,8 +738,9 @@ mod test { .unwrap(); std::fs::File::create("test/USER_WRITTEN").unwrap(); } - _ => {} + _ => unreachable!(), } + assert!(Path::new("test/COMMIT").exists()) } #[test] @@ -739,7 +749,15 @@ mod test { let s = test_auth_post(); - println!("{}", s); - assert!(s.starts_with("Status: 302")) + let mut file = std::fs::OpenOptions::new() + .create(true) + .write(true) + .open("test/RESPONSE") + .unwrap(); + file.write_all(s.as_bytes()).unwrap(); + + assert!(s.starts_with("Status: 302")); + assert!(s.ends_with("\n\n")); + assert!(!Path::new("test/COPIED").exists()); } } |