diff options
Diffstat (limited to 'src/nostr/policy')
| -rw-r--r-- | src/nostr/policy/state.rs | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/src/nostr/policy/state.rs b/src/nostr/policy/state.rs index acb76a3..d26b5ec 100644 --- a/src/nostr/policy/state.rs +++ b/src/nostr/policy/state.rs | |||
| @@ -78,6 +78,46 @@ impl StatePolicy { | |||
| 78 | // Get all repositories and state events from db with identifier | 78 | // Get all repositories and state events from db with identifier |
| 79 | let db_repo_data = fetch_repository_data(&self.ctx.database, &state.identifier).await?; | 79 | let db_repo_data = fetch_repository_data(&self.ctx.database, &state.identifier).await?; |
| 80 | 80 | ||
| 81 | // CRITICAL: Check if author is authorized via maintainer set | ||
| 82 | // State events MUST be rejected if author is not in maintainer set of any accepted announcement | ||
| 83 | if db_repo_data.announcements.is_empty() { | ||
| 84 | tracing::warn!( | ||
| 85 | event_id = %event.id, | ||
| 86 | identifier = %state.identifier, | ||
| 87 | author = %event.pubkey.to_hex(), | ||
| 88 | "Rejecting state event: no announcement exists for this repository" | ||
| 89 | ); | ||
| 90 | return Ok(WritePolicyResult::Reject { | ||
| 91 | status: false, | ||
| 92 | message: "invalid: no announcement exists for this repository".into(), | ||
| 93 | }); | ||
| 94 | } | ||
| 95 | |||
| 96 | let authorized_owners = | ||
| 97 | crate::git::authorization::pubkey_authorised_for_repo_owners(&event.pubkey, &db_repo_data); | ||
| 98 | |||
| 99 | if authorized_owners.is_empty() { | ||
| 100 | tracing::warn!( | ||
| 101 | event_id = %event.id, | ||
| 102 | identifier = %state.identifier, | ||
| 103 | author = %event.pubkey.to_hex(), | ||
| 104 | announcements_count = db_repo_data.announcements.len(), | ||
| 105 | "Rejecting state event: author not in maintainer set of any announcement" | ||
| 106 | ); | ||
| 107 | return Ok(WritePolicyResult::Reject { | ||
| 108 | status: false, | ||
| 109 | message: "invalid: author not authorized for this repository".into(), | ||
| 110 | }); | ||
| 111 | } | ||
| 112 | |||
| 113 | tracing::debug!( | ||
| 114 | event_id = %event.id, | ||
| 115 | identifier = %state.identifier, | ||
| 116 | author = %event.pubkey.to_hex(), | ||
| 117 | authorized_for_owners = ?authorized_owners, | ||
| 118 | "State event author authorized via maintainer set" | ||
| 119 | ); | ||
| 120 | |||
| 81 | // Duplicate check in db | 121 | // Duplicate check in db |
| 82 | if db_repo_data.states.iter().any(|e| e.event.id.eq(&event.id)) { | 122 | if db_repo_data.states.iter().any(|e| e.event.id.eq(&event.id)) { |
| 83 | tracing::debug!("processed state event duplicate (in db): {}", event.id); | 123 | tracing::debug!("processed state event duplicate (in db): {}", event.id); |