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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
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(())
}
}
|