2021-05-26 21:25:32 +00:00
|
|
|
use super::{Command, Execution, ExecutionResult};
|
2021-05-22 14:52:32 +00:00
|
|
|
use crate::db::Users;
|
2021-05-26 15:28:59 +00:00
|
|
|
use crate::error::BotError::{AccountDoesNotExist, PasswordCreationError};
|
2021-05-24 21:32:00 +00:00
|
|
|
use crate::logic::hash_password;
|
2021-05-25 15:05:35 +00:00
|
|
|
use crate::models::{AccountStatus, User};
|
2021-05-25 23:54:06 +00:00
|
|
|
use crate::{context::Context, error::BotError};
|
2020-11-22 21:30:24 +00:00
|
|
|
use async_trait::async_trait;
|
2021-05-25 23:54:06 +00:00
|
|
|
use std::convert::{Into, TryFrom};
|
2021-05-21 22:33:49 +00:00
|
|
|
|
2021-05-26 15:28:59 +00:00
|
|
|
pub struct RegisterCommand;
|
2021-05-21 22:33:49 +00:00
|
|
|
|
2021-05-25 23:54:06 +00:00
|
|
|
impl From<RegisterCommand> for Box<dyn Command> {
|
|
|
|
fn from(cmd: RegisterCommand) -> Self {
|
|
|
|
Box::new(cmd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<&str> for RegisterCommand {
|
|
|
|
type Error = BotError;
|
|
|
|
|
2021-05-26 15:28:59 +00:00
|
|
|
fn try_from(_: &str) -> Result<Self, Self::Error> {
|
|
|
|
Ok(RegisterCommand)
|
2021-05-25 23:54:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-21 22:33:49 +00:00
|
|
|
#[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 {
|
2021-05-26 21:04:53 +00:00
|
|
|
if ctx.account.is_registered() {
|
2021-05-26 21:25:32 +00:00
|
|
|
return Err(BotError::AccountAlreadyExists);
|
2021-05-26 15:28:59 +00:00
|
|
|
}
|
|
|
|
|
2021-05-22 14:52:32 +00:00
|
|
|
let user = User {
|
|
|
|
username: ctx.username.to_owned(),
|
2021-05-26 15:28:59 +00:00
|
|
|
password: None,
|
2021-05-25 15:05:35 +00:00
|
|
|
account_status: AccountStatus::Registered,
|
|
|
|
..Default::default()
|
2021-05-22 14:52:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
ctx.db.upsert_user(&user).await?;
|
2021-05-26 21:04:53 +00:00
|
|
|
|
2021-05-23 13:58:58 +00:00
|
|
|
Execution::success(format!(
|
2021-05-26 15:28:59 +00:00
|
|
|
"User account {} registered for bot commands.",
|
|
|
|
ctx.username
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct UnlinkCommand(pub String);
|
|
|
|
|
|
|
|
impl From<UnlinkCommand> for Box<dyn Command> {
|
|
|
|
fn from(cmd: UnlinkCommand) -> Self {
|
|
|
|
Box::new(cmd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<&str> for UnlinkCommand {
|
|
|
|
type Error = BotError;
|
|
|
|
|
|
|
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
|
|
|
Ok(UnlinkCommand(value.to_owned()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
impl Command for UnlinkCommand {
|
|
|
|
fn name(&self) -> &'static str {
|
|
|
|
"unlink user accountx from external applications"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_secure(&self) -> bool {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn execute(&self, ctx: &Context<'_>) -> ExecutionResult {
|
|
|
|
let mut user = ctx
|
|
|
|
.db
|
|
|
|
.get_user(&ctx.username)
|
|
|
|
.await?
|
|
|
|
.ok_or(BotError::AccountDoesNotExist)?;
|
|
|
|
|
|
|
|
user.password = None;
|
|
|
|
ctx.db.upsert_user(&user).await?;
|
|
|
|
|
|
|
|
Execution::success(format!(
|
|
|
|
"Accounted {} is now inaccessible to external applications.",
|
2021-05-23 13:58:58 +00:00
|
|
|
ctx.username
|
|
|
|
))
|
2021-05-21 22:33:49 +00:00
|
|
|
}
|
|
|
|
}
|
2021-05-22 22:25:00 +00:00
|
|
|
|
2021-05-26 15:28:59 +00:00
|
|
|
pub struct LinkCommand(pub String);
|
|
|
|
|
|
|
|
impl From<LinkCommand> for Box<dyn Command> {
|
|
|
|
fn from(cmd: LinkCommand) -> Self {
|
|
|
|
Box::new(cmd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<&str> for LinkCommand {
|
|
|
|
type Error = BotError;
|
|
|
|
|
|
|
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
|
|
|
Ok(LinkCommand(value.to_owned()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
impl Command for LinkCommand {
|
|
|
|
fn name(&self) -> &'static str {
|
|
|
|
"link user account to external applications"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_secure(&self) -> bool {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn execute(&self, ctx: &Context<'_>) -> ExecutionResult {
|
|
|
|
let mut user = ctx
|
|
|
|
.db
|
|
|
|
.get_user(&ctx.username)
|
|
|
|
.await?
|
|
|
|
.ok_or(BotError::AccountDoesNotExist)?;
|
|
|
|
|
|
|
|
let pw_hash = hash_password(&self.0).map_err(|e| PasswordCreationError(e))?;
|
|
|
|
user.password = Some(pw_hash);
|
|
|
|
ctx.db.upsert_user(&user).await?;
|
|
|
|
|
|
|
|
Execution::success(format!(
|
|
|
|
"Accounted now available for external use. Please log in to \
|
|
|
|
external applications with username {} and the password you set.",
|
|
|
|
ctx.username
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct CheckCommand;
|
2021-05-22 22:25:00 +00:00
|
|
|
|
2021-05-25 23:54:06 +00:00
|
|
|
impl From<CheckCommand> for Box<dyn Command> {
|
|
|
|
fn from(cmd: CheckCommand) -> Self {
|
|
|
|
Box::new(cmd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<&str> for CheckCommand {
|
|
|
|
type Error = BotError;
|
|
|
|
|
2021-05-26 15:28:59 +00:00
|
|
|
fn try_from(_: &str) -> Result<Self, Self::Error> {
|
|
|
|
Ok(CheckCommand)
|
2021-05-25 23:54:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-22 22:25:00 +00:00
|
|
|
#[async_trait]
|
|
|
|
impl Command for CheckCommand {
|
|
|
|
fn name(&self) -> &'static str {
|
2021-05-26 15:28:59 +00:00
|
|
|
"check user account status"
|
2021-05-22 22:25:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn is_secure(&self) -> bool {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn execute(&self, ctx: &Context<'_>) -> ExecutionResult {
|
2021-05-26 15:28:59 +00:00
|
|
|
let user = ctx.db.get_user(&ctx.username).await?;
|
2021-05-22 22:25:00 +00:00
|
|
|
|
|
|
|
match user {
|
2021-05-26 15:28:59 +00:00
|
|
|
Some(user) => match user.password {
|
|
|
|
Some(_) => Execution::success(
|
|
|
|
"Account exists, and is available to external applications with a password. If you forgot your password, change it with !link.".to_string(),
|
|
|
|
),
|
|
|
|
None => Execution::success(
|
|
|
|
"Account exists, but is not available to external applications.".to_string(),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
None => Execution::success(
|
|
|
|
"No account registered. Only simple commands in public rooms are available.".to_string(),
|
|
|
|
),
|
2021-05-22 22:25:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-05-22 23:12:17 +00:00
|
|
|
|
|
|
|
pub struct UnregisterCommand;
|
|
|
|
|
2021-05-25 23:54:06 +00:00
|
|
|
impl From<UnregisterCommand> for Box<dyn Command> {
|
|
|
|
fn from(cmd: UnregisterCommand) -> Self {
|
|
|
|
Box::new(cmd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<&str> for UnregisterCommand {
|
|
|
|
type Error = BotError;
|
|
|
|
|
|
|
|
fn try_from(_: &str) -> Result<Self, Self::Error> {
|
|
|
|
Ok(UnregisterCommand)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-22 23:12:17 +00:00
|
|
|
#[async_trait]
|
|
|
|
impl Command for UnregisterCommand {
|
|
|
|
fn name(&self) -> &'static str {
|
|
|
|
"unregister user account"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_secure(&self) -> bool {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn execute(&self, ctx: &Context<'_>) -> ExecutionResult {
|
|
|
|
let user = ctx.db.get_user(&ctx.username).await?;
|
|
|
|
|
|
|
|
match user {
|
|
|
|
Some(_) => {
|
|
|
|
ctx.db.delete_user(&ctx.username).await?;
|
|
|
|
Execution::success("Your user account has been removed.".to_string())
|
|
|
|
}
|
|
|
|
None => Err(AccountDoesNotExist.into()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|