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

feat: use user id instead of username #56

Merged
merged 2 commits into from
Mar 30, 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
2 changes: 1 addition & 1 deletion src/bors/handlers/trybuild.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ async fn check_try_permissions<Client: RepositoryClient>(
) -> anyhow::Result<bool> {
let result = if !repo
.permissions_resolver
.has_permission(&author.username, PermissionType::Try)
.has_permission(&author.id, PermissionType::Try)
.await
{
tracing::info!("Permission denied");
Expand Down
2 changes: 2 additions & 0 deletions src/github/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! for working with (GitHub) repositories.
use std::fmt::{Debug, Display, Formatter};

use octocrab::models::UserId;
use url::Url;

pub mod api;
Expand Down Expand Up @@ -46,6 +47,7 @@ impl Display for GithubRepoName {

#[derive(Debug, PartialEq)]
pub struct GithubUser {
pub id: UserId,
pub username: String,
pub html_url: Url,
}
Expand Down
10 changes: 10 additions & 0 deletions src/github/webhook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ fn parse_comment_from_pr_review(

fn parse_user(user: Author) -> GithubUser {
GithubUser {
id: user.id,
username: user.login,
html_url: user.html_url,
}
Expand Down Expand Up @@ -381,6 +382,9 @@ mod tests {
name: "bors-kindergarten",
},
author: GithubUser {
id: UserId(
4539057,
),
username: "Kobzol",
html_url: Url {
scheme: "https",
Expand Down Expand Up @@ -424,6 +428,9 @@ mod tests {
name: "bors-kindergarten",
},
author: GithubUser {
id: UserId(
4539057,
),
username: "Kobzol",
html_url: Url {
scheme: "https",
Expand Down Expand Up @@ -467,6 +474,9 @@ mod tests {
name: "bors-kindergarten",
},
author: GithubUser {
id: UserId(
4539057,
),
username: "Kobzol",
html_url: Url {
scheme: "https",
Expand Down
23 changes: 12 additions & 11 deletions src/permissions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use axum::async_trait;
use octocrab::models::UserId;
use std::collections::HashSet;
use tokio::sync::Mutex;

Expand All @@ -14,7 +15,7 @@
/// Decides if a GitHub user can perform various actions using the bot.
#[async_trait]
pub trait PermissionResolver {
async fn has_permission(&self, username: &str, permission: PermissionType) -> bool;
async fn has_permission(&self, user_id: &UserId, permission: PermissionType) -> bool;
async fn reload(&self);
}

Expand Down Expand Up @@ -46,11 +47,11 @@

#[async_trait]
impl PermissionResolver for TeamApiPermissionResolver {
async fn has_permission(&self, username: &str, permission: PermissionType) -> bool {
async fn has_permission(&self, user_id: &UserId, permission: PermissionType) -> bool {
self.permissions
.lock()
.await
.has_permission(username, permission)
.has_permission(user_id, permission)
}

async fn reload(&self) {
Expand All @@ -59,15 +60,15 @@
}

pub struct UserPermissions {
review_users: HashSet<String>,
try_users: HashSet<String>,
review_users: HashSet<UserId>,
try_users: HashSet<UserId>,
}

impl UserPermissions {
fn has_permission(&self, username: &str, permission: PermissionType) -> bool {
fn has_permission(&self, user_id: &UserId, permission: PermissionType) -> bool {
match permission {
PermissionType::Review => self.review_users.contains(username),
PermissionType::Try => self.try_users.contains(username),
PermissionType::Review => self.review_users.contains(user_id),
PermissionType::Try => self.try_users.contains(user_id),
}
}
}
Expand All @@ -90,20 +91,20 @@

#[derive(serde::Deserialize)]
struct UserPermissionsResponse {
github_users: HashSet<String>,
github_ids: HashSet<UserId>,
}

/// Loads users that are allowed to perform try/review from the Rust Team API.
async fn load_users_from_team_api(
repository_name: &str,
permission: PermissionType,
) -> anyhow::Result<HashSet<String>> {
) -> anyhow::Result<HashSet<UserId>> {
let permission = match permission {
PermissionType::Review => "review",
PermissionType::Try => "try",
};

let normalized_name = repository_name.replace("-", "_");

Check warning on line 107 in src/permissions.rs

View workflow job for this annotation

GitHub Actions / Test

single-character string constant used as pattern
let url = format!("https://team-api.infra.rust-lang.org/v1/permissions/bors.{normalized_name}.{permission}.json");
let users = reqwest::get(url)
.await
Expand All @@ -112,5 +113,5 @@
.json::<UserPermissionsResponse>()
.await
.map_err(|error| anyhow::anyhow!("Cannot deserialize users from team API: {error:?}"))?;
Ok(users.github_users)
Ok(users.github_ids)
}
3 changes: 2 additions & 1 deletion src/tests/event.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use derive_builder::Builder;
use octocrab::models::RunId;
use octocrab::models::{RunId, UserId};

use crate::bors::event::PullRequestComment;
use crate::bors::{event, CheckSuite, CheckSuiteStatus};
Expand All @@ -9,6 +9,7 @@ use crate::tests::state::{default_merge_sha, default_repo_name};

fn default_user() -> GithubUser {
GithubUser {
id: UserId(1),
username: "<user>".to_string(),
html_url: "https://user.com".parse().unwrap(),
}
Expand Down
7 changes: 4 additions & 3 deletions src/tests/permissions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ use std::sync::{Arc, Mutex};

use crate::permissions::{PermissionResolver, PermissionType};
use axum::async_trait;
use octocrab::models::UserId;

pub struct NoPermissions;

#[async_trait]
impl PermissionResolver for NoPermissions {
async fn has_permission(&self, _username: &str, _permission: PermissionType) -> bool {
async fn has_permission(&self, _user_id: &UserId, _permission: PermissionType) -> bool {
false
}
async fn reload(&self) {}
Expand All @@ -17,7 +18,7 @@ pub struct AllPermissions;

#[async_trait]
impl PermissionResolver for AllPermissions {
async fn has_permission(&self, _username: &str, _permission: PermissionType) -> bool {
async fn has_permission(&self, _user_id: &UserId, _permission: PermissionType) -> bool {
true
}
async fn reload(&self) {}
Expand All @@ -37,7 +38,7 @@ impl Default for MockPermissions {

#[async_trait]
impl PermissionResolver for Arc<Mutex<MockPermissions>> {
async fn has_permission(&self, _username: &str, _permission: PermissionType) -> bool {
async fn has_permission(&self, _user_id: &UserId, _permission: PermissionType) -> bool {
false
}
async fn reload(&self) {
Expand Down
4 changes: 3 additions & 1 deletion src/tests/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::time::Duration;
use crate::config::RepositoryConfig;
use axum::async_trait;
use derive_builder::Builder;
use octocrab::models::RunId;
use octocrab::models::{RunId, UserId};

use super::permissions::AllPermissions;
use crate::bors::event::{
Expand All @@ -29,6 +29,8 @@ use crate::tests::github::{default_base_branch, PRBuilder};

pub fn test_bot_user() -> GithubUser {
GithubUser {
// just a random one, to reduce the chance of duplicate id
id: UserId(517237103),
username: "<test-bot>".to_string(),
html_url: "https://test-bors.bot.com".parse().unwrap(),
}
Expand Down
Loading