ephemeris_forge_forgejo/reconcile/
access.rs1use ephemeris_forge::{AccessOperation, Caller, Observed, RepoRef, TeamName, UserName};
2
3use super::Client;
4use crate::api::{Api, ForgeError};
5use crate::config::Access;
6use crate::{Live, Permission};
7
8impl<A: Api> Client<A> {
9 pub(super) async fn read_access(
10 &self,
11 repository: &RepoRef,
12 config: Option<&Access>,
13 live: &mut Live,
14 ) -> Result<(), ForgeError> {
15 if config.is_none() {
16 return Ok(());
17 }
18 for team in self.api.teams(repository).await? {
19 let Some(name) = team.name.and_then(|name| TeamName::try_from(name).ok()) else {
20 continue;
21 };
22 if team.includes_all_repositories == Some(true) {
23 live.access.inherited_teams.insert(name.clone());
24 }
25 let permission = team.permission.as_deref().unwrap_or("none");
26 live.access.teams.insert(name, Observed::parse(permission));
27 }
28 live.access.organization_teams = self
29 .api
30 .organization_teams(repository.owner())
31 .await?
32 .into_iter()
33 .filter_map(|team| {
34 let permission = Observed::parse(team.permission.as_deref().unwrap_or("none"));
35 Some((TeamName::try_from(team.name?).ok()?, permission))
36 })
37 .collect();
38 live.access.collaborators = self
39 .api
40 .collaborators(repository)
41 .await?
42 .into_iter()
43 .filter_map(|collaborator| {
44 Some((
45 UserName::try_from(collaborator.login).ok()?,
46 Observed::parse(&collaborator.permission),
47 ))
48 })
49 .collect();
50 live.access.caller = Some(self.read_caller(repository.owner()).await?);
51 Ok(())
52 }
53
54 async fn read_caller(&self, organization: &str) -> Result<Caller, ForgeError> {
55 let login = self.api.current_user().await?;
56 let teams = self
57 .api
58 .user_teams()
59 .await?
60 .into_iter()
61 .filter(|team| {
62 team.organization
63 .as_ref()
64 .and_then(|owner| owner.username.as_deref())
65 .is_some_and(|name| name.eq_ignore_ascii_case(organization))
66 })
67 .filter_map(|team| TeamName::try_from(team.name?).ok())
68 .collect();
69 Ok(Caller::user(login, teams)?)
70 }
71
72 pub(super) async fn apply_access(
73 &self,
74 repository: &RepoRef,
75 operation: &AccessOperation<Permission>,
76 ) -> Result<(), ForgeError> {
77 match operation {
78 AccessOperation::AddTeam { team, permission } => {
79 self.api.add_team(repository, team, *permission).await
80 }
81 AccessOperation::RemoveTeam { team } => {
82 self.api.remove_team(repository, team.as_str()).await
83 }
84 AccessOperation::AddCollaborator { user, permission } => {
85 self.api
86 .add_collaborator(repository, user, *permission)
87 .await
88 }
89 AccessOperation::RemoveCollaborator { user } => {
90 self.api
91 .remove_collaborator(repository, user.as_str())
92 .await
93 }
94 }
95 }
96}