use crate::database::Database;
use crate::models::projects;
use crate::repoman::RepoMan;
use rocket::fs::NamedFile;
use rocket::{Route, State};
#[get("/<org_path>/<proj_path>/.pijul?<channel>&<id>", rank = 2)]
async fn remote_id(
db: &State<Database>,
repoman: &State<RepoMan>,
org_path: String,
proj_path: String,
channel: String, id: Option<String>,
) -> Option<String> {
let p = match projects::find(db, org_path, proj_path).await {
Some(p) => p,
None => return None,
};
match p.repository(&repoman.storage_root) {
Ok(r) => r.channel_remote_id(channel, id),
Err(e) => {
println!("{}", e);
None
}
}
}
#[get("/<org_path>/<proj_path>/.pijul?<changelist>&<channel>")]
async fn changelist(
db: &State<Database>,
repoman: &State<RepoMan>,
org_path: String,
proj_path: String,
channel: String, changelist: u64,
) -> Option<String> {
let p = projects::find(db, org_path, proj_path).await?;
match p
.repository(&repoman.storage_root)
.unwrap()
.changelist(channel, changelist)
{
Ok(out) => Some(out),
Err(e) => {
println!("error getting changelist: {}", e);
None
}
}
}
use rocket::fs::TempFile;
#[post("/<org_path>/<proj_path>/.pijul?<apply>", data = "<patch>")]
async fn apply(
db: &State<Database>,
repoman: &State<RepoMan>,
current_user: crate::models::users::User,
org_path: String,
proj_path: String,
apply: String,
mut patch: TempFile<'_>,
) -> rocket::http::Status {
let p = if let Some(p) = projects::find(db, org_path, proj_path).await {
p
} else {
return rocket::http::Status::NotFound;
};
let repo = p.repository(&repoman.storage_root).unwrap();
let hash =
if let Some(h) = crate::models::pijul::changestores::Changestore::hash_from_string(apply) {
h
} else {
return rocket::http::Status::InternalServerError;
};
if !crate::authz::can_apply_patch(db, ¤t_user, &repo).await {
return rocket::http::Status::Unauthorized;
}
let patch_path = repo.changestore().change_file(hash);
if repo.changestore().ensure_parent_dirs(hash).is_err() {
println!("No write permission?");
return rocket::http::Status::InternalServerError;
}
if patch.persist_to(&patch_path).await.is_err() {
return rocket::http::Status::InternalServerError;
}
if !repo.valid_change(hash) {
println!("Not valid as object");
return rocket::http::Status::InternalServerError;
}
if repo.apply_change_to_channel("main", hash).is_ok() {
return rocket::http::Status::Accepted;
};
rocket::http::Status::InternalServerError
}
#[derive(FromForm)]
struct Identities {
identities: Vec<String>,
}
use rocket::serde::{json::Json, Serialize};
#[derive(Serialize, FromForm)]
struct IdentitieRes {
id: Vec<String>,
rev: u64,
}
#[get("/<_>/<_>/.pijul?<identities>", rank = 4)]
fn identities(identities: Identities) -> Json<IdentitieRes> {
println!("{:?}", identities.identities);
Json(IdentitieRes { id: vec![], rev: 0 })
}
#[get("/<org_path>/<proj_path>/.pijul?<change>", rank = 3)]
async fn change(
db: &State<Database>,
repoman: &State<RepoMan>,
org_path: String,
proj_path: String,
change: String,
) -> Option<NamedFile> {
let p = projects::find(db, org_path, proj_path).await?;
let hash = crate::models::pijul::changestores::Changestore::hash_from_string(change)?;
let repo = p.repository(&repoman.storage_root).ok()?;
let path = repo.changestore().change_file(hash);
NamedFile::open(path).await.ok()
}
pub fn routes() -> Vec<Route> {
routes![remote_id, changelist, apply, identities, change]
}