diff options
Diffstat (limited to 'src/git/authorization.rs')
| -rw-r--r-- | src/git/authorization.rs | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/src/git/authorization.rs b/src/git/authorization.rs index 27107db..df780bb 100644 --- a/src/git/authorization.rs +++ b/src/git/authorization.rs | |||
| @@ -287,6 +287,39 @@ pub async fn fetch_repository_data( | |||
| 287 | }) | 287 | }) |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | /// Fetch repository data including announcements from purgatory | ||
| 291 | /// | ||
| 292 | /// This combines database announcements with purgatory announcements, | ||
| 293 | /// which is needed for authorization when the announcement hasn't been | ||
| 294 | /// promoted yet (no git data has arrived). | ||
| 295 | pub async fn fetch_repository_data_with_purgatory( | ||
| 296 | database: &SharedDatabase, | ||
| 297 | purgatory: &crate::purgatory::Purgatory, | ||
| 298 | identifier: &str, | ||
| 299 | ) -> Result<RepositoryData> { | ||
| 300 | // First, fetch from database | ||
| 301 | let mut repo_data = fetch_repository_data(database, identifier).await?; | ||
| 302 | |||
| 303 | // Then, add announcements from purgatory | ||
| 304 | let purgatory_announcements = purgatory.get_announcements_by_identifier(identifier); | ||
| 305 | let purgatory_count = purgatory_announcements.len(); | ||
| 306 | |||
| 307 | for entry in purgatory_announcements { | ||
| 308 | if let Ok(announcement) = RepositoryAnnouncement::from_event(entry.event) { | ||
| 309 | repo_data.announcements.push(announcement); | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | debug!( | ||
| 314 | "Fetched repository data with purgatory: {} announcements ({} from purgatory), {} states", | ||
| 315 | repo_data.announcements.len(), | ||
| 316 | purgatory_count, | ||
| 317 | repo_data.states.len() | ||
| 318 | ); | ||
| 319 | |||
| 320 | Ok(repo_data) | ||
| 321 | } | ||
| 322 | |||
| 290 | pub fn pubkey_authorised_for_repo_owners( | 323 | pub fn pubkey_authorised_for_repo_owners( |
| 291 | pubkey: &PublicKey, | 324 | pubkey: &PublicKey, |
| 292 | db_repo_data: &RepositoryData, | 325 | db_repo_data: &RepositoryData, |
| @@ -539,8 +572,9 @@ pub async fn get_state_authorization_for_specific_owner_repo( | |||
| 539 | use crate::git::list_refs; | 572 | use crate::git::list_refs; |
| 540 | use crate::purgatory::RefUpdate; | 573 | use crate::purgatory::RefUpdate; |
| 541 | 574 | ||
| 542 | // Fetch announcements only - we don't need database states | 575 | // Fetch announcements from database AND purgatory - needed for authorization |
| 543 | let repo_data = fetch_repository_data(database, identifier).await?; | 576 | // when the announcement hasn't been promoted yet (no git data has arrived) |
| 577 | let repo_data = fetch_repository_data_with_purgatory(database, purgatory, identifier).await?; | ||
| 544 | 578 | ||
| 545 | if repo_data.announcements.is_empty() { | 579 | if repo_data.announcements.is_empty() { |
| 546 | return Ok(AuthorizationResult::denied( | 580 | return Ok(AuthorizationResult::denied( |
| @@ -649,6 +683,27 @@ pub async fn get_state_authorization_for_specific_owner_repo( | |||
| 649 | .unwrap_or_else(|_| latest_authorized.pubkey.to_hex()) | 683 | .unwrap_or_else(|_| latest_authorized.pubkey.to_hex()) |
| 650 | ); | 684 | ); |
| 651 | 685 | ||
| 686 | // Extend purgatory announcement expiry for the owner. | ||
| 687 | // | ||
| 688 | // Per design doc decision #4: git auth extending a state event's expiry | ||
| 689 | // also extends the announcement's expiry. The repo is actively receiving | ||
| 690 | // git data, so the announcement should not expire prematurely. | ||
| 691 | // This also revives soft-expired announcements (recreates bare repo). | ||
| 692 | if let Ok(owner_pk) = PublicKey::parse(owner_pubkey) { | ||
| 693 | if purgatory.has_purgatory_announcement(&owner_pk, identifier) { | ||
| 694 | purgatory.extend_announcement_expiry( | ||
| 695 | &owner_pk, | ||
| 696 | identifier, | ||
| 697 | std::time::Duration::from_secs(1800), | ||
| 698 | ); | ||
| 699 | debug!( | ||
| 700 | identifier = %identifier, | ||
| 701 | owner = %owner_pubkey, | ||
| 702 | "Extended purgatory announcement expiry due to git push authorization" | ||
| 703 | ); | ||
| 704 | } | ||
| 705 | } | ||
| 706 | |||
| 652 | return Ok(AuthorizationResult { | 707 | return Ok(AuthorizationResult { |
| 653 | authorized: true, | 708 | authorized: true, |
| 654 | reason: "Authorized by state event in purgatory".to_string(), | 709 | reason: "Authorized by state event in purgatory".to_string(), |