mirror of
https://github.com/stoatchat/stoatchat.git
synced 2026-07-14 21:47:02 +00:00
feat: initial bulk role reorder route
This commit is contained in:
@@ -165,6 +165,9 @@ pub enum EventV1 {
|
||||
/// Server role deleted
|
||||
ServerRoleDelete { id: String, role_id: String },
|
||||
|
||||
/// Server roles ranks updated
|
||||
ServerRoleRanksUpdate { ranks: Vec<String> },
|
||||
|
||||
/// Update existing user
|
||||
UserUpdate {
|
||||
id: String,
|
||||
|
||||
@@ -267,6 +267,7 @@ auto_derived!(
|
||||
pub hoist: Option<bool>,
|
||||
/// Ranking position
|
||||
///
|
||||
/// **Deprecated** - use the edit server role positions route.
|
||||
/// Smaller values take priority.
|
||||
pub rank: Option<i64>,
|
||||
/// Fields to remove from role object
|
||||
@@ -286,4 +287,9 @@ auto_derived!(
|
||||
/// Whether to not send a leave message
|
||||
pub leave_silently: Option<bool>,
|
||||
}
|
||||
|
||||
/// New role positions
|
||||
pub struct DataEditRoleRanks {
|
||||
pub ranks: Vec<String>,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -18,6 +18,7 @@ mod roles_create;
|
||||
mod roles_delete;
|
||||
mod roles_edit;
|
||||
mod roles_fetch;
|
||||
mod roles_edit_positions;
|
||||
mod server_ack;
|
||||
mod server_create;
|
||||
mod server_delete;
|
||||
@@ -47,6 +48,7 @@ pub fn routes() -> (Vec<Route>, OpenApi) {
|
||||
roles_delete::delete,
|
||||
permissions_set::set_role_permission,
|
||||
permissions_set_default::set_default_permissions,
|
||||
emoji_list::list_emoji
|
||||
emoji_list::list_emoji,
|
||||
roles_edit_positions::edit_role_positions
|
||||
]
|
||||
}
|
||||
|
||||
@@ -45,22 +45,15 @@ pub async fn edit(
|
||||
name,
|
||||
colour,
|
||||
hoist,
|
||||
rank,
|
||||
remove,
|
||||
// rank is deprecated
|
||||
..
|
||||
} = data;
|
||||
|
||||
// Prevent us from moving a role above other roles
|
||||
if let Some(rank) = &rank {
|
||||
if rank <= &member_rank {
|
||||
return Err(create_error!(NotElevated));
|
||||
}
|
||||
}
|
||||
|
||||
let partial = PartialRole {
|
||||
name,
|
||||
colour,
|
||||
hoist,
|
||||
rank,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
||||
80
crates/delta/src/routes/servers/roles_edit_positions.rs
Normal file
80
crates/delta/src/routes/servers/roles_edit_positions.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
use revolt_database::{events::client::EventV1, util::{permissions::DatabasePermissionQuery, reference::Reference}, Database, PartialRole, User};
|
||||
use revolt_permissions::{calculate_server_permissions, ChannelPermission};
|
||||
use rocket::{serde::json::Json, State};
|
||||
use revolt_result::{create_error, Result};
|
||||
use revolt_models::v0;
|
||||
|
||||
/// # Edits server roles ranks
|
||||
///
|
||||
/// Edit's server role's ranks.
|
||||
#[openapi(tag = "Server Permissions")]
|
||||
#[patch("/<target>/roles/ranks", data = "<data>")]
|
||||
pub async fn edit_role_ranks(
|
||||
db: &State<Database>,
|
||||
user: User,
|
||||
target: Reference,
|
||||
data: Json<v0::DataEditRoleRanks>,
|
||||
) -> Result<Json<v0::Server>> {
|
||||
let data = data.into_inner();
|
||||
|
||||
let mut server = target.as_server(db).await?;
|
||||
let mut query = DatabasePermissionQuery::new(db, &user).server(&server);
|
||||
calculate_server_permissions(&mut query)
|
||||
.await
|
||||
.throw_if_lacking_channel_permission(ChannelPermission::ManageRole)?;
|
||||
|
||||
let existing_order = server.roles.keys().cloned().collect::<Vec<_>>();
|
||||
let new_order = data.ranks.clone().into_iter().collect::<Vec<_>>();
|
||||
|
||||
// verify all roles are in the new ordering
|
||||
if data.ranks.len() != server.roles.len() && server.roles.iter().all(|(id, _)| data.ranks.contains(id)) {
|
||||
return Err(create_error!(InvalidOperation))
|
||||
}
|
||||
|
||||
let member_top_rank = query.get_member_rank();
|
||||
|
||||
// find all roles above the member which we should not be able to reorder
|
||||
let cant_modify = server.roles.clone()
|
||||
.into_iter()
|
||||
.filter(|(_, role)| if let Some(top_rank) = member_top_rank { role.rank >= top_rank } else { true })
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// check if any roles which we cant reorder have tried to been reordered
|
||||
if cant_modify.iter()
|
||||
.any(|(id, _)| {
|
||||
let existing_rank = existing_order.iter().position(|existing_id| id == existing_id);
|
||||
let new_rank = new_order.iter().position(|new_id| id == new_id);
|
||||
|
||||
existing_rank != new_rank
|
||||
})
|
||||
{
|
||||
return Err(create_error!(NotElevated))
|
||||
}
|
||||
|
||||
// update the roles which have had their rank changed
|
||||
for (role_id, role) in &mut server.roles {
|
||||
let new_rank = new_order.iter().position(|id| id == role_id).unwrap() as i64; // unwrap - we check if its in the data earlier on
|
||||
|
||||
if new_rank != role.rank {
|
||||
// cant use Role::update here because we dont want to publish seperate role update events
|
||||
let partial = PartialRole {
|
||||
rank: Some(new_rank),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
db.update_role(&server.id, role_id, &partial, Vec::new()).await?;
|
||||
|
||||
role.apply_options(PartialRole {
|
||||
rank: Some(new_rank),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// publish bulk update event
|
||||
EventV1::ServerRoleRanksUpdate {
|
||||
ranks: new_order
|
||||
}.p(server.id.clone()).await;
|
||||
|
||||
Ok(Json(server.into()))
|
||||
}
|
||||
Reference in New Issue
Block a user