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(¶ms.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// }