mirror of
https://github.com/moghtech/komodo.git
synced 2026-03-11 17:44:19 -05:00
replace those helpers with Resource trait
This commit is contained in:
@@ -3,25 +3,19 @@ use std::time::Duration;
|
||||
use anyhow::{anyhow, Context};
|
||||
use monitor_types::{
|
||||
entities::{
|
||||
alerter::Alerter,
|
||||
build::Build,
|
||||
builder::Builder,
|
||||
deployment::{Deployment, DockerContainerState},
|
||||
repo::Repo,
|
||||
server::{Server, ServerStatus},
|
||||
tag::CustomTag,
|
||||
update::{ResourceTarget, Update},
|
||||
user::User,
|
||||
Operation, PermissionLevel,
|
||||
Operation,
|
||||
},
|
||||
monitor_timestamp,
|
||||
permissioned::Permissioned,
|
||||
};
|
||||
use mungos::{mongodb::bson::doc, AggStage::*};
|
||||
use periphery_client::{requests, PeripheryClient};
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, resource::Resource, state::State};
|
||||
|
||||
pub mod alert;
|
||||
pub mod cache;
|
||||
@@ -60,8 +54,6 @@ pub fn make_update(
|
||||
}
|
||||
|
||||
impl State {
|
||||
// USER
|
||||
|
||||
pub async fn get_user(&self, user_id: &str) -> anyhow::Result<User> {
|
||||
self.db
|
||||
.users
|
||||
@@ -70,22 +62,11 @@ impl State {
|
||||
.context(format!("no user exists with id {user_id}"))
|
||||
}
|
||||
|
||||
// SERVER
|
||||
|
||||
pub async fn get_server(&self, server_id: &str) -> anyhow::Result<Server> {
|
||||
self.db
|
||||
.servers
|
||||
.find_one_by_id(server_id)
|
||||
.await
|
||||
.context("failed to get server from db")?
|
||||
.context(format!("did not find any server with id {server_id}"))
|
||||
}
|
||||
|
||||
pub async fn get_server_with_status(
|
||||
&self,
|
||||
server_id: &str,
|
||||
) -> anyhow::Result<(Server, ServerStatus)> {
|
||||
let server = self.get_server(server_id).await?;
|
||||
let server: Server = self.get_resource(server_id).await?;
|
||||
if !server.config.enabled {
|
||||
return Ok((server, ServerStatus::Disabled));
|
||||
}
|
||||
@@ -100,45 +81,6 @@ impl State {
|
||||
Ok((server, status))
|
||||
}
|
||||
|
||||
pub async fn get_server_check_permissions(
|
||||
&self,
|
||||
server_id: &str,
|
||||
user: &RequestUser,
|
||||
permission_level: PermissionLevel,
|
||||
) -> anyhow::Result<Server> {
|
||||
let server = self.get_server(server_id).await?;
|
||||
let permissions = server.get_user_permissions(&user.id);
|
||||
if user.is_admin || permissions >= permission_level {
|
||||
Ok(server)
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"user does not have required permissions on this server"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_user_permission_on_server(
|
||||
&self,
|
||||
user_id: &str,
|
||||
server_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let server = self.get_server(server_id).await?;
|
||||
Ok(server.get_user_permissions(user_id))
|
||||
}
|
||||
|
||||
// DEPLOYMENT
|
||||
|
||||
pub async fn get_deployment(&self, deployment_id: &str) -> anyhow::Result<Deployment> {
|
||||
self.db
|
||||
.deployments
|
||||
.find_one_by_id(deployment_id)
|
||||
.await
|
||||
.context("failed to get deployment from db")?
|
||||
.context(format!(
|
||||
"did not find any deployment with id {deployment_id}"
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn get_deployment_state(
|
||||
&self,
|
||||
deployment: &Deployment,
|
||||
@@ -167,208 +109,6 @@ impl State {
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
pub async fn get_deployment_check_permissions(
|
||||
&self,
|
||||
deployment_id: &str,
|
||||
user: &RequestUser,
|
||||
permission_level: PermissionLevel,
|
||||
) -> anyhow::Result<Deployment> {
|
||||
let deployment = self.get_deployment(deployment_id).await?;
|
||||
let permissions = deployment.get_user_permissions(&user.id);
|
||||
if user.is_admin || permissions >= permission_level {
|
||||
Ok(deployment)
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"user does not have required permissions on this deployment"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_user_permission_on_deployment(
|
||||
&self,
|
||||
user_id: &str,
|
||||
deployment_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let deployment = self.get_deployment(deployment_id).await?;
|
||||
Ok(deployment.get_user_permissions(user_id))
|
||||
}
|
||||
|
||||
// BUILD
|
||||
|
||||
pub async fn get_build(&self, build_id: &str) -> anyhow::Result<Build> {
|
||||
self.db
|
||||
.builds
|
||||
.find_one_by_id(build_id)
|
||||
.await
|
||||
.context("failed to get build from db")?
|
||||
.context(format!("did not find any build with id {build_id}"))
|
||||
}
|
||||
|
||||
pub async fn get_build_check_permissions(
|
||||
&self,
|
||||
build_id: &str,
|
||||
user: &RequestUser,
|
||||
permission_level: PermissionLevel,
|
||||
) -> anyhow::Result<Build> {
|
||||
let build = self.get_build(build_id).await?;
|
||||
let permissions = build.get_user_permissions(&user.id);
|
||||
if user.is_admin || permissions >= permission_level {
|
||||
Ok(build)
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"user does not have required permissions on this build"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_user_permission_on_build(
|
||||
&self,
|
||||
user_id: &str,
|
||||
build_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let build = self.get_build(build_id).await?;
|
||||
Ok(build.get_user_permissions(user_id))
|
||||
}
|
||||
|
||||
pub async fn get_build_ids_for_non_admin(&self, user_id: &str) -> anyhow::Result<Vec<String>> {
|
||||
self.db
|
||||
.builds
|
||||
.aggregate_collect(
|
||||
[
|
||||
Match(doc! {
|
||||
format!("permissions.{}", user_id): { "$in": ["update", "execute", "read"] }
|
||||
}),
|
||||
Project(doc! { "_id": 1 }),
|
||||
],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.context("failed to get build ids for non admin | aggregation")?
|
||||
.into_iter()
|
||||
.map(|d| {
|
||||
let id = d
|
||||
.get("_id")
|
||||
.context("no _id field")?
|
||||
.as_object_id()
|
||||
.context("_id not ObjectId")?
|
||||
.to_string();
|
||||
anyhow::Ok(id)
|
||||
})
|
||||
.collect::<anyhow::Result<Vec<_>>>()
|
||||
.context("failed to get build ids for non admin | extract id from document")
|
||||
}
|
||||
|
||||
// BUILDER
|
||||
|
||||
pub async fn get_builder(&self, builder_id: &str) -> anyhow::Result<Builder> {
|
||||
self.db
|
||||
.builders
|
||||
.find_one_by_id(builder_id)
|
||||
.await
|
||||
.context("failed to get builder from db")?
|
||||
.context(format!("did not find any builder with id {builder_id}"))
|
||||
}
|
||||
|
||||
pub async fn get_builder_check_permissions(
|
||||
&self,
|
||||
builder_id: &str,
|
||||
user: &RequestUser,
|
||||
permission_level: PermissionLevel,
|
||||
) -> anyhow::Result<Builder> {
|
||||
let builder = self.get_builder(builder_id).await?;
|
||||
let permissions = builder.get_user_permissions(&user.id);
|
||||
if user.is_admin || permissions >= permission_level {
|
||||
Ok(builder)
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"user does not have required permissions on this builder"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_user_permission_on_builder(
|
||||
&self,
|
||||
user_id: &str,
|
||||
builder_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let builder = self.get_builder(builder_id).await?;
|
||||
Ok(builder.get_user_permissions(user_id))
|
||||
}
|
||||
|
||||
// REPO
|
||||
|
||||
pub async fn get_repo(&self, repo_id: &str) -> anyhow::Result<Repo> {
|
||||
self.db
|
||||
.repos
|
||||
.find_one_by_id(repo_id)
|
||||
.await
|
||||
.context("failed to get repo from db")?
|
||||
.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.get_repo(repo_id).await?;
|
||||
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))
|
||||
}
|
||||
|
||||
// ALERTER
|
||||
|
||||
pub async fn get_alerter(&self, alerter_id: &str) -> anyhow::Result<Alerter> {
|
||||
self.db
|
||||
.alerters
|
||||
.find_one_by_id(alerter_id)
|
||||
.await
|
||||
.context("failed to get alerter from mongo")?
|
||||
.context(format!("did not find any alerter with id {alerter_id}"))
|
||||
}
|
||||
|
||||
pub async fn get_alerter_check_permissions(
|
||||
&self,
|
||||
alerter_id: &str,
|
||||
user: &RequestUser,
|
||||
permission_level: PermissionLevel,
|
||||
) -> anyhow::Result<Alerter> {
|
||||
let alerter = self.get_alerter(alerter_id).await?;
|
||||
let permissions = alerter.get_user_permissions(&user.id);
|
||||
if user.is_admin || permissions >= permission_level {
|
||||
Ok(alerter)
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"user does not have required permissions on this alerter"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_user_permission_on_alerter(
|
||||
&self,
|
||||
user_id: &str,
|
||||
alerter_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let alerter = self.get_alerter(alerter_id).await?;
|
||||
Ok(alerter.get_user_permissions(user_id))
|
||||
}
|
||||
|
||||
// TAG
|
||||
|
||||
pub async fn get_tag(&self, tag_id: &str) -> anyhow::Result<CustomTag> {
|
||||
|
||||
@@ -2,7 +2,7 @@ use anyhow::{anyhow, Context};
|
||||
use axum::{extract::Path, http::HeaderMap, routing::post, Router};
|
||||
use hex::ToHex;
|
||||
use hmac::{Hmac, Mac};
|
||||
use monitor_types::requests::execute;
|
||||
use monitor_types::{requests::execute, entities::{build::Build, repo::Repo}};
|
||||
use resolver_api::Resolve;
|
||||
use serde::Deserialize;
|
||||
use sha2::Sha256;
|
||||
@@ -10,7 +10,7 @@ use sha2::Sha256;
|
||||
use crate::{
|
||||
auth::InnerRequestUser,
|
||||
helpers::random_duration,
|
||||
state::{State, StateExtension},
|
||||
state::{State, StateExtension}, resource::Resource,
|
||||
};
|
||||
|
||||
type HmacSha256 = Hmac<Sha256>;
|
||||
@@ -72,8 +72,8 @@ impl State {
|
||||
) -> anyhow::Result<()> {
|
||||
self.verify_gh_signature(headers, &body).await?;
|
||||
let request_branch = extract_branch(&body)?;
|
||||
let expected_branch = self.get_build(&build_id).await?.config.branch;
|
||||
if request_branch != expected_branch {
|
||||
let build: Build = self.get_resource(&build_id).await?;
|
||||
if request_branch != build.config.branch {
|
||||
return Err(anyhow!("request branch does not match expected"));
|
||||
}
|
||||
self.resolve(
|
||||
@@ -99,8 +99,8 @@ impl State {
|
||||
) -> anyhow::Result<()> {
|
||||
self.verify_gh_signature(headers, &body).await?;
|
||||
let request_branch = extract_branch(&body)?;
|
||||
let expected_branch = self.get_repo(&repo_id).await?.config.branch;
|
||||
if request_branch != expected_branch {
|
||||
let repo: Repo = self.get_resource(&repo_id).await?;
|
||||
if request_branch != repo.config.branch {
|
||||
return Err(anyhow!("request branch does not match expected"));
|
||||
}
|
||||
self.resolve(
|
||||
@@ -126,8 +126,8 @@ impl State {
|
||||
) -> anyhow::Result<()> {
|
||||
self.verify_gh_signature(headers, &body).await?;
|
||||
let request_branch = extract_branch(&body)?;
|
||||
let expected_branch = self.get_repo(&repo_id).await?.config.branch;
|
||||
if request_branch != expected_branch {
|
||||
let repo: Repo = self.get_resource(&repo_id).await?;
|
||||
if request_branch != repo.config.branch {
|
||||
return Err(anyhow!("request branch does not match expected"));
|
||||
}
|
||||
self.resolve(
|
||||
|
||||
@@ -14,6 +14,7 @@ mod monitor;
|
||||
mod requests;
|
||||
mod state;
|
||||
mod ws;
|
||||
mod resource;
|
||||
|
||||
async fn app() -> anyhow::Result<()> {
|
||||
let state = state::State::load().await?;
|
||||
|
||||
@@ -7,8 +7,9 @@ use monitor_types::{
|
||||
all_logs_success,
|
||||
entities::{
|
||||
build::{Build, BuildBuilderConfig},
|
||||
builder::{AwsBuilderConfig, BuilderConfig},
|
||||
builder::{AwsBuilderConfig, Builder, BuilderConfig},
|
||||
deployment::DockerContainerState,
|
||||
server::Server,
|
||||
update::{Log, Update},
|
||||
Operation, PermissionLevel,
|
||||
},
|
||||
@@ -27,6 +28,7 @@ use crate::{
|
||||
auth::{InnerRequestUser, RequestUser},
|
||||
cloud::{aws::Ec2Instance, BuildCleanupData},
|
||||
helpers::make_update,
|
||||
resource::Resource,
|
||||
state::State,
|
||||
};
|
||||
|
||||
@@ -41,8 +43,8 @@ impl Resolve<RunBuild, RequestUser> for State {
|
||||
return Err(anyhow!("build busy"));
|
||||
}
|
||||
|
||||
let mut build = self
|
||||
.get_build_check_permissions(&build_id, &user, PermissionLevel::Execute)
|
||||
let mut build: Build = self
|
||||
.get_resource_check_permissions(&build_id, &user, PermissionLevel::Execute)
|
||||
.await?;
|
||||
|
||||
build.config.version.increment();
|
||||
@@ -199,7 +201,8 @@ impl Resolve<CancelBuild, RequestUser> for State {
|
||||
CancelBuild { build_id }: CancelBuild,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<CancelBuildResponse> {
|
||||
self.get_build_check_permissions(&build_id, &user, PermissionLevel::Execute)
|
||||
let _: Build = self
|
||||
.get_resource_check_permissions(&build_id, &user, PermissionLevel::Execute)
|
||||
.await?;
|
||||
self.build_cancel.sender.lock().await.send(build_id)?;
|
||||
Ok(CancelBuildResponse {})
|
||||
@@ -220,7 +223,7 @@ impl State {
|
||||
if server_id.is_empty() {
|
||||
return Err(anyhow!("build has not configured a builder"));
|
||||
}
|
||||
let server = self.get_server(server_id).await?;
|
||||
let server: Server = self.get_resource(server_id).await?;
|
||||
let periphery = self.periphery_client(&server);
|
||||
Ok((
|
||||
periphery,
|
||||
@@ -233,7 +236,7 @@ impl State {
|
||||
if builder_id.is_empty() {
|
||||
return Err(anyhow!("build has not configured a builder"));
|
||||
}
|
||||
let builder = self.get_builder(builder_id).await?;
|
||||
let builder: Builder = self.get_resource(builder_id).await?;
|
||||
match builder.config {
|
||||
BuilderConfig::Aws(config) => self.get_aws_builder(build, config, update).await,
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@ use anyhow::anyhow;
|
||||
use async_trait::async_trait;
|
||||
use monitor_types::{
|
||||
entities::{
|
||||
deployment::DeploymentImage,
|
||||
build::Build,
|
||||
deployment::{Deployment, DeploymentImage},
|
||||
server::ServerStatus,
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
Operation, PermissionLevel, Version,
|
||||
@@ -13,7 +14,7 @@ use monitor_types::{
|
||||
use periphery_client::requests;
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, resource::Resource, state::State};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<Deploy, RequestUser> for State {
|
||||
@@ -30,8 +31,8 @@ impl Resolve<Deploy, RequestUser> for State {
|
||||
return Err(anyhow!("deployment busy"));
|
||||
}
|
||||
|
||||
let mut deployment = self
|
||||
.get_deployment_check_permissions(&deployment_id, &user, PermissionLevel::Execute)
|
||||
let mut deployment: Deployment = self
|
||||
.get_resource_check_permissions(&deployment_id, &user, PermissionLevel::Execute)
|
||||
.await?;
|
||||
|
||||
if deployment.config.server_id.is_empty() {
|
||||
@@ -54,7 +55,7 @@ impl Resolve<Deploy, RequestUser> for State {
|
||||
|
||||
let version = match deployment.config.image {
|
||||
DeploymentImage::Build { build_id, version } => {
|
||||
let build = self.get_build(&build_id).await?;
|
||||
let build: Build = self.get_resource(&build_id).await?;
|
||||
let image_name = get_image_name(&build);
|
||||
let version = if version.is_none() {
|
||||
build.config.version
|
||||
@@ -136,8 +137,8 @@ impl Resolve<StartContainer, RequestUser> for State {
|
||||
return Err(anyhow!("deployment busy"));
|
||||
}
|
||||
|
||||
let deployment = self
|
||||
.get_deployment_check_permissions(&deployment_id, &user, PermissionLevel::Execute)
|
||||
let deployment: Deployment = self
|
||||
.get_resource_check_permissions(&deployment_id, &user, PermissionLevel::Execute)
|
||||
.await?;
|
||||
|
||||
if deployment.config.server_id.is_empty() {
|
||||
@@ -223,8 +224,8 @@ impl Resolve<StopContainer, RequestUser> for State {
|
||||
return Err(anyhow!("deployment busy"));
|
||||
}
|
||||
|
||||
let deployment = self
|
||||
.get_deployment_check_permissions(&deployment_id, &user, PermissionLevel::Execute)
|
||||
let deployment: Deployment = self
|
||||
.get_resource_check_permissions(&deployment_id, &user, PermissionLevel::Execute)
|
||||
.await?;
|
||||
|
||||
if deployment.config.server_id.is_empty() {
|
||||
@@ -314,8 +315,8 @@ impl Resolve<RemoveContainer, RequestUser> for State {
|
||||
return Err(anyhow!("deployment busy"));
|
||||
}
|
||||
|
||||
let deployment = self
|
||||
.get_deployment_check_permissions(&deployment_id, &user, PermissionLevel::Execute)
|
||||
let deployment: Deployment = self
|
||||
.get_resource_check_permissions(&deployment_id, &user, PermissionLevel::Execute)
|
||||
.await?;
|
||||
|
||||
if deployment.config.server_id.is_empty() {
|
||||
|
||||
@@ -3,7 +3,7 @@ use async_trait::async_trait;
|
||||
use monitor_types::{
|
||||
entities::{
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
Operation, PermissionLevel,
|
||||
Operation, PermissionLevel, repo::Repo, server::Server,
|
||||
},
|
||||
monitor_timestamp, optional_string,
|
||||
requests::execute::*,
|
||||
@@ -12,7 +12,7 @@ use mungos::mongodb::bson::doc;
|
||||
use periphery_client::requests;
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, state::State, resource::Resource};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<CloneRepo, RequestUser> for State {
|
||||
@@ -21,8 +21,8 @@ impl Resolve<CloneRepo, RequestUser> for State {
|
||||
CloneRepo { id }: CloneRepo,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Update> {
|
||||
let repo = self
|
||||
.get_repo_check_permissions(&id, &user, PermissionLevel::Execute)
|
||||
let repo: Repo = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Execute)
|
||||
.await?;
|
||||
|
||||
let inner = || async move {
|
||||
@@ -32,7 +32,7 @@ impl Resolve<CloneRepo, RequestUser> for State {
|
||||
return Err(anyhow!("repo has no server attached"));
|
||||
}
|
||||
|
||||
let server = self.get_server(&repo.config.server_id).await?;
|
||||
let server: Server = self.get_resource(&repo.config.server_id).await?;
|
||||
|
||||
let mut update = Update {
|
||||
operation: Operation::CloneRepo,
|
||||
@@ -112,8 +112,8 @@ impl Resolve<PullRepo, RequestUser> for State {
|
||||
PullRepo { id }: PullRepo,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Update> {
|
||||
let repo = self
|
||||
.get_repo_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let repo: Repo = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let inner = || async move {
|
||||
@@ -123,7 +123,7 @@ impl Resolve<PullRepo, RequestUser> for State {
|
||||
return Err(anyhow!("repo has no server attached"));
|
||||
}
|
||||
|
||||
let server = self.get_server(&repo.config.server_id).await?;
|
||||
let server: Server = self.get_resource(&repo.config.server_id).await?;
|
||||
|
||||
let mut update = Update {
|
||||
operation: Operation::PullRepo,
|
||||
|
||||
@@ -3,7 +3,7 @@ use async_trait::async_trait;
|
||||
use monitor_types::{
|
||||
entities::{
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
Operation, PermissionLevel,
|
||||
Operation, PermissionLevel, server::Server,
|
||||
},
|
||||
monitor_timestamp,
|
||||
requests::execute::*,
|
||||
@@ -11,7 +11,7 @@ use monitor_types::{
|
||||
use periphery_client::requests;
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, state::State, resource::Resource};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<PruneDockerContainers, RequestUser> for State {
|
||||
@@ -24,8 +24,8 @@ impl Resolve<PruneDockerContainers, RequestUser> for State {
|
||||
return Err(anyhow!("server busy"));
|
||||
}
|
||||
|
||||
let server = self
|
||||
.get_server_check_permissions(&server_id, &user, PermissionLevel::Execute)
|
||||
let server: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Execute)
|
||||
.await?;
|
||||
|
||||
let inner = || async {
|
||||
@@ -95,8 +95,8 @@ impl Resolve<PruneDockerNetworks, RequestUser> for State {
|
||||
}
|
||||
|
||||
let inner = || async {
|
||||
let server = self
|
||||
.get_server_check_permissions(&server_id, &user, PermissionLevel::Execute)
|
||||
let server: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Execute)
|
||||
.await?;
|
||||
|
||||
let start_ts = monitor_timestamp();
|
||||
@@ -165,8 +165,8 @@ impl Resolve<PruneDockerImages, RequestUser> for State {
|
||||
}
|
||||
|
||||
let inner = || async {
|
||||
let server = self
|
||||
.get_server_check_permissions(&server_id, &user, PermissionLevel::Execute)
|
||||
let server: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Execute)
|
||||
.await?;
|
||||
|
||||
let start_ts = monitor_timestamp();
|
||||
|
||||
77
bin/core/src/requests/read/alerter.rs
Normal file
77
bin/core/src/requests/read/alerter.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
use anyhow::Context;
|
||||
use async_trait::async_trait;
|
||||
use monitor_types::{
|
||||
entities::{alerter::Alerter, PermissionLevel},
|
||||
requests::read::*,
|
||||
};
|
||||
use mungos::mongodb::bson::doc;
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, resource::Resource, state::State};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<GetAlerter, RequestUser> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
GetAlerter { id }: GetAlerter,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Alerter> {
|
||||
self.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<ListAlerters, RequestUser> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
ListAlerters { query }: ListAlerters,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Vec<Alerter>> {
|
||||
let mut query = query.unwrap_or_default();
|
||||
if !user.is_admin {
|
||||
query.insert(
|
||||
format!("permissions.{}", user.id),
|
||||
doc! { "$in": ["read", "execute", "update"] },
|
||||
);
|
||||
}
|
||||
|
||||
let alerters = self
|
||||
.db
|
||||
.alerters
|
||||
.get_some(query, None)
|
||||
.await
|
||||
.context("failed to pull alerters from mongo")?;
|
||||
|
||||
Ok(alerters)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<GetAlertersSummary, RequestUser> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
GetAlertersSummary {}: GetAlertersSummary,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<GetAlertersSummaryResponse> {
|
||||
let query = if user.is_admin {
|
||||
None
|
||||
} else {
|
||||
let query = doc! {
|
||||
format!("permissions.{}", user.id): { "$in": ["read", "execute", "update"] }
|
||||
};
|
||||
Some(query)
|
||||
};
|
||||
let total = self
|
||||
.db
|
||||
.alerters
|
||||
.collection
|
||||
.count_documents(query, None)
|
||||
.await
|
||||
.context("failed to count all alerter documents")?;
|
||||
let res = GetAlertersSummaryResponse {
|
||||
total: total as u32,
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,12 @@ use monitor_types::{
|
||||
use mungos::mongodb::bson::doc;
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, resource::Resource, state::State};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<GetBuild, RequestUser> for State {
|
||||
async fn resolve(&self, GetBuild { id }: GetBuild, user: RequestUser) -> anyhow::Result<Build> {
|
||||
self.get_build_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
self.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -27,20 +27,7 @@ impl Resolve<ListBuilds, RequestUser> for State {
|
||||
ListBuilds { query }: ListBuilds,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Vec<BuildListItem>> {
|
||||
let mut query = query.unwrap_or_default();
|
||||
if !user.is_admin {
|
||||
query.insert(
|
||||
format!("permissions.{}", user.id),
|
||||
doc! { "$in": ["read", "execute", "update"] },
|
||||
);
|
||||
}
|
||||
|
||||
let builds = self
|
||||
.db
|
||||
.builds
|
||||
.get_some(query, None)
|
||||
.await
|
||||
.context("failed to pull builds from mongo")?;
|
||||
let builds: Vec<Build> = self.list_resources_for_user(&user, query).await?;
|
||||
|
||||
let builds = builds
|
||||
.into_iter()
|
||||
@@ -64,7 +51,7 @@ impl Resolve<GetBuildActionState, RequestUser> for State {
|
||||
GetBuildActionState { id }: GetBuildActionState,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<BuildActionState> {
|
||||
self.get_build_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
let _: Build = self.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let action_state = self.action_states.build.get(&id).await.unwrap_or_default();
|
||||
Ok(action_state)
|
||||
|
||||
@@ -7,7 +7,7 @@ use monitor_types::{
|
||||
use mungos::mongodb::bson::doc;
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, resource::Resource, state::State};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<GetBuilder, RequestUser> for State {
|
||||
@@ -16,7 +16,7 @@ impl Resolve<GetBuilder, RequestUser> for State {
|
||||
GetBuilder { id }: GetBuilder,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Builder> {
|
||||
self.get_builder_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
self.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -28,22 +28,7 @@ impl Resolve<ListBuilders, RequestUser> for State {
|
||||
ListBuilders { query }: ListBuilders,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Vec<Builder>> {
|
||||
let mut query = query.unwrap_or_default();
|
||||
if !user.is_admin {
|
||||
query.insert(
|
||||
format!("permissions.{}", user.id),
|
||||
doc! { "$in": ["read", "execute", "update"] },
|
||||
);
|
||||
}
|
||||
|
||||
let builders = self
|
||||
.db
|
||||
.builders
|
||||
.get_some(query, None)
|
||||
.await
|
||||
.context("failed to pull builders from mongo")?;
|
||||
|
||||
Ok(builders)
|
||||
self.list_resources_for_user(&user, query).await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +53,7 @@ impl Resolve<GetBuildersSummary, RequestUser> for State {
|
||||
.collection
|
||||
.count_documents(query, None)
|
||||
.await
|
||||
.context("failed to count all build documents")?;
|
||||
.context("failed to count all builder documents")?;
|
||||
let res = GetBuildersSummaryResponse {
|
||||
total: total as u32,
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@ use monitor_types::{
|
||||
Deployment, DeploymentActionState, DeploymentConfig, DeploymentImage,
|
||||
DockerContainerState, DockerContainerStats,
|
||||
},
|
||||
server::Server,
|
||||
update::{Log, UpdateStatus},
|
||||
Operation, PermissionLevel,
|
||||
},
|
||||
@@ -18,7 +19,7 @@ use mungos::mongodb::{bson::doc, options::FindOneOptions};
|
||||
use periphery_client::requests;
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, resource::Resource, state::State};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<GetDeployment, RequestUser> for State {
|
||||
@@ -27,7 +28,7 @@ impl Resolve<GetDeployment, RequestUser> for State {
|
||||
GetDeployment { id }: GetDeployment,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Deployment> {
|
||||
self.get_deployment_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
self.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -39,19 +40,7 @@ impl Resolve<ListDeployments, RequestUser> for State {
|
||||
ListDeployments { query }: ListDeployments,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Vec<DeploymentListItem>> {
|
||||
let mut query = query.unwrap_or_default();
|
||||
if !user.is_admin {
|
||||
query.insert(
|
||||
format!("permissions.{}", user.id),
|
||||
doc! { "$in": ["read", "execute", "update"] },
|
||||
);
|
||||
}
|
||||
let deployments = self
|
||||
.db
|
||||
.deployments
|
||||
.get_some(query, None)
|
||||
.await
|
||||
.context("failed to pull deployments from mongo")?;
|
||||
let deployments: Vec<Deployment> = self.list_resources_for_user(&user, query).await?;
|
||||
|
||||
let deployments = deployments.into_iter().map(|deployment| async {
|
||||
let status = self.deployment_status_cache.get(&deployment.id).await;
|
||||
@@ -81,7 +70,8 @@ impl Resolve<GetDeploymentStatus, RequestUser> for State {
|
||||
GetDeploymentStatus { id }: GetDeploymentStatus,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<GetDeploymentStatusResponse> {
|
||||
self.get_deployment_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
let _: Deployment = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let status = self
|
||||
.deployment_status_cache
|
||||
@@ -113,12 +103,12 @@ impl Resolve<GetLog, RequestUser> for State {
|
||||
config: DeploymentConfig { server_id, .. },
|
||||
..
|
||||
} = self
|
||||
.get_deployment_check_permissions(&deployment_id, &user, PermissionLevel::Read)
|
||||
.get_resource_check_permissions(&deployment_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
if server_id.is_empty() {
|
||||
return Ok(Log::default());
|
||||
}
|
||||
let server = self.get_server(&server_id).await?;
|
||||
let server: Server = self.get_resource(&server_id).await?;
|
||||
self.periphery_client(&server)
|
||||
.request(requests::GetContainerLog {
|
||||
name,
|
||||
@@ -140,7 +130,7 @@ impl Resolve<GetDeployedVersion, RequestUser> for State {
|
||||
config: DeploymentConfig { image, .. },
|
||||
..
|
||||
} = self
|
||||
.get_deployment_check_permissions(&deployment_id, &user, PermissionLevel::Read)
|
||||
.get_resource_check_permissions(&deployment_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let version = match image {
|
||||
DeploymentImage::Build { .. } => {
|
||||
@@ -196,12 +186,12 @@ impl Resolve<GetDeploymentStats, RequestUser> for State {
|
||||
config: DeploymentConfig { server_id, .. },
|
||||
..
|
||||
} = self
|
||||
.get_deployment_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
if server_id.is_empty() {
|
||||
return Err(anyhow!("deployment has no server attached"));
|
||||
}
|
||||
let server = self.get_server(&server_id).await?;
|
||||
let server: Server = self.get_resource(&server_id).await?;
|
||||
self.periphery_client(&server)
|
||||
.request(requests::GetContainerStats { name })
|
||||
.await
|
||||
@@ -216,7 +206,8 @@ impl Resolve<GetDeploymentActionState, RequestUser> for State {
|
||||
GetDeploymentActionState { id }: GetDeploymentActionState,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<DeploymentActionState> {
|
||||
self.get_deployment_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
let _: Deployment = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let action_state = self
|
||||
.action_states
|
||||
|
||||
@@ -25,6 +25,7 @@ mod server;
|
||||
mod tag;
|
||||
mod update;
|
||||
mod user;
|
||||
mod alerter;
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Resolver)]
|
||||
@@ -67,17 +68,22 @@ enum ReadRequest {
|
||||
ListBuilds(ListBuilds),
|
||||
GetBuildActionState(GetBuildActionState),
|
||||
|
||||
// ==== BUILDER ====
|
||||
GetBuildersSummary(GetBuildersSummary),
|
||||
GetBuilder(GetBuilder),
|
||||
ListBuilders(ListBuilders),
|
||||
|
||||
// ==== REPO ====
|
||||
GetReposSummary(GetReposSummary),
|
||||
GetRepo(GetRepo),
|
||||
ListRepos(ListRepos),
|
||||
GetRepoActionState(GetRepoActionState),
|
||||
|
||||
// ==== BUILDER ====
|
||||
GetBuildersSummary(GetBuildersSummary),
|
||||
GetBuilder(GetBuilder),
|
||||
ListBuilders(ListBuilders),
|
||||
|
||||
// ==== ALERTER ====
|
||||
GetAlertersSummary(GetAlertersSummary),
|
||||
GetAlerter(GetAlerter),
|
||||
ListAlerters(ListAlerters),
|
||||
|
||||
// ==== TAG ====
|
||||
GetTag(GetTag),
|
||||
ListTags(ListTags),
|
||||
|
||||
@@ -10,12 +10,12 @@ use monitor_types::{
|
||||
use mungos::mongodb::bson::doc;
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, resource::Resource, 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)
|
||||
self.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -27,20 +27,7 @@ impl Resolve<ListRepos, RequestUser> for State {
|
||||
ListRepos { query }: ListRepos,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Vec<RepoListItem>> {
|
||||
let mut query = query.unwrap_or_default();
|
||||
if !user.is_admin {
|
||||
query.insert(
|
||||
format!("permissions.{}", user.id),
|
||||
doc! { "$in": ["read", "execute", "update"] },
|
||||
);
|
||||
}
|
||||
|
||||
let repos = self
|
||||
.db
|
||||
.repos
|
||||
.get_some(query, None)
|
||||
.await
|
||||
.context("failed to pull repos from mongo")?;
|
||||
let repos: Vec<Repo> = self.list_resources_for_user(&user, query).await?;
|
||||
|
||||
let repos = repos
|
||||
.into_iter()
|
||||
@@ -63,7 +50,7 @@ impl Resolve<GetRepoActionState, RequestUser> for State {
|
||||
GetRepoActionState { id }: GetRepoActionState,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<RepoActionState> {
|
||||
self.get_repo_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
let _: Repo = self.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let action_state = self.action_states.repo.get(&id).await.unwrap_or_default();
|
||||
Ok(action_state)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use anyhow::{anyhow, Context};
|
||||
use anyhow::anyhow;
|
||||
use async_trait::async_trait;
|
||||
use futures::future::join_all;
|
||||
use monitor_types::{
|
||||
@@ -12,11 +12,10 @@ use monitor_types::{
|
||||
},
|
||||
requests::read::*,
|
||||
};
|
||||
use mungos::mongodb::bson::doc;
|
||||
use periphery_client::requests;
|
||||
use resolver_api::{Resolve, ResolveToString};
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, resource::Resource, state::State};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<GetPeripheryVersion, RequestUser> for State {
|
||||
@@ -25,7 +24,8 @@ impl Resolve<GetPeripheryVersion, RequestUser> for State {
|
||||
req: GetPeripheryVersion,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<GetPeripheryVersionResponse> {
|
||||
self.get_server_check_permissions(&req.server_id, &user, PermissionLevel::Read)
|
||||
let _: Server = self
|
||||
.get_resource_check_permissions(&req.server_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let version = self
|
||||
.server_status_cache
|
||||
@@ -40,7 +40,7 @@ impl Resolve<GetPeripheryVersion, RequestUser> for State {
|
||||
#[async_trait]
|
||||
impl Resolve<GetServer, RequestUser> for State {
|
||||
async fn resolve(&self, req: GetServer, user: RequestUser) -> anyhow::Result<Server> {
|
||||
self.get_server_check_permissions(&req.id, &user, PermissionLevel::Read)
|
||||
self.get_resource_check_permissions(&req.id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -52,22 +52,9 @@ impl Resolve<ListServers, RequestUser> for State {
|
||||
ListServers { query }: ListServers,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Vec<ServerListItem>> {
|
||||
let mut query = query.unwrap_or_default();
|
||||
if !user.is_admin {
|
||||
query.insert(
|
||||
format!("permissions.{}", user.id),
|
||||
doc! { "$in": ["read", "execute", "update"] },
|
||||
);
|
||||
}
|
||||
let servers = self.list_resources_for_user(&user, query).await?;
|
||||
|
||||
let servers = self
|
||||
.db
|
||||
.servers
|
||||
.get_some(query, None)
|
||||
.await
|
||||
.context("failed to pull servers from mongo")?;
|
||||
|
||||
let servers = servers.into_iter().map(|server| async {
|
||||
let servers = servers.into_iter().map(|server: Server| async {
|
||||
let status = self.server_status_cache.get(&server.id).await;
|
||||
ServerListItem {
|
||||
id: server.id,
|
||||
@@ -90,7 +77,8 @@ impl Resolve<GetServerStatus, RequestUser> for State {
|
||||
GetServerStatus { id }: GetServerStatus,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<GetServerStatusResponse> {
|
||||
self.get_server_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
let _: Server = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let status = self
|
||||
.server_status_cache
|
||||
@@ -111,7 +99,8 @@ impl Resolve<GetServerActionState, RequestUser> for State {
|
||||
GetServerActionState { id }: GetServerActionState,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<ServerActionState> {
|
||||
self.get_server_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
let _: Server = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let action_state = self.action_states.server.get(&id).await.unwrap_or_default();
|
||||
Ok(action_state)
|
||||
@@ -125,8 +114,8 @@ impl Resolve<GetSystemInformation, RequestUser> for State {
|
||||
GetSystemInformation { server_id }: GetSystemInformation,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<SystemInformation> {
|
||||
let server = self
|
||||
.get_server_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
let server: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
self.periphery_client(&server)
|
||||
.request(requests::GetSystemInformation {})
|
||||
@@ -141,7 +130,8 @@ impl ResolveToString<GetAllSystemStats, RequestUser> for State {
|
||||
GetAllSystemStats { server_id }: GetAllSystemStats,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<String> {
|
||||
self.get_server_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
let _: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let status = self
|
||||
.server_status_cache
|
||||
@@ -164,7 +154,8 @@ impl ResolveToString<GetBasicSystemStats, RequestUser> for State {
|
||||
GetBasicSystemStats { server_id }: GetBasicSystemStats,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<String> {
|
||||
self.get_server_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
let _: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let status = self
|
||||
.server_status_cache
|
||||
@@ -187,7 +178,8 @@ impl ResolveToString<GetCpuUsage, RequestUser> for State {
|
||||
GetCpuUsage { server_id }: GetCpuUsage,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<String> {
|
||||
self.get_server_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
let _: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let status = self
|
||||
.server_status_cache
|
||||
@@ -210,7 +202,8 @@ impl ResolveToString<GetDiskUsage, RequestUser> for State {
|
||||
GetDiskUsage { server_id }: GetDiskUsage,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<String> {
|
||||
self.get_server_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
let _: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let status = self
|
||||
.server_status_cache
|
||||
@@ -233,7 +226,8 @@ impl ResolveToString<GetNetworkUsage, RequestUser> for State {
|
||||
GetNetworkUsage { server_id }: GetNetworkUsage,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<String> {
|
||||
self.get_server_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
let _: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let status = self
|
||||
.server_status_cache
|
||||
@@ -256,7 +250,8 @@ impl ResolveToString<GetSystemProcesses, RequestUser> for State {
|
||||
GetSystemProcesses { server_id }: GetSystemProcesses,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<String> {
|
||||
self.get_server_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
let _: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let status = self
|
||||
.server_status_cache
|
||||
@@ -279,7 +274,8 @@ impl ResolveToString<GetSystemComponents, RequestUser> for State {
|
||||
GetSystemComponents { server_id }: GetSystemComponents,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<String> {
|
||||
self.get_server_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
let _: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
let status = self
|
||||
.server_status_cache
|
||||
@@ -302,8 +298,8 @@ impl Resolve<GetDockerImages, RequestUser> for State {
|
||||
GetDockerImages { server_id }: GetDockerImages,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Vec<ImageSummary>> {
|
||||
let server = self
|
||||
.get_server_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
let server: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
self.periphery_client(&server)
|
||||
.request(requests::GetImageList {})
|
||||
@@ -318,8 +314,8 @@ impl Resolve<GetDockerNetworks, RequestUser> for State {
|
||||
GetDockerNetworks { server_id }: GetDockerNetworks,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Vec<DockerNetwork>> {
|
||||
let server = self
|
||||
.get_server_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
let server: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
self.periphery_client(&server)
|
||||
.request(requests::GetNetworkList {})
|
||||
@@ -334,8 +330,8 @@ impl Resolve<GetDockerContainers, RequestUser> for State {
|
||||
GetDockerContainers { server_id }: GetDockerContainers,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Vec<ContainerSummary>> {
|
||||
let server = self
|
||||
.get_server_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
let server: Server = self
|
||||
.get_resource_check_permissions(&server_id, &user, PermissionLevel::Read)
|
||||
.await?;
|
||||
self.periphery_client(&server)
|
||||
.request(requests::GetContainerList {})
|
||||
@@ -350,20 +346,7 @@ impl Resolve<GetServersSummary, RequestUser> for State {
|
||||
GetServersSummary {}: GetServersSummary,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<GetServersSummaryResponse> {
|
||||
let query = if user.is_admin {
|
||||
None
|
||||
} else {
|
||||
let query = doc! {
|
||||
format!("permissions.{}", user.id): { "$in": ["read", "execute", "update"] }
|
||||
};
|
||||
Some(query)
|
||||
};
|
||||
let servers = self
|
||||
.db
|
||||
.servers
|
||||
.get_some(query, None)
|
||||
.await
|
||||
.context("failed to get servers from db")?;
|
||||
let servers: Vec<Server> = self.list_resources_for_user(&user, None).await?;
|
||||
let mut res = GetServersSummaryResponse::default();
|
||||
for server in servers {
|
||||
res.total += 1;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use async_trait::async_trait;
|
||||
use monitor_types::{entities::update::Update, requests::read::ListUpdates};
|
||||
use monitor_types::{entities::{update::Update, build::Build}, requests::read::ListUpdates};
|
||||
use mungos::mongodb::{bson::doc, options::FindOptions};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, state::State, resource::Resource};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<ListUpdates, RequestUser> for State {
|
||||
@@ -23,7 +23,7 @@ impl Resolve<ListUpdates, RequestUser> for State {
|
||||
.await?;
|
||||
Ok(updates)
|
||||
} else {
|
||||
let build_ids = self.get_build_ids_for_non_admin(&user.id).await?;
|
||||
let build_ids = <State as Resource<Build>>::get_resource_ids_for_non_admin(self, &user.id).await?;
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use monitor_types::{
|
||||
use mungos::mongodb::bson::{doc, to_bson};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, helpers::make_update, state::State};
|
||||
use crate::{auth::RequestUser, helpers::make_update, state::State, resource::Resource};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<CreateAlerter, RequestUser> for State {
|
||||
@@ -37,7 +37,7 @@ impl Resolve<CreateAlerter, RequestUser> for State {
|
||||
.create_one(alerter)
|
||||
.await
|
||||
.context("failed to add alerter to db")?;
|
||||
let alerter = self.get_alerter(&alerter_id).await?;
|
||||
let alerter: Alerter = self.get_resource(&alerter_id).await?;
|
||||
|
||||
let mut update = make_update(&alerter, Operation::CreateAlerter, &user);
|
||||
|
||||
@@ -70,7 +70,7 @@ impl Resolve<CopyAlerter, RequestUser> for State {
|
||||
description,
|
||||
..
|
||||
} = self
|
||||
.get_alerter_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
let start_ts = monitor_timestamp();
|
||||
let alerter = Alerter {
|
||||
@@ -91,7 +91,7 @@ impl Resolve<CopyAlerter, RequestUser> for State {
|
||||
.create_one(alerter)
|
||||
.await
|
||||
.context("failed to add alerter to db")?;
|
||||
let alerter = self.get_alerter(&alerter_id).await?;
|
||||
let alerter: Alerter = self.get_resource(&alerter_id).await?;
|
||||
|
||||
let mut update = make_update(&alerter, Operation::CreateAlerter, &user);
|
||||
|
||||
@@ -120,8 +120,8 @@ impl Resolve<DeleteAlerter, RequestUser> for State {
|
||||
DeleteAlerter { id }: DeleteAlerter,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Alerter> {
|
||||
let alerter = self
|
||||
.get_alerter_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let alerter: Alerter = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let mut update = make_update(
|
||||
@@ -156,8 +156,8 @@ impl Resolve<UpdateAlerter, RequestUser> for State {
|
||||
UpdateAlerter { id, config }: UpdateAlerter,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Alerter> {
|
||||
let alerter = self
|
||||
.get_alerter_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let alerter: Alerter = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let mut update = make_update(&alerter, Operation::UpdateAlerter, &user);
|
||||
@@ -174,7 +174,7 @@ impl Resolve<UpdateAlerter, RequestUser> for State {
|
||||
)
|
||||
.await?;
|
||||
|
||||
let alerter = self.get_alerter(&id).await?;
|
||||
let alerter: Alerter = self.get_resource(&id).await?;
|
||||
|
||||
update.finalize();
|
||||
self.add_update(update).await?;
|
||||
|
||||
@@ -4,7 +4,7 @@ use monitor_types::{
|
||||
entities::{
|
||||
build::{Build, BuildBuilderConfig},
|
||||
update::{Log, UpdateStatus},
|
||||
Operation, PermissionLevel,
|
||||
Operation, PermissionLevel, server::Server, builder::Builder,
|
||||
},
|
||||
monitor_timestamp,
|
||||
requests::write::*,
|
||||
@@ -15,7 +15,7 @@ use resolver_api::Resolve;
|
||||
use crate::{
|
||||
auth::RequestUser,
|
||||
helpers::{empty_or_only_spaces, make_update},
|
||||
state::State,
|
||||
state::State, resource::Resource,
|
||||
};
|
||||
|
||||
#[async_trait]
|
||||
@@ -28,7 +28,7 @@ impl Resolve<CreateBuild, RequestUser> for State {
|
||||
if let Some(builder) = &config.builder {
|
||||
match builder {
|
||||
BuildBuilderConfig::Server { server_id } => {
|
||||
self.get_server_check_permissions(
|
||||
let _: Server = self.get_resource_check_permissions(
|
||||
server_id,
|
||||
&user,
|
||||
PermissionLevel::Update,
|
||||
@@ -37,7 +37,7 @@ impl Resolve<CreateBuild, RequestUser> for State {
|
||||
.context("cannot create build on this server. user must have update permissions on the server.")?;
|
||||
}
|
||||
BuildBuilderConfig::Builder { builder_id } => {
|
||||
self.get_builder_check_permissions(
|
||||
let _: Builder = self.get_resource_check_permissions(
|
||||
builder_id,
|
||||
&user,
|
||||
PermissionLevel::Read,
|
||||
@@ -66,7 +66,7 @@ impl Resolve<CreateBuild, RequestUser> for State {
|
||||
.create_one(build)
|
||||
.await
|
||||
.context("failed to add build to db")?;
|
||||
let build = self.get_build(&build_id).await?;
|
||||
let build: Build = self.get_resource(&build_id).await?;
|
||||
|
||||
let mut update = make_update(&build, Operation::CreateBuild, &user);
|
||||
|
||||
@@ -98,11 +98,11 @@ impl Resolve<CopyBuild, RequestUser> for State {
|
||||
tags,
|
||||
..
|
||||
} = self
|
||||
.get_build_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
match &config.builder {
|
||||
BuildBuilderConfig::Server { server_id } => {
|
||||
self.get_server_check_permissions(
|
||||
let _: Server = self.get_resource_check_permissions(
|
||||
server_id,
|
||||
&user,
|
||||
PermissionLevel::Update,
|
||||
@@ -111,7 +111,7 @@ impl Resolve<CopyBuild, RequestUser> for State {
|
||||
.context("cannot create build on this server. user must have update permissions on the server.")?;
|
||||
}
|
||||
BuildBuilderConfig::Builder { builder_id } => {
|
||||
self.get_builder_check_permissions(
|
||||
let _: Builder = self.get_resource_check_permissions(
|
||||
builder_id,
|
||||
&user,
|
||||
PermissionLevel::Read,
|
||||
@@ -139,7 +139,7 @@ impl Resolve<CopyBuild, RequestUser> for State {
|
||||
.create_one(build)
|
||||
.await
|
||||
.context("failed to add build to db")?;
|
||||
let build = self.get_build(&build_id).await?;
|
||||
let build: Build = self.get_resource(&build_id).await?;
|
||||
|
||||
let mut update = make_update(&build, Operation::CreateBuild, &user);
|
||||
|
||||
@@ -168,8 +168,8 @@ impl Resolve<DeleteBuild, RequestUser> for State {
|
||||
return Err(anyhow!("build busy"));
|
||||
}
|
||||
|
||||
let build = self
|
||||
.get_build_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let build: Build = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let mut update = make_update(&build, Operation::DeleteBuild, &user);
|
||||
@@ -207,15 +207,15 @@ impl Resolve<UpdateBuild, RequestUser> for State {
|
||||
return Err(anyhow!("build busy"));
|
||||
}
|
||||
|
||||
let build = self
|
||||
.get_build_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let build: Build = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let inner = || async move {
|
||||
if let Some(builder) = &config.builder {
|
||||
match builder {
|
||||
BuildBuilderConfig::Server { server_id } => {
|
||||
self.get_server_check_permissions(
|
||||
let _: Server = self.get_resource_check_permissions(
|
||||
server_id,
|
||||
&user,
|
||||
PermissionLevel::Update,
|
||||
@@ -224,7 +224,7 @@ impl Resolve<UpdateBuild, RequestUser> for State {
|
||||
.context("cannot create build on this server. user must have update permissions on the server.")?;
|
||||
}
|
||||
BuildBuilderConfig::Builder { builder_id } => {
|
||||
self.get_builder_check_permissions(
|
||||
let _: Builder = self.get_resource_check_permissions(
|
||||
builder_id,
|
||||
&user,
|
||||
PermissionLevel::Read,
|
||||
@@ -261,7 +261,7 @@ impl Resolve<UpdateBuild, RequestUser> for State {
|
||||
|
||||
self.add_update(update).await?;
|
||||
|
||||
let build = self.get_build(&build.id).await?;
|
||||
let build: Build = self.get_resource(&build.id).await?;
|
||||
|
||||
anyhow::Ok(build)
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ use monitor_types::{
|
||||
use mungos::mongodb::bson::{doc, to_bson};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, state::State, resource::Resource};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<CreateBuilder, RequestUser> for State {
|
||||
@@ -39,7 +39,7 @@ impl Resolve<CreateBuilder, RequestUser> for State {
|
||||
.create_one(builder)
|
||||
.await
|
||||
.context("failed to add builder to db")?;
|
||||
let builder = self.get_builder(&builder_id).await?;
|
||||
let builder: Builder = self.get_resource(&builder_id).await?;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Builder(builder_id),
|
||||
operation: Operation::CreateBuilder,
|
||||
@@ -78,7 +78,7 @@ impl Resolve<CopyBuilder, RequestUser> for State {
|
||||
description,
|
||||
..
|
||||
} = self
|
||||
.get_builder_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
let start_ts = monitor_timestamp();
|
||||
let builder = Builder {
|
||||
@@ -98,7 +98,7 @@ impl Resolve<CopyBuilder, RequestUser> for State {
|
||||
.create_one(builder)
|
||||
.await
|
||||
.context("failed to add builder to db")?;
|
||||
let builder = self.get_builder(&builder_id).await?;
|
||||
let builder: Builder = self.get_resource(&builder_id).await?;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Builder(builder_id),
|
||||
operation: Operation::CreateBuilder,
|
||||
@@ -132,8 +132,8 @@ impl Resolve<DeleteBuilder, RequestUser> for State {
|
||||
DeleteBuilder { id }: DeleteBuilder,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Builder> {
|
||||
let builder = self
|
||||
.get_builder_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let builder: Builder = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let start_ts = monitor_timestamp();
|
||||
@@ -178,8 +178,8 @@ impl Resolve<UpdateBuilder, RequestUser> for State {
|
||||
UpdateBuilder { id, config }: UpdateBuilder,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Builder> {
|
||||
let builder = self
|
||||
.get_builder_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let builder: Builder = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let mut update = Update {
|
||||
@@ -204,7 +204,7 @@ impl Resolve<UpdateBuilder, RequestUser> for State {
|
||||
)
|
||||
.await?;
|
||||
|
||||
let builder = self.get_builder(&id).await?;
|
||||
let builder: Builder = self.get_resource(&id).await?;
|
||||
|
||||
update.finalize();
|
||||
self.add_update(update).await?;
|
||||
|
||||
@@ -3,7 +3,9 @@ use async_trait::async_trait;
|
||||
use monitor_types::{
|
||||
all_logs_success,
|
||||
entities::{
|
||||
build::Build,
|
||||
deployment::{Deployment, DeploymentImage, DockerContainerState},
|
||||
server::Server,
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
Operation, PermissionLevel,
|
||||
},
|
||||
@@ -15,7 +17,7 @@ use mungos::mongodb::bson::{doc, to_bson};
|
||||
use periphery_client::requests;
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, helpers::empty_or_only_spaces, state::State};
|
||||
use crate::{auth::RequestUser, helpers::empty_or_only_spaces, resource::Resource, state::State};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<CreateDeployment, RequestUser> for State {
|
||||
@@ -26,14 +28,14 @@ impl Resolve<CreateDeployment, RequestUser> for State {
|
||||
) -> anyhow::Result<Deployment> {
|
||||
if let Some(server_id) = &config.server_id {
|
||||
if !server_id.is_empty() {
|
||||
self.get_server_check_permissions(server_id, &user, PermissionLevel::Update)
|
||||
let _: Server = self.get_resource_check_permissions(server_id, &user, PermissionLevel::Update)
|
||||
.await
|
||||
.context("cannot create deployment on this server. user must have update permissions on the server to perform this action.")?;
|
||||
}
|
||||
}
|
||||
if let Some(DeploymentImage::Build { build_id, .. }) = &config.image {
|
||||
if !build_id.is_empty() {
|
||||
self.get_build_check_permissions(build_id, &user, PermissionLevel::Read)
|
||||
let _: Build = self.get_resource_check_permissions(build_id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
.context("cannot create deployment with this build attached. user must have at least read permissions on the build to perform this action.")?;
|
||||
}
|
||||
@@ -56,7 +58,7 @@ impl Resolve<CreateDeployment, RequestUser> for State {
|
||||
.create_one(&deployment)
|
||||
.await
|
||||
.context("failed to add deployment to db")?;
|
||||
let deployment = self.get_deployment(&deployment_id).await?;
|
||||
let deployment: Deployment = self.get_resource(&deployment_id).await?;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Deployment(deployment_id),
|
||||
operation: Operation::CreateDeployment,
|
||||
@@ -96,16 +98,16 @@ impl Resolve<CopyDeployment, RequestUser> for State {
|
||||
tags,
|
||||
..
|
||||
} = self
|
||||
.get_deployment_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
if !config.server_id.is_empty() {
|
||||
self.get_server_check_permissions(&config.server_id, &user, PermissionLevel::Update)
|
||||
let _: Server = self.get_resource_check_permissions(&config.server_id, &user, PermissionLevel::Update)
|
||||
.await
|
||||
.context("cannot create deployment on this server. user must have update permissions on the server to perform this action.")?;
|
||||
}
|
||||
if let DeploymentImage::Build { build_id, .. } = &config.image {
|
||||
if !build_id.is_empty() {
|
||||
self.get_build_check_permissions(build_id, &user, PermissionLevel::Read)
|
||||
let _: Build = self.get_resource_check_permissions(build_id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
.context("cannot create deployment with this build attached. user must have at least read permissions on the build to perform this action.")?;
|
||||
}
|
||||
@@ -128,7 +130,7 @@ impl Resolve<CopyDeployment, RequestUser> for State {
|
||||
.create_one(&deployment)
|
||||
.await
|
||||
.context("failed to add deployment to db")?;
|
||||
let deployment = self.get_deployment(&deployment_id).await?;
|
||||
let deployment: Deployment = self.get_resource(&deployment_id).await?;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Deployment(deployment_id),
|
||||
operation: Operation::CreateDeployment,
|
||||
@@ -166,8 +168,8 @@ impl Resolve<DeleteDeployment, RequestUser> for State {
|
||||
return Err(anyhow!("deployment busy"));
|
||||
}
|
||||
|
||||
let deployment = self
|
||||
.get_deployment_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let deployment: Deployment = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let inner = || async move {
|
||||
@@ -195,7 +197,8 @@ impl Resolve<DeleteDeployment, RequestUser> for State {
|
||||
DockerContainerState::NotDeployed | DockerContainerState::Unknown
|
||||
) {
|
||||
// container needs to be destroyed
|
||||
let server = self.get_server(&deployment.config.server_id).await;
|
||||
let server: anyhow::Result<Server> =
|
||||
self.get_resource(&deployment.config.server_id).await;
|
||||
if let Err(e) = server {
|
||||
update.logs.push(Log::error(
|
||||
"remove container",
|
||||
@@ -283,20 +286,20 @@ impl Resolve<UpdateDeployment, RequestUser> for State {
|
||||
return Err(anyhow!("deployment busy"));
|
||||
}
|
||||
|
||||
let deployment = self
|
||||
.get_deployment_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let deployment: Deployment = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let inner = || async move {
|
||||
let start_ts = monitor_timestamp();
|
||||
|
||||
if let Some(server_id) = &config.server_id {
|
||||
self.get_server_check_permissions(server_id, &user, PermissionLevel::Update)
|
||||
let _: Server = self.get_resource_check_permissions(server_id, &user, PermissionLevel::Update)
|
||||
.await
|
||||
.context("cannot create deployment on this server. user must have update permissions on the server to perform this action.")?;
|
||||
}
|
||||
if let Some(DeploymentImage::Build { build_id, .. }) = &config.image {
|
||||
self.get_build_check_permissions(build_id, &user, PermissionLevel::Read)
|
||||
let _: Build = self.get_resource_check_permissions(build_id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
.context("cannot create deployment with this build attached. user must have at least read permissions on the build to perform this action.")?;
|
||||
}
|
||||
@@ -346,7 +349,7 @@ impl Resolve<UpdateDeployment, RequestUser> for State {
|
||||
|
||||
self.add_update(update).await?;
|
||||
|
||||
let deployment = self.get_deployment(&id).await?;
|
||||
let deployment: Deployment = self.get_resource(&id).await?;
|
||||
|
||||
anyhow::Ok(deployment)
|
||||
};
|
||||
@@ -382,8 +385,8 @@ impl Resolve<RenameDeployment, RequestUser> for State {
|
||||
return Err(anyhow!("deployment busy"));
|
||||
}
|
||||
|
||||
let deployment = self
|
||||
.get_deployment_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let deployment: Deployment = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let inner = || async {
|
||||
@@ -401,7 +404,7 @@ impl Resolve<RenameDeployment, RequestUser> for State {
|
||||
}
|
||||
|
||||
if container_state != DockerContainerState::NotDeployed {
|
||||
let server = self.get_server(&deployment.config.server_id).await?;
|
||||
let server: Server = self.get_resource(&deployment.config.server_id).await?;
|
||||
match self
|
||||
.periphery_client(&server)
|
||||
.request(requests::RenameContainer {
|
||||
|
||||
@@ -4,7 +4,7 @@ use monitor_types::{
|
||||
entities::{
|
||||
repo::Repo,
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
Operation, PermissionLevel,
|
||||
Operation, PermissionLevel, server::Server,
|
||||
},
|
||||
monitor_timestamp,
|
||||
requests::{execute, write::*},
|
||||
@@ -13,7 +13,7 @@ use mungos::mongodb::bson::{doc, to_bson};
|
||||
use periphery_client::requests;
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, state::State, resource::Resource};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<CreateRepo, RequestUser> for State {
|
||||
@@ -24,7 +24,7 @@ impl Resolve<CreateRepo, RequestUser> for State {
|
||||
) -> anyhow::Result<Repo> {
|
||||
if let Some(server_id) = &config.server_id {
|
||||
if !server_id.is_empty() {
|
||||
self.get_server_check_permissions(
|
||||
let _: Server = self.get_resource_check_permissions(
|
||||
server_id,
|
||||
&user,
|
||||
PermissionLevel::Update,
|
||||
@@ -53,7 +53,7 @@ impl Resolve<CreateRepo, RequestUser> for State {
|
||||
.await
|
||||
.context("failed to add repo to db")?;
|
||||
|
||||
let repo = self.get_repo(&repo_id).await?;
|
||||
let repo: Repo = self.get_resource(&repo_id).await?;
|
||||
|
||||
let update = Update {
|
||||
target: ResourceTarget::Repo(repo_id),
|
||||
@@ -102,10 +102,10 @@ impl Resolve<CopyRepo, RequestUser> for State {
|
||||
tags,
|
||||
..
|
||||
} = self
|
||||
.get_repo_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
if !config.server_id.is_empty() {
|
||||
self.get_server_check_permissions(
|
||||
let _: Server = self.get_resource_check_permissions(
|
||||
&config.server_id,
|
||||
&user,
|
||||
PermissionLevel::Update,
|
||||
@@ -132,7 +132,7 @@ impl Resolve<CopyRepo, RequestUser> for State {
|
||||
.create_one(repo)
|
||||
.await
|
||||
.context("failed to add repo to db")?;
|
||||
let repo = self.get_repo(&repo_id).await?;
|
||||
let repo: Repo = self.get_resource(&repo_id).await?;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Repo(repo_id),
|
||||
operation: Operation::CreateRepo,
|
||||
@@ -163,8 +163,8 @@ impl Resolve<DeleteRepo, RequestUser> for State {
|
||||
DeleteRepo { id }: DeleteRepo,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Repo> {
|
||||
let repo = self
|
||||
.get_repo_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let repo: Repo = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let inner = || async move {
|
||||
@@ -194,7 +194,7 @@ impl Resolve<DeleteRepo, RequestUser> for State {
|
||||
update.logs.push(log);
|
||||
|
||||
if !repo.config.server_id.is_empty() {
|
||||
let server = self.get_server(&repo.config.server_id).await;
|
||||
let server: anyhow::Result<Server> = self.get_resource(&repo.config.server_id).await;
|
||||
if let Ok(server) = server {
|
||||
match self
|
||||
.periphery_client(&server)
|
||||
@@ -248,8 +248,8 @@ impl Resolve<UpdateRepo, RequestUser> for State {
|
||||
UpdateRepo { id, config }: UpdateRepo,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Repo> {
|
||||
let repo = self
|
||||
.get_repo_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let repo: Repo = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let inner = || async move {
|
||||
@@ -257,7 +257,7 @@ impl Resolve<UpdateRepo, RequestUser> for State {
|
||||
|
||||
if let Some(server_id) = &config.server_id {
|
||||
if !server_id.is_empty() {
|
||||
self.get_server_check_permissions(
|
||||
let _: Server = self.get_resource_check_permissions(
|
||||
server_id,
|
||||
&user,
|
||||
PermissionLevel::Update,
|
||||
@@ -297,7 +297,7 @@ impl Resolve<UpdateRepo, RequestUser> for State {
|
||||
if new_server_id != repo.config.server_id {
|
||||
if !repo.config.server_id.is_empty() {
|
||||
// clean up old server
|
||||
let old_server = self.get_server(&repo.config.server_id).await?;
|
||||
let old_server: Server = self.get_resource(&repo.config.server_id).await?;
|
||||
let res = self
|
||||
.periphery_client(&old_server)
|
||||
.request(requests::DeleteRepo { name: repo.name })
|
||||
@@ -323,7 +323,7 @@ impl Resolve<UpdateRepo, RequestUser> for State {
|
||||
}
|
||||
}
|
||||
|
||||
let repo = self.get_repo(&repo.id).await?;
|
||||
let repo: Repo = self.get_resource(&repo.id).await?;
|
||||
|
||||
anyhow::Ok(repo)
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ use monitor_types::{
|
||||
use mungos::mongodb::bson::{doc, to_bson};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
use crate::{auth::RequestUser, state::State, resource::Resource};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<CreateServer, RequestUser> for State {
|
||||
@@ -38,7 +38,7 @@ impl Resolve<CreateServer, RequestUser> for State {
|
||||
.create_one(&server)
|
||||
.await
|
||||
.context("failed to add server to db")?;
|
||||
let server = self.get_server(&server_id).await?;
|
||||
let server: Server = self.get_resource(&server_id).await?;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Server(server_id),
|
||||
operation: Operation::CreateServer,
|
||||
@@ -75,8 +75,8 @@ impl Resolve<DeleteServer, RequestUser> for State {
|
||||
return Err(anyhow!("server busy"));
|
||||
}
|
||||
|
||||
let server = self
|
||||
.get_server_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let server: Server = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
|
||||
let start_ts = monitor_timestamp();
|
||||
@@ -146,7 +146,7 @@ impl Resolve<UpdateServer, RequestUser> for State {
|
||||
return Err(anyhow!("server busy"));
|
||||
}
|
||||
let start_ts = monitor_timestamp();
|
||||
self.get_server_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let _: Server = self.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
self.db
|
||||
.servers
|
||||
@@ -171,7 +171,7 @@ impl Resolve<UpdateServer, RequestUser> for State {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let new_server = self.get_server(&id).await?;
|
||||
let new_server: Server = self.get_resource(&id).await?;
|
||||
|
||||
self.update_cache_for_server(&new_server, 0).await;
|
||||
|
||||
@@ -189,8 +189,8 @@ impl Resolve<RenameServer, RequestUser> for State {
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Update> {
|
||||
let start_ts = monitor_timestamp();
|
||||
let server = self
|
||||
.get_server_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
let server: Server = self
|
||||
.get_resource_check_permissions(&id, &user, PermissionLevel::Update)
|
||||
.await?;
|
||||
self.db
|
||||
.updates
|
||||
|
||||
170
bin/core/src/resource.rs
Normal file
170
bin/core/src/resource.rs
Normal file
@@ -0,0 +1,170 @@
|
||||
use anyhow::{anyhow, Context};
|
||||
use async_trait::async_trait;
|
||||
use monitor_types::{
|
||||
entities::{
|
||||
alerter::Alerter, build::Build, builder::Builder, deployment::Deployment, repo::Repo,
|
||||
server::Server, PermissionLevel,
|
||||
},
|
||||
permissioned::Permissioned,
|
||||
};
|
||||
use mungos::{
|
||||
mongodb::bson::{doc, Document},
|
||||
AggStage::*,
|
||||
Collection, Indexed,
|
||||
};
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
|
||||
#[async_trait]
|
||||
pub trait Resource<T: Indexed + Send + Unpin + Permissioned> {
|
||||
fn name() -> &'static str;
|
||||
fn coll(&self) -> &Collection<T>;
|
||||
|
||||
async fn get_resource(&self, id: &str) -> anyhow::Result<T> {
|
||||
self.coll()
|
||||
.find_one_by_id(id)
|
||||
.await
|
||||
.context(format!("failed to get {} from db", Self::name()))?
|
||||
.context(format!("did not find any {} with id {id}", Self::name()))
|
||||
}
|
||||
|
||||
async fn get_resource_check_permissions(
|
||||
&self,
|
||||
id: &str,
|
||||
user: &RequestUser,
|
||||
permission_level: PermissionLevel,
|
||||
) -> anyhow::Result<T> {
|
||||
let resource = self.get_resource(id).await?;
|
||||
let permissions = resource.get_user_permissions(&user.id);
|
||||
if user.is_admin || permissions >= permission_level {
|
||||
Ok(resource)
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"user does not have required permissions on this {}",
|
||||
Self::name()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_user_permission_on_resource(
|
||||
&self,
|
||||
user_id: &str,
|
||||
resource_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let resource = self.get_resource(resource_id).await?;
|
||||
Ok(resource.get_user_permissions(user_id))
|
||||
}
|
||||
|
||||
async fn get_resource_ids_for_non_admin(&self, user_id: &str) -> anyhow::Result<Vec<String>> {
|
||||
self.coll()
|
||||
.aggregate_collect(
|
||||
[
|
||||
Match(doc! {
|
||||
format!("permissions.{}", user_id): { "$in": ["update", "execute", "read"] }
|
||||
}),
|
||||
Project(doc! { "_id": 1 }),
|
||||
],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.context(format!(
|
||||
"failed to get {} ids for non admin | aggregation",
|
||||
Self::name()
|
||||
))?
|
||||
.into_iter()
|
||||
.map(|d| {
|
||||
let id = d
|
||||
.get("_id")
|
||||
.context("no _id field")?
|
||||
.as_object_id()
|
||||
.context("_id not ObjectId")?
|
||||
.to_string();
|
||||
anyhow::Ok(id)
|
||||
})
|
||||
.collect::<anyhow::Result<Vec<_>>>()
|
||||
.context(format!(
|
||||
"failed to get {} ids for non admin | extract id from document",
|
||||
Self::name()
|
||||
))
|
||||
}
|
||||
|
||||
async fn list_resources_for_user(
|
||||
&self,
|
||||
user: &RequestUser,
|
||||
query: Option<Document>,
|
||||
) -> anyhow::Result<Vec<T>> {
|
||||
let mut query = query.unwrap_or_default();
|
||||
if !user.is_admin {
|
||||
query.insert(
|
||||
format!("permissions.{}", user.id),
|
||||
doc! { "$in": ["read", "execute", "update"] },
|
||||
);
|
||||
}
|
||||
self.coll()
|
||||
.get_some(query, None)
|
||||
.await
|
||||
.context(format!("failed to pull {}s from mongo", Self::name()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl Resource<Server> for State {
|
||||
fn name() -> &'static str {
|
||||
"server"
|
||||
}
|
||||
|
||||
fn coll(&self) -> &Collection<Server> {
|
||||
&self.db.servers
|
||||
}
|
||||
}
|
||||
|
||||
impl Resource<Deployment> for State {
|
||||
fn name() -> &'static str {
|
||||
"deployment"
|
||||
}
|
||||
|
||||
fn coll(&self) -> &Collection<Deployment> {
|
||||
&self.db.deployments
|
||||
}
|
||||
}
|
||||
|
||||
impl Resource<Build> for State {
|
||||
fn name() -> &'static str {
|
||||
"build"
|
||||
}
|
||||
|
||||
fn coll(&self) -> &Collection<Build> {
|
||||
&self.db.builds
|
||||
}
|
||||
}
|
||||
|
||||
impl Resource<Builder> for State {
|
||||
fn name() -> &'static str {
|
||||
"builder"
|
||||
}
|
||||
|
||||
fn coll(&self) -> &Collection<Builder> {
|
||||
&self.db.builders
|
||||
}
|
||||
}
|
||||
|
||||
impl Resource<Repo> for State {
|
||||
fn name() -> &'static str {
|
||||
"repo"
|
||||
}
|
||||
|
||||
fn coll(&self) -> &Collection<Repo> {
|
||||
&self.db.repos
|
||||
}
|
||||
}
|
||||
|
||||
impl Resource<Alerter> for State {
|
||||
fn name() -> &'static str {
|
||||
"alerter"
|
||||
}
|
||||
|
||||
fn coll(&self) -> &Collection<Alerter> {
|
||||
&self.db.alerters
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,19 @@ use axum::{
|
||||
Router,
|
||||
};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use monitor_types::entities::{
|
||||
update::{ResourceTarget, ResourceTargetVariant},
|
||||
user::User,
|
||||
PermissionLevel,
|
||||
use monitor_types::{
|
||||
entities::{
|
||||
alerter::Alerter,
|
||||
build::Build,
|
||||
builder::Builder,
|
||||
deployment::Deployment,
|
||||
repo::Repo,
|
||||
server::Server,
|
||||
update::{ResourceTarget, ResourceTargetVariant},
|
||||
user::User,
|
||||
PermissionLevel,
|
||||
},
|
||||
permissioned::Permissioned,
|
||||
};
|
||||
use serde_json::json;
|
||||
use tokio::select;
|
||||
@@ -20,6 +29,7 @@ use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::{
|
||||
auth::RequestUser,
|
||||
resource::Resource,
|
||||
state::{State, StateExtension},
|
||||
};
|
||||
|
||||
@@ -143,36 +153,46 @@ impl State {
|
||||
}
|
||||
let (permissions, target) = match update_target {
|
||||
ResourceTarget::Server(server_id) => {
|
||||
let permissions = self
|
||||
.get_user_permission_on_server(user_id, server_id)
|
||||
.await?;
|
||||
(permissions, ResourceTargetVariant::Server)
|
||||
let resource: Server = self.get_resource(server_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(user_id),
|
||||
ResourceTargetVariant::Server,
|
||||
)
|
||||
}
|
||||
ResourceTarget::Deployment(deployment_id) => {
|
||||
let permissions = self
|
||||
.get_user_permission_on_deployment(user_id, deployment_id)
|
||||
.await?;
|
||||
(permissions, ResourceTargetVariant::Deployment)
|
||||
let resource: Deployment = self.get_resource(deployment_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(user_id),
|
||||
ResourceTargetVariant::Deployment,
|
||||
)
|
||||
}
|
||||
ResourceTarget::Build(build_id) => {
|
||||
let permissions = self.get_user_permission_on_build(user_id, build_id).await?;
|
||||
(permissions, ResourceTargetVariant::Build)
|
||||
let resource: Build = self.get_resource(build_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(user_id),
|
||||
ResourceTargetVariant::Build,
|
||||
)
|
||||
}
|
||||
ResourceTarget::Builder(builder_id) => {
|
||||
let permissions = self
|
||||
.get_user_permission_on_builder(user_id, builder_id)
|
||||
.await?;
|
||||
(permissions, ResourceTargetVariant::Builder)
|
||||
let resource: Builder = self.get_resource(builder_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(user_id),
|
||||
ResourceTargetVariant::Builder,
|
||||
)
|
||||
}
|
||||
ResourceTarget::Repo(repo_id) => {
|
||||
let permissions = self.get_user_permission_on_repo(user_id, repo_id).await?;
|
||||
(permissions, ResourceTargetVariant::Repo)
|
||||
let resource: Repo = self.get_resource(repo_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(user_id),
|
||||
ResourceTargetVariant::Repo,
|
||||
)
|
||||
}
|
||||
ResourceTarget::Alerter(alerter_id) => {
|
||||
let permissions = self
|
||||
.get_user_permission_on_alerter(user_id, alerter_id)
|
||||
.await?;
|
||||
(permissions, ResourceTargetVariant::Alerter)
|
||||
let resource: Alerter = self.get_resource(alerter_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(user_id),
|
||||
ResourceTargetVariant::Alerter,
|
||||
)
|
||||
}
|
||||
ResourceTarget::System => {
|
||||
return Err(anyhow!("user not admin, can't recieve system updates"))
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
use resolver_api::derive::Request;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::{entities::alerter::Alerter, MongoDocument};
|
||||
|
||||
//
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||
#[response(Alerter)]
|
||||
pub struct GetAlerter {
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||
#[response(Vec<Alerter>)]
|
||||
pub struct ListAlerters {
|
||||
pub query: Option<MongoDocument>,
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||
#[response(GetAlertersSummaryResponse)]
|
||||
pub struct GetAlertersSummary {}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct GetAlertersSummaryResponse {
|
||||
pub total: u32,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user