Unverified Commit a54e4762 authored by tec's avatar tec

Add start of account verification

parent a8a035eb
use chrono::{
prelude::{SecondsFormat, Utc},
DateTime,
};
use rand::Rng;
use serenity::model::user::User;
use std::str;
lazy_static! {
static ref key: [u8; 32] = rand::thread_rng().gen::<[u8; 32]>();
}
fn encrypt(plaintext: &str) -> &str {
return plaintext;
}
fn decrypt(ciphertext: &str) -> &str {
return ciphertext;
}
pub fn generate_token<'a>(discord_user: &User, username: &str) -> String {
// if username doesn't exist : throw error
let timestamp = Utc::now().to_rfc3339();
let payload = format!(
"{},{},{}",
timestamp,
discord_user.id.0.to_string(),
username
);
info!("Token generated for {}: {}", discord_user.name, &payload);
encrypt(&payload).to_string()
}
#[derive(Debug)]
pub enum TokenError {
DiscordIdMismatch,
TokenExpired,
}
impl std::fmt::Display for TokenError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
pub fn parse_token(discord_user: &User, token: &str) -> Result<String, TokenError> {
let token_components: Vec<_> = decrypt(token).splitn(3, ',').collect();
info!(
"Verification attempt from '{}'(uid: {}) for account '{}' with token from {}",
discord_user.name, token_components[1], token_components[2], token_components[0]
);
let token_timestamp =
DateTime::parse_from_rfc3339(token_components[0]).expect("Invalid date format");
let token_discord_user = token_components[1];
let token_username = token_components[2];
if token_discord_user != discord_user.id.0.to_string() {
warn!("... attempt failed : DiscordID mismatch");
return Err(TokenError::DiscordIdMismatch);
}
let time_delta_seconds = Utc::now().timestamp() - token_timestamp.timestamp();
if time_delta_seconds > 5 * 60 {
warn!(
"... attempt failed : token expired ({} seconds old)",
time_delta_seconds
);
return Err(TokenError::TokenExpired);
}
info!(
"... verification successful (token {} seconds old)",
time_delta_seconds
);
return Ok(token_username.to_owned());
}
...@@ -6,6 +6,7 @@ use serenity::{ ...@@ -6,6 +6,7 @@ use serenity::{
}; };
use crate::config::CONFIG; use crate::config::CONFIG;
use crate::token_management::*;
macro_rules! e { macro_rules! e {
($error: literal, $x:expr) => { ($error: literal, $x:expr) => {
...@@ -59,48 +60,63 @@ impl Commands { ...@@ -59,48 +60,63 @@ impl Commands {
); );
return; return;
} }
// token stuff e!(
"Error sending message: {:?}",
// TODO convert to email
msg.channel_id
.say(&ctx.http, generate_token(&msg.author, name))
);
e!("Error deleting register message: {:?}", msg.delete(ctx)); e!("Error deleting register message: {:?}", msg.delete(ctx));
} }
pub fn verify(ctx: Context, msg: Message, content: &str) { pub fn verify(ctx: Context, msg: Message, content: &str) {
let token = content; let token = content;
// if token is valid match parse_token(&msg.author, content) {
e!( Ok(name) => {
"Unable to get member: {:?}", e!(
serenity::model::id::GuildId(CONFIG.server_id) "Unable to get member: {:?}",
.member(ctx.http.clone(), msg.author.id) serenity::model::id::GuildId(CONFIG.server_id)
.map(|mut member| { .member(ctx.http.clone(), msg.author.id)
e!( .map(|mut member| {
"Unable to remove role: {:?}", e!(
member.remove_role(&ctx.http, CONFIG.unregistered_member_role) "Unable to remove role: {:?}",
); member.remove_role(&ctx.http, CONFIG.unregistered_member_role)
e!( );
"Unable to edit nickname: {:?}", e!(
member "Unable to edit nickname: {:?}",
.edit(&ctx.http, |m| { member.edit(&ctx.http, |m| {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
m.nickname(format!( m.nickname(format!(
"{}, {}", "{}, {}",
name, name,
[ [
"The Big Cheese", "The Big Cheese",
"The One and Only", "The One and Only",
"The Exalted One", "The Exalted One",
"not to be trusted", "not to be trusted",
"The Scoundrel", "The Scoundrel",
"A big fish in a small pond", "A big fish in a small pond",
][rng.gen_range(0, 5)] ][rng.gen_range(0, 5)]
)); ));
m m
}) })
.map(|()| { );
e!( let new_msg = msg
"Unable to add role: {:?}", .channel_id
member.add_role(&ctx.http, CONFIG.registered_member_role) .say(&ctx.http, "Verification succesful")
); .expect("Error sending message");
}) e!(
); "Error deleting register message: {:?}",
}) new_msg.delete(&ctx)
); );
})
);
}
Err(reason) => e!(
"Error sending message: {:?}",
msg.channel_id
.say(&ctx.http, format!("Verification error: {:?}", reason))
),
}
e!("Error deleting register message: {:?}", msg.delete(&ctx));
} }
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment