diff options
| author | KunoiSayami <[email protected]> | 2021-05-15 00:58:56 +0800 |
|---|---|---|
| committer | KunoiSayami <[email protected]> | 2021-05-15 01:02:20 +0800 |
| commit | 722d7da76380d8f3814f5f2a59e3ef14928b6203 (patch) | |
| tree | f103015d9bf8190d85f20c81f3c1eed035599d45 /src/datastructures.rs | |
| parent | daa61c3e0c96800c58931f1e933462b462fc7b66 (diff) | |
feat(core): Add per-repository protect optionv0.4.0
* feat(auth): Support per-repository user authenticate
* feat(test): Support new configure structure test
* refactor(database): Upgrade database structure to v3
Diffstat (limited to 'src/datastructures.rs')
| -rw-r--r-- | src/datastructures.rs | 148 |
1 files changed, 107 insertions, 41 deletions
diff --git a/src/datastructures.rs b/src/datastructures.rs index 4fa72ab..81e04aa 100644 --- a/src/datastructures.rs +++ b/src/datastructures.rs @@ -70,6 +70,10 @@ pub fn rand_str(len: usize) -> String { password } +pub(crate) trait TestSuite { + fn generate_test_config() -> Self; +} + #[derive(Debug, Clone)] pub struct Config { pub cookie_ttl: u64, @@ -78,6 +82,7 @@ pub struct Config { pub bypass_root: bool, //secret: String, pub(crate) test: bool, + protected_repos: ProtectedRepo, } impl Default for Config { @@ -88,6 +93,7 @@ impl Default for Config { bypass_root: false, //secret: Default::default(), test: false, + protected_repos: Default::default(), } } } @@ -98,7 +104,7 @@ impl Config { } pub fn load_from_path<P: AsRef<Path>>(path: P) -> Self { - let file = read_to_string(path).unwrap_or_default(); + let file = read_to_string(&path).unwrap_or_default(); let mut cookie_ttl: u64 = DEFAULT_COOKIE_TTL; let mut database: &str = "/etc/cgit/auth.db"; let mut bypass_root: bool = false; @@ -129,6 +135,7 @@ impl Config { bypass_root, test: false, //secret: secret.to_string(), + protected_repos: ProtectedRepo::load_from_file(path), } } @@ -148,15 +155,6 @@ impl Config { ) } - pub(crate) fn generate_test_config() -> Self { - Self { - database: "test/tmp.db".to_string(), - bypass_root: false, - cookie_ttl: DEFAULT_COOKIE_TTL, - 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(); @@ -206,6 +204,22 @@ impl Config { )) .await } + + pub fn check_repo_protect(&self, repo: &str) -> bool { + self.protected_repos.query_is_protected(repo) + } +} + +impl TestSuite for Config { + fn generate_test_config() -> Self { + Self { + database: "test/tmp.db".to_string(), + bypass_root: false, + cookie_ttl: DEFAULT_COOKIE_TTL, + test: true, + protected_repos: Default::default(), + } + } } #[derive(Debug, Clone, Default)] @@ -365,6 +379,7 @@ impl Cookie { format!("{}_{}", self.timestamp, self.randint) } + #[allow(dead_code)] pub fn get_user(&self) -> &str { self.user.as_str() } @@ -388,48 +403,99 @@ impl std::fmt::Display for Cookie { } } -/* -pub struct CookieOrigin { - timestamp: u64, - randint: RandIntType, - user: String, - rand_str: String, + +/// To set specify repository protect, You should setup repo's protect attribute +/// +/// # Examples +/// +/// ```conf +/// repo.url=test +/// repo.protected=true +/// ``` +/// +/// OR: +/// +/// Set all repository under protected, by set cgit-simple-auth-protect=full + +#[derive(Debug, Clone)] +pub struct ProtectedRepo { + protect_all: bool, + protect_repos: Vec<String>, } -impl CookieOrigin { - pub fn new(randint: RandIntType, user: &String, rand_str: &String) -> Self { - Self { - timestamp: get_current_timestamp(), - randint, - user: user.clone(), - rand_str: rand_str.clone(), - } - } +impl ProtectedRepo { - pub async fn to_cookie(&self, cfg: &Config) -> Result<Cookie> { - let mut file = File::open(Path::new(CACHE_DIR).join(DEFAULT_IV_FILE_NAME)).await?; - let mut context = String::new(); - file.read_to_string(&mut context).await?; - let iv_file: IvFile = serde_json::from_str(&context)?; - let key = cfg.secret.to_hex(); - let iv = iv_file.iv.to_hex(); + pub fn load_from_file<P: AsRef<Path>>(path: P) -> Self { + let context = read_to_string(path).unwrap(); - let mut cipher = Blowfish::new(key); + let mut protect_repos = Vec::new(); - cipher.write_all().awa + let mut protect_all = false; + let mut current_repo: &str = ""; - let mut buffer = [0u8, 128]; + for line in context.lines() { + let line = line.trim(); + if line.starts_with('#') || !line.contains('=') { + continue + } - let plain_text = format!("{}, {}", self.user, self.rand_str); + let (key, value) = if line.contains('#') { + line.split_once('#').unwrap().0.trim().split_once('=').unwrap() + } else { + line.split_once('=').unwrap() + }; + + if key.eq("repo.url") { + current_repo = value.trim(); + continue + } - let pos = plain_text.len(); + if key.eq("repo.protect") { + if value.trim().to_lowercase().eq("true") && !current_repo.is_empty() { + protect_repos.push(current_repo.to_string()); + } + } + + if key.eq("include") { + let r = Self::load_from_file(value); + if r.protect_all { + protect_all = true; + break + } + protect_repos.extend(r.protect_repos) + } - buffer[..pos].copy_from_slice(plain_text.as_bytes()); + if key.eq("cgit-simple-auth-protect") && value.trim().to_lowercase().eq("full") { + protect_all = true; + break + } + } + if protect_all { + protect_repos.clear(); + } + Self { + protect_all, + protect_repos, + } + } - let b = Block::from_mut_slice(&mut buffer); + pub fn query_is_protected(&self, repo: &str) -> bool { + if self.protect_all { + return true + } + self.protect_repos.iter().any(|x| x.eq(repo)) + } + pub fn query_is_all_protected(&self) -> bool { + self.protect_all + } +} - Ok(()) +impl Default for ProtectedRepo { + fn default() -> Self { + Self { + protect_all: true, + protect_repos: Default::default() + } } } -*/ |
