1use crate::{AppState, Request, RequestExt as _};
2use async_trait::async_trait;
3use std::sync::Arc;
4
5pub fn add_routes(app: &mut tide::Server<Arc<AppState>>) {
6 app.at("/users/:github_login").get(get_user);
7}
8
9async fn get_user(request: Request) -> tide::Result {
10 request.require_token().await?;
11
12 let user = request
13 .db()
14 .get_user_by_github_login(request.param("github_login")?)
15 .await?
16 .ok_or_else(|| surf::Error::from_str(404, "user not found"))?;
17
18 Ok(tide::Response::builder(200)
19 .body(tide::Body::from_json(&user)?)
20 .build())
21}
22
23#[async_trait]
24pub trait RequestExt {
25 async fn require_token(&self) -> tide::Result<()>;
26}
27
28#[async_trait]
29impl RequestExt for Request {
30 async fn require_token(&self) -> tide::Result<()> {
31 let token = self
32 .header("Authorization")
33 .and_then(|header| header.get(0))
34 .and_then(|header| header.as_str().strip_prefix("token "))
35 .ok_or_else(|| surf::Error::from_str(403, "invalid authorization header"))?;
36
37 if token == self.state().config.api_token {
38 Ok(())
39 } else {
40 Err(tide::Error::from_str(403, "invalid authorization token"))
41 }
42 }
43}