summaryrefslogtreecommitdiff
path: root/src/handlers/ships.rs
blob: 9d985ea4fd4a4355f64fc1bc504205d6465ee32a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use std::sync::Arc;

use axum::{Json, extract::Path, Extension};
use hyper::StatusCode;
use solarlib::ship::{Ship, DbShip, Sha256};
use sqlx::{query_as, query, Error as SqlxError};
use axum_auth::AuthBearer;
use tracing::log::warn;

use crate::{errors::{JsonResult, StringResult, ServiceError}, State};


pub async fn list(state: Extension<Arc<State>>) -> JsonResult<Json<Vec<Ship>>> {
    let mut conn = state.conn.acquire().await?;

    let db_ships = query_as!(DbShip, "SELECT * FROM ships").fetch_all(&mut conn).await?;

    let ships = db_ships.into_iter().map(|d| d.into()).collect::<Vec<Ship>>();

    Ok(Json(ships))
}

pub async fn new(Json(new_ship): Json<Ship>, state: Extension<Arc<State>>, AuthBearer(token): AuthBearer) -> StringResult {
    check_bearer(token)?;
    let mut conn = state.conn.acquire().await?;

    query!("INSERT INTO ships (name, shasum, download_url, version) VALUES ($1, $2, $3, $4)", new_ship.name, new_ship.shasum.to_string(), new_ship.download_url, new_ship.version).execute(&mut conn).await?;

    Ok("OK")
}

pub async fn delete(Path(shasum): Path<Sha256>, state: Extension<Arc<State>>, AuthBearer(token): AuthBearer) -> StringResult {
    check_bearer(token)?;
    let mut conn = state.conn.acquire().await?;

    query!("DELETE FROM ships WHERE shasum=$1", shasum.to_string()).execute(&mut conn).await?;

    Ok("OK")
}

pub async fn get(Path(shasum): Path<Sha256>, state: Extension<Arc<State>>) -> JsonResult<Json<DbShip>> {
    let mut conn = state.conn.acquire().await?;

    let db_ship = match query_as!(DbShip, "SELECT * FROM ships WHERE shasum=$1", shasum.to_string()).fetch_one(&mut conn).await {
        Ok(d) => d,
        Err(e) => {
            match e {
               SqlxError::RowNotFound => {
                   return Err(ServiceError::NotFound)
               },
               _ => {
                   return Err(e.into());
               }
            }
        },
    };

    Ok(Json(db_ship))
}

fn check_bearer(token: String) -> Result<(), ServiceError> {
    let expected_token = match std::env::var("SHARED_KEY") {
        Ok(t) => t,
        Err(_) => {
            warn!("No pre-shared key set in environment. This is not secure!");
            "bad-key".into()
        }
    };

    if token != expected_token {
        Err(ServiceError::NotAuthorized)
    } else {
        Ok(())
    }
}