upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/git/handlers.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-02-26 12:19:06 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-02-26 12:19:31 +0000
commitb13c6d924f7de5ff34405254b8bb21adf33c78c0 (patch)
tree67f5205d0b01cf9677b8b21fb3dce97954e51e30 /src/git/handlers.rs
parentfd6b098f41baf8621551f15114c50891642b5872 (diff)
send auth rejection reason to git client via ERR pkt-line
Previously push auth failures returned HTTP 403 which git clients display as a generic transport error. Now they return HTTP 200 with an ERR pkt-line containing the rejection reason (e.g. 'authorisation failed: No state events in purgatory'), which git displays directly. Remove GitError::Unauthorized as it is no longer used. GitError variants now represent only transport/infrastructure failures; app-level rejections use ERR pkt-line responses.
Diffstat (limited to 'src/git/handlers.rs')
-rw-r--r--src/git/handlers.rs17
1 files changed, 12 insertions, 5 deletions
diff --git a/src/git/handlers.rs b/src/git/handlers.rs
index f43cbb6..5ff3a7f 100644
--- a/src/git/handlers.rs
+++ b/src/git/handlers.rs
@@ -288,7 +288,10 @@ pub async fn handle_receive_pack(
288 Ok(auth_result) => { 288 Ok(auth_result) => {
289 if !auth_result.authorized { 289 if !auth_result.authorized {
290 warn!("Push rejected for {}: {}", identifier, auth_result.reason); 290 warn!("Push rejected for {}: {}", identifier, auth_result.reason);
291 return Err(GitError::Unauthorized); 291 return Ok(build_git_protocol_error_response(
292 GitService::ReceivePack,
293 &format!("authorisation failed: {}", auth_result.reason),
294 ));
292 } 295 }
293 info!( 296 info!(
294 "Push authorized for {} - {} maintainers, {} purgatory events: {}", 297 "Push authorized for {} - {} maintainers, {} purgatory events: {}",
@@ -301,7 +304,10 @@ pub async fn handle_receive_pack(
301 } 304 }
302 Err(e) => { 305 Err(e) => {
303 warn!("Authorization check failed for {}: {}", identifier, e); 306 warn!("Authorization check failed for {}: {}", identifier, e);
304 return Err(GitError::Unauthorized); 307 return Ok(build_git_protocol_error_response(
308 GitService::ReceivePack,
309 &format!("authorisation failed: {}", e),
310 ));
305 } 311 }
306 }; 312 };
307 313
@@ -442,13 +448,16 @@ pub async fn handle_receive_pack(
442} 448}
443 449
444/// Errors that can occur in Git handlers 450/// Errors that can occur in Git handlers
451///
452/// These represent transport/infrastructure failures, not application-level
453/// rejections. Application-level rejections (e.g. auth failures) are returned
454/// as HTTP 200 with an ERR pkt-line so git clients can display the message.
445#[derive(Debug)] 455#[derive(Debug)]
446pub enum GitError { 456pub enum GitError {
447 RepositoryNotFound, 457 RepositoryNotFound,
448 ProcessSpawnFailed(std::io::Error), 458 ProcessSpawnFailed(std::io::Error),
449 IoError(std::io::Error), 459 IoError(std::io::Error),
450 GitFailed(Option<i32>), 460 GitFailed(Option<i32>),
451 Unauthorized,
452} 461}
453 462
454impl std::fmt::Display for GitError { 463impl std::fmt::Display for GitError {
@@ -458,7 +467,6 @@ impl std::fmt::Display for GitError {
458 Self::ProcessSpawnFailed(e) => write!(f, "failed to spawn git process: {}", e), 467 Self::ProcessSpawnFailed(e) => write!(f, "failed to spawn git process: {}", e),
459 Self::IoError(e) => write!(f, "IO error: {}", e), 468 Self::IoError(e) => write!(f, "IO error: {}", e),
460 Self::GitFailed(code) => write!(f, "git process failed with code: {:?}", code), 469 Self::GitFailed(code) => write!(f, "git process failed with code: {:?}", code),
461 Self::Unauthorized => write!(f, "unauthorized"),
462 } 470 }
463 } 471 }
464} 472}
@@ -470,7 +478,6 @@ impl GitError {
470 pub fn status_code(&self) -> StatusCode { 478 pub fn status_code(&self) -> StatusCode {
471 match self { 479 match self {
472 Self::RepositoryNotFound => StatusCode::NOT_FOUND, 480 Self::RepositoryNotFound => StatusCode::NOT_FOUND,
473 Self::Unauthorized => StatusCode::FORBIDDEN,
474 _ => StatusCode::INTERNAL_SERVER_ERROR, 481 _ => StatusCode::INTERNAL_SERVER_ERROR,
475 } 482 }
476 } 483 }