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_name: Option<&str>,
69 github_user_created_at: DateTimeUtc,
70 initial_channel_id: Option<ChannelId>,
71 ) -> Result<()> {
72 self.transaction(|tx| async move {
73 let user = self
74 .update_or_create_user_by_github_account_tx(
75 github_login,
76 github_user_id,
77 github_email,
78 github_name,
79 github_user_created_at.naive_utc(),
80 initial_channel_id,
81 &tx,
82 )
83 .await?;
84
85 contributor::Entity::insert(contributor::ActiveModel {
86 user_id: ActiveValue::Set(user.id),
87 signed_at: ActiveValue::NotSet,
88 })
89 .on_conflict(
90 OnConflict::column(contributor::Column::UserId)
91 .do_nothing()
92 .to_owned(),
93 )
94 .exec_without_returning(&*tx)
95 .await?;
96 Ok(())
97 })
98 .await
99 }
100}