use crate::permissions::Perm;
use crate::repository::RepoPath;
use crate::Config;
use axum::{
extract::{Form, State},
response::{IntoResponse, Redirect, Response},
routing::post,
Router,
};
use axum_extra::extract::SignedCookieJar;
use serde_derive::*;
use tracing::*;
pub fn router() -> Router<Config> {
Router::new()
.route("/{owner}/{repo}/fork", post(fork))
.route("/{owner}/{repo}/prune", post(prune))
.route("/{owner}/{repo}/rename", post(rename))
.fallback(crate::fallback)
}
pub const MAIN_CHANNEL: &'static str = "main";
#[derive(Debug, Deserialize)]
pub struct Fork {
name: String,
token: String,
}
async fn fork(
State(config): State<crate::Config>,
jar: SignedCookieJar,
p: RepoPath,
token: axum_csrf::CsrfToken,
Form(fork): Form<Fork>,
) -> Result<Response, crate::Error> {
debug!("fork {:?}", fork);
token.verify(&fork.token)?;
let uid = crate::get_user_id(&jar)?;
let mut it = p.repo.split(":");
let repo = it.next().unwrap();
let channel = it.next().unwrap_or("");
let mut db = config.db.get().await?;
let (repo, _) = crate::repository::repository_id(&mut db, &p.owner, &repo, uid, Perm::EDIT_CHANNELS)
.await?;
let redirect = format!("/{}/{}:{}", p.owner, p.repo, fork.name);
debug!("fork id = {:?}", repo);
config
.replicator
.handle_update(
None,
None,
None,
::replication::Update::Fork {
repo,
channel: if channel.is_empty() {
MAIN_CHANNEL.to_string()
} else {
channel.to_string()
},
new: fork.name,
},
)
.await
.unwrap();
Ok(Redirect::to(&redirect).into_response())
}
async fn rename(
State(config): State<crate::Config>,
jar: SignedCookieJar,
p: RepoPath,
token: axum_csrf::CsrfToken,
Form(rename): Form<Fork>,
) -> Result<Response, crate::Error> {
debug!("rename {:?} {:?}", p, rename);
if p.channel.as_deref().unwrap_or(MAIN_CHANNEL) == MAIN_CHANNEL {
debug!("trying to rename main channel");
return Ok(Redirect::to(&format!("/{}/{}", p.owner, p.repo)).into_response())
}
token.verify(&rename.token)?;
let uid = crate::get_user_id(&jar)?;
let mut db = config.db.get().await?;
let (repo, _) =
crate::repository::repository_id(&mut db, &p.owner, &p.repo, uid, Perm::EDIT_CHANNELS)
.await?;
let redirect = format!("/{}/{}:{}", p.owner, p.repo, rename.name);
config
.replicator
.handle_update(
None,
None,
None,
::replication::Update::Rename {
repo,
channel: p.channel.unwrap_or_else(|| MAIN_CHANNEL.to_string()),
new: rename.name,
},
)
.await?;
Ok(Redirect::to(&redirect).into_response())
}
#[derive(Debug, Deserialize)]
pub struct Prune {
token: String,
}
async fn prune(
State(config): State<crate::Config>,
jar: SignedCookieJar,
p: RepoPath,
token: axum_csrf::CsrfToken,
Form(prune): Form<Prune>,
) -> Result<Response, crate::Error> {
debug!("prune {:?}", prune);
if p.channel.as_deref().unwrap_or(MAIN_CHANNEL) == MAIN_CHANNEL {
return Ok(Redirect::to(&format!("/{}/{}", p.owner, p.repo)).into_response())
}
token.verify(&prune.token)?;
let uid = crate::get_user_id(&jar)?;
let mut db = config.db.get().await.unwrap();
let (repo, _) =
crate::repository::repository_id(&mut db, &p.owner, &p.repo, uid, Perm::EDIT_CHANNELS)
.await?;
config
.replicator
.handle_update(
None,
None,
None,
::replication::Update::Prune {
repo,
channel: p.channel.unwrap_or_else(|| MAIN_CHANNEL.to_string()),
},
)
.await?;
Ok(Redirect::to(&format!("/{}/{}", p.owner, p.repo)).into_response())
}