Switched from sea-orm to sqlx
This commit is contained in:
@ -10,4 +10,4 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
futures = "0.3"
|
||||
sea-orm = "0.12"
|
||||
sqlx = "0.7.2"
|
||||
|
@ -1,90 +1,96 @@
|
||||
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
|
||||
use super::Pool;
|
||||
use futures::{Stream, TryStreamExt};
|
||||
use sqlx::{query, query_as, Executor, FromRow, MySql};
|
||||
|
||||
use futures::Stream;
|
||||
use sea_orm::{entity::prelude::*, ActiveValue::Set, QueryOrder, QuerySelect, Statement};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "account")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, FromRow, Default)]
|
||||
pub struct Account {
|
||||
pub user_id: u64,
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub name: String,
|
||||
#[sea_orm(column_type = "Binary(BlobSize::Blob(Some(64)))")]
|
||||
pub salt: Vec<u8>,
|
||||
#[sea_orm(column_type = "VarBinary(256)")]
|
||||
pub enc_login: Vec<u8>,
|
||||
#[sea_orm(column_type = "VarBinary(256)")]
|
||||
pub enc_password: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {}
|
||||
impl Account {
|
||||
// Inserts the account into DB
|
||||
#[inline]
|
||||
pub async fn insert(&self, pool: &Pool) -> crate::Result<()> {
|
||||
query!(
|
||||
"INSERT INTO account VALUES (?, ?, ?, ?, ?)",
|
||||
self.user_id,
|
||||
self.name,
|
||||
self.salt,
|
||||
self.enc_login,
|
||||
self.enc_password
|
||||
)
|
||||
.execute(pool)
|
||||
.await
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
||||
impl Entity {
|
||||
/// Gets all user's account from DB
|
||||
#[inline]
|
||||
pub async fn get_all(
|
||||
user_id: u64,
|
||||
db: &DatabaseConnection,
|
||||
) -> crate::Result<impl Stream<Item = crate::Result<Model>> + '_> {
|
||||
Self::find()
|
||||
.filter(Column::UserId.eq(user_id))
|
||||
.stream(db)
|
||||
.await
|
||||
pub fn get_all(user_id: u64, pool: &Pool) -> impl Stream<Item = crate::Result<Self>> + '_ {
|
||||
query_as("SELECT * FROM account WHERE user_id = ?")
|
||||
.bind(user_id)
|
||||
.fetch(pool)
|
||||
}
|
||||
|
||||
/// Streams the names of the user accounts
|
||||
#[inline]
|
||||
pub async fn get_names(
|
||||
user_id: u64,
|
||||
db: &DatabaseConnection,
|
||||
) -> crate::Result<impl Stream<Item = crate::Result<String>> + '_> {
|
||||
Self::find()
|
||||
.select_only()
|
||||
.column(Column::Name)
|
||||
.filter(Column::UserId.eq(user_id))
|
||||
.order_by_asc(Column::Name)
|
||||
.into_tuple()
|
||||
.stream(db)
|
||||
.await
|
||||
pub fn get_names(user_id: u64, pool: &Pool) -> impl Stream<Item = crate::Result<String>> + '_ {
|
||||
query_as::<_, (String,)>("SELECT name FROM account WHERE user_id = ?")
|
||||
.bind(user_id)
|
||||
.fetch(pool)
|
||||
.map_ok(|(name,)| name)
|
||||
}
|
||||
|
||||
/// Checks if the account exists
|
||||
#[inline]
|
||||
pub async fn exists(
|
||||
user_id: u64,
|
||||
account_name: impl Into<String> + Send,
|
||||
db: &DatabaseConnection,
|
||||
) -> crate::Result<bool> {
|
||||
let count = Self::find_by_id((user_id, account_name.into()))
|
||||
.count(db)
|
||||
.await?;
|
||||
Ok(count != 0)
|
||||
pub async fn exists(user_id: u64, account_name: &str, pool: &Pool) -> crate::Result<bool> {
|
||||
query_as::<_, (bool,)>(
|
||||
"SELECT EXISTS(SELECT * FROM account WHERE user_id = ? AND name = ? LIMIT 1) as value",
|
||||
)
|
||||
.bind(user_id)
|
||||
.bind(account_name)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.map(|(exists,)| exists)
|
||||
}
|
||||
|
||||
/// Gets the account from the DB
|
||||
#[inline]
|
||||
pub async fn get(
|
||||
user_id: u64,
|
||||
account_name: impl Into<String> + Send,
|
||||
db: &DatabaseConnection,
|
||||
) -> crate::Result<Option<Model>> {
|
||||
Self::find_by_id((user_id, account_name.into()))
|
||||
.one(db)
|
||||
pub async fn get(user_id: u64, account_name: &str, pool: &Pool) -> crate::Result<Option<Self>> {
|
||||
query_as("SELECT * FROM account WHERE user_id = ? AND name = ?")
|
||||
.bind(user_id)
|
||||
.bind(account_name)
|
||||
.fetch_optional(pool)
|
||||
.await
|
||||
}
|
||||
|
||||
// Deletes the account from DB
|
||||
#[inline]
|
||||
pub async fn delete(user_id: u64, name: &str, pool: &Pool) -> crate::Result<()> {
|
||||
query!(
|
||||
"DELETE FROM account WHERE user_id = ? AND name = ?",
|
||||
user_id,
|
||||
name
|
||||
)
|
||||
.execute(pool)
|
||||
.await
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
/// Deletes all the user's accounts from DB
|
||||
#[inline]
|
||||
pub async fn delete_all(user_id: u64, db: &impl ConnectionTrait) -> crate::Result<()> {
|
||||
Self::delete_many()
|
||||
.filter(Column::UserId.eq(user_id))
|
||||
.exec(db)
|
||||
.await?;
|
||||
Ok(())
|
||||
pub async fn delete_all(
|
||||
user_id: u64,
|
||||
pool: impl Executor<'_, Database = MySql>,
|
||||
) -> crate::Result<()> {
|
||||
query!("DELETE FROM account WHERE user_id = ?", user_id)
|
||||
.execute(pool)
|
||||
.await
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
/// Gets a name by a hex of a SHA256 hash of the name
|
||||
@ -92,49 +98,82 @@ impl Entity {
|
||||
pub async fn get_name_by_hash(
|
||||
user_id: u64,
|
||||
hash: String,
|
||||
db: &DatabaseConnection,
|
||||
pool: &Pool,
|
||||
) -> crate::Result<Option<String>> {
|
||||
db.query_one(Statement::from_sql_and_values(
|
||||
sea_orm::DatabaseBackend::MySql,
|
||||
let name = query_as::<_, (String,)>(
|
||||
"SELECT `name` FROM `account` WHERE SHA2(`name`, 256) = ? AND `user_id` = ?;",
|
||||
[hash.into(), user_id.into()],
|
||||
))
|
||||
.await?
|
||||
.map(|result| result.try_get_by_index(0))
|
||||
.transpose()
|
||||
)
|
||||
.bind(hash)
|
||||
.bind(user_id)
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
|
||||
Ok(name.map(|(name,)| name))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub async fn get_salt(
|
||||
user_id: u64,
|
||||
name: String,
|
||||
db: &DatabaseConnection,
|
||||
) -> crate::Result<Option<Vec<u8>>> {
|
||||
Self::find_by_id((user_id, name))
|
||||
.select_only()
|
||||
.column(Column::Salt)
|
||||
.into_tuple()
|
||||
.one(db)
|
||||
.await
|
||||
pub async fn get_salt(user_id: u64, name: &str, pool: &Pool) -> crate::Result<Option<Vec<u8>>> {
|
||||
let salt =
|
||||
query_as::<_, (Vec<u8>,)>("SELECT salt FROM account WHERE user_id = ? AND name = ?")
|
||||
.bind(user_id)
|
||||
.bind(name)
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
|
||||
Ok(salt.map(|(salt,)| salt))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub async fn update_name(
|
||||
user_id: u64,
|
||||
original_name: String,
|
||||
new_name: String,
|
||||
db: &DatabaseConnection,
|
||||
original_name: &str,
|
||||
new_name: &str,
|
||||
pool: &Pool,
|
||||
) -> crate::Result<()> {
|
||||
Self::update_many()
|
||||
.set(ActiveModel {
|
||||
name: Set(new_name),
|
||||
..Default::default()
|
||||
})
|
||||
.filter(Column::UserId.eq(user_id))
|
||||
.filter(Column::Name.eq(original_name))
|
||||
.exec(db)
|
||||
.await?;
|
||||
query!(
|
||||
"UPDATE account SET name = ? WHERE user_id = ? AND name = ?",
|
||||
new_name,
|
||||
user_id,
|
||||
original_name
|
||||
)
|
||||
.execute(pool)
|
||||
.await
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
Ok(())
|
||||
#[inline]
|
||||
pub async fn update_login(
|
||||
user_id: u64,
|
||||
name: &str,
|
||||
login: Vec<u8>,
|
||||
pool: &Pool,
|
||||
) -> crate::Result<()> {
|
||||
query!(
|
||||
"UPDATE account SET enc_login = ? WHERE user_id = ? AND name = ?",
|
||||
login,
|
||||
user_id,
|
||||
name
|
||||
)
|
||||
.execute(pool)
|
||||
.await
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub async fn update_password(
|
||||
user_id: u64,
|
||||
name: &str,
|
||||
password: Vec<u8>,
|
||||
pool: &Pool,
|
||||
) -> crate::Result<()> {
|
||||
query!(
|
||||
"UPDATE account SET enc_password = ? WHERE user_id = ? AND name = ?",
|
||||
password,
|
||||
user_id,
|
||||
name
|
||||
)
|
||||
.execute(pool)
|
||||
.await
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,6 @@ pub mod account;
|
||||
pub mod master_pass;
|
||||
pub mod prelude;
|
||||
|
||||
use sea_orm::DbErr;
|
||||
pub use sqlx::Result;
|
||||
|
||||
type Result<T> = std::result::Result<T, DbErr>;
|
||||
pub type Pool = sqlx::mysql::MySqlPool;
|
||||
|
@ -1,40 +1,57 @@
|
||||
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
|
||||
use super::Pool;
|
||||
use sqlx::{prelude::FromRow, query, query_as, Executor, MySql};
|
||||
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "master_pass")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
#[derive(Clone, Debug, PartialEq, FromRow, Eq)]
|
||||
pub struct MasterPass {
|
||||
pub user_id: u64,
|
||||
#[sea_orm(column_type = "Binary(BlobSize::Blob(Some(64)))")]
|
||||
pub salt: Vec<u8>,
|
||||
#[sea_orm(column_type = "Binary(BlobSize::Blob(Some(64)))")]
|
||||
pub password_hash: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {}
|
||||
impl MasterPass {
|
||||
// Inserts the master password into DB
|
||||
#[inline]
|
||||
pub async fn insert(&self, pool: &Pool) -> crate::Result<()> {
|
||||
query!(
|
||||
"INSERT INTO master_pass VALUES (?, ?, ?)",
|
||||
self.user_id,
|
||||
self.salt,
|
||||
self.password_hash
|
||||
)
|
||||
.execute(pool)
|
||||
.await
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
||||
impl Entity {
|
||||
/// Gets the master password from the database
|
||||
#[inline]
|
||||
pub async fn get(user_id: u64, db: &DatabaseConnection) -> crate::Result<Option<Model>> {
|
||||
Self::find_by_id(user_id).one(db).await
|
||||
pub async fn get(user_id: u64, pool: &Pool) -> crate::Result<Option<Self>> {
|
||||
query_as("SELECT * FROM master_pass WHERE user_id = ?")
|
||||
.bind(user_id)
|
||||
.fetch_optional(pool)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Checks if the master password for the user exists
|
||||
#[inline]
|
||||
pub async fn exists(user_id: u64, db: &DatabaseConnection) -> Result<bool, DbErr> {
|
||||
let count = Self::find_by_id(user_id).count(db).await?;
|
||||
Ok(count != 0)
|
||||
pub async fn exists(user_id: u64, pool: &Pool) -> crate::Result<bool> {
|
||||
query_as::<_, (bool,)>(
|
||||
"SELECT EXISTS(SELECT * FROM master_pass WHERE user_id = ? LIMIT 1) as value",
|
||||
)
|
||||
.bind(user_id)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.map(|(exists,)| exists)
|
||||
}
|
||||
|
||||
/// Removes a master password of the user from the database
|
||||
pub async fn remove(user_id: u64, db: &impl ConnectionTrait) -> Result<(), DbErr> {
|
||||
Self::delete_by_id(user_id).exec(db).await?;
|
||||
Ok(())
|
||||
pub async fn remove(
|
||||
user_id: u64,
|
||||
pool: impl Executor<'_, Database = MySql>,
|
||||
) -> crate::Result<()> {
|
||||
query!("DELETE FROM master_pass WHERE user_id = ?", user_id)
|
||||
.execute(pool)
|
||||
.await
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,2 @@
|
||||
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
|
||||
|
||||
pub use crate::account::{self, Entity as Account};
|
||||
pub use crate::master_pass::{self, Entity as MasterPass};
|
||||
pub use crate::account::Account;
|
||||
pub use crate::master_pass::MasterPass;
|
||||
|
Reference in New Issue
Block a user