Made cryptography and entity modules
Coupling was rising so it just makes sense
This commit is contained in:
parent
9af37f78b2
commit
5871943c01
109
Cargo.lock
generated
109
Cargo.lock
generated
@ -94,9 +94,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
@ -281,6 +281,25 @@ version = "2.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.3.11"
|
version = "0.3.11"
|
||||||
@ -307,24 +326,6 @@ dependencies = [
|
|||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cryptography"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"arrayvec",
|
|
||||||
"bitflags 2.5.0",
|
|
||||||
"chacha20poly1305",
|
|
||||||
"entity",
|
|
||||||
"once_cell",
|
|
||||||
"pbkdf2",
|
|
||||||
"rand",
|
|
||||||
"scrypt",
|
|
||||||
"serde",
|
|
||||||
"sha2",
|
|
||||||
"subtle",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.13.4"
|
version = "0.13.4"
|
||||||
@ -429,15 +430,6 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "entity"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"futures",
|
|
||||||
"hex",
|
|
||||||
"sqlx",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -1053,9 +1045,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-iter"
|
name = "num-iter"
|
||||||
version = "0.1.44"
|
version = "0.1.45"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9"
|
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
@ -1064,9 +1056,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.18"
|
version = "0.2.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"libm",
|
"libm",
|
||||||
@ -1096,6 +1088,9 @@ name = "once_cell"
|
|||||||
version = "1.19.0"
|
version = "1.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
dependencies = [
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opaque-debug"
|
name = "opaque-debug"
|
||||||
@ -1140,17 +1135,24 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"cryptography",
|
"bitflags 2.5.0",
|
||||||
|
"chacha20poly1305",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"entity",
|
|
||||||
"futures",
|
"futures",
|
||||||
|
"hex",
|
||||||
"itertools 0.12.1",
|
"itertools 0.12.1",
|
||||||
|
"once_cell",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"pbkdf2",
|
||||||
|
"rand",
|
||||||
|
"scrypt",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"sha2",
|
"sha2",
|
||||||
|
"sqlx",
|
||||||
|
"subtle",
|
||||||
"teloxide",
|
"teloxide",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -1184,6 +1186,8 @@ checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"digest",
|
"digest",
|
||||||
"hmac",
|
"hmac",
|
||||||
|
"password-hash",
|
||||||
|
"rayon",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1349,6 +1353,26 @@ dependencies = [
|
|||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rc-box"
|
name = "rc-box"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@ -1872,6 +1896,7 @@ dependencies = [
|
|||||||
"sha2",
|
"sha2",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"sqlx-mysql",
|
"sqlx-mysql",
|
||||||
|
"sqlx-sqlite",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -1974,6 +1999,7 @@ dependencies = [
|
|||||||
"libsqlite3-sys",
|
"libsqlite3-sys",
|
||||||
"log",
|
"log",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
|
"serde",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"url",
|
||||||
@ -2244,16 +2270,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.10"
|
version = "0.7.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
|
checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2757,18 +2782,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.7.32"
|
version = "0.7.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
checksum = "087eca3c1eaf8c47b94d02790dd086cd594b912d2043d4de4bfdd466b3befb7c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.7.32"
|
version = "0.7.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
checksum = "6f4b6c273f496d8fd4eaf18853e6b448760225dc030ff2c485a786859aea6393"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
28
Cargo.toml
28
Cargo.toml
@ -10,36 +10,44 @@ debug = 1
|
|||||||
lto = true
|
lto = true
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
||||||
[workspace]
|
[lints.clippy]
|
||||||
members = [".", "entity", "cryptography"]
|
|
||||||
|
|
||||||
[workspace.lints.clippy]
|
|
||||||
pedantic = "warn"
|
pedantic = "warn"
|
||||||
all = "warn"
|
all = "warn"
|
||||||
nursery = "warn"
|
|
||||||
|
|
||||||
[lints]
|
|
||||||
workspace = true
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ahash = "0.8"
|
ahash = "0.8"
|
||||||
anyhow = { version = "1", features = ["backtrace"] }
|
anyhow = { version = "1", features = ["backtrace"] }
|
||||||
arrayvec = "0.7"
|
arrayvec = "0.7"
|
||||||
base64 = "0.22"
|
base64 = "0.22"
|
||||||
cryptography = { version = "0.1", path = "cryptography" }
|
bitflags = "2"
|
||||||
|
chacha20poly1305 = { version = "0.10", features = ["std"] }
|
||||||
derive_more = { version = "0.99", default-features = false, features = [
|
derive_more = { version = "0.99", default-features = false, features = [
|
||||||
"deref",
|
"deref",
|
||||||
"display",
|
"display",
|
||||||
] }
|
] }
|
||||||
dotenvy = "0.15"
|
dotenvy = "0.15"
|
||||||
entity = { version = "0.1", path = "entity" }
|
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
|
hex = "0.4"
|
||||||
itertools = "0.12"
|
itertools = "0.12"
|
||||||
|
once_cell = { version = "1", features = ["parking_lot"] }
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
|
pbkdf2 = { version = "0.12", features = ["parallel"] }
|
||||||
|
rand = { version = "0.8", default-features = false, features = [
|
||||||
|
"std_rng",
|
||||||
|
"std",
|
||||||
|
] }
|
||||||
|
scrypt = { version = "0.11", default-features = false, features = ["std"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
serde_yaml = "0.9"
|
serde_yaml = "0.9"
|
||||||
sha2 = "0.10"
|
sha2 = "0.10"
|
||||||
|
sqlx = { version = "0.7", features = [
|
||||||
|
"mysql",
|
||||||
|
"runtime-tokio-rustls",
|
||||||
|
"macros",
|
||||||
|
"migrate",
|
||||||
|
] }
|
||||||
|
subtle = "2"
|
||||||
teloxide = { version = "0.12", features = [
|
teloxide = { version = "0.12", features = [
|
||||||
"macros",
|
"macros",
|
||||||
"ctrlc_handler",
|
"ctrlc_handler",
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "cryptography"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[lints]
|
|
||||||
workspace = true
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
sha2 = "0.10"
|
|
||||||
scrypt = { version = "0.11", default-features = false, features = ["std"] }
|
|
||||||
pbkdf2 = "0.12"
|
|
||||||
thiserror = "1"
|
|
||||||
entity = { version = "0.1", path = "../entity" }
|
|
||||||
chacha20poly1305 = { version = "0.10", features = ["std"] }
|
|
||||||
rand = { version = "0.8", default-features = false, features = [
|
|
||||||
"std_rng",
|
|
||||||
"std",
|
|
||||||
] }
|
|
||||||
bitflags = "2"
|
|
||||||
arrayvec = "0.7"
|
|
||||||
subtle = "2"
|
|
||||||
once_cell = "1"
|
|
||||||
serde = { version = "1", features = ["derive"] }
|
|
@ -1,19 +0,0 @@
|
|||||||
use super::hashing::HashedBytes;
|
|
||||||
use entity::master_pass;
|
|
||||||
|
|
||||||
pub trait FromUnencryptedExt {
|
|
||||||
fn from_unencrypted(user_id: u64, password: &str) -> master_pass::MasterPass;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromUnencryptedExt for master_pass::MasterPass {
|
|
||||||
/// Hashes the password and creates an `ActiveModel` with all fields set to Set variant
|
|
||||||
#[inline]
|
|
||||||
fn from_unencrypted(user_id: u64, password: &str) -> Self {
|
|
||||||
let hash = HashedBytes::new(password.as_bytes());
|
|
||||||
Self {
|
|
||||||
user_id,
|
|
||||||
password_hash: hash.hash.to_vec(),
|
|
||||||
salt: hash.salt.to_vec(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
pub use crate::{
|
|
||||||
account::Decrypted as DecryptedAccount, master_pass::FromUnencryptedExt as _, validate_field,
|
|
||||||
};
|
|
@ -1,19 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "entity"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[lints]
|
|
||||||
workspace = true
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
futures = "0.3"
|
|
||||||
sqlx = { version = "0.7", features = [
|
|
||||||
"mysql",
|
|
||||||
"runtime-tokio-rustls",
|
|
||||||
"macros",
|
|
||||||
"migrate",
|
|
||||||
], default-features = false }
|
|
||||||
hex = "0.4"
|
|
@ -1 +0,0 @@
|
|||||||
pub use crate::{account::Account, master_pass::MasterPass, Pool};
|
|
@ -10,9 +10,11 @@ crate::export_handlers!(
|
|||||||
change_locale
|
change_locale
|
||||||
);
|
);
|
||||||
|
|
||||||
use crate::{errors::InvalidCommand, handle_error, locales::LocaleTypeExt};
|
use crate::{
|
||||||
|
entity::locale::LocaleType, errors::handle_error, errors::InvalidCommand,
|
||||||
|
locales::LocaleTypeExt,
|
||||||
|
};
|
||||||
use base64::{engine::general_purpose::STANDARD_NO_PAD as B64_ENGINE, Engine as _};
|
use base64::{engine::general_purpose::STANDARD_NO_PAD as B64_ENGINE, Engine as _};
|
||||||
use entity::locale::LocaleType;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use teloxide::types::CallbackQuery;
|
use teloxide::types::CallbackQuery;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
use crate::entity::account::Account;
|
||||||
use chacha20poly1305::{AeadCore, AeadInPlace, ChaCha20Poly1305, KeyInit};
|
use chacha20poly1305::{AeadCore, AeadInPlace, ChaCha20Poly1305, KeyInit};
|
||||||
use entity::account::Account;
|
|
||||||
use pbkdf2::pbkdf2_hmac_array;
|
use pbkdf2::pbkdf2_hmac_array;
|
||||||
use rand::{rngs::OsRng, RngCore};
|
use rand::{rngs::OsRng, RngCore};
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
@ -36,9 +36,9 @@ impl Cipher {
|
|||||||
/// Returns an error if the tag doesn't match the ciphertext
|
/// Returns an error if the tag doesn't match the ciphertext
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(clippy::missing_panics_doc)]
|
#[allow(clippy::missing_panics_doc)]
|
||||||
pub fn decrypt(&self, value: &mut Vec<u8>) -> crate::Result<()> {
|
pub fn decrypt(&self, value: &mut Vec<u8>) -> super::Result<()> {
|
||||||
if value.len() <= 12 {
|
if value.len() <= 12 {
|
||||||
return Err(crate::Error::InvalidInputLength);
|
return Err(super::Error::InvalidInputLength);
|
||||||
}
|
}
|
||||||
let nonce: [u8; 12] = value[value.len() - 12..].try_into().unwrap();
|
let nonce: [u8; 12] = value[value.len() - 12..].try_into().unwrap();
|
||||||
value.truncate(value.len() - 12);
|
value.truncate(value.len() - 12);
|
||||||
@ -63,7 +63,7 @@ impl Decrypted {
|
|||||||
///
|
///
|
||||||
/// Returns an error if the tag doesn't match the ciphertext or if the decrypted data isn't valid UTF-8
|
/// Returns an error if the tag doesn't match the ciphertext or if the decrypted data isn't valid UTF-8
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_account(mut account: Account, master_pass: &str) -> crate::Result<Self> {
|
pub fn from_account(mut account: Account, master_pass: &str) -> super::Result<Self> {
|
||||||
let cipher = Cipher::new(master_pass.as_bytes(), &account.salt);
|
let cipher = Cipher::new(master_pass.as_bytes(), &account.salt);
|
||||||
cipher.decrypt(&mut account.enc_login)?;
|
cipher.decrypt(&mut account.enc_login)?;
|
||||||
cipher.decrypt(&mut account.enc_password)?;
|
cipher.decrypt(&mut account.enc_password)?;
|
||||||
@ -125,7 +125,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cipher_test() -> crate::Result<()> {
|
fn cipher_test() -> crate::cryptography::Result<()> {
|
||||||
const ORIGINAL: &[u8] = b"Data to protect";
|
const ORIGINAL: &[u8] = b"Data to protect";
|
||||||
let mut data = ORIGINAL.to_owned();
|
let mut data = ORIGINAL.to_owned();
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn account_encryption() -> crate::Result<()> {
|
fn account_encryption() -> crate::cryptography::Result<()> {
|
||||||
let original = Decrypted {
|
let original = Decrypted {
|
||||||
name: "Account Name".to_owned(),
|
name: "Account Name".to_owned(),
|
||||||
login: "StrongLogin@mail.com".to_owned(),
|
login: "StrongLogin@mail.com".to_owned(),
|
||||||
@ -157,7 +157,7 @@ mod tests {
|
|||||||
|
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
CIPHER.decrypt(&mut bytes),
|
CIPHER.decrypt(&mut bytes),
|
||||||
Err(crate::Error::InvalidInputLength)
|
Err(crate::cryptography::Error::InvalidInputLength)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use entity::master_pass::MasterPass;
|
use crate::entity::master_pass::MasterPass;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use rand::{rngs::OsRng, RngCore};
|
use rand::{rngs::OsRng, RngCore};
|
||||||
use scrypt::{scrypt, Params};
|
use scrypt::{scrypt, Params};
|
@ -2,15 +2,13 @@
|
|||||||
|
|
||||||
pub mod account;
|
pub mod account;
|
||||||
pub mod hashing;
|
pub mod hashing;
|
||||||
pub mod master_pass;
|
|
||||||
pub mod passwords;
|
pub mod passwords;
|
||||||
pub mod prelude;
|
|
||||||
|
|
||||||
/// Returns true if the field is valid
|
/// Returns true if the field is valid
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn validate_field(field: &str) -> bool {
|
pub fn validate_field(field: &str) -> bool {
|
||||||
if !(1..255).contains(&field.len()) {
|
if field.len() > 255 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
field
|
field
|
||||||
@ -24,7 +22,7 @@ pub enum Error {
|
|||||||
InvalidInputLength,
|
InvalidInputLength,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
ChaChaError(#[from] chacha20poly1305::Error),
|
ChaCha(#[from] chacha20poly1305::Error),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
InvalidUTF8(#[from] std::string::FromUtf8Error),
|
InvalidUTF8(#[from] std::string::FromUtf8Error),
|
@ -103,7 +103,7 @@ pub fn check_master_pass(password: &str) -> PasswordValidity {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::passwords::CHARS;
|
use super::CHARS;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn chars_must_be_ascii() {
|
fn chars_must_be_ascii() {
|
@ -14,7 +14,7 @@ pub struct Account {
|
|||||||
impl Account {
|
impl Account {
|
||||||
// Inserts the account into DB
|
// Inserts the account into DB
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn insert(&self, pool: &Pool) -> crate::Result<()> {
|
pub async fn insert(&self, pool: &Pool) -> super::Result<()> {
|
||||||
query!(
|
query!(
|
||||||
"INSERT INTO account VALUES (?, ?, ?, ?, ?)",
|
"INSERT INTO account VALUES (?, ?, ?, ?, ?)",
|
||||||
self.user_id,
|
self.user_id,
|
||||||
@ -30,7 +30,7 @@ impl Account {
|
|||||||
|
|
||||||
/// Gets all user's account from DB
|
/// Gets all user's account from DB
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_all(user_id: u64, pool: &Pool) -> impl Stream<Item = crate::Result<Self>> + '_ {
|
pub fn get_all(user_id: u64, pool: &Pool) -> impl Stream<Item = super::Result<Self>> + '_ {
|
||||||
query_as("SELECT * FROM account WHERE user_id = ?")
|
query_as("SELECT * FROM account WHERE user_id = ?")
|
||||||
.bind(user_id)
|
.bind(user_id)
|
||||||
.fetch(pool)
|
.fetch(pool)
|
||||||
@ -38,7 +38,7 @@ impl Account {
|
|||||||
|
|
||||||
/// Streams the names of the user accounts
|
/// Streams the names of the user accounts
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_names(user_id: u64, pool: &Pool) -> impl Stream<Item = crate::Result<String>> + '_ {
|
pub fn get_names(user_id: u64, pool: &Pool) -> impl Stream<Item = super::Result<String>> + '_ {
|
||||||
query_as::<_, (String,)>("SELECT name FROM account WHERE user_id = ? ORDER BY name")
|
query_as::<_, (String,)>("SELECT name FROM account WHERE user_id = ? ORDER BY name")
|
||||||
.bind(user_id)
|
.bind(user_id)
|
||||||
.fetch(pool)
|
.fetch(pool)
|
||||||
@ -47,7 +47,7 @@ impl Account {
|
|||||||
|
|
||||||
/// Checks if the account exists
|
/// Checks if the account exists
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn exists(user_id: u64, account_name: &str, pool: &Pool) -> crate::Result<bool> {
|
pub async fn exists(user_id: u64, account_name: &str, pool: &Pool) -> super::Result<bool> {
|
||||||
query_as::<_, (bool,)>(
|
query_as::<_, (bool,)>(
|
||||||
"SELECT EXISTS(SELECT * FROM account WHERE user_id = ? AND name = ? LIMIT 1) as value",
|
"SELECT EXISTS(SELECT * FROM account WHERE user_id = ? AND name = ? LIMIT 1) as value",
|
||||||
)
|
)
|
||||||
@ -60,7 +60,7 @@ impl Account {
|
|||||||
|
|
||||||
/// Gets the account from the DB
|
/// Gets the account from the DB
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn get(user_id: u64, account_name: &str, pool: &Pool) -> crate::Result<Option<Self>> {
|
pub async fn get(user_id: u64, account_name: &str, pool: &Pool) -> super::Result<Option<Self>> {
|
||||||
query_as("SELECT * FROM account WHERE user_id = ? AND name = ?")
|
query_as("SELECT * FROM account WHERE user_id = ? AND name = ?")
|
||||||
.bind(user_id)
|
.bind(user_id)
|
||||||
.bind(account_name)
|
.bind(account_name)
|
||||||
@ -70,7 +70,7 @@ impl Account {
|
|||||||
|
|
||||||
// Deletes the account from DB
|
// Deletes the account from DB
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn delete(user_id: u64, name: &str, pool: &Pool) -> crate::Result<()> {
|
pub async fn delete(user_id: u64, name: &str, pool: &Pool) -> super::Result<()> {
|
||||||
query!(
|
query!(
|
||||||
"DELETE FROM account WHERE user_id = ? AND name = ?",
|
"DELETE FROM account WHERE user_id = ? AND name = ?",
|
||||||
user_id,
|
user_id,
|
||||||
@ -86,7 +86,7 @@ impl Account {
|
|||||||
pub async fn delete_all(
|
pub async fn delete_all(
|
||||||
user_id: u64,
|
user_id: u64,
|
||||||
pool: impl Executor<'_, Database = MySql>,
|
pool: impl Executor<'_, Database = MySql>,
|
||||||
) -> crate::Result<()> {
|
) -> super::Result<()> {
|
||||||
query!("DELETE FROM account WHERE user_id = ?", user_id)
|
query!("DELETE FROM account WHERE user_id = ?", user_id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await
|
.await
|
||||||
@ -99,7 +99,7 @@ impl Account {
|
|||||||
user_id: u64,
|
user_id: u64,
|
||||||
hash: &[u8],
|
hash: &[u8],
|
||||||
pool: &Pool,
|
pool: &Pool,
|
||||||
) -> crate::Result<Option<String>> {
|
) -> super::Result<Option<String>> {
|
||||||
let hash = hex::encode(hash);
|
let hash = hex::encode(hash);
|
||||||
let name = query_as::<_, (String,)>(
|
let name = query_as::<_, (String,)>(
|
||||||
"SELECT `name` FROM `account` WHERE SHA2(`name`, 256) = ? AND `user_id` = ?;",
|
"SELECT `name` FROM `account` WHERE SHA2(`name`, 256) = ? AND `user_id` = ?;",
|
||||||
@ -113,7 +113,7 @@ impl Account {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn get_salt(user_id: u64, name: &str, pool: &Pool) -> crate::Result<Option<Vec<u8>>> {
|
pub async fn get_salt(user_id: u64, name: &str, pool: &Pool) -> super::Result<Option<Vec<u8>>> {
|
||||||
let salt =
|
let salt =
|
||||||
query_as::<_, (Vec<u8>,)>("SELECT salt FROM account WHERE user_id = ? AND name = ?")
|
query_as::<_, (Vec<u8>,)>("SELECT salt FROM account WHERE user_id = ? AND name = ?")
|
||||||
.bind(user_id)
|
.bind(user_id)
|
||||||
@ -130,7 +130,7 @@ impl Account {
|
|||||||
original_name: &str,
|
original_name: &str,
|
||||||
new_name: &str,
|
new_name: &str,
|
||||||
pool: &Pool,
|
pool: &Pool,
|
||||||
) -> crate::Result<bool> {
|
) -> super::Result<bool> {
|
||||||
query!(
|
query!(
|
||||||
"UPDATE account SET name = ? WHERE user_id = ? AND name = ?",
|
"UPDATE account SET name = ? WHERE user_id = ? AND name = ?",
|
||||||
new_name,
|
new_name,
|
||||||
@ -148,7 +148,7 @@ impl Account {
|
|||||||
name: &str,
|
name: &str,
|
||||||
login: Vec<u8>,
|
login: Vec<u8>,
|
||||||
pool: &Pool,
|
pool: &Pool,
|
||||||
) -> crate::Result<bool> {
|
) -> super::Result<bool> {
|
||||||
query!(
|
query!(
|
||||||
"UPDATE account SET enc_login = ? WHERE user_id = ? AND name = ?",
|
"UPDATE account SET enc_login = ? WHERE user_id = ? AND name = ?",
|
||||||
login,
|
login,
|
||||||
@ -166,7 +166,7 @@ impl Account {
|
|||||||
name: &str,
|
name: &str,
|
||||||
password: Vec<u8>,
|
password: Vec<u8>,
|
||||||
pool: &Pool,
|
pool: &Pool,
|
||||||
) -> crate::Result<bool> {
|
) -> super::Result<bool> {
|
||||||
query!(
|
query!(
|
||||||
"UPDATE account SET enc_password = ? WHERE user_id = ? AND name = ?",
|
"UPDATE account SET enc_password = ? WHERE user_id = ? AND name = ?",
|
||||||
password,
|
password,
|
@ -28,7 +28,7 @@ impl From<LocaleType> for u8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LocaleType {
|
impl LocaleType {
|
||||||
pub async fn get_from_db(user_id: u64, db: &Pool) -> crate::Result<Option<Self>> {
|
pub async fn get_from_db(user_id: u64, db: &Pool) -> super::Result<Option<Self>> {
|
||||||
let result: Option<(u8,)> = query_as("SELECT locale FROM master_pass WHERE user_id = ?")
|
let result: Option<(u8,)> = query_as("SELECT locale FROM master_pass WHERE user_id = ?")
|
||||||
.bind(user_id)
|
.bind(user_id)
|
||||||
.fetch_optional(db)
|
.fetch_optional(db)
|
||||||
@ -36,7 +36,7 @@ impl LocaleType {
|
|||||||
Ok(result.and_then(|val| val.0.try_into().ok()))
|
Ok(result.and_then(|val| val.0.try_into().ok()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update(self, user_id: u64, db: &Pool) -> crate::Result<bool> {
|
pub async fn update(self, user_id: u64, db: &Pool) -> super::Result<bool> {
|
||||||
let result: QueryResult = query!(
|
let result: QueryResult = query!(
|
||||||
"UPDATE master_pass SET locale = ? WHERE user_id = ?",
|
"UPDATE master_pass SET locale = ? WHERE user_id = ?",
|
||||||
u8::from(self),
|
u8::from(self),
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{locale::LocaleType, Pool};
|
use super::{locale::LocaleType, Pool};
|
||||||
use sqlx::{prelude::FromRow, query, query_as, Executor, MySql};
|
use sqlx::{prelude::FromRow, query, query_as, Executor, MySql};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, FromRow, Eq)]
|
#[derive(Clone, Debug, PartialEq, FromRow, Eq)]
|
||||||
@ -11,7 +11,7 @@ pub struct MasterPass {
|
|||||||
impl MasterPass {
|
impl MasterPass {
|
||||||
// Inserts the master password into DB
|
// Inserts the master password into DB
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn insert(&self, pool: &Pool, locale: LocaleType) -> crate::Result<()> {
|
pub async fn insert(&self, pool: &Pool, locale: LocaleType) -> super::Result<()> {
|
||||||
let locale: u8 = locale.into();
|
let locale: u8 = locale.into();
|
||||||
query!(
|
query!(
|
||||||
"INSERT INTO master_pass VALUES (?, ?, ?, ?)",
|
"INSERT INTO master_pass VALUES (?, ?, ?, ?)",
|
||||||
@ -27,7 +27,7 @@ impl MasterPass {
|
|||||||
|
|
||||||
/// Gets the master password from the database
|
/// Gets the master password from the database
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn get(user_id: u64, pool: &Pool) -> crate::Result<Option<Self>> {
|
pub async fn get(user_id: u64, pool: &Pool) -> super::Result<Option<Self>> {
|
||||||
query_as("SELECT user_id, salt, password_hash FROM master_pass WHERE user_id = ?")
|
query_as("SELECT user_id, salt, password_hash FROM master_pass WHERE user_id = ?")
|
||||||
.bind(user_id)
|
.bind(user_id)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
@ -36,7 +36,7 @@ impl MasterPass {
|
|||||||
|
|
||||||
/// Checks if the master password for the user exists
|
/// Checks if the master password for the user exists
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn exists(user_id: u64, pool: &Pool) -> crate::Result<bool> {
|
pub async fn exists(user_id: u64, pool: &Pool) -> super::Result<bool> {
|
||||||
query_as::<_, (bool,)>(
|
query_as::<_, (bool,)>(
|
||||||
"SELECT EXISTS(SELECT * FROM master_pass WHERE user_id = ? LIMIT 1) as value",
|
"SELECT EXISTS(SELECT * FROM master_pass WHERE user_id = ? LIMIT 1) as value",
|
||||||
)
|
)
|
||||||
@ -50,7 +50,7 @@ impl MasterPass {
|
|||||||
pub async fn remove(
|
pub async fn remove(
|
||||||
user_id: u64,
|
user_id: u64,
|
||||||
pool: impl Executor<'_, Database = MySql>,
|
pool: impl Executor<'_, Database = MySql>,
|
||||||
) -> crate::Result<()> {
|
) -> super::Result<()> {
|
||||||
query!("DELETE FROM master_pass WHERE user_id = ?", user_id)
|
query!("DELETE FROM master_pass WHERE user_id = ?", user_id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await
|
.await
|
@ -4,7 +4,6 @@
|
|||||||
pub mod account;
|
pub mod account;
|
||||||
pub mod locale;
|
pub mod locale;
|
||||||
pub mod master_pass;
|
pub mod master_pass;
|
||||||
pub mod prelude;
|
|
||||||
|
|
||||||
pub use sqlx::{mysql::MySqlPool as Pool, Result};
|
pub use sqlx::{mysql::MySqlPool as Pool, Result};
|
||||||
|
|
37
src/main.rs
37
src/main.rs
@ -1,7 +1,9 @@
|
|||||||
mod callbacks;
|
mod callbacks;
|
||||||
mod commands;
|
mod commands;
|
||||||
|
mod cryptography;
|
||||||
mod default;
|
mod default;
|
||||||
mod delete_mesage_handler;
|
mod delete_mesage_handler;
|
||||||
|
mod entity;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod filter_user_info;
|
mod filter_user_info;
|
||||||
mod locales;
|
mod locales;
|
||||||
@ -13,18 +15,25 @@ mod prelude;
|
|||||||
mod state;
|
mod state;
|
||||||
|
|
||||||
use anyhow::{Error, Result};
|
use anyhow::{Error, Result};
|
||||||
use dotenvy::dotenv;
|
|
||||||
use prelude::*;
|
|
||||||
use std::{env, sync::Arc};
|
|
||||||
use teloxide::{adaptors::throttle::Limits, dispatching::dialogue::InMemStorage, filter_command};
|
|
||||||
|
|
||||||
use crate::callbacks::CallbackCommand;
|
|
||||||
|
|
||||||
fn get_dispatcher(
|
fn get_dispatcher(
|
||||||
token: String,
|
token: String,
|
||||||
db: Pool,
|
db: prelude::Pool,
|
||||||
) -> Dispatcher<Throttle<Bot>, crate::Error, teloxide::dispatching::DefaultKey> {
|
) -> teloxide::prelude::Dispatcher<
|
||||||
use dptree::{case, deps};
|
teloxide::adaptors::Throttle<teloxide::Bot>,
|
||||||
|
crate::Error,
|
||||||
|
teloxide::dispatching::DefaultKey,
|
||||||
|
> {
|
||||||
|
use callbacks::CallbackCommand;
|
||||||
|
use commands::Command;
|
||||||
|
use state::State;
|
||||||
|
use teloxide::{
|
||||||
|
adaptors::throttle::Limits,
|
||||||
|
dispatching::dialogue::InMemStorage,
|
||||||
|
dptree::{case, deps},
|
||||||
|
filter_command,
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
let bot = Bot::new(token).throttle(Limits::default());
|
let bot = Bot::new(token).throttle(Limits::default());
|
||||||
|
|
||||||
@ -73,28 +82,30 @@ fn get_dispatcher(
|
|||||||
.branch(case![CallbackCommand::ChangeLocale(locale)].endpoint(callbacks::change_locale));
|
.branch(case![CallbackCommand::ChangeLocale(locale)].endpoint(callbacks::change_locale));
|
||||||
|
|
||||||
let handler = dptree::entry()
|
let handler = dptree::entry()
|
||||||
.map_async(Locale::from_update)
|
.map_async(locales::Locale::from_update)
|
||||||
.enter_dialogue::<Update, InMemStorage<State>, State>()
|
.enter_dialogue::<Update, InMemStorage<State>, State>()
|
||||||
.branch(message_handler)
|
.branch(message_handler)
|
||||||
.branch(callback_handler);
|
.branch(callback_handler);
|
||||||
|
|
||||||
Dispatcher::builder(bot, handler)
|
Dispatcher::builder(bot, handler)
|
||||||
.dependencies(deps![db, InMemStorage::<State>::new()])
|
.dependencies(deps![db, InMemStorage::<State>::new()])
|
||||||
.error_handler(Arc::from(errors::ErrorHandler))
|
.error_handler(std::sync::Arc::from(errors::ErrorHandler))
|
||||||
.enable_ctrlc_handler()
|
.enable_ctrlc_handler()
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
let _ = dotenv();
|
use std::env;
|
||||||
|
|
||||||
|
let _ = dotenvy::dotenv();
|
||||||
errors::init_logger();
|
errors::init_logger();
|
||||||
|
|
||||||
locales::LocaleStore::init();
|
locales::LocaleStore::init();
|
||||||
|
|
||||||
let token = env::var("TOKEN").expect("expected TOKEN in the enviroment");
|
let token = env::var("TOKEN").expect("expected TOKEN in the enviroment");
|
||||||
let database_url = env::var("DATABASE_URL").expect("expected DATABASE_URL in the enviroment");
|
let database_url = env::var("DATABASE_URL").expect("expected DATABASE_URL in the enviroment");
|
||||||
let pool = Pool::connect(&database_url).await?;
|
let pool = entity::Pool::connect(&database_url).await?;
|
||||||
|
|
||||||
entity::migrate(&pool).await?;
|
entity::migrate(&pool).await?;
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
pub use crate::{
|
pub(crate) use crate::cryptography::{
|
||||||
commands::Command,
|
self, account::Decrypted as DecryptedAccount, validate_field,
|
||||||
|
};
|
||||||
|
pub(crate) use crate::entity::{self, account::Account, master_pass::MasterPass, Pool};
|
||||||
|
pub(crate) use crate::{
|
||||||
errors::{handle_error, NoUserInfo},
|
errors::{handle_error, NoUserInfo},
|
||||||
first_handler, handler,
|
first_handler, handler,
|
||||||
locales::{Locale, LocaleRef},
|
locales::LocaleRef,
|
||||||
markups::*,
|
markups::*,
|
||||||
models::*,
|
models::*,
|
||||||
state::{Handler, MainDialogue, MessageIds, PackagedHandler, State},
|
state::{Handler, MainDialogue, MessageIds, PackagedHandler, State},
|
||||||
};
|
};
|
||||||
pub use cryptography::prelude::*;
|
pub(crate) use futures::{StreamExt, TryStreamExt};
|
||||||
pub use entity::{prelude::*, Pool};
|
pub(crate) use teloxide::{adaptors::Throttle, prelude::*};
|
||||||
pub use futures::{StreamExt, TryStreamExt};
|
|
||||||
pub use teloxide::{adaptors::Throttle, prelude::*};
|
|
||||||
|
Loading…
Reference in New Issue
Block a user