Skip to content

Commit

Permalink
Validate users detected in some kinds of changes (#284)
Browse files Browse the repository at this point in the history
Signed-off-by: Sergio Castaño Arteaga <[email protected]>
  • Loading branch information
tegioz authored Nov 27, 2024
1 parent fc77bc3 commit e9c9714
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 4 deletions.
52 changes: 48 additions & 4 deletions clowarden-core/src/services/github/mod.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
//! This module contains the implementation of the GitHub service handler.
use anyhow::{Context, Result};
use std::collections::HashSet;

use anyhow::{format_err, Context, Result};
use as_any::Downcast;
use async_trait::async_trait;
use state::Changes;
use tracing::debug;

use crate::{
cfg::Organization,
directory::{DirectoryChange, UserName},
github::{DynGH, Source},
multierror::MultiError,
services::ChangeApplied,
};

Expand Down Expand Up @@ -56,6 +60,45 @@ impl Handler {
});
Ok(invitation_id)
}

/// Validate users found in some of the changes provided.
async fn validate_users(&self, ctx: &Ctx, changes: &Changes) -> Result<()> {
let mut merr = MultiError::new(Some("invalid github service configuration".to_string()));

// Collect users to validate from changes
let mut users_to_validate = HashSet::new();
for change in &changes.directory {
if let DirectoryChange::TeamMemberAdded(_, user_name) = change {
users_to_validate.insert(user_name);
}
}
for change in &changes.repositories {
if let RepositoryChange::CollaboratorAdded(_, user_name, _) = change {
users_to_validate.insert(user_name);
}
}

// Validate users collected
for user_name in users_to_validate {
match self.svc.get_user_login(ctx, user_name).await {
Ok(valid_user_name) => {
if user_name != &valid_user_name {
merr.push(format_err!(
"user[{user_name}]: invalid username, should be {valid_user_name}",
));
}
}
Err(err) => {
merr.push(format_err!("user[{user_name}]: error validating username: {err}"));
}
}
}

if merr.contains_errors() {
return Err(merr.into());
}
Ok(())
}
}

#[async_trait]
Expand All @@ -71,13 +114,14 @@ impl ServiceHandler for Handler {
.await
{
Ok(base_state) => {
let changes = base_state
.diff(&head_state)
let changes = base_state.diff(&head_state);
self.validate_users(&ctx, &changes).await?;
let repositories_changes = changes
.repositories
.into_iter()
.map(|change| Box::new(change) as DynChange)
.collect();
(changes, BaseRefConfigStatus::Valid)
(repositories_changes, BaseRefConfigStatus::Valid)
}
Err(_) => (vec![], BaseRefConfigStatus::Invalid),
};
Expand Down
9 changes: 9 additions & 0 deletions clowarden-core/src/services/github/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ pub trait Svc {
user_name: &UserName,
) -> Result<TeamMembership>;

/// Get user login.
async fn get_user_login(&self, ctx: &Ctx, user_name: &UserName) -> Result<UserName>;

/// List organization admins.
async fn list_org_admins(&self, ctx: &Ctx) -> Result<Vec<SimpleUser>>;

Expand Down Expand Up @@ -392,6 +395,12 @@ impl Svc for SvcApi {
Ok(client.teams().get_membership_for_user_in_org(&ctx.org, team_name, user_name).await?)
}

/// [Svc::get_user_login]
async fn get_user_login(&self, ctx: &Ctx, user_name: &UserName) -> Result<UserName> {
let client = self.setup_client(ctx.inst_id)?;
Ok(client.users().get_by_username_public_user(user_name).await?.login)
}

/// [Svc::list_org_admins]
async fn list_org_admins(&self, ctx: &Ctx) -> Result<Vec<SimpleUser>> {
#[cached(
Expand Down

0 comments on commit e9c9714

Please sign in to comment.