mirror of
https://github.com/moghtech/komodo.git
synced 2026-03-11 17:44:19 -05:00
implement user group api
This commit is contained in:
@@ -28,6 +28,7 @@ mod server;
|
||||
mod tag;
|
||||
mod update;
|
||||
mod user;
|
||||
mod user_group;
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Resolver)]
|
||||
@@ -44,6 +45,10 @@ enum ReadRequest {
|
||||
ListApiKeys(ListApiKeys),
|
||||
ListUserPermissions(ListUserPermissions),
|
||||
|
||||
// ==== USER GROUP ====
|
||||
GetUserGroup(GetUserGroup),
|
||||
ListUserGroups(ListUserGroups),
|
||||
|
||||
// ==== SEARCH ====
|
||||
FindResources(FindResources),
|
||||
|
||||
|
||||
61
bin/core/src/api/read/user_group.rs
Normal file
61
bin/core/src/api/read/user_group.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Context;
|
||||
use async_trait::async_trait;
|
||||
use monitor_client::{
|
||||
api::read::{
|
||||
GetUserGroup, GetUserGroupResponse, ListUserGroups,
|
||||
ListUserGroupsResponse,
|
||||
},
|
||||
entities::user::User,
|
||||
};
|
||||
use mungos::{
|
||||
find::find_collect,
|
||||
mongodb::bson::{doc, oid::ObjectId, Document},
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{db::db_client, state::State};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<GetUserGroup, User> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
GetUserGroup { user_group }: GetUserGroup,
|
||||
user: User,
|
||||
) -> anyhow::Result<GetUserGroupResponse> {
|
||||
let mut filter = match ObjectId::from_str(&user_group) {
|
||||
Ok(id) => doc! { "_id": id },
|
||||
Err(_) => doc! { "name": &user_group },
|
||||
};
|
||||
// Don't allow non admin users to get UserGroups they aren't a part of.
|
||||
if !user.admin {
|
||||
// Filter for only UserGroups which contain the users id
|
||||
filter.insert("users", &user.id);
|
||||
}
|
||||
db_client()
|
||||
.await
|
||||
.user_groups
|
||||
.find_one(filter, None)
|
||||
.await
|
||||
.context("failed to query db for user groups")?
|
||||
.context("no UserGroup found with given name or id")
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<ListUserGroups, User> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
ListUserGroups {}: ListUserGroups,
|
||||
user: User,
|
||||
) -> anyhow::Result<ListUserGroupsResponse> {
|
||||
let mut filter = Document::new();
|
||||
if !user.admin {
|
||||
filter.insert("users", &user.id);
|
||||
}
|
||||
find_collect(&db_client().await.user_groups, filter, None)
|
||||
.await
|
||||
.context("failed to query db for UserGroups")
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ mod repo;
|
||||
mod server;
|
||||
mod tag;
|
||||
mod user;
|
||||
mod user_group;
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Resolver)]
|
||||
@@ -44,9 +45,16 @@ enum WriteRequest {
|
||||
CreateServiceUser(CreateServiceUser),
|
||||
UpdateServiceUserDescription(UpdateServiceUserDescription),
|
||||
|
||||
// ==== USER GROUP ====
|
||||
CreateUserGroup(CreateUserGroup),
|
||||
RenameUserGroup(RenameUserGroup),
|
||||
DeleteUserGroup(DeleteUserGroup),
|
||||
AddUserToUserGroup(AddUserToUserGroup),
|
||||
RemoveUserFromUserGroup(RemoveUserFromUserGroup),
|
||||
|
||||
// ==== PERMISSIONS ====
|
||||
UpdateUserPerimissions(UpdateUserPermissions),
|
||||
UpdateUserPermissionsOnTarget(UpdateUserPermissionsOnTarget),
|
||||
UpdateUserBasePermissions(UpdateUserBasePermissions),
|
||||
UpdatePermissionOnTarget(UpdatePermissionOnTarget),
|
||||
|
||||
// ==== DESCRIPTION ====
|
||||
UpdateDescription(UpdateDescription),
|
||||
|
||||
@@ -2,13 +2,10 @@ use anyhow::{anyhow, Context};
|
||||
use async_trait::async_trait;
|
||||
use monitor_client::{
|
||||
api::write::{
|
||||
UpdateUserPermissions, UpdateUserPermissionsOnTarget,
|
||||
},
|
||||
entities::{
|
||||
update::{ResourceTarget, Update},
|
||||
user::User,
|
||||
Operation,
|
||||
UpdatePermissionOnTarget, UpdatePermissionOnTargetResponse,
|
||||
UpdateUserBasePermissions, UpdateUserBasePermissionsResponse,
|
||||
},
|
||||
entities::{permission::UserTarget, user::User},
|
||||
};
|
||||
use mungos::{
|
||||
by_id::{find_one_by_id, update_one_by_id},
|
||||
@@ -19,28 +16,21 @@ use mungos::{
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{
|
||||
db::db_client,
|
||||
helpers::{
|
||||
query::get_user,
|
||||
update::{add_update, make_update},
|
||||
},
|
||||
state::State,
|
||||
};
|
||||
use crate::{db::db_client, helpers::query::get_user, state::State};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<UpdateUserPermissions, User> for State {
|
||||
#[instrument(name = "UpdateUserPermissions", skip(self, admin))]
|
||||
impl Resolve<UpdateUserBasePermissions, User> for State {
|
||||
#[instrument(name = "UpdateUserBasePermissions", skip(self, admin))]
|
||||
async fn resolve(
|
||||
&self,
|
||||
UpdateUserPermissions {
|
||||
UpdateUserBasePermissions {
|
||||
user_id,
|
||||
enabled,
|
||||
create_servers,
|
||||
create_builds,
|
||||
}: UpdateUserPermissions,
|
||||
}: UpdateUserBasePermissions,
|
||||
admin: User,
|
||||
) -> anyhow::Result<Update> {
|
||||
) -> anyhow::Result<UpdateUserBasePermissionsResponse> {
|
||||
if !admin.admin {
|
||||
return Err(anyhow!("this method is admin only"));
|
||||
}
|
||||
@@ -72,74 +62,69 @@ impl Resolve<UpdateUserPermissions, User> for State {
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut update = make_update(
|
||||
ResourceTarget::System("system".to_string()),
|
||||
Operation::UpdateUserPermissions,
|
||||
&admin,
|
||||
);
|
||||
update.push_simple_log("modify user enabled", format!(
|
||||
"update permissions for {} ({})\nenabled: {enabled:?}\ncreate servers: {create_servers:?}\ncreate builds: {create_builds:?}",
|
||||
user.username,
|
||||
user.id,
|
||||
));
|
||||
update.finalize();
|
||||
update.id = add_update(update.clone()).await?;
|
||||
Ok(update)
|
||||
Ok(UpdateUserBasePermissionsResponse {})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<UpdateUserPermissionsOnTarget, User> for State {
|
||||
#[instrument(
|
||||
name = "UpdateUserPermissionsOnTarget",
|
||||
skip(self, admin)
|
||||
)]
|
||||
impl Resolve<UpdatePermissionOnTarget, User> for State {
|
||||
#[instrument(name = "UpdatePermissionOnTarget", skip(self, admin))]
|
||||
async fn resolve(
|
||||
&self,
|
||||
UpdateUserPermissionsOnTarget {
|
||||
user_id,
|
||||
UpdatePermissionOnTarget {
|
||||
user_target,
|
||||
resource_target,
|
||||
permission,
|
||||
target,
|
||||
}: UpdateUserPermissionsOnTarget,
|
||||
}: UpdatePermissionOnTarget,
|
||||
admin: User,
|
||||
) -> anyhow::Result<Update> {
|
||||
) -> anyhow::Result<UpdatePermissionOnTargetResponse> {
|
||||
if !admin.admin {
|
||||
return Err(anyhow!("this method is admin only"));
|
||||
}
|
||||
let user = get_user(&user_id).await?;
|
||||
if user.admin {
|
||||
return Err(anyhow!(
|
||||
"cannot use this method to update other admins permissions"
|
||||
));
|
||||
|
||||
// Some extra checks if user target is an actual User
|
||||
if let UserTarget::User(user_id) = &user_target {
|
||||
let user = get_user(user_id).await?;
|
||||
if user.admin {
|
||||
return Err(anyhow!(
|
||||
"cannot use this method to update other admins permissions"
|
||||
));
|
||||
}
|
||||
if !user.enabled {
|
||||
return Err(anyhow!("user not enabled"));
|
||||
}
|
||||
}
|
||||
if !user.enabled {
|
||||
return Err(anyhow!("user not enabled"));
|
||||
}
|
||||
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(),
|
||||
}
|
||||
},
|
||||
UpdateOptions::builder().upsert(true).build()
|
||||
).await?;
|
||||
let log_text = format!(
|
||||
"user {} given {} permissions on {target:?}",
|
||||
user.username, permission,
|
||||
);
|
||||
let mut update = make_update(
|
||||
target,
|
||||
Operation::UpdateUserPermissionsOnTarget,
|
||||
&admin,
|
||||
);
|
||||
update.push_simple_log("modify permissions", log_text);
|
||||
update.finalize();
|
||||
update.id = add_update(update.clone()).await?;
|
||||
Ok(update)
|
||||
|
||||
let (user_target_variant, user_target_id) =
|
||||
user_target.extract_variant_id();
|
||||
let (resource_variant, resource_id) =
|
||||
resource_target.extract_variant_id();
|
||||
let (user_target_variant, resource_variant) =
|
||||
(user_target_variant.as_ref(), resource_variant.as_ref());
|
||||
|
||||
db_client()
|
||||
.await
|
||||
.permissions
|
||||
.update_one(
|
||||
doc! {
|
||||
"user_target.type": user_target_variant,
|
||||
"user_target.id": &user_target_id,
|
||||
"resource_target.type": resource_variant,
|
||||
"resource_target.id": &resource_id
|
||||
},
|
||||
doc! {
|
||||
"$set": {
|
||||
"user_target.type": user_target_variant,
|
||||
"user_target.id": user_target_id,
|
||||
"resource_target.type": resource_variant,
|
||||
"resource_target.id": resource_id,
|
||||
"level": permission.as_ref(),
|
||||
}
|
||||
},
|
||||
UpdateOptions::builder().upsert(true).build(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(UpdatePermissionOnTargetResponse {})
|
||||
}
|
||||
}
|
||||
|
||||
174
bin/core/src/api/write/user_group.rs
Normal file
174
bin/core/src/api/write/user_group.rs
Normal file
@@ -0,0 +1,174 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{anyhow, Context};
|
||||
use axum::async_trait;
|
||||
use monitor_client::{
|
||||
api::write::{
|
||||
AddUserToUserGroup, CreateUserGroup, DeleteUserGroup,
|
||||
RemoveUserFromUserGroup, RenameUserGroup,
|
||||
},
|
||||
entities::{monitor_timestamp, user::User, user_group::UserGroup},
|
||||
};
|
||||
use mungos::{
|
||||
by_id::{delete_one_by_id, find_one_by_id, update_one_by_id},
|
||||
mongodb::bson::{doc, oid::ObjectId},
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{db::db_client, state::State};
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<CreateUserGroup, User> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
CreateUserGroup { name }: CreateUserGroup,
|
||||
admin: User,
|
||||
) -> anyhow::Result<UserGroup> {
|
||||
if !admin.admin {
|
||||
return Err(anyhow!("This call is admin-only"));
|
||||
}
|
||||
let user_group = UserGroup {
|
||||
id: Default::default(),
|
||||
users: Default::default(),
|
||||
updated_at: monitor_timestamp(),
|
||||
name,
|
||||
};
|
||||
let db = db_client().await;
|
||||
let id = db
|
||||
.user_groups
|
||||
.insert_one(user_group, None)
|
||||
.await
|
||||
.context("failed to create UserGroup on db")?
|
||||
.inserted_id
|
||||
.as_object_id()
|
||||
.context("inserted id is not ObjectId")?
|
||||
.to_string();
|
||||
find_one_by_id(&db.user_groups, &id)
|
||||
.await
|
||||
.context("failed to query db for user groups")?
|
||||
.context("user group at id not found")
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<RenameUserGroup, User> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
RenameUserGroup { id, name }: RenameUserGroup,
|
||||
admin: User,
|
||||
) -> anyhow::Result<UserGroup> {
|
||||
if !admin.admin {
|
||||
return Err(anyhow!("This call is admin-only"));
|
||||
}
|
||||
let db = db_client().await;
|
||||
update_one_by_id(
|
||||
&db.user_groups,
|
||||
&id,
|
||||
doc! { "$set": { "name": name } },
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.context("failed to rename UserGroup on db")?;
|
||||
find_one_by_id(&db.user_groups, &id)
|
||||
.await
|
||||
.context("failed to query db for UserGroups")?
|
||||
.context("no user group with given id")
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<DeleteUserGroup, User> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
DeleteUserGroup { id }: DeleteUserGroup,
|
||||
admin: User,
|
||||
) -> anyhow::Result<UserGroup> {
|
||||
if !admin.admin {
|
||||
return Err(anyhow!("This call is admin-only"));
|
||||
}
|
||||
let db = db_client().await;
|
||||
let ug = find_one_by_id(&db.user_groups, &id)
|
||||
.await
|
||||
.context("failed to query db for UserGroups")?
|
||||
.context("no UserGroup found with given id")?;
|
||||
delete_one_by_id(&db.user_groups, &id, None)
|
||||
.await
|
||||
.context("failed to delete UserGroup from db")?;
|
||||
db.permissions
|
||||
.delete_many(doc! {
|
||||
"user_target.type": "UserGroup",
|
||||
"user_target.id": id,
|
||||
}, None)
|
||||
.await
|
||||
.context("failed to clean up UserGroups permissions. User Group has been deleted")?;
|
||||
Ok(ug)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<AddUserToUserGroup, User> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
AddUserToUserGroup {
|
||||
user_group,
|
||||
user_id,
|
||||
}: AddUserToUserGroup,
|
||||
admin: User,
|
||||
) -> anyhow::Result<UserGroup> {
|
||||
if !admin.admin {
|
||||
return Err(anyhow!("This call is admin-only"));
|
||||
}
|
||||
let filter = match ObjectId::from_str(&user_group) {
|
||||
Ok(id) => doc! { "_id": id },
|
||||
Err(_) => doc! { "name": &user_group },
|
||||
};
|
||||
let db = db_client().await;
|
||||
db.user_groups
|
||||
.update_one(
|
||||
filter.clone(),
|
||||
doc! { "$push": { "users": user_id } },
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.context("failed to add user to group on db")?;
|
||||
db.user_groups
|
||||
.find_one(filter, None)
|
||||
.await
|
||||
.context("failed to query db for UserGroups")?
|
||||
.context("no user group with given id")
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<RemoveUserFromUserGroup, User> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
RemoveUserFromUserGroup {
|
||||
user_group,
|
||||
user_id,
|
||||
}: RemoveUserFromUserGroup,
|
||||
admin: User,
|
||||
) -> anyhow::Result<UserGroup> {
|
||||
if !admin.admin {
|
||||
return Err(anyhow!("This call is admin-only"));
|
||||
}
|
||||
let filter = match ObjectId::from_str(&user_group) {
|
||||
Ok(id) => doc! { "_id": id },
|
||||
Err(_) => doc! { "name": &user_group },
|
||||
};
|
||||
let db = db_client().await;
|
||||
db.user_groups
|
||||
.update_one(
|
||||
filter.clone(),
|
||||
doc! { "$pull": { "users": user_id } },
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.context("failed to add user to group on db")?;
|
||||
db.user_groups
|
||||
.find_one(filter, None)
|
||||
.await
|
||||
.context("failed to query db for UserGroups")?
|
||||
.context("no user group with given id")
|
||||
}
|
||||
}
|
||||
@@ -193,16 +193,10 @@ impl From<Operation> for monitor_client::entities::Operation {
|
||||
Operation::CreateGroup => None,
|
||||
Operation::UpdateGroup => None,
|
||||
Operation::DeleteGroup => None,
|
||||
Operation::ModifyUserEnabled => UpdateUserPermissions,
|
||||
Operation::ModifyUserCreateServerPermissions => {
|
||||
UpdateUserPermissions
|
||||
}
|
||||
Operation::ModifyUserCreateBuildPermissions => {
|
||||
UpdateUserPermissions
|
||||
}
|
||||
Operation::ModifyUserPermissions => {
|
||||
UpdateUserPermissionsOnTarget
|
||||
}
|
||||
Operation::ModifyUserEnabled => None,
|
||||
Operation::ModifyUserCreateServerPermissions => None,
|
||||
Operation::ModifyUserCreateBuildPermissions => None,
|
||||
Operation::ModifyUserPermissions => None,
|
||||
Operation::AutoBuild => RunBuild,
|
||||
Operation::AutoPull => PullRepo,
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ mod search;
|
||||
mod server;
|
||||
mod tag;
|
||||
mod update;
|
||||
mod user_group;
|
||||
|
||||
pub use alert::*;
|
||||
pub use alerter::*;
|
||||
@@ -28,6 +29,7 @@ pub use search::*;
|
||||
pub use server::*;
|
||||
pub use tag::*;
|
||||
pub use update::*;
|
||||
pub use user_group::*;
|
||||
|
||||
use crate::entities::{api_key::ApiKey, user::User, Timelength};
|
||||
|
||||
|
||||
31
client/core/rs/src/api/read/user_group.rs
Normal file
31
client/core/rs/src/api/read/user_group.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use derive_empty_traits::EmptyTraits;
|
||||
use resolver_api::derive::Request;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::entities::user_group::UserGroup;
|
||||
|
||||
use super::MonitorReadRequest;
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Request, EmptyTraits)]
|
||||
#[empty_traits(MonitorReadRequest)]
|
||||
#[response(GetUserGroupResponse)]
|
||||
pub struct GetUserGroup {
|
||||
/// Name or Id
|
||||
pub user_group: String,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
pub type GetUserGroupResponse = UserGroup;
|
||||
|
||||
//
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Request, EmptyTraits)]
|
||||
#[empty_traits(MonitorReadRequest)]
|
||||
#[response(ListUserGroupsResponse)]
|
||||
pub struct ListUserGroups {}
|
||||
|
||||
#[typeshare]
|
||||
pub type ListUserGroupsResponse = Vec<UserGroup>;
|
||||
@@ -11,6 +11,7 @@ mod repo;
|
||||
mod server;
|
||||
mod tags;
|
||||
mod user;
|
||||
mod user_group;
|
||||
|
||||
pub use alerter::*;
|
||||
pub use api_key::*;
|
||||
@@ -25,5 +26,6 @@ pub use repo::*;
|
||||
pub use server::*;
|
||||
pub use tags::*;
|
||||
pub use user::*;
|
||||
pub use user_group::*;
|
||||
|
||||
pub trait MonitorWriteRequest: resolver_api::HasResponse {}
|
||||
|
||||
@@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::entities::{
|
||||
permission::PermissionLevel,
|
||||
update::{ResourceTarget, Update},
|
||||
permission::{PermissionLevel, UserTarget},
|
||||
update::ResourceTarget,
|
||||
};
|
||||
|
||||
use super::MonitorWriteRequest;
|
||||
@@ -15,22 +15,32 @@ use super::MonitorWriteRequest;
|
||||
Serialize, Deserialize, Debug, Clone, Request, EmptyTraits,
|
||||
)]
|
||||
#[empty_traits(MonitorWriteRequest)]
|
||||
#[response(Update)]
|
||||
pub struct UpdateUserPermissionsOnTarget {
|
||||
pub user_id: String,
|
||||
#[response(UpdatePermissionOnTargetResponse)]
|
||||
pub struct UpdatePermissionOnTarget {
|
||||
pub user_target: UserTarget,
|
||||
pub resource_target: ResourceTarget,
|
||||
pub permission: PermissionLevel,
|
||||
pub target: ResourceTarget,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct UpdatePermissionOnTargetResponse {}
|
||||
|
||||
//
|
||||
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Serialize, Deserialize, Debug, Clone, Request, EmptyTraits,
|
||||
)]
|
||||
#[empty_traits(MonitorWriteRequest)]
|
||||
#[response(Update)]
|
||||
pub struct UpdateUserPermissions {
|
||||
#[response(UpdateUserBasePermissionsResponse)]
|
||||
pub struct UpdateUserBasePermissions {
|
||||
pub user_id: String,
|
||||
pub enabled: Option<bool>,
|
||||
pub create_servers: Option<bool>,
|
||||
pub create_builds: Option<bool>,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct UpdateUserBasePermissionsResponse {}
|
||||
|
||||
74
client/core/rs/src/api/write/user_group.rs
Normal file
74
client/core/rs/src/api/write/user_group.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
use derive_empty_traits::EmptyTraits;
|
||||
use resolver_api::derive::Request;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::entities::user_group::UserGroup;
|
||||
|
||||
use super::MonitorWriteRequest;
|
||||
|
||||
/// Admin only
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Serialize, Deserialize, Debug, Clone, Request, EmptyTraits,
|
||||
)]
|
||||
#[empty_traits(MonitorWriteRequest)]
|
||||
#[response(UserGroup)]
|
||||
pub struct CreateUserGroup {
|
||||
/// The name to assign to the new UserGroup
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// Admin only
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Serialize, Deserialize, Debug, Clone, Request, EmptyTraits,
|
||||
)]
|
||||
#[empty_traits(MonitorWriteRequest)]
|
||||
#[response(UserGroup)]
|
||||
pub struct RenameUserGroup {
|
||||
/// The id of the UserGroup
|
||||
pub id: String,
|
||||
/// The new name for the UserGroup
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// Admin only
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Serialize, Deserialize, Debug, Clone, Request, EmptyTraits,
|
||||
)]
|
||||
#[empty_traits(MonitorWriteRequest)]
|
||||
#[response(UserGroup)]
|
||||
pub struct DeleteUserGroup {
|
||||
/// The id of the UserGroup
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
/// Admin only
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Serialize, Deserialize, Debug, Clone, Request, EmptyTraits,
|
||||
)]
|
||||
#[empty_traits(MonitorWriteRequest)]
|
||||
#[response(UserGroup)]
|
||||
pub struct AddUserToUserGroup {
|
||||
/// The name or id of UserGroup that user should be added to.
|
||||
pub user_group: String,
|
||||
/// The id of the user to add
|
||||
pub user_id: String,
|
||||
}
|
||||
|
||||
/// Admin only
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Serialize, Deserialize, Debug, Clone, Request, EmptyTraits,
|
||||
)]
|
||||
#[empty_traits(MonitorWriteRequest)]
|
||||
#[response(UserGroup)]
|
||||
pub struct RemoveUserFromUserGroup {
|
||||
/// The name or id of UserGroup that user should be removed from.
|
||||
pub user_group: String,
|
||||
/// The id of the user to remove
|
||||
pub user_id: String,
|
||||
}
|
||||
@@ -375,10 +375,6 @@ pub enum Operation {
|
||||
UpdateProcedure,
|
||||
DeleteProcedure,
|
||||
RunProcedure,
|
||||
|
||||
// user
|
||||
UpdateUserPermissions,
|
||||
UpdateUserPermissionsOnTarget,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use derive_variants::EnumVariants;
|
||||
use mongo_indexed::derive::MongoIndexed;
|
||||
use mungos::mongodb::bson::{
|
||||
doc, serde_helpers::hex_string_as_object_id, Document,
|
||||
@@ -11,10 +12,17 @@ use super::{update::ResourceTarget, MongoId};
|
||||
/// Representation of a User or UserGroups permission on a resource.
|
||||
#[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 })]
|
||||
// To query for all permissions on user target
|
||||
#[doc_index(doc! { "user_target.type": 1, "user_target.id": 1 })]
|
||||
// To query for all permissions on a resource target
|
||||
#[doc_index(doc! { "resource_target.type": 1, "resource_target.id": 1 })]
|
||||
// Only one permission allowed per user / resource target
|
||||
#[unique_doc_index(doc! {
|
||||
"user_target.type": 1,
|
||||
"user_target.id": 1,
|
||||
"target.type": 1,
|
||||
"target.id": 1
|
||||
})]
|
||||
pub struct Permission {
|
||||
/// The id of the permission document
|
||||
#[serde(
|
||||
@@ -24,8 +32,7 @@ pub struct Permission {
|
||||
with = "hex_string_as_object_id"
|
||||
)]
|
||||
pub id: MongoId,
|
||||
/// Attached user
|
||||
#[index]
|
||||
/// The target User / UserGroup
|
||||
pub user_target: UserTarget,
|
||||
/// The target resource
|
||||
pub resource_target: ResourceTarget,
|
||||
@@ -35,7 +42,15 @@ pub struct Permission {
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, EnumVariants)]
|
||||
#[variant_derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
AsRefStr
|
||||
)]
|
||||
#[serde(tag = "type", content = "id")]
|
||||
pub enum UserTarget {
|
||||
/// User Id
|
||||
@@ -44,6 +59,15 @@ pub enum UserTarget {
|
||||
UserGroup(String),
|
||||
}
|
||||
|
||||
impl UserTarget {
|
||||
pub fn extract_variant_id(self) -> (UserTargetVariant, String) {
|
||||
match self {
|
||||
UserTarget::User(id) => (UserTargetVariant::User, id),
|
||||
UserTarget::UserGroup(id) => (UserTargetVariant::UserGroup, id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The levels of permission that a User or UserGroup can have on a resource.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
|
||||
Reference in New Issue
Block a user