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            if let Some(user) = user::Entity::find().filter(condition).one(&*tx).await? {
46                if user.admin {
47                    return Ok(Some(user.created_at));
48                }
49
50                if let Some(contributor) =
51                    contributor::Entity::find_by_id(user.id).one(&*tx).await?
52                {
53                    return Ok(Some(contributor.signed_at));
54                }
55            }
56
57            Ok(None)
58        })
59        .await
60    }
61
62    /// Records that a given user has signed the CLA.
63    pub async fn add_contributor(
64        &self,
65        github_login: &str,
66        github_user_id: i32,
67        github_email: Option<&str>,
68        github_user_created_at: DateTimeUtc,
69        initial_channel_id: Option<ChannelId>,
70    ) -> Result<()> {
71        self.transaction(|tx| async move {
72            let user = self
73                .get_or_create_user_by_github_account_tx(
74                    github_login,
75                    github_user_id,
76                    github_email,
77                    github_user_created_at.naive_utc(),
78                    initial_channel_id,
79                    &tx,
80                )
81                .await?;
82
83            contributor::Entity::insert(contributor::ActiveModel {
84                user_id: ActiveValue::Set(user.id),
85                signed_at: ActiveValue::NotSet,
86            })
87            .on_conflict(
88                OnConflict::column(contributor::Column::UserId)
89                    .do_nothing()
90                    .to_owned(),
91            )
92            .exec_without_returning(&*tx)
93            .await?;
94            Ok(())
95        })
96        .await
97    }
98}