contributors.rs

 1use super::*;
 2
 3#[derive(Debug)]
 4pub enum ContributorSelector {
 5    GitHubUserId { github_user_id: i32 },
 6    GitHubLogin { github_login: String },
 7}
 8
 9impl Database {
10    /// Retrieves the GitHub logins of all users who have signed the CLA.
11    pub async fn get_contributors(&self) -> Result<Vec<String>> {
12        self.transaction(|tx| async move {
13            #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
14            enum QueryGithubLogin {
15                GithubLogin,
16            }
17
18            Ok(contributor::Entity::find()
19                .inner_join(user::Entity)
20                .order_by_asc(contributor::Column::SignedAt)
21                .select_only()
22                .column(user::Column::GithubLogin)
23                .into_values::<_, QueryGithubLogin>()
24                .all(&*tx)
25                .await?)
26        })
27        .await
28    }
29
30    /// Records that a given user has signed the CLA.
31    pub async fn get_contributor_sign_timestamp(
32        &self,
33        selector: &ContributorSelector,
34    ) -> Result<Option<DateTime>> {
35        self.transaction(|tx| async move {
36            let condition = match selector {
37                ContributorSelector::GitHubUserId { github_user_id } => {
38                    user::Column::GithubUserId.eq(*github_user_id)
39                }
40                ContributorSelector::GitHubLogin { github_login } => {
41                    user::Column::GithubLogin.eq(github_login)
42                }
43            };
44
45            let Some(user) = user::Entity::find().filter(condition).one(&*tx).await? else {
46                return Ok(None);
47            };
48            let Some(contributor) = contributor::Entity::find_by_id(user.id).one(&*tx).await?
49            else {
50                return Ok(None);
51            };
52            Ok(Some(contributor.signed_at))
53        })
54        .await
55    }
56
57    /// Records that a given user has signed the CLA.
58    pub async fn add_contributor(
59        &self,
60        github_login: &str,
61        github_user_id: Option<i32>,
62        github_email: Option<&str>,
63    ) -> Result<()> {
64        self.transaction(|tx| async move {
65            let user = self
66                .get_or_create_user_by_github_account_tx(
67                    github_login,
68                    github_user_id,
69                    github_email,
70                    &*tx,
71                )
72                .await?;
73
74            contributor::Entity::insert(contributor::ActiveModel {
75                user_id: ActiveValue::Set(user.id),
76                signed_at: ActiveValue::NotSet,
77            })
78            .on_conflict(
79                OnConflict::column(contributor::Column::UserId)
80                    .do_nothing()
81                    .to_owned(),
82            )
83            .exec_without_returning(&*tx)
84            .await?;
85            Ok(())
86        })
87        .await
88    }
89}