Skip to content

Commit 745d2e4

Browse files
authored
collab: Extract contributor endpoints to their own module (#15251)
This PR extracts the contributor endpoints to their own module for organizational purposes. Release Notes: - N/A
1 parent 50dbab0 commit 745d2e4

File tree

2 files changed

+126
-107
lines changed

2 files changed

+126
-107
lines changed

crates/collab/src/api.rs

Lines changed: 5 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1+
pub mod contributors;
12
pub mod events;
23
pub mod extensions;
34
pub mod ips_file;
45
pub mod slack;
56

67
use crate::{
78
auth,
8-
db::{ContributorSelector, User, UserId},
9+
db::{User, UserId},
910
rpc, AppState, Error, Result,
1011
};
1112
use anyhow::anyhow;
1213
use axum::{
1314
body::Body,
14-
extract::{self, Path, Query},
15+
extract::{Path, Query},
1516
http::{self, Request, StatusCode},
1617
middleware::{self, Next},
1718
response::IntoResponse,
1819
routing::{get, post},
1920
Extension, Json, Router,
2021
};
2122
use axum_extra::response::ErasedJson;
22-
use chrono::{NaiveDateTime, SecondsFormat};
2323
use serde::{Deserialize, Serialize};
24-
use std::sync::{Arc, OnceLock};
24+
use std::sync::Arc;
2525
use tower::ServiceBuilder;
2626

2727
pub use extensions::fetch_extensions_from_blob_store_periodically;
@@ -31,8 +31,7 @@ pub fn routes(rpc_server: Option<Arc<rpc::Server>>, state: Arc<AppState>) -> Rou
3131
.route("/user", get(get_authenticated_user))
3232
.route("/users/:id/access_tokens", post(create_access_token))
3333
.route("/rpc_server_snapshot", get(get_rpc_server_snapshot))
34-
.route("/contributors", get(get_contributors).post(add_contributor))
35-
.route("/contributor", get(check_is_contributor))
34+
.merge(contributors::router())
3635
.layer(
3736
ServiceBuilder::new()
3837
.layer(Extension(state))
@@ -126,107 +125,6 @@ async fn get_rpc_server_snapshot(
126125
Ok(ErasedJson::pretty(rpc_server.snapshot().await))
127126
}
128127

129-
async fn get_contributors(Extension(app): Extension<Arc<AppState>>) -> Result<Json<Vec<String>>> {
130-
Ok(Json(app.db.get_contributors().await?))
131-
}
132-
133-
#[derive(Debug, Deserialize)]
134-
struct CheckIsContributorParams {
135-
github_user_id: Option<i32>,
136-
github_login: Option<String>,
137-
}
138-
139-
impl CheckIsContributorParams {
140-
fn as_contributor_selector(self) -> Result<ContributorSelector> {
141-
if let Some(github_user_id) = self.github_user_id {
142-
return Ok(ContributorSelector::GitHubUserId { github_user_id });
143-
}
144-
145-
if let Some(github_login) = self.github_login {
146-
return Ok(ContributorSelector::GitHubLogin { github_login });
147-
}
148-
149-
Err(anyhow!(
150-
"must be one of `github_user_id` or `github_login`."
151-
))?
152-
}
153-
}
154-
155-
#[derive(Debug, Serialize)]
156-
struct CheckIsContributorResponse {
157-
signed_at: Option<String>,
158-
}
159-
160-
async fn check_is_contributor(
161-
Extension(app): Extension<Arc<AppState>>,
162-
Query(params): Query<CheckIsContributorParams>,
163-
) -> Result<Json<CheckIsContributorResponse>> {
164-
let params = params.as_contributor_selector()?;
165-
166-
if RenovateBot::is_renovate_bot(&params) {
167-
return Ok(Json(CheckIsContributorResponse {
168-
signed_at: Some(
169-
RenovateBot::created_at()
170-
.and_utc()
171-
.to_rfc3339_opts(SecondsFormat::Millis, true),
172-
),
173-
}));
174-
}
175-
176-
Ok(Json(CheckIsContributorResponse {
177-
signed_at: app
178-
.db
179-
.get_contributor_sign_timestamp(&params)
180-
.await?
181-
.map(|ts| ts.and_utc().to_rfc3339_opts(SecondsFormat::Millis, true)),
182-
}))
183-
}
184-
185-
/// The Renovate bot GitHub user (`renovate[bot]`).
186-
///
187-
/// https://api.github.com/users/renovate[bot]
188-
struct RenovateBot;
189-
190-
impl RenovateBot {
191-
const LOGIN: &'static str = "renovate[bot]";
192-
const USER_ID: i32 = 29139614;
193-
194-
/// Returns the `created_at` timestamp for the Renovate bot user.
195-
fn created_at() -> &'static NaiveDateTime {
196-
static CREATED_AT: OnceLock<NaiveDateTime> = OnceLock::new();
197-
CREATED_AT.get_or_init(|| {
198-
chrono::DateTime::parse_from_rfc3339("2017-06-02T07:04:12Z")
199-
.expect("failed to parse 'created_at' for 'renovate[bot]'")
200-
.naive_utc()
201-
})
202-
}
203-
204-
/// Returns whether the given contributor selector corresponds to the Renovate bot user.
205-
fn is_renovate_bot(contributor: &ContributorSelector) -> bool {
206-
match contributor {
207-
ContributorSelector::GitHubLogin { github_login } => github_login == Self::LOGIN,
208-
ContributorSelector::GitHubUserId { github_user_id } => {
209-
github_user_id == &Self::USER_ID
210-
}
211-
}
212-
}
213-
}
214-
215-
async fn add_contributor(
216-
Extension(app): Extension<Arc<AppState>>,
217-
extract::Json(params): extract::Json<AuthenticatedUserParams>,
218-
) -> Result<()> {
219-
let initial_channel_id = app.config.auto_join_channel_id;
220-
app.db
221-
.add_contributor(
222-
&params.github_login,
223-
params.github_user_id,
224-
params.github_email.as_deref(),
225-
initial_channel_id,
226-
)
227-
.await
228-
}
229-
230128
#[derive(Deserialize)]
231129
struct CreateAccessTokenQueryParams {
232130
public_key: String,

crates/collab/src/api/contributors.rs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
use std::sync::{Arc, OnceLock};
2+
3+
use anyhow::anyhow;
4+
use axum::{
5+
extract::{self, Query},
6+
routing::get,
7+
Extension, Json, Router,
8+
};
9+
use chrono::{NaiveDateTime, SecondsFormat};
10+
use serde::{Deserialize, Serialize};
11+
12+
use crate::api::AuthenticatedUserParams;
13+
use crate::db::ContributorSelector;
14+
use crate::{AppState, Result};
15+
16+
pub fn router() -> Router {
17+
Router::new()
18+
.route("/contributors", get(get_contributors).post(add_contributor))
19+
.route("/contributor", get(check_is_contributor))
20+
}
21+
22+
async fn get_contributors(Extension(app): Extension<Arc<AppState>>) -> Result<Json<Vec<String>>> {
23+
Ok(Json(app.db.get_contributors().await?))
24+
}
25+
26+
#[derive(Debug, Deserialize)]
27+
struct CheckIsContributorParams {
28+
github_user_id: Option<i32>,
29+
github_login: Option<String>,
30+
}
31+
32+
impl CheckIsContributorParams {
33+
fn as_contributor_selector(self) -> Result<ContributorSelector> {
34+
if let Some(github_user_id) = self.github_user_id {
35+
return Ok(ContributorSelector::GitHubUserId { github_user_id });
36+
}
37+
38+
if let Some(github_login) = self.github_login {
39+
return Ok(ContributorSelector::GitHubLogin { github_login });
40+
}
41+
42+
Err(anyhow!(
43+
"must be one of `github_user_id` or `github_login`."
44+
))?
45+
}
46+
}
47+
48+
#[derive(Debug, Serialize)]
49+
struct CheckIsContributorResponse {
50+
signed_at: Option<String>,
51+
}
52+
53+
async fn check_is_contributor(
54+
Extension(app): Extension<Arc<AppState>>,
55+
Query(params): Query<CheckIsContributorParams>,
56+
) -> Result<Json<CheckIsContributorResponse>> {
57+
let params = params.as_contributor_selector()?;
58+
59+
if RenovateBot::is_renovate_bot(&params) {
60+
return Ok(Json(CheckIsContributorResponse {
61+
signed_at: Some(
62+
RenovateBot::created_at()
63+
.and_utc()
64+
.to_rfc3339_opts(SecondsFormat::Millis, true),
65+
),
66+
}));
67+
}
68+
69+
Ok(Json(CheckIsContributorResponse {
70+
signed_at: app
71+
.db
72+
.get_contributor_sign_timestamp(&params)
73+
.await?
74+
.map(|ts| ts.and_utc().to_rfc3339_opts(SecondsFormat::Millis, true)),
75+
}))
76+
}
77+
78+
/// The Renovate bot GitHub user (`renovate[bot]`).
79+
///
80+
/// https://api.github.com/users/renovate[bot]
81+
struct RenovateBot;
82+
83+
impl RenovateBot {
84+
const LOGIN: &'static str = "renovate[bot]";
85+
const USER_ID: i32 = 29139614;
86+
87+
/// Returns the `created_at` timestamp for the Renovate bot user.
88+
fn created_at() -> &'static NaiveDateTime {
89+
static CREATED_AT: OnceLock<NaiveDateTime> = OnceLock::new();
90+
CREATED_AT.get_or_init(|| {
91+
chrono::DateTime::parse_from_rfc3339("2017-06-02T07:04:12Z")
92+
.expect("failed to parse 'created_at' for 'renovate[bot]'")
93+
.naive_utc()
94+
})
95+
}
96+
97+
/// Returns whether the given contributor selector corresponds to the Renovate bot user.
98+
fn is_renovate_bot(contributor: &ContributorSelector) -> bool {
99+
match contributor {
100+
ContributorSelector::GitHubLogin { github_login } => github_login == Self::LOGIN,
101+
ContributorSelector::GitHubUserId { github_user_id } => {
102+
github_user_id == &Self::USER_ID
103+
}
104+
}
105+
}
106+
}
107+
108+
async fn add_contributor(
109+
Extension(app): Extension<Arc<AppState>>,
110+
extract::Json(params): extract::Json<AuthenticatedUserParams>,
111+
) -> Result<()> {
112+
let initial_channel_id = app.config.auto_join_channel_id;
113+
app.db
114+
.add_contributor(
115+
&params.github_login,
116+
params.github_user_id,
117+
params.github_email.as_deref(),
118+
initial_channel_id,
119+
)
120+
.await
121+
}

0 commit comments

Comments
 (0)