forked from github-starred/komodo
work on repo api
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use monitor_types::entities::{
|
||||
build::Build, builder::Builder, deployment::Deployment, server::Server, update::Update,
|
||||
user::User,
|
||||
build::Build, builder::Builder, deployment::Deployment, repo::Repo, server::Server,
|
||||
update::Update, user::User,
|
||||
};
|
||||
use mungos::{Collection, Indexed, Mungos};
|
||||
|
||||
@@ -12,6 +12,7 @@ pub struct DbClient {
|
||||
pub deployments: Collection<Deployment>,
|
||||
pub builds: Collection<Build>,
|
||||
pub builders: Collection<Builder>,
|
||||
pub repos: Collection<Repo>,
|
||||
pub updates: Collection<Update>,
|
||||
}
|
||||
|
||||
@@ -28,6 +29,7 @@ impl DbClient {
|
||||
deployments: Deployment::collection(&mungos, &config.mongo.db_name, true).await?,
|
||||
builds: Build::collection(&mungos, &config.mongo.db_name, true).await?,
|
||||
builders: Builder::collection(&mungos, &config.mongo.db_name, true).await?,
|
||||
repos: Repo::collection(&mungos, &config.mongo.db_name, true).await?,
|
||||
updates: Update::collection(&mungos, &config.mongo.db_name, true).await?,
|
||||
};
|
||||
Ok(client)
|
||||
|
||||
@@ -7,6 +7,7 @@ use monitor_types::{
|
||||
build::Build,
|
||||
builder::Builder,
|
||||
deployment::{Deployment, DockerContainerState},
|
||||
repo::Repo,
|
||||
server::{Server, ServerStatus},
|
||||
update::Update,
|
||||
user::User,
|
||||
@@ -264,6 +265,45 @@ impl State {
|
||||
Ok(builder.get_user_permissions(user_id))
|
||||
}
|
||||
|
||||
pub async fn get_repo(&self, repo_id: &str) -> anyhow::Result<Repo> {
|
||||
self.db
|
||||
.repos
|
||||
.find_one_by_id(repo_id)
|
||||
.await?
|
||||
.context(format!("did not find any repo with id {repo_id}"))
|
||||
}
|
||||
|
||||
pub async fn get_repo_check_permissions(
|
||||
&self,
|
||||
repo_id: &str,
|
||||
user: &RequestUser,
|
||||
permission_level: PermissionLevel,
|
||||
) -> anyhow::Result<Repo> {
|
||||
let repo = self
|
||||
.db
|
||||
.repos
|
||||
.find_one_by_id(repo_id)
|
||||
.await?
|
||||
.context(format!("did not find any repo with id {repo_id}"))?;
|
||||
let permissions = repo.get_user_permissions(&user.id);
|
||||
if user.is_admin || permissions >= permission_level {
|
||||
Ok(repo)
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"user does not have required permissions on this repo"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_user_permission_on_repo(
|
||||
&self,
|
||||
user_id: &str,
|
||||
repo_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let repo = self.get_repo(repo_id).await?;
|
||||
Ok(repo.get_user_permissions(user_id))
|
||||
}
|
||||
|
||||
pub async fn send_update(&self, update: Update) -> anyhow::Result<()> {
|
||||
self.update.sender.lock().await.send(update)?;
|
||||
Ok(())
|
||||
|
||||
@@ -329,89 +329,109 @@ impl Resolve<DeleteDeployment, RequestUser> for State {
|
||||
return Err(anyhow!("deployment busy"));
|
||||
}
|
||||
|
||||
let start_ts = monitor_timestamp();
|
||||
|
||||
let deployment = self
|
||||
.get_deployment_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let state = self
|
||||
.get_deployment_state(&deployment)
|
||||
.await
|
||||
.context("failed to get container state")?;
|
||||
let inner = || async move {
|
||||
let start_ts = monitor_timestamp();
|
||||
|
||||
let mut update = Update {
|
||||
target: ResourceTarget::Deployment(id.clone()),
|
||||
operation: Operation::DeleteDeployment,
|
||||
start_ts,
|
||||
operator: user.id.clone(),
|
||||
success: true,
|
||||
status: UpdateStatus::InProgress,
|
||||
..Default::default()
|
||||
};
|
||||
let state = self
|
||||
.get_deployment_state(&deployment)
|
||||
.await
|
||||
.context("failed to get container state")?;
|
||||
|
||||
update.id = self.add_update(update.clone()).await?;
|
||||
let mut update = Update {
|
||||
target: ResourceTarget::Deployment(deployment.id.clone()),
|
||||
operation: Operation::DeleteDeployment,
|
||||
start_ts,
|
||||
operator: user.id.clone(),
|
||||
success: true,
|
||||
status: UpdateStatus::InProgress,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
if !matches!(
|
||||
state,
|
||||
DockerContainerState::NotDeployed | DockerContainerState::Unknown
|
||||
) {
|
||||
// container needs to be destroyed
|
||||
let server = self.get_server(&deployment.config.server_id).await;
|
||||
if let Err(e) = server {
|
||||
update.logs.push(Log::error(
|
||||
"remove container",
|
||||
format!(
|
||||
"failed to retrieve server at {} from mongo | {e:#?}",
|
||||
deployment.config.server_id
|
||||
),
|
||||
));
|
||||
} else {
|
||||
let server = server.unwrap();
|
||||
match self
|
||||
.periphery_client(&server)
|
||||
.request(requests::RemoveContainer {
|
||||
name: deployment.name.clone(),
|
||||
signal: deployment.config.termination_signal.into(),
|
||||
time: deployment.config.termination_timeout.into(),
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(log) => update.logs.push(log),
|
||||
Err(e) => update.logs.push(Log::error(
|
||||
update.id = self.add_update(update.clone()).await?;
|
||||
|
||||
if !matches!(
|
||||
state,
|
||||
DockerContainerState::NotDeployed | DockerContainerState::Unknown
|
||||
) {
|
||||
// container needs to be destroyed
|
||||
let server = self.get_server(&deployment.config.server_id).await;
|
||||
if let Err(e) = server {
|
||||
update.logs.push(Log::error(
|
||||
"remove container",
|
||||
format!("failed to remove container on periphery | {e:#?}"),
|
||||
)),
|
||||
format!(
|
||||
"failed to retrieve server at {} from mongo | {e:#?}",
|
||||
deployment.config.server_id
|
||||
),
|
||||
));
|
||||
} else {
|
||||
let server = server.unwrap();
|
||||
match self
|
||||
.periphery_client(&server)
|
||||
.request(requests::RemoveContainer {
|
||||
name: deployment.name.clone(),
|
||||
signal: deployment.config.termination_signal.into(),
|
||||
time: deployment.config.termination_timeout.into(),
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(log) => update.logs.push(log),
|
||||
Err(e) => update.logs.push(Log::error(
|
||||
"remove container",
|
||||
format!("failed to remove container on periphery | {e:#?}"),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let res = self
|
||||
.db
|
||||
.deployments
|
||||
.delete_one(&id)
|
||||
.await
|
||||
.context("failed to delete deployment from mongo");
|
||||
let res = self
|
||||
.db
|
||||
.deployments
|
||||
.delete_one(&deployment.id)
|
||||
.await
|
||||
.context("failed to delete deployment from mongo");
|
||||
|
||||
let log = match res {
|
||||
Ok(_) => Log::simple(
|
||||
"delete deployment",
|
||||
format!("deleted deployment {}", deployment.name),
|
||||
),
|
||||
Err(e) => Log::error(
|
||||
"delete deployment",
|
||||
format!("failed to delete deployment\n{e:#?}"),
|
||||
),
|
||||
let log = match res {
|
||||
Ok(_) => Log::simple(
|
||||
"delete deployment",
|
||||
format!("deleted deployment {}", deployment.name),
|
||||
),
|
||||
Err(e) => Log::error(
|
||||
"delete deployment",
|
||||
format!("failed to delete deployment\n{e:#?}"),
|
||||
),
|
||||
};
|
||||
|
||||
update.logs.push(log);
|
||||
update.end_ts = Some(monitor_timestamp());
|
||||
update.status = UpdateStatus::Complete;
|
||||
update.success = all_logs_success(&update.logs);
|
||||
|
||||
self.update_update(update).await?;
|
||||
|
||||
Ok(deployment)
|
||||
};
|
||||
|
||||
update.logs.push(log);
|
||||
update.end_ts = Some(monitor_timestamp());
|
||||
update.status = UpdateStatus::Complete;
|
||||
update.success = all_logs_success(&update.logs);
|
||||
self.action_states
|
||||
.deployment
|
||||
.update_entry(id.clone(), |entry| {
|
||||
entry.deleting = true;
|
||||
})
|
||||
.await;
|
||||
|
||||
self.update_update(update).await?;
|
||||
let res = inner().await;
|
||||
|
||||
Ok(deployment)
|
||||
self.action_states
|
||||
.deployment
|
||||
.update_entry(id, |entry| {
|
||||
entry.deleting = false;
|
||||
})
|
||||
.await;
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ use crate::{
|
||||
mod build;
|
||||
mod deployment;
|
||||
mod permissions;
|
||||
mod repo;
|
||||
mod secret;
|
||||
mod server;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ use monitor_types::{
|
||||
build::Build,
|
||||
builder::Builder,
|
||||
deployment::Deployment,
|
||||
repo::Repo,
|
||||
server::Server,
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
Operation,
|
||||
@@ -204,6 +205,28 @@ impl Resolve<UpdateUserPermissionsOnTarget, RequestUser> for State {
|
||||
user.username, permission, server.name
|
||||
)
|
||||
}
|
||||
ResourceTarget::Repo(id) => {
|
||||
let repo = self
|
||||
.db
|
||||
.repos
|
||||
.find_one_by_id(id)
|
||||
.await
|
||||
.context("failed at find repo query")?
|
||||
.ok_or(anyhow!("failed to find a repo with id {id}"))?;
|
||||
self.db
|
||||
.repos
|
||||
.update_one::<Repo>(
|
||||
id,
|
||||
mungos::Update::Set(doc! {
|
||||
format!("permissions.{}", user_id): permission.to_string()
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
format!(
|
||||
"user {} given {} permissions on repo {}",
|
||||
user.username, permission, repo.name
|
||||
)
|
||||
}
|
||||
};
|
||||
let mut update = Update {
|
||||
operation: Operation::UpdateUserPermissionsOnTarget,
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
use anyhow::{anyhow, Context};
|
||||
use async_trait::async_trait;
|
||||
use monitor_types::{
|
||||
entities::{
|
||||
repo::Repo,
|
||||
update::{Log, ResourceTarget, Update},
|
||||
Operation, PermissionLevel,
|
||||
},
|
||||
monitor_timestamp,
|
||||
permissioned::Permissioned,
|
||||
requests::api::{
|
||||
CloneRepo, CopyRepo, CreateRepo, DeleteRepo, GetRepo, ListRepos, PullRepo, UpdateRepo,
|
||||
},
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<GetRepo, RequestUser> for State {
|
||||
async fn resolve(&self, GetRepo { id }: GetRepo, user: RequestUser) -> anyhow::Result<Repo> {
|
||||
self.get_repo_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<ListRepos, RequestUser> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
ListRepos { query }: ListRepos,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Vec<Repo>> {
|
||||
let repos = self
|
||||
.db
|
||||
.repos
|
||||
.get_some(query, None)
|
||||
.await
|
||||
.context("failed to pull repos from mongo")?;
|
||||
|
||||
let repos = if user.is_admin {
|
||||
repos
|
||||
} else {
|
||||
repos
|
||||
.into_iter()
|
||||
.filter(|repo| repo.get_user_permissions(&user.id) > PermissionLevel::None)
|
||||
.collect()
|
||||
};
|
||||
|
||||
Ok(repos)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<CreateRepo, RequestUser> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
CreateRepo { name, config }: CreateRepo,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Repo> {
|
||||
if let Some(server_id) = &config.server_id {
|
||||
if !server_id.is_empty() {
|
||||
self.get_server_check_permissions(
|
||||
server_id,
|
||||
&user,
|
||||
PermissionLevel::Update,
|
||||
)
|
||||
.await
|
||||
.context("cannot create repo on this server. user must have update permissions on the server.")?;
|
||||
}
|
||||
}
|
||||
let start_ts = monitor_timestamp();
|
||||
let repo = Repo {
|
||||
id: Default::default(),
|
||||
name,
|
||||
created_at: start_ts,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description: Default::default(),
|
||||
config: config.into(),
|
||||
};
|
||||
let repo_id = self
|
||||
.db
|
||||
.repos
|
||||
.create_one(repo)
|
||||
.await
|
||||
.context("failed to add repo to db")?;
|
||||
|
||||
let repo = self.get_repo(&repo_id).await?;
|
||||
|
||||
let update = Update {
|
||||
target: ResourceTarget::Repo(repo_id),
|
||||
operation: Operation::CreateRepo,
|
||||
start_ts,
|
||||
end_ts: Some(monitor_timestamp()),
|
||||
operator: user.id.clone(),
|
||||
success: true,
|
||||
logs: vec![
|
||||
Log::simple(
|
||||
"create repo",
|
||||
format!("created repo\nid: {}\nname: {}", repo.id, repo.name),
|
||||
),
|
||||
Log::simple("config", format!("{:#?}", repo.config)),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
self.add_update(update).await?;
|
||||
|
||||
if !repo.config.repo.is_empty() && !repo.config.server_id.is_empty() {
|
||||
let _ = self
|
||||
.resolve(
|
||||
CloneRepo {
|
||||
id: repo.id.clone(),
|
||||
},
|
||||
user,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
Ok(repo)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<CopyRepo, RequestUser> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
CopyRepo { name, id }: CopyRepo,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Repo> {
|
||||
let Repo {
|
||||
config,
|
||||
description,
|
||||
..
|
||||
} = self
|
||||
.get_repo_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
if !config.server_id.is_empty() {
|
||||
self.get_server_check_permissions(
|
||||
&config.server_id,
|
||||
&user,
|
||||
PermissionLevel::Update,
|
||||
)
|
||||
.await
|
||||
.context("cannot create repo on this server. user must have update permissions on the server.")?;
|
||||
}
|
||||
let start_ts = monitor_timestamp();
|
||||
let repo = Repo {
|
||||
id: Default::default(),
|
||||
name,
|
||||
created_at: start_ts,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description,
|
||||
config,
|
||||
};
|
||||
let repo_id = self
|
||||
.db
|
||||
.repos
|
||||
.create_one(repo)
|
||||
.await
|
||||
.context("failed to add repo to db")?;
|
||||
let repo = self.get_repo(&repo_id).await?;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Repo(repo_id),
|
||||
operation: Operation::CreateRepo,
|
||||
start_ts,
|
||||
end_ts: Some(monitor_timestamp()),
|
||||
operator: user.id.clone(),
|
||||
success: true,
|
||||
logs: vec![
|
||||
Log::simple(
|
||||
"create repo",
|
||||
format!("created repo\nid: {}\nname: {}", repo.id, repo.name),
|
||||
),
|
||||
Log::simple("config", format!("{:#?}", repo.config)),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
self.add_update(update).await?;
|
||||
|
||||
Ok(repo)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<DeleteRepo, RequestUser> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
DeleteRepo { id }: DeleteRepo,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Repo> {
|
||||
let repo = self
|
||||
.get_repo_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let inner = || async move {
|
||||
let start_ts = monitor_timestamp();
|
||||
|
||||
todo!()
|
||||
};
|
||||
|
||||
if self.action_states.repo.busy(&id).await {
|
||||
return Err(anyhow!("repo busy"));
|
||||
}
|
||||
|
||||
self.action_states
|
||||
.repo
|
||||
.update_entry(repo.id.clone(), |entry| {
|
||||
entry.deleting = true;
|
||||
})
|
||||
.await;
|
||||
|
||||
let res = inner().await;
|
||||
|
||||
self.action_states
|
||||
.repo
|
||||
.update_entry(repo.id, |entry| {
|
||||
entry.deleting = false;
|
||||
})
|
||||
.await;
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<UpdateRepo, RequestUser> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
UpdateRepo { id, config }: UpdateRepo,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Repo> {
|
||||
let repo = self
|
||||
.get_repo_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let inner = || async move {
|
||||
let start_ts = monitor_timestamp();
|
||||
|
||||
todo!()
|
||||
};
|
||||
|
||||
if self.action_states.repo.busy(&id).await {
|
||||
return Err(anyhow!("repo busy"));
|
||||
}
|
||||
|
||||
self.action_states
|
||||
.repo
|
||||
.update_entry(repo.id.clone(), |entry| {
|
||||
entry.updating = true;
|
||||
})
|
||||
.await;
|
||||
|
||||
let res = inner().await;
|
||||
|
||||
self.action_states
|
||||
.repo
|
||||
.update_entry(repo.id, |entry| {
|
||||
entry.updating = false;
|
||||
})
|
||||
.await;
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<CloneRepo, RequestUser> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
CloneRepo { id }: CloneRepo,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Update> {
|
||||
let repo = self
|
||||
.get_repo_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let inner = || async move {
|
||||
let start_ts = monitor_timestamp();
|
||||
|
||||
todo!()
|
||||
};
|
||||
|
||||
if self.action_states.repo.busy(&id).await {
|
||||
return Err(anyhow!("repo busy"));
|
||||
}
|
||||
|
||||
self.action_states
|
||||
.repo
|
||||
.update_entry(repo.id.clone(), |entry| {
|
||||
entry.cloning = true;
|
||||
})
|
||||
.await;
|
||||
|
||||
let res = inner().await;
|
||||
|
||||
self.action_states
|
||||
.repo
|
||||
.update_entry(repo.id, |entry| {
|
||||
entry.cloning = false;
|
||||
})
|
||||
.await;
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<PullRepo, RequestUser> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
PullRepo { id }: PullRepo,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Update> {
|
||||
let repo = self
|
||||
.get_repo_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let inner = || async move {
|
||||
let start_ts = monitor_timestamp();
|
||||
|
||||
todo!()
|
||||
};
|
||||
|
||||
if self.action_states.repo.busy(&id).await {
|
||||
return Err(anyhow!("repo busy"));
|
||||
}
|
||||
|
||||
self.action_states
|
||||
.repo
|
||||
.update_entry(repo.id.clone(), |entry| {
|
||||
entry.pulling = true;
|
||||
})
|
||||
.await;
|
||||
|
||||
let res = inner().await;
|
||||
|
||||
self.action_states
|
||||
.repo
|
||||
.update_entry(repo.id, |entry| {
|
||||
entry.pulling = false;
|
||||
})
|
||||
.await;
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ use anyhow::Context;
|
||||
use axum::Extension;
|
||||
use monitor_types::{
|
||||
entities::{
|
||||
build::BuildActionState, deployment::DeploymentActionState, server::ServerActionState,
|
||||
build::BuildActionState, deployment::DeploymentActionState, repo::RepoActionState,
|
||||
server::ServerActionState,
|
||||
},
|
||||
requests::auth::GetLoginOptionsResponse,
|
||||
};
|
||||
@@ -99,5 +100,6 @@ pub struct ActionStates {
|
||||
pub build: Cache<BuildActionState>,
|
||||
pub deployment: Cache<DeploymentActionState>,
|
||||
pub server: Cache<ServerActionState>,
|
||||
pub repo: Cache<RepoActionState>,
|
||||
// pub command: Cache<CommandActionState>,
|
||||
}
|
||||
|
||||
@@ -188,6 +188,10 @@ impl State {
|
||||
.await?;
|
||||
(permissions, "builder")
|
||||
}
|
||||
ResourceTarget::Repo(repo_id) => {
|
||||
let permissions = self.get_user_permission_on_repo(user_id, repo_id).await?;
|
||||
(permissions, "repo")
|
||||
}
|
||||
// UpdateTarget::Procedure(procedure_id) => {
|
||||
// let permissions = db_client
|
||||
// .get_user_permission_on_procedure(user_id, procedure_id)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::entities::{
|
||||
build::BuildActionState, deployment::DeploymentActionState, server::ServerActionState,
|
||||
build::BuildActionState, deployment::DeploymentActionState, repo::RepoActionState,
|
||||
server::ServerActionState,
|
||||
};
|
||||
|
||||
pub trait Busy {
|
||||
@@ -15,13 +16,12 @@ impl Busy for ServerActionState {
|
||||
impl Busy for DeploymentActionState {
|
||||
fn busy(&self) -> bool {
|
||||
self.deploying
|
||||
|| self.pulling
|
||||
|| self.recloning
|
||||
|| self.removing
|
||||
|| self.starting
|
||||
|| self.stopping
|
||||
|| self.updating
|
||||
|| self.renaming
|
||||
|| self.deleting
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,3 +30,9 @@ impl Busy for BuildActionState {
|
||||
self.building || self.updating
|
||||
}
|
||||
}
|
||||
|
||||
impl Busy for RepoActionState {
|
||||
fn busy(&self) -> bool {
|
||||
self.cloning || self.pulling || self.updating || self.deleting
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,8 +319,7 @@ pub struct DeploymentActionState {
|
||||
pub stopping: bool,
|
||||
pub starting: bool,
|
||||
pub removing: bool,
|
||||
pub pulling: bool,
|
||||
pub recloning: bool,
|
||||
pub updating: bool,
|
||||
pub renaming: bool,
|
||||
pub deleting: bool,
|
||||
}
|
||||
|
||||
@@ -252,6 +252,11 @@ pub enum Operation {
|
||||
DeleteBuild,
|
||||
RunBuild,
|
||||
|
||||
// builder
|
||||
CreateBuilder,
|
||||
UpdateBuilder,
|
||||
DeleteBuilder,
|
||||
|
||||
// deployment
|
||||
CreateDeployment,
|
||||
UpdateDeployment,
|
||||
@@ -264,21 +269,28 @@ pub enum Operation {
|
||||
RecloneDeployment,
|
||||
RenameDeployment,
|
||||
|
||||
// procedure
|
||||
CreateProcedure,
|
||||
UpdateProcedure,
|
||||
DeleteProcedure,
|
||||
// repo
|
||||
CreateRepo,
|
||||
UpdateRepo,
|
||||
DeleteRepo,
|
||||
CloneRepo,
|
||||
PullRepo,
|
||||
|
||||
// command
|
||||
CreateCommand,
|
||||
UpdateCommand,
|
||||
DeleteCommand,
|
||||
RunCommand,
|
||||
// // procedure
|
||||
// CreateProcedure,
|
||||
// UpdateProcedure,
|
||||
// DeleteProcedure,
|
||||
|
||||
// group
|
||||
CreateGroup,
|
||||
UpdateGroup,
|
||||
DeleteGroup,
|
||||
// // command
|
||||
// CreateCommand,
|
||||
// UpdateCommand,
|
||||
// DeleteCommand,
|
||||
// RunCommand,
|
||||
|
||||
// // group
|
||||
// CreateGroup,
|
||||
// UpdateGroup,
|
||||
// DeleteGroup,
|
||||
|
||||
// user
|
||||
UpdateUserPermissions,
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
use bson::serde_helpers::hex_string_as_object_id;
|
||||
use derive_builder::Builder;
|
||||
use mungos::MungosIndexed;
|
||||
use partial_derive2::Partial;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::{i64_is_zero, I64};
|
||||
|
||||
use super::{PermissionsMap, SystemCommand};
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, MungosIndexed)]
|
||||
pub struct Repo {
|
||||
#[serde(
|
||||
default,
|
||||
@@ -18,6 +21,7 @@ pub struct Repo {
|
||||
#[builder(setter(skip))]
|
||||
pub id: String,
|
||||
|
||||
#[unique_index]
|
||||
pub name: String,
|
||||
|
||||
#[serde(default)]
|
||||
@@ -28,22 +32,23 @@ pub struct Repo {
|
||||
#[builder(setter(skip))]
|
||||
pub permissions: PermissionsMap,
|
||||
|
||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||
#[serde(default, skip_serializing_if = "i64_is_zero")]
|
||||
#[builder(setter(skip))]
|
||||
pub created_at: String,
|
||||
pub created_at: I64,
|
||||
|
||||
#[serde(default)]
|
||||
#[builder(setter(skip))]
|
||||
pub updated_at: String,
|
||||
pub updated_at: I64,
|
||||
|
||||
pub config: RepoConfig,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial, MungosIndexed)]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[skip_serializing_none]
|
||||
pub struct RepoConfig {
|
||||
#[index]
|
||||
pub server_id: String,
|
||||
|
||||
pub repo: String,
|
||||
@@ -82,7 +87,16 @@ impl From<PartialRepoConfig> for RepoConfig {
|
||||
github_account: value.github_account.unwrap_or_default(),
|
||||
on_clone: value.on_clone.unwrap_or_default(),
|
||||
on_pull: value.on_pull.unwrap_or_default(),
|
||||
tags: value.tags.unwrap_or_default()
|
||||
tags: value.tags.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
pub struct RepoActionState {
|
||||
pub cloning: bool,
|
||||
pub pulling: bool,
|
||||
pub updating: bool,
|
||||
pub deleting: bool,
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ pub enum ResourceTarget {
|
||||
Builder(String),
|
||||
Deployment(String),
|
||||
Server(String),
|
||||
Repo(String),
|
||||
// Procedure(String),
|
||||
// Group(String),
|
||||
// Command(String),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::entities::{
|
||||
build::Build, builder::Builder, deployment::Deployment, server::Server, PermissionLevel,
|
||||
PermissionsMap,
|
||||
build::Build, builder::Builder, deployment::Deployment, repo::Repo, server::Server,
|
||||
PermissionLevel, PermissionsMap,
|
||||
};
|
||||
|
||||
pub trait Permissioned {
|
||||
@@ -34,3 +34,9 @@ impl Permissioned for Builder {
|
||||
&self.permissions
|
||||
}
|
||||
}
|
||||
|
||||
impl Permissioned for Repo {
|
||||
fn permissions_map(&self) -> &PermissionsMap {
|
||||
&self.permissions
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::{
|
||||
entities::repo::{PartialRepoConfig, Repo},
|
||||
entities::{
|
||||
repo::{PartialRepoConfig, Repo},
|
||||
update::Update,
|
||||
},
|
||||
MongoDocument,
|
||||
};
|
||||
|
||||
@@ -66,3 +69,18 @@ pub struct UpdateRepo {
|
||||
|
||||
//
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||
#[response(Update)]
|
||||
pub struct CloneRepo {
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||
#[response(Update)]
|
||||
pub struct PullRepo {
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user