feat: implemented the /backup/list [GET] API endpoint

This commit is contained in:
antifallobst 2023-11-14 11:12:14 +01:00
parent 05ee74eb7b
commit a081744f8b
Signed by: antifallobst
GPG Key ID: 2B4F402172791BAF
5 changed files with 78 additions and 0 deletions

View File

@ -19,6 +19,17 @@ async fn backup_create(
} }
} }
#[get("/backup/list")]
async fn backup_list(data: web::Data<State>) -> impl Responder {
match handlers::backup_list(&data.pool).await {
Ok(resp) => HttpResponse::Ok().json(&resp),
Err(e) => {
error!("While handling /backup/create [POST] request: {e}");
HttpResponse::InternalServerError().finish()
}
}
}
#[post("/backup/preset")] #[post("/backup/preset")]
async fn backup_preset_post( async fn backup_preset_post(
data: web::Data<State>, data: web::Data<State>,

View File

@ -11,6 +11,14 @@ pub struct BackupConfig {
pub docker: Option<BackupConfigDocker>, pub docker: Option<BackupConfigDocker>,
} }
#[derive(Debug, Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct Backup {
pub id: u64,
pub time: u64,
pub config: BackupConfig,
}
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub enum BackupCreateRequest { pub enum BackupCreateRequest {
Preset(String), Preset(String),
@ -22,6 +30,12 @@ pub enum BackupCreateResponse {
Success, Success,
} }
#[derive(Debug, Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct BackupListResponse {
pub backups: Vec<Backup>,
}
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "PascalCase")] #[serde(rename_all = "PascalCase")]
pub struct BackupPreset { pub struct BackupPreset {

View File

@ -24,6 +24,19 @@ pub async fn backup_create(
Ok(BackupCreateResponse::Success) Ok(BackupCreateResponse::Success)
} }
pub async fn backup_list(pool: &SqlitePool) -> Result<BackupListResponse> {
Ok(BackupListResponse {
backups: backup::get_all_backups(pool, |b| match b.status() {
backup::Status::Finished => Some(b),
_ => None,
})
.await?
.iter()
.map(|preset| preset.clone().into())
.collect(),
})
}
pub async fn backup_preset_post( pub async fn backup_preset_post(
pool: &SqlitePool, pool: &SqlitePool,
request: BackupPreset, request: BackupPreset,

View File

@ -23,6 +23,7 @@ pub async fn start(
let _ = HttpServer::new(move || { let _ = HttpServer::new(move || {
App::new() App::new()
.service(calls::backup_create) .service(calls::backup_create)
.service(calls::backup_list)
.service(calls::backup_preset_post) .service(calls::backup_preset_post)
.service(calls::backup_preset_get) .service(calls::backup_preset_get)
.service(calls::backup_preset_id_get) .service(calls::backup_preset_id_get)

View File

@ -4,6 +4,7 @@ pub mod worker;
use crate::api; use crate::api;
use anyhow::{Context, Error, Result}; use anyhow::{Context, Error, Result};
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use log::error;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::SqlitePool; use sqlx::SqlitePool;
use std::path::PathBuf; use std::path::PathBuf;
@ -67,6 +68,7 @@ pub enum Status {
Failed, Failed,
} }
#[derive(Clone)]
pub struct RawBackup { pub struct RawBackup {
id: i64, id: i64,
time: i64, time: i64,
@ -99,6 +101,16 @@ impl TryFrom<RawBackup> for Backup {
} }
} }
impl From<Backup> for api::data::Backup {
fn from(value: Backup) -> Self {
Self {
id: value.id,
time: value.time.timestamp() as u64,
config: value.config.into(),
}
}
}
impl Backup { impl Backup {
pub async fn new(pool: &SqlitePool, tx: mpsc::Sender<Backup>, config: Config) -> Result<Self> { pub async fn new(pool: &SqlitePool, tx: mpsc::Sender<Backup>, config: Config) -> Result<Self> {
let time = chrono::Utc::now().naive_utc(); let time = chrono::Utc::now().naive_utc();
@ -149,6 +161,10 @@ impl Backup {
} }
} }
pub fn status(&self) -> Status {
self.status.clone()
}
pub async fn set_status(&self, pool: &SqlitePool, status: Status) -> Result<()> { pub async fn set_status(&self, pool: &SqlitePool, status: Status) -> Result<()> {
let status = serde_json::to_string(&status)?; let status = serde_json::to_string(&status)?;
let id = self.id as i64; let id = self.id as i64;
@ -164,3 +180,26 @@ impl Backup {
Ok(()) Ok(())
} }
} }
pub async fn get_all_backups<F>(pool: &SqlitePool, filter: F) -> Result<Vec<Backup>>
where
F: Fn(Backup) -> Option<Backup>,
{
let query_result = sqlx::query_as!(RawBackup, r#"SELECT * FROM Backups;"#)
.fetch_all(pool)
.await;
match query_result {
Ok(raw_presets) => Ok(raw_presets
.iter()
.filter_map(|raw| match raw.clone().try_into() {
Ok(b) => filter(b),
Err(e) => {
error!("Failed to parse backup from database row: {e}");
None
}
})
.collect::<Vec<Backup>>()),
Err(e) => Err(Error::new(e)),
}
}