mirror of
https://git.ngram.ca/OpenJam/rc-servers
synced 2026-08-23 23:08:52 +00:00
Add some basic commands for sysadmins and permission system for them
This commit is contained in:
@@ -15,9 +15,38 @@ pub struct ChatConfig {
|
||||
|
||||
impl super::config::SelfValidator for ChatConfig {
|
||||
type Context = crate::ConfigImpl;
|
||||
fn validate(&self, _info: &mut super::config::ValidationInfo, _ctx: &Self::Context) -> bool {
|
||||
// TODO
|
||||
true
|
||||
fn validate(&self, info: &mut super::config::ValidationInfo, _ctx: &Self::Context) -> bool {
|
||||
let mut is_ok = true;
|
||||
if !self.public_channels.contains(&self.command_channel) {
|
||||
info.warn(super::config::ValidationMessage {
|
||||
path: vec!["public_channels".to_owned()],
|
||||
message: "Chat command channel is not a public channel".to_owned(),
|
||||
});
|
||||
}
|
||||
if !self.public_channels.contains(&self.default_channel) {
|
||||
info.warn(super::config::ValidationMessage {
|
||||
path: vec!["public_channels".to_owned()],
|
||||
message: "Chat default channel is not a public channel".to_owned(),
|
||||
});
|
||||
}
|
||||
if self.command_channel.is_empty() {
|
||||
info.error(super::config::ValidationMessage {
|
||||
path: vec!["command_channel".to_owned()],
|
||||
message: "Chat command channel should not be empty".to_owned(),
|
||||
});
|
||||
is_ok = false;
|
||||
}
|
||||
for (i, cmd) in self.commands.iter().enumerate() {
|
||||
is_ok &= cmd.validate_in(info, self, &format!("commands[{}]", i));
|
||||
}
|
||||
if self.default_channel.is_empty() {
|
||||
info.error(super::config::ValidationMessage {
|
||||
path: vec!["default_channel".to_owned()],
|
||||
message: "Chat default channel should not be empty".to_owned(),
|
||||
});
|
||||
is_ok = false;
|
||||
}
|
||||
is_ok
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +54,52 @@ impl super::config::SelfValidator for ChatConfig {
|
||||
pub struct ChatCommand {
|
||||
pub regex: String,
|
||||
pub op: ChatOperation,
|
||||
pub permission: ChatPermission,
|
||||
}
|
||||
|
||||
impl super::config::SelfValidator for ChatCommand {
|
||||
type Context = ChatConfig;
|
||||
fn validate(&self, info: &mut super::config::ValidationInfo, ctx: &Self::Context) -> bool {
|
||||
let mut is_ok = true;
|
||||
let regex_count = ctx.commands.iter().filter(|other| self.regex == other.regex).count();
|
||||
if regex_count != 1 {
|
||||
info.error(super::config::ValidationMessage {
|
||||
path: vec!["regex".to_owned()],
|
||||
message: format!("Only one chat command can use an identical regex pattern {}; found {}", self.regex, regex_count),
|
||||
});
|
||||
is_ok = false;
|
||||
}
|
||||
// TODO validate regex
|
||||
|
||||
// recommended commands to only allow with elevated permissions
|
||||
if matches!(
|
||||
self.op,
|
||||
ChatOperation::BuiltIn(BuiltInChatOperation::Intercom(IntercomChatOperation::DevBroadcast))
|
||||
| ChatOperation::BuiltIn(BuiltInChatOperation::Intercom(IntercomChatOperation::Maintenance))
|
||||
) {
|
||||
if !matches!(self.permission, ChatPermission::Administrator | ChatPermission::Developer | ChatPermission::Royal) {
|
||||
info.warn(crate::persist::config::ValidationMessage {
|
||||
path: vec!["permission".to_owned()],
|
||||
message: format!("Chat command {:?} is recommended to require Administrator, Developer, or Royal permissions; found {:?}", self.op, self.permission),
|
||||
});
|
||||
}
|
||||
}
|
||||
is_ok
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub enum ChatPermission {
|
||||
Player,
|
||||
#[serde(alias = "Mod")]
|
||||
Moderator,
|
||||
#[serde(alias = "Admin")]
|
||||
Administrator,
|
||||
#[serde(alias = "Dev")]
|
||||
Developer,
|
||||
#[serde(alias = "Special")]
|
||||
Royal,
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
@@ -50,6 +125,8 @@ pub enum BuiltInChatOperation {
|
||||
#[serde(tag = "intercom")]
|
||||
pub enum IntercomChatOperation {
|
||||
DevMessage,
|
||||
DevBroadcast,
|
||||
Maintenance,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ mod settings;
|
||||
pub use settings::{Settings, QueueMode};
|
||||
|
||||
mod chat;
|
||||
pub use chat::{ChatConfig, ChatCommand, ChatOperation, BuiltInChatOperation, IntercomChatOperation};
|
||||
pub use chat::{ChatConfig, ChatCommand, ChatOperation, BuiltInChatOperation, IntercomChatOperation, ChatPermission};
|
||||
|
||||
mod vehicle_factory;
|
||||
pub use vehicle_factory::{FactoryConfig, AdapterSettings, ArcFactorySettings};
|
||||
|
||||
@@ -18,6 +18,10 @@ impl super::CommonUser for UserData {
|
||||
self.perms.developer
|
||||
}
|
||||
|
||||
fn is_royal(&self) -> bool {
|
||||
self.perms.royalty
|
||||
}
|
||||
|
||||
fn is_banned(&self) -> bool {
|
||||
self.perms.banned
|
||||
}
|
||||
|
||||
@@ -65,23 +65,38 @@ impl super::IntercomUser for super::account_json::UserData {
|
||||
let data = IntercomWebServiceMessage {
|
||||
public_ids: to,
|
||||
data: IntercomWebServiceUserMessage::DevMessage(msg),
|
||||
everyone: false,
|
||||
};
|
||||
if let Err(e) = self.post_to_intercom(&data, ".oj_services", "messages").await {
|
||||
log::error!("Failed to send intercom dev message: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
async fn enter_maintenance(&self, msg: IntercomMaintenanceMessage, to: Vec<String>) {
|
||||
let send_to_everyone = to.is_empty();
|
||||
let data = IntercomWebServiceMessage {
|
||||
public_ids: to,
|
||||
data: IntercomWebServiceUserMessage::Maintenance(msg),
|
||||
everyone: send_to_everyone,
|
||||
};
|
||||
if let Err(e) = self.post_to_intercom(&data, ".oj_services", "messages").await {
|
||||
log::error!("Failed to send intercom maintenance mode message: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct IntercomWebServiceMessage {
|
||||
pub public_ids: Vec<String>,
|
||||
pub data: IntercomWebServiceUserMessage,
|
||||
pub everyone: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum IntercomWebServiceUserMessage {
|
||||
DevMessage(IntercomDevMessage),
|
||||
Maintenance(IntercomMaintenanceMessage),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
@@ -90,6 +105,11 @@ pub struct IntercomDevMessage {
|
||||
pub duration: u32,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct IntercomMaintenanceMessage {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
pub fn generate_token(salt: &[u8], key: &[u8]) -> String {
|
||||
use sha2::{Digest, Sha512};
|
||||
let mut hasher = Sha512::new();
|
||||
|
||||
@@ -338,6 +338,7 @@ pub trait IntercomUser {
|
||||
async fn save_custom_avatar(&self, image: Vec<u8>) -> Result<(), polariton_server::operations::SimpleOpError>;
|
||||
async fn webservice_listener(&self) -> Result<IntercomListener<super::intercom::IntercomWebServiceUserMessage>, polariton_server::operations::SimpleOpError>;
|
||||
async fn show_dev_message(&self, msg: super::intercom::IntercomDevMessage, to: Vec<String>);
|
||||
async fn enter_maintenance(&self, msg: super::intercom::IntercomMaintenanceMessage, to: Vec<String>);
|
||||
}
|
||||
|
||||
pub struct IntercomListener<D: serde::de::DeserializeOwned> {
|
||||
@@ -373,5 +374,6 @@ pub trait CommonUser: Send + Sync {
|
||||
fn is_mod(&self) -> bool;
|
||||
fn is_admin(&self) -> bool;
|
||||
fn is_dev(&self) -> bool;
|
||||
fn is_royal(&self) -> bool;
|
||||
fn is_banned(&self) -> bool;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user