api.rs

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