mirror of
https://github.com/moghtech/komodo.git
synced 2026-08-02 10:58:59 -05:00
more resource permissions to own table
This commit is contained in:
@@ -13,10 +13,11 @@ use monitor_client::{
|
||||
builder::{AwsBuilderConfig, Builder, BuilderConfig},
|
||||
deployment::DockerContainerState,
|
||||
monitor_timestamp,
|
||||
permission::PermissionLevel,
|
||||
server::Server,
|
||||
update::{Log, Update},
|
||||
user::User,
|
||||
Operation, PermissionLevel,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
|
||||
@@ -7,10 +7,11 @@ use monitor_client::{
|
||||
build::Build,
|
||||
deployment::{Deployment, DeploymentImage},
|
||||
get_image_name, monitor_timestamp,
|
||||
permission::PermissionLevel,
|
||||
server::ServerStatus,
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
user::User,
|
||||
Operation, PermissionLevel, Version,
|
||||
Operation, Version,
|
||||
},
|
||||
};
|
||||
use mungos::{find::find_collect, mongodb::bson::doc};
|
||||
|
||||
@@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||
use monitor_client::{
|
||||
api::execute::RunProcedure,
|
||||
entities::{
|
||||
procedure::Procedure, update::Update, user::User, Operation,
|
||||
PermissionLevel,
|
||||
permission::PermissionLevel, procedure::Procedure,
|
||||
update::Update, user::User, Operation,
|
||||
},
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
@@ -6,11 +6,12 @@ use monitor_client::{
|
||||
api::execute::*,
|
||||
entities::{
|
||||
monitor_timestamp, optional_string,
|
||||
permission::PermissionLevel,
|
||||
repo::Repo,
|
||||
server::Server,
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
user::User,
|
||||
Operation, PermissionLevel,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use mungos::mongodb::bson::{doc, oid::ObjectId};
|
||||
|
||||
@@ -4,10 +4,11 @@ use monitor_client::{
|
||||
api::execute::*,
|
||||
entities::{
|
||||
monitor_timestamp,
|
||||
permission::PermissionLevel,
|
||||
server::Server,
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
user::User,
|
||||
Operation, PermissionLevel,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use periphery_client::api;
|
||||
|
||||
@@ -4,9 +4,9 @@ use monitor_client::{
|
||||
api::read::*,
|
||||
entities::{
|
||||
alerter::{Alerter, AlerterListItem},
|
||||
permission::PermissionLevel,
|
||||
resource::AddFilters,
|
||||
user::User,
|
||||
PermissionLevel,
|
||||
},
|
||||
};
|
||||
use mungos::mongodb::bson::{doc, Document};
|
||||
|
||||
@@ -8,10 +8,11 @@ use monitor_client::{
|
||||
api::read::*,
|
||||
entities::{
|
||||
build::{Build, BuildActionState, BuildListItem},
|
||||
permission::PermissionLevel,
|
||||
resource::AddFilters,
|
||||
update::UpdateStatus,
|
||||
user::User,
|
||||
Operation, PermissionLevel,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
|
||||
@@ -4,9 +4,9 @@ use monitor_client::{
|
||||
api::read::{self, *},
|
||||
entities::{
|
||||
builder::{Builder, BuilderConfig, BuilderListItem},
|
||||
permission::PermissionLevel,
|
||||
resource::AddFilters,
|
||||
user::User,
|
||||
PermissionLevel,
|
||||
},
|
||||
};
|
||||
use mungos::mongodb::bson::{doc, Document};
|
||||
|
||||
@@ -10,11 +10,12 @@ use monitor_client::{
|
||||
DeploymentImage, DeploymentListItem, DockerContainerState,
|
||||
DockerContainerStats,
|
||||
},
|
||||
permission::PermissionLevel,
|
||||
resource::AddFilters,
|
||||
server::Server,
|
||||
update::{Log, UpdateStatus},
|
||||
user::User,
|
||||
Operation, PermissionLevel,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
|
||||
@@ -9,8 +9,8 @@ use monitor_client::{
|
||||
ListProceduresResponse,
|
||||
},
|
||||
entities::{
|
||||
procedure::Procedure, resource::AddFilters, user::User,
|
||||
PermissionLevel,
|
||||
permission::PermissionLevel, procedure::Procedure,
|
||||
resource::AddFilters, user::User,
|
||||
},
|
||||
};
|
||||
use mungos::mongodb::bson::{doc, Document};
|
||||
|
||||
@@ -3,10 +3,10 @@ use async_trait::async_trait;
|
||||
use monitor_client::{
|
||||
api::read::*,
|
||||
entities::{
|
||||
permission::PermissionLevel,
|
||||
repo::{Repo, RepoActionState, RepoListItem},
|
||||
resource::AddFilters,
|
||||
user::User,
|
||||
PermissionLevel,
|
||||
},
|
||||
};
|
||||
use mungos::mongodb::bson::{doc, Document};
|
||||
|
||||
@@ -5,6 +5,7 @@ use monitor_client::{
|
||||
api::read::*,
|
||||
entities::{
|
||||
deployment::ContainerSummary,
|
||||
permission::PermissionLevel,
|
||||
resource::AddFilters,
|
||||
server::{
|
||||
docker_image::ImageSummary, docker_network::DockerNetwork,
|
||||
@@ -12,7 +13,6 @@ use monitor_client::{
|
||||
ServerListItem, ServerStatus,
|
||||
},
|
||||
user::User,
|
||||
PermissionLevel,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
|
||||
@@ -9,12 +9,12 @@ use monitor_client::{
|
||||
build::Build,
|
||||
builder::Builder,
|
||||
deployment::Deployment,
|
||||
permission::PermissionLevel,
|
||||
procedure::Procedure,
|
||||
repo::Repo,
|
||||
server::Server,
|
||||
update::{ResourceTarget, Update, UpdateListItem},
|
||||
user::User,
|
||||
PermissionLevel,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
|
||||
@@ -7,8 +7,9 @@ use monitor_client::{
|
||||
entities::{
|
||||
alerter::{Alerter, AlerterInfo},
|
||||
monitor_timestamp,
|
||||
permission::PermissionLevel,
|
||||
user::User,
|
||||
Operation, PermissionLevel,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
@@ -20,8 +21,8 @@ use resolver_api::Resolve;
|
||||
use crate::{
|
||||
db::db_client,
|
||||
helpers::{
|
||||
add_update, make_update, remove_from_recently_viewed,
|
||||
resource::StateResource,
|
||||
add_update, create_permission, make_update,
|
||||
remove_from_recently_viewed, resource::StateResource,
|
||||
},
|
||||
state::State,
|
||||
};
|
||||
@@ -44,9 +45,6 @@ impl Resolve<CreateAlerter, User> for State {
|
||||
id: Default::default(),
|
||||
name,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description: Default::default(),
|
||||
tags: Default::default(),
|
||||
config: config.into(),
|
||||
@@ -64,6 +62,8 @@ impl Resolve<CreateAlerter, User> for State {
|
||||
.to_string();
|
||||
let alerter: Alerter = self.get_resource(&alerter_id).await?;
|
||||
|
||||
create_permission(&user, &alerter, PermissionLevel::Update).await;
|
||||
|
||||
let mut update =
|
||||
make_update(&alerter, Operation::CreateAlerter, &user);
|
||||
|
||||
@@ -108,9 +108,6 @@ impl Resolve<CopyAlerter, User> for State {
|
||||
id: Default::default(),
|
||||
name,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description,
|
||||
config,
|
||||
tags: Default::default(),
|
||||
@@ -128,6 +125,8 @@ impl Resolve<CopyAlerter, User> for State {
|
||||
.to_string();
|
||||
let alerter: Alerter = self.get_resource(&alerter_id).await?;
|
||||
|
||||
create_permission(&user, &alerter, PermissionLevel::Update).await;
|
||||
|
||||
let mut update =
|
||||
make_update(&alerter, Operation::CreateAlerter, &user);
|
||||
|
||||
|
||||
@@ -7,10 +7,12 @@ use monitor_client::{
|
||||
entities::{
|
||||
build::Build,
|
||||
builder::Builder,
|
||||
monitor_timestamp, to_monitor_name,
|
||||
monitor_timestamp,
|
||||
permission::PermissionLevel,
|
||||
to_monitor_name,
|
||||
update::{Log, UpdateStatus},
|
||||
user::User,
|
||||
Operation, PermissionLevel,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
@@ -22,7 +24,7 @@ use resolver_api::Resolve;
|
||||
use crate::{
|
||||
db::db_client,
|
||||
helpers::{
|
||||
add_update, empty_or_only_spaces, make_update,
|
||||
add_update, create_permission, empty_or_only_spaces, make_update,
|
||||
remove_from_recently_viewed, resource::StateResource,
|
||||
update_update,
|
||||
},
|
||||
@@ -48,9 +50,6 @@ impl Resolve<CreateBuild, User> for State {
|
||||
id: Default::default(),
|
||||
name,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description: Default::default(),
|
||||
tags: Default::default(),
|
||||
config: config.into(),
|
||||
@@ -68,6 +67,8 @@ impl Resolve<CreateBuild, User> for State {
|
||||
.to_string();
|
||||
let build: Build = self.get_resource(&build_id).await?;
|
||||
|
||||
create_permission(&user, &build, PermissionLevel::Update).await;
|
||||
|
||||
let mut update =
|
||||
make_update(&build, Operation::CreateBuild, &user);
|
||||
|
||||
@@ -115,9 +116,6 @@ impl Resolve<CopyBuild, User> for State {
|
||||
id: Default::default(),
|
||||
name,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description,
|
||||
tags,
|
||||
config,
|
||||
@@ -135,6 +133,8 @@ impl Resolve<CopyBuild, User> for State {
|
||||
.to_string();
|
||||
let build: Build = self.get_resource(&build_id).await?;
|
||||
|
||||
create_permission(&user, &build, PermissionLevel::Update).await;
|
||||
|
||||
let mut update =
|
||||
make_update(&build, Operation::CreateBuild, &user);
|
||||
|
||||
|
||||
@@ -5,9 +5,10 @@ use monitor_client::{
|
||||
entities::{
|
||||
builder::Builder,
|
||||
monitor_timestamp,
|
||||
permission::PermissionLevel,
|
||||
update::{Log, ResourceTarget, Update},
|
||||
user::User,
|
||||
Operation, PermissionLevel,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
@@ -19,7 +20,8 @@ use resolver_api::Resolve;
|
||||
use crate::{
|
||||
db::db_client,
|
||||
helpers::{
|
||||
add_update, remove_from_recently_viewed, resource::StateResource,
|
||||
add_update, create_permission, remove_from_recently_viewed,
|
||||
resource::StateResource,
|
||||
},
|
||||
state::State,
|
||||
};
|
||||
@@ -36,9 +38,6 @@ impl Resolve<CreateBuilder, User> for State {
|
||||
id: Default::default(),
|
||||
name,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description: Default::default(),
|
||||
tags: Default::default(),
|
||||
config: config.into(),
|
||||
@@ -55,6 +54,7 @@ impl Resolve<CreateBuilder, User> for State {
|
||||
.context("inserted_id is not ObjectId")?
|
||||
.to_string();
|
||||
let builder: Builder = self.get_resource(&builder_id).await?;
|
||||
create_permission(&user, &builder, PermissionLevel::Update).await;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Builder(builder_id),
|
||||
operation: Operation::CreateBuilder,
|
||||
@@ -104,9 +104,6 @@ impl Resolve<CopyBuilder, User> for State {
|
||||
id: Default::default(),
|
||||
name,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description,
|
||||
tags: Default::default(),
|
||||
config,
|
||||
@@ -123,6 +120,7 @@ impl Resolve<CopyBuilder, User> for State {
|
||||
.context("inserted_id is not ObjectId")?
|
||||
.to_string();
|
||||
let builder: Builder = self.get_resource(&builder_id).await?;
|
||||
create_permission(&user, &builder, PermissionLevel::Update).await;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Builder(builder_id),
|
||||
operation: Operation::CreateBuilder,
|
||||
|
||||
@@ -7,11 +7,12 @@ use monitor_client::{
|
||||
build::Build,
|
||||
deployment::{Deployment, DeploymentImage, DockerContainerState},
|
||||
monitor_timestamp,
|
||||
permission::PermissionLevel,
|
||||
server::Server,
|
||||
to_monitor_name,
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
user::User,
|
||||
Operation, PermissionLevel,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
@@ -24,9 +25,10 @@ use resolver_api::Resolve;
|
||||
use crate::{
|
||||
db::db_client,
|
||||
helpers::{
|
||||
add_update, empty_or_only_spaces, get_deployment_state,
|
||||
make_update, periphery_client, remove_from_recently_viewed,
|
||||
resource::StateResource, update_update,
|
||||
add_update, create_permission, empty_or_only_spaces,
|
||||
get_deployment_state, make_update, periphery_client,
|
||||
remove_from_recently_viewed, resource::StateResource,
|
||||
update_update,
|
||||
},
|
||||
state::{action_states, State},
|
||||
};
|
||||
@@ -60,9 +62,6 @@ impl Resolve<CreateDeployment, User> for State {
|
||||
id: Default::default(),
|
||||
name,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description: Default::default(),
|
||||
tags: Default::default(),
|
||||
config: config.into(),
|
||||
@@ -80,25 +79,21 @@ impl Resolve<CreateDeployment, User> for State {
|
||||
.to_string();
|
||||
let deployment: Deployment =
|
||||
self.get_resource(&deployment_id).await?;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Deployment(deployment_id),
|
||||
operation: Operation::CreateDeployment,
|
||||
start_ts,
|
||||
end_ts: Some(monitor_timestamp()),
|
||||
operator: user.id.clone(),
|
||||
success: true,
|
||||
logs: vec![
|
||||
Log::simple(
|
||||
"create deployment",
|
||||
format!(
|
||||
"created deployment\nid: {}\nname: {}",
|
||||
deployment.id, deployment.name
|
||||
),
|
||||
),
|
||||
Log::simple("config", format!("{:#?}", deployment.config)),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
create_permission(&user, &deployment, PermissionLevel::Update)
|
||||
.await;
|
||||
|
||||
let mut update =
|
||||
make_update(&deployment, Operation::CreateDeployment, &user);
|
||||
update.push_simple_log(
|
||||
"create deployment",
|
||||
format!(
|
||||
"created deployment\nid: {}\nname: {}",
|
||||
deployment.id, deployment.name
|
||||
),
|
||||
);
|
||||
update
|
||||
.push_simple_log("config", format!("{:#?}", deployment.config));
|
||||
update.finalize();
|
||||
|
||||
add_update(update).await?;
|
||||
|
||||
@@ -128,14 +123,14 @@ impl Resolve<CopyDeployment, User> for State {
|
||||
.await?;
|
||||
if !config.server_id.is_empty() {
|
||||
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.")?;
|
||||
.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() {
|
||||
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.")?;
|
||||
.await
|
||||
.context("cannot create deployment with this build attached. user must have at least read permissions on the build to perform this action.")?;
|
||||
}
|
||||
}
|
||||
let start_ts = monitor_timestamp();
|
||||
@@ -143,9 +138,6 @@ impl Resolve<CopyDeployment, User> for State {
|
||||
id: Default::default(),
|
||||
name,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description,
|
||||
tags,
|
||||
config,
|
||||
@@ -163,25 +155,22 @@ impl Resolve<CopyDeployment, User> for State {
|
||||
.to_string();
|
||||
let deployment: Deployment =
|
||||
self.get_resource(&deployment_id).await?;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Deployment(deployment_id),
|
||||
operation: Operation::CreateDeployment,
|
||||
start_ts,
|
||||
end_ts: Some(monitor_timestamp()),
|
||||
operator: user.id.clone(),
|
||||
success: true,
|
||||
logs: vec![
|
||||
Log::simple(
|
||||
"create deployment",
|
||||
format!(
|
||||
"created deployment\nid: {}\nname: {}",
|
||||
deployment.id, deployment.name
|
||||
),
|
||||
),
|
||||
Log::simple("config", format!("{:#?}", deployment.config)),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
create_permission(&user, &deployment, PermissionLevel::Update)
|
||||
.await;
|
||||
|
||||
let mut update =
|
||||
make_update(&deployment, Operation::CreateDeployment, &user);
|
||||
update.push_simple_log(
|
||||
"create deployment",
|
||||
format!(
|
||||
"created deployment\nid: {}\nname: {}",
|
||||
deployment.id, deployment.name
|
||||
),
|
||||
);
|
||||
update
|
||||
.push_simple_log("config", format!("{:#?}", deployment.config));
|
||||
update.finalize();
|
||||
|
||||
add_update(update).await?;
|
||||
|
||||
|
||||
@@ -5,11 +5,7 @@ use monitor_client::{
|
||||
UpdateUserPermissions, UpdateUserPermissionsOnTarget,
|
||||
},
|
||||
entities::{
|
||||
alerter::Alerter,
|
||||
monitor_timestamp,
|
||||
procedure::Procedure,
|
||||
repo::Repo,
|
||||
server::Server,
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
user::User,
|
||||
Operation,
|
||||
@@ -23,7 +19,7 @@ use resolver_api::Resolve;
|
||||
|
||||
use crate::{
|
||||
db::db_client,
|
||||
helpers::{add_update, get_user, resource::StateResource},
|
||||
helpers::{add_update, get_user},
|
||||
state::State,
|
||||
};
|
||||
|
||||
@@ -43,7 +39,6 @@ impl Resolve<UpdateUserPermissions, User> for State {
|
||||
if !admin.admin {
|
||||
return Err(anyhow!("this method is admin only"));
|
||||
}
|
||||
|
||||
let user = find_one_by_id(&db_client().await.users, &user_id)
|
||||
.await
|
||||
.context("failed to query mongo for user")?
|
||||
@@ -81,7 +76,6 @@ impl Resolve<UpdateUserPermissions, User> for State {
|
||||
"update permissions for {} ({})\nenabled: {enabled:?}\ncreate servers: {create_servers:?}\ncreate builds: {create_builds:?}",
|
||||
user.username,
|
||||
user.id,
|
||||
|
||||
),
|
||||
)],
|
||||
start_ts,
|
||||
@@ -111,7 +105,6 @@ impl Resolve<UpdateUserPermissionsOnTarget, User> for State {
|
||||
if !admin.admin {
|
||||
return Err(anyhow!("this method is admin only"));
|
||||
}
|
||||
|
||||
let user = get_user(&user_id).await?;
|
||||
if user.admin {
|
||||
return Err(anyhow!(
|
||||
@@ -121,143 +114,23 @@ impl Resolve<UpdateUserPermissionsOnTarget, User> for State {
|
||||
if !user.enabled {
|
||||
return Err(anyhow!("user not enabled"));
|
||||
}
|
||||
let log_text = match &target {
|
||||
ResourceTarget::System(_) => {
|
||||
return Err(anyhow!("target can not be system"))
|
||||
}
|
||||
ResourceTarget::Build(id) => {
|
||||
let build = find_one_by_id(&db_client().await.builds, id)
|
||||
.await
|
||||
.context("failed at find build query")?
|
||||
.ok_or(anyhow!("failed to find a build with id {id}"))?;
|
||||
|
||||
update_one_by_id(
|
||||
&db_client().await.builds,
|
||||
id,
|
||||
mungos::update::Update::Set(doc! {
|
||||
format!("permissions.{}", user_id): permission.to_string()
|
||||
}),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
format!(
|
||||
"user {} given {} permissions on build {}",
|
||||
user.username, permission, build.name
|
||||
)
|
||||
}
|
||||
ResourceTarget::Builder(id) => {
|
||||
let builder = find_one_by_id(&db_client().await.builders, id)
|
||||
.await
|
||||
.context("failed at find builder query")?
|
||||
.with_context(|| {
|
||||
format!("failed to find a builder with id {id}")
|
||||
})?;
|
||||
|
||||
update_one_by_id(
|
||||
&db_client().await.builders,
|
||||
id,
|
||||
mungos::update::Update::Set(doc! {
|
||||
format!("permissions.{}", user_id): permission.to_string()
|
||||
}),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
format!(
|
||||
"user {} given {} permissions on builder {}",
|
||||
user.username, permission, builder.name
|
||||
)
|
||||
}
|
||||
ResourceTarget::Deployment(id) => {
|
||||
let deployment =
|
||||
find_one_by_id(&db_client().await.deployments, id)
|
||||
.await
|
||||
.context("failed at find deployment query")?
|
||||
.with_context(|| {
|
||||
format!("failed to find a deployment with id {id}")
|
||||
})?;
|
||||
|
||||
update_one_by_id(
|
||||
&db_client().await.deployments,
|
||||
id,
|
||||
mungos::update::Update::Set(doc! {
|
||||
format!("permissions.{}", user_id): permission.to_string()
|
||||
}),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
format!(
|
||||
"user {} given {} permissions on deployment {}",
|
||||
user.username, permission, deployment.name
|
||||
)
|
||||
}
|
||||
ResourceTarget::Server(id) => {
|
||||
// find_one_by_id(&db_client().await.servers, id)
|
||||
let server: Server = self.get_resource(id).await?;
|
||||
|
||||
update_one_by_id(
|
||||
&db_client().await.servers,
|
||||
id,
|
||||
mungos::update::Update::Set(doc! {
|
||||
format!("permissions.{}", user_id): permission.to_string()
|
||||
}),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
format!(
|
||||
"user {} given {} permissions on server {}",
|
||||
user.username, permission, server.name
|
||||
)
|
||||
}
|
||||
ResourceTarget::Repo(id) => {
|
||||
let repo: Repo = self.get_resource(id).await?;
|
||||
|
||||
update_one_by_id(
|
||||
&db_client().await.repos,
|
||||
id,
|
||||
mungos::update::Update::Set(doc! {
|
||||
format!("permissions.{}", user_id): permission.to_string()
|
||||
}),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
format!(
|
||||
"user {} given {} permissions on repo {}",
|
||||
user.username, permission, repo.name
|
||||
)
|
||||
}
|
||||
ResourceTarget::Alerter(id) => {
|
||||
let alerter: Alerter = self.get_resource(id).await?;
|
||||
update_one_by_id(
|
||||
&db_client().await.alerters,
|
||||
id,
|
||||
mungos::update::Update::Set(doc! {
|
||||
format!("permissions.{}", user_id): permission.to_string()
|
||||
}),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
format!(
|
||||
"user {} given {} permissions on alerter {}",
|
||||
user.username, permission, alerter.name
|
||||
)
|
||||
}
|
||||
ResourceTarget::Procedure(id) => {
|
||||
let procedure: Procedure = self.get_resource(id).await?;
|
||||
update_one_by_id(
|
||||
&db_client().await.procedures,
|
||||
id,
|
||||
mungos::update::Update::Set(doc! {
|
||||
format!("permissions.{}", user_id): permission.to_string()
|
||||
}),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
format!(
|
||||
"user {} given {} permissions on procedure {}",
|
||||
user.username, permission, procedure.id
|
||||
)
|
||||
}
|
||||
};
|
||||
let (variant, id) = target.extract_variant_id();
|
||||
db_client().await.permissions.update_one(
|
||||
doc! { "user_id": &user.id, "target.type": variant.as_ref(), "target.id": id },
|
||||
doc! {
|
||||
"$set": {
|
||||
"user_id": &user.id,
|
||||
"target.type": variant.as_ref(),
|
||||
"target.id": id,
|
||||
"level": permission.as_ref(),
|
||||
}
|
||||
},
|
||||
None
|
||||
).await?;
|
||||
let log_text = format!(
|
||||
"user {} given {} permissions on {target:?}",
|
||||
user.username, permission,
|
||||
);
|
||||
let mut update = Update {
|
||||
operation: Operation::UpdateUserPermissionsOnTarget,
|
||||
start_ts,
|
||||
|
||||
@@ -3,8 +3,9 @@ use async_trait::async_trait;
|
||||
use monitor_client::{
|
||||
api::write::*,
|
||||
entities::{
|
||||
monitor_timestamp, procedure::Procedure, to_monitor_name,
|
||||
update::Log, user::User, Operation, PermissionLevel,
|
||||
monitor_timestamp, permission::PermissionLevel,
|
||||
procedure::Procedure, to_monitor_name, update::Log, user::User,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
@@ -16,8 +17,9 @@ use resolver_api::Resolve;
|
||||
use crate::{
|
||||
db::db_client,
|
||||
helpers::{
|
||||
add_update, make_update, remove_from_recently_viewed,
|
||||
resource::StateResource, update_update,
|
||||
add_update, create_permission, make_update,
|
||||
remove_from_recently_viewed, resource::StateResource,
|
||||
update_update,
|
||||
},
|
||||
state::{action_states, State},
|
||||
};
|
||||
@@ -35,9 +37,6 @@ impl Resolve<CreateProcedure, User> for State {
|
||||
id: Default::default(),
|
||||
name,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description: Default::default(),
|
||||
tags: Default::default(),
|
||||
info: Default::default(),
|
||||
@@ -56,6 +55,9 @@ impl Resolve<CreateProcedure, User> for State {
|
||||
let procedure: Procedure =
|
||||
self.get_resource(&procedure_id).await?;
|
||||
|
||||
create_permission(&user, &procedure, PermissionLevel::Update)
|
||||
.await;
|
||||
|
||||
let mut update =
|
||||
make_update(&procedure, Operation::CreateProcedure, &user);
|
||||
|
||||
@@ -103,9 +105,6 @@ impl Resolve<CopyProcedure, User> for State {
|
||||
id: Default::default(),
|
||||
name,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description,
|
||||
tags,
|
||||
config,
|
||||
@@ -124,6 +123,9 @@ impl Resolve<CopyProcedure, User> for State {
|
||||
let procedure: Procedure =
|
||||
self.get_resource(&procedure_id).await?;
|
||||
|
||||
create_permission(&user, &procedure, PermissionLevel::Update)
|
||||
.await;
|
||||
|
||||
let mut update =
|
||||
make_update(&procedure, Operation::CreateProcedure, &user);
|
||||
|
||||
|
||||
@@ -4,12 +4,13 @@ use monitor_client::{
|
||||
api::{execute, write::*},
|
||||
entities::{
|
||||
monitor_timestamp,
|
||||
permission::PermissionLevel,
|
||||
repo::Repo,
|
||||
server::Server,
|
||||
to_monitor_name,
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
user::User,
|
||||
Operation, PermissionLevel,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
@@ -22,7 +23,7 @@ use resolver_api::Resolve;
|
||||
use crate::{
|
||||
db::db_client,
|
||||
helpers::{
|
||||
add_update, make_update, periphery_client,
|
||||
add_update, create_permission, make_update, periphery_client,
|
||||
remove_from_recently_viewed, resource::StateResource,
|
||||
update_update,
|
||||
},
|
||||
@@ -40,12 +41,12 @@ impl Resolve<CreateRepo, User> for State {
|
||||
if let Some(server_id) = &config.server_id {
|
||||
if !server_id.is_empty() {
|
||||
let _: Server = self.get_resource_check_permissions(
|
||||
server_id,
|
||||
&user,
|
||||
PermissionLevel::Update,
|
||||
)
|
||||
.await
|
||||
.context("cannot create repo on this server. user must have update permissions on the server.")?;
|
||||
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();
|
||||
@@ -53,9 +54,6 @@ impl Resolve<CreateRepo, User> for State {
|
||||
id: Default::default(),
|
||||
name,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description: Default::default(),
|
||||
tags: Default::default(),
|
||||
config: config.into(),
|
||||
@@ -74,6 +72,8 @@ impl Resolve<CreateRepo, User> for State {
|
||||
|
||||
let repo: Repo = self.get_resource(&repo_id).await?;
|
||||
|
||||
create_permission(&user, &repo, PermissionLevel::Update).await;
|
||||
|
||||
let update = Update {
|
||||
target: ResourceTarget::Repo(repo_id),
|
||||
operation: Operation::CreateRepo,
|
||||
@@ -134,21 +134,18 @@ impl Resolve<CopyRepo, User> for State {
|
||||
.await?;
|
||||
if !config.server_id.is_empty() {
|
||||
let _: Server = self.get_resource_check_permissions(
|
||||
&config.server_id,
|
||||
&user,
|
||||
PermissionLevel::Update,
|
||||
)
|
||||
.await
|
||||
.context("cannot create repo on this server. user must have update permissions on the server.")?;
|
||||
&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,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description,
|
||||
tags,
|
||||
config,
|
||||
@@ -165,6 +162,7 @@ impl Resolve<CopyRepo, User> for State {
|
||||
.context("inserted_id is not ObjectId")?
|
||||
.to_string();
|
||||
let repo: Repo = self.get_resource(&repo_id).await?;
|
||||
create_permission(&user, &repo, PermissionLevel::Update).await;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Repo(repo_id),
|
||||
operation: Operation::CreateRepo,
|
||||
|
||||
@@ -4,10 +4,11 @@ use monitor_client::{
|
||||
api::write::*,
|
||||
entities::{
|
||||
monitor_timestamp,
|
||||
permission::PermissionLevel,
|
||||
server::Server,
|
||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||
user::User,
|
||||
Operation, PermissionLevel,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
@@ -20,8 +21,8 @@ use resolver_api::Resolve;
|
||||
use crate::{
|
||||
db::db_client,
|
||||
helpers::{
|
||||
add_update, cache::server_status_cache, make_update,
|
||||
periphery_client, remove_from_recently_viewed,
|
||||
add_update, cache::server_status_cache, create_permission,
|
||||
make_update, periphery_client, remove_from_recently_viewed,
|
||||
resource::StateResource, update_update,
|
||||
},
|
||||
monitor::update_cache_for_server,
|
||||
@@ -45,9 +46,6 @@ impl Resolve<CreateServer, User> for State {
|
||||
id: Default::default(),
|
||||
name,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description: Default::default(),
|
||||
tags: Default::default(),
|
||||
config: config.into(),
|
||||
@@ -64,6 +62,7 @@ impl Resolve<CreateServer, User> for State {
|
||||
.context("inserted_id is not ObjectId")?
|
||||
.to_string();
|
||||
let server: Server = self.get_resource(&server_id).await?;
|
||||
create_permission(&user, &server, PermissionLevel::Update).await;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Server(server_id),
|
||||
operation: Operation::CreateServer,
|
||||
|
||||
@@ -7,9 +7,9 @@ use monitor_client::{
|
||||
},
|
||||
entities::{
|
||||
alerter::Alerter, build::Build, builder::Builder,
|
||||
deployment::Deployment, procedure::Procedure, repo::Repo,
|
||||
server::Server, tag::CustomTag, update::ResourceTarget,
|
||||
user::User, PermissionLevel,
|
||||
deployment::Deployment, permission::PermissionLevel,
|
||||
procedure::Procedure, repo::Repo, server::Server, tag::CustomTag,
|
||||
update::ResourceTarget, user::User,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
|
||||
@@ -6,6 +6,7 @@ use monitor_client::entities::{
|
||||
build::Build,
|
||||
builder::Builder,
|
||||
deployment::Deployment,
|
||||
permission::Permission,
|
||||
procedure::Procedure,
|
||||
repo::Repo,
|
||||
server::{stats::SystemStatsRecord, Server},
|
||||
@@ -34,6 +35,7 @@ pub async fn db_client() -> &'static DbClient {
|
||||
|
||||
pub struct DbClient {
|
||||
pub users: Collection<User>,
|
||||
pub permissions: Collection<Permission>,
|
||||
pub api_keys: Collection<ApiKey>,
|
||||
pub tags: Collection<CustomTag>,
|
||||
pub updates: Collection<Update>,
|
||||
@@ -88,6 +90,7 @@ impl DbClient {
|
||||
|
||||
let client = DbClient {
|
||||
users: User::collection(&db, true).await?,
|
||||
permissions: Permission::collection(&db, true).await?,
|
||||
api_keys: ApiKey::collection(&db, true).await?,
|
||||
tags: CustomTag::collection(&db, true).await?,
|
||||
updates: Update::collection(&db, true).await?,
|
||||
|
||||
@@ -4,6 +4,7 @@ use anyhow::{anyhow, Context};
|
||||
use monitor_client::entities::{
|
||||
deployment::{Deployment, DockerContainerState},
|
||||
monitor_timestamp,
|
||||
permission::{Permission, PermissionLevel},
|
||||
server::{Server, ServerStatus},
|
||||
tag::CustomTag,
|
||||
update::{ResourceTarget, Update, UpdateListItem},
|
||||
@@ -223,3 +224,31 @@ pub fn periphery_client(
|
||||
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
pub async fn create_permission(
|
||||
user: &User,
|
||||
target: impl Into<ResourceTarget>,
|
||||
level: PermissionLevel,
|
||||
) {
|
||||
// No need to actually create permissions for admins
|
||||
if user.admin {
|
||||
return;
|
||||
}
|
||||
let target: ResourceTarget = target.into();
|
||||
if let Err(e) = db_client()
|
||||
.await
|
||||
.permissions
|
||||
.insert_one(
|
||||
Permission {
|
||||
id: Default::default(),
|
||||
user_id: user.id.clone(),
|
||||
target: target.clone(),
|
||||
level,
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
warn!("failed to create permission for {target:?} | {e:#}");
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,32 +3,26 @@ use std::str::FromStr;
|
||||
use anyhow::{anyhow, Context};
|
||||
use async_trait::async_trait;
|
||||
use futures::future::join_all;
|
||||
use monitor_client::{
|
||||
entities::{
|
||||
alerter::{
|
||||
Alerter, AlerterConfig, AlerterListItem, AlerterListItemInfo,
|
||||
},
|
||||
build::{Build, BuildListItem, BuildListItemInfo},
|
||||
builder::{
|
||||
Builder, BuilderConfig, BuilderListItem, BuilderListItemInfo,
|
||||
},
|
||||
deployment::{
|
||||
Deployment, DeploymentImage, DeploymentListItem,
|
||||
DeploymentListItemInfo,
|
||||
},
|
||||
procedure::{
|
||||
Procedure, ProcedureListItem, ProcedureListItemInfo,
|
||||
},
|
||||
repo::{Repo, RepoInfo, RepoListItem},
|
||||
server::{Server, ServerListItem, ServerListItemInfo},
|
||||
update::ResourceTargetVariant,
|
||||
user::User,
|
||||
PermissionLevel,
|
||||
use monitor_client::entities::{
|
||||
alerter::{
|
||||
Alerter, AlerterConfig, AlerterListItem, AlerterListItemInfo,
|
||||
},
|
||||
permissioned::Permissioned,
|
||||
build::{Build, BuildListItem, BuildListItemInfo},
|
||||
builder::{
|
||||
Builder, BuilderConfig, BuilderListItem, BuilderListItemInfo,
|
||||
},
|
||||
deployment::{
|
||||
Deployment, DeploymentImage, DeploymentListItem,
|
||||
DeploymentListItemInfo,
|
||||
},
|
||||
permission::PermissionLevel,
|
||||
procedure::{Procedure, ProcedureListItem, ProcedureListItemInfo},
|
||||
repo::{Repo, RepoInfo, RepoListItem},
|
||||
server::{Server, ServerListItem, ServerListItemInfo},
|
||||
update::ResourceTargetVariant,
|
||||
user::User,
|
||||
};
|
||||
use mungos::{
|
||||
aggregate::aggregate_collect,
|
||||
by_id::{find_one_by_id, update_one_by_id},
|
||||
find::find_collect,
|
||||
mongodb::{
|
||||
@@ -44,12 +38,13 @@ use super::cache::{deployment_status_cache, server_status_cache};
|
||||
|
||||
#[async_trait]
|
||||
pub trait StateResource<
|
||||
T: Send + Sync + Unpin + Serialize + DeserializeOwned + Permissioned,
|
||||
T: Send + Sync + Unpin + Serialize + DeserializeOwned,
|
||||
>
|
||||
{
|
||||
type ListItem: Serialize + Send;
|
||||
|
||||
fn name() -> &'static str;
|
||||
fn resource_target_variant(&self) -> ResourceTargetVariant;
|
||||
async fn coll(&self) -> &Collection<T>;
|
||||
async fn to_list_item(
|
||||
&self,
|
||||
@@ -72,7 +67,8 @@ pub trait StateResource<
|
||||
permission_level: PermissionLevel,
|
||||
) -> anyhow::Result<T> {
|
||||
let resource = self.get_resource(id).await?;
|
||||
let permissions = resource.get_user_permissions(&user.id);
|
||||
let permissions =
|
||||
self.get_user_permission_on_resource(&user.id, id).await?;
|
||||
if user.admin || permissions >= permission_level {
|
||||
Ok(resource)
|
||||
} else {
|
||||
@@ -88,40 +84,29 @@ pub trait StateResource<
|
||||
user_id: &str,
|
||||
resource_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let resource = self.get_resource(resource_id).await?;
|
||||
Ok(resource.get_user_permissions(user_id))
|
||||
get_user_permission_on_resource(
|
||||
user_id,
|
||||
self.resource_target_variant(),
|
||||
resource_id,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_resource_ids_for_non_admin(
|
||||
&self,
|
||||
user_id: &str,
|
||||
) -> anyhow::Result<Vec<String>> {
|
||||
use mungos::aggregate::AggStage::*;
|
||||
aggregate_collect(
|
||||
self.coll().await,
|
||||
[
|
||||
Match(doc! {
|
||||
format!("permissions.{}", user_id): { "$in": ["update", "execute", "read"] }
|
||||
}),
|
||||
Project(doc! { "_id": 1 }),
|
||||
], None)
|
||||
.await
|
||||
.with_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<_>>>()
|
||||
.with_context(|| format!(
|
||||
"failed to get {} ids for non admin | extract id from document",
|
||||
Self::name()
|
||||
))
|
||||
let permissions = find_collect(
|
||||
&db_client().await.permissions,
|
||||
doc! { "user_id": user_id, "target.type": self.resource_target_variant().as_ref() },
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.context("failed to query permissions on db")?
|
||||
.into_iter()
|
||||
.map(|p| p.target.extract_variant_id().1.to_string())
|
||||
.collect();
|
||||
Ok(permissions)
|
||||
}
|
||||
|
||||
async fn list_resources_for_user(
|
||||
@@ -130,10 +115,13 @@ pub trait StateResource<
|
||||
user: &User,
|
||||
) -> anyhow::Result<Vec<Self::ListItem>> {
|
||||
if !user.admin {
|
||||
filters.insert(
|
||||
format!("permissions.{}", user.id),
|
||||
doc! { "$in": ["read", "execute", "update"] },
|
||||
);
|
||||
let ids = self
|
||||
.get_resource_ids_for_non_admin(&user.id)
|
||||
.await?
|
||||
.into_iter()
|
||||
.flat_map(|id| ObjectId::from_str(&id))
|
||||
.collect::<Vec<_>>();
|
||||
filters.insert("_id", doc! { "$in": ids });
|
||||
}
|
||||
let list = find_collect(self.coll().await, filters, None)
|
||||
.await
|
||||
@@ -221,6 +209,10 @@ impl StateResource<Server> for State {
|
||||
"server"
|
||||
}
|
||||
|
||||
fn resource_target_variant(&self) -> ResourceTargetVariant {
|
||||
ResourceTargetVariant::Server
|
||||
}
|
||||
|
||||
async fn coll(&self) -> &Collection<Server> {
|
||||
&db_client().await.servers
|
||||
}
|
||||
@@ -261,6 +253,10 @@ impl StateResource<Deployment> for State {
|
||||
"deployment"
|
||||
}
|
||||
|
||||
fn resource_target_variant(&self) -> ResourceTargetVariant {
|
||||
ResourceTargetVariant::Deployment
|
||||
}
|
||||
|
||||
async fn coll(&self) -> &Collection<Deployment> {
|
||||
&db_client().await.deployments
|
||||
}
|
||||
@@ -314,6 +310,10 @@ impl StateResource<Build> for State {
|
||||
"build"
|
||||
}
|
||||
|
||||
fn resource_target_variant(&self) -> ResourceTargetVariant {
|
||||
ResourceTargetVariant::Build
|
||||
}
|
||||
|
||||
async fn coll(&self) -> &Collection<Build> {
|
||||
&db_client().await.builds
|
||||
}
|
||||
@@ -346,6 +346,10 @@ impl StateResource<Repo> for State {
|
||||
"repo"
|
||||
}
|
||||
|
||||
fn resource_target_variant(&self) -> ResourceTargetVariant {
|
||||
ResourceTargetVariant::Repo
|
||||
}
|
||||
|
||||
async fn coll(&self) -> &Collection<Repo> {
|
||||
&db_client().await.repos
|
||||
}
|
||||
@@ -377,6 +381,10 @@ impl StateResource<Builder> for State {
|
||||
"builder"
|
||||
}
|
||||
|
||||
fn resource_target_variant(&self) -> ResourceTargetVariant {
|
||||
ResourceTargetVariant::Builder
|
||||
}
|
||||
|
||||
async fn coll(&self) -> &Collection<Builder> {
|
||||
&db_client().await.builders
|
||||
}
|
||||
@@ -418,6 +426,10 @@ impl StateResource<Alerter> for State {
|
||||
"alerter"
|
||||
}
|
||||
|
||||
fn resource_target_variant(&self) -> ResourceTargetVariant {
|
||||
ResourceTargetVariant::Alerter
|
||||
}
|
||||
|
||||
async fn coll(&self) -> &Collection<Alerter> {
|
||||
&db_client().await.alerters
|
||||
}
|
||||
@@ -454,6 +466,10 @@ impl StateResource<Procedure> for State {
|
||||
"procedure"
|
||||
}
|
||||
|
||||
fn resource_target_variant(&self) -> ResourceTargetVariant {
|
||||
ResourceTargetVariant::Procedure
|
||||
}
|
||||
|
||||
async fn coll(&self) -> &Collection<Procedure> {
|
||||
&db_client().await.procedures
|
||||
}
|
||||
@@ -476,3 +492,26 @@ impl StateResource<Procedure> for State {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_user_permission_on_resource(
|
||||
user_id: &str,
|
||||
resource_variant: ResourceTargetVariant,
|
||||
resource_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let permission = db_client()
|
||||
.await
|
||||
.permissions
|
||||
.find_one(
|
||||
doc! {
|
||||
"user_id": user_id,
|
||||
"target.type": resource_variant.as_ref(),
|
||||
"target.id": resource_id
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.context("failed to query permissions table")?
|
||||
.map(|permission| permission.level)
|
||||
.unwrap_or_default();
|
||||
Ok(permission)
|
||||
}
|
||||
|
||||
+10
-73
@@ -11,18 +11,8 @@ use axum::{
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use monitor_client::{
|
||||
entities::{
|
||||
alerter::Alerter,
|
||||
build::Build,
|
||||
builder::Builder,
|
||||
deployment::Deployment,
|
||||
procedure::Procedure,
|
||||
repo::Repo,
|
||||
server::Server,
|
||||
update::{ResourceTarget, ResourceTargetVariant},
|
||||
user::User,
|
||||
PermissionLevel,
|
||||
permission::PermissionLevel, update::ResourceTarget, user::User,
|
||||
},
|
||||
permissioned::Permissioned,
|
||||
ws::WsLoginMessage,
|
||||
};
|
||||
use mungos::by_id::find_one_by_id;
|
||||
@@ -33,8 +23,10 @@ use tokio_util::sync::CancellationToken;
|
||||
use crate::{
|
||||
auth::{auth_api_key_check_enabled, auth_jwt_check_enabled},
|
||||
db::db_client,
|
||||
helpers::{channel::update_channel, resource::StateResource},
|
||||
state::State,
|
||||
helpers::{
|
||||
channel::update_channel,
|
||||
resource::get_user_permission_on_resource,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn router() -> Router {
|
||||
@@ -207,67 +199,12 @@ async fn user_can_see_update(
|
||||
if user.admin {
|
||||
return Ok(());
|
||||
}
|
||||
let (permissions, target) = match update_target {
|
||||
ResourceTarget::Server(server_id) => {
|
||||
let resource: Server = State.get_resource(server_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(&user.id),
|
||||
ResourceTargetVariant::Server,
|
||||
)
|
||||
}
|
||||
ResourceTarget::Deployment(deployment_id) => {
|
||||
let resource: Deployment =
|
||||
State.get_resource(deployment_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(&user.id),
|
||||
ResourceTargetVariant::Deployment,
|
||||
)
|
||||
}
|
||||
ResourceTarget::Build(build_id) => {
|
||||
let resource: Build = State.get_resource(build_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(&user.id),
|
||||
ResourceTargetVariant::Build,
|
||||
)
|
||||
}
|
||||
ResourceTarget::Builder(builder_id) => {
|
||||
let resource: Builder = State.get_resource(builder_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(&user.id),
|
||||
ResourceTargetVariant::Builder,
|
||||
)
|
||||
}
|
||||
ResourceTarget::Repo(repo_id) => {
|
||||
let resource: Repo = State.get_resource(repo_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(&user.id),
|
||||
ResourceTargetVariant::Repo,
|
||||
)
|
||||
}
|
||||
ResourceTarget::Alerter(alerter_id) => {
|
||||
let resource: Alerter = State.get_resource(alerter_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(&user.id),
|
||||
ResourceTargetVariant::Alerter,
|
||||
)
|
||||
}
|
||||
ResourceTarget::Procedure(prodecure_id) => {
|
||||
let resource: Procedure =
|
||||
State.get_resource(prodecure_id).await?;
|
||||
(
|
||||
resource.get_user_permissions(&user.id),
|
||||
ResourceTargetVariant::Procedure,
|
||||
)
|
||||
}
|
||||
ResourceTarget::System(_) => {
|
||||
return Err(anyhow!(
|
||||
"user not admin, can't recieve system updates"
|
||||
))
|
||||
}
|
||||
};
|
||||
if permissions != PermissionLevel::None {
|
||||
let (variant, id) = update_target.extract_variant_id();
|
||||
let permissions =
|
||||
get_user_permission_on_resource(&user.id, variant, id).await?;
|
||||
if permissions > PermissionLevel::None {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow!("user does not have permissions on {target}"))
|
||||
Err(anyhow!("user does not have permissions on {variant} {id}"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,11 +193,11 @@ impl TryFrom<Build> for monitor_client::entities::build::Build {
|
||||
id: value.id,
|
||||
name: value.name,
|
||||
description: value.description,
|
||||
permissions: value
|
||||
.permissions
|
||||
.into_iter()
|
||||
.map(|(id, p)| (id, p.into()))
|
||||
.collect(),
|
||||
// permissions: value
|
||||
// .permissions
|
||||
// .into_iter()
|
||||
// .map(|(id, p)| (id, p.into()))
|
||||
// .collect(),
|
||||
updated_at: unix_from_monitor_ts(&value.updated_at)?,
|
||||
tags: Vec::new(),
|
||||
info: BuildInfo {
|
||||
|
||||
@@ -327,11 +327,11 @@ impl TryFrom<Deployment>
|
||||
id: value.id,
|
||||
name: value.name,
|
||||
description: value.description,
|
||||
permissions: value
|
||||
.permissions
|
||||
.into_iter()
|
||||
.map(|(id, p)| (id, p.into()))
|
||||
.collect(),
|
||||
// permissions: value
|
||||
// .permissions
|
||||
// .into_iter()
|
||||
// .map(|(id, p)| (id, p.into()))
|
||||
// .collect(),
|
||||
updated_at: unix_from_monitor_ts(&value.updated_at)?,
|
||||
tags: Vec::new(),
|
||||
info: (),
|
||||
|
||||
@@ -238,10 +238,10 @@ impl Default for &PermissionLevel {
|
||||
}
|
||||
|
||||
impl From<PermissionLevel>
|
||||
for monitor_client::entities::PermissionLevel
|
||||
for monitor_client::entities::permission::PermissionLevel
|
||||
{
|
||||
fn from(value: PermissionLevel) -> Self {
|
||||
use monitor_client::entities::PermissionLevel::*;
|
||||
use monitor_client::entities::permission::PermissionLevel::*;
|
||||
match value {
|
||||
PermissionLevel::None => None,
|
||||
PermissionLevel::Read => Read,
|
||||
|
||||
@@ -293,11 +293,11 @@ impl TryFrom<Server> for monitor_client::entities::server::Server {
|
||||
id: value.id,
|
||||
name: value.name,
|
||||
description: value.description,
|
||||
permissions: value
|
||||
.permissions
|
||||
.into_iter()
|
||||
.map(|(id, p)| (id, p.into()))
|
||||
.collect(),
|
||||
// permissions: value
|
||||
// .permissions
|
||||
// .into_iter()
|
||||
// .map(|(id, p)| (id, p.into()))
|
||||
// .collect(),
|
||||
updated_at: unix_from_monitor_ts(&value.updated_at)?,
|
||||
tags: Vec::new(),
|
||||
info: (),
|
||||
|
||||
@@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::entities::{
|
||||
permission::PermissionLevel,
|
||||
update::{ResourceTarget, Update},
|
||||
PermissionLevel,
|
||||
};
|
||||
|
||||
use super::MonitorWriteRequest;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::{anyhow, Context};
|
||||
use async_timing_util::unix_timestamp_ms;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -12,6 +10,7 @@ pub mod api_key;
|
||||
pub mod build;
|
||||
pub mod builder;
|
||||
pub mod deployment;
|
||||
pub mod permission;
|
||||
pub mod procedure;
|
||||
pub mod repo;
|
||||
pub mod resource;
|
||||
@@ -28,8 +27,6 @@ pub type U64 = u64;
|
||||
pub type MongoDocument = mungos::mongodb::bson::Document;
|
||||
#[typeshare(serialized_as = "MongoIdObj")]
|
||||
pub type MongoId = String;
|
||||
#[typeshare]
|
||||
pub type PermissionsMap = HashMap<String, PermissionLevel>;
|
||||
|
||||
pub fn all_logs_success(logs: &[update::Log]) -> bool {
|
||||
for log in logs {
|
||||
@@ -296,38 +293,6 @@ pub enum Timelength {
|
||||
ThirtyDays,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Debug,
|
||||
Display,
|
||||
EnumString,
|
||||
Hash,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Default,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum PermissionLevel {
|
||||
#[default]
|
||||
None,
|
||||
Read,
|
||||
Execute,
|
||||
Update,
|
||||
}
|
||||
|
||||
impl Default for &PermissionLevel {
|
||||
fn default() -> Self {
|
||||
&PermissionLevel::None
|
||||
}
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Serialize,
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
use mongo_indexed::derive::MongoIndexed;
|
||||
use mungos::mongodb::bson::{
|
||||
doc, serde_helpers::hex_string_as_object_id, Document,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{AsRefStr, Display, EnumString};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use super::{update::ResourceTarget, MongoId};
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, MongoIndexed)]
|
||||
// To query for all permissions on a target
|
||||
#[doc_index(doc! { "target.type": 1, "target.id": 1 })]
|
||||
// Only one permission allowed per user / target
|
||||
#[unique_doc_index(doc! { "user_id": 1, "target.type": 1, "target.id": 1 })]
|
||||
pub struct Permission {
|
||||
#[serde(
|
||||
default,
|
||||
rename = "_id",
|
||||
skip_serializing_if = "String::is_empty",
|
||||
with = "hex_string_as_object_id"
|
||||
)]
|
||||
pub id: MongoId,
|
||||
#[index]
|
||||
pub user_id: String,
|
||||
pub target: ResourceTarget,
|
||||
#[serde(default)]
|
||||
pub level: PermissionLevel,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Debug,
|
||||
Display,
|
||||
EnumString,
|
||||
AsRefStr,
|
||||
Hash,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Default,
|
||||
)]
|
||||
pub enum PermissionLevel {
|
||||
#[default]
|
||||
None,
|
||||
Read,
|
||||
Execute,
|
||||
Update,
|
||||
}
|
||||
|
||||
impl Default for &PermissionLevel {
|
||||
fn default() -> Self {
|
||||
&PermissionLevel::None
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ use typeshare::typeshare;
|
||||
|
||||
use crate::entities::{MongoId, I64};
|
||||
|
||||
use super::{update::ResourceTargetVariant, PermissionsMap};
|
||||
use super::update::ResourceTargetVariant;
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder)]
|
||||
@@ -28,10 +28,6 @@ pub struct Resource<Config, Info: Default = ()> {
|
||||
#[builder(default)]
|
||||
pub description: String,
|
||||
|
||||
#[serde(default)]
|
||||
#[builder(setter(skip))]
|
||||
pub permissions: PermissionsMap,
|
||||
|
||||
#[serde(default)]
|
||||
#[builder(setter(skip))]
|
||||
pub updated_at: I64,
|
||||
|
||||
@@ -5,7 +5,7 @@ use mungos::mongodb::bson::{
|
||||
doc, serde_helpers::hex_string_as_object_id, Document,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{Display, EnumString};
|
||||
use strum::{AsRefStr, Display, EnumString};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::entities::{
|
||||
@@ -151,6 +151,7 @@ impl Log {
|
||||
Copy,
|
||||
Display,
|
||||
EnumString,
|
||||
AsRefStr,
|
||||
PartialEq,
|
||||
Eq
|
||||
)]
|
||||
@@ -166,6 +167,25 @@ pub enum ResourceTarget {
|
||||
Procedure(String),
|
||||
}
|
||||
|
||||
impl ResourceTarget {
|
||||
pub fn extract_variant_id(
|
||||
&self,
|
||||
) -> (ResourceTargetVariant, &String) {
|
||||
let variant: ResourceTargetVariant = self.into();
|
||||
let id = match &self {
|
||||
ResourceTarget::System(id) => id,
|
||||
ResourceTarget::Build(id) => id,
|
||||
ResourceTarget::Builder(id) => id,
|
||||
ResourceTarget::Deployment(id) => id,
|
||||
ResourceTarget::Server(id) => id,
|
||||
ResourceTarget::Repo(id) => id,
|
||||
ResourceTarget::Alerter(id) => id,
|
||||
ResourceTarget::Procedure(id) => id,
|
||||
};
|
||||
(variant, id)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ResourceTarget {
|
||||
fn default() -> Self {
|
||||
Self::System("system".to_string())
|
||||
|
||||
@@ -5,7 +5,6 @@ use serde::Deserialize;
|
||||
pub mod api;
|
||||
pub mod busy;
|
||||
pub mod entities;
|
||||
pub mod permissioned;
|
||||
pub mod ws;
|
||||
|
||||
mod request;
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
use crate::entities::{
|
||||
resource::Resource, PermissionLevel, PermissionsMap,
|
||||
};
|
||||
|
||||
pub trait Permissioned {
|
||||
fn permissions_map(&self) -> &PermissionsMap;
|
||||
|
||||
fn get_user_permissions(&self, user_id: &str) -> PermissionLevel {
|
||||
*self.permissions_map().get(user_id).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, I: Default> Permissioned for Resource<C, I> {
|
||||
fn permissions_map(&self) -> &PermissionsMap {
|
||||
&self.permissions
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user