use std::sync::Arc; use backchannel_common::protocol::ServerMessage; use backchannel_common::types::{has_permission, PermissionFlags}; use uuid::Uuid; use crate::db::{keys, roles}; use crate::error::{Result, ServerError}; use crate::state::{AppState, ChannelBroadcast}; use crate::ws::session::Session; pub async fn handle_create( session: &Session, state: &Arc, name: String, permissions: u64, ) -> Result<()> { let user_id = session.require_auth()?; let perms = roles::get_user_permissions(&state.db, user_id).await?; if !has_permission(perms, PermissionFlags::MANAGE_ROLES) { return Err(ServerError::Forbidden); } let role_id = roles::create(&state.db, &name, permissions).await?; let _ = state.channel_broadcast.send(ChannelBroadcast { message: ServerMessage::RoleCreated { role_id, name, permissions }, }); Ok(()) } pub async fn handle_assign( session: &Session, state: &Arc, user_id: Uuid, role_id: Uuid, ) -> Result<()> { let caller_id = session.require_auth()?; let perms = roles::get_user_permissions(&state.db, caller_id).await?; if !has_permission(perms, PermissionFlags::MANAGE_ROLES) { return Err(ServerError::Forbidden); } roles::find_by_id(&state.db, role_id) .await? .ok_or_else(|| ServerError::NotFound("Role not found".into()))?; roles::assign(&state.db, user_id, role_id).await?; let _ = state.channel_broadcast.send(ChannelBroadcast { message: ServerMessage::RoleAssigned { user_id, role_id }, }); Ok(()) } pub async fn handle_revoke( session: &Session, state: &Arc, user_id: Uuid, role_id: Uuid, ) -> Result<()> { let caller_id = session.require_auth()?; let perms = roles::get_user_permissions(&state.db, caller_id).await?; if !has_permission(perms, PermissionFlags::MANAGE_ROLES) { return Err(ServerError::Forbidden); } roles::revoke(&state.db, user_id, role_id).await?; let _ = state.channel_broadcast.send(ChannelBroadcast { message: ServerMessage::RoleRevoked { user_id, role_id }, }); Ok(()) } pub async fn handle_query_key( session: &Session, state: &Arc, user_id: Uuid, ) -> Result<()> { session.require_auth()?; let pubkey = keys::get_identity_key(&state.db, user_id).await?; session.send(ServerMessage::IdentityKeyResponse { user_id, identity_pubkey: pubkey }) }