aboutsummaryrefslogtreecommitdiff
path: root/src/datastructures.rs
diff options
context:
space:
mode:
authorKunoiSayami <[email protected]>2021-07-13 00:13:44 +0800
committerKunoiSayami <[email protected]>2021-07-13 00:13:44 +0800
commit29680c6a0ac46684ad6c6712896649f6acff737f (patch)
tree9cfc603f103345198bff5e175504c61d2b90908c /src/datastructures.rs
parente92521c9143fb41fbb664ac6864e575fd79416b3 (diff)
feat(core): Rewritten configure file parserv3.0.0
* feat(core): Support full protect mode * feat(test): Reduced sleeping time and support new parser * feat(crate): Bump version
Diffstat (limited to 'src/datastructures.rs')
-rw-r--r--src/datastructures.rs258
1 files changed, 174 insertions, 84 deletions
diff --git a/src/datastructures.rs b/src/datastructures.rs
index 51f000c..6e03679 100644
--- a/src/datastructures.rs
+++ b/src/datastructures.rs
@@ -79,26 +79,7 @@ pub struct Config {
database: String,
pub bypass_root: bool,
pub(crate) test: bool,
-
- /// To set specify repository protect, You should setup repo's protect attribute
- /// First, set cgit-simple-auth-protect to none in /etc/cgitrc file
- ///
- /// # Examples
- ///
- /// In /etc/cgitrc:
- /// ```conf
- /// cgit-simple-auth-full-protect=false
- /// ```
- ///
- /// In repo.conf
- /// ```conf
- /// repo.url=test
- /// repo.protect=true
- /// ```
- ///
- /// Default behavior is protect all repository
- protect_all: bool,
- protected_repos: Vec<String>,
+ protect_config: ProtectSettings,
}
impl Default for Config {
@@ -108,8 +89,7 @@ impl Default for Config {
database: DEFAULT_DATABASE_LOCATION.to_string(),
bypass_root: false,
test: false,
- protect_all: true,
- protected_repos: Default::default(),
+ protect_config: Default::default()
}
}
}
@@ -125,7 +105,8 @@ impl Config {
let mut cookie_ttl: u64 = DEFAULT_COOKIE_TTL;
let mut database: &str = "/etc/cgit/auth.db";
let mut bypass_root: bool = false;
- let mut protect_all: bool = true;
+ let mut protect_enabled: bool = true;
+ let mut protect_white_list_mode: bool = true;
for line in file.lines() {
let line = line.trim();
@@ -144,71 +125,35 @@ impl Config {
"cookie-ttl" => cookie_ttl = value.parse().unwrap_or(DEFAULT_COOKIE_TTL),
"database" => database = value,
"bypass-root" => bypass_root = value.to_lowercase().eq("true"),
- "full-protect" => protect_all = !value.to_lowercase().eq("false"),
+ "protect" => {
+ match value.to_lowercase().as_str() {
+ "full" => {
+ protect_enabled = true;
+ protect_white_list_mode = true;
+ }
+ "part" => {
+ protect_enabled = true;
+ protect_white_list_mode = false;
+ }
+ "none" => {
+ protect_enabled = false;
+ }
+ _ => {}
+ }
+ },
_ => {}
}
}
- let protected_repos = if !protect_all {
- Self::load_protect_repos_from_file(path)
- } else {
- Default::default()
- };
-
Self {
cookie_ttl,
database: database.to_string(),
bypass_root,
test: false,
- protect_all,
- protected_repos,
+ protect_config: ProtectSettings::from_path(protect_enabled, protect_white_list_mode, path)
}
}
- pub fn load_protect_repos_from_file<P: AsRef<Path>>(path: P) -> Vec<String> {
- let context = read_to_string(path).unwrap();
-
- let mut protect_repos = Vec::new();
-
- let mut current_repo: &str = "";
-
- for line in context.lines() {
- let line = line.trim();
- if line.starts_with('#') || !line.contains('=') {
- continue;
- }
-
- 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;
- }
-
- if key.eq("repo.protect")
- && 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_protect_repos_from_file(value);
- protect_repos.extend(r)
- }
- }
- protect_repos
- }
-
pub fn get_database_location(&self) -> &str {
self.database.as_str()
}
@@ -276,15 +221,12 @@ impl Config {
}
pub fn check_repo_protect(&self, repo: &str) -> bool {
- if self.protect_all {
- return true;
- }
- self.protected_repos.iter().any(|x| x.eq(repo))
+ self.protect_config.check_repo_protect(repo)
}
#[cfg(test)]
- pub(crate) fn query_is_all_protected(&self) -> bool {
- self.protect_all
+ pub(crate) fn get_white_list_mode_status(&self) -> bool {
+ self.protect_config.get_white_list_mode_status()
}
}
@@ -295,12 +237,160 @@ impl TestSuite for Config {
bypass_root: false,
cookie_ttl: DEFAULT_COOKIE_TTL,
test: true,
- protect_all: false,
- protected_repos: vec!["test".to_string(), "repo".to_string()],
+ protect_config: ProtectSettings::generate_test_config()
+ }
+ }
+}
+
+
+
+/// To set specify repository protect, You should setup repo's protect attribute
+/// First, set cgit-simple-auth-protect to none in /etc/cgitrc file
+///
+/// # Examples
+///
+/// In /etc/cgitrc:
+/// ```conf
+/// # Available value: full, part, none
+/// cgit-simple-auth-protect=none
+/// ```
+///
+/// If option set to `part`, only some repositories will be protected
+/// which is enabled protect manually by `repo.protect=true`
+///
+/// If option set to `full`, vice versa. You can manually disable protection
+/// by set `repo.protect=false`
+///
+///
+/// In repo.conf
+/// ```conf
+/// repo.url=test
+/// repo.protect=true
+/// ```
+///
+/// If option set to `none`, all protection will be disabled.
+///
+/// Default behavior is protect all repository
+
+#[derive(Debug, Clone, Default)]
+struct ProtectSettings {
+ protect_enabled: bool,
+ /// If white list mode set to true,
+ /// Only repository in repos is unprotected
+ protect_white_list_mode: bool,
+ repos: Vec<String>
+}
+
+impl ProtectSettings {
+ pub fn from_path<P: AsRef<Path>>(protect_enabled: bool, protect_white_list_mode: bool, path: P) -> Self {
+ Self {
+ protect_enabled,
+ protect_white_list_mode,
+ repos: if protect_enabled {
+ Self::load_repos_from_path(protect_white_list_mode, path)
+ } else {
+ Default::default()
+ }
+ }
+ }
+
+ fn load_repos_from_path<P: AsRef<Path>>(white_list_mode: bool, path: P) -> Vec<String> {
+ let context = read_to_string(path).unwrap();
+
+ Self::load_repos_from_context(white_list_mode, &context)
+
+ }
+
+ fn load_repos_from_context(white_list_mode: bool, s: &String) -> Vec<String> {
+ let mut repos: Vec<String> = Default::default();
+
+ let mut last_insert_repo = "";
+ let mut last_repo = "";
+
+ for line in s.trim().lines() {
+ let line = line.trim();
+
+ if line.is_empty() || line.starts_with('#') || !line.contains('=') {
+ continue
+ }
+
+ let (key, value) = if line.contains('#') {
+ line.split_once('#')
+ .unwrap()
+ .0
+ .trim()
+ .split_once('=')
+ .unwrap()
+ } else {
+ line.split_once('=').unwrap()
+ };
+
+ if key.eq("include") {
+ repos.extend(Self::load_repos_from_path(white_list_mode, value));
+ continue
+ }
+
+ if !key.starts_with("repo.") {
+ continue
+ }
+
+ let (_, key) = key.split_once(".").unwrap();
+
+
+ if key.eq("url") {
+ last_repo = value;
+ }
+
+ if key.eq("protect") {
+ if last_repo.is_empty() {
+ continue
+ }
+ let value = value.to_lowercase();
+
+ if (white_list_mode && value.eq("false")) || (!white_list_mode && value.eq("true")) {
+ if last_insert_repo.eq(last_repo) {
+ log::warn!("Found duplicate options in repo {}", last_repo);
+ continue
+ }
+ repos.push(last_repo.to_string());
+ last_insert_repo = last_repo;
+ }
+ }
+
+ }
+ repos
+ }
+
+ pub fn check_repo_protect(&self, repo: &str) -> bool {
+ if !self.protect_enabled {
+ return false;
+ }
+ let ret = self.repos.iter().any(|x| x.eq(repo));
+ if self.protect_white_list_mode {
+ !ret
+ } else {
+ ret
+ }
+ }
+
+ #[cfg(test)]
+ pub(crate) fn get_white_list_mode_status(&self) -> bool {
+ self.protect_white_list_mode
+ }
+
+}
+
+impl TestSuite for ProtectSettings {
+ fn generate_test_config() -> Self {
+ Self {
+ protect_enabled: true,
+ protect_white_list_mode: false,
+ repos: vec!["test".to_string(), "repo".to_string()],
}
}
}
+
#[derive(Debug, Clone, Default)]
pub struct FormData {
user: String,