mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2025-09-10 10:45:57 +03:00
Add support for multiple simultaneous database features by using macros.
Diesel requires the following changes: - Separate connection and pool types per connection, the generate_connections! macro generates an enum with a variant per db type - Separate migrations and schemas, these were always imported as one type depending on db feature, now they are all imported under different module names - Separate model objects per connection, the db_object! macro generates one object for each connection with the diesel macros, a generic object, and methods to convert between the connection-specific and the generic ones - Separate connection queries, the db_run! macro allows writing only one that gets compiled for all databases or multiple ones
This commit is contained in:
@@ -3,26 +3,28 @@ use chrono::{NaiveDateTime, Utc};
|
||||
use super::User;
|
||||
use crate::CONFIG;
|
||||
|
||||
#[derive(Debug, Identifiable, Queryable, Insertable, Associations, AsChangeset)]
|
||||
#[table_name = "devices"]
|
||||
#[changeset_options(treat_none_as_null="true")]
|
||||
#[belongs_to(User, foreign_key = "user_uuid")]
|
||||
#[primary_key(uuid)]
|
||||
pub struct Device {
|
||||
pub uuid: String,
|
||||
pub created_at: NaiveDateTime,
|
||||
pub updated_at: NaiveDateTime,
|
||||
db_object! {
|
||||
#[derive(Debug, Identifiable, Queryable, Insertable, Associations, AsChangeset)]
|
||||
#[table_name = "devices"]
|
||||
#[changeset_options(treat_none_as_null="true")]
|
||||
#[belongs_to(User, foreign_key = "user_uuid")]
|
||||
#[primary_key(uuid)]
|
||||
pub struct Device {
|
||||
pub uuid: String,
|
||||
pub created_at: NaiveDateTime,
|
||||
pub updated_at: NaiveDateTime,
|
||||
|
||||
pub user_uuid: String,
|
||||
pub user_uuid: String,
|
||||
|
||||
pub name: String,
|
||||
/// https://github.com/bitwarden/core/tree/master/src/Core/Enums
|
||||
pub atype: i32,
|
||||
pub push_token: Option<String>,
|
||||
pub name: String,
|
||||
// https://github.com/bitwarden/core/tree/master/src/Core/Enums
|
||||
pub atype: i32,
|
||||
pub push_token: Option<String>,
|
||||
|
||||
pub refresh_token: String,
|
||||
pub refresh_token: String,
|
||||
|
||||
pub twofactor_remember: Option<String>,
|
||||
pub twofactor_remember: Option<String>,
|
||||
}
|
||||
}
|
||||
|
||||
/// Local methods
|
||||
@@ -105,41 +107,39 @@ impl Device {
|
||||
}
|
||||
}
|
||||
|
||||
use crate::db::schema::devices;
|
||||
use crate::db::DbConn;
|
||||
use diesel::prelude::*;
|
||||
|
||||
use crate::api::EmptyResult;
|
||||
use crate::error::MapResult;
|
||||
|
||||
/// Database methods
|
||||
impl Device {
|
||||
#[cfg(feature = "postgresql")]
|
||||
pub fn save(&mut self, conn: &DbConn) -> EmptyResult {
|
||||
self.updated_at = Utc::now().naive_utc();
|
||||
|
||||
crate::util::retry(
|
||||
|| diesel::insert_into(devices::table).values(&*self).on_conflict(devices::uuid).do_update().set(&*self).execute(&**conn),
|
||||
10,
|
||||
)
|
||||
.map_res("Error saving device")
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "postgresql"))]
|
||||
pub fn save(&mut self, conn: &DbConn) -> EmptyResult {
|
||||
self.updated_at = Utc::now().naive_utc();
|
||||
|
||||
crate::util::retry(
|
||||
|| diesel::replace_into(devices::table).values(&*self).execute(&**conn),
|
||||
10,
|
||||
)
|
||||
.map_res("Error saving device")
|
||||
db_run! { conn:
|
||||
sqlite, mysql {
|
||||
crate::util::retry(
|
||||
|| diesel::replace_into(devices::table).values(DeviceDb::to_db(self)).execute(conn),
|
||||
10,
|
||||
).map_res("Error saving device")
|
||||
}
|
||||
postgresql {
|
||||
let value = DeviceDb::to_db(self);
|
||||
crate::util::retry(
|
||||
|| diesel::insert_into(devices::table).values(&value).on_conflict(devices::uuid).do_update().set(&value).execute(conn),
|
||||
10,
|
||||
).map_res("Error saving device")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete(self, conn: &DbConn) -> EmptyResult {
|
||||
diesel::delete(devices::table.filter(devices::uuid.eq(self.uuid)))
|
||||
.execute(&**conn)
|
||||
.map_res("Error removing device")
|
||||
db_run! { conn: {
|
||||
diesel::delete(devices::table.filter(devices::uuid.eq(self.uuid)))
|
||||
.execute(conn)
|
||||
.map_res("Error removing device")
|
||||
}}
|
||||
}
|
||||
|
||||
pub fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult {
|
||||
@@ -150,23 +150,32 @@ impl Device {
|
||||
}
|
||||
|
||||
pub fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> {
|
||||
devices::table
|
||||
.filter(devices::uuid.eq(uuid))
|
||||
.first::<Self>(&**conn)
|
||||
.ok()
|
||||
db_run! { conn: {
|
||||
devices::table
|
||||
.filter(devices::uuid.eq(uuid))
|
||||
.first::<DeviceDb>(conn)
|
||||
.ok()
|
||||
.from_db()
|
||||
}}
|
||||
}
|
||||
|
||||
pub fn find_by_refresh_token(refresh_token: &str, conn: &DbConn) -> Option<Self> {
|
||||
devices::table
|
||||
.filter(devices::refresh_token.eq(refresh_token))
|
||||
.first::<Self>(&**conn)
|
||||
.ok()
|
||||
db_run! { conn: {
|
||||
devices::table
|
||||
.filter(devices::refresh_token.eq(refresh_token))
|
||||
.first::<DeviceDb>(conn)
|
||||
.ok()
|
||||
.from_db()
|
||||
}}
|
||||
}
|
||||
|
||||
pub fn find_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> {
|
||||
devices::table
|
||||
.filter(devices::user_uuid.eq(user_uuid))
|
||||
.load::<Self>(&**conn)
|
||||
.expect("Error loading devices")
|
||||
db_run! { conn: {
|
||||
devices::table
|
||||
.filter(devices::user_uuid.eq(user_uuid))
|
||||
.load::<DeviceDb>(conn)
|
||||
.expect("Error loading devices")
|
||||
.from_db()
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user