ephemeris_forge/
refusal.rs1use crate::{Lockout, RepoRef, Report};
2
3#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
5pub enum Refusal {
6 #[error("administering {repository} requires the admin permission, which the token lacks")]
8 AdminRequired {
9 repository: RepoRef,
11 },
12 #[error(
14 "applying would remove the caller's own access through {}, so the configuration must \
15 declare them",
16 lockouts.iter().map(ToString::to_string).collect::<Vec<_>>().join(", ")
17 )]
18 Lockout {
19 lockouts: Vec<Lockout>,
21 },
22 #[error("the repository is archived, so apply refuses to write anything")]
24 Archived,
25}
26
27impl Report {
28 #[must_use]
30 pub fn refusal(&self, repository: &RepoRef) -> Option<Refusal> {
31 if self.admin == Some(false) {
32 return Some(Refusal::AdminRequired {
33 repository: repository.clone(),
34 });
35 }
36 if !self.lockouts.is_empty() {
37 return Some(Refusal::Lockout {
38 lockouts: self.lockouts.clone(),
39 });
40 }
41 self.archived.then_some(Refusal::Archived)
42 }
43
44 pub fn lines(&self) -> impl Iterator<Item = String> + '_ {
46 self.changes
47 .iter()
48 .flat_map(|(resource, change)| change.lines(resource))
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 fn repository() -> RepoRef {
57 "owner/name".parse().expect("valid")
58 }
59
60 #[test]
61 fn a_clean_report_has_no_refusal() {
62 assert_eq!(Report::default().refusal(&repository()), None);
63 }
64
65 #[test]
66 fn a_missing_admin_permission_comes_first() {
67 let report = Report {
68 admin: Some(false),
69 archived: true,
70 ..Report::default()
71 };
72 assert_eq!(
73 report.refusal(&repository()),
74 Some(Refusal::AdminRequired {
75 repository: repository()
76 })
77 );
78 }
79
80 #[test]
81 fn an_archived_repository_is_refused() {
82 let report = Report {
83 archived: true,
84 ..Report::default()
85 };
86 assert_eq!(report.refusal(&repository()), Some(Refusal::Archived));
87 }
88}