diff options
author | Justin Wernick <justin@worthe-it.co.za> | 2023-03-30 00:03:59 +0200 |
---|---|---|
committer | Justin Wernick <justin@worthe-it.co.za> | 2023-03-30 00:03:59 +0200 |
commit | 3c59f9494f6b3cf9c8f9fb6cca0580d053329cf0 (patch) | |
tree | d5c80b5cdf79c8e377c085de5bde2af6abbecc7c /src | |
parent | 745cd8ab27480a3cf516a2684db2c4fd7cf2144c (diff) |
Update path restrictions to allow shared repos
Diffstat (limited to 'src')
-rw-r--r-- | src/git.rs | 54 |
1 files changed, 37 insertions, 17 deletions
@@ -3,19 +3,20 @@ use crate::{ ShackleError, }; use git2::{Repository, RepositoryInitMode, RepositoryInitOptions}; -use std::{ - path::{Path, PathBuf}, - process::Command, -}; +use std::{path::PathBuf, process::Command}; use user_info::{get_user_groups, get_username}; pub struct GitInitResult { pub path: PathBuf, } +fn git_dir_prefix() -> PathBuf { + PathBuf::from("git") +} + fn personal_git_dir() -> Result<PathBuf, ShackleError> { let username = get_username().ok_or(ShackleError::UserReadError)?; - Ok(Path::new("git").join(username)) + Ok(git_dir_prefix().join(username)) } fn group_git_dir(group: &str) -> Result<PathBuf, ShackleError> { @@ -23,26 +24,45 @@ fn group_git_dir(group: &str) -> Result<PathBuf, ShackleError> { if !groups.iter().any(|g| g == group) { Err(ShackleError::InvalidGroup) } else { - Ok(Path::new("git").join(group)) + Ok(git_dir_prefix().join(group)) } } -fn is_valid_personal_git_repo(path: &PathBuf) -> Result<bool, ShackleError> { - let valid_dir = personal_git_dir()?; - let relative_path = match path.strip_prefix(&valid_dir) { +fn is_valid_git_repo_path(path: &PathBuf) -> Result<bool, ShackleError> { + let prefix = git_dir_prefix(); + let relative_path = match path.strip_prefix(&prefix) { Ok(relative_path) => relative_path, Err(_) => { return Ok(false); } }; - if relative_path.parent() != Some(Path::new("")) - || relative_path.extension().map(|ext| ext == "git") != Some(true) - { - return Ok(false); + let mut it = relative_path.iter(); + let group = it.next(); + let repo_name = it.next(); + let end = it.next(); + + match (group, repo_name, end) { + (_, _, Some(_)) | (None, _, _) | (_, None, _) => Ok(false), + (Some(group_name), Some(_repo_name), _) => { + if relative_path.extension().map(|ext| ext == "git") != Some(true) { + Ok(false) + } else { + let group_name = group_name.to_string_lossy(); + + let user_name = get_username(); + let is_valid_personal_repo_path = user_name + .map(|user_name| user_name == group_name) + .unwrap_or(false); + + let user_groups = get_user_groups(); + let is_valid_shared_repo_path = + user_groups.iter().any(|group| group.as_ref() == group_name); + + Ok(is_valid_personal_repo_path || is_valid_shared_repo_path) + } + } } - - Ok(true) } pub fn init(repo_name: &str, group: &Option<String>) -> Result<GitInitResult, ShackleError> { @@ -80,7 +100,7 @@ pub fn init(repo_name: &str, group: &Option<String>) -> Result<GitInitResult, Sh } pub fn upload_pack(upload_pack_args: &GitUploadPackArgs) -> Result<(), ShackleError> { - if !is_valid_personal_git_repo(&upload_pack_args.directory)? { + if !is_valid_git_repo_path(&upload_pack_args.directory)? { return Err(ShackleError::InvalidDirectory); } @@ -107,7 +127,7 @@ pub fn upload_pack(upload_pack_args: &GitUploadPackArgs) -> Result<(), ShackleEr } pub fn receive_pack(receive_pack_args: &GitReceivePackArgs) -> Result<(), ShackleError> { - if !is_valid_personal_git_repo(&receive_pack_args.directory)? { + if !is_valid_git_repo_path(&receive_pack_args.directory)? { return Err(ShackleError::InvalidDirectory); } |