summaryrefslogblamecommitdiff
path: root/src/handlers/ships.rs
blob: 3101e54673a23fb5ec6ea9174004743575883bac (plain) (tree)
1
2
3
4
5
6
7
8
9
                   
 
                                           
                          


                                                
                       
 
            
                                                                

          

                                                                                

                                               


                                                           
 



                                

                   

 



                                  
                
                         

                                               








                                                                                          

            

 



                                  
                
                         

                                               


                                                                   

            

 



                                 

                                               







                                              
                   



                                                                         


             

                     
 
 
                                                                













                                                                               
use std::sync::Arc;

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

use crate::{
    errors::{JsonResult, ServiceError, StringResult, StrResult},
    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,
) -> StrResult {
    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,
) -> StrResult {
    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))
}

pub 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(())
    }
}