diff --git a/Cargo.lock b/Cargo.lock index bedf3e0..552b2c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -185,6 +185,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6776fc96284a0bb647b615056fc496d1fe1644a7ab01829818a6d91cae888b84" + [[package]] name = "bitvec" version = "1.0.1" @@ -357,7 +363,7 @@ version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ - "bitflags", + "bitflags 1.3.2", "clap_derive", "clap_lex", "indexmap", @@ -1308,6 +1314,7 @@ version = "0.1.0" dependencies = [ "anyhow", "arrayvec", + "bitflags 2.3.1", "chacha20poly1305", "dotenv", "futures", @@ -1572,7 +1579,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1754,7 +1761,7 @@ version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", @@ -2201,7 +2208,7 @@ dependencies = [ "ahash 0.7.6", "atoi", "bigdecimal", - "bitflags", + "bitflags 1.3.2", "byteorder", "bytes", "chrono", @@ -2371,7 +2378,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "303db260110c238e3af77bb9dff18bf7a5b5196f783059b0852aab75f91d5a16" dependencies = [ - "bitflags", + "bitflags 1.3.2", "bytes", "chrono", "derive_more", diff --git a/Cargo.toml b/Cargo.toml index 172a67f..a194dfd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ members = [".", "migration"] [dependencies] anyhow = "1.0.71" arrayvec = "0.7.2" +bitflags = "2.3.1" chacha20poly1305 = { version = "0.10.1", features = ["std"] } dotenv = "0.15.0" futures = "0.3.28" diff --git a/src/handlers/commands/gen_password.rs b/src/handlers/commands/gen_password.rs index 4608c89..8336be7 100644 --- a/src/handlers/commands/gen_password.rs +++ b/src/handlers/commands/gen_password.rs @@ -1,26 +1,38 @@ use crate::handlers::markups::deletion_markup; use arrayvec::{ArrayString, ArrayVec}; use rand::{rngs::OsRng, seq::SliceRandom}; -use std::str::from_utf8_unchecked; +use std::{fmt::Write, str::from_utf8_unchecked}; use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode}; use tokio::task::spawn_blocking; const CHARS: &[u8] = br##"!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~"##; +bitflags::bitflags! { + #[derive(PartialEq)] + struct PasswordFlags: u8 { + const LOWERCASE = 0b0001; + const UPPERCASE = 0b0010; + const NUMBER = 0b0100; + const SPECIAL_CHARACTER = 0b1000; + } +} + /// Returns true if the generated master password is valid. /// It checks that it has at least one lowercase, one lowercase and one punctuation char #[inline] fn check_generated_password(password: &[u8]) -> bool { - let mut flags: u8 = 0; + let mut flags = PasswordFlags::empty(); for &byte in password { match byte { - b'a'..=b'z' => flags |= 0b1, - b'A'..=b'Z' => flags |= 0b10, - b'0'..=b'9' => flags |= 0b100, - b'!'..=b'/' | b':'..=b'@' | b'['..=b'`' | b'{'..=b'~' => flags |= 0b1000, + b'a'..=b'z' => flags |= PasswordFlags::LOWERCASE, + b'A'..=b'Z' => flags |= PasswordFlags::UPPERCASE, + b'0'..=b'9' => flags |= PasswordFlags::NUMBER, + b'!'..=b'/' | b':'..=b'@' | b'['..=b'`' | b'{'..=b'~' => { + flags |= PasswordFlags::SPECIAL_CHARACTER + } _ => (), } - if flags == 0b1111 { + if flags == PasswordFlags::all() { return true; } } @@ -29,17 +41,15 @@ fn check_generated_password(password: &[u8]) -> bool { /// Continuously generates the password until it passes the checks #[inline] -fn generate_passwords() -> [ArrayString<34>; 10] { +fn generate_passwords() -> [ArrayString<32>; 10] { let mut passwords = ArrayVec::new_const(); while !passwords.is_full() { let password: ArrayVec = (0..32) .map(|_| *CHARS.choose(&mut OsRng).unwrap()) .collect(); if check_generated_password(&password) { - let mut string = ArrayString::<34>::new_const(); - string.push('`'); + let mut string = ArrayString::<32>::new_const(); unsafe { string.push_str(from_utf8_unchecked(&password)) }; - string.push('`'); passwords.push(string) } } @@ -51,8 +61,7 @@ pub async fn gen_password(bot: Throttle, msg: Message) -> crate::Result<()> let mut message: ArrayString<{ 10 + 35 * 10 }> = "Passwords:".try_into().unwrap(); let passwords = spawn_blocking(generate_passwords).await?; for password in passwords { - message.push('\n'); - message.push_str(&password) + write!(message, "\n`{password}`").unwrap(); } bot.send_message(msg.chat.id, message.as_str()) .parse_mode(ParseMode::MarkdownV2)