From 3c59f9494f6b3cf9c8f9fb6cca0580d053329cf0 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Thu, 30 Mar 2023 00:03:59 +0200 Subject: Update path restrictions to allow shared repos --- src/git.rs | 54 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/git.rs b/src/git.rs index dcdb71b..7337a6a 100644 --- a/src/git.rs +++ b/src/git.rs @@ -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 { 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 { @@ -23,26 +24,45 @@ fn group_git_dir(group: &str) -> Result { 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 { - let valid_dir = personal_git_dir()?; - let relative_path = match path.strip_prefix(&valid_dir) { +fn is_valid_git_repo_path(path: &PathBuf) -> Result { + 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) -> Result { @@ -80,7 +100,7 @@ pub fn init(repo_name: &str, group: &Option) -> Result 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); } -- cgit v1.2.3