forked from projectmoon/tenebrous-dicebot
Add user accounts, registration command, secure command valiation.
This commit is contained in:
parent
a84d4fd869
commit
c1ec7366e4
|
@ -33,3 +33,20 @@ impl Command for ResyncCommand {
|
||||||
Execution::success(message)
|
Execution::success(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct RegisterCommand(pub String);
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Command for RegisterCommand {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"register user account"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_secure(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn execute(&self, ctx: &Context<'_>) -> ExecutionResult {
|
||||||
|
Execution::success("User account registered".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,9 @@ pub enum CommandError {
|
||||||
#[error("invalid command: {0}")]
|
#[error("invalid command: {0}")]
|
||||||
InvalidCommand(String),
|
InvalidCommand(String),
|
||||||
|
|
||||||
|
#[error("command can only be executed from encrypted direct message")]
|
||||||
|
InsecureExecution,
|
||||||
|
|
||||||
#[error("ignored command")]
|
#[error("ignored command")]
|
||||||
IgnoredCommand,
|
IgnoredCommand,
|
||||||
}
|
}
|
||||||
|
@ -99,13 +102,33 @@ pub trait Command: Send + Sync {
|
||||||
fn is_secure(&self) -> bool;
|
fn is_secure(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determine if we are allowed to execute this command. Currently the
|
||||||
|
/// rules are that secure commands must be executed in secure rooms
|
||||||
|
/// (encrypted + direct), and anything else can be executed where
|
||||||
|
/// ever. Later, we can add stuff like admin/regular user power
|
||||||
|
/// separation, etc.
|
||||||
|
fn execution_allowed(cmd: &(impl Command + ?Sized), ctx: &Context<'_>) -> Result<(), CommandError> {
|
||||||
|
if cmd.is_secure() {
|
||||||
|
if ctx.is_secure() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(CommandError::InsecureExecution)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Attempt to execute a command, and return the content that should
|
/// Attempt to execute a command, and return the content that should
|
||||||
/// go back to Matrix, if the command was executed (successfully or
|
/// go back to Matrix, if the command was executed (successfully or
|
||||||
/// not). If a command is determined to be ignored, this function will
|
/// not). If a command is determined to be ignored, this function will
|
||||||
/// return None, signifying that we should not send a response.
|
/// return None, signifying that we should not send a response.
|
||||||
pub async fn execute_command(ctx: &Context<'_>) -> ExecutionResult {
|
pub async fn execute_command(ctx: &Context<'_>) -> ExecutionResult {
|
||||||
let cmd = parser::parse_command(&ctx.message_body)?;
|
let cmd = parser::parse_command(&ctx.message_body)?;
|
||||||
cmd.execute(ctx).await
|
|
||||||
|
match execution_allowed(cmd.as_ref(), ctx) {
|
||||||
|
Ok(_) => cmd.execute(ctx).await,
|
||||||
|
Err(e) => Err(ExecutionError(e.into())),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::commands::{
|
||||||
basic_rolling::RollCommand,
|
basic_rolling::RollCommand,
|
||||||
cofd::PoolRollCommand,
|
cofd::PoolRollCommand,
|
||||||
cthulhu::{CthAdvanceRoll, CthRoll},
|
cthulhu::{CthAdvanceRoll, CthRoll},
|
||||||
management::ResyncCommand,
|
management::{RegisterCommand, ResyncCommand},
|
||||||
misc::HelpCommand,
|
misc::HelpCommand,
|
||||||
variables::{
|
variables::{
|
||||||
DeleteVariableCommand, GetAllVariablesCommand, GetVariableCommand, SetVariableCommand,
|
DeleteVariableCommand, GetAllVariablesCommand, GetVariableCommand, SetVariableCommand,
|
||||||
|
@ -47,6 +47,10 @@ fn parse_roll(input: &str) -> Result<Box<dyn Command>, BotError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_register_command(input: &str) -> Result<Box<dyn Command>, BotError> {
|
||||||
|
Ok(Box::new(RegisterCommand(input.to_owned())))
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_get_variable_command(input: &str) -> Result<Box<dyn Command>, BotError> {
|
fn parse_get_variable_command(input: &str) -> Result<Box<dyn Command>, BotError> {
|
||||||
Ok(Box::new(GetVariableCommand(input.to_owned())))
|
Ok(Box::new(GetVariableCommand(input.to_owned())))
|
||||||
}
|
}
|
||||||
|
@ -141,6 +145,7 @@ pub fn parse_command(input: &str) -> Result<Box<dyn Command>, BotError> {
|
||||||
"cthadv" | "ctharoll" => parse_cth_advancement_roll(&cmd_input),
|
"cthadv" | "ctharoll" => parse_cth_advancement_roll(&cmd_input),
|
||||||
"chance" => chance_die(),
|
"chance" => chance_die(),
|
||||||
"help" => help(&cmd_input),
|
"help" => help(&cmd_input),
|
||||||
|
"register" => parse_register_command(&cmd_input),
|
||||||
_ => Err(CommandParsingError::UnrecognizedCommand(cmd).into()),
|
_ => Err(CommandParsingError::UnrecognizedCommand(cmd).into()),
|
||||||
},
|
},
|
||||||
//All other errors passed up.
|
//All other errors passed up.
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
use barrel::backend::Sqlite;
|
||||||
|
use barrel::{types, types::Type, Migration};
|
||||||
|
|
||||||
|
fn primary_uuid() -> Type {
|
||||||
|
types::text().unique(true).primary(true).nullable(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn migration() -> String {
|
||||||
|
let mut m = Migration::new();
|
||||||
|
|
||||||
|
//Table of room ID, event ID, event timestamp
|
||||||
|
m.create_table("accounts", move |t| {
|
||||||
|
t.add_column("user_id", primary_uuid());
|
||||||
|
t.add_column("password", types::text().nullable(false));
|
||||||
|
});
|
||||||
|
|
||||||
|
m.make::<Sqlite>()
|
||||||
|
}
|
Loading…
Reference in New Issue