api.rs

  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(&params.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// }