110 lines
3.6 KiB
Rust
110 lines
3.6 KiB
Rust
use crate::addressing::Address;
|
|
use crate::database::{retrieve_file, retrieve_object, DbPool, Entry};
|
|
use crate::filesystem::{list_directory, lookup_by_filename, UPath};
|
|
use crate::hash::{decode, encode};
|
|
use actix_files::NamedFile;
|
|
use actix_web::error::{ErrorBadRequest, ErrorInternalServerError, ErrorNotFound};
|
|
use actix_web::{error, get, post, web, Error, HttpResponse};
|
|
use anyhow::Result;
|
|
use log::debug;
|
|
use serde::Deserialize;
|
|
use std::collections::HashMap;
|
|
use std::path::PathBuf;
|
|
|
|
#[derive(Clone)]
|
|
pub struct State {
|
|
pub directory: PathBuf,
|
|
pub db_pool: DbPool,
|
|
}
|
|
|
|
#[get("/api/raw/{hash}")]
|
|
pub async fn get_raw(state: web::Data<State>, hash: web::Path<String>) -> Result<NamedFile, Error> {
|
|
let address = Address::decode(&decode(hash.into_inner()).map_err(ErrorInternalServerError)?)
|
|
.map_err(ErrorInternalServerError)?;
|
|
if let Address::Hash(hash) = address {
|
|
let connection = state.db_pool.get().map_err(ErrorInternalServerError)?;
|
|
let response = retrieve_file(&connection, hash);
|
|
|
|
debug!("{:?}", response);
|
|
|
|
match response {
|
|
Ok(result) => match result {
|
|
Some(path) => Ok(NamedFile::open(state.directory.join(path))?),
|
|
None => Err(error::ErrorNotFound("NOT FOUND")),
|
|
},
|
|
Err(e) => Err(error::ErrorInternalServerError(e)),
|
|
}
|
|
} else {
|
|
Err(ErrorBadRequest("Address does not refer to a file."))
|
|
}
|
|
}
|
|
|
|
#[get("/api/get/{address_str}")]
|
|
pub async fn get_object(
|
|
state: web::Data<State>,
|
|
address_str: web::Path<String>,
|
|
) -> Result<HttpResponse, Error> {
|
|
let connection = state.db_pool.get().map_err(ErrorInternalServerError)?;
|
|
let response: Result<Vec<Entry>> = retrieve_object(
|
|
&connection,
|
|
Address::decode(&decode(address_str.into_inner()).map_err(ErrorBadRequest)?)
|
|
.map_err(ErrorInternalServerError)?,
|
|
);
|
|
|
|
debug!("{:?}", response);
|
|
|
|
let mut result: HashMap<String, serde_json::Value> = HashMap::new();
|
|
for entry in response.map_err(error::ErrorInternalServerError)? {
|
|
result.insert(encode(&entry.identity.0), entry.as_json());
|
|
}
|
|
Ok(HttpResponse::Ok().json(result))
|
|
}
|
|
|
|
#[get("/api/hier/{path:.*}")]
|
|
pub async fn list_hier(
|
|
state: web::Data<State>,
|
|
path: web::Path<String>,
|
|
) -> Result<HttpResponse, Error> {
|
|
let connection = state.db_pool.get().map_err(ErrorInternalServerError)?;
|
|
let upath: UPath = path.into_inner().parse().map_err(ErrorBadRequest)?;
|
|
let entries: Vec<Entry> = list_directory(&connection, &upath)
|
|
.await
|
|
.map_err(ErrorNotFound)?; // todo: 500 if actual error occurs
|
|
|
|
Ok(HttpResponse::Ok().json(
|
|
entries
|
|
.iter()
|
|
.map(Entry::as_json)
|
|
.collect::<serde_json::Value>(),
|
|
))
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct LookupRequest {
|
|
query: String,
|
|
}
|
|
|
|
#[get("/api/lookup")]
|
|
pub async fn get_lookup(
|
|
state: web::Data<State>,
|
|
web::Query(info): web::Query<LookupRequest>,
|
|
) -> Result<HttpResponse, Error> {
|
|
let connection = state.db_pool.get().map_err(ErrorInternalServerError)?;
|
|
let response = lookup_by_filename(&connection, info.query).map_err(ErrorInternalServerError)?;
|
|
|
|
Ok(HttpResponse::Ok().json(
|
|
response
|
|
.iter()
|
|
.map(Entry::as_json)
|
|
.collect::<serde_json::Value>(),
|
|
))
|
|
}
|
|
|
|
#[post("/api/refresh")]
|
|
pub async fn api_refresh(state: web::Data<State>) -> Result<HttpResponse, Error> {
|
|
let _pool = state.db_pool.clone();
|
|
let _directory = state.directory.clone();
|
|
actix::spawn(crate::filesystem::reimport_directory(_pool, _directory));
|
|
Ok(HttpResponse::Ok().finish())
|
|
}
|