api.rs

 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}