1
0
Fork 0
mirror of https://github.com/dani-garcia/vaultwarden.git synced 2025-06-19 09:50:09 +00:00

Update to diesel2

This commit is contained in:
Daniel García 2022-05-20 23:39:47 +02:00
parent b878495d64
commit 8409b31d6b
No known key found for this signature in database
GPG key ID: FC8A7D14C3CD543A
36 changed files with 1267 additions and 1270 deletions

View file

@ -365,7 +365,7 @@ pub mod models;
/// Creates a back-up of the sqlite database
/// MySQL/MariaDB and PostgreSQL are not supported.
pub async fn backup_database(conn: &DbConn) -> Result<(), Error> {
pub async fn backup_database(conn: &mut DbConn) -> Result<(), Error> {
db_run! {@raw conn:
postgresql, mysql {
let _ = conn;
@ -383,15 +383,19 @@ pub async fn backup_database(conn: &DbConn) -> Result<(), Error> {
}
/// Get the SQL Server version
pub async fn get_sql_server_version(conn: &DbConn) -> String {
pub async fn get_sql_server_version(conn: &mut DbConn) -> String {
db_run! {@raw conn:
postgresql, mysql {
no_arg_sql_function!(version, diesel::sql_types::Text);
diesel::select(version).get_result::<String>(conn).unwrap_or_else(|_| "Unknown".to_string())
sql_function!{
fn version() -> diesel::sql_types::Text;
}
diesel::select(version()).get_result::<String>(conn).unwrap_or_else(|_| "Unknown".to_string())
}
sqlite {
no_arg_sql_function!(sqlite_version, diesel::sql_types::Text);
diesel::select(sqlite_version).get_result::<String>(conn).unwrap_or_else(|_| "Unknown".to_string())
sql_function!{
fn sqlite_version() -> diesel::sql_types::Text;
}
diesel::select(sqlite_version()).get_result::<String>(conn).unwrap_or_else(|_| "Unknown".to_string())
}
}
}
@ -416,7 +420,8 @@ impl<'r> FromRequest<'r> for DbConn {
// https://docs.rs/diesel_migrations/*/diesel_migrations/macro.embed_migrations.html
#[cfg(sqlite)]
mod sqlite_migrations {
embed_migrations!("migrations/sqlite");
use diesel_migrations::{EmbeddedMigrations, MigrationHarness};
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations/sqlite");
pub fn run_migrations() -> Result<(), super::Error> {
// Make sure the directory exists
@ -432,52 +437,54 @@ mod sqlite_migrations {
use diesel::{Connection, RunQueryDsl};
// Make sure the database is up to date (create if it doesn't exist, or run the migrations)
let connection = diesel::sqlite::SqliteConnection::establish(&crate::CONFIG.database_url())?;
let mut connection = diesel::sqlite::SqliteConnection::establish(&crate::CONFIG.database_url())?;
// Disable Foreign Key Checks during migration
// Scoped to a connection.
diesel::sql_query("PRAGMA foreign_keys = OFF")
.execute(&connection)
.execute(&mut connection)
.expect("Failed to disable Foreign Key Checks during migrations");
// Turn on WAL in SQLite
if crate::CONFIG.enable_db_wal() {
diesel::sql_query("PRAGMA journal_mode=wal").execute(&connection).expect("Failed to turn on WAL");
diesel::sql_query("PRAGMA journal_mode=wal").execute(&mut connection).expect("Failed to turn on WAL");
}
embedded_migrations::run_with_output(&connection, &mut std::io::stdout())?;
connection.run_pending_migrations(MIGRATIONS).expect("Error running migrations");
Ok(())
}
}
#[cfg(mysql)]
mod mysql_migrations {
embed_migrations!("migrations/mysql");
use diesel_migrations::{EmbeddedMigrations, MigrationHarness};
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations/mysql");
pub fn run_migrations() -> Result<(), super::Error> {
use diesel::{Connection, RunQueryDsl};
// Make sure the database is up to date (create if it doesn't exist, or run the migrations)
let connection = diesel::mysql::MysqlConnection::establish(&crate::CONFIG.database_url())?;
let mut connection = diesel::mysql::MysqlConnection::establish(&crate::CONFIG.database_url())?;
// Disable Foreign Key Checks during migration
// Scoped to a connection/session.
diesel::sql_query("SET FOREIGN_KEY_CHECKS = 0")
.execute(&connection)
.execute(&mut connection)
.expect("Failed to disable Foreign Key Checks during migrations");
embedded_migrations::run_with_output(&connection, &mut std::io::stdout())?;
connection.run_pending_migrations(MIGRATIONS).expect("Error running migrations");
Ok(())
}
}
#[cfg(postgresql)]
mod postgresql_migrations {
embed_migrations!("migrations/postgresql");
use diesel_migrations::{EmbeddedMigrations, MigrationHarness};
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations/postgresql");
pub fn run_migrations() -> Result<(), super::Error> {
use diesel::{Connection, RunQueryDsl};
// Make sure the database is up to date (create if it doesn't exist, or run the migrations)
let connection = diesel::pg::PgConnection::establish(&crate::CONFIG.database_url())?;
let mut connection = diesel::pg::PgConnection::establish(&crate::CONFIG.database_url())?;
// Disable Foreign Key Checks during migration
// FIXME: Per https://www.postgresql.org/docs/12/sql-set-constraints.html,
@ -487,10 +494,10 @@ mod postgresql_migrations {
// Migrations that need to disable foreign key checks should run this
// from within the migration script itself.
diesel::sql_query("SET CONSTRAINTS ALL DEFERRED")
.execute(&connection)
.execute(&mut connection)
.expect("Failed to disable Foreign Key Checks during migrations");
embedded_migrations::run_with_output(&connection, &mut std::io::stdout())?;
connection.run_pending_migrations(MIGRATIONS).expect("Error running migrations");
Ok(())
}
}

View file

@ -6,9 +6,9 @@ use crate::CONFIG;
db_object! {
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "attachments"]
#[changeset_options(treat_none_as_null="true")]
#[primary_key(id)]
#[diesel(table_name = attachments)]
#[diesel(treat_none_as_null = true)]
#[diesel(primary_key(id))]
pub struct Attachment {
pub id: String,
pub cipher_uuid: String,
@ -58,7 +58,7 @@ use crate::error::MapResult;
/// Database methods
impl Attachment {
pub async fn save(&self, conn: &DbConn) -> EmptyResult {
pub async fn save(&self, conn: &mut DbConn) -> EmptyResult {
db_run! { conn:
sqlite, mysql {
match diesel::replace_into(attachments::table)
@ -90,7 +90,7 @@ impl Attachment {
}
}
pub async fn delete(&self, conn: &DbConn) -> EmptyResult {
pub async fn delete(&self, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
crate::util::retry(
|| diesel::delete(attachments::table.filter(attachments::id.eq(&self.id))).execute(conn),
@ -114,14 +114,14 @@ impl Attachment {
}}
}
pub async fn delete_all_by_cipher(cipher_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_cipher(cipher_uuid: &str, conn: &mut DbConn) -> EmptyResult {
for attachment in Attachment::find_by_cipher(cipher_uuid, conn).await {
attachment.delete(conn).await?;
}
Ok(())
}
pub async fn find_by_id(id: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_id(id: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
attachments::table
.filter(attachments::id.eq(id.to_lowercase()))
@ -131,7 +131,7 @@ impl Attachment {
}}
}
pub async fn find_by_cipher(cipher_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_cipher(cipher_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
attachments::table
.filter(attachments::cipher_uuid.eq(cipher_uuid))
@ -141,7 +141,7 @@ impl Attachment {
}}
}
pub async fn size_by_user(user_uuid: &str, conn: &DbConn) -> i64 {
pub async fn size_by_user(user_uuid: &str, conn: &mut DbConn) -> i64 {
db_run! { conn: {
let result: Option<i64> = attachments::table
.left_join(ciphers::table.on(ciphers::uuid.eq(attachments::cipher_uuid)))
@ -153,7 +153,7 @@ impl Attachment {
}}
}
pub async fn count_by_user(user_uuid: &str, conn: &DbConn) -> i64 {
pub async fn count_by_user(user_uuid: &str, conn: &mut DbConn) -> i64 {
db_run! { conn: {
attachments::table
.left_join(ciphers::table.on(ciphers::uuid.eq(attachments::cipher_uuid)))
@ -164,7 +164,7 @@ impl Attachment {
}}
}
pub async fn size_by_org(org_uuid: &str, conn: &DbConn) -> i64 {
pub async fn size_by_org(org_uuid: &str, conn: &mut DbConn) -> i64 {
db_run! { conn: {
let result: Option<i64> = attachments::table
.left_join(ciphers::table.on(ciphers::uuid.eq(attachments::cipher_uuid)))
@ -176,7 +176,7 @@ impl Attachment {
}}
}
pub async fn count_by_org(org_uuid: &str, conn: &DbConn) -> i64 {
pub async fn count_by_org(org_uuid: &str, conn: &mut DbConn) -> i64 {
db_run! { conn: {
attachments::table
.left_join(ciphers::table.on(ciphers::uuid.eq(attachments::cipher_uuid)))
@ -187,7 +187,7 @@ impl Attachment {
}}
}
pub async fn find_all_by_ciphers(cipher_uuids: &Vec<String>, conn: &DbConn) -> Vec<Self> {
pub async fn find_all_by_ciphers(cipher_uuids: &Vec<String>, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
attachments::table
.filter(attachments::cipher_uuid.eq_any(cipher_uuids))

View file

@ -12,9 +12,9 @@ use std::borrow::Cow;
db_object! {
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "ciphers"]
#[changeset_options(treat_none_as_null="true")]
#[primary_key(uuid)]
#[diesel(table_name = ciphers)]
#[diesel(treat_none_as_null = true)]
#[diesel(primary_key(uuid))]
pub struct Cipher {
pub uuid: String,
pub created_at: NaiveDateTime,
@ -87,7 +87,7 @@ impl Cipher {
host: &str,
user_uuid: &str,
cipher_sync_data: Option<&CipherSyncData>,
conn: &DbConn,
conn: &mut DbConn,
) -> Value {
use crate::util::format_date;
@ -148,7 +148,7 @@ impl Cipher {
Cow::from(Vec::with_capacity(0))
}
} else {
Cow::from(self.get_collections(user_uuid, conn).await)
Cow::from(self.get_collections(user_uuid.to_string(), conn).await)
};
// There are three types of cipher response models in upstream
@ -210,7 +210,7 @@ impl Cipher {
json_object
}
pub async fn update_users_revision(&self, conn: &DbConn) -> Vec<String> {
pub async fn update_users_revision(&self, conn: &mut DbConn) -> Vec<String> {
let mut user_uuids = Vec::new();
match self.user_uuid {
Some(ref user_uuid) => {
@ -230,7 +230,7 @@ impl Cipher {
user_uuids
}
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
pub async fn save(&mut self, conn: &mut DbConn) -> EmptyResult {
self.update_users_revision(conn).await;
self.updated_at = Utc::now().naive_utc();
@ -265,7 +265,7 @@ impl Cipher {
}
}
pub async fn delete(&self, conn: &DbConn) -> EmptyResult {
pub async fn delete(&self, conn: &mut DbConn) -> EmptyResult {
self.update_users_revision(conn).await;
FolderCipher::delete_all_by_cipher(&self.uuid, conn).await?;
@ -280,7 +280,7 @@ impl Cipher {
}}
}
pub async fn delete_all_by_organization(org_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_organization(org_uuid: &str, conn: &mut DbConn) -> EmptyResult {
// TODO: Optimize this by executing a DELETE directly on the database, instead of first fetching.
for cipher in Self::find_by_org(org_uuid, conn).await {
cipher.delete(conn).await?;
@ -288,7 +288,7 @@ impl Cipher {
Ok(())
}
pub async fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_user(user_uuid: &str, conn: &mut DbConn) -> EmptyResult {
for cipher in Self::find_owned_by_user(user_uuid, conn).await {
cipher.delete(conn).await?;
}
@ -296,7 +296,7 @@ impl Cipher {
}
/// Purge all ciphers that are old enough to be auto-deleted.
pub async fn purge_trash(conn: &DbConn) {
pub async fn purge_trash(conn: &mut DbConn) {
if let Some(auto_delete_days) = CONFIG.trash_auto_delete_days() {
let now = Utc::now().naive_utc();
let dt = now - Duration::days(auto_delete_days);
@ -306,7 +306,7 @@ impl Cipher {
}
}
pub async fn move_to_folder(&self, folder_uuid: Option<String>, user_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn move_to_folder(&self, folder_uuid: Option<String>, user_uuid: &str, conn: &mut DbConn) -> EmptyResult {
User::update_uuid_revision(user_uuid, conn).await;
match (self.get_folder_uuid(user_uuid, conn).await, folder_uuid) {
@ -343,7 +343,7 @@ impl Cipher {
&self,
user_uuid: &str,
cipher_sync_data: Option<&CipherSyncData>,
conn: &DbConn,
conn: &mut DbConn,
) -> bool {
if let Some(ref org_uuid) = self.organization_uuid {
if let Some(cipher_sync_data) = cipher_sync_data {
@ -362,7 +362,7 @@ impl Cipher {
&self,
user_uuid: &str,
cipher_sync_data: Option<&CipherSyncData>,
conn: &DbConn,
conn: &mut DbConn,
) -> bool {
if let Some(ref org_uuid) = self.organization_uuid {
if let Some(cipher_sync_data) = cipher_sync_data {
@ -383,7 +383,7 @@ impl Cipher {
&self,
user_uuid: &str,
cipher_sync_data: Option<&CipherSyncData>,
conn: &DbConn,
conn: &mut DbConn,
) -> Option<(bool, bool)> {
// Check whether this cipher is directly owned by the user, or is in
// a collection that the user has full access to. If so, there are no
@ -441,7 +441,7 @@ impl Cipher {
Some((read_only, hide_passwords))
}
async fn get_user_collections_access_flags(&self, user_uuid: &str, conn: &DbConn) -> Vec<(bool, bool)> {
async fn get_user_collections_access_flags(&self, user_uuid: &str, conn: &mut DbConn) -> Vec<(bool, bool)> {
db_run! {conn: {
// Check whether this cipher is in any collections accessible to the
// user. If so, retrieve the access flags for each collection.
@ -458,7 +458,7 @@ impl Cipher {
}}
}
async fn get_group_collections_access_flags(&self, user_uuid: &str, conn: &DbConn) -> Vec<(bool, bool)> {
async fn get_group_collections_access_flags(&self, user_uuid: &str, conn: &mut DbConn) -> Vec<(bool, bool)> {
db_run! {conn: {
ciphers::table
.filter(ciphers::uuid.eq(&self.uuid))
@ -481,31 +481,31 @@ impl Cipher {
}}
}
pub async fn is_write_accessible_to_user(&self, user_uuid: &str, conn: &DbConn) -> bool {
pub async fn is_write_accessible_to_user(&self, user_uuid: &str, conn: &mut DbConn) -> bool {
match self.get_access_restrictions(user_uuid, None, conn).await {
Some((read_only, _hide_passwords)) => !read_only,
None => false,
}
}
pub async fn is_accessible_to_user(&self, user_uuid: &str, conn: &DbConn) -> bool {
pub async fn is_accessible_to_user(&self, user_uuid: &str, conn: &mut DbConn) -> bool {
self.get_access_restrictions(user_uuid, None, conn).await.is_some()
}
// Returns whether this cipher is a favorite of the specified user.
pub async fn is_favorite(&self, user_uuid: &str, conn: &DbConn) -> bool {
pub async fn is_favorite(&self, user_uuid: &str, conn: &mut DbConn) -> bool {
Favorite::is_favorite(&self.uuid, user_uuid, conn).await
}
// Sets whether this cipher is a favorite of the specified user.
pub async fn set_favorite(&self, favorite: Option<bool>, user_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn set_favorite(&self, favorite: Option<bool>, user_uuid: &str, conn: &mut DbConn) -> EmptyResult {
match favorite {
None => Ok(()), // No change requested.
Some(status) => Favorite::set_favorite(status, &self.uuid, user_uuid, conn).await,
}
}
pub async fn get_folder_uuid(&self, user_uuid: &str, conn: &DbConn) -> Option<String> {
pub async fn get_folder_uuid(&self, user_uuid: &str, conn: &mut DbConn) -> Option<String> {
db_run! {conn: {
folders_ciphers::table
.inner_join(folders::table)
@ -517,7 +517,7 @@ impl Cipher {
}}
}
pub async fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! {conn: {
ciphers::table
.filter(ciphers::uuid.eq(uuid))
@ -539,7 +539,7 @@ impl Cipher {
// true, then the non-interesting ciphers will not be returned. As a
// result, those ciphers will not appear in "My Vault" for the org
// owner/admin, but they can still be accessed via the org vault view.
pub async fn find_by_user(user_uuid: &str, visible_only: bool, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_user(user_uuid: &str, visible_only: bool, conn: &mut DbConn) -> Vec<Self> {
db_run! {conn: {
let mut query = ciphers::table
.left_join(ciphers_collections::table.on(
@ -587,12 +587,12 @@ impl Cipher {
}
// Find all ciphers visible to the specified user.
pub async fn find_by_user_visible(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_user_visible(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
Self::find_by_user(user_uuid, true, conn).await
}
// Find all ciphers directly owned by the specified user.
pub async fn find_owned_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_owned_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! {conn: {
ciphers::table
.filter(
@ -603,7 +603,7 @@ impl Cipher {
}}
}
pub async fn count_owned_by_user(user_uuid: &str, conn: &DbConn) -> i64 {
pub async fn count_owned_by_user(user_uuid: &str, conn: &mut DbConn) -> i64 {
db_run! {conn: {
ciphers::table
.filter(ciphers::user_uuid.eq(user_uuid))
@ -614,7 +614,7 @@ impl Cipher {
}}
}
pub async fn find_by_org(org_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_org(org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! {conn: {
ciphers::table
.filter(ciphers::organization_uuid.eq(org_uuid))
@ -622,7 +622,7 @@ impl Cipher {
}}
}
pub async fn count_by_org(org_uuid: &str, conn: &DbConn) -> i64 {
pub async fn count_by_org(org_uuid: &str, conn: &mut DbConn) -> i64 {
db_run! {conn: {
ciphers::table
.filter(ciphers::organization_uuid.eq(org_uuid))
@ -633,7 +633,7 @@ impl Cipher {
}}
}
pub async fn find_by_folder(folder_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_folder(folder_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! {conn: {
folders_ciphers::table.inner_join(ciphers::table)
.filter(folders_ciphers::folder_uuid.eq(folder_uuid))
@ -643,7 +643,7 @@ impl Cipher {
}
/// Find all ciphers that were deleted before the specified datetime.
pub async fn find_deleted_before(dt: &NaiveDateTime, conn: &DbConn) -> Vec<Self> {
pub async fn find_deleted_before(dt: &NaiveDateTime, conn: &mut DbConn) -> Vec<Self> {
db_run! {conn: {
ciphers::table
.filter(ciphers::deleted_at.lt(dt))
@ -651,7 +651,7 @@ impl Cipher {
}}
}
pub async fn get_collections(&self, user_id: &str, conn: &DbConn) -> Vec<String> {
pub async fn get_collections(&self, user_id: String, conn: &mut DbConn) -> Vec<String> {
db_run! {conn: {
ciphers_collections::table
.inner_join(collections::table.on(
@ -659,12 +659,12 @@ impl Cipher {
))
.inner_join(users_organizations::table.on(
users_organizations::org_uuid.eq(collections::org_uuid).and(
users_organizations::user_uuid.eq(user_id)
users_organizations::user_uuid.eq(user_id.clone())
)
))
.left_join(users_collections::table.on(
users_collections::collection_uuid.eq(ciphers_collections::collection_uuid).and(
users_collections::user_uuid.eq(user_id)
users_collections::user_uuid.eq(user_id.clone())
)
))
.filter(ciphers_collections::cipher_uuid.eq(&self.uuid))
@ -680,7 +680,7 @@ impl Cipher {
/// Return a Vec with (cipher_uuid, collection_uuid)
/// This is used during a full sync so we only need one query for all collections accessible.
pub async fn get_collections_with_cipher_by_user(user_id: &str, conn: &DbConn) -> Vec<(String, String)> {
pub async fn get_collections_with_cipher_by_user(user_id: String, conn: &mut DbConn) -> Vec<(String, String)> {
db_run! {conn: {
ciphers_collections::table
.inner_join(collections::table.on(
@ -688,12 +688,12 @@ impl Cipher {
))
.inner_join(users_organizations::table.on(
users_organizations::org_uuid.eq(collections::org_uuid).and(
users_organizations::user_uuid.eq(user_id)
users_organizations::user_uuid.eq(user_id.clone())
)
))
.left_join(users_collections::table.on(
users_collections::collection_uuid.eq(ciphers_collections::collection_uuid).and(
users_collections::user_uuid.eq(user_id)
users_collections::user_uuid.eq(user_id.clone())
)
))
.left_join(groups_users::table.on(

View file

@ -4,8 +4,8 @@ use super::{CollectionGroup, User, UserOrgStatus, UserOrgType, UserOrganization}
db_object! {
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "collections"]
#[primary_key(uuid)]
#[diesel(table_name = collections)]
#[diesel(primary_key(uuid))]
pub struct Collection {
pub uuid: String,
pub org_uuid: String,
@ -13,8 +13,8 @@ db_object! {
}
#[derive(Identifiable, Queryable, Insertable)]
#[table_name = "users_collections"]
#[primary_key(user_uuid, collection_uuid)]
#[diesel(table_name = users_collections)]
#[diesel(primary_key(user_uuid, collection_uuid))]
pub struct CollectionUser {
pub user_uuid: String,
pub collection_uuid: String,
@ -23,8 +23,8 @@ db_object! {
}
#[derive(Identifiable, Queryable, Insertable)]
#[table_name = "ciphers_collections"]
#[primary_key(cipher_uuid, collection_uuid)]
#[diesel(table_name = ciphers_collections)]
#[diesel(primary_key(cipher_uuid, collection_uuid))]
pub struct CollectionCipher {
pub cipher_uuid: String,
pub collection_uuid: String,
@ -56,7 +56,7 @@ impl Collection {
&self,
user_uuid: &str,
cipher_sync_data: Option<&crate::api::core::CipherSyncData>,
conn: &DbConn,
conn: &mut DbConn,
) -> Value {
let (read_only, hide_passwords) = if let Some(cipher_sync_data) = cipher_sync_data {
match cipher_sync_data.user_organizations.get(&self.org_uuid) {
@ -89,7 +89,7 @@ use crate::error::MapResult;
/// Database methods
impl Collection {
pub async fn save(&self, conn: &DbConn) -> EmptyResult {
pub async fn save(&self, conn: &mut DbConn) -> EmptyResult {
self.update_users_revision(conn).await;
db_run! { conn:
@ -123,7 +123,7 @@ impl Collection {
}
}
pub async fn delete(self, conn: &DbConn) -> EmptyResult {
pub async fn delete(self, conn: &mut DbConn) -> EmptyResult {
self.update_users_revision(conn).await;
CollectionCipher::delete_all_by_collection(&self.uuid, conn).await?;
CollectionUser::delete_all_by_collection(&self.uuid, conn).await?;
@ -136,20 +136,20 @@ impl Collection {
}}
}
pub async fn delete_all_by_organization(org_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_organization(org_uuid: &str, conn: &mut DbConn) -> EmptyResult {
for collection in Self::find_by_organization(org_uuid, conn).await {
collection.delete(conn).await?;
}
Ok(())
}
pub async fn update_users_revision(&self, conn: &DbConn) {
pub async fn update_users_revision(&self, conn: &mut DbConn) {
for user_org in UserOrganization::find_by_collection_and_org(&self.uuid, &self.org_uuid, conn).await.iter() {
User::update_uuid_revision(&user_org.user_uuid, conn).await;
}
}
pub async fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
collections::table
.filter(collections::uuid.eq(uuid))
@ -159,17 +159,17 @@ impl Collection {
}}
}
pub async fn find_by_user_uuid(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_user_uuid(user_uuid: String, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
collections::table
.left_join(users_collections::table.on(
users_collections::collection_uuid.eq(collections::uuid).and(
users_collections::user_uuid.eq(user_uuid)
users_collections::user_uuid.eq(user_uuid.clone())
)
))
.left_join(users_organizations::table.on(
collections::org_uuid.eq(users_organizations::org_uuid).and(
users_organizations::user_uuid.eq(user_uuid)
users_organizations::user_uuid.eq(user_uuid.clone())
)
))
.left_join(groups_users::table.on(
@ -203,11 +203,15 @@ impl Collection {
}}
}
pub async fn find_by_organization_and_user_uuid(org_uuid: &str, user_uuid: &str, conn: &DbConn) -> Vec<Self> {
Self::find_by_user_uuid(user_uuid, conn).await.into_iter().filter(|c| c.org_uuid == org_uuid).collect()
pub async fn find_by_organization_and_user_uuid(org_uuid: &str, user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
Self::find_by_user_uuid(user_uuid.to_owned(), conn)
.await
.into_iter()
.filter(|c| c.org_uuid == org_uuid)
.collect()
}
pub async fn find_by_organization(org_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_organization(org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
collections::table
.filter(collections::org_uuid.eq(org_uuid))
@ -217,7 +221,7 @@ impl Collection {
}}
}
pub async fn find_by_uuid_and_org(uuid: &str, org_uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid_and_org(uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
collections::table
.filter(collections::uuid.eq(uuid))
@ -229,12 +233,12 @@ impl Collection {
}}
}
pub async fn find_by_uuid_and_user(uuid: &str, user_uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid_and_user(uuid: &str, user_uuid: String, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
collections::table
.left_join(users_collections::table.on(
users_collections::collection_uuid.eq(collections::uuid).and(
users_collections::user_uuid.eq(user_uuid)
users_collections::user_uuid.eq(user_uuid.clone())
)
))
.left_join(users_organizations::table.on(
@ -255,7 +259,7 @@ impl Collection {
}}
}
pub async fn is_writable_by_user(&self, user_uuid: &str, conn: &DbConn) -> bool {
pub async fn is_writable_by_user(&self, user_uuid: &str, conn: &mut DbConn) -> bool {
match UserOrganization::find_by_user_and_org(user_uuid, &self.org_uuid, conn).await {
None => false, // Not in Org
Some(user_org) => {
@ -277,7 +281,7 @@ impl Collection {
}
}
pub async fn hide_passwords_for_user(&self, user_uuid: &str, conn: &DbConn) -> bool {
pub async fn hide_passwords_for_user(&self, user_uuid: &str, conn: &mut DbConn) -> bool {
match UserOrganization::find_by_user_and_org(user_uuid, &self.org_uuid, conn).await {
None => true, // Not in Org
Some(user_org) => {
@ -302,7 +306,7 @@ impl Collection {
/// Database methods
impl CollectionUser {
pub async fn find_by_organization_and_user_uuid(org_uuid: &str, user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_organization_and_user_uuid(org_uuid: &str, user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
users_collections::table
.filter(users_collections::user_uuid.eq(user_uuid))
@ -320,7 +324,7 @@ impl CollectionUser {
collection_uuid: &str,
read_only: bool,
hide_passwords: bool,
conn: &DbConn,
conn: &mut DbConn,
) -> EmptyResult {
User::update_uuid_revision(user_uuid, conn).await;
@ -373,7 +377,7 @@ impl CollectionUser {
}
}
pub async fn delete(self, conn: &DbConn) -> EmptyResult {
pub async fn delete(self, conn: &mut DbConn) -> EmptyResult {
User::update_uuid_revision(&self.user_uuid, conn).await;
db_run! { conn: {
@ -387,7 +391,7 @@ impl CollectionUser {
}}
}
pub async fn find_by_collection(collection_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_collection(collection_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
users_collections::table
.filter(users_collections::collection_uuid.eq(collection_uuid))
@ -398,7 +402,11 @@ impl CollectionUser {
}}
}
pub async fn find_by_collection_and_user(collection_uuid: &str, user_uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_collection_and_user(
collection_uuid: &str,
user_uuid: &str,
conn: &mut DbConn,
) -> Option<Self> {
db_run! { conn: {
users_collections::table
.filter(users_collections::collection_uuid.eq(collection_uuid))
@ -410,7 +418,7 @@ impl CollectionUser {
}}
}
pub async fn find_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
users_collections::table
.filter(users_collections::user_uuid.eq(user_uuid))
@ -421,7 +429,7 @@ impl CollectionUser {
}}
}
pub async fn delete_all_by_collection(collection_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_collection(collection_uuid: &str, conn: &mut DbConn) -> EmptyResult {
for collection in CollectionUser::find_by_collection(collection_uuid, conn).await.iter() {
User::update_uuid_revision(&collection.user_uuid, conn).await;
}
@ -433,7 +441,7 @@ impl CollectionUser {
}}
}
pub async fn delete_all_by_user_and_org(user_uuid: &str, org_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_user_and_org(user_uuid: &str, org_uuid: &str, conn: &mut DbConn) -> EmptyResult {
let collectionusers = Self::find_by_organization_and_user_uuid(org_uuid, user_uuid, conn).await;
db_run! { conn: {
@ -452,7 +460,7 @@ impl CollectionUser {
/// Database methods
impl CollectionCipher {
pub async fn save(cipher_uuid: &str, collection_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn save(cipher_uuid: &str, collection_uuid: &str, conn: &mut DbConn) -> EmptyResult {
Self::update_users_revision(collection_uuid, conn).await;
db_run! { conn:
@ -482,7 +490,7 @@ impl CollectionCipher {
}
}
pub async fn delete(cipher_uuid: &str, collection_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete(cipher_uuid: &str, collection_uuid: &str, conn: &mut DbConn) -> EmptyResult {
Self::update_users_revision(collection_uuid, conn).await;
db_run! { conn: {
@ -496,7 +504,7 @@ impl CollectionCipher {
}}
}
pub async fn delete_all_by_cipher(cipher_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_cipher(cipher_uuid: &str, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(ciphers_collections::table.filter(ciphers_collections::cipher_uuid.eq(cipher_uuid)))
.execute(conn)
@ -504,7 +512,7 @@ impl CollectionCipher {
}}
}
pub async fn delete_all_by_collection(collection_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_collection(collection_uuid: &str, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(ciphers_collections::table.filter(ciphers_collections::collection_uuid.eq(collection_uuid)))
.execute(conn)
@ -512,7 +520,7 @@ impl CollectionCipher {
}}
}
pub async fn update_users_revision(collection_uuid: &str, conn: &DbConn) {
pub async fn update_users_revision(collection_uuid: &str, conn: &mut DbConn) {
if let Some(collection) = Collection::find_by_uuid(collection_uuid, conn).await {
collection.update_users_revision(conn).await;
}

View file

@ -4,9 +4,9 @@ use crate::CONFIG;
db_object! {
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "devices"]
#[changeset_options(treat_none_as_null="true")]
#[primary_key(uuid, user_uuid)]
#[diesel(table_name = devices)]
#[diesel(treat_none_as_null = true)]
#[diesel(primary_key(uuid, user_uuid))]
pub struct Device {
pub uuid: String,
pub created_at: NaiveDateTime,
@ -116,7 +116,7 @@ use crate::error::MapResult;
/// Database methods
impl Device {
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
pub async fn save(&mut self, conn: &mut DbConn) -> EmptyResult {
self.updated_at = Utc::now().naive_utc();
db_run! { conn:
@ -136,7 +136,7 @@ impl Device {
}
}
pub async fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_user(user_uuid: &str, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(devices::table.filter(devices::user_uuid.eq(user_uuid)))
.execute(conn)
@ -144,7 +144,7 @@ impl Device {
}}
}
pub async fn find_by_uuid_and_user(uuid: &str, user_uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid_and_user(uuid: &str, user_uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
devices::table
.filter(devices::uuid.eq(uuid))
@ -155,7 +155,7 @@ impl Device {
}}
}
pub async fn find_by_refresh_token(refresh_token: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_refresh_token(refresh_token: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
devices::table
.filter(devices::refresh_token.eq(refresh_token))
@ -165,7 +165,7 @@ impl Device {
}}
}
pub async fn find_latest_active_by_user(user_uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_latest_active_by_user(user_uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
devices::table
.filter(devices::user_uuid.eq(user_uuid))

View file

@ -5,9 +5,9 @@ use super::User;
db_object! {
#[derive(Debug, Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "emergency_access"]
#[changeset_options(treat_none_as_null="true")]
#[primary_key(uuid)]
#[diesel(table_name = emergency_access)]
#[diesel(treat_none_as_null = true)]
#[diesel(primary_key(uuid))]
pub struct EmergencyAccess {
pub uuid: String,
pub grantor_uuid: String,
@ -72,7 +72,7 @@ impl EmergencyAccess {
})
}
pub async fn to_json_grantor_details(&self, conn: &DbConn) -> Value {
pub async fn to_json_grantor_details(&self, conn: &mut DbConn) -> Value {
let grantor_user = User::find_by_uuid(&self.grantor_uuid, conn).await.expect("Grantor user not found.");
json!({
@ -88,7 +88,7 @@ impl EmergencyAccess {
}
#[allow(clippy::manual_map)]
pub async fn to_json_grantee_details(&self, conn: &DbConn) -> Value {
pub async fn to_json_grantee_details(&self, conn: &mut DbConn) -> Value {
let grantee_user = if let Some(grantee_uuid) = self.grantee_uuid.as_deref() {
Some(User::find_by_uuid(grantee_uuid, conn).await.expect("Grantee user not found."))
} else if let Some(email) = self.email.as_deref() {
@ -154,7 +154,7 @@ use crate::api::EmptyResult;
use crate::error::MapResult;
impl EmergencyAccess {
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
pub async fn save(&mut self, conn: &mut DbConn) -> EmptyResult {
User::update_uuid_revision(&self.grantor_uuid, conn).await;
self.updated_at = Utc::now().naive_utc();
@ -189,7 +189,7 @@ impl EmergencyAccess {
}
}
pub async fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_user(user_uuid: &str, conn: &mut DbConn) -> EmptyResult {
for ea in Self::find_all_by_grantor_uuid(user_uuid, conn).await {
ea.delete(conn).await?;
}
@ -199,7 +199,7 @@ impl EmergencyAccess {
Ok(())
}
pub async fn delete(self, conn: &DbConn) -> EmptyResult {
pub async fn delete(self, conn: &mut DbConn) -> EmptyResult {
User::update_uuid_revision(&self.grantor_uuid, conn).await;
db_run! { conn: {
@ -209,7 +209,7 @@ impl EmergencyAccess {
}}
}
pub async fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
emergency_access::table
.filter(emergency_access::uuid.eq(uuid))
@ -222,7 +222,7 @@ impl EmergencyAccess {
grantor_uuid: &str,
grantee_uuid: &str,
email: &str,
conn: &DbConn,
conn: &mut DbConn,
) -> Option<Self> {
db_run! { conn: {
emergency_access::table
@ -233,7 +233,7 @@ impl EmergencyAccess {
}}
}
pub async fn find_all_recoveries(conn: &DbConn) -> Vec<Self> {
pub async fn find_all_recoveries(conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
emergency_access::table
.filter(emergency_access::status.eq(EmergencyAccessStatus::RecoveryInitiated as i32))
@ -241,7 +241,7 @@ impl EmergencyAccess {
}}
}
pub async fn find_by_uuid_and_grantor_uuid(uuid: &str, grantor_uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid_and_grantor_uuid(uuid: &str, grantor_uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
emergency_access::table
.filter(emergency_access::uuid.eq(uuid))
@ -251,7 +251,7 @@ impl EmergencyAccess {
}}
}
pub async fn find_all_by_grantee_uuid(grantee_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_all_by_grantee_uuid(grantee_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
emergency_access::table
.filter(emergency_access::grantee_uuid.eq(grantee_uuid))
@ -259,7 +259,7 @@ impl EmergencyAccess {
}}
}
pub async fn find_invited_by_grantee_email(grantee_email: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_invited_by_grantee_email(grantee_email: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
emergency_access::table
.filter(emergency_access::email.eq(grantee_email))
@ -269,7 +269,7 @@ impl EmergencyAccess {
}}
}
pub async fn find_all_by_grantor_uuid(grantor_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_all_by_grantor_uuid(grantor_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
emergency_access::table
.filter(emergency_access::grantor_uuid.eq(grantor_uuid))

View file

@ -2,8 +2,8 @@ use super::User;
db_object! {
#[derive(Identifiable, Queryable, Insertable)]
#[table_name = "favorites"]
#[primary_key(user_uuid, cipher_uuid)]
#[diesel(table_name = favorites)]
#[diesel(primary_key(user_uuid, cipher_uuid))]
pub struct Favorite {
pub user_uuid: String,
pub cipher_uuid: String,
@ -17,7 +17,7 @@ use crate::error::MapResult;
impl Favorite {
// Returns whether the specified cipher is a favorite of the specified user.
pub async fn is_favorite(cipher_uuid: &str, user_uuid: &str, conn: &DbConn) -> bool {
pub async fn is_favorite(cipher_uuid: &str, user_uuid: &str, conn: &mut DbConn) -> bool {
db_run! { conn: {
let query = favorites::table
.filter(favorites::cipher_uuid.eq(cipher_uuid))
@ -29,7 +29,7 @@ impl Favorite {
}
// Sets whether the specified cipher is a favorite of the specified user.
pub async fn set_favorite(favorite: bool, cipher_uuid: &str, user_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn set_favorite(favorite: bool, cipher_uuid: &str, user_uuid: &str, conn: &mut DbConn) -> EmptyResult {
let (old, new) = (Self::is_favorite(cipher_uuid, user_uuid, conn).await, favorite);
match (old, new) {
(false, true) => {
@ -62,7 +62,7 @@ impl Favorite {
}
// Delete all favorite entries associated with the specified cipher.
pub async fn delete_all_by_cipher(cipher_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_cipher(cipher_uuid: &str, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(favorites::table.filter(favorites::cipher_uuid.eq(cipher_uuid)))
.execute(conn)
@ -71,7 +71,7 @@ impl Favorite {
}
// Delete all favorite entries associated with the specified user.
pub async fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_user(user_uuid: &str, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(favorites::table.filter(favorites::user_uuid.eq(user_uuid)))
.execute(conn)
@ -81,7 +81,7 @@ impl Favorite {
/// Return a vec with (cipher_uuid) this will only contain favorite flagged ciphers
/// This is used during a full sync so we only need one query for all favorite cipher matches.
pub async fn get_all_cipher_uuid_by_user(user_uuid: &str, conn: &DbConn) -> Vec<String> {
pub async fn get_all_cipher_uuid_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<String> {
db_run! { conn: {
favorites::table
.filter(favorites::user_uuid.eq(user_uuid))

View file

@ -5,8 +5,8 @@ use super::User;
db_object! {
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "folders"]
#[primary_key(uuid)]
#[diesel(table_name = folders)]
#[diesel(primary_key(uuid))]
pub struct Folder {
pub uuid: String,
pub created_at: NaiveDateTime,
@ -16,8 +16,8 @@ db_object! {
}
#[derive(Identifiable, Queryable, Insertable)]
#[table_name = "folders_ciphers"]
#[primary_key(cipher_uuid, folder_uuid)]
#[diesel(table_name = folders_ciphers)]
#[diesel(primary_key(cipher_uuid, folder_uuid))]
pub struct FolderCipher {
pub cipher_uuid: String,
pub folder_uuid: String,
@ -67,7 +67,7 @@ use crate::error::MapResult;
/// Database methods
impl Folder {
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
pub async fn save(&mut self, conn: &mut DbConn) -> EmptyResult {
User::update_uuid_revision(&self.user_uuid, conn).await;
self.updated_at = Utc::now().naive_utc();
@ -102,7 +102,7 @@ impl Folder {
}
}
pub async fn delete(&self, conn: &DbConn) -> EmptyResult {
pub async fn delete(&self, conn: &mut DbConn) -> EmptyResult {
User::update_uuid_revision(&self.user_uuid, conn).await;
FolderCipher::delete_all_by_folder(&self.uuid, conn).await?;
@ -113,14 +113,14 @@ impl Folder {
}}
}
pub async fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_user(user_uuid: &str, conn: &mut DbConn) -> EmptyResult {
for folder in Self::find_by_user(user_uuid, conn).await {
folder.delete(conn).await?;
}
Ok(())
}
pub async fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
folders::table
.filter(folders::uuid.eq(uuid))
@ -130,7 +130,7 @@ impl Folder {
}}
}
pub async fn find_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
folders::table
.filter(folders::user_uuid.eq(user_uuid))
@ -142,7 +142,7 @@ impl Folder {
}
impl FolderCipher {
pub async fn save(&self, conn: &DbConn) -> EmptyResult {
pub async fn save(&self, conn: &mut DbConn) -> EmptyResult {
db_run! { conn:
sqlite, mysql {
// Not checking for ForeignKey Constraints here.
@ -164,7 +164,7 @@ impl FolderCipher {
}
}
pub async fn delete(self, conn: &DbConn) -> EmptyResult {
pub async fn delete(self, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(
folders_ciphers::table
@ -176,7 +176,7 @@ impl FolderCipher {
}}
}
pub async fn delete_all_by_cipher(cipher_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_cipher(cipher_uuid: &str, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(folders_ciphers::table.filter(folders_ciphers::cipher_uuid.eq(cipher_uuid)))
.execute(conn)
@ -184,7 +184,7 @@ impl FolderCipher {
}}
}
pub async fn delete_all_by_folder(folder_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_folder(folder_uuid: &str, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(folders_ciphers::table.filter(folders_ciphers::folder_uuid.eq(folder_uuid)))
.execute(conn)
@ -192,7 +192,7 @@ impl FolderCipher {
}}
}
pub async fn find_by_folder_and_cipher(folder_uuid: &str, cipher_uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_folder_and_cipher(folder_uuid: &str, cipher_uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
folders_ciphers::table
.filter(folders_ciphers::folder_uuid.eq(folder_uuid))
@ -203,7 +203,7 @@ impl FolderCipher {
}}
}
pub async fn find_by_folder(folder_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_folder(folder_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
folders_ciphers::table
.filter(folders_ciphers::folder_uuid.eq(folder_uuid))
@ -215,7 +215,7 @@ impl FolderCipher {
/// Return a vec with (cipher_uuid, folder_uuid)
/// This is used during a full sync so we only need one query for all folder matches.
pub async fn find_by_user(user_uuid: &str, conn: &DbConn) -> Vec<(String, String)> {
pub async fn find_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<(String, String)> {
db_run! { conn: {
folders_ciphers::table
.inner_join(folders::table)

View file

@ -3,8 +3,8 @@ use serde_json::Value;
db_object! {
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "groups"]
#[primary_key(uuid)]
#[diesel(table_name = groups)]
#[diesel(primary_key(uuid))]
pub struct Group {
pub uuid: String,
pub organizations_uuid: String,
@ -16,8 +16,8 @@ db_object! {
}
#[derive(Identifiable, Queryable, Insertable)]
#[table_name = "collections_groups"]
#[primary_key(collections_uuid, groups_uuid)]
#[diesel(table_name = collections_groups)]
#[diesel(primary_key(collections_uuid, groups_uuid))]
pub struct CollectionGroup {
pub collections_uuid: String,
pub groups_uuid: String,
@ -26,8 +26,8 @@ db_object! {
}
#[derive(Identifiable, Queryable, Insertable)]
#[table_name = "groups_users"]
#[primary_key(groups_uuid, users_organizations_uuid)]
#[diesel(table_name = groups_users)]
#[diesel(primary_key(groups_uuid, users_organizations_uuid))]
pub struct GroupUser {
pub groups_uuid: String,
pub users_organizations_uuid: String
@ -117,7 +117,7 @@ use super::{User, UserOrganization};
/// Database methods
impl Group {
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
pub async fn save(&mut self, conn: &mut DbConn) -> EmptyResult {
self.revision_date = Utc::now().naive_utc();
db_run! { conn:
@ -151,7 +151,7 @@ impl Group {
}
}
pub async fn find_by_organization(organizations_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_organization(organizations_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
groups::table
.filter(groups::organizations_uuid.eq(organizations_uuid))
@ -161,7 +161,7 @@ impl Group {
}}
}
pub async fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
groups::table
.filter(groups::uuid.eq(uuid))
@ -172,7 +172,7 @@ impl Group {
}
//Returns all organizations the user has full access to
pub async fn gather_user_organizations_full_access(user_uuid: &str, conn: &DbConn) -> Vec<String> {
pub async fn gather_user_organizations_full_access(user_uuid: &str, conn: &mut DbConn) -> Vec<String> {
db_run! { conn: {
groups_users::table
.inner_join(users_organizations::table.on(
@ -190,7 +190,7 @@ impl Group {
}}
}
pub async fn is_in_full_access_group(user_uuid: &str, org_uuid: &str, conn: &DbConn) -> bool {
pub async fn is_in_full_access_group(user_uuid: &str, org_uuid: &str, conn: &mut DbConn) -> bool {
db_run! { conn: {
groups::table
.inner_join(groups_users::table.on(
@ -208,7 +208,7 @@ impl Group {
}}
}
pub async fn delete(&self, conn: &DbConn) -> EmptyResult {
pub async fn delete(&self, conn: &mut DbConn) -> EmptyResult {
CollectionGroup::delete_all_by_group(&self.uuid, conn).await?;
GroupUser::delete_all_by_group(&self.uuid, conn).await?;
@ -219,13 +219,13 @@ impl Group {
}}
}
pub async fn update_revision(uuid: &str, conn: &DbConn) {
pub async fn update_revision(uuid: &str, conn: &mut DbConn) {
if let Err(e) = Self::_update_revision(uuid, &Utc::now().naive_utc(), conn).await {
warn!("Failed to update revision for {}: {:#?}", uuid, e);
}
}
async fn _update_revision(uuid: &str, date: &NaiveDateTime, conn: &DbConn) -> EmptyResult {
async fn _update_revision(uuid: &str, date: &NaiveDateTime, conn: &mut DbConn) -> EmptyResult {
db_run! {conn: {
crate::util::retry(|| {
diesel::update(groups::table.filter(groups::uuid.eq(uuid)))
@ -238,7 +238,7 @@ impl Group {
}
impl CollectionGroup {
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
pub async fn save(&mut self, conn: &mut DbConn) -> EmptyResult {
let group_users = GroupUser::find_by_group(&self.groups_uuid, conn).await;
for group_user in group_users {
group_user.update_user_revision(conn).await;
@ -293,7 +293,7 @@ impl CollectionGroup {
}
}
pub async fn find_by_group(group_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_group(group_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
collections_groups::table
.filter(collections_groups::groups_uuid.eq(group_uuid))
@ -303,7 +303,7 @@ impl CollectionGroup {
}}
}
pub async fn find_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
collections_groups::table
.inner_join(groups_users::table.on(
@ -320,7 +320,7 @@ impl CollectionGroup {
}}
}
pub async fn find_by_collection(collection_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_collection(collection_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
collections_groups::table
.filter(collections_groups::collections_uuid.eq(collection_uuid))
@ -331,7 +331,7 @@ impl CollectionGroup {
}}
}
pub async fn delete(&self, conn: &DbConn) -> EmptyResult {
pub async fn delete(&self, conn: &mut DbConn) -> EmptyResult {
let group_users = GroupUser::find_by_group(&self.groups_uuid, conn).await;
for group_user in group_users {
group_user.update_user_revision(conn).await;
@ -346,7 +346,7 @@ impl CollectionGroup {
}}
}
pub async fn delete_all_by_group(group_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_group(group_uuid: &str, conn: &mut DbConn) -> EmptyResult {
let group_users = GroupUser::find_by_group(group_uuid, conn).await;
for group_user in group_users {
group_user.update_user_revision(conn).await;
@ -360,7 +360,7 @@ impl CollectionGroup {
}}
}
pub async fn delete_all_by_collection(collection_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_collection(collection_uuid: &str, conn: &mut DbConn) -> EmptyResult {
let collection_assigned_to_groups = CollectionGroup::find_by_collection(collection_uuid, conn).await;
for collection_assigned_to_group in collection_assigned_to_groups {
let group_users = GroupUser::find_by_group(&collection_assigned_to_group.groups_uuid, conn).await;
@ -379,7 +379,7 @@ impl CollectionGroup {
}
impl GroupUser {
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
pub async fn save(&mut self, conn: &mut DbConn) -> EmptyResult {
self.update_user_revision(conn).await;
db_run! { conn:
@ -425,7 +425,7 @@ impl GroupUser {
}
}
pub async fn find_by_group(group_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_group(group_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
groups_users::table
.filter(groups_users::groups_uuid.eq(group_uuid))
@ -435,7 +435,7 @@ impl GroupUser {
}}
}
pub async fn find_by_user(users_organizations_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_user(users_organizations_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
groups_users::table
.filter(groups_users::users_organizations_uuid.eq(users_organizations_uuid))
@ -445,7 +445,7 @@ impl GroupUser {
}}
}
pub async fn update_user_revision(&self, conn: &DbConn) {
pub async fn update_user_revision(&self, conn: &mut DbConn) {
match UserOrganization::find_by_uuid(&self.users_organizations_uuid, conn).await {
Some(user) => User::update_uuid_revision(&user.user_uuid, conn).await,
None => warn!("User could not be found!"),
@ -455,7 +455,7 @@ impl GroupUser {
pub async fn delete_by_group_id_and_user_id(
group_uuid: &str,
users_organizations_uuid: &str,
conn: &DbConn,
conn: &mut DbConn,
) -> EmptyResult {
match UserOrganization::find_by_uuid(users_organizations_uuid, conn).await {
Some(user) => User::update_uuid_revision(&user.user_uuid, conn).await,
@ -471,7 +471,7 @@ impl GroupUser {
}}
}
pub async fn delete_all_by_group(group_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_group(group_uuid: &str, conn: &mut DbConn) -> EmptyResult {
let group_users = GroupUser::find_by_group(group_uuid, conn).await;
for group_user in group_users {
group_user.update_user_revision(conn).await;
@ -485,7 +485,7 @@ impl GroupUser {
}}
}
pub async fn delete_all_by_user(users_organizations_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_user(users_organizations_uuid: &str, conn: &mut DbConn) -> EmptyResult {
match UserOrganization::find_by_uuid(users_organizations_uuid, conn).await {
Some(user) => User::update_uuid_revision(&user.user_uuid, conn).await,
None => warn!("User could not be found!"),

View file

@ -10,8 +10,8 @@ use super::{TwoFactor, UserOrgStatus, UserOrgType, UserOrganization};
db_object! {
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "org_policies"]
#[primary_key(uuid)]
#[diesel(table_name = org_policies)]
#[diesel(primary_key(uuid))]
pub struct OrgPolicy {
pub uuid: String,
pub org_uuid: String,
@ -83,7 +83,7 @@ impl OrgPolicy {
/// Database methods
impl OrgPolicy {
pub async fn save(&self, conn: &DbConn) -> EmptyResult {
pub async fn save(&self, conn: &mut DbConn) -> EmptyResult {
db_run! { conn:
sqlite, mysql {
match diesel::replace_into(org_policies::table)
@ -126,7 +126,7 @@ impl OrgPolicy {
}
}
pub async fn delete(self, conn: &DbConn) -> EmptyResult {
pub async fn delete(self, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(org_policies::table.filter(org_policies::uuid.eq(self.uuid)))
.execute(conn)
@ -134,7 +134,7 @@ impl OrgPolicy {
}}
}
pub async fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
org_policies::table
.filter(org_policies::uuid.eq(uuid))
@ -144,7 +144,7 @@ impl OrgPolicy {
}}
}
pub async fn find_by_org(org_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_org(org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
org_policies::table
.filter(org_policies::org_uuid.eq(org_uuid))
@ -154,7 +154,7 @@ impl OrgPolicy {
}}
}
pub async fn find_confirmed_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_confirmed_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
org_policies::table
.inner_join(
@ -172,7 +172,7 @@ impl OrgPolicy {
}}
}
pub async fn find_by_org_and_type(org_uuid: &str, policy_type: OrgPolicyType, conn: &DbConn) -> Option<Self> {
pub async fn find_by_org_and_type(org_uuid: &str, policy_type: OrgPolicyType, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
org_policies::table
.filter(org_policies::org_uuid.eq(org_uuid))
@ -183,7 +183,7 @@ impl OrgPolicy {
}}
}
pub async fn delete_all_by_organization(org_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_organization(org_uuid: &str, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(org_policies::table.filter(org_policies::org_uuid.eq(org_uuid)))
.execute(conn)
@ -194,7 +194,7 @@ impl OrgPolicy {
pub async fn find_accepted_and_confirmed_by_user_and_active_policy(
user_uuid: &str,
policy_type: OrgPolicyType,
conn: &DbConn,
conn: &mut DbConn,
) -> Vec<Self> {
db_run! { conn: {
org_policies::table
@ -221,7 +221,7 @@ impl OrgPolicy {
pub async fn find_confirmed_by_user_and_active_policy(
user_uuid: &str,
policy_type: OrgPolicyType,
conn: &DbConn,
conn: &mut DbConn,
) -> Vec<Self> {
db_run! { conn: {
org_policies::table
@ -249,7 +249,7 @@ impl OrgPolicy {
user_uuid: &str,
policy_type: OrgPolicyType,
exclude_org_uuid: Option<&str>,
conn: &DbConn,
conn: &mut DbConn,
) -> bool {
for policy in
OrgPolicy::find_accepted_and_confirmed_by_user_and_active_policy(user_uuid, policy_type, conn).await
@ -272,7 +272,7 @@ impl OrgPolicy {
user_uuid: &str,
org_uuid: &str,
exclude_current_org: bool,
conn: &DbConn,
conn: &mut DbConn,
) -> OrgPolicyResult {
// Enforce TwoFactor/TwoStep login
if TwoFactor::find_by_user(user_uuid, conn).await.is_empty() {
@ -300,7 +300,7 @@ impl OrgPolicy {
/// Returns true if the user belongs to an org that has enabled the `DisableHideEmail`
/// option of the `Send Options` policy, and the user is not an owner or admin of that org.
pub async fn is_hide_email_disabled(user_uuid: &str, conn: &DbConn) -> bool {
pub async fn is_hide_email_disabled(user_uuid: &str, conn: &mut DbConn) -> bool {
for policy in
OrgPolicy::find_confirmed_by_user_and_active_policy(user_uuid, OrgPolicyType::SendOptions, conn).await
{

View file

@ -6,8 +6,8 @@ use super::{CollectionUser, GroupUser, OrgPolicy, OrgPolicyType, User};
db_object! {
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "organizations"]
#[primary_key(uuid)]
#[diesel(table_name = organizations)]
#[diesel(primary_key(uuid))]
pub struct Organization {
pub uuid: String,
pub name: String,
@ -17,8 +17,8 @@ db_object! {
}
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "users_organizations"]
#[primary_key(uuid)]
#[diesel(table_name = users_organizations)]
#[diesel(primary_key(uuid))]
pub struct UserOrganization {
pub uuid: String,
pub user_uuid: String,
@ -216,7 +216,7 @@ use crate::error::MapResult;
/// Database methods
impl Organization {
pub async fn save(&self, conn: &DbConn) -> EmptyResult {
pub async fn save(&self, conn: &mut DbConn) -> EmptyResult {
for user_org in UserOrganization::find_by_org(&self.uuid, conn).await.iter() {
User::update_uuid_revision(&user_org.user_uuid, conn).await;
}
@ -253,7 +253,7 @@ impl Organization {
}
}
pub async fn delete(self, conn: &DbConn) -> EmptyResult {
pub async fn delete(self, conn: &mut DbConn) -> EmptyResult {
use super::{Cipher, Collection};
Cipher::delete_all_by_organization(&self.uuid, conn).await?;
@ -268,7 +268,7 @@ impl Organization {
}}
}
pub async fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
organizations::table
.filter(organizations::uuid.eq(uuid))
@ -277,7 +277,7 @@ impl Organization {
}}
}
pub async fn get_all(conn: &DbConn) -> Vec<Self> {
pub async fn get_all(conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
organizations::table.load::<OrganizationDb>(conn).expect("Error loading organizations").from_db()
}}
@ -285,7 +285,7 @@ impl Organization {
}
impl UserOrganization {
pub async fn to_json(&self, conn: &DbConn) -> Value {
pub async fn to_json(&self, conn: &mut DbConn) -> Value {
let org = Organization::find_by_uuid(&self.org_uuid, conn).await.unwrap();
// https://github.com/bitwarden/server/blob/13d1e74d6960cf0d042620b72d85bf583a4236f7/src/Api/Models/Response/ProfileOrganizationResponseModel.cs
@ -350,7 +350,7 @@ impl UserOrganization {
})
}
pub async fn to_json_user_details(&self, conn: &DbConn) -> Value {
pub async fn to_json_user_details(&self, conn: &mut DbConn) -> Value {
let user = User::find_by_uuid(&self.user_uuid, conn).await.unwrap();
// Because BitWarden want the status to be -1 for revoked users we need to catch that here.
@ -383,7 +383,7 @@ impl UserOrganization {
})
}
pub async fn to_json_details(&self, conn: &DbConn) -> Value {
pub async fn to_json_details(&self, conn: &mut DbConn) -> Value {
let coll_uuids = if self.access_all {
vec![] // If we have complete access, no need to fill the array
} else {
@ -421,7 +421,7 @@ impl UserOrganization {
"Object": "organizationUserDetails",
})
}
pub async fn save(&self, conn: &DbConn) -> EmptyResult {
pub async fn save(&self, conn: &mut DbConn) -> EmptyResult {
User::update_uuid_revision(&self.user_uuid, conn).await;
db_run! { conn:
@ -455,7 +455,7 @@ impl UserOrganization {
}
}
pub async fn delete(self, conn: &DbConn) -> EmptyResult {
pub async fn delete(self, conn: &mut DbConn) -> EmptyResult {
User::update_uuid_revision(&self.user_uuid, conn).await;
CollectionUser::delete_all_by_user_and_org(&self.user_uuid, &self.org_uuid, conn).await?;
@ -468,21 +468,21 @@ impl UserOrganization {
}}
}
pub async fn delete_all_by_organization(org_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_organization(org_uuid: &str, conn: &mut DbConn) -> EmptyResult {
for user_org in Self::find_by_org(org_uuid, conn).await {
user_org.delete(conn).await?;
}
Ok(())
}
pub async fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_user(user_uuid: &str, conn: &mut DbConn) -> EmptyResult {
for user_org in Self::find_any_state_by_user(user_uuid, conn).await {
user_org.delete(conn).await?;
}
Ok(())
}
pub async fn find_by_email_and_org(email: &str, org_id: &str, conn: &DbConn) -> Option<UserOrganization> {
pub async fn find_by_email_and_org(email: &str, org_id: &str, conn: &mut DbConn) -> Option<UserOrganization> {
if let Some(user) = super::User::find_by_mail(email, conn).await {
if let Some(user_org) = UserOrganization::find_by_user_and_org(&user.uuid, org_id, conn).await {
return Some(user_org);
@ -504,7 +504,7 @@ impl UserOrganization {
(self.access_all || self.atype >= UserOrgType::Admin) && self.has_status(UserOrgStatus::Confirmed)
}
pub async fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::uuid.eq(uuid))
@ -513,7 +513,7 @@ impl UserOrganization {
}}
}
pub async fn find_by_uuid_and_org(uuid: &str, org_uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid_and_org(uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::uuid.eq(uuid))
@ -523,7 +523,7 @@ impl UserOrganization {
}}
}
pub async fn find_confirmed_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_confirmed_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::user_uuid.eq(user_uuid))
@ -533,7 +533,7 @@ impl UserOrganization {
}}
}
pub async fn find_invited_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_invited_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::user_uuid.eq(user_uuid))
@ -543,7 +543,7 @@ impl UserOrganization {
}}
}
pub async fn find_any_state_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_any_state_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::user_uuid.eq(user_uuid))
@ -552,7 +552,7 @@ impl UserOrganization {
}}
}
pub async fn count_accepted_and_confirmed_by_user(user_uuid: &str, conn: &DbConn) -> i64 {
pub async fn count_accepted_and_confirmed_by_user(user_uuid: &str, conn: &mut DbConn) -> i64 {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::user_uuid.eq(user_uuid))
@ -564,7 +564,7 @@ impl UserOrganization {
}}
}
pub async fn find_by_org(org_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_org(org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::org_uuid.eq(org_uuid))
@ -573,7 +573,7 @@ impl UserOrganization {
}}
}
pub async fn count_by_org(org_uuid: &str, conn: &DbConn) -> i64 {
pub async fn count_by_org(org_uuid: &str, conn: &mut DbConn) -> i64 {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::org_uuid.eq(org_uuid))
@ -584,7 +584,7 @@ impl UserOrganization {
}}
}
pub async fn find_by_org_and_type(org_uuid: &str, atype: UserOrgType, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_org_and_type(org_uuid: &str, atype: UserOrgType, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::org_uuid.eq(org_uuid))
@ -594,7 +594,7 @@ impl UserOrganization {
}}
}
pub async fn count_confirmed_by_org_and_type(org_uuid: &str, atype: UserOrgType, conn: &DbConn) -> i64 {
pub async fn count_confirmed_by_org_and_type(org_uuid: &str, atype: UserOrgType, conn: &mut DbConn) -> i64 {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::org_uuid.eq(org_uuid))
@ -606,7 +606,7 @@ impl UserOrganization {
}}
}
pub async fn find_by_user_and_org(user_uuid: &str, org_uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_user_and_org(user_uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::user_uuid.eq(user_uuid))
@ -616,7 +616,7 @@ impl UserOrganization {
}}
}
pub async fn find_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::user_uuid.eq(user_uuid))
@ -625,7 +625,7 @@ impl UserOrganization {
}}
}
pub async fn find_by_user_and_policy(user_uuid: &str, policy_type: OrgPolicyType, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_user_and_policy(user_uuid: &str, policy_type: OrgPolicyType, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
users_organizations::table
.inner_join(
@ -644,7 +644,7 @@ impl UserOrganization {
}}
}
pub async fn find_by_cipher_and_org(cipher_uuid: &str, org_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_cipher_and_org(cipher_uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::org_uuid.eq(org_uuid))
@ -666,7 +666,7 @@ impl UserOrganization {
}}
}
pub async fn find_by_collection_and_org(collection_uuid: &str, org_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_collection_and_org(collection_uuid: &str, org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
users_organizations::table
.filter(users_organizations::org_uuid.eq(org_uuid))

View file

@ -5,9 +5,9 @@ use super::User;
db_object! {
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "sends"]
#[changeset_options(treat_none_as_null="true")]
#[primary_key(uuid)]
#[diesel(table_name = sends)]
#[diesel(treat_none_as_null = true)]
#[diesel(primary_key(uuid))]
pub struct Send {
pub uuid: String,
@ -101,7 +101,7 @@ impl Send {
}
}
pub async fn creator_identifier(&self, conn: &DbConn) -> Option<String> {
pub async fn creator_identifier(&self, conn: &mut DbConn) -> Option<String> {
if let Some(hide_email) = self.hide_email {
if hide_email {
return None;
@ -148,7 +148,7 @@ impl Send {
})
}
pub async fn to_json_access(&self, conn: &DbConn) -> Value {
pub async fn to_json_access(&self, conn: &mut DbConn) -> Value {
use crate::util::format_date;
let data: Value = serde_json::from_str(&self.data).unwrap_or_default();
@ -174,7 +174,7 @@ use crate::api::EmptyResult;
use crate::error::MapResult;
impl Send {
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
pub async fn save(&mut self, conn: &mut DbConn) -> EmptyResult {
self.update_users_revision(conn).await;
self.revision_date = Utc::now().naive_utc();
@ -209,7 +209,7 @@ impl Send {
}
}
pub async fn delete(&self, conn: &DbConn) -> EmptyResult {
pub async fn delete(&self, conn: &mut DbConn) -> EmptyResult {
self.update_users_revision(conn).await;
if self.atype == SendType::File as i32 {
@ -224,13 +224,13 @@ impl Send {
}
/// Purge all sends that are past their deletion date.
pub async fn purge(conn: &DbConn) {
pub async fn purge(conn: &mut DbConn) {
for send in Self::find_by_past_deletion_date(conn).await {
send.delete(conn).await.ok();
}
}
pub async fn update_users_revision(&self, conn: &DbConn) -> Vec<String> {
pub async fn update_users_revision(&self, conn: &mut DbConn) -> Vec<String> {
let mut user_uuids = Vec::new();
match &self.user_uuid {
Some(user_uuid) => {
@ -244,14 +244,14 @@ impl Send {
user_uuids
}
pub async fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_user(user_uuid: &str, conn: &mut DbConn) -> EmptyResult {
for send in Self::find_by_user(user_uuid, conn).await {
send.delete(conn).await?;
}
Ok(())
}
pub async fn find_by_access_id(access_id: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_access_id(access_id: &str, conn: &mut DbConn) -> Option<Self> {
use data_encoding::BASE64URL_NOPAD;
use uuid::Uuid;
@ -268,7 +268,7 @@ impl Send {
Self::find_by_uuid(&uuid, conn).await
}
pub async fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! {conn: {
sends::table
.filter(sends::uuid.eq(uuid))
@ -278,7 +278,7 @@ impl Send {
}}
}
pub async fn find_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! {conn: {
sends::table
.filter(sends::user_uuid.eq(user_uuid))
@ -286,7 +286,7 @@ impl Send {
}}
}
pub async fn find_by_org(org_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_org(org_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! {conn: {
sends::table
.filter(sends::organization_uuid.eq(org_uuid))
@ -294,7 +294,7 @@ impl Send {
}}
}
pub async fn find_by_past_deletion_date(conn: &DbConn) -> Vec<Self> {
pub async fn find_by_past_deletion_date(conn: &mut DbConn) -> Vec<Self> {
let now = Utc::now().naive_utc();
db_run! {conn: {
sends::table

View file

@ -4,8 +4,8 @@ use crate::{api::EmptyResult, db::DbConn, error::MapResult};
db_object! {
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "twofactor"]
#[primary_key(uuid)]
#[diesel(table_name = twofactor)]
#[diesel(primary_key(uuid))]
pub struct TwoFactor {
pub uuid: String,
pub user_uuid: String,
@ -68,7 +68,7 @@ impl TwoFactor {
/// Database methods
impl TwoFactor {
pub async fn save(&self, conn: &DbConn) -> EmptyResult {
pub async fn save(&self, conn: &mut DbConn) -> EmptyResult {
db_run! { conn:
sqlite, mysql {
match diesel::replace_into(twofactor::table)
@ -107,7 +107,7 @@ impl TwoFactor {
}
}
pub async fn delete(self, conn: &DbConn) -> EmptyResult {
pub async fn delete(self, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(twofactor::table.filter(twofactor::uuid.eq(self.uuid)))
.execute(conn)
@ -115,7 +115,7 @@ impl TwoFactor {
}}
}
pub async fn find_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
pub async fn find_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
twofactor::table
.filter(twofactor::user_uuid.eq(user_uuid))
@ -126,7 +126,7 @@ impl TwoFactor {
}}
}
pub async fn find_by_user_and_type(user_uuid: &str, atype: i32, conn: &DbConn) -> Option<Self> {
pub async fn find_by_user_and_type(user_uuid: &str, atype: i32, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
twofactor::table
.filter(twofactor::user_uuid.eq(user_uuid))
@ -137,7 +137,7 @@ impl TwoFactor {
}}
}
pub async fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_user(user_uuid: &str, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(twofactor::table.filter(twofactor::user_uuid.eq(user_uuid)))
.execute(conn)
@ -145,7 +145,7 @@ impl TwoFactor {
}}
}
pub async fn migrate_u2f_to_webauthn(conn: &DbConn) -> EmptyResult {
pub async fn migrate_u2f_to_webauthn(conn: &mut DbConn) -> EmptyResult {
let u2f_factors = db_run! { conn: {
twofactor::table
.filter(twofactor::atype.eq(TwoFactorType::U2f as i32))

View file

@ -4,8 +4,8 @@ use crate::{api::EmptyResult, auth::ClientIp, db::DbConn, error::MapResult, CONF
db_object! {
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "twofactor_incomplete"]
#[primary_key(user_uuid, device_uuid)]
#[diesel(table_name = twofactor_incomplete)]
#[diesel(primary_key(user_uuid, device_uuid))]
pub struct TwoFactorIncomplete {
pub user_uuid: String,
// This device UUID is simply what's claimed by the device. It doesn't
@ -24,7 +24,7 @@ impl TwoFactorIncomplete {
device_uuid: &str,
device_name: &str,
ip: &ClientIp,
conn: &DbConn,
conn: &mut DbConn,
) -> EmptyResult {
if CONFIG.incomplete_2fa_time_limit() <= 0 || !CONFIG.mail_enabled() {
return Ok(());
@ -52,7 +52,7 @@ impl TwoFactorIncomplete {
}}
}
pub async fn mark_complete(user_uuid: &str, device_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn mark_complete(user_uuid: &str, device_uuid: &str, conn: &mut DbConn) -> EmptyResult {
if CONFIG.incomplete_2fa_time_limit() <= 0 || !CONFIG.mail_enabled() {
return Ok(());
}
@ -60,7 +60,7 @@ impl TwoFactorIncomplete {
Self::delete_by_user_and_device(user_uuid, device_uuid, conn).await
}
pub async fn find_by_user_and_device(user_uuid: &str, device_uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_user_and_device(user_uuid: &str, device_uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! { conn: {
twofactor_incomplete::table
.filter(twofactor_incomplete::user_uuid.eq(user_uuid))
@ -71,7 +71,7 @@ impl TwoFactorIncomplete {
}}
}
pub async fn find_logins_before(dt: &NaiveDateTime, conn: &DbConn) -> Vec<Self> {
pub async fn find_logins_before(dt: &NaiveDateTime, conn: &mut DbConn) -> Vec<Self> {
db_run! {conn: {
twofactor_incomplete::table
.filter(twofactor_incomplete::login_time.lt(dt))
@ -81,11 +81,11 @@ impl TwoFactorIncomplete {
}}
}
pub async fn delete(self, conn: &DbConn) -> EmptyResult {
pub async fn delete(self, conn: &mut DbConn) -> EmptyResult {
Self::delete_by_user_and_device(&self.user_uuid, &self.device_uuid, conn).await
}
pub async fn delete_by_user_and_device(user_uuid: &str, device_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_by_user_and_device(user_uuid: &str, device_uuid: &str, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(twofactor_incomplete::table
.filter(twofactor_incomplete::user_uuid.eq(user_uuid))
@ -95,7 +95,7 @@ impl TwoFactorIncomplete {
}}
}
pub async fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
pub async fn delete_all_by_user(user_uuid: &str, conn: &mut DbConn) -> EmptyResult {
db_run! { conn: {
diesel::delete(twofactor_incomplete::table.filter(twofactor_incomplete::user_uuid.eq(user_uuid)))
.execute(conn)

View file

@ -6,9 +6,9 @@ use crate::CONFIG;
db_object! {
#[derive(Identifiable, Queryable, Insertable, AsChangeset)]
#[table_name = "users"]
#[changeset_options(treat_none_as_null="true")]
#[primary_key(uuid)]
#[diesel(table_name = users)]
#[diesel(treat_none_as_null = true)]
#[diesel(primary_key(uuid))]
pub struct User {
pub uuid: String,
pub enabled: bool,
@ -32,7 +32,7 @@ db_object! {
pub private_key: Option<String>,
pub public_key: Option<String>,
#[column_name = "totp_secret"] // Note, this is only added to the UserDb structs, not to User
#[diesel(column_name = "totp_secret")] // Note, this is only added to the UserDb structs, not to User
_totp_secret: Option<String>,
pub totp_recover: Option<String>,
@ -49,8 +49,8 @@ db_object! {
}
#[derive(Identifiable, Queryable, Insertable)]
#[table_name = "invitations"]
#[primary_key(email)]
#[diesel(table_name = invitations)]
#[diesel(primary_key(email))]
pub struct Invitation {
pub email: String,
}
@ -192,18 +192,13 @@ use crate::db::DbConn;
use crate::api::EmptyResult;
use crate::error::MapResult;
use futures::{stream, stream::StreamExt};
/// Database methods
impl User {
pub async fn to_json(&self, conn: &DbConn) -> Value {
let orgs_json = stream::iter(UserOrganization::find_confirmed_by_user(&self.uuid, conn).await)
.then(|c| async {
let c = c; // Move out this single variable
c.to_json(conn).await
})
.collect::<Vec<Value>>()
.await;
pub async fn to_json(&self, conn: &mut DbConn) -> Value {
let mut orgs_json = Vec::new();
for c in UserOrganization::find_confirmed_by_user(&self.uuid, conn).await {
orgs_json.push(c.to_json(conn).await);
}
let twofactor_enabled = !TwoFactor::find_by_user(&self.uuid, conn).await.is_empty();
@ -235,7 +230,7 @@ impl User {
})
}
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult {
pub async fn save(&mut self, conn: &mut DbConn) -> EmptyResult {
if self.email.trim().is_empty() {
err!("User email can't be empty")
}
@ -273,7 +268,7 @@ impl User {
}
}
pub async fn delete(self, conn: &DbConn) -> EmptyResult {
pub async fn delete(self, conn: &mut DbConn) -> EmptyResult {
for user_org in UserOrganization::find_confirmed_by_user(&self.uuid, conn).await {
if user_org.atype == UserOrgType::Owner
&& UserOrganization::count_confirmed_by_org_and_type(&user_org.org_uuid, UserOrgType::Owner, conn).await
@ -301,13 +296,13 @@ impl User {
}}
}
pub async fn update_uuid_revision(uuid: &str, conn: &DbConn) {
pub async fn update_uuid_revision(uuid: &str, conn: &mut DbConn) {
if let Err(e) = Self::_update_revision(uuid, &Utc::now().naive_utc(), conn).await {
warn!("Failed to update revision for {}: {:#?}", uuid, e);
}
}
pub async fn update_all_revisions(conn: &DbConn) -> EmptyResult {
pub async fn update_all_revisions(conn: &mut DbConn) -> EmptyResult {
let updated_at = Utc::now().naive_utc();
db_run! {conn: {
@ -320,13 +315,13 @@ impl User {
}}
}
pub async fn update_revision(&mut self, conn: &DbConn) -> EmptyResult {
pub async fn update_revision(&mut self, conn: &mut DbConn) -> EmptyResult {
self.updated_at = Utc::now().naive_utc();
Self::_update_revision(&self.uuid, &self.updated_at, conn).await
}
async fn _update_revision(uuid: &str, date: &NaiveDateTime, conn: &DbConn) -> EmptyResult {
async fn _update_revision(uuid: &str, date: &NaiveDateTime, conn: &mut DbConn) -> EmptyResult {
db_run! {conn: {
crate::util::retry(|| {
diesel::update(users::table.filter(users::uuid.eq(uuid)))
@ -337,7 +332,7 @@ impl User {
}}
}
pub async fn find_by_mail(mail: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_mail(mail: &str, conn: &mut DbConn) -> Option<Self> {
let lower_mail = mail.to_lowercase();
db_run! {conn: {
users::table
@ -348,19 +343,19 @@ impl User {
}}
}
pub async fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_uuid(uuid: &str, conn: &mut DbConn) -> Option<Self> {
db_run! {conn: {
users::table.filter(users::uuid.eq(uuid)).first::<UserDb>(conn).ok().from_db()
}}
}
pub async fn get_all(conn: &DbConn) -> Vec<Self> {
pub async fn get_all(conn: &mut DbConn) -> Vec<Self> {
db_run! {conn: {
users::table.load::<UserDb>(conn).expect("Error loading users").from_db()
}}
}
pub async fn last_active(&self, conn: &DbConn) -> Option<NaiveDateTime> {
pub async fn last_active(&self, conn: &mut DbConn) -> Option<NaiveDateTime> {
match Device::find_latest_active_by_user(&self.uuid, conn).await {
Some(device) => Some(device.updated_at),
None => None,
@ -376,7 +371,7 @@ impl Invitation {
}
}
pub async fn save(&self, conn: &DbConn) -> EmptyResult {
pub async fn save(&self, conn: &mut DbConn) -> EmptyResult {
if self.email.trim().is_empty() {
err!("Invitation email can't be empty")
}
@ -401,7 +396,7 @@ impl Invitation {
}
}
pub async fn delete(self, conn: &DbConn) -> EmptyResult {
pub async fn delete(self, conn: &mut DbConn) -> EmptyResult {
db_run! {conn: {
diesel::delete(invitations::table.filter(invitations::email.eq(self.email)))
.execute(conn)
@ -409,7 +404,7 @@ impl Invitation {
}}
}
pub async fn find_by_mail(mail: &str, conn: &DbConn) -> Option<Self> {
pub async fn find_by_mail(mail: &str, conn: &mut DbConn) -> Option<Self> {
let lower_mail = mail.to_lowercase();
db_run! {conn: {
invitations::table
@ -420,7 +415,7 @@ impl Invitation {
}}
}
pub async fn take(mail: &str, conn: &DbConn) -> bool {
pub async fn take(mail: &str, conn: &mut DbConn) -> bool {
match Self::find_by_mail(mail, conn).await {
Some(invitation) => invitation.delete(conn).await.is_ok(),
None => false,