From ab95a69dc8be20401bcc3167c51fb5f8b99ed2a2 Mon Sep 17 00:00:00 2001 From: Emil Madsen Date: Mon, 20 May 2019 21:12:41 +0200 Subject: [PATCH] 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() {