1// use crate::{auth, db::UserId, AppState, Request, RequestExt as _};
2use async_trait::async_trait;
3use serde::Deserialize;
4use serde_json::json;
5use std::sync::Arc;
6// use surf::StatusCode;
7
8// pub fn add_routes(app: &mut tide::Server<Arc<AppState>>) {
9// app.at("/users").get(get_users);
10// app.at("/users").post(create_user);
11// app.at("/users/:id").put(update_user);
12// app.at("/users/:id").delete(destroy_user);
13// app.at("/users/:github_login").get(get_user);
14// app.at("/users/:github_login/access_tokens")
15// .post(create_access_token);
16// }
17
18// async fn get_user(request: Request) -> tide::Result {
19// request.require_token().await?;
20
21// let user = request
22// .db()
23// .get_user_by_github_login(request.param("github_login")?)
24// .await?
25// .ok_or_else(|| surf::Error::from_str(404, "user not found"))?;
26
27// Ok(tide::Response::builder(StatusCode::Ok)
28// .body(tide::Body::from_json(&user)?)
29// .build())
30// }
31
32// async fn get_users(request: Request) -> tide::Result {
33// request.require_token().await?;
34
35// let users = request.db().get_all_users().await?;
36
37// Ok(tide::Response::builder(StatusCode::Ok)
38// .body(tide::Body::from_json(&users)?)
39// .build())
40// }
41
42// async fn create_user(mut request: Request) -> tide::Result {
43// request.require_token().await?;
44
45// #[derive(Deserialize)]
46// struct Params {
47// github_login: String,
48// admin: bool,
49// }
50// let params = request.body_json::<Params>().await?;
51
52// let user_id = request
53// .db()
54// .create_user(¶ms.github_login, params.admin)
55// .await?;
56
57// let user = request.db().get_user_by_id(user_id).await?.ok_or_else(|| {
58// surf::Error::from_str(
59// StatusCode::InternalServerError,
60// "couldn't find the user we just created",
61// )
62// })?;
63
64// Ok(tide::Response::builder(StatusCode::Ok)
65// .body(tide::Body::from_json(&user)?)
66// .build())
67// }
68
69// async fn update_user(mut request: Request) -> tide::Result {
70// request.require_token().await?;
71
72// #[derive(Deserialize)]
73// struct Params {
74// admin: bool,
75// }
76// let user_id = UserId(
77// request
78// .param("id")?
79// .parse::<i32>()
80// .map_err(|error| surf::Error::from_str(StatusCode::BadRequest, error.to_string()))?,
81// );
82// let params = request.body_json::<Params>().await?;
83
84// request
85// .db()
86// .set_user_is_admin(user_id, params.admin)
87// .await?;
88
89// Ok(tide::Response::builder(StatusCode::Ok).build())
90// }
91
92// async fn destroy_user(request: Request) -> tide::Result {
93// request.require_token().await?;
94// let user_id = UserId(
95// request
96// .param("id")?
97// .parse::<i32>()
98// .map_err(|error| surf::Error::from_str(StatusCode::BadRequest, error.to_string()))?,
99// );
100
101// request.db().destroy_user(user_id).await?;
102
103// Ok(tide::Response::builder(StatusCode::Ok).build())
104// }
105
106// async fn create_access_token(request: Request) -> tide::Result {
107// request.require_token().await?;
108
109// let user = request
110// .db()
111// .get_user_by_github_login(request.param("github_login")?)
112// .await?
113// .ok_or_else(|| surf::Error::from_str(StatusCode::NotFound, "user not found"))?;
114
115// #[derive(Deserialize)]
116// struct QueryParams {
117// public_key: String,
118// impersonate: Option<String>,
119// }
120
121// let query_params: QueryParams = request.query().map_err(|_| {
122// surf::Error::from_str(StatusCode::UnprocessableEntity, "invalid query params")
123// })?;
124
125// let mut user_id = user.id;
126// if let Some(impersonate) = query_params.impersonate {
127// if user.admin {
128// if let Some(impersonated_user) =
129// request.db().get_user_by_github_login(&impersonate).await?
130// {
131// user_id = impersonated_user.id;
132// } else {
133// return Ok(tide::Response::builder(StatusCode::UnprocessableEntity)
134// .body(format!(
135// "Can't impersonate non-existent user {}",
136// impersonate
137// ))
138// .build());
139// }
140// } else {
141// return Ok(tide::Response::builder(StatusCode::Unauthorized)
142// .body(format!(
143// "Can't impersonate user {} because the real user isn't an admin",
144// impersonate
145// ))
146// .build());
147// }
148// }
149
150// let access_token = auth::create_access_token(request.db().as_ref(), user_id).await?;
151// let encrypted_access_token =
152// auth::encrypt_access_token(&access_token, query_params.public_key.clone())?;
153
154// Ok(tide::Response::builder(StatusCode::Ok)
155// .body(json!({"user_id": user_id, "encrypted_access_token": encrypted_access_token}))
156// .build())
157// }
158
159// #[async_trait]
160// pub trait RequestExt {
161// async fn require_token(&self) -> tide::Result<()>;
162// }
163
164// #[async_trait]
165// impl RequestExt for Request {
166// async fn require_token(&self) -> tide::Result<()> {
167// let token = self
168// .header("Authorization")
169// .and_then(|header| header.get(0))
170// .and_then(|header| header.as_str().strip_prefix("token "))
171// .ok_or_else(|| surf::Error::from_str(403, "invalid authorization header"))?;
172
173// if token == self.state().config.api_token {
174// Ok(())
175// } else {
176// Err(tide::Error::from_str(403, "invalid authorization token"))
177// }
178// }
179// }