Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate users detected in some kinds of changes #284

Merged
merged 1 commit into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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