Updated models and entities

This commit is contained in:
StNicolay 2023-05-15 19:09:15 +03:00
parent 31c52a7771
commit 02d090dd6a
Signed by: StNicolay
GPG Key ID: 9693D04DCD962B0D
7 changed files with 34 additions and 18 deletions

View File

@ -1,5 +1,3 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2
use chacha20poly1305::{aead::Aead, AeadCore, ChaCha20Poly1305, KeyInit};
use futures::{Stream, TryStreamExt};
use pbkdf2::pbkdf2_hmac_array;
@ -33,6 +31,7 @@ struct Cipher {
impl Cipher {
/// Creates a new cipher from a master password and the salt
#[inline]
fn new(password: &[u8], salt: &[u8]) -> Self {
let key = pbkdf2_hmac_array::<Sha256, 32>(password, salt, 480000);
@ -42,6 +41,7 @@ impl Cipher {
}
/// Encrypts the value with the current cipher. The 12 byte nonce is appended to the result
#[inline]
pub fn encrypt(&self, value: &[u8]) -> crate::Result<Vec<u8>> {
let nonce = ChaCha20Poly1305::generate_nonce(&mut OsRng);
let mut result = self.chacha.encrypt(&nonce, value)?;
@ -50,6 +50,7 @@ impl Cipher {
}
/// Decrypts the value with the current cipher. The 12 byte nonce is expected to be at the end of the value
#[inline]
fn decrypt(&self, value: &[u8]) -> crate::Result<Vec<u8>> {
let (data, nonce) = value.split_at(value.len() - 12);
self.chacha.decrypt(nonce.into(), data).map_err(Into::into)
@ -58,6 +59,7 @@ impl Cipher {
impl ActiveModel {
/// Encryptes the provided data by the master password and creates the ActiveModel with all fields set to Set variant
#[inline]
pub fn from_unencrypted(
user_id: u64,
name: String,
@ -82,6 +84,7 @@ impl ActiveModel {
impl Model {
/// Returns the decrypted login and password of the account
#[inline]
pub fn decrypt(&self, master_pass: &str) -> crate::Result<(String, String)> {
let cipher = Cipher::new(master_pass.as_bytes(), &self.salt);
let login = String::from_utf8(cipher.decrypt(&self.enc_login)?)?;
@ -92,6 +95,7 @@ impl Model {
impl Entity {
/// Gets all user's account from DB
#[inline]
pub async fn get_all(
user_id: u64,
db: &DatabaseConnection,
@ -104,6 +108,7 @@ impl Entity {
}
/// Gets a list of account names of a user
#[inline]
pub async fn get_names(
user_id: u64,
db: &DatabaseConnection,
@ -121,6 +126,7 @@ impl Entity {
}
/// Checks if the account exists
#[inline]
pub async fn exists(
user_id: u64,
account_name: impl Into<String>,
@ -136,6 +142,7 @@ impl Entity {
}
/// Gets the account from the DB
#[inline]
pub async fn get(
user_id: u64,
account_name: impl Into<String>,
@ -148,6 +155,7 @@ impl Entity {
}
/// Deletes all the user's accounts from DB
#[inline]
pub async fn delete_all(user_id: u64, db: &DatabaseConnection) -> crate::Result<()> {
Self::delete_many()
.filter(Column::UserId.eq(user_id))

View File

@ -1,5 +1,3 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2
use rand::{rngs::OsRng, RngCore};
use scrypt::{scrypt, Params};
use sea_orm::{entity::prelude::*, ActiveValue::Set, QuerySelect};
@ -22,6 +20,7 @@ pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
/// Hashes the password with Scrypt with the given salt
#[inline]
fn hash_password(password: &[u8], salt: &[u8]) -> crate::Result<Vec<u8>> {
let params = Params::new(14, Params::RECOMMENDED_R, Params::RECOMMENDED_P, 64)?;
let mut password_hash = vec![0; 64];
@ -31,6 +30,7 @@ fn hash_password(password: &[u8], salt: &[u8]) -> crate::Result<Vec<u8>> {
impl ActiveModel {
/// Hashes the password and creates an ActiveModel with all fields set to Set variant
#[inline]
pub fn from_unencrypted(user_id: u64, password: &str) -> crate::Result<Self> {
let mut salt = vec![0; 64];
OsRng.fill_bytes(&mut salt);
@ -45,6 +45,7 @@ impl ActiveModel {
impl Entity {
/// Verifies the provided master password against the one from DB
#[inline]
pub async fn verify_master_pass(
user_id: u64,
master_pass: String,
@ -61,6 +62,7 @@ impl Entity {
}
/// Checks if the master password for the user exists
#[inline]
pub async fn exists(user_id: u64, db: &DatabaseConnection) -> crate::Result<bool> {
let id = Self::find_by_id(user_id)
.select_only()

View File

@ -1,6 +1,5 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2
pub mod prelude;
//! Entities to work with the database
pub mod account;
pub mod master_pass;
pub mod prelude;

View File

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2
pub use super::account::Entity as Account;
pub use super::master_pass::Entity as MasterPass;
pub use super::account::{self, Entity as Account};
pub use super::master_pass::{self, Entity as MasterPass};

View File

@ -1,5 +1,5 @@
use crate::{
entity::{master_pass, prelude::*},
entity::prelude::*,
errors::NoUserInfo,
handlers::{markups::deletion_markup, utils::package_handler, MainDialogue, State},
};

View File

@ -5,12 +5,11 @@ mod models;
use anyhow::{Error, Result};
use dotenv::dotenv;
use futures::future::BoxFuture as PinnedFuture;
use handlers::get_dispatcher;
use migration::{Migrator, MigratorTrait};
use sea_orm::Database;
use std::{env, future::Future, pin::Pin};
type PinnedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
use std::env;
#[tokio::main]
async fn main() -> Result<()> {

View File

@ -1,4 +1,6 @@
use crate::entity::account;
//! Models to export and import the accounts
use crate::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
@ -10,24 +12,30 @@ pub struct DecryptedAccount {
impl DecryptedAccount {
/// Constructs DecryptedAccount by decrypting the provided account
#[inline]
pub fn from_account(account: account::Model, master_pass: &str) -> crate::Result<Self> {
let name = account.name.clone();
let (login, password) = account.decrypt(master_pass)?;
Ok(Self {
name,
name: account.name,
login,
password,
})
}
/// Constructs ActiveModel with eath field Set by encrypting `self`
#[inline]
pub fn into_account(
self,
user_id: u64,
master_pass: &str,
) -> crate::Result<account::ActiveModel> {
let (name, login, password) = (self.name, self.login, self.password);
account::ActiveModel::from_unencrypted(user_id, name, &login, &password, master_pass)
account::ActiveModel::from_unencrypted(
user_id,
self.name,
&self.login,
&self.password,
master_pass,
)
}
/// Returns true if the account's fields are valid