This repository has been archived on 2023-11-08. You can view files and clone it, but cannot push or open issues or pull requests.
fiddle/src/api/mod.rs

210 lines
6.3 KiB
Rust

use diesel::prelude::*;
use juniper::{graphql_object, EmptySubscription, FieldResult, IntoFieldError, RootNode};
use std::fs;
use uuidv7::Uuid;
use crate::{db, prune_many, prune_single, CONFIG};
pub mod context;
pub mod error;
pub mod loaders;
pub mod models;
pub mod scalars;
pub use context::Context;
pub use error::{Error, QueryResultIntoFieldResult};
use loaders::TryOptionLoad;
pub struct Query;
#[graphql_object(context = Context)]
impl Query {
fn ping() -> &'static str {
"pong"
}
async fn directories(context: &Context) -> FieldResult<Vec<models::directory::Directory>> {
let db_conn = &mut context.get_db_conn()?;
let ids: Vec<Uuid> = db::schema::directories::table
.select(db::schema::directories::id)
.filter(db::schema::directories::active)
.load(db_conn)
.into_field_result()?;
context
.loaders
.directory
.try_load_many(ids)
.await
.map_or_else(
|_| Err(Error::Internal.into_field_error()),
|x| Ok(x.into_values().collect()),
)
}
async fn directory(
context: &Context,
id: scalars::Uuid,
) -> FieldResult<Option<models::directory::Directory>> {
context
.loaders
.directory
.try_option_load(*id)
.await
.map_err(|_| Error::Internal.into_field_error())
}
}
pub struct Mutation;
#[graphql_object(context = Context)]
impl Mutation {
async fn create_directory(context: &Context) -> FieldResult<models::directory::Directory> {
let db_conn = &mut context.get_db_conn()?;
let id = diesel::insert_into(db::schema::directories::table)
.values(db::models::NewDirectory { active: true })
.returning(db::schema::directories::id)
.get_result::<Uuid>(db_conn)
.into_field_result()?;
fs::create_dir(format!("{}/{}", CONFIG.data_dir, id))
.map_err(|_| Error::Internal.into_field_error())?;
context
.loaders
.directory
.try_load(id)
.await
.map_err(|_| Error::Internal.into_field_error())
}
async fn create_directories(
context: &Context,
count: i32,
) -> FieldResult<Vec<models::directory::Directory>> {
match count {
_ if count < 0 => return Err(Error::CountNegative.into_field_error()),
0 => return Ok(vec![]),
_ => {}
}
let db_conn = &mut context.get_db_conn()?;
let input = vec![db::models::NewDirectory { active: true }];
let ids = diesel::insert_into(db::schema::directories::table)
.values(
input
.iter()
.cycle()
.take(count as usize)
.collect::<Vec<_>>(),
)
.returning(db::schema::directories::id)
.load::<Uuid>(db_conn)
.into_field_result()?;
for id in ids.iter() {
fs::create_dir(format!("{}/{}", CONFIG.data_dir, id))
.map_err(|_| Error::Internal.into_field_error())?;
}
context
.loaders
.directory
.try_load_many(ids)
.await
.map_or_else(
|_| Err(Error::Internal.into_field_error()),
|x| Ok(x.into_values().collect()),
)
}
async fn delete_directory(
context: &Context,
id: scalars::Uuid,
immediate: Option<bool>,
) -> FieldResult<bool> {
let db_conn = &mut context.get_db_conn()?;
if diesel::select(diesel::dsl::not(diesel::dsl::exists(
db::schema::directories::table.filter(db::schema::directories::id.eq(*id)),
)))
.get_result::<bool>(db_conn)
.into_field_result()?
{
return Err(Error::DoesNotExist.into_field_error());
}
if immediate.unwrap_or(false) {
prune_single(&id.to_string()).map_err(|_| Error::Internal.into_field_error())?;
diesel::delete(
db::schema::directories::table.filter(db::schema::directories::id.eq(*id)),
)
.execute(db_conn)
.into_field_result()?;
} else {
diesel::update(
db::schema::directories::table.filter(db::schema::directories::id.eq(*id)),
)
.set(db::schema::directories::active.eq(false))
.execute(db_conn)
.into_field_result()?;
}
Ok(true)
}
async fn delete_directories(
context: &Context,
ids: Vec<scalars::Uuid>,
immediate: Option<bool>,
) -> FieldResult<bool> {
let db_conn = &mut context.get_db_conn()?;
let ids: Vec<Uuid> = ids.into_iter().map(|id| *id).collect();
let count: i64 = db::schema::directories::table
.filter(db::schema::directories::id.eq_any(&ids))
.count()
.get_result::<i64>(db_conn)
.into_field_result()?;
dbg!(&count);
if count == ids.len() as i64 {
if immediate.unwrap_or(false) {
prune_many(&ids.iter().map(|id| id.to_string()).collect::<Vec<_>>())?;
diesel::delete(
db::schema::directories::table.filter(db::schema::directories::id.eq_any(ids)),
)
.execute(db_conn)
.into_field_result()?;
} else {
diesel::update(
db::schema::directories::table.filter(db::schema::directories::id.eq_any(ids)),
)
.set(db::schema::directories::active.eq(false))
.execute(db_conn)
.into_field_result()?;
}
} else {
return Err(Error::DoesNotExist.into_field_error());
}
Ok(true)
}
async fn prune(context: &Context) -> FieldResult<bool> {
let db_conn = &mut context.get_db_conn()?;
crate::prune(db_conn).map_err(|_| Error::Internal.into_field_error())?;
Ok(true)
}
}
pub type Schema = RootNode<'static, Query, Mutation, EmptySubscription<Context>>;
pub fn schema() -> Schema {
Schema::new(Query, Mutation, EmptySubscription::new())
}