From 42af7c6dab113388a0db4fae0c196bae14761bc1 Mon Sep 17 00:00:00 2001 From: Emil Madsen Date: Mon, 20 May 2019 19:53:14 +0200 Subject: [PATCH 01/21] MySQL database --- src/config.rs | 2 +- src/db/mod.rs | 6 +++--- src/main.rs | 19 +------------------ 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/src/config.rs b/src/config.rs index 1bcb7557..39c27924 100644 --- a/src/config.rs +++ b/src/config.rs @@ -201,7 +201,7 @@ make_config! { data_folder: String, false, def, "data".to_string(); /// Database URL - database_url: String, false, auto, |c| format!("{}/{}", c.data_folder, "db.sqlite3"); + database_url: String, false, auto, |c| format!("mysql://root:my-secret-pw@localhost:3306/"); /// Icon chache folder icon_cache_folder: String, false, auto, |c| format!("{}/{}", c.data_folder, "icon_cache"); /// Attachments folder diff --git a/src/db/mod.rs b/src/db/mod.rs index 54ecfb19..90d8ab61 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use diesel::r2d2; use diesel::r2d2::ConnectionManager; -use diesel::sqlite::SqliteConnection; +use diesel::sqlite::MysqlConnection; use diesel::{Connection as DieselConnection, ConnectionError}; use rocket::http::Status; @@ -12,9 +12,9 @@ use rocket::{Outcome, Request, State}; use crate::CONFIG; /// An alias to the database connection used -type Connection = SqliteConnection; +type Connection = MysqlConnection; -/// An alias to the type for a pool of Diesel SQLite connections. +/// An alias to the type for a pool of Diesel MySQL connections. type Pool = r2d2::Pool>; /// Connection request guard type: a wrapper around an r2d2 pooled connection. diff --git a/src/main.rs b/src/main.rs index 51c68891..36c3f338 100644 --- a/src/main.rs +++ b/src/main.rs @@ -123,24 +123,7 @@ fn chain_syslog(logger: fern::Dispatch) -> fern::Dispatch { fn check_db() { let url = CONFIG.database_url(); - let path = Path::new(&url); - - if let Some(parent) = path.parent() { - use std::fs; - if fs::create_dir_all(parent).is_err() { - error!("Error creating database directory"); - exit(1); - } - } - - // Turn on WAL in SQLite - if CONFIG.enable_db_wal() { - use diesel::RunQueryDsl; - let connection = db::get_connection().expect("Can't conect to DB"); - diesel::sql_query("PRAGMA journal_mode=wal") - .execute(&connection) - .expect("Failed to turn on WAL"); - } + println!(url.to_string()); } fn check_rsa_keys() { From ab95a69dc8be20401bcc3167c51fb5f8b99ed2a2 Mon Sep 17 00:00:00 2001 From: Emil Madsen Date: Mon, 20 May 2019 21:12:41 +0200 Subject: [PATCH 02/21] Rework migrations for MySQL --- .env.template | 146 ------------------ Cargo.lock | 25 ++- Cargo.toml | 7 +- .../2018-01-14-171611_create_tables/up.sql | 32 ++-- .../up.sql | 21 ++- .../up.sql | 16 +- .../up.sql | 6 +- .../up.sql | 6 +- .../up.sql | 14 +- .../2018-09-10-111213_add_invites/up.sql | 4 +- .../up.sql | 2 +- src/config.rs | 3 +- src/db/mod.rs | 6 +- src/db/models/attachment.rs | 6 +- src/db/models/cipher.rs | 20 +-- src/db/models/collection.rs | 2 +- src/db/models/device.rs | 14 +- src/db/models/organization.rs | 16 +- src/db/models/two_factor.rs | 14 +- src/db/models/user.rs | 6 +- src/db/schema.rs | 106 ++++++------- src/main.rs | 3 +- 22 files changed, 154 insertions(+), 321 deletions(-) delete mode 100644 .env.template diff --git a/.env.template b/.env.template deleted file mode 100644 index 63c6c01a..00000000 --- a/.env.template +++ /dev/null @@ -1,146 +0,0 @@ -## Bitwarden_RS Configuration File -## Uncomment any of the following lines to change the defaults - -## Main data folder -# DATA_FOLDER=data - -## Individual folders, these override %DATA_FOLDER% -# DATABASE_URL=data/db.sqlite3 -# RSA_KEY_FILENAME=data/rsa_key -# ICON_CACHE_FOLDER=data/icon_cache -# ATTACHMENTS_FOLDER=data/attachments - -## Templates data folder, by default uses embedded templates -## Check source code to see the format -# TEMPLATES_FOLDER=/path/to/templates -## Automatically reload the templates for every request, slow, use only for development -# RELOAD_TEMPLATES=false - -## Cache time-to-live for successfully obtained icons, in seconds (0 is "forever") -# ICON_CACHE_TTL=2592000 -## Cache time-to-live for icons which weren't available, in seconds (0 is "forever") -# ICON_CACHE_NEGTTL=259200 - -## Web vault settings -# WEB_VAULT_FOLDER=web-vault/ -# WEB_VAULT_ENABLED=true - -## Enables websocket notifications -# WEBSOCKET_ENABLED=false - -## Controls the WebSocket server address and port -# WEBSOCKET_ADDRESS=0.0.0.0 -# WEBSOCKET_PORT=3012 - -## Enable extended logging -## This shows timestamps and allows logging to file and to syslog -### To enable logging to file, use the LOG_FILE env variable -### To enable syslog, use the USE_SYSLOG env variable -# EXTENDED_LOGGING=true - -## Logging to file -## This requires extended logging -## It's recommended to also set 'ROCKET_CLI_COLORS=off' -# LOG_FILE=/path/to/log - -## Logging to Syslog -## This requires extended logging -## It's recommended to also set 'ROCKET_CLI_COLORS=off' -# USE_SYSLOG=false - -## Log level -## Change the verbosity of the log output -## Valid values are "trace", "debug", "info", "warn", "error" and "off" -## This requires extended logging -# LOG_LEVEL=Info - -## Enable WAL for the DB -## Set to false to avoid enabling WAL during startup. -## Note that if the DB already has WAL enabled, you will also need to disable WAL in the DB, -## this setting only prevents bitwarden_rs from automatically enabling it on start. -## Please read project wiki page about this setting first before changing the value as it can -## cause performance degradation or might render the service unable to start. -# ENABLE_DB_WAL=true - -## Disable icon downloading -## Set to true to disable icon downloading, this would still serve icons from $ICON_CACHE_FOLDER, -## but it won't produce any external network request. Needs to set $ICON_CACHE_TTL to 0, -## otherwise it will delete them and they won't be downloaded again. -# DISABLE_ICON_DOWNLOAD=false - -## Icon download timeout -## Configure the timeout value when downloading the favicons. -## The default is 10 seconds, but this could be to low on slower network connections -# ICON_DOWNLOAD_TIMEOUT=10 - -## Icon blacklist Regex -## Any domains or IPs that match this regex won't be fetched by the icon service. -## Useful to hide other servers in the local network. Check the WIKI for more details -# ICON_BLACKLIST_REGEX=192\.168\.1\.[0-9].*^ - -## Disable 2FA remember -## Enabling this would force the users to use a second factor to login every time. -## Note that the checkbox would still be present, but ignored. -# DISABLE_2FA_REMEMBER=false - -## Controls if new users can register -# SIGNUPS_ALLOWED=true - -## Token for the admin interface, preferably use a long random string -## One option is to use 'openssl rand -base64 48' -## If not set, the admin panel is disabled -# ADMIN_TOKEN=Vy2VyYTTsKPv8W5aEOWUbB/Bt3DEKePbHmI4m9VcemUMS2rEviDowNAFqYi1xjmp -# DISABLE_ADMIN_TOKEN=false - -## Invitations org admins to invite users, even when signups are disabled -# INVITATIONS_ALLOWED=true - -## Controls the PBBKDF password iterations to apply on the server -## The change only applies when the password is changed -# PASSWORD_ITERATIONS=100000 - -## Whether password hint should be sent into the error response when the client request it -# SHOW_PASSWORD_HINT=true - -## Domain settings -## The domain must match the address from where you access the server -## It's recommended to configure this value, otherwise certain functionality might not work, -## like attachment downloads, email links and U2F. -## For U2F to work, the server must use HTTPS, you can use Let's Encrypt for free certs -# DOMAIN=https://bw.domain.tld:8443 - -## Yubico (Yubikey) Settings -## Set your Client ID and Secret Key for Yubikey OTP -## You can generate it here: https://upgrade.yubico.com/getapikey/ -## You can optionally specify a custom OTP server -# YUBICO_CLIENT_ID=11111 -# YUBICO_SECRET_KEY=AAAAAAAAAAAAAAAAAAAAAAAA -# YUBICO_SERVER=http://yourdomain.com/wsapi/2.0/verify - -## Duo Settings -## You need to configure all options to enable global Duo support, otherwise users would need to configure it themselves -## Create an account and protect an application as mentioned in this link (only the first step, not the rest): -## https://help.bitwarden.com/article/setup-two-step-login-duo/#create-a-duo-security-account -## Then set the following options, based on the values obtained from the last step: -# DUO_IKEY= -# DUO_SKEY= -# DUO_HOST= -## After that, you should be able to follow the rest of the guide linked above, -## ignoring the fields that ask for the values that you already configured beforehand. - -## Rocket specific settings, check Rocket documentation to learn more -# ROCKET_ENV=staging -# ROCKET_ADDRESS=0.0.0.0 # Enable this to test mobile app -# ROCKET_PORT=8000 -# ROCKET_TLS={certs="/path/to/certs.pem",key="/path/to/key.pem"} - -## Mail specific settings, set SMTP_HOST and SMTP_FROM to enable the mail service. -## To make sure the email links are pointing to the correct host, set the DOMAIN variable. -## Note: if SMTP_USERNAME is specified, SMTP_PASSWORD is mandatory -# SMTP_HOST=smtp.domain.tld -# SMTP_FROM=bitwarden-rs@domain.tld -# SMTP_FROM_NAME=Bitwarden_RS -# SMTP_PORT=587 -# SMTP_SSL=true -# SMTP_USERNAME=username -# SMTP_PASSWORD=password diff --git a/Cargo.lock b/Cargo.lock index 2e0b6958..025ed4ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,7 +116,6 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lettre 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "lettre_email 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libsqlite3-sys 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "multipart 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -429,8 +428,9 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "diesel_derives 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsqlite3-sys 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mysqlclient-sys 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "r2d2 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1044,16 +1044,6 @@ name = "libc" version = "0.2.55" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "libsqlite3-sys" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "lock_api" version = "0.1.5" @@ -1250,6 +1240,15 @@ dependencies = [ "twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mysqlclient-sys" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "native-tls" version = "0.2.3" @@ -2861,7 +2860,6 @@ dependencies = [ "checksum lettre 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "646aee0a55545eaffdf0df1ac19b500b51adb3095ec4dfdc704134e56ea23531" "checksum lettre_email 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae1b3d43e4bb7beb9974a359cbb3ea4f93dfba6c1c0c6e9c9f82e538e0f9ab9f" "checksum libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "42914d39aad277d9e176efbdad68acb1d5443ab65afe0e0e4f0d49352a950880" -"checksum libsqlite3-sys 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd6457c70bbff456d9fe49deaba35ec47c3e598bf8d7950ff0575ceb7a8a6ad1" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" @@ -2883,6 +2881,7 @@ dependencies = [ "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum multipart 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "136eed74cadb9edd2651ffba732b19a450316b680e4f48d6c79e905799e19d01" +"checksum mysqlclient-sys 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7e9637d93448044078aaafea7419aed69d301b4a12bcc4aa0ae856eb169bef85" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30" diff --git a/Cargo.toml b/Cargo.toml index f22fb7a1..148ebc81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,11 +47,8 @@ log = "0.4.6" fern = { version = "0.5.8", features = ["syslog-4"] } # A safe, extensible ORM and Query builder -diesel = { version = "1.4.2", features = ["sqlite", "chrono", "r2d2"] } -diesel_migrations = { version = "1.4.0", features = ["sqlite"] } - -# Bundled SQLite -libsqlite3-sys = { version = "0.12.0", features = ["bundled"] } +diesel = { version = "1.4.2", features = ["mysql", "chrono", "r2d2"] } +diesel_migrations = { version = "1.4.0", features = ["mysql"] } # Crypto library ring = "0.14.6" diff --git a/migrations/2018-01-14-171611_create_tables/up.sql b/migrations/2018-01-14-171611_create_tables/up.sql index 263ed8f3..0a1fc8c9 100644 --- a/migrations/2018-01-14-171611_create_tables/up.sql +++ b/migrations/2018-01-14-171611_create_tables/up.sql @@ -1,14 +1,14 @@ CREATE TABLE users ( - uuid TEXT NOT NULL PRIMARY KEY, + uuid VARCHAR(40) NOT NULL PRIMARY KEY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, - email TEXT NOT NULL UNIQUE, + email VARCHAR(255) NOT NULL UNIQUE, name TEXT NOT NULL, password_hash BLOB NOT NULL, salt BLOB NOT NULL, password_iterations INTEGER NOT NULL, password_hint TEXT, - key TEXT NOT NULL, + akey TEXT NOT NULL, private_key TEXT, public_key TEXT, totp_secret TEXT, @@ -19,24 +19,24 @@ CREATE TABLE users ( ); CREATE TABLE devices ( - uuid TEXT NOT NULL PRIMARY KEY, + uuid VARCHAR(40) NOT NULL PRIMARY KEY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, - user_uuid TEXT NOT NULL REFERENCES users (uuid), + user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), name TEXT NOT NULL, - type INTEGER NOT NULL, + atype INTEGER NOT NULL, push_token TEXT, refresh_token TEXT NOT NULL ); CREATE TABLE ciphers ( - uuid TEXT NOT NULL PRIMARY KEY, + uuid VARCHAR(40) NOT NULL PRIMARY KEY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, - user_uuid TEXT NOT NULL REFERENCES users (uuid), - folder_uuid TEXT REFERENCES folders (uuid), - organization_uuid TEXT, - type INTEGER NOT NULL, + user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), + folder_uuid VARCHAR(40) REFERENCES folders (uuid), + organization_uuid VARCHAR(40), + atype INTEGER NOT NULL, name TEXT NOT NULL, notes TEXT, fields TEXT, @@ -45,18 +45,18 @@ CREATE TABLE ciphers ( ); CREATE TABLE attachments ( - id TEXT NOT NULL PRIMARY KEY, - cipher_uuid TEXT NOT NULL REFERENCES ciphers (uuid), + id VARCHAR(40) NOT NULL PRIMARY KEY, + cipher_uuid VARCHAR(40) NOT NULL REFERENCES ciphers (uuid), file_name TEXT NOT NULL, file_size INTEGER NOT NULL ); CREATE TABLE folders ( - uuid TEXT NOT NULL PRIMARY KEY, + uuid VARCHAR(40) NOT NULL PRIMARY KEY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, - user_uuid TEXT NOT NULL REFERENCES users (uuid), + user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), name TEXT NOT NULL ); - \ No newline at end of file + diff --git a/migrations/2018-02-17-205753_create_collections_and_orgs/up.sql b/migrations/2018-02-17-205753_create_collections_and_orgs/up.sql index 29601a4a..8d5508ff 100644 --- a/migrations/2018-02-17-205753_create_collections_and_orgs/up.sql +++ b/migrations/2018-02-17-205753_create_collections_and_orgs/up.sql @@ -1,31 +1,30 @@ CREATE TABLE collections ( - uuid TEXT NOT NULL PRIMARY KEY, - org_uuid TEXT NOT NULL REFERENCES organizations (uuid), + uuid VARCHAR(40) NOT NULL PRIMARY KEY, + org_uuid VARCHAR(40) NOT NULL REFERENCES organizations (uuid), name TEXT NOT NULL ); CREATE TABLE organizations ( - uuid TEXT NOT NULL PRIMARY KEY, + uuid VARCHAR(40) NOT NULL PRIMARY KEY, name TEXT NOT NULL, billing_email TEXT NOT NULL ); - CREATE TABLE users_collections ( - user_uuid TEXT NOT NULL REFERENCES users (uuid), - collection_uuid TEXT NOT NULL REFERENCES collections (uuid), + user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), + collection_uuid VARCHAR(40) NOT NULL REFERENCES collections (uuid), PRIMARY KEY (user_uuid, collection_uuid) ); CREATE TABLE users_organizations ( - uuid TEXT NOT NULL PRIMARY KEY, - user_uuid TEXT NOT NULL REFERENCES users (uuid), - org_uuid TEXT NOT NULL REFERENCES organizations (uuid), + uuid VARCHAR(40) NOT NULL PRIMARY KEY, + user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), + org_uuid VARCHAR(40) NOT NULL REFERENCES organizations (uuid), access_all BOOLEAN NOT NULL, - key TEXT NOT NULL, + akey TEXT NOT NULL, status INTEGER NOT NULL, - type INTEGER NOT NULL, + atype INTEGER NOT NULL, UNIQUE (user_uuid, org_uuid) ); diff --git a/migrations/2018-04-27-155151_create_users_ciphers/up.sql b/migrations/2018-04-27-155151_create_users_ciphers/up.sql index 747f9e29..00989e4a 100644 --- a/migrations/2018-04-27-155151_create_users_ciphers/up.sql +++ b/migrations/2018-04-27-155151_create_users_ciphers/up.sql @@ -1,13 +1,13 @@ ALTER TABLE ciphers RENAME TO oldCiphers; CREATE TABLE ciphers ( - uuid TEXT NOT NULL PRIMARY KEY, + uuid VARCHAR(40) NOT NULL PRIMARY KEY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, - user_uuid TEXT REFERENCES users (uuid), -- Make this optional - organization_uuid TEXT REFERENCES organizations (uuid), -- Add reference to orgs table + user_uuid VARCHAR(40) REFERENCES users (uuid), -- Make this optional + organization_uuid VARCHAR(40) REFERENCES organizations (uuid), -- Add reference to orgs table -- Remove folder_uuid - type INTEGER NOT NULL, + atype INTEGER NOT NULL, name TEXT NOT NULL, notes TEXT, fields TEXT, @@ -16,14 +16,14 @@ CREATE TABLE ciphers ( ); CREATE TABLE folders_ciphers ( - cipher_uuid TEXT NOT NULL REFERENCES ciphers (uuid), - folder_uuid TEXT NOT NULL REFERENCES folders (uuid), + cipher_uuid VARCHAR(40) NOT NULL REFERENCES ciphers (uuid), + folder_uuid VARCHAR(40) NOT NULL REFERENCES folders (uuid), PRIMARY KEY (cipher_uuid, folder_uuid) ); -INSERT INTO ciphers (uuid, created_at, updated_at, user_uuid, organization_uuid, type, name, notes, fields, data, favorite) -SELECT uuid, created_at, updated_at, user_uuid, organization_uuid, type, name, notes, fields, data, favorite FROM oldCiphers; +INSERT INTO ciphers (uuid, created_at, updated_at, user_uuid, organization_uuid, atype, name, notes, fields, data, favorite) +SELECT uuid, created_at, updated_at, user_uuid, organization_uuid, atype, name, notes, fields, data, favorite FROM oldCiphers; INSERT INTO folders_ciphers (cipher_uuid, folder_uuid) SELECT uuid, folder_uuid FROM oldCiphers WHERE folder_uuid IS NOT NULL; diff --git a/migrations/2018-05-08-161616_create_collection_cipher_map/up.sql b/migrations/2018-05-08-161616_create_collection_cipher_map/up.sql index 9fdd7066..fe407be1 100644 --- a/migrations/2018-05-08-161616_create_collection_cipher_map/up.sql +++ b/migrations/2018-05-08-161616_create_collection_cipher_map/up.sql @@ -1,5 +1,5 @@ CREATE TABLE ciphers_collections ( - cipher_uuid TEXT NOT NULL REFERENCES ciphers (uuid), - collection_uuid TEXT NOT NULL REFERENCES collections (uuid), + cipher_uuid VARCHAR(40) NOT NULL REFERENCES ciphers (uuid), + collection_uuid VARCHAR(40) NOT NULL REFERENCES collections (uuid), PRIMARY KEY (cipher_uuid, collection_uuid) -); \ No newline at end of file +); diff --git a/migrations/2018-05-25-232323_update_attachments_reference/up.sql b/migrations/2018-05-25-232323_update_attachments_reference/up.sql index b7adb77e..eef50768 100644 --- a/migrations/2018-05-25-232323_update_attachments_reference/up.sql +++ b/migrations/2018-05-25-232323_update_attachments_reference/up.sql @@ -1,8 +1,8 @@ ALTER TABLE attachments RENAME TO oldAttachments; CREATE TABLE attachments ( - id TEXT NOT NULL PRIMARY KEY, - cipher_uuid TEXT NOT NULL REFERENCES ciphers (uuid), + id VARCHAR(40) NOT NULL PRIMARY KEY, + cipher_uuid VARCHAR(40) NOT NULL REFERENCES ciphers (uuid), file_name TEXT NOT NULL, file_size INTEGER NOT NULL @@ -11,4 +11,4 @@ CREATE TABLE attachments ( INSERT INTO attachments (id, cipher_uuid, file_name, file_size) SELECT id, cipher_uuid, file_name, file_size FROM oldAttachments; -DROP TABLE oldAttachments; \ No newline at end of file +DROP TABLE oldAttachments; diff --git a/migrations/2018-07-11-181453_create_u2f_twofactor/up.sql b/migrations/2018-07-11-181453_create_u2f_twofactor/up.sql index 3e78e721..7da3a51b 100644 --- a/migrations/2018-07-11-181453_create_u2f_twofactor/up.sql +++ b/migrations/2018-07-11-181453_create_u2f_twofactor/up.sql @@ -1,15 +1,15 @@ CREATE TABLE twofactor ( - uuid TEXT NOT NULL PRIMARY KEY, - user_uuid TEXT NOT NULL REFERENCES users (uuid), - type INTEGER NOT NULL, + uuid VARCHAR(40) NOT NULL PRIMARY KEY, + user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), + atype INTEGER NOT NULL, enabled BOOLEAN NOT NULL, data TEXT NOT NULL, - UNIQUE (user_uuid, type) + UNIQUE (user_uuid, atype) ); -INSERT INTO twofactor (uuid, user_uuid, type, enabled, data) -SELECT lower(hex(randomblob(16))) , uuid, 0, 1, u.totp_secret FROM users u where u.totp_secret IS NOT NULL; +INSERT INTO twofactor (uuid, user_uuid, atype, enabled, data) +SELECT UUID(), uuid, 0, 1, u.totp_secret FROM users u where u.totp_secret IS NOT NULL; -UPDATE users SET totp_secret = NULL; -- Instead of recreating the table, just leave the columns empty \ No newline at end of file +UPDATE users SET totp_secret = NULL; -- Instead of recreating the table, just leave the columns empty diff --git a/migrations/2018-09-10-111213_add_invites/up.sql b/migrations/2018-09-10-111213_add_invites/up.sql index b42e9a2a..4245aa82 100644 --- a/migrations/2018-09-10-111213_add_invites/up.sql +++ b/migrations/2018-09-10-111213_add_invites/up.sql @@ -1,3 +1,3 @@ CREATE TABLE invitations ( - email TEXT NOT NULL PRIMARY KEY -); \ No newline at end of file + email VARCHAR(255) NOT NULL PRIMARY KEY +); diff --git a/migrations/2018-11-27-152651_add_att_key_columns/up.sql b/migrations/2018-11-27-152651_add_att_key_columns/up.sql index 4a73a8c9..858d3778 100644 --- a/migrations/2018-11-27-152651_add_att_key_columns/up.sql +++ b/migrations/2018-11-27-152651_add_att_key_columns/up.sql @@ -1,3 +1,3 @@ ALTER TABLE attachments ADD COLUMN - key TEXT; \ No newline at end of file + akey TEXT; diff --git a/src/config.rs b/src/config.rs index 775f2d43..b599bedc 100644 --- a/src/config.rs +++ b/src/config.rs @@ -204,7 +204,8 @@ make_config! { data_folder: String, false, def, "data".to_string(); /// Database URL - database_url: String, false, auto, |c| format!("mysql://root:my-secret-pw@localhost:3306/"); + /// docker run -e MYSQL_ROOT_PASSWORD=my-secret-pw -e MYSQL_DATABASE=bitwarden -p 3306:3306 -d mysql:5.7 + database_url: String, false, auto, |_c| format!("mysql://root:my-secret-pw@0.0.0.0:3306/bitwarden"); /// Icon chache folder icon_cache_folder: String, false, auto, |c| format!("{}/{}", c.data_folder, "icon_cache"); /// Attachments folder diff --git a/src/db/mod.rs b/src/db/mod.rs index 90d8ab61..18bf0969 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use diesel::r2d2; use diesel::r2d2::ConnectionManager; -use diesel::sqlite::MysqlConnection; +use diesel::mysql::MysqlConnection; use diesel::{Connection as DieselConnection, ConnectionError}; use rocket::http::Status; @@ -31,7 +31,9 @@ pub fn init_pool() -> Pool { } pub fn get_connection() -> Result { - Connection::establish(&CONFIG.database_url()) + let url = CONFIG.database_url(); + println!("{}", url.to_string()); + Connection::establish(&url) } /// Attempts to retrieve a single connection from the managed database pool. If diff --git a/src/db/models/attachment.rs b/src/db/models/attachment.rs index b27704f0..030400e7 100644 --- a/src/db/models/attachment.rs +++ b/src/db/models/attachment.rs @@ -12,7 +12,7 @@ pub struct Attachment { pub cipher_uuid: String, pub file_name: String, pub file_size: i32, - pub key: Option, + pub akey: Option, } /// Local methods @@ -23,7 +23,7 @@ impl Attachment { cipher_uuid, file_name, file_size, - key: None, + akey: None, } } @@ -43,7 +43,7 @@ impl Attachment { "FileName": self.file_name, "Size": self.file_size.to_string(), "SizeName": display_size, - "Key": self.key, + "Key": self.akey, "Object": "attachment" }) } diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs index 21cabb90..0bd7673c 100644 --- a/src/db/models/cipher.rs +++ b/src/db/models/cipher.rs @@ -24,7 +24,7 @@ pub struct Cipher { Card = 3, Identity = 4 */ - pub type_: i32, + pub atype: i32, pub name: String, pub notes: Option, pub fields: Option, @@ -37,7 +37,7 @@ pub struct Cipher { /// Local methods impl Cipher { - pub fn new(type_: i32, name: String) -> Self { + pub fn new(atype: i32, name: String) -> Self { let now = Utc::now().naive_utc(); Self { @@ -48,7 +48,7 @@ impl Cipher { user_uuid: None, organization_uuid: None, - type_, + atype, favorite: false, name, @@ -94,7 +94,7 @@ impl Cipher { // TODO: ******* Backwards compat start ********** // To remove backwards compatibility, just remove this entire section // and remove the compat code from ciphers::update_cipher_from_data - if self.type_ == 1 && data_json["Uris"].is_array() { + if self.atype == 1 && data_json["Uris"].is_array() { let uri = data_json["Uris"][0]["Uri"].clone(); data_json["Uri"] = uri; } @@ -102,7 +102,7 @@ impl Cipher { let mut json_object = json!({ "Id": self.uuid, - "Type": self.type_, + "Type": self.atype, "RevisionDate": format_date(&self.updated_at), "FolderId": self.get_folder_uuid(&user_uuid, &conn), "Favorite": self.favorite, @@ -123,7 +123,7 @@ impl Cipher { "PasswordHistory": password_history_json, }); - let key = match self.type_ { + let key = match self.atype { 1 => "Login", 2 => "SecureNote", 3 => "Card", @@ -237,7 +237,7 @@ impl Cipher { // Cipher owner users_organizations::access_all.eq(true).or( // access_all in Organization - users_organizations::type_.le(UserOrgType::Admin as i32).or( + users_organizations::atype.le(UserOrgType::Admin as i32).or( // Org admin or owner users_collections::user_uuid.eq(user_uuid).and( users_collections::read_only.eq(false), //R/W access to collection @@ -268,7 +268,7 @@ impl Cipher { // Cipher owner users_organizations::access_all.eq(true).or( // access_all in Organization - users_organizations::type_.le(UserOrgType::Admin as i32).or( + users_organizations::atype.le(UserOrgType::Admin as i32).or( // Org admin or owner users_collections::user_uuid.eq(user_uuid), // Access to Collection ), @@ -315,7 +315,7 @@ impl Cipher { )) .filter(ciphers::user_uuid.eq(user_uuid).or( // Cipher owner users_organizations::access_all.eq(true).or( // access_all in Organization - users_organizations::type_.le(UserOrgType::Admin as i32).or( // Org admin or owner + users_organizations::atype.le(UserOrgType::Admin as i32).or( // Org admin or owner users_collections::user_uuid.eq(user_uuid).and( // Access to Collection users_organizations::status.eq(UserOrgStatus::Confirmed as i32) ) @@ -365,7 +365,7 @@ impl Cipher { .filter(ciphers_collections::cipher_uuid.eq(&self.uuid)) .filter(users_collections::user_uuid.eq(user_id).or( // User has access to collection users_organizations::access_all.eq(true).or( // User has access all - users_organizations::type_.le(UserOrgType::Admin as i32) // User is admin or owner + users_organizations::atype.le(UserOrgType::Admin as i32) // User is admin or owner ) )) .select(ciphers_collections::collection_uuid) diff --git a/src/db/models/collection.rs b/src/db/models/collection.rs index c6047aa7..e2b58cf1 100644 --- a/src/db/models/collection.rs +++ b/src/db/models/collection.rs @@ -146,7 +146,7 @@ impl Collection { .filter( users_collections::collection_uuid.eq(uuid).or( // Directly accessed collection users_organizations::access_all.eq(true).or( // access_all in Organization - users_organizations::type_.le(UserOrgType::Admin as i32) // Org admin or owner + users_organizations::atype.le(UserOrgType::Admin as i32) // Org admin or owner ) ) ).select(collections::all_columns) diff --git a/src/db/models/device.rs b/src/db/models/device.rs index 157bd9a3..83824bac 100644 --- a/src/db/models/device.rs +++ b/src/db/models/device.rs @@ -15,7 +15,7 @@ pub struct Device { pub name: String, /// https://github.com/bitwarden/core/tree/master/src/Core/Enums - pub type_: i32, + pub atype: i32, pub push_token: Option, pub refresh_token: String, @@ -25,7 +25,7 @@ pub struct Device { /// Local methods impl Device { - pub fn new(uuid: String, user_uuid: String, name: String, type_: i32) -> Self { + pub fn new(uuid: String, user_uuid: String, name: String, atype: i32) -> Self { let now = Utc::now().naive_utc(); Self { @@ -35,7 +35,7 @@ impl Device { user_uuid, name, - type_, + atype, push_token: None, refresh_token: String::new(), @@ -70,10 +70,10 @@ impl Device { let time_now = Utc::now().naive_utc(); self.updated_at = time_now; - let orgowner: Vec<_> = orgs.iter().filter(|o| o.type_ == 0).map(|o| o.org_uuid.clone()).collect(); - let orgadmin: Vec<_> = orgs.iter().filter(|o| o.type_ == 1).map(|o| o.org_uuid.clone()).collect(); - let orguser: Vec<_> = orgs.iter().filter(|o| o.type_ == 2).map(|o| o.org_uuid.clone()).collect(); - let orgmanager: Vec<_> = orgs.iter().filter(|o| o.type_ == 3).map(|o| o.org_uuid.clone()).collect(); + let orgowner: Vec<_> = orgs.iter().filter(|o| o.atype == 0).map(|o| o.org_uuid.clone()).collect(); + let orgadmin: Vec<_> = orgs.iter().filter(|o| o.atype == 1).map(|o| o.org_uuid.clone()).collect(); + let orguser: Vec<_> = orgs.iter().filter(|o| o.atype == 2).map(|o| o.org_uuid.clone()).collect(); + let orgmanager: Vec<_> = orgs.iter().filter(|o| o.atype == 3).map(|o| o.org_uuid.clone()).collect(); // Create the JWT claims struct, to send to the client diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs index 491c4fc3..463e1d0f 100644 --- a/src/db/models/organization.rs +++ b/src/db/models/organization.rs @@ -23,7 +23,7 @@ pub struct UserOrganization { pub access_all: bool, pub key: String, pub status: i32, - pub type_: i32, + pub atype: i32, } pub enum UserOrgStatus { @@ -198,7 +198,7 @@ impl UserOrganization { access_all: false, key: String::new(), status: UserOrgStatus::Accepted as i32, - type_: UserOrgType::User as i32, + atype: UserOrgType::User as i32, } } } @@ -268,7 +268,7 @@ impl UserOrganization { // These are per user "Key": self.key, "Status": self.status, - "Type": self.type_, + "Type": self.atype, "Enabled": true, "Object": "profileOrganization", @@ -285,7 +285,7 @@ impl UserOrganization { "Email": user.email, "Status": self.status, - "Type": self.type_, + "Type": self.atype, "AccessAll": self.access_all, "Object": "organizationUserUserDetails", @@ -315,7 +315,7 @@ impl UserOrganization { "UserId": self.user_uuid, "Status": self.status, - "Type": self.type_, + "Type": self.atype, "AccessAll": self.access_all, "Collections": coll_uuids, @@ -357,7 +357,7 @@ impl UserOrganization { } pub fn has_full_access(self) -> bool { - self.access_all || self.type_ >= UserOrgType::Admin + self.access_all || self.atype >= UserOrgType::Admin } pub fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option { @@ -405,10 +405,10 @@ impl UserOrganization { .expect("Error loading user organizations") } - pub fn find_by_org_and_type(org_uuid: &str, type_: i32, conn: &DbConn) -> Vec { + pub fn find_by_org_and_type(org_uuid: &str, atype: i32, conn: &DbConn) -> Vec { users_organizations::table .filter(users_organizations::org_uuid.eq(org_uuid)) - .filter(users_organizations::type_.eq(type_)) + .filter(users_organizations::atype.eq(atype)) .load::(&**conn) .expect("Error loading user organizations") } diff --git a/src/db/models/two_factor.rs b/src/db/models/two_factor.rs index fc48313d..30a7b475 100644 --- a/src/db/models/two_factor.rs +++ b/src/db/models/two_factor.rs @@ -9,7 +9,7 @@ use super::User; pub struct TwoFactor { pub uuid: String, pub user_uuid: String, - pub type_: i32, + pub atype: i32, pub enabled: bool, pub data: String, } @@ -32,11 +32,11 @@ pub enum TwoFactorType { /// Local methods impl TwoFactor { - pub fn new(user_uuid: String, type_: TwoFactorType, data: String) -> Self { + pub fn new(user_uuid: String, atype: TwoFactorType, data: String) -> Self { Self { uuid: crate::util::get_uuid(), user_uuid, - type_: type_ as i32, + atype: atype as i32, enabled: true, data, } @@ -53,7 +53,7 @@ impl TwoFactor { pub fn to_json_list(&self) -> Value { json!({ "Enabled": self.enabled, - "Type": self.type_, + "Type": self.atype, "Object": "twoFactorProvider" }) } @@ -85,15 +85,15 @@ impl TwoFactor { pub fn find_by_user(user_uuid: &str, conn: &DbConn) -> Vec { twofactor::table .filter(twofactor::user_uuid.eq(user_uuid)) - .filter(twofactor::type_.lt(1000)) // Filter implementation types + .filter(twofactor::atype.lt(1000)) // Filter implementation types .load::(&**conn) .expect("Error loading twofactor") } - pub fn find_by_user_and_type(user_uuid: &str, type_: i32, conn: &DbConn) -> Option { + pub fn find_by_user_and_type(user_uuid: &str, atype: i32, conn: &DbConn) -> Option { twofactor::table .filter(twofactor::user_uuid.eq(user_uuid)) - .filter(twofactor::type_.eq(type_)) + .filter(twofactor::atype.eq(atype)) .first::(&**conn) .ok() } diff --git a/src/db/models/user.rs b/src/db/models/user.rs index 150a97b0..2f7183bf 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -20,7 +20,7 @@ pub struct User { pub password_iterations: i32, pub password_hint: Option, - pub key: String, + pub akey: String, pub private_key: Option, pub public_key: Option, @@ -58,7 +58,7 @@ impl User { updated_at: now, name: email.clone(), email, - key: String::new(), + akey: String::new(), password_hash: Vec::new(), salt: crypto::get_random_64(), @@ -140,7 +140,7 @@ impl User { "MasterPasswordHint": self.password_hint, "Culture": "en-US", "TwoFactorEnabled": twofactor_enabled, - "Key": self.key, + "Key": self.akey, "PrivateKey": self.private_key, "SecurityStamp": self.security_stamp, "Organizations": orgs_json, diff --git a/src/db/schema.rs b/src/db/schema.rs index 48168537..33c4301d 100644 --- a/src/db/schema.rs +++ b/src/db/schema.rs @@ -1,22 +1,21 @@ table! { attachments (id) { - id -> Text, - cipher_uuid -> Text, + id -> Varchar, + cipher_uuid -> Varchar, file_name -> Text, file_size -> Integer, - key -> Nullable, + akey -> Nullable, } } table! { ciphers (uuid) { - uuid -> Text, - created_at -> Timestamp, - updated_at -> Timestamp, - user_uuid -> Nullable, - organization_uuid -> Nullable, - #[sql_name = "type"] - type_ -> Integer, + uuid -> Varchar, + created_at -> Datetime, + updated_at -> Datetime, + user_uuid -> Nullable, + organization_uuid -> Nullable, + atype -> Integer, name -> Text, notes -> Nullable, fields -> Nullable, @@ -28,28 +27,27 @@ table! { table! { ciphers_collections (cipher_uuid, collection_uuid) { - cipher_uuid -> Text, - collection_uuid -> Text, + cipher_uuid -> Varchar, + collection_uuid -> Varchar, } } table! { collections (uuid) { - uuid -> Text, - org_uuid -> Text, + uuid -> Varchar, + org_uuid -> Varchar, name -> Text, } } table! { devices (uuid) { - uuid -> Text, - created_at -> Timestamp, - updated_at -> Timestamp, - user_uuid -> Text, + uuid -> Varchar, + created_at -> Datetime, + updated_at -> Datetime, + user_uuid -> Varchar, name -> Text, - #[sql_name = "type"] - type_ -> Integer, + atype -> Integer, push_token -> Nullable, refresh_token -> Text, twofactor_remember -> Nullable, @@ -58,30 +56,30 @@ table! { table! { folders (uuid) { - uuid -> Text, - created_at -> Timestamp, - updated_at -> Timestamp, - user_uuid -> Text, + uuid -> Varchar, + created_at -> Datetime, + updated_at -> Datetime, + user_uuid -> Varchar, name -> Text, } } table! { folders_ciphers (cipher_uuid, folder_uuid) { - cipher_uuid -> Text, - folder_uuid -> Text, + cipher_uuid -> Varchar, + folder_uuid -> Varchar, } } table! { invitations (email) { - email -> Text, + email -> Varchar, } } table! { organizations (uuid) { - uuid -> Text, + uuid -> Varchar, name -> Text, billing_email -> Text, } @@ -89,10 +87,9 @@ table! { table! { twofactor (uuid) { - uuid -> Text, - user_uuid -> Text, - #[sql_name = "type"] - type_ -> Integer, + uuid -> Varchar, + user_uuid -> Varchar, + atype -> Integer, enabled -> Bool, data -> Text, } @@ -100,16 +97,16 @@ table! { table! { users (uuid) { - uuid -> Text, - created_at -> Timestamp, - updated_at -> Timestamp, - email -> Text, + uuid -> Varchar, + created_at -> Datetime, + updated_at -> Datetime, + email -> Varchar, name -> Text, - password_hash -> Binary, - salt -> Binary, + password_hash -> Blob, + salt -> Blob, password_iterations -> Integer, password_hint -> Nullable, - key -> Text, + akey -> Text, private_key -> Nullable, public_key -> Nullable, totp_secret -> Nullable, @@ -124,41 +121,24 @@ table! { table! { users_collections (user_uuid, collection_uuid) { - user_uuid -> Text, - collection_uuid -> Text, + user_uuid -> Varchar, + collection_uuid -> Varchar, read_only -> Bool, } } table! { users_organizations (uuid) { - uuid -> Text, - user_uuid -> Text, - org_uuid -> Text, + uuid -> Varchar, + user_uuid -> Varchar, + org_uuid -> Varchar, access_all -> Bool, - key -> Text, + akey -> Text, status -> Integer, - #[sql_name = "type"] - type_ -> Integer, + atype -> Integer, } } -joinable!(attachments -> ciphers (cipher_uuid)); -joinable!(ciphers -> organizations (organization_uuid)); -joinable!(ciphers -> users (user_uuid)); -joinable!(ciphers_collections -> ciphers (cipher_uuid)); -joinable!(ciphers_collections -> collections (collection_uuid)); -joinable!(collections -> organizations (org_uuid)); -joinable!(devices -> users (user_uuid)); -joinable!(folders -> users (user_uuid)); -joinable!(folders_ciphers -> ciphers (cipher_uuid)); -joinable!(folders_ciphers -> folders (folder_uuid)); -joinable!(twofactor -> users (user_uuid)); -joinable!(users_collections -> collections (collection_uuid)); -joinable!(users_collections -> users (user_uuid)); -joinable!(users_organizations -> organizations (org_uuid)); -joinable!(users_organizations -> users (user_uuid)); - allow_tables_to_appear_in_same_query!( attachments, ciphers, diff --git a/src/main.rs b/src/main.rs index c0dd0dbd..c34eb2d0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -123,7 +123,8 @@ fn chain_syslog(logger: fern::Dispatch) -> fern::Dispatch { fn check_db() { let url = CONFIG.database_url(); - println!(url.to_string()); + println!("{}", url.to_string()); + db::get_connection().expect("Can't conect to DB"); } fn check_rsa_keys() { From e22e290f677c01354446bf784287114696f2eeaa Mon Sep 17 00:00:00 2001 From: Emil Madsen Date: Mon, 20 May 2019 21:24:29 +0200 Subject: [PATCH 03/21] Fix key and type variable names for mysql --- src/api/core/accounts.rs | 10 +++++----- src/api/core/ciphers.rs | 6 +++--- src/api/core/mod.rs | 2 +- src/api/core/organizations.rs | 28 ++++++++++++++-------------- src/api/identity.rs | 8 ++++---- src/auth.rs | 2 +- src/db/models/organization.rs | 6 +++--- src/db/models/user.rs | 2 +- 8 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index bc2d2868..3b16514a 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -106,7 +106,7 @@ fn register(data: JsonUpcase, conn: DbConn) -> EmptyResult { } user.set_password(&data.MasterPasswordHash); - user.key = data.Key; + user.akey = data.Key; // Add extra fields if present if let Some(name) = data.Name { @@ -204,7 +204,7 @@ fn post_password(data: JsonUpcase, headers: Headers, conn: DbCon } user.set_password(&data.NewMasterPasswordHash); - user.key = data.Key; + user.akey = data.Key; user.save(&conn) } @@ -231,7 +231,7 @@ fn post_kdf(data: JsonUpcase, headers: Headers, conn: DbConn) -> user.client_kdf_iter = data.KdfIterations; user.client_kdf_type = data.Kdf; user.set_password(&data.NewMasterPasswordHash); - user.key = data.Key; + user.akey = data.Key; user.save(&conn) } @@ -306,7 +306,7 @@ fn post_rotatekey(data: JsonUpcase, headers: Headers, conn: DbConn, nt: // Update user data let mut user = headers.user; - user.key = data.Key; + user.akey = data.Key; user.private_key = Some(data.PrivateKey); user.reset_security_stamp(); @@ -377,7 +377,7 @@ fn post_email(data: JsonUpcase, headers: Headers, conn: DbConn) user.email = data.NewEmail; user.set_password(&data.NewMasterPasswordHash); - user.key = data.Key; + user.akey = data.Key; user.save(&conn) } diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index f44ad513..05ee7e10 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -267,7 +267,7 @@ pub fn update_cipher_from_data( err!("Attachment is not owned by the cipher") } - saved_att.key = Some(attachment.Key); + saved_att.akey = Some(attachment.Key); saved_att.file_name = attachment.FileName; saved_att.save(&conn)?; @@ -691,7 +691,7 @@ fn post_attachment( }; let mut attachment = Attachment::new(file_name, cipher.uuid.clone(), name, size); - attachment.key = attachment_key.clone(); + attachment.akey = attachment_key.clone(); attachment.save(&conn).expect("Error saving attachment"); } _ => error!("Invalid multipart name"), @@ -899,7 +899,7 @@ fn delete_all( match UserOrganization::find_by_user_and_org(&user.uuid, &org_data.org_id, &conn) { None => err!("You don't have permission to purge the organization vault"), Some(user_org) => { - if user_org.type_ == UserOrgType::Owner { + if user_org.atype == UserOrgType::Owner { Cipher::delete_all_by_organization(&org_data.org_id, &conn)?; Collection::delete_all_by_organization(&org_data.org_id, &conn)?; nt.send_user_update(UpdateType::Vault, &user); diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs index 4abe31a4..6be0f9c1 100644 --- a/src/api/core/mod.rs +++ b/src/api/core/mod.rs @@ -63,7 +63,7 @@ fn put_device_token(uuid: String, data: JsonUpcase, headers: Headers) -> Ok(Json(json!({ "Id": headers.device.uuid, "Name": headers.device.name, - "Type": headers.device.type_, + "Type": headers.device.atype, "Identifier": headers.device.uuid, "CreationDate": crate::util::format_date(&headers.device.created_at), }))) diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs index 43967331..0a6a9db1 100644 --- a/src/api/core/organizations.rs +++ b/src/api/core/organizations.rs @@ -80,9 +80,9 @@ fn create_organization(headers: Headers, data: JsonUpcase, conn: DbConn let mut user_org = UserOrganization::new(headers.user.uuid.clone(), org.uuid.clone()); let collection = Collection::new(org.uuid.clone(), data.CollectionName); - user_org.key = data.Key; + user_org.akey = data.Key; user_org.access_all = true; - user_org.type_ = UserOrgType::Owner as i32; + user_org.atype = UserOrgType::Owner as i32; user_org.status = UserOrgStatus::Confirmed as i32; org.save(&conn)?; @@ -127,7 +127,7 @@ fn leave_organization(org_id: String, headers: Headers, conn: DbConn) -> EmptyRe match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &conn) { None => err!("User not part of organization"), Some(user_org) => { - if user_org.type_ == UserOrgType::Owner { + if user_org.atype == UserOrgType::Owner { let num_owners = UserOrganization::find_by_org_and_type(&org_id, UserOrgType::Owner as i32, &conn).len(); @@ -505,7 +505,7 @@ fn send_invite(org_id: String, data: JsonUpcase, headers: AdminHeade let mut new_user = UserOrganization::new(user.uuid.clone(), org_id.clone()); let access_all = data.AccessAll.unwrap_or(false); new_user.access_all = access_all; - new_user.type_ = new_type; + new_user.atype = new_type; new_user.status = user_org_status; // If no accessAll, add the collections received @@ -657,7 +657,7 @@ fn confirm_invite( None => err!("The specified user isn't a member of the organization"), }; - if user_to_confirm.type_ != UserOrgType::User && headers.org_user_type != UserOrgType::Owner { + if user_to_confirm.atype != UserOrgType::User && headers.org_user_type != UserOrgType::Owner { err!("Only Owners can confirm Managers, Admins or Owners") } @@ -666,7 +666,7 @@ fn confirm_invite( } user_to_confirm.status = UserOrgStatus::Confirmed as i32; - user_to_confirm.key = match data["Key"].as_str() { + user_to_confirm.akey = match data["Key"].as_str() { Some(key) => key.to_string(), None => err!("Invalid key provided"), }; @@ -735,18 +735,18 @@ fn edit_user( None => err!("The specified user isn't member of the organization"), }; - if new_type != user_to_edit.type_ - && (user_to_edit.type_ >= UserOrgType::Admin || new_type >= UserOrgType::Admin) + if new_type != user_to_edit.atype + && (user_to_edit.atype >= UserOrgType::Admin || new_type >= UserOrgType::Admin) && headers.org_user_type != UserOrgType::Owner { err!("Only Owners can grant and remove Admin or Owner privileges") } - if user_to_edit.type_ == UserOrgType::Owner && headers.org_user_type != UserOrgType::Owner { + if user_to_edit.atype == UserOrgType::Owner && headers.org_user_type != UserOrgType::Owner { err!("Only Owners can edit Owner users") } - if user_to_edit.type_ == UserOrgType::Owner && new_type != UserOrgType::Owner { + if user_to_edit.atype == UserOrgType::Owner && new_type != UserOrgType::Owner { // Removing owner permmission, check that there are at least another owner let num_owners = UserOrganization::find_by_org_and_type(&org_id, UserOrgType::Owner as i32, &conn).len(); @@ -756,7 +756,7 @@ fn edit_user( } user_to_edit.access_all = data.AccessAll; - user_to_edit.type_ = new_type as i32; + user_to_edit.atype = new_type as i32; // Delete all the odd collections for c in CollectionUser::find_by_organization_and_user_uuid(&org_id, &user_to_edit.user_uuid, &conn) { @@ -785,11 +785,11 @@ fn delete_user(org_id: String, org_user_id: String, headers: AdminHeaders, conn: None => err!("User to delete isn't member of the organization"), }; - if user_to_delete.type_ != UserOrgType::User && headers.org_user_type != UserOrgType::Owner { + if user_to_delete.atype != UserOrgType::User && headers.org_user_type != UserOrgType::Owner { err!("Only Owners can delete Admins or Owners") } - if user_to_delete.type_ == UserOrgType::Owner { + if user_to_delete.atype == UserOrgType::Owner { // Removing owner, check that there are at least another owner let num_owners = UserOrganization::find_by_org_and_type(&org_id, UserOrgType::Owner as i32, &conn).len(); @@ -842,7 +842,7 @@ fn post_org_import( None => err!("User is not part of the organization"), }; - if org_user.type_ < UserOrgType::Admin { + if org_user.atype < UserOrgType::Admin { err!("Only admins or owners can import into an organization") } diff --git a/src/api/identity.rs b/src/api/identity.rs index 0645dad1..3602dc97 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -68,7 +68,7 @@ fn _refresh_login(data: ConnectData, conn: DbConn) -> JsonResult { "expires_in": expires_in, "token_type": "Bearer", "refresh_token": device.refresh_token, - "Key": user.key, + "Key": user.akey, "PrivateKey": user.private_key, }))) } @@ -132,7 +132,7 @@ fn _password_login(data: ConnectData, conn: DbConn, ip: ClientIp) -> JsonResult "expires_in": expires_in, "token_type": "Bearer", "refresh_token": device.refresh_token, - "Key": user.key, + "Key": user.akey, "PrivateKey": user.private_key, //"TwoFactorToken": "11122233333444555666777888999" }); @@ -158,7 +158,7 @@ fn twofactor_auth( return Ok(None); } - let twofactor_ids: Vec<_> = twofactors.iter().map(|tf| tf.type_).collect(); + let twofactor_ids: Vec<_> = twofactors.iter().map(|tf| tf.atype).collect(); let selected_id = data.two_factor_provider.unwrap_or(twofactor_ids[0]); // If we aren't given a two factor provider, asume the first one let twofactor_code = match data.two_factor_token { @@ -166,7 +166,7 @@ fn twofactor_auth( None => err_json!(_json_err_twofactor(&twofactor_ids, user_uuid, conn)?), }; - let selected_twofactor = twofactors.into_iter().filter(|tf| tf.type_ == selected_id).nth(0); + let selected_twofactor = twofactors.into_iter().filter(|tf| tf.atype == selected_id).nth(0); use crate::api::core::two_factor as _tf; use crate::crypto::ct_eq; diff --git a/src/auth.rs b/src/auth.rs index 7c65dea3..eab1e900 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -286,7 +286,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for OrgHeaders { device: headers.device, user, org_user_type: { - if let Some(org_usr_type) = UserOrgType::from_i32(org_user.type_) { + if let Some(org_usr_type) = UserOrgType::from_i32(org_user.atype) { org_usr_type } else { // This should only happen if the DB is corrupted diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs index 463e1d0f..2e5ec0f5 100644 --- a/src/db/models/organization.rs +++ b/src/db/models/organization.rs @@ -21,7 +21,7 @@ pub struct UserOrganization { pub org_uuid: String, pub access_all: bool, - pub key: String, + pub akey: String, pub status: i32, pub atype: i32, } @@ -196,7 +196,7 @@ impl UserOrganization { org_uuid, access_all: false, - key: String::new(), + akey: String::new(), status: UserOrgStatus::Accepted as i32, atype: UserOrgType::User as i32, } @@ -266,7 +266,7 @@ impl UserOrganization { "MaxStorageGb": 10, // The value doesn't matter, we don't check server-side // These are per user - "Key": self.key, + "Key": self.akey, "Status": self.status, "Type": self.atype, "Enabled": true, diff --git a/src/db/models/user.rs b/src/db/models/user.rs index 2f7183bf..c0d2f73d 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -163,7 +163,7 @@ impl User { pub fn delete(self, conn: &DbConn) -> EmptyResult { for user_org in UserOrganization::find_by_user(&self.uuid, &*conn) { - if user_org.type_ == UserOrgType::Owner { + if user_org.atype == UserOrgType::Owner { let owner_type = UserOrgType::Owner as i32; if UserOrganization::find_by_org_and_type(&user_org.org_uuid, owner_type, &conn).len() <= 1 { err!("Can't delete last owner") From 233b48bdad8d5c9571831a40dd8b7d6cb0e6f280 Mon Sep 17 00:00:00 2001 From: Emil Madsen Date: Mon, 20 May 2019 21:30:31 +0200 Subject: [PATCH 04/21] Fix missing joinable in schema --- src/db/schema.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/db/schema.rs b/src/db/schema.rs index 33c4301d..51ec1880 100644 --- a/src/db/schema.rs +++ b/src/db/schema.rs @@ -139,6 +139,22 @@ table! { } } +joinable!(attachments -> ciphers (cipher_uuid)); +joinable!(ciphers -> organizations (organization_uuid)); +joinable!(ciphers -> users (user_uuid)); +joinable!(ciphers_collections -> ciphers (cipher_uuid)); +joinable!(ciphers_collections -> collections (collection_uuid)); +joinable!(collections -> organizations (org_uuid)); +joinable!(devices -> users (user_uuid)); +joinable!(folders -> users (user_uuid)); +joinable!(folders_ciphers -> ciphers (cipher_uuid)); +joinable!(folders_ciphers -> folders (folder_uuid)); +joinable!(twofactor -> users (user_uuid)); +joinable!(users_collections -> collections (collection_uuid)); +joinable!(users_collections -> users (user_uuid)); +joinable!(users_organizations -> organizations (org_uuid)); +joinable!(users_organizations -> users (user_uuid)); + allow_tables_to_appear_in_same_query!( attachments, ciphers, From eb9d5e1196840a45a11329e46911c1db7ce7a496 Mon Sep 17 00:00:00 2001 From: Emil Madsen Date: Mon, 20 May 2019 21:34:20 +0200 Subject: [PATCH 05/21] Reintroduce .env.template --- .env.template | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 .env.template diff --git a/.env.template b/.env.template new file mode 100644 index 00000000..63c6c01a --- /dev/null +++ b/.env.template @@ -0,0 +1,146 @@ +## Bitwarden_RS Configuration File +## Uncomment any of the following lines to change the defaults + +## Main data folder +# DATA_FOLDER=data + +## Individual folders, these override %DATA_FOLDER% +# DATABASE_URL=data/db.sqlite3 +# RSA_KEY_FILENAME=data/rsa_key +# ICON_CACHE_FOLDER=data/icon_cache +# ATTACHMENTS_FOLDER=data/attachments + +## Templates data folder, by default uses embedded templates +## Check source code to see the format +# TEMPLATES_FOLDER=/path/to/templates +## Automatically reload the templates for every request, slow, use only for development +# RELOAD_TEMPLATES=false + +## Cache time-to-live for successfully obtained icons, in seconds (0 is "forever") +# ICON_CACHE_TTL=2592000 +## Cache time-to-live for icons which weren't available, in seconds (0 is "forever") +# ICON_CACHE_NEGTTL=259200 + +## Web vault settings +# WEB_VAULT_FOLDER=web-vault/ +# WEB_VAULT_ENABLED=true + +## Enables websocket notifications +# WEBSOCKET_ENABLED=false + +## Controls the WebSocket server address and port +# WEBSOCKET_ADDRESS=0.0.0.0 +# WEBSOCKET_PORT=3012 + +## Enable extended logging +## This shows timestamps and allows logging to file and to syslog +### To enable logging to file, use the LOG_FILE env variable +### To enable syslog, use the USE_SYSLOG env variable +# EXTENDED_LOGGING=true + +## Logging to file +## This requires extended logging +## It's recommended to also set 'ROCKET_CLI_COLORS=off' +# LOG_FILE=/path/to/log + +## Logging to Syslog +## This requires extended logging +## It's recommended to also set 'ROCKET_CLI_COLORS=off' +# USE_SYSLOG=false + +## Log level +## Change the verbosity of the log output +## Valid values are "trace", "debug", "info", "warn", "error" and "off" +## This requires extended logging +# LOG_LEVEL=Info + +## Enable WAL for the DB +## Set to false to avoid enabling WAL during startup. +## Note that if the DB already has WAL enabled, you will also need to disable WAL in the DB, +## this setting only prevents bitwarden_rs from automatically enabling it on start. +## Please read project wiki page about this setting first before changing the value as it can +## cause performance degradation or might render the service unable to start. +# ENABLE_DB_WAL=true + +## Disable icon downloading +## Set to true to disable icon downloading, this would still serve icons from $ICON_CACHE_FOLDER, +## but it won't produce any external network request. Needs to set $ICON_CACHE_TTL to 0, +## otherwise it will delete them and they won't be downloaded again. +# DISABLE_ICON_DOWNLOAD=false + +## Icon download timeout +## Configure the timeout value when downloading the favicons. +## The default is 10 seconds, but this could be to low on slower network connections +# ICON_DOWNLOAD_TIMEOUT=10 + +## Icon blacklist Regex +## Any domains or IPs that match this regex won't be fetched by the icon service. +## Useful to hide other servers in the local network. Check the WIKI for more details +# ICON_BLACKLIST_REGEX=192\.168\.1\.[0-9].*^ + +## Disable 2FA remember +## Enabling this would force the users to use a second factor to login every time. +## Note that the checkbox would still be present, but ignored. +# DISABLE_2FA_REMEMBER=false + +## Controls if new users can register +# SIGNUPS_ALLOWED=true + +## Token for the admin interface, preferably use a long random string +## One option is to use 'openssl rand -base64 48' +## If not set, the admin panel is disabled +# ADMIN_TOKEN=Vy2VyYTTsKPv8W5aEOWUbB/Bt3DEKePbHmI4m9VcemUMS2rEviDowNAFqYi1xjmp +# DISABLE_ADMIN_TOKEN=false + +## Invitations org admins to invite users, even when signups are disabled +# INVITATIONS_ALLOWED=true + +## Controls the PBBKDF password iterations to apply on the server +## The change only applies when the password is changed +# PASSWORD_ITERATIONS=100000 + +## Whether password hint should be sent into the error response when the client request it +# SHOW_PASSWORD_HINT=true + +## Domain settings +## The domain must match the address from where you access the server +## It's recommended to configure this value, otherwise certain functionality might not work, +## like attachment downloads, email links and U2F. +## For U2F to work, the server must use HTTPS, you can use Let's Encrypt for free certs +# DOMAIN=https://bw.domain.tld:8443 + +## Yubico (Yubikey) Settings +## Set your Client ID and Secret Key for Yubikey OTP +## You can generate it here: https://upgrade.yubico.com/getapikey/ +## You can optionally specify a custom OTP server +# YUBICO_CLIENT_ID=11111 +# YUBICO_SECRET_KEY=AAAAAAAAAAAAAAAAAAAAAAAA +# YUBICO_SERVER=http://yourdomain.com/wsapi/2.0/verify + +## Duo Settings +## You need to configure all options to enable global Duo support, otherwise users would need to configure it themselves +## Create an account and protect an application as mentioned in this link (only the first step, not the rest): +## https://help.bitwarden.com/article/setup-two-step-login-duo/#create-a-duo-security-account +## Then set the following options, based on the values obtained from the last step: +# DUO_IKEY= +# DUO_SKEY= +# DUO_HOST= +## After that, you should be able to follow the rest of the guide linked above, +## ignoring the fields that ask for the values that you already configured beforehand. + +## Rocket specific settings, check Rocket documentation to learn more +# ROCKET_ENV=staging +# ROCKET_ADDRESS=0.0.0.0 # Enable this to test mobile app +# ROCKET_PORT=8000 +# ROCKET_TLS={certs="/path/to/certs.pem",key="/path/to/key.pem"} + +## Mail specific settings, set SMTP_HOST and SMTP_FROM to enable the mail service. +## To make sure the email links are pointing to the correct host, set the DOMAIN variable. +## Note: if SMTP_USERNAME is specified, SMTP_PASSWORD is mandatory +# SMTP_HOST=smtp.domain.tld +# SMTP_FROM=bitwarden-rs@domain.tld +# SMTP_FROM_NAME=Bitwarden_RS +# SMTP_PORT=587 +# SMTP_SSL=true +# SMTP_USERNAME=username +# SMTP_PASSWORD=password From 5fb6531db869ae395f1ac08695023d0dd27879d0 Mon Sep 17 00:00:00 2001 From: Emil Madsen Date: Mon, 20 May 2019 21:54:01 +0200 Subject: [PATCH 06/21] Attempt to fix azure pipeline --- azure-pipelines.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f2c3e120..1127491b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -8,6 +8,11 @@ steps: echo "##vso[task.prependpath]$HOME/.cargo/bin" displayName: 'Install Rust' +- script: | + apt-get update + apt-get install -y libmysql++-dev + displayName: Install libmysql + - script: | rustc -Vv cargo -V From 6f78395ef71bd037fff24aeb60318c109294971a Mon Sep 17 00:00:00 2001 From: Emil Madsen Date: Mon, 20 May 2019 21:59:18 +0200 Subject: [PATCH 07/21] Passwordless sudo on azure? --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1127491b..9280f64c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -9,8 +9,8 @@ steps: displayName: 'Install Rust' - script: | - apt-get update - apt-get install -y libmysql++-dev + sudo apt-get update + sudo apt-get install -y libmysql++-dev displayName: Install libmysql - script: | From badd22ac3d1b6c364c7be59e64ec0c48f2b960dd Mon Sep 17 00:00:00 2001 From: Emil Madsen Date: Mon, 20 May 2019 22:36:27 +0200 Subject: [PATCH 08/21] Make docker image build --- Dockerfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Dockerfile b/Dockerfile index 4ddf7627..8faca0ed 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,6 +29,12 @@ FROM rust as build # --no-install-recommends\ # && rm -rf /var/lib/apt/lists/* +# Install MySQL package +RUN apt-get update && apt-get install -y \ + libmysql++-dev \ + --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* + # Creates a dummy project used to grab dependencies RUN USER=root cargo new --bin app WORKDIR /app From ff759397f6742781a722dab029d695c4bbcf794a Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Sun, 26 May 2019 23:02:41 +0200 Subject: [PATCH 09/21] initial mysql support --- Cargo.toml | 9 +- Dockerfile | 12 +- .../2018-01-14-171611_create_tables/down.sql | 0 .../2018-01-14-171611_create_tables/up.sql | 6 +- .../down.sql | 0 .../up.sql | 4 +- .../down.sql | 0 .../up.sql | 6 +- .../down.sql | 0 .../up.sql | 0 .../down.sql | 0 .../up.sql | 0 .../down.sql | 0 .../up.sql | 0 .../down.sql | 0 .../up.sql | 6 +- .../2018-08-27-172114_update_ciphers/down.sql | 0 .../2018-08-27-172114_update_ciphers/up.sql | 0 .../2018-09-10-111213_add_invites/down.sql | 0 .../2018-09-10-111213_add_invites/up.sql | 0 .../down.sql | 0 .../2018-09-19-144557_add_kdf_columns/up.sql | 0 .../down.sql | 0 .../up.sql | 3 + .../down.sql | 7 + .../up.sql | 7 + .../2018-01-14-171611_create_tables/down.sql | 9 + .../2018-01-14-171611_create_tables/up.sql | 62 +++++++ .../down.sql | 8 + .../up.sql | 31 ++++ .../down.sql | 0 .../up.sql | 34 ++++ .../down.sql | 1 + .../up.sql | 5 + .../down.sql | 0 .../up.sql | 14 ++ .../down.sql | 1 + .../up.sql | 3 + .../down.sql | 8 + .../up.sql | 15 ++ .../2018-08-27-172114_update_ciphers/down.sql | 0 .../2018-08-27-172114_update_ciphers/up.sql | 3 + .../2018-09-10-111213_add_invites/down.sql | 1 + .../2018-09-10-111213_add_invites/up.sql | 3 + .../down.sql | 0 .../2018-09-19-144557_add_kdf_columns/up.sql | 7 + .../down.sql | 0 .../up.sql | 2 +- .../down.sql | 7 + .../up.sql | 7 + src/config.rs | 4 +- src/db/mod.rs | 12 ++ src/db/{ => schemas/mysql}/schema.rs | 0 src/db/schemas/sqlite/schema.rs | 172 ++++++++++++++++++ src/main.rs | 6 +- 55 files changed, 454 insertions(+), 21 deletions(-) rename migrations/{ => mysql}/2018-01-14-171611_create_tables/down.sql (100%) rename migrations/{ => mysql}/2018-01-14-171611_create_tables/up.sql (94%) rename migrations/{ => mysql}/2018-02-17-205753_create_collections_and_orgs/down.sql (100%) rename migrations/{ => mysql}/2018-02-17-205753_create_collections_and_orgs/up.sql (93%) rename migrations/{ => mysql}/2018-04-27-155151_create_users_ciphers/down.sql (100%) rename migrations/{ => mysql}/2018-04-27-155151_create_users_ciphers/up.sql (87%) rename migrations/{ => mysql}/2018-05-08-161616_create_collection_cipher_map/down.sql (100%) rename migrations/{ => mysql}/2018-05-08-161616_create_collection_cipher_map/up.sql (100%) rename migrations/{ => mysql}/2018-05-25-232323_update_attachments_reference/down.sql (100%) rename migrations/{ => mysql}/2018-05-25-232323_update_attachments_reference/up.sql (100%) rename migrations/{ => mysql}/2018-06-01-112529_update_devices_twofactor_remember/down.sql (100%) rename migrations/{ => mysql}/2018-06-01-112529_update_devices_twofactor_remember/up.sql (100%) rename migrations/{ => mysql}/2018-07-11-181453_create_u2f_twofactor/down.sql (100%) rename migrations/{ => mysql}/2018-07-11-181453_create_u2f_twofactor/up.sql (75%) rename migrations/{ => mysql}/2018-08-27-172114_update_ciphers/down.sql (100%) rename migrations/{ => mysql}/2018-08-27-172114_update_ciphers/up.sql (100%) rename migrations/{ => mysql}/2018-09-10-111213_add_invites/down.sql (100%) rename migrations/{ => mysql}/2018-09-10-111213_add_invites/up.sql (100%) rename migrations/{ => mysql}/2018-09-19-144557_add_kdf_columns/down.sql (100%) rename migrations/{ => mysql}/2018-09-19-144557_add_kdf_columns/up.sql (100%) rename migrations/{ => mysql}/2018-11-27-152651_add_att_key_columns/down.sql (100%) create mode 100644 migrations/mysql/2018-11-27-152651_add_att_key_columns/up.sql create mode 100644 migrations/mysql/2019-05-26-216651_rename_key_and_type_columns/down.sql create mode 100644 migrations/mysql/2019-05-26-216651_rename_key_and_type_columns/up.sql create mode 100644 migrations/sqlite/2018-01-14-171611_create_tables/down.sql create mode 100644 migrations/sqlite/2018-01-14-171611_create_tables/up.sql create mode 100644 migrations/sqlite/2018-02-17-205753_create_collections_and_orgs/down.sql create mode 100644 migrations/sqlite/2018-02-17-205753_create_collections_and_orgs/up.sql create mode 100644 migrations/sqlite/2018-04-27-155151_create_users_ciphers/down.sql create mode 100644 migrations/sqlite/2018-04-27-155151_create_users_ciphers/up.sql create mode 100644 migrations/sqlite/2018-05-08-161616_create_collection_cipher_map/down.sql create mode 100644 migrations/sqlite/2018-05-08-161616_create_collection_cipher_map/up.sql create mode 100644 migrations/sqlite/2018-05-25-232323_update_attachments_reference/down.sql create mode 100644 migrations/sqlite/2018-05-25-232323_update_attachments_reference/up.sql create mode 100644 migrations/sqlite/2018-06-01-112529_update_devices_twofactor_remember/down.sql create mode 100644 migrations/sqlite/2018-06-01-112529_update_devices_twofactor_remember/up.sql create mode 100644 migrations/sqlite/2018-07-11-181453_create_u2f_twofactor/down.sql create mode 100644 migrations/sqlite/2018-07-11-181453_create_u2f_twofactor/up.sql create mode 100644 migrations/sqlite/2018-08-27-172114_update_ciphers/down.sql create mode 100644 migrations/sqlite/2018-08-27-172114_update_ciphers/up.sql create mode 100644 migrations/sqlite/2018-09-10-111213_add_invites/down.sql create mode 100644 migrations/sqlite/2018-09-10-111213_add_invites/up.sql create mode 100644 migrations/sqlite/2018-09-19-144557_add_kdf_columns/down.sql create mode 100644 migrations/sqlite/2018-09-19-144557_add_kdf_columns/up.sql create mode 100644 migrations/sqlite/2018-11-27-152651_add_att_key_columns/down.sql rename migrations/{ => sqlite}/2018-11-27-152651_add_att_key_columns/up.sql (72%) create mode 100644 migrations/sqlite/2019-05-26-216651_rename_key_and_type_columns/down.sql create mode 100644 migrations/sqlite/2019-05-26-216651_rename_key_and_type_columns/up.sql rename src/db/{ => schemas/mysql}/schema.rs (100%) create mode 100644 src/db/schemas/sqlite/schema.rs diff --git a/Cargo.toml b/Cargo.toml index 148ebc81..292bfb37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,8 @@ build = "build.rs" [features] # Empty to keep compatibility, prefer to set USE_SYSLOG=true enable_syslog = [] +mysql = [] +sqlite = [] [target."cfg(not(windows))".dependencies] syslog = "4.0.1" @@ -47,8 +49,11 @@ log = "0.4.6" fern = { version = "0.5.8", features = ["syslog-4"] } # A safe, extensible ORM and Query builder -diesel = { version = "1.4.2", features = ["mysql", "chrono", "r2d2"] } -diesel_migrations = { version = "1.4.0", features = ["mysql"] } +diesel = { version = "1.4.2", features = ["mysql", "sqlite", "chrono", "r2d2"] } +diesel_migrations = { version = "1.4.0", features = ["mysql", "sqlite"] } + +# Bundled SQLite +libsqlite3-sys = { version = "0.12.0", features = ["bundled"] } # Crypto library ring = "0.14.6" diff --git a/Dockerfile b/Dockerfile index 8faca0ed..cfa1e293 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,6 +23,9 @@ RUN ls # we need the Rust compiler and Cargo tooling FROM rust as build +# set sqlite as default for DB ARG for backward comaptibility +ARG DB=sqlite + # Using bundled SQLite, no need to install it # RUN apt-get update && apt-get install -y\ # sqlite3\ @@ -31,8 +34,8 @@ FROM rust as build # Install MySQL package RUN apt-get update && apt-get install -y \ - libmysql++-dev \ - --no-install-recommends \ + libmariadb-dev\ + --no-install-recommends\ && rm -rf /var/lib/apt/lists/* # Creates a dummy project used to grab dependencies @@ -47,7 +50,7 @@ COPY ./build.rs ./build.rs # Builds your dependencies and removes the # dummy project, except the target folder # This folder contains the compiled dependencies -RUN cargo build --release +RUN cargo build --features ${DB} --release RUN find . -not -path "./target*" -delete # Copies the complete project @@ -59,7 +62,7 @@ RUN touch src/main.rs # Builds again, this time it'll just be # your actual source files being built -RUN cargo build --release +RUN cargo build --features ${DB} --release ######################## RUNTIME IMAGE ######################## # Create a new stage with a minimal image @@ -74,6 +77,7 @@ ENV ROCKET_WORKERS=10 RUN apt-get update && apt-get install -y\ openssl\ ca-certificates\ + libmariadbclient-dev\ --no-install-recommends\ && rm -rf /var/lib/apt/lists/* diff --git a/migrations/2018-01-14-171611_create_tables/down.sql b/migrations/mysql/2018-01-14-171611_create_tables/down.sql similarity index 100% rename from migrations/2018-01-14-171611_create_tables/down.sql rename to migrations/mysql/2018-01-14-171611_create_tables/down.sql diff --git a/migrations/2018-01-14-171611_create_tables/up.sql b/migrations/mysql/2018-01-14-171611_create_tables/up.sql similarity index 94% rename from migrations/2018-01-14-171611_create_tables/up.sql rename to migrations/mysql/2018-01-14-171611_create_tables/up.sql index 0a1fc8c9..244c3c80 100644 --- a/migrations/2018-01-14-171611_create_tables/up.sql +++ b/migrations/mysql/2018-01-14-171611_create_tables/up.sql @@ -8,7 +8,7 @@ CREATE TABLE users ( salt BLOB NOT NULL, password_iterations INTEGER NOT NULL, password_hint TEXT, - akey TEXT NOT NULL, + `key` TEXT NOT NULL, private_key TEXT, public_key TEXT, totp_secret TEXT, @@ -24,7 +24,7 @@ CREATE TABLE devices ( updated_at DATETIME NOT NULL, user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), name TEXT NOT NULL, - atype INTEGER NOT NULL, + type INTEGER NOT NULL, push_token TEXT, refresh_token TEXT NOT NULL ); @@ -36,7 +36,7 @@ CREATE TABLE ciphers ( user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), folder_uuid VARCHAR(40) REFERENCES folders (uuid), organization_uuid VARCHAR(40), - atype INTEGER NOT NULL, + type INTEGER NOT NULL, name TEXT NOT NULL, notes TEXT, fields TEXT, diff --git a/migrations/2018-02-17-205753_create_collections_and_orgs/down.sql b/migrations/mysql/2018-02-17-205753_create_collections_and_orgs/down.sql similarity index 100% rename from migrations/2018-02-17-205753_create_collections_and_orgs/down.sql rename to migrations/mysql/2018-02-17-205753_create_collections_and_orgs/down.sql diff --git a/migrations/2018-02-17-205753_create_collections_and_orgs/up.sql b/migrations/mysql/2018-02-17-205753_create_collections_and_orgs/up.sql similarity index 93% rename from migrations/2018-02-17-205753_create_collections_and_orgs/up.sql rename to migrations/mysql/2018-02-17-205753_create_collections_and_orgs/up.sql index 8d5508ff..c5200a76 100644 --- a/migrations/2018-02-17-205753_create_collections_and_orgs/up.sql +++ b/migrations/mysql/2018-02-17-205753_create_collections_and_orgs/up.sql @@ -22,9 +22,9 @@ CREATE TABLE users_organizations ( org_uuid VARCHAR(40) NOT NULL REFERENCES organizations (uuid), access_all BOOLEAN NOT NULL, - akey TEXT NOT NULL, + `key` TEXT NOT NULL, status INTEGER NOT NULL, - atype INTEGER NOT NULL, + type INTEGER NOT NULL, UNIQUE (user_uuid, org_uuid) ); diff --git a/migrations/2018-04-27-155151_create_users_ciphers/down.sql b/migrations/mysql/2018-04-27-155151_create_users_ciphers/down.sql similarity index 100% rename from migrations/2018-04-27-155151_create_users_ciphers/down.sql rename to migrations/mysql/2018-04-27-155151_create_users_ciphers/down.sql diff --git a/migrations/2018-04-27-155151_create_users_ciphers/up.sql b/migrations/mysql/2018-04-27-155151_create_users_ciphers/up.sql similarity index 87% rename from migrations/2018-04-27-155151_create_users_ciphers/up.sql rename to migrations/mysql/2018-04-27-155151_create_users_ciphers/up.sql index 00989e4a..65c53d54 100644 --- a/migrations/2018-04-27-155151_create_users_ciphers/up.sql +++ b/migrations/mysql/2018-04-27-155151_create_users_ciphers/up.sql @@ -7,7 +7,7 @@ CREATE TABLE ciphers ( user_uuid VARCHAR(40) REFERENCES users (uuid), -- Make this optional organization_uuid VARCHAR(40) REFERENCES organizations (uuid), -- Add reference to orgs table -- Remove folder_uuid - atype INTEGER NOT NULL, + type INTEGER NOT NULL, name TEXT NOT NULL, notes TEXT, fields TEXT, @@ -22,8 +22,8 @@ CREATE TABLE folders_ciphers ( PRIMARY KEY (cipher_uuid, folder_uuid) ); -INSERT INTO ciphers (uuid, created_at, updated_at, user_uuid, organization_uuid, atype, name, notes, fields, data, favorite) -SELECT uuid, created_at, updated_at, user_uuid, organization_uuid, atype, name, notes, fields, data, favorite FROM oldCiphers; +INSERT INTO ciphers (uuid, created_at, updated_at, user_uuid, organization_uuid, type, name, notes, fields, data, favorite) +SELECT uuid, created_at, updated_at, user_uuid, organization_uuid, type, name, notes, fields, data, favorite FROM oldCiphers; INSERT INTO folders_ciphers (cipher_uuid, folder_uuid) SELECT uuid, folder_uuid FROM oldCiphers WHERE folder_uuid IS NOT NULL; diff --git a/migrations/2018-05-08-161616_create_collection_cipher_map/down.sql b/migrations/mysql/2018-05-08-161616_create_collection_cipher_map/down.sql similarity index 100% rename from migrations/2018-05-08-161616_create_collection_cipher_map/down.sql rename to migrations/mysql/2018-05-08-161616_create_collection_cipher_map/down.sql diff --git a/migrations/2018-05-08-161616_create_collection_cipher_map/up.sql b/migrations/mysql/2018-05-08-161616_create_collection_cipher_map/up.sql similarity index 100% rename from migrations/2018-05-08-161616_create_collection_cipher_map/up.sql rename to migrations/mysql/2018-05-08-161616_create_collection_cipher_map/up.sql diff --git a/migrations/2018-05-25-232323_update_attachments_reference/down.sql b/migrations/mysql/2018-05-25-232323_update_attachments_reference/down.sql similarity index 100% rename from migrations/2018-05-25-232323_update_attachments_reference/down.sql rename to migrations/mysql/2018-05-25-232323_update_attachments_reference/down.sql diff --git a/migrations/2018-05-25-232323_update_attachments_reference/up.sql b/migrations/mysql/2018-05-25-232323_update_attachments_reference/up.sql similarity index 100% rename from migrations/2018-05-25-232323_update_attachments_reference/up.sql rename to migrations/mysql/2018-05-25-232323_update_attachments_reference/up.sql diff --git a/migrations/2018-06-01-112529_update_devices_twofactor_remember/down.sql b/migrations/mysql/2018-06-01-112529_update_devices_twofactor_remember/down.sql similarity index 100% rename from migrations/2018-06-01-112529_update_devices_twofactor_remember/down.sql rename to migrations/mysql/2018-06-01-112529_update_devices_twofactor_remember/down.sql diff --git a/migrations/2018-06-01-112529_update_devices_twofactor_remember/up.sql b/migrations/mysql/2018-06-01-112529_update_devices_twofactor_remember/up.sql similarity index 100% rename from migrations/2018-06-01-112529_update_devices_twofactor_remember/up.sql rename to migrations/mysql/2018-06-01-112529_update_devices_twofactor_remember/up.sql diff --git a/migrations/2018-07-11-181453_create_u2f_twofactor/down.sql b/migrations/mysql/2018-07-11-181453_create_u2f_twofactor/down.sql similarity index 100% rename from migrations/2018-07-11-181453_create_u2f_twofactor/down.sql rename to migrations/mysql/2018-07-11-181453_create_u2f_twofactor/down.sql diff --git a/migrations/2018-07-11-181453_create_u2f_twofactor/up.sql b/migrations/mysql/2018-07-11-181453_create_u2f_twofactor/up.sql similarity index 75% rename from migrations/2018-07-11-181453_create_u2f_twofactor/up.sql rename to migrations/mysql/2018-07-11-181453_create_u2f_twofactor/up.sql index 7da3a51b..4fd57175 100644 --- a/migrations/2018-07-11-181453_create_u2f_twofactor/up.sql +++ b/migrations/mysql/2018-07-11-181453_create_u2f_twofactor/up.sql @@ -1,15 +1,15 @@ CREATE TABLE twofactor ( uuid VARCHAR(40) NOT NULL PRIMARY KEY, user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), - atype INTEGER NOT NULL, + type INTEGER NOT NULL, enabled BOOLEAN NOT NULL, data TEXT NOT NULL, - UNIQUE (user_uuid, atype) + UNIQUE (user_uuid, type) ); -INSERT INTO twofactor (uuid, user_uuid, atype, enabled, data) +INSERT INTO twofactor (uuid, user_uuid, type, enabled, data) SELECT UUID(), uuid, 0, 1, u.totp_secret FROM users u where u.totp_secret IS NOT NULL; UPDATE users SET totp_secret = NULL; -- Instead of recreating the table, just leave the columns empty diff --git a/migrations/2018-08-27-172114_update_ciphers/down.sql b/migrations/mysql/2018-08-27-172114_update_ciphers/down.sql similarity index 100% rename from migrations/2018-08-27-172114_update_ciphers/down.sql rename to migrations/mysql/2018-08-27-172114_update_ciphers/down.sql diff --git a/migrations/2018-08-27-172114_update_ciphers/up.sql b/migrations/mysql/2018-08-27-172114_update_ciphers/up.sql similarity index 100% rename from migrations/2018-08-27-172114_update_ciphers/up.sql rename to migrations/mysql/2018-08-27-172114_update_ciphers/up.sql diff --git a/migrations/2018-09-10-111213_add_invites/down.sql b/migrations/mysql/2018-09-10-111213_add_invites/down.sql similarity index 100% rename from migrations/2018-09-10-111213_add_invites/down.sql rename to migrations/mysql/2018-09-10-111213_add_invites/down.sql diff --git a/migrations/2018-09-10-111213_add_invites/up.sql b/migrations/mysql/2018-09-10-111213_add_invites/up.sql similarity index 100% rename from migrations/2018-09-10-111213_add_invites/up.sql rename to migrations/mysql/2018-09-10-111213_add_invites/up.sql diff --git a/migrations/2018-09-19-144557_add_kdf_columns/down.sql b/migrations/mysql/2018-09-19-144557_add_kdf_columns/down.sql similarity index 100% rename from migrations/2018-09-19-144557_add_kdf_columns/down.sql rename to migrations/mysql/2018-09-19-144557_add_kdf_columns/down.sql diff --git a/migrations/2018-09-19-144557_add_kdf_columns/up.sql b/migrations/mysql/2018-09-19-144557_add_kdf_columns/up.sql similarity index 100% rename from migrations/2018-09-19-144557_add_kdf_columns/up.sql rename to migrations/mysql/2018-09-19-144557_add_kdf_columns/up.sql diff --git a/migrations/2018-11-27-152651_add_att_key_columns/down.sql b/migrations/mysql/2018-11-27-152651_add_att_key_columns/down.sql similarity index 100% rename from migrations/2018-11-27-152651_add_att_key_columns/down.sql rename to migrations/mysql/2018-11-27-152651_add_att_key_columns/down.sql diff --git a/migrations/mysql/2018-11-27-152651_add_att_key_columns/up.sql b/migrations/mysql/2018-11-27-152651_add_att_key_columns/up.sql new file mode 100644 index 00000000..e77599fc --- /dev/null +++ b/migrations/mysql/2018-11-27-152651_add_att_key_columns/up.sql @@ -0,0 +1,3 @@ +ALTER TABLE attachments + ADD COLUMN + `key` TEXT; diff --git a/migrations/mysql/2019-05-26-216651_rename_key_and_type_columns/down.sql b/migrations/mysql/2019-05-26-216651_rename_key_and_type_columns/down.sql new file mode 100644 index 00000000..8a87d193 --- /dev/null +++ b/migrations/mysql/2019-05-26-216651_rename_key_and_type_columns/down.sql @@ -0,0 +1,7 @@ +ALTER TABLE attachments CHANGE COLUMN akey `key` TEXT; +ALTER TABLE ciphers CHANGE COLUMN atype type INTEGER NOT NULL; +ALTER TABLE devices CHANGE COLUMN atype type INTEGER NOT NULL; +ALTER TABLE twofactor CHANGE COLUMN atype type INTEGER NOT NULL; +ALTER TABLE users CHANGE COLUMN akey `key` TEXT; +ALTER TABLE users_organizations CHANGE COLUMN akey `key` TEXT; +ALTER TABLE users_organizations CHANGE COLUMN atype type INTEGER NOT NULL; \ No newline at end of file diff --git a/migrations/mysql/2019-05-26-216651_rename_key_and_type_columns/up.sql b/migrations/mysql/2019-05-26-216651_rename_key_and_type_columns/up.sql new file mode 100644 index 00000000..cee0351e --- /dev/null +++ b/migrations/mysql/2019-05-26-216651_rename_key_and_type_columns/up.sql @@ -0,0 +1,7 @@ +ALTER TABLE attachments CHANGE COLUMN `key` akey TEXT; +ALTER TABLE ciphers CHANGE COLUMN type atype INTEGER NOT NULL; +ALTER TABLE devices CHANGE COLUMN type atype INTEGER NOT NULL; +ALTER TABLE twofactor CHANGE COLUMN type atype INTEGER NOT NULL; +ALTER TABLE users CHANGE COLUMN `key` akey TEXT; +ALTER TABLE users_organizations CHANGE COLUMN `key` akey TEXT; +ALTER TABLE users_organizations CHANGE COLUMN type atype INTEGER NOT NULL; \ No newline at end of file diff --git a/migrations/sqlite/2018-01-14-171611_create_tables/down.sql b/migrations/sqlite/2018-01-14-171611_create_tables/down.sql new file mode 100644 index 00000000..1025a2c0 --- /dev/null +++ b/migrations/sqlite/2018-01-14-171611_create_tables/down.sql @@ -0,0 +1,9 @@ +DROP TABLE users; + +DROP TABLE devices; + +DROP TABLE ciphers; + +DROP TABLE attachments; + +DROP TABLE folders; \ No newline at end of file diff --git a/migrations/sqlite/2018-01-14-171611_create_tables/up.sql b/migrations/sqlite/2018-01-14-171611_create_tables/up.sql new file mode 100644 index 00000000..263ed8f3 --- /dev/null +++ b/migrations/sqlite/2018-01-14-171611_create_tables/up.sql @@ -0,0 +1,62 @@ +CREATE TABLE users ( + uuid TEXT NOT NULL PRIMARY KEY, + created_at DATETIME NOT NULL, + updated_at DATETIME NOT NULL, + email TEXT NOT NULL UNIQUE, + name TEXT NOT NULL, + password_hash BLOB NOT NULL, + salt BLOB NOT NULL, + password_iterations INTEGER NOT NULL, + password_hint TEXT, + key TEXT NOT NULL, + private_key TEXT, + public_key TEXT, + totp_secret TEXT, + totp_recover TEXT, + security_stamp TEXT NOT NULL, + equivalent_domains TEXT NOT NULL, + excluded_globals TEXT NOT NULL +); + +CREATE TABLE devices ( + uuid TEXT NOT NULL PRIMARY KEY, + created_at DATETIME NOT NULL, + updated_at DATETIME NOT NULL, + user_uuid TEXT NOT NULL REFERENCES users (uuid), + name TEXT NOT NULL, + type INTEGER NOT NULL, + push_token TEXT, + refresh_token TEXT NOT NULL +); + +CREATE TABLE ciphers ( + uuid TEXT NOT NULL PRIMARY KEY, + created_at DATETIME NOT NULL, + updated_at DATETIME NOT NULL, + user_uuid TEXT NOT NULL REFERENCES users (uuid), + folder_uuid TEXT REFERENCES folders (uuid), + organization_uuid TEXT, + type INTEGER NOT NULL, + name TEXT NOT NULL, + notes TEXT, + fields TEXT, + data TEXT NOT NULL, + favorite BOOLEAN NOT NULL +); + +CREATE TABLE attachments ( + id TEXT NOT NULL PRIMARY KEY, + cipher_uuid TEXT NOT NULL REFERENCES ciphers (uuid), + file_name TEXT NOT NULL, + file_size INTEGER NOT NULL + +); + +CREATE TABLE folders ( + uuid TEXT NOT NULL PRIMARY KEY, + created_at DATETIME NOT NULL, + updated_at DATETIME NOT NULL, + user_uuid TEXT NOT NULL REFERENCES users (uuid), + name TEXT NOT NULL +); + \ No newline at end of file diff --git a/migrations/sqlite/2018-02-17-205753_create_collections_and_orgs/down.sql b/migrations/sqlite/2018-02-17-205753_create_collections_and_orgs/down.sql new file mode 100644 index 00000000..b6446cd8 --- /dev/null +++ b/migrations/sqlite/2018-02-17-205753_create_collections_and_orgs/down.sql @@ -0,0 +1,8 @@ +DROP TABLE collections; + +DROP TABLE organizations; + + +DROP TABLE users_collections; + +DROP TABLE users_organizations; diff --git a/migrations/sqlite/2018-02-17-205753_create_collections_and_orgs/up.sql b/migrations/sqlite/2018-02-17-205753_create_collections_and_orgs/up.sql new file mode 100644 index 00000000..29601a4a --- /dev/null +++ b/migrations/sqlite/2018-02-17-205753_create_collections_and_orgs/up.sql @@ -0,0 +1,31 @@ +CREATE TABLE collections ( + uuid TEXT NOT NULL PRIMARY KEY, + org_uuid TEXT NOT NULL REFERENCES organizations (uuid), + name TEXT NOT NULL +); + +CREATE TABLE organizations ( + uuid TEXT NOT NULL PRIMARY KEY, + name TEXT NOT NULL, + billing_email TEXT NOT NULL +); + + +CREATE TABLE users_collections ( + user_uuid TEXT NOT NULL REFERENCES users (uuid), + collection_uuid TEXT NOT NULL REFERENCES collections (uuid), + PRIMARY KEY (user_uuid, collection_uuid) +); + +CREATE TABLE users_organizations ( + uuid TEXT NOT NULL PRIMARY KEY, + user_uuid TEXT NOT NULL REFERENCES users (uuid), + org_uuid TEXT NOT NULL REFERENCES organizations (uuid), + + access_all BOOLEAN NOT NULL, + key TEXT NOT NULL, + status INTEGER NOT NULL, + type INTEGER NOT NULL, + + UNIQUE (user_uuid, org_uuid) +); diff --git a/migrations/sqlite/2018-04-27-155151_create_users_ciphers/down.sql b/migrations/sqlite/2018-04-27-155151_create_users_ciphers/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/sqlite/2018-04-27-155151_create_users_ciphers/up.sql b/migrations/sqlite/2018-04-27-155151_create_users_ciphers/up.sql new file mode 100644 index 00000000..747f9e29 --- /dev/null +++ b/migrations/sqlite/2018-04-27-155151_create_users_ciphers/up.sql @@ -0,0 +1,34 @@ +ALTER TABLE ciphers RENAME TO oldCiphers; + +CREATE TABLE ciphers ( + uuid TEXT NOT NULL PRIMARY KEY, + created_at DATETIME NOT NULL, + updated_at DATETIME NOT NULL, + user_uuid TEXT REFERENCES users (uuid), -- Make this optional + organization_uuid TEXT REFERENCES organizations (uuid), -- Add reference to orgs table + -- Remove folder_uuid + type INTEGER NOT NULL, + name TEXT NOT NULL, + notes TEXT, + fields TEXT, + data TEXT NOT NULL, + favorite BOOLEAN NOT NULL +); + +CREATE TABLE folders_ciphers ( + cipher_uuid TEXT NOT NULL REFERENCES ciphers (uuid), + folder_uuid TEXT NOT NULL REFERENCES folders (uuid), + + PRIMARY KEY (cipher_uuid, folder_uuid) +); + +INSERT INTO ciphers (uuid, created_at, updated_at, user_uuid, organization_uuid, type, name, notes, fields, data, favorite) +SELECT uuid, created_at, updated_at, user_uuid, organization_uuid, type, name, notes, fields, data, favorite FROM oldCiphers; + +INSERT INTO folders_ciphers (cipher_uuid, folder_uuid) +SELECT uuid, folder_uuid FROM oldCiphers WHERE folder_uuid IS NOT NULL; + + +DROP TABLE oldCiphers; + +ALTER TABLE users_collections ADD COLUMN read_only BOOLEAN NOT NULL DEFAULT 0; -- False diff --git a/migrations/sqlite/2018-05-08-161616_create_collection_cipher_map/down.sql b/migrations/sqlite/2018-05-08-161616_create_collection_cipher_map/down.sql new file mode 100644 index 00000000..ba973f4f --- /dev/null +++ b/migrations/sqlite/2018-05-08-161616_create_collection_cipher_map/down.sql @@ -0,0 +1 @@ +DROP TABLE ciphers_collections; \ No newline at end of file diff --git a/migrations/sqlite/2018-05-08-161616_create_collection_cipher_map/up.sql b/migrations/sqlite/2018-05-08-161616_create_collection_cipher_map/up.sql new file mode 100644 index 00000000..9fdd7066 --- /dev/null +++ b/migrations/sqlite/2018-05-08-161616_create_collection_cipher_map/up.sql @@ -0,0 +1,5 @@ +CREATE TABLE ciphers_collections ( + cipher_uuid TEXT NOT NULL REFERENCES ciphers (uuid), + collection_uuid TEXT NOT NULL REFERENCES collections (uuid), + PRIMARY KEY (cipher_uuid, collection_uuid) +); \ No newline at end of file diff --git a/migrations/sqlite/2018-05-25-232323_update_attachments_reference/down.sql b/migrations/sqlite/2018-05-25-232323_update_attachments_reference/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/sqlite/2018-05-25-232323_update_attachments_reference/up.sql b/migrations/sqlite/2018-05-25-232323_update_attachments_reference/up.sql new file mode 100644 index 00000000..b7adb77e --- /dev/null +++ b/migrations/sqlite/2018-05-25-232323_update_attachments_reference/up.sql @@ -0,0 +1,14 @@ +ALTER TABLE attachments RENAME TO oldAttachments; + +CREATE TABLE attachments ( + id TEXT NOT NULL PRIMARY KEY, + cipher_uuid TEXT NOT NULL REFERENCES ciphers (uuid), + file_name TEXT NOT NULL, + file_size INTEGER NOT NULL + +); + +INSERT INTO attachments (id, cipher_uuid, file_name, file_size) +SELECT id, cipher_uuid, file_name, file_size FROM oldAttachments; + +DROP TABLE oldAttachments; \ No newline at end of file diff --git a/migrations/sqlite/2018-06-01-112529_update_devices_twofactor_remember/down.sql b/migrations/sqlite/2018-06-01-112529_update_devices_twofactor_remember/down.sql new file mode 100644 index 00000000..291a97c5 --- /dev/null +++ b/migrations/sqlite/2018-06-01-112529_update_devices_twofactor_remember/down.sql @@ -0,0 +1 @@ +-- This file should undo anything in `up.sql` \ No newline at end of file diff --git a/migrations/sqlite/2018-06-01-112529_update_devices_twofactor_remember/up.sql b/migrations/sqlite/2018-06-01-112529_update_devices_twofactor_remember/up.sql new file mode 100644 index 00000000..aaad8eab --- /dev/null +++ b/migrations/sqlite/2018-06-01-112529_update_devices_twofactor_remember/up.sql @@ -0,0 +1,3 @@ +ALTER TABLE devices + ADD COLUMN + twofactor_remember TEXT; \ No newline at end of file diff --git a/migrations/sqlite/2018-07-11-181453_create_u2f_twofactor/down.sql b/migrations/sqlite/2018-07-11-181453_create_u2f_twofactor/down.sql new file mode 100644 index 00000000..84b6ee63 --- /dev/null +++ b/migrations/sqlite/2018-07-11-181453_create_u2f_twofactor/down.sql @@ -0,0 +1,8 @@ +UPDATE users +SET totp_secret = ( + SELECT twofactor.data FROM twofactor + WHERE twofactor.type = 0 + AND twofactor.user_uuid = users.uuid +); + +DROP TABLE twofactor; \ No newline at end of file diff --git a/migrations/sqlite/2018-07-11-181453_create_u2f_twofactor/up.sql b/migrations/sqlite/2018-07-11-181453_create_u2f_twofactor/up.sql new file mode 100644 index 00000000..3e78e721 --- /dev/null +++ b/migrations/sqlite/2018-07-11-181453_create_u2f_twofactor/up.sql @@ -0,0 +1,15 @@ +CREATE TABLE twofactor ( + uuid TEXT NOT NULL PRIMARY KEY, + user_uuid TEXT NOT NULL REFERENCES users (uuid), + type INTEGER NOT NULL, + enabled BOOLEAN NOT NULL, + data TEXT NOT NULL, + + UNIQUE (user_uuid, type) +); + + +INSERT INTO twofactor (uuid, user_uuid, type, enabled, data) +SELECT lower(hex(randomblob(16))) , uuid, 0, 1, u.totp_secret FROM users u where u.totp_secret IS NOT NULL; + +UPDATE users SET totp_secret = NULL; -- Instead of recreating the table, just leave the columns empty \ No newline at end of file diff --git a/migrations/sqlite/2018-08-27-172114_update_ciphers/down.sql b/migrations/sqlite/2018-08-27-172114_update_ciphers/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/sqlite/2018-08-27-172114_update_ciphers/up.sql b/migrations/sqlite/2018-08-27-172114_update_ciphers/up.sql new file mode 100644 index 00000000..624efd66 --- /dev/null +++ b/migrations/sqlite/2018-08-27-172114_update_ciphers/up.sql @@ -0,0 +1,3 @@ +ALTER TABLE ciphers + ADD COLUMN + password_history TEXT; \ No newline at end of file diff --git a/migrations/sqlite/2018-09-10-111213_add_invites/down.sql b/migrations/sqlite/2018-09-10-111213_add_invites/down.sql new file mode 100644 index 00000000..af3776cf --- /dev/null +++ b/migrations/sqlite/2018-09-10-111213_add_invites/down.sql @@ -0,0 +1 @@ +DROP TABLE invitations; \ No newline at end of file diff --git a/migrations/sqlite/2018-09-10-111213_add_invites/up.sql b/migrations/sqlite/2018-09-10-111213_add_invites/up.sql new file mode 100644 index 00000000..b42e9a2a --- /dev/null +++ b/migrations/sqlite/2018-09-10-111213_add_invites/up.sql @@ -0,0 +1,3 @@ +CREATE TABLE invitations ( + email TEXT NOT NULL PRIMARY KEY +); \ No newline at end of file diff --git a/migrations/sqlite/2018-09-19-144557_add_kdf_columns/down.sql b/migrations/sqlite/2018-09-19-144557_add_kdf_columns/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/sqlite/2018-09-19-144557_add_kdf_columns/up.sql b/migrations/sqlite/2018-09-19-144557_add_kdf_columns/up.sql new file mode 100644 index 00000000..bd98f40e --- /dev/null +++ b/migrations/sqlite/2018-09-19-144557_add_kdf_columns/up.sql @@ -0,0 +1,7 @@ +ALTER TABLE users + ADD COLUMN + client_kdf_type INTEGER NOT NULL DEFAULT 0; -- PBKDF2 + +ALTER TABLE users + ADD COLUMN + client_kdf_iter INTEGER NOT NULL DEFAULT 5000; diff --git a/migrations/sqlite/2018-11-27-152651_add_att_key_columns/down.sql b/migrations/sqlite/2018-11-27-152651_add_att_key_columns/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/2018-11-27-152651_add_att_key_columns/up.sql b/migrations/sqlite/2018-11-27-152651_add_att_key_columns/up.sql similarity index 72% rename from migrations/2018-11-27-152651_add_att_key_columns/up.sql rename to migrations/sqlite/2018-11-27-152651_add_att_key_columns/up.sql index 858d3778..4a73a8c9 100644 --- a/migrations/2018-11-27-152651_add_att_key_columns/up.sql +++ b/migrations/sqlite/2018-11-27-152651_add_att_key_columns/up.sql @@ -1,3 +1,3 @@ ALTER TABLE attachments ADD COLUMN - akey TEXT; + key TEXT; \ No newline at end of file diff --git a/migrations/sqlite/2019-05-26-216651_rename_key_and_type_columns/down.sql b/migrations/sqlite/2019-05-26-216651_rename_key_and_type_columns/down.sql new file mode 100644 index 00000000..4e6902aa --- /dev/null +++ b/migrations/sqlite/2019-05-26-216651_rename_key_and_type_columns/down.sql @@ -0,0 +1,7 @@ +ALTER TABLE attachments RENAME COLUMN akey TO key; +ALTER TABLE ciphers RENAME COLUMN atype TO type; +ALTER TABLE devices RENAME COLUMN atype TO type; +ALTER TABLE twofactor RENAME COLUMN atype TO type; +ALTER TABLE users RENAME COLUMN akey TO key; +ALTER TABLE users_organizations RENAME COLUMN akey TO key; +ALTER TABLE users_organizations RENAME COLUMN atype TO type; \ No newline at end of file diff --git a/migrations/sqlite/2019-05-26-216651_rename_key_and_type_columns/up.sql b/migrations/sqlite/2019-05-26-216651_rename_key_and_type_columns/up.sql new file mode 100644 index 00000000..ab2c5b52 --- /dev/null +++ b/migrations/sqlite/2019-05-26-216651_rename_key_and_type_columns/up.sql @@ -0,0 +1,7 @@ +ALTER TABLE attachments RENAME COLUMN key TO akey; +ALTER TABLE ciphers RENAME COLUMN type TO atype; +ALTER TABLE devices RENAME COLUMN type TO atype; +ALTER TABLE twofactor RENAME COLUMN type TO atype; +ALTER TABLE users RENAME COLUMN key TO akey; +ALTER TABLE users_organizations RENAME COLUMN key TO akey; +ALTER TABLE users_organizations RENAME COLUMN type TO atype; \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index b599bedc..be0b5152 100644 --- a/src/config.rs +++ b/src/config.rs @@ -204,8 +204,8 @@ make_config! { data_folder: String, false, def, "data".to_string(); /// Database URL - /// docker run -e MYSQL_ROOT_PASSWORD=my-secret-pw -e MYSQL_DATABASE=bitwarden -p 3306:3306 -d mysql:5.7 - database_url: String, false, auto, |_c| format!("mysql://root:my-secret-pw@0.0.0.0:3306/bitwarden"); + /// Database URL + database_url: String, false, auto, |c| format!("{}/{}", c.data_folder, "db.sqlite3"); /// Icon chache folder icon_cache_folder: String, false, auto, |c| format!("{}/{}", c.data_folder, "icon_cache"); /// Attachments folder diff --git a/src/db/mod.rs b/src/db/mod.rs index 18bf0969..6a60ae43 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -2,6 +2,9 @@ use std::ops::Deref; use diesel::r2d2; use diesel::r2d2::ConnectionManager; +#[cfg(feature = "sqlite")] +use diesel::sqlite::SqliteConnection; +#[cfg(feature = "mysql")] use diesel::mysql::MysqlConnection; use diesel::{Connection as DieselConnection, ConnectionError}; @@ -12,6 +15,9 @@ use rocket::{Outcome, Request, State}; use crate::CONFIG; /// An alias to the database connection used +#[cfg(feature = "sqlite")] +type Connection = SqliteConnection; +#[cfg(feature = "mysql")] type Connection = MysqlConnection; /// An alias to the type for a pool of Diesel MySQL connections. @@ -21,7 +27,13 @@ type Pool = r2d2::Pool>; pub struct DbConn(pub r2d2::PooledConnection>); pub mod models; +#[cfg(feature = "sqlite")] +#[path = "schemas/sqlite/schema.rs"] pub mod schema; +#[cfg(feature = "mysql")] +#[path = "schemas/mysql/schema.rs"] +pub mod schema; + /// Initializes a database pool. pub fn init_pool() -> Pool { diff --git a/src/db/schema.rs b/src/db/schemas/mysql/schema.rs similarity index 100% rename from src/db/schema.rs rename to src/db/schemas/mysql/schema.rs diff --git a/src/db/schemas/sqlite/schema.rs b/src/db/schemas/sqlite/schema.rs new file mode 100644 index 00000000..1bc924c9 --- /dev/null +++ b/src/db/schemas/sqlite/schema.rs @@ -0,0 +1,172 @@ +table! { + attachments (id) { + id -> Text, + cipher_uuid -> Text, + file_name -> Text, + file_size -> Integer, + akey -> Nullable, + } +} + +table! { + ciphers (uuid) { + uuid -> Text, + created_at -> Timestamp, + updated_at -> Timestamp, + user_uuid -> Nullable, + organization_uuid -> Nullable, + atype -> Integer, + name -> Text, + notes -> Nullable, + fields -> Nullable, + data -> Text, + favorite -> Bool, + password_history -> Nullable, + } +} + +table! { + ciphers_collections (cipher_uuid, collection_uuid) { + cipher_uuid -> Text, + collection_uuid -> Text, + } +} + +table! { + collections (uuid) { + uuid -> Text, + org_uuid -> Text, + name -> Text, + } +} + +table! { + devices (uuid) { + uuid -> Text, + created_at -> Timestamp, + updated_at -> Timestamp, + user_uuid -> Text, + name -> Text, + atype -> Integer, + push_token -> Nullable, + refresh_token -> Text, + twofactor_remember -> Nullable, + } +} + +table! { + folders (uuid) { + uuid -> Text, + created_at -> Timestamp, + updated_at -> Timestamp, + user_uuid -> Text, + name -> Text, + } +} + +table! { + folders_ciphers (cipher_uuid, folder_uuid) { + cipher_uuid -> Text, + folder_uuid -> Text, + } +} + +table! { + invitations (email) { + email -> Text, + } +} + +table! { + organizations (uuid) { + uuid -> Text, + name -> Text, + billing_email -> Text, + } +} + +table! { + twofactor (uuid) { + uuid -> Text, + user_uuid -> Text, + atype -> Integer, + enabled -> Bool, + data -> Text, + } +} + +table! { + users (uuid) { + uuid -> Text, + created_at -> Timestamp, + updated_at -> Timestamp, + email -> Text, + name -> Text, + password_hash -> Binary, + salt -> Binary, + password_iterations -> Integer, + password_hint -> Nullable, + akey -> Text, + private_key -> Nullable, + public_key -> Nullable, + totp_secret -> Nullable, + totp_recover -> Nullable, + security_stamp -> Text, + equivalent_domains -> Text, + excluded_globals -> Text, + client_kdf_type -> Integer, + client_kdf_iter -> Integer, + } +} + +table! { + users_collections (user_uuid, collection_uuid) { + user_uuid -> Text, + collection_uuid -> Text, + read_only -> Bool, + } +} + +table! { + users_organizations (uuid) { + uuid -> Text, + user_uuid -> Text, + org_uuid -> Text, + access_all -> Bool, + akey -> Text, + status -> Integer, + atype -> Integer, + } +} + +joinable!(attachments -> ciphers (cipher_uuid)); +joinable!(ciphers -> organizations (organization_uuid)); +joinable!(ciphers -> users (user_uuid)); +joinable!(ciphers_collections -> ciphers (cipher_uuid)); +joinable!(ciphers_collections -> collections (collection_uuid)); +joinable!(collections -> organizations (org_uuid)); +joinable!(devices -> users (user_uuid)); +joinable!(folders -> users (user_uuid)); +joinable!(folders_ciphers -> ciphers (cipher_uuid)); +joinable!(folders_ciphers -> folders (folder_uuid)); +joinable!(twofactor -> users (user_uuid)); +joinable!(users_collections -> collections (collection_uuid)); +joinable!(users_collections -> users (user_uuid)); +joinable!(users_organizations -> organizations (org_uuid)); +joinable!(users_organizations -> users (user_uuid)); + +allow_tables_to_appear_in_same_query!( + attachments, + ciphers, + ciphers_collections, + collections, + devices, + folders, + folders_ciphers, + invitations, + organizations, + twofactor, + users, + users_collections, + users_organizations, +); \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c34eb2d0..21e55eb5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -191,7 +191,11 @@ fn check_web_vault() { // https://docs.rs/diesel_migrations/*/diesel_migrations/macro.embed_migrations.html #[allow(unused_imports)] mod migrations { - embed_migrations!(); + + #[cfg(feature = "sqlite")] + embed_migrations!("migrations/sqlite"); + #[cfg(feature = "mysql")] + embed_migrations!("migrations/mysql"); pub fn run_migrations() { // Make sure the database is up to date (create if it doesn't exist, or run the migrations) From edc26cb1e16009426429cb4585e03af10eb579db Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Mon, 27 May 2019 00:19:59 +0200 Subject: [PATCH 10/21] adapt pipline to no enable conflicting features --- azure-pipelines.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9280f64c..20451811 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -10,7 +10,7 @@ steps: - script: | sudo apt-get update - sudo apt-get install -y libmysql++-dev + sudo apt-get install -y libmariadb-dev displayName: Install libmysql - script: | @@ -18,5 +18,8 @@ steps: cargo -V displayName: Query rust and cargo versions -- script : cargo build --all-features - displayName: 'Build project' +- script : cargo build --features sqlite enable_syslog + displayName: 'Build project with sqlite backend' + +- script : cargo build --features mysql enable_syslog + displayName: 'Build project with mysql backend' From ce0651b79c178bfbdf652e632cfadb837eac4829 Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Mon, 27 May 2019 00:23:42 +0200 Subject: [PATCH 11/21] fix mysql package in ubuntu --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 20451811..ec8ee4b5 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -10,7 +10,7 @@ steps: - script: | sudo apt-get update - sudo apt-get install -y libmariadb-dev + sudo apt-get install -y libmysql++-dev displayName: Install libmysql - script: | From f57b407c60d82b84cdcf2f46f8c8ac4f8621320a Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Mon, 27 May 2019 00:29:31 +0200 Subject: [PATCH 12/21] fix cargo syntax --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ec8ee4b5..be0a9cdf 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -18,8 +18,8 @@ steps: cargo -V displayName: Query rust and cargo versions -- script : cargo build --features sqlite enable_syslog +- script : cargo build --features "sqlite enable_syslog" displayName: 'Build project with sqlite backend' -- script : cargo build --features mysql enable_syslog +- script : cargo build --features "mysql enable_syslog" displayName: 'Build project with mysql backend' From 4c9cc9890c9e63840a33233264bd50f8a6d938b2 Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Mon, 27 May 2019 00:41:42 +0200 Subject: [PATCH 13/21] adapt travis to not enable conflicting features --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index abf1db7b..0bbb5ae8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,4 +6,6 @@ cache: cargo # Nothing to install install: true -script: cargo build --all-features +script: +- cargo build --features "sqlite enable_syslog" +- cargo build --features "mysql enable_syslog" From 6c38026ef53535bbe88799dd5a85ecd02b95f541 Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Mon, 27 May 2019 17:20:20 +0200 Subject: [PATCH 14/21] user char(36) for uuid columns --- .../2018-01-14-171611_create_tables/up.sql | 22 +++++++++---------- .../up.sql | 10 ++++----- .../up.sql | 10 ++++----- .../up.sql | 4 ++-- .../up.sql | 4 ++-- .../up.sql | 4 ++-- 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/migrations/mysql/2018-01-14-171611_create_tables/up.sql b/migrations/mysql/2018-01-14-171611_create_tables/up.sql index 244c3c80..69d161f1 100644 --- a/migrations/mysql/2018-01-14-171611_create_tables/up.sql +++ b/migrations/mysql/2018-01-14-171611_create_tables/up.sql @@ -1,5 +1,5 @@ CREATE TABLE users ( - uuid VARCHAR(40) NOT NULL PRIMARY KEY, + uuid CHAR(36) NOT NULL PRIMARY KEY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, email VARCHAR(255) NOT NULL UNIQUE, @@ -19,10 +19,10 @@ CREATE TABLE users ( ); CREATE TABLE devices ( - uuid VARCHAR(40) NOT NULL PRIMARY KEY, + uuid CHAR(36) NOT NULL PRIMARY KEY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, - user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), + user_uuid CHAR(36) NOT NULL REFERENCES users (uuid), name TEXT NOT NULL, type INTEGER NOT NULL, push_token TEXT, @@ -30,12 +30,12 @@ CREATE TABLE devices ( ); CREATE TABLE ciphers ( - uuid VARCHAR(40) NOT NULL PRIMARY KEY, + uuid CHAR(36) NOT NULL PRIMARY KEY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, - user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), - folder_uuid VARCHAR(40) REFERENCES folders (uuid), - organization_uuid VARCHAR(40), + user_uuid CHAR(36) NOT NULL REFERENCES users (uuid), + folder_uuid CHAR(36) REFERENCES folders (uuid), + organization_uuid CHAR(36), type INTEGER NOT NULL, name TEXT NOT NULL, notes TEXT, @@ -45,18 +45,18 @@ CREATE TABLE ciphers ( ); CREATE TABLE attachments ( - id VARCHAR(40) NOT NULL PRIMARY KEY, - cipher_uuid VARCHAR(40) NOT NULL REFERENCES ciphers (uuid), + id CHAR(36) NOT NULL PRIMARY KEY, + cipher_uuid CHAR(36) NOT NULL REFERENCES ciphers (uuid), file_name TEXT NOT NULL, file_size INTEGER NOT NULL ); CREATE TABLE folders ( - uuid VARCHAR(40) NOT NULL PRIMARY KEY, + uuid CHAR(36) NOT NULL PRIMARY KEY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, - user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), + user_uuid CHAR(36) NOT NULL REFERENCES users (uuid), name TEXT NOT NULL ); diff --git a/migrations/mysql/2018-02-17-205753_create_collections_and_orgs/up.sql b/migrations/mysql/2018-02-17-205753_create_collections_and_orgs/up.sql index c5200a76..dd90f9dc 100644 --- a/migrations/mysql/2018-02-17-205753_create_collections_and_orgs/up.sql +++ b/migrations/mysql/2018-02-17-205753_create_collections_and_orgs/up.sql @@ -11,15 +11,15 @@ CREATE TABLE organizations ( ); CREATE TABLE users_collections ( - user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), - collection_uuid VARCHAR(40) NOT NULL REFERENCES collections (uuid), + user_uuid CHAR(36) NOT NULL REFERENCES users (uuid), + collection_uuid CHAR(36) NOT NULL REFERENCES collections (uuid), PRIMARY KEY (user_uuid, collection_uuid) ); CREATE TABLE users_organizations ( - uuid VARCHAR(40) NOT NULL PRIMARY KEY, - user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), - org_uuid VARCHAR(40) NOT NULL REFERENCES organizations (uuid), + uuid CHAR(36) NOT NULL PRIMARY KEY, + user_uuid CHAR(36) NOT NULL REFERENCES users (uuid), + org_uuid CHAR(36) NOT NULL REFERENCES organizations (uuid), access_all BOOLEAN NOT NULL, `key` TEXT NOT NULL, diff --git a/migrations/mysql/2018-04-27-155151_create_users_ciphers/up.sql b/migrations/mysql/2018-04-27-155151_create_users_ciphers/up.sql index 65c53d54..573eaf03 100644 --- a/migrations/mysql/2018-04-27-155151_create_users_ciphers/up.sql +++ b/migrations/mysql/2018-04-27-155151_create_users_ciphers/up.sql @@ -1,11 +1,11 @@ ALTER TABLE ciphers RENAME TO oldCiphers; CREATE TABLE ciphers ( - uuid VARCHAR(40) NOT NULL PRIMARY KEY, + uuid CHAR(36) NOT NULL PRIMARY KEY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, - user_uuid VARCHAR(40) REFERENCES users (uuid), -- Make this optional - organization_uuid VARCHAR(40) REFERENCES organizations (uuid), -- Add reference to orgs table + user_uuid CHAR(36) REFERENCES users (uuid), -- Make this optional + organization_uuid CHAR(36) REFERENCES organizations (uuid), -- Add reference to orgs table -- Remove folder_uuid type INTEGER NOT NULL, name TEXT NOT NULL, @@ -16,8 +16,8 @@ CREATE TABLE ciphers ( ); CREATE TABLE folders_ciphers ( - cipher_uuid VARCHAR(40) NOT NULL REFERENCES ciphers (uuid), - folder_uuid VARCHAR(40) NOT NULL REFERENCES folders (uuid), + cipher_uuid CHAR(36) NOT NULL REFERENCES ciphers (uuid), + folder_uuid CHAR(36) NOT NULL REFERENCES folders (uuid), PRIMARY KEY (cipher_uuid, folder_uuid) ); diff --git a/migrations/mysql/2018-05-08-161616_create_collection_cipher_map/up.sql b/migrations/mysql/2018-05-08-161616_create_collection_cipher_map/up.sql index fe407be1..a2a97406 100644 --- a/migrations/mysql/2018-05-08-161616_create_collection_cipher_map/up.sql +++ b/migrations/mysql/2018-05-08-161616_create_collection_cipher_map/up.sql @@ -1,5 +1,5 @@ CREATE TABLE ciphers_collections ( - cipher_uuid VARCHAR(40) NOT NULL REFERENCES ciphers (uuid), - collection_uuid VARCHAR(40) NOT NULL REFERENCES collections (uuid), + cipher_uuid CHAR(36) NOT NULL REFERENCES ciphers (uuid), + collection_uuid CHAR(36) NOT NULL REFERENCES collections (uuid), PRIMARY KEY (cipher_uuid, collection_uuid) ); diff --git a/migrations/mysql/2018-05-25-232323_update_attachments_reference/up.sql b/migrations/mysql/2018-05-25-232323_update_attachments_reference/up.sql index eef50768..50b2c8e2 100644 --- a/migrations/mysql/2018-05-25-232323_update_attachments_reference/up.sql +++ b/migrations/mysql/2018-05-25-232323_update_attachments_reference/up.sql @@ -1,8 +1,8 @@ ALTER TABLE attachments RENAME TO oldAttachments; CREATE TABLE attachments ( - id VARCHAR(40) NOT NULL PRIMARY KEY, - cipher_uuid VARCHAR(40) NOT NULL REFERENCES ciphers (uuid), + id CHAR(36) NOT NULL PRIMARY KEY, + cipher_uuid CHAR(36) NOT NULL REFERENCES ciphers (uuid), file_name TEXT NOT NULL, file_size INTEGER NOT NULL diff --git a/migrations/mysql/2018-07-11-181453_create_u2f_twofactor/up.sql b/migrations/mysql/2018-07-11-181453_create_u2f_twofactor/up.sql index 4fd57175..ab6c753b 100644 --- a/migrations/mysql/2018-07-11-181453_create_u2f_twofactor/up.sql +++ b/migrations/mysql/2018-07-11-181453_create_u2f_twofactor/up.sql @@ -1,6 +1,6 @@ CREATE TABLE twofactor ( - uuid VARCHAR(40) NOT NULL PRIMARY KEY, - user_uuid VARCHAR(40) NOT NULL REFERENCES users (uuid), + uuid CHAR(36) NOT NULL PRIMARY KEY, + user_uuid CHAR(36) NOT NULL REFERENCES users (uuid), type INTEGER NOT NULL, enabled BOOLEAN NOT NULL, data TEXT NOT NULL, From dc36f0cb6c47017e9e188ca55e42fdb75b7b87ce Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Mon, 27 May 2019 22:58:52 +0200 Subject: [PATCH 15/21] re-added sqlite check_db code, cleanup --- Cargo.toml | 4 ++-- src/config.rs | 2 -- src/db/mod.rs | 10 +++------- src/main.rs | 23 +++++++++++++++++++++++ 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 292bfb37..1260c9c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,8 +13,8 @@ build = "build.rs" [features] # Empty to keep compatibility, prefer to set USE_SYSLOG=true enable_syslog = [] -mysql = [] -sqlite = [] +mysql = ["diesel/mysql", "diesel_migrations/mysql"] +sqlite = ["diesel/sqlite", "diesel_migrations/sqlite"] [target."cfg(not(windows))".dependencies] syslog = "4.0.1" diff --git a/src/config.rs b/src/config.rs index be0b5152..b17df579 100644 --- a/src/config.rs +++ b/src/config.rs @@ -202,8 +202,6 @@ make_config! { folders { /// Data folder |> Main data folder data_folder: String, false, def, "data".to_string(); - - /// Database URL /// Database URL database_url: String, false, auto, |c| format!("{}/{}", c.data_folder, "db.sqlite3"); /// Icon chache folder diff --git a/src/db/mod.rs b/src/db/mod.rs index 6a60ae43..9d7a9f46 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -2,10 +2,6 @@ use std::ops::Deref; use diesel::r2d2; use diesel::r2d2::ConnectionManager; -#[cfg(feature = "sqlite")] -use diesel::sqlite::SqliteConnection; -#[cfg(feature = "mysql")] -use diesel::mysql::MysqlConnection; use diesel::{Connection as DieselConnection, ConnectionError}; use rocket::http::Status; @@ -16,11 +12,11 @@ use crate::CONFIG; /// An alias to the database connection used #[cfg(feature = "sqlite")] -type Connection = SqliteConnection; +type Connection = diesel::sqlite::SqliteConnection; #[cfg(feature = "mysql")] -type Connection = MysqlConnection; +type Connection = diesel::mysql::MysqlConnection; -/// An alias to the type for a pool of Diesel MySQL connections. +/// An alias to the type for a pool of Diesel connections. type Pool = r2d2::Pool>; /// Connection request guard type: a wrapper around an r2d2 pooled connection. diff --git a/src/main.rs b/src/main.rs index 21e55eb5..5526ef77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,6 +45,9 @@ fn main() { init_logging().ok(); } + #[cfg(all(feature = "sqlite", feature = "mysql"))] + compile_error!("Can't enable both backends"); + check_db(); check_rsa_keys(); check_web_vault(); @@ -123,6 +126,26 @@ fn chain_syslog(logger: fern::Dispatch) -> fern::Dispatch { fn check_db() { let url = CONFIG.database_url(); + if cfg!(feature = "sqlite") { + let path = Path::new(&url); + + if let Some(parent) = path.parent() { + use std::fs; + if fs::create_dir_all(parent).is_err() { + error!("Error creating database directory"); + exit(1); + } + } + + // Turn on WAL in SQLite + if CONFIG.enable_db_wal() { + use diesel::RunQueryDsl; + let connection = db::get_connection().expect("Can't conect to DB"); + diesel::sql_query("PRAGMA journal_mode=wal") + .execute(&connection) + .expect("Failed to turn on WAL"); + } + } println!("{}", url.to_string()); db::get_connection().expect("Can't conect to DB"); } From 6a5f1613e75e58adc1c11490f771a6501c811475 Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Mon, 27 May 2019 23:07:47 +0200 Subject: [PATCH 16/21] include libsqlite3-sys optionally --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1260c9c4..63b33d43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ build = "build.rs" # Empty to keep compatibility, prefer to set USE_SYSLOG=true enable_syslog = [] mysql = ["diesel/mysql", "diesel_migrations/mysql"] -sqlite = ["diesel/sqlite", "diesel_migrations/sqlite"] +sqlite = ["diesel/sqlite", "diesel_migrations/sqlite", "libsqlite3-sys"] [target."cfg(not(windows))".dependencies] syslog = "4.0.1" @@ -53,7 +53,7 @@ diesel = { version = "1.4.2", features = ["mysql", "sqlite", "chrono", "r2d2"] } diesel_migrations = { version = "1.4.0", features = ["mysql", "sqlite"] } # Bundled SQLite -libsqlite3-sys = { version = "0.12.0", features = ["bundled"] } +libsqlite3-sys = { version = "0.12.0", features = ["bundled"], optional = true } # Crypto library ring = "0.14.6" From c11f47903aacf173eac4d0399e801c17468fddb3 Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Mon, 27 May 2019 23:18:45 +0200 Subject: [PATCH 17/21] revert include libsqlite3-sys optionally --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 63b33d43..1260c9c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ build = "build.rs" # Empty to keep compatibility, prefer to set USE_SYSLOG=true enable_syslog = [] mysql = ["diesel/mysql", "diesel_migrations/mysql"] -sqlite = ["diesel/sqlite", "diesel_migrations/sqlite", "libsqlite3-sys"] +sqlite = ["diesel/sqlite", "diesel_migrations/sqlite"] [target."cfg(not(windows))".dependencies] syslog = "4.0.1" @@ -53,7 +53,7 @@ diesel = { version = "1.4.2", features = ["mysql", "sqlite", "chrono", "r2d2"] } diesel_migrations = { version = "1.4.0", features = ["mysql", "sqlite"] } # Bundled SQLite -libsqlite3-sys = { version = "0.12.0", features = ["bundled"], optional = true } +libsqlite3-sys = { version = "0.12.0", features = ["bundled"] } # Crypto library ring = "0.14.6" From ee277de707d66b1dbcec6ad5c3b21c9b2745b3d2 Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Mon, 27 May 2019 23:31:56 +0200 Subject: [PATCH 18/21] include libsqlite3-sys optionally, removed non common features --- Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1260c9c4..a4dca522 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ build = "build.rs" # Empty to keep compatibility, prefer to set USE_SYSLOG=true enable_syslog = [] mysql = ["diesel/mysql", "diesel_migrations/mysql"] -sqlite = ["diesel/sqlite", "diesel_migrations/sqlite"] +sqlite = ["diesel/sqlite", "diesel_migrations/sqlite", "libsqlite3-sys"] [target."cfg(not(windows))".dependencies] syslog = "4.0.1" @@ -49,11 +49,11 @@ log = "0.4.6" fern = { version = "0.5.8", features = ["syslog-4"] } # A safe, extensible ORM and Query builder -diesel = { version = "1.4.2", features = ["mysql", "sqlite", "chrono", "r2d2"] } -diesel_migrations = { version = "1.4.0", features = ["mysql", "sqlite"] } +diesel = { version = "1.4.2", features = [ "chrono", "r2d2"] } +diesel_migrations = { version = "1.4.0" } # Bundled SQLite -libsqlite3-sys = { version = "0.12.0", features = ["bundled"] } +libsqlite3-sys = { version = "0.12.0", features = ["bundled"], optional = true } # Crypto library ring = "0.14.6" From 4859932d35b459f12eadd48019618c3aae9889be Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Tue, 28 May 2019 07:48:17 +0200 Subject: [PATCH 19/21] fixed typo --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 5526ef77..efdc9678 100644 --- a/src/main.rs +++ b/src/main.rs @@ -147,7 +147,7 @@ fn check_db() { } } println!("{}", url.to_string()); - db::get_connection().expect("Can't conect to DB"); + db::get_connection().expect("Can't connect to DB"); } fn check_rsa_keys() { From 6f7220b68ed9f718efd72979b9f0d34c5105c939 Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Tue, 28 May 2019 11:56:49 +0200 Subject: [PATCH 20/21] adapt other Dockerfiles --- Dockerfile.aarch64 | 9 +++++++-- Dockerfile.alpine | 17 +++++++++++++++-- Dockerfile.armv6 | 9 +++++++-- Dockerfile.armv7 | 10 ++++++++-- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index 3d84629d..c151d9ba 100644 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -23,6 +23,9 @@ RUN ls # we need the Rust compiler and Cargo tooling FROM rust as build +# set sqlite as default for DB ARG for backward comaptibility +ARG DB=sqlite + RUN apt-get update \ && apt-get install -y \ gcc-aarch64-linux-gnu \ @@ -42,7 +45,8 @@ RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \ && apt-get update \ && apt-get install -y \ libssl-dev:arm64 \ - libc6-dev:arm64 + libc6-dev:arm64 \ + libmariadb-dev:arm64 ENV CC_aarch64_unknown_linux_gnu="/usr/bin/aarch64-linux-gnu-gcc" ENV CROSS_COMPILE="1" @@ -55,7 +59,7 @@ COPY . . # Build RUN rustup target add aarch64-unknown-linux-gnu -RUN cargo build --release --target=aarch64-unknown-linux-gnu -v +RUN cargo build --features ${DB} --release --target=aarch64-unknown-linux-gnu -v ######################## RUNTIME IMAGE ######################## # Create a new stage with a minimal image @@ -72,6 +76,7 @@ RUN [ "cross-build-start" ] RUN apt-get update && apt-get install -y\ openssl\ ca-certificates\ + libmariadbclient-dev\ --no-install-recommends\ && rm -rf /var/lib/apt/lists/* diff --git a/Dockerfile.alpine b/Dockerfile.alpine index 2154ca14..8d7eefc1 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -22,8 +22,17 @@ RUN ls # Musl build image for statically compiled binary FROM clux/muslrust:nightly-2018-12-01 as build +# set sqlite as default for DB ARG for backward comaptibility +ARG DB=sqlite + ENV USER "root" +# Install needed libraries +RUN apt-get update && apt-get install -y\ + libmysqlclient-dev\ + --no-install-recommends\ + && rm -rf /var/lib/apt/lists/* + WORKDIR /app # Copies the complete project @@ -32,8 +41,11 @@ COPY . . RUN rustup target add x86_64-unknown-linux-musl +# Make sure that we actually build the project +RUN touch src/main.rs + # Build -RUN cargo build --release +RUN cargo build --features ${DB} --release ######################## RUNTIME IMAGE ######################## # Create a new stage with a minimal image @@ -47,7 +59,8 @@ ENV SSL_CERT_DIR=/etc/ssl/certs # Install needed libraries RUN apk add \ - openssl\ + openssl \ + mariadb-connector-c \ ca-certificates \ && rm /var/cache/apk/* diff --git a/Dockerfile.armv6 b/Dockerfile.armv6 index 3f4514f2..a99f73e4 100644 --- a/Dockerfile.armv6 +++ b/Dockerfile.armv6 @@ -23,6 +23,9 @@ RUN ls # we need the Rust compiler and Cargo tooling FROM rust as build +# set sqlite as default for DB ARG for backward comaptibility +ARG DB=sqlite + RUN apt-get update \ && apt-get install -y \ gcc-arm-linux-gnueabi \ @@ -42,7 +45,8 @@ RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \ && apt-get update \ && apt-get install -y \ libssl-dev:armel \ - libc6-dev:armel + libc6-dev:armel \ + libmariadb-dev:armel ENV CC_arm_unknown_linux_gnueabi="/usr/bin/arm-linux-gnueabi-gcc" ENV CROSS_COMPILE="1" @@ -55,7 +59,7 @@ COPY . . # Build RUN rustup target add arm-unknown-linux-gnueabi -RUN cargo build --release --target=arm-unknown-linux-gnueabi -v +RUN cargo build --features ${DB} --release --target=arm-unknown-linux-gnueabi -v ######################## RUNTIME IMAGE ######################## # Create a new stage with a minimal image @@ -72,6 +76,7 @@ RUN [ "cross-build-start" ] RUN apt-get update && apt-get install -y\ openssl\ ca-certificates\ + libmariadbclient-dev\ --no-install-recommends\ && ln -s /lib/ld-linux-armhf.so.3 /lib/ld-linux.so.3\ && rm -rf /var/lib/apt/lists/* diff --git a/Dockerfile.armv7 b/Dockerfile.armv7 index ef1e3471..c93988f7 100644 --- a/Dockerfile.armv7 +++ b/Dockerfile.armv7 @@ -23,6 +23,9 @@ RUN ls # we need the Rust compiler and Cargo tooling FROM rust as build +# set sqlite as default for DB ARG for backward comaptibility +ARG DB=sqlite + RUN apt-get update \ && apt-get install -y \ gcc-arm-linux-gnueabihf \ @@ -42,7 +45,9 @@ RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \ && apt-get update \ && apt-get install -y \ libssl-dev:armhf \ - libc6-dev:armhf + libc6-dev:armhf \ + libmariadb-dev:armhf + ENV CC_armv7_unknown_linux_gnueabihf="/usr/bin/arm-linux-gnueabihf-gcc" ENV CROSS_COMPILE="1" @@ -55,7 +60,7 @@ COPY . . # Build RUN rustup target add armv7-unknown-linux-gnueabihf -RUN cargo build --release --target=armv7-unknown-linux-gnueabihf -v +RUN cargo build --features ${DB} --release --target=armv7-unknown-linux-gnueabihf -v ######################## RUNTIME IMAGE ######################## # Create a new stage with a minimal image @@ -72,6 +77,7 @@ RUN [ "cross-build-start" ] RUN apt-get update && apt-get install -y\ openssl\ ca-certificates\ + libmariadbclient-dev\ --no-install-recommends\ && rm -rf /var/lib/apt/lists/* From 62a461ae15fe78193015fe7e34458d1bf31bf455 Mon Sep 17 00:00:00 2001 From: Nils Domrose Date: Thu, 30 May 2019 22:19:58 +0200 Subject: [PATCH 21/21] remove syslog from ci, make features flag more clear --- azure-pipelines.yml | 4 ++-- src/main.rs | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index be0a9cdf..30a7ebf5 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -18,8 +18,8 @@ steps: cargo -V displayName: Query rust and cargo versions -- script : cargo build --features "sqlite enable_syslog" +- script : cargo build --features "sqlite" displayName: 'Build project with sqlite backend' -- script : cargo build --features "mysql enable_syslog" +- script : cargo build --features "mysql" displayName: 'Build project with mysql backend' diff --git a/src/main.rs b/src/main.rs index efdc9678..4ff6c627 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,6 +48,9 @@ fn main() { #[cfg(all(feature = "sqlite", feature = "mysql"))] compile_error!("Can't enable both backends"); + #[cfg(not(any(feature = "sqlite", feature = "mysql")))] + compile_error!("You need to enable one DB backend. To build with previous defaults do: cargo build --features sqlite"); + check_db(); check_rsa_keys(); check_web_vault();