From 431462d839f2b5b338254ffb7ea783cedc23bd7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Sat, 13 Mar 2021 22:02:11 +0100 Subject: [PATCH 1/7] Update dependencies and enable serde integration for chrono --- Cargo.lock | 79 ++++++++++++++++++++++++------------------------------ Cargo.toml | 8 +++--- 2 files changed, 39 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c574491..419d1700 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -224,9 +224,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "byteorder" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" @@ -281,6 +281,7 @@ dependencies = [ "libc", "num-integer", "num-traits", + "serde", "time 0.1.44", "winapi 0.3.9", ] @@ -400,7 +401,7 @@ dependencies = [ "bitflags", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.62", + "syn 1.0.63", ] [[package]] @@ -428,7 +429,7 @@ checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.62", + "syn 1.0.63", ] [[package]] @@ -650,7 +651,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.62", + "syn 1.0.63", ] [[package]] @@ -840,7 +841,7 @@ dependencies = [ "markup5ever", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.62", + "syn 1.0.63", ] [[package]] @@ -1076,9 +1077,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lettre" -version = "0.10.0-beta.1" +version = "0.10.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f060515ec950723c5482163457b3faad8c088810c4a01a42523bc98e15bcb3e" +checksum = "a8dcca2a7f2c772f90dd58c3293ff4ac416486a7f0f4339a0d6775363e6bd12a" dependencies = [ "base64 0.13.0", "hostname", @@ -1223,7 +1224,7 @@ dependencies = [ "migrations_internals", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.62", + "syn 1.0.63", ] [[package]] @@ -1442,7 +1443,7 @@ checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.62", + "syn 1.0.63", ] [[package]] @@ -1717,7 +1718,7 @@ dependencies = [ "pest_meta", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.62", + "syn 1.0.63", ] [[package]] @@ -1792,7 +1793,7 @@ checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.62", + "syn 1.0.63", ] [[package]] @@ -2056,21 +2057,20 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.3" +version = "1.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +checksum = "54fd1046a3107eb58f42de31d656fee6853e5d276c455fd943742dce89fc3dd3" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local", ] [[package]] name = "regex-syntax" -version = "0.6.22" +version = "0.6.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" +checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" [[package]] name = "remove_dir_all" @@ -2083,9 +2083,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0460542b551950620a3648c6aa23318ac6b3cd779114bd873209e6e8b5eb1c34" +checksum = "bf12057f289428dbf5c591c74bf10392e4a8003f993405a902f20117019022d4" dependencies = [ "base64 0.13.0", "bytes 1.0.1", @@ -2306,9 +2306,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfd318104249865096c8da1dfabf09ddbb6d0330ea176812a62ec75e40c4166" +checksum = "d493c5f39e02dfb062cd8f33301f90f9b13b650e8c1b1d0fd75c19dd64bff69d" dependencies = [ "bitflags", "core-foundation", @@ -2359,7 +2359,7 @@ checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.62", + "syn 1.0.63", ] [[package]] @@ -2542,7 +2542,7 @@ dependencies = [ "quote 1.0.9", "serde", "serde_derive", - "syn 1.0.62", + "syn 1.0.63", ] [[package]] @@ -2558,7 +2558,7 @@ dependencies = [ "serde_derive", "serde_json", "sha1", - "syn 1.0.62", + "syn 1.0.63", ] [[package]] @@ -2611,9 +2611,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123a78a3596b24fee53a6464ce52d8ecbf62241e6294c7e7fe12086cd161f512" +checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", @@ -2663,15 +2663,6 @@ dependencies = [ "utf-8", ] -[[package]] -name = "thread_local" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" -dependencies = [ - "once_cell", -] - [[package]] name = "threadpool" version = "1.8.1" @@ -2727,7 +2718,7 @@ dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", "standback", - "syn 1.0.62", + "syn 1.0.63", ] [[package]] @@ -2747,9 +2738,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8190d04c665ea9e6b6a0dc45523ade572c088d2e6566244c1122671dbf4ae3a" +checksum = "8d56477f6ed99e10225f38f9f75f872f29b8b8bd8c0b946f63345bb144e9eeda" dependencies = [ "autocfg", "bytes 1.0.1", @@ -2772,9 +2763,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebb7cb2f00c5ae8df755b252306272cd1790d39728363936e01827e11f0b017b" +checksum = "ec31e5cc6b46e653cf57762f36f71d5e6386391d88a72fd6db4508f8f676fb29" dependencies = [ "bytes 1.0.1", "futures-core", @@ -2848,9 +2839,9 @@ checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] name = "typenum" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" [[package]] name = "u2f" @@ -3041,7 +3032,7 @@ dependencies = [ "log 0.4.14", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.62", + "syn 1.0.63", "wasm-bindgen-shared", ] @@ -3075,7 +3066,7 @@ checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.62", + "syn 1.0.63", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index 667bdb02..938be6e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ rocket = { version = "0.5.0-dev", features = ["tls"], default-features = false } rocket_contrib = "0.5.0-dev" # HTTP client -reqwest = { version = "0.11.1", features = ["blocking", "json"] } +reqwest = { version = "0.11.2", features = ["blocking", "json"] } # multipart/form-data support multipart = { version = "0.17.1", features = ["server"], default-features = false } @@ -69,7 +69,7 @@ ring = "0.16.20" uuid = { version = "0.8.2", features = ["v4"] } # Date and time libraries -chrono = "0.4.19" +chrono = { version = "0.4.19", features = ["serde"] } chrono-tz = "0.5.3" time = "0.2.25" @@ -99,7 +99,7 @@ num-traits = "0.2.14" num-derive = "0.3.3" # Email libraries -lettre = { version = "0.10.0-beta.1", features = ["smtp-transport", "builder", "serde", "native-tls", "hostname", "tracing"], default-features = false } +lettre = { version = "0.10.0-beta.2", features = ["smtp-transport", "builder", "serde", "native-tls", "hostname", "tracing"], default-features = false } newline-converter = "0.2.0" # Template library @@ -108,7 +108,7 @@ handlebars = { version = "3.5.3", features = ["dir_source"] } # For favicon extraction from main website html5ever = "0.25.1" markup5ever_rcdom = "0.1.0" -regex = { version = "1.4.3", features = ["std", "perf"], default-features = false } +regex = { version = "1.4.4", features = ["std", "perf"], default-features = false } data-url = "0.1.0" # Used by U2F, JWT and Postgres From ce62e898c3de0ec160354d0f7f622b03a1f48c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Sat, 13 Mar 2021 22:04:04 +0100 Subject: [PATCH 2/7] Remove debug impl from database structs This is only implemented for the database specific structs, which is not what we want --- src/db/models/attachment.rs | 2 +- src/db/models/cipher.rs | 2 +- src/db/models/collection.rs | 6 +++--- src/db/models/device.rs | 2 +- src/db/models/favorite.rs | 2 +- src/db/models/folder.rs | 4 ++-- src/db/models/org_policy.rs | 2 +- src/db/models/organization.rs | 4 ++-- src/db/models/two_factor.rs | 2 +- src/db/models/user.rs | 4 ++-- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/db/models/attachment.rs b/src/db/models/attachment.rs index f89a6dbc..6a8fc5b0 100644 --- a/src/db/models/attachment.rs +++ b/src/db/models/attachment.rs @@ -4,7 +4,7 @@ use super::Cipher; use crate::CONFIG; db_object! { - #[derive(Debug, Identifiable, Queryable, Insertable, Associations, AsChangeset)] + #[derive(Identifiable, Queryable, Insertable, Associations, AsChangeset)] #[table_name = "attachments"] #[changeset_options(treat_none_as_null="true")] #[belongs_to(super::Cipher, foreign_key = "cipher_uuid")] diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs index d41ebfb8..da3eabab 100644 --- a/src/db/models/cipher.rs +++ b/src/db/models/cipher.rs @@ -14,7 +14,7 @@ use super::{ }; db_object! { - #[derive(Debug, Identifiable, Queryable, Insertable, Associations, AsChangeset)] + #[derive(Identifiable, Queryable, Insertable, Associations, AsChangeset)] #[table_name = "ciphers"] #[changeset_options(treat_none_as_null="true")] #[belongs_to(User, foreign_key = "user_uuid")] diff --git a/src/db/models/collection.rs b/src/db/models/collection.rs index 4e75279d..5fbc3128 100644 --- a/src/db/models/collection.rs +++ b/src/db/models/collection.rs @@ -3,7 +3,7 @@ use serde_json::Value; use super::{Organization, UserOrgStatus, UserOrgType, UserOrganization, User, Cipher}; db_object! { - #[derive(Debug, Identifiable, Queryable, Insertable, Associations, AsChangeset)] + #[derive(Identifiable, Queryable, Insertable, Associations, AsChangeset)] #[table_name = "collections"] #[belongs_to(Organization, foreign_key = "org_uuid")] #[primary_key(uuid)] @@ -13,7 +13,7 @@ db_object! { pub name: String, } - #[derive(Debug, Identifiable, Queryable, Insertable, Associations)] + #[derive(Identifiable, Queryable, Insertable, Associations)] #[table_name = "users_collections"] #[belongs_to(User, foreign_key = "user_uuid")] #[belongs_to(Collection, foreign_key = "collection_uuid")] @@ -25,7 +25,7 @@ db_object! { pub hide_passwords: bool, } - #[derive(Debug, Identifiable, Queryable, Insertable, Associations)] + #[derive(Identifiable, Queryable, Insertable, Associations)] #[table_name = "ciphers_collections"] #[belongs_to(Cipher, foreign_key = "cipher_uuid")] #[belongs_to(Collection, foreign_key = "collection_uuid")] diff --git a/src/db/models/device.rs b/src/db/models/device.rs index 0172ffb5..b3413ada 100644 --- a/src/db/models/device.rs +++ b/src/db/models/device.rs @@ -4,7 +4,7 @@ use super::User; use crate::CONFIG; db_object! { - #[derive(Debug, Identifiable, Queryable, Insertable, Associations, AsChangeset)] + #[derive(Identifiable, Queryable, Insertable, Associations, AsChangeset)] #[table_name = "devices"] #[changeset_options(treat_none_as_null="true")] #[belongs_to(User, foreign_key = "user_uuid")] diff --git a/src/db/models/favorite.rs b/src/db/models/favorite.rs index f419e07d..4f610f21 100644 --- a/src/db/models/favorite.rs +++ b/src/db/models/favorite.rs @@ -1,7 +1,7 @@ use super::{Cipher, User}; db_object! { - #[derive(Debug, Identifiable, Queryable, Insertable, Associations)] + #[derive(Identifiable, Queryable, Insertable, Associations)] #[table_name = "favorites"] #[belongs_to(User, foreign_key = "user_uuid")] #[belongs_to(Cipher, foreign_key = "cipher_uuid")] diff --git a/src/db/models/folder.rs b/src/db/models/folder.rs index 3656afb3..b5bbcc79 100644 --- a/src/db/models/folder.rs +++ b/src/db/models/folder.rs @@ -4,7 +4,7 @@ use serde_json::Value; use super::{Cipher, User}; db_object! { - #[derive(Debug, Identifiable, Queryable, Insertable, Associations, AsChangeset)] + #[derive(Identifiable, Queryable, Insertable, Associations, AsChangeset)] #[table_name = "folders"] #[belongs_to(User, foreign_key = "user_uuid")] #[primary_key(uuid)] @@ -16,7 +16,7 @@ db_object! { pub name: String, } - #[derive(Debug, Identifiable, Queryable, Insertable, Associations)] + #[derive(Identifiable, Queryable, Insertable, Associations)] #[table_name = "folders_ciphers"] #[belongs_to(Cipher, foreign_key = "cipher_uuid")] #[belongs_to(Folder, foreign_key = "folder_uuid")] diff --git a/src/db/models/org_policy.rs b/src/db/models/org_policy.rs index 679b7e57..65569b48 100644 --- a/src/db/models/org_policy.rs +++ b/src/db/models/org_policy.rs @@ -7,7 +7,7 @@ use crate::error::MapResult; use super::{Organization, UserOrgStatus}; db_object! { - #[derive(Debug, Identifiable, Queryable, Insertable, Associations, AsChangeset)] + #[derive(Identifiable, Queryable, Insertable, Associations, AsChangeset)] #[table_name = "org_policies"] #[belongs_to(Organization, foreign_key = "org_uuid")] #[primary_key(uuid)] diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs index ade0040b..2e93426d 100644 --- a/src/db/models/organization.rs +++ b/src/db/models/organization.rs @@ -5,7 +5,7 @@ use num_traits::FromPrimitive; use super::{CollectionUser, User, OrgPolicy}; db_object! { - #[derive(Debug, Identifiable, Queryable, Insertable, AsChangeset)] + #[derive(Identifiable, Queryable, Insertable, AsChangeset)] #[table_name = "organizations"] #[primary_key(uuid)] pub struct Organization { @@ -14,7 +14,7 @@ db_object! { pub billing_email: String, } - #[derive(Debug, Identifiable, Queryable, Insertable, AsChangeset)] + #[derive(Identifiable, Queryable, Insertable, AsChangeset)] #[table_name = "users_organizations"] #[primary_key(uuid)] pub struct UserOrganization { diff --git a/src/db/models/two_factor.rs b/src/db/models/two_factor.rs index 79a35c19..18073bad 100644 --- a/src/db/models/two_factor.rs +++ b/src/db/models/two_factor.rs @@ -7,7 +7,7 @@ use crate::error::MapResult; use super::User; db_object! { - #[derive(Debug, Identifiable, Queryable, Insertable, Associations, AsChangeset)] + #[derive(Identifiable, Queryable, Insertable, Associations, AsChangeset)] #[table_name = "twofactor"] #[belongs_to(User, foreign_key = "user_uuid")] #[primary_key(uuid)] diff --git a/src/db/models/user.rs b/src/db/models/user.rs index eab46e51..e1ddf456 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -5,7 +5,7 @@ use crate::crypto; use crate::CONFIG; db_object! { - #[derive(Debug, Identifiable, Queryable, Insertable, AsChangeset)] + #[derive(Identifiable, Queryable, Insertable, AsChangeset)] #[table_name = "users"] #[changeset_options(treat_none_as_null="true")] #[primary_key(uuid)] @@ -47,7 +47,7 @@ db_object! { } - #[derive(Debug, Identifiable, Queryable, Insertable)] + #[derive(Identifiable, Queryable, Insertable)] #[table_name = "invitations"] #[primary_key(email)] pub struct Invitation { From 2969e87b5262b0c75d9298f8a2bf4a82336e918d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Sun, 14 Mar 2021 23:24:47 +0100 Subject: [PATCH 3/7] Add separate host-only fromrequest handler --- src/auth.rs | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index eaf4c707..4041cc6b 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -222,13 +222,12 @@ use crate::db::{ DbConn, }; -pub struct Headers { - pub host: String, - pub device: Device, - pub user: User, +pub struct Host { + pub host: String } -impl<'a, 'r> FromRequest<'a, 'r> for Headers { + +impl<'a, 'r> FromRequest<'a, 'r> for Host { type Error = &'static str; fn from_request(request: &'a Request<'r>) -> Outcome { @@ -262,6 +261,28 @@ impl<'a, 'r> FromRequest<'a, 'r> for Headers { format!("{}://{}", protocol, host) }; + Outcome::Success(Host { host }) + } +} + +pub struct Headers { + pub host: String, + pub device: Device, + pub user: User, +} + +impl<'a, 'r> FromRequest<'a, 'r> for Headers { + type Error = &'static str; + + fn from_request(request: &'a Request<'r>) -> Outcome { + let headers = request.headers(); + + let host = match Host::from_request(request) { + Outcome::Forward(_) => return Outcome::Forward(()), + Outcome::Failure(f) => return Outcome::Failure(f), + Outcome::Success(host) => host.host, + }; + // Get access_token let access_token: &str = match headers.get_one("Authorization") { Some(a) => match a.rsplit("Bearer ").next() { From 8da5b994828cedad67c2d32df8d89fa79749b04f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Sun, 14 Mar 2021 23:35:55 +0100 Subject: [PATCH 4/7] Send API --- .env.template | 1 + .../2021-03-11-190243_add_sends/down.sql | 1 + .../mysql/2021-03-11-190243_add_sends/up.sql | 25 ++ .../2021-03-11-190243_add_sends/down.sql | 1 + .../2021-03-11-190243_add_sends/up.sql | 25 ++ .../2021-03-11-190243_add_sends/down.sql | 1 + .../sqlite/2021-03-11-190243_add_sends/up.sql | 25 ++ src/api/core/ciphers.rs | 7 + src/api/core/mod.rs | 2 + src/api/core/sends.rs | 383 ++++++++++++++++++ src/api/notifications.rs | 4 + src/api/web.rs | 7 +- src/config.rs | 2 + src/db/models/mod.rs | 2 + src/db/models/send.rs | 235 +++++++++++ src/db/models/user.rs | 3 +- src/db/schemas/mysql/schema.rs | 26 ++ src/db/schemas/postgresql/schema.rs | 26 ++ src/db/schemas/sqlite/schema.rs | 26 ++ src/error.rs | 12 + 20 files changed, 812 insertions(+), 2 deletions(-) create mode 100644 migrations/mysql/2021-03-11-190243_add_sends/down.sql create mode 100644 migrations/mysql/2021-03-11-190243_add_sends/up.sql create mode 100644 migrations/postgresql/2021-03-11-190243_add_sends/down.sql create mode 100644 migrations/postgresql/2021-03-11-190243_add_sends/up.sql create mode 100644 migrations/sqlite/2021-03-11-190243_add_sends/down.sql create mode 100644 migrations/sqlite/2021-03-11-190243_add_sends/up.sql create mode 100644 src/api/core/sends.rs create mode 100644 src/db/models/send.rs diff --git a/.env.template b/.env.template index 8e5fab73..34e0e294 100644 --- a/.env.template +++ b/.env.template @@ -28,6 +28,7 @@ # RSA_KEY_FILENAME=data/rsa_key # ICON_CACHE_FOLDER=data/icon_cache # ATTACHMENTS_FOLDER=data/attachments +# SENDS_FOLDER=data/sends ## Templates data folder, by default uses embedded templates ## Check source code to see the format diff --git a/migrations/mysql/2021-03-11-190243_add_sends/down.sql b/migrations/mysql/2021-03-11-190243_add_sends/down.sql new file mode 100644 index 00000000..b843b76a --- /dev/null +++ b/migrations/mysql/2021-03-11-190243_add_sends/down.sql @@ -0,0 +1 @@ +DROP TABLE sends; diff --git a/migrations/mysql/2021-03-11-190243_add_sends/up.sql b/migrations/mysql/2021-03-11-190243_add_sends/up.sql new file mode 100644 index 00000000..ccc457dc --- /dev/null +++ b/migrations/mysql/2021-03-11-190243_add_sends/up.sql @@ -0,0 +1,25 @@ +CREATE TABLE sends ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + user_uuid CHAR(36) REFERENCES users (uuid), + organization_uuid CHAR(36) REFERENCES organizations (uuid), + + name TEXT NOT NULL, + notes TEXT, + + atype INTEGER NOT NULL, + data TEXT NOT NULL, + key TEXT NOT NULL, + password_hash BLOB, + password_salt BLOB, + password_iter INTEGER, + + max_access_count INTEGER, + access_count INTEGER NOT NULL, + + creation_date DATETIME NOT NULL, + revision_date DATETIME NOT NULL, + expiration_date DATETIME, + deletion_date DATETIME NOT NULL, + + disabled BOOLEAN NOT NULL +); \ No newline at end of file diff --git a/migrations/postgresql/2021-03-11-190243_add_sends/down.sql b/migrations/postgresql/2021-03-11-190243_add_sends/down.sql new file mode 100644 index 00000000..b843b76a --- /dev/null +++ b/migrations/postgresql/2021-03-11-190243_add_sends/down.sql @@ -0,0 +1 @@ +DROP TABLE sends; diff --git a/migrations/postgresql/2021-03-11-190243_add_sends/up.sql b/migrations/postgresql/2021-03-11-190243_add_sends/up.sql new file mode 100644 index 00000000..c57ca93b --- /dev/null +++ b/migrations/postgresql/2021-03-11-190243_add_sends/up.sql @@ -0,0 +1,25 @@ +CREATE TABLE sends ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + user_uuid CHAR(36) REFERENCES users (uuid), + organization_uuid CHAR(36) REFERENCES organizations (uuid), + + name TEXT NOT NULL, + notes TEXT, + + atype INTEGER NOT NULL, + data TEXT NOT NULL, + key TEXT NOT NULL, + password_hash BYTEA, + password_salt BYTEA, + password_iter INTEGER, + + max_access_count INTEGER, + access_count INTEGER NOT NULL, + + creation_date TIMESTAMP NOT NULL, + revision_date TIMESTAMP NOT NULL, + expiration_date TIMESTAMP, + deletion_date TIMESTAMP NOT NULL, + + disabled BOOLEAN NOT NULL +); \ No newline at end of file diff --git a/migrations/sqlite/2021-03-11-190243_add_sends/down.sql b/migrations/sqlite/2021-03-11-190243_add_sends/down.sql new file mode 100644 index 00000000..b843b76a --- /dev/null +++ b/migrations/sqlite/2021-03-11-190243_add_sends/down.sql @@ -0,0 +1 @@ +DROP TABLE sends; diff --git a/migrations/sqlite/2021-03-11-190243_add_sends/up.sql b/migrations/sqlite/2021-03-11-190243_add_sends/up.sql new file mode 100644 index 00000000..0c1e17ba --- /dev/null +++ b/migrations/sqlite/2021-03-11-190243_add_sends/up.sql @@ -0,0 +1,25 @@ +CREATE TABLE sends ( + uuid TEXT NOT NULL PRIMARY KEY, + user_uuid TEXT REFERENCES users (uuid), + organization_uuid TEXT REFERENCES organizations (uuid), + + name TEXT NOT NULL, + notes TEXT, + + atype INTEGER NOT NULL, + data TEXT NOT NULL, + key TEXT NOT NULL, + password_hash BLOB, + password_salt BLOB, + password_iter INTEGER, + + max_access_count INTEGER, + access_count INTEGER NOT NULL, + + creation_date DATETIME NOT NULL, + revision_date DATETIME NOT NULL, + expiration_date DATETIME, + deletion_date DATETIME NOT NULL, + + disabled BOOLEAN NOT NULL +); \ No newline at end of file diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index a882be97..fe815401 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -104,6 +104,12 @@ fn sync(data: Form, headers: Headers, conn: DbConn) -> JsonResult { .map(|c| c.to_json(&headers.host, &headers.user.uuid, &conn)) .collect(); + let sends = Send::find_by_user(&headers.user.uuid, &conn); + let sends_json: Vec = sends + .iter() + .map(|s| s.to_json()) + .collect(); + let domains_json = if data.exclude_domains { Value::Null } else { @@ -117,6 +123,7 @@ fn sync(data: Form, headers: Headers, conn: DbConn) -> JsonResult { "Policies": policies_json, "Ciphers": ciphers_json, "Domains": domains_json, + "Sends": sends_json, "Object": "sync" }))) } diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs index a2af79a5..4f0c19c9 100644 --- a/src/api/core/mod.rs +++ b/src/api/core/mod.rs @@ -3,6 +3,7 @@ mod ciphers; mod folders; mod organizations; pub mod two_factor; +mod sends; pub fn routes() -> Vec { let mut mod_routes = routes![ @@ -20,6 +21,7 @@ pub fn routes() -> Vec { routes.append(&mut folders::routes()); routes.append(&mut organizations::routes()); routes.append(&mut two_factor::routes()); + routes.append(&mut sends::routes()); routes.append(&mut mod_routes); routes diff --git a/src/api/core/sends.rs b/src/api/core/sends.rs new file mode 100644 index 00000000..6fc1dcbc --- /dev/null +++ b/src/api/core/sends.rs @@ -0,0 +1,383 @@ +use std::{io::Read, path::Path}; + +use chrono::{DateTime, Duration, Utc}; +use multipart::server::{save::SavedData, Multipart, SaveResult}; +use rocket::{http::ContentType, Data}; +use rocket_contrib::json::Json; +use serde_json::Value; + +use crate::{ + api::{ApiResult, EmptyResult, JsonResult, JsonUpcase, Notify, UpdateType}, + auth::{Headers, Host}, + db::{models::*, DbConn}, + CONFIG, +}; + +pub fn routes() -> Vec { + routes![ + post_send, + post_send_file, + post_access, + post_access_file, + put_send, + delete_send, + put_remove_password + ] +} + +#[derive(Deserialize)] +#[allow(non_snake_case)] +pub struct SendData { + pub Type: i32, + pub Key: String, + pub Password: Option, + pub MaxAccessCount: Option, + pub ExpirationDate: Option>, + pub DeletionDate: DateTime, + pub Disabled: bool, + + // Data field + pub Name: String, + pub Notes: Option, + pub Text: Option, + pub File: Option, +} + +fn create_send(data: SendData, user_uuid: String) -> ApiResult { + let data_val = if data.Type == SendType::Text as i32 { + data.Text + } else if data.Type == SendType::File as i32 { + data.File + } else { + err!("Invalid Send type") + }; + + let data_str = if let Some(mut d) = data_val { + d.as_object_mut().and_then(|o| o.remove("Response")); + serde_json::to_string(&d)? + } else { + err!("Send data not provided"); + }; + + if data.DeletionDate > Utc::now() + Duration::days(31) { + err!( + "You cannot have a Send with a deletion date that far into the future. Adjust the Deletion Date to a value less than 31 days from now and try again." + ); + } + + let mut send = Send::new(data.Type, data.Name, data_str, data.Key, data.DeletionDate.naive_utc()); + send.user_uuid = Some(user_uuid); + send.notes = data.Notes; + send.max_access_count = data.MaxAccessCount; + send.expiration_date = data.ExpirationDate.map(|d| d.naive_utc()); + send.disabled = data.Disabled; + send.atype = data.Type; + + send.set_password(data.Password.as_deref()); + + Ok(send) +} + +#[post("/sends", data = "")] +fn post_send(data: JsonUpcase, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult { + let data: SendData = data.into_inner().data; + + if data.Type == SendType::File as i32 { + err!("File sends should use /api/sends/file") + } + + let mut send = create_send(data, headers.user.uuid.clone())?; + send.save(&conn)?; + nt.send_user_update(UpdateType::SyncSendCreate, &headers.user); + + Ok(Json(send.to_json())) +} + +#[post("/sends/file", format = "multipart/form-data", data = "")] +fn post_send_file(data: Data, content_type: &ContentType, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult { + let boundary = content_type.params().next().expect("No boundary provided").1; + + let mut mpart = Multipart::with_body(data.open(), boundary); + + // First entry is the SendData JSON + let mut model_entry = match mpart.read_entry()? { + Some(e) if &*e.headers.name == "model" => e, + Some(_) => err!("Invalid entry name"), + None => err!("No model entry present"), + }; + + let mut buf = String::new(); + model_entry.data.read_to_string(&mut buf)?; + let data = serde_json::from_str::>(&buf)?; + + // Get the file length and add an extra 10% to avoid issues + const SIZE_110_MB: u64 = 115_343_360; + + let size_limit = match CONFIG.user_attachment_limit() { + Some(0) => err!("File uploads are disabled"), + Some(limit_kb) => { + let left = (limit_kb * 1024) - Attachment::size_by_user(&headers.user.uuid, &conn); + if left <= 0 { + err!("Attachment size limit reached! Delete some files to open space") + } + std::cmp::Ord::max(left as u64, SIZE_110_MB) + } + None => SIZE_110_MB, + }; + + // Create the Send + let mut send = create_send(data.data, headers.user.uuid.clone())?; + let file_id: String = data_encoding::HEXLOWER.encode(&crate::crypto::get_random(vec![0; 32])); + + if send.atype != SendType::File as i32 { + err!("Send content is not a file"); + } + + let file_path = Path::new(&CONFIG.sends_folder()).join(&send.uuid).join(&file_id); + + // Read the data entry and save the file + let mut data_entry = match mpart.read_entry()? { + Some(e) if &*e.headers.name == "data" => e, + Some(_) => err!("Invalid entry name"), + None => err!("No model entry present"), + }; + + let size = match data_entry + .data + .save() + .memory_threshold(0) + .size_limit(size_limit) + .with_path(&file_path) + { + SaveResult::Full(SavedData::File(_, size)) => size as i32, + SaveResult::Full(other) => { + std::fs::remove_file(&file_path).ok(); + err!(format!("Attachment is not a file: {:?}", other)); + } + SaveResult::Partial(_, reason) => { + std::fs::remove_file(&file_path).ok(); + err!(format!("Attachment size limit exceeded with this file: {:?}", reason)); + } + SaveResult::Error(e) => { + std::fs::remove_file(&file_path).ok(); + err!(format!("Error: {:?}", e)); + } + }; + + // Set ID and sizes + let mut data_value: Value = serde_json::from_str(&send.data)?; + if let Some(o) = data_value.as_object_mut() { + o.insert(String::from("Id"), Value::String(file_id)); + o.insert(String::from("Size"), Value::Number(size.into())); + o.insert( + String::from("SizeName"), + Value::String(crate::util::get_display_size(size)), + ); + } + send.data = serde_json::to_string(&data_value)?; + + // Save the changes in the database + send.save(&conn)?; + nt.send_user_update(UpdateType::SyncSendCreate, &headers.user); + + Ok(Json(send.to_json())) +} + +#[derive(Deserialize)] +#[allow(non_snake_case)] +pub struct SendAccessData { + pub Password: Option, +} + +#[post("/sends/access/", data = "")] +fn post_access(access_id: String, data: JsonUpcase, conn: DbConn) -> JsonResult { + let mut send = match Send::find_by_access_id(&access_id, &conn) { + Some(s) => s, + None => err_code!("Send not found", 404), + }; + + if let Some(max_access_count) = send.max_access_count { + if send.access_count > max_access_count { + err_code!("Max access count reached", 404); + } + } + + if let Some(expiration) = send.expiration_date { + if Utc::now().naive_utc() > expiration { + err_code!("Send has expired", 404) + } + } + + if Utc::now().naive_utc() > send.deletion_date { + err_code!("Send has been deleted", 404) + } + + if send.disabled { + err_code!("Send has been disabled", 404) + } + + if send.password_hash.is_some() { + match data.into_inner().data.Password { + Some(ref p) if send.check_password(p) => { /* Nothing to do here */ } + Some(_) => err!("Invalid password."), + None => err_code!("Password not provided", 401), + } + } + + // Files are incremented during the download + if send.atype == SendType::Text as i32 { + send.access_count += 1; + } + + send.save(&conn)?; + + Ok(Json(send.to_json())) +} + +#[post("/sends//access/file/", data = "")] +fn post_access_file( + send_id: String, + file_id: String, + data: JsonUpcase, + host: Host, + conn: DbConn, +) -> JsonResult { + let mut send = match Send::find_by_uuid(&send_id, &conn) { + Some(s) => s, + None => err_code!("Send not found", 404), + }; + + if let Some(max_access_count) = send.max_access_count { + if send.access_count > max_access_count { + err_code!("Max access count reached", 404); + } + } + + if let Some(expiration) = send.expiration_date { + if Utc::now().naive_utc() > expiration { + err_code!("Send has expired", 404) + } + } + + if Utc::now().naive_utc() > send.deletion_date { + err_code!("Send has been deleted", 404) + } + + if send.disabled { + err_code!("Send has been disabled", 404) + } + + if send.password_hash.is_some() { + match data.into_inner().data.Password { + Some(ref p) if send.check_password(p) => { /* Nothing to do here */ } + Some(_) => err!("Invalid password."), + None => err_code!("Password not provided", 401), + } + } + + send.access_count += 1; + + send.save(&conn)?; + + Ok(Json(json!({ + "Object": "send-fileDownload", + "Id": file_id, + "Url": format!("{}/sends/{}/{}", &host.host, send_id, file_id) + }))) +} + +#[put("/sends/", data = "")] +fn put_send(id: String, data: JsonUpcase, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult { + let data: SendData = data.into_inner().data; + + let mut send = match Send::find_by_uuid(&id, &conn) { + Some(s) => s, + None => err!("Send not found"), + }; + + if send.user_uuid.as_ref() != Some(&headers.user.uuid) { + err!("Send is not owned by user") + } + + if send.atype != data.Type { + err!("Sends can't change type") + } + + let data_val = if data.Type == SendType::Text as i32 { + data.Text + } else if data.Type == SendType::File as i32 { + data.File + } else { + err!("Invalid Send type") + }; + + let data_str = if let Some(mut d) = data_val { + d.as_object_mut().and_then(|d| d.remove("Response")); + serde_json::to_string(&d)? + } else { + err!("Send data not provided"); + }; + + if data.DeletionDate > Utc::now() + Duration::days(31) { + err!( + "You cannot have a Send with a deletion date that far into the future. Adjust the Deletion Date to a value less than 31 days from now and try again." + ); + } + send.data = data_str; + send.name = data.Name; + send.key = data.Key; + send.deletion_date = data.DeletionDate.naive_utc(); + send.notes = data.Notes; + send.max_access_count = data.MaxAccessCount; + send.expiration_date = data.ExpirationDate.map(|d| d.naive_utc()); + send.disabled = data.Disabled; + + // Only change the value if it's present + if let Some(password) = data.Password { + send.set_password(Some(&password)); + } + + send.save(&conn)?; + nt.send_user_update(UpdateType::SyncSendUpdate, &headers.user); + + Ok(Json(send.to_json())) +} + +#[delete("/sends/")] +fn delete_send(id: String, headers: Headers, conn: DbConn, nt: Notify) -> EmptyResult { + let send = match Send::find_by_uuid(&id, &conn) { + Some(s) => s, + None => err!("Send not found"), + }; + + if send.user_uuid.as_ref() != Some(&headers.user.uuid) { + err!("Send is not owned by user") + } + + if send.atype == SendType::File as i32 { + std::fs::remove_dir_all(Path::new(&CONFIG.sends_folder()).join(&send.uuid)).ok(); + } + + send.delete(&conn)?; + nt.send_user_update(UpdateType::SyncSendDelete, &headers.user); + + Ok(()) +} + +#[put("/sends//remove-password")] +fn put_remove_password(id: String, headers: Headers, conn: DbConn, nt: Notify) -> JsonResult { + let mut send = match Send::find_by_uuid(&id, &conn) { + Some(s) => s, + None => err!("Send not found"), + }; + + if send.user_uuid.as_ref() != Some(&headers.user.uuid) { + err!("Send is not owned by user") + } + + send.set_password(None); + send.save(&conn)?; + nt.send_user_update(UpdateType::SyncSendUpdate, &headers.user); + + Ok(Json(send.to_json())) +} diff --git a/src/api/notifications.rs b/src/api/notifications.rs index 2e81b620..3a6423c1 100644 --- a/src/api/notifications.rs +++ b/src/api/notifications.rs @@ -394,6 +394,10 @@ pub enum UpdateType { LogOut = 11, + SyncSendCreate = 12, + SyncSendUpdate = 13, + SyncSendDelete = 14, + None = 100, } diff --git a/src/api/web.rs b/src/api/web.rs index 7956c674..90e572a8 100644 --- a/src/api/web.rs +++ b/src/api/web.rs @@ -10,7 +10,7 @@ pub fn routes() -> Vec { // If addding more routes here, consider also adding them to // crate::utils::LOGGED_ROUTES to make sure they appear in the log if CONFIG.web_vault_enabled() { - routes![web_index, app_id, web_files, attachments, alive, static_files] + routes![web_index, app_id, web_files, attachments, sends, alive, static_files] } else { routes![attachments, alive, static_files] } @@ -60,6 +60,11 @@ fn attachments(uuid: String, file: PathBuf) -> Option { NamedFile::open(Path::new(&CONFIG.attachments_folder()).join(uuid).join(file)).ok() } +#[get("/sends//")] +fn sends(send_id: String, file_id: String) -> Option { + NamedFile::open(Path::new(&CONFIG.sends_folder()).join(send_id).join(file_id)).ok() +} + #[get("/alive")] fn alive() -> Json { use crate::util::format_date; diff --git a/src/config.rs b/src/config.rs index 3f344f01..6c41c975 100644 --- a/src/config.rs +++ b/src/config.rs @@ -299,6 +299,8 @@ make_config! { icon_cache_folder: String, false, auto, |c| format!("{}/{}", c.data_folder, "icon_cache"); /// Attachments folder attachments_folder: String, false, auto, |c| format!("{}/{}", c.data_folder, "attachments"); + /// Sends folder + sends_folder: String, false, auto, |c| format!("{}/{}", c.data_folder, "sends"); /// Templates folder templates_folder: String, false, auto, |c| format!("{}/{}", c.data_folder, "templates"); /// Session JWT key diff --git a/src/db/models/mod.rs b/src/db/models/mod.rs index 8c886fb4..a4fb635b 100644 --- a/src/db/models/mod.rs +++ b/src/db/models/mod.rs @@ -8,6 +8,7 @@ mod org_policy; mod organization; mod two_factor; mod user; +mod send; pub use self::attachment::Attachment; pub use self::cipher::Cipher; @@ -19,3 +20,4 @@ pub use self::org_policy::{OrgPolicy, OrgPolicyType}; pub use self::organization::{Organization, UserOrgStatus, UserOrgType, UserOrganization}; pub use self::two_factor::{TwoFactor, TwoFactorType}; pub use self::user::{Invitation, User, UserStampException}; +pub use self::send::{Send, SendType}; \ No newline at end of file diff --git a/src/db/models/send.rs b/src/db/models/send.rs new file mode 100644 index 00000000..674337ed --- /dev/null +++ b/src/db/models/send.rs @@ -0,0 +1,235 @@ +use chrono::{NaiveDateTime, Utc}; +use serde_json::Value; + +use super::{Organization, User}; + +db_object! { + #[derive(Identifiable, Queryable, Insertable, Associations, AsChangeset)] + #[table_name = "sends"] + #[changeset_options(treat_none_as_null="true")] + #[belongs_to(User, foreign_key = "user_uuid")] + #[belongs_to(Organization, foreign_key = "organization_uuid")] + #[primary_key(uuid)] + pub struct Send { + pub uuid: String, + + pub user_uuid: Option, + pub organization_uuid: Option, + + + pub name: String, + pub notes: Option, + + pub atype: i32, + pub data: String, + pub key: String, + pub password_hash: Option>, + password_salt: Option>, + password_iter: Option, + + pub max_access_count: Option, + pub access_count: i32, + + pub creation_date: NaiveDateTime, + pub revision_date: NaiveDateTime, + pub expiration_date: Option, + pub deletion_date: NaiveDateTime, + + pub disabled: bool, + } +} + +#[derive(Copy, Clone, PartialEq, Eq, num_derive::FromPrimitive)] +pub enum SendType { + Text = 0, + File = 1, +} + +impl Send { + pub fn new(atype: i32, name: String, data: String, key: String, deletion_date: NaiveDateTime) -> Self { + let now = Utc::now().naive_utc(); + + Self { + uuid: crate::util::get_uuid(), + user_uuid: None, + organization_uuid: None, + + name, + notes: None, + + atype, + data, + key, + password_hash: None, + password_salt: None, + password_iter: None, + + max_access_count: None, + access_count: 0, + + creation_date: now, + revision_date: now, + expiration_date: None, + deletion_date, + + disabled: false, + } + } + + pub fn set_password(&mut self, password: Option<&str>) { + const PASSWORD_ITER: i32 = 100_000; + + if let Some(password) = password { + self.password_iter = Some(PASSWORD_ITER); + let salt = crate::crypto::get_random_64(); + let hash = crate::crypto::hash_password(password.as_bytes(), &salt, PASSWORD_ITER as u32); + self.password_salt = Some(salt); + self.password_hash = Some(hash); + } else { + self.password_iter = None; + self.password_salt = None; + self.password_hash = None; + } + } + + pub fn check_password(&self, password: &str) -> bool { + match (&self.password_hash, &self.password_salt, self.password_iter) { + (Some(hash), Some(salt), Some(iter)) => { + crate::crypto::verify_password_hash(password.as_bytes(), salt, hash, iter as u32) + } + _ => false, + } + } + + pub fn to_json(&self) -> Value { + use crate::util::format_date; + use data_encoding::BASE64URL_NOPAD; + use uuid::Uuid; + + let data: Value = serde_json::from_str(&self.data).unwrap_or_default(); + + json!({ + "Id": self.uuid, + "AccessId": BASE64URL_NOPAD.encode(Uuid::parse_str(&self.uuid).unwrap_or_default().as_bytes()), + "Type": self.atype, + + "Name": self.name, + "Notes": self.notes, + "Text": if self.atype == SendType::Text as i32 { Some(&data) } else { None }, + "File": if self.atype == SendType::File as i32 { Some(&data) } else { None }, + + "Key": self.key, + "MaxAccessCount": self.max_access_count, + "AccessCount": self.access_count, + "Password": self.password_hash.as_deref().map(|h| BASE64URL_NOPAD.encode(h)), + "Disabled": self.disabled, + + "RevisionDate": format_date(&self.revision_date), + "ExpirationDate": self.expiration_date.as_ref().map(format_date), + "DeletionDate": format_date(&self.deletion_date), + "Object": "send", + }) + } +} + +use crate::db::DbConn; + +use crate::api::EmptyResult; +use crate::error::MapResult; + +impl Send { + pub fn save(&mut self, conn: &DbConn) -> EmptyResult { + // self.update_users_revision(conn); + self.revision_date = Utc::now().naive_utc(); + + db_run! { conn: + sqlite, mysql { + match diesel::replace_into(sends::table) + .values(SendDb::to_db(self)) + .execute(conn) + { + Ok(_) => Ok(()), + // Record already exists and causes a Foreign Key Violation because replace_into() wants to delete the record first. + Err(diesel::result::Error::DatabaseError(diesel::result::DatabaseErrorKind::ForeignKeyViolation, _)) => { + diesel::update(sends::table) + .filter(sends::uuid.eq(&self.uuid)) + .set(SendDb::to_db(self)) + .execute(conn) + .map_res("Error saving send") + } + Err(e) => Err(e.into()), + }.map_res("Error saving send") + } + postgresql { + let value = SendDb::to_db(self); + diesel::insert_into(sends::table) + .values(&value) + .on_conflict(sends::uuid) + .do_update() + .set(&value) + .execute(conn) + .map_res("Error saving send") + } + } + } + + pub fn delete(&self, conn: &DbConn) -> EmptyResult { + // self.update_users_revision(conn); + + db_run! { conn: { + diesel::delete(sends::table.filter(sends::uuid.eq(&self.uuid))) + .execute(conn) + .map_res("Error deleting send") + }} + } + + pub fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> EmptyResult { + for send in Self::find_by_user(user_uuid, &conn) { + send.delete(&conn)?; + } + Ok(()) + } + + pub fn find_by_access_id(access_id: &str, conn: &DbConn) -> Option { + use data_encoding::BASE64URL_NOPAD; + use uuid::Uuid; + + let uuid_vec = match BASE64URL_NOPAD.decode(access_id.as_bytes()) { + Ok(v) => v, + Err(_) => return None, + }; + + let uuid = match Uuid::from_slice(&uuid_vec) { + Ok(u) => u.to_string(), + Err(_) => return None, + }; + + Self::find_by_uuid(&uuid, conn) + } + + pub fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option { + db_run! {conn: { + sends::table + .filter(sends::uuid.eq(uuid)) + .first::(conn) + .ok() + .from_db() + }} + } + + pub fn find_by_user(user_uuid: &str, conn: &DbConn) -> Vec { + db_run! {conn: { + sends::table + .filter(sends::user_uuid.eq(user_uuid)) + .load::(conn).expect("Error loading sends").from_db() + }} + } + + pub fn find_by_org(org_uuid: &str, conn: &DbConn) -> Vec { + db_run! {conn: { + sends::table + .filter(sends::organization_uuid.eq(org_uuid)) + .load::(conn).expect("Error loading sends").from_db() + }} + } +} diff --git a/src/db/models/user.rs b/src/db/models/user.rs index e1ddf456..fdd2dcae 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -177,7 +177,7 @@ impl User { } } -use super::{Cipher, Device, Favorite, Folder, TwoFactor, UserOrgType, UserOrganization}; +use super::{Cipher, Device, Favorite, Folder, Send, TwoFactor, UserOrgType, UserOrganization}; use crate::db::DbConn; use crate::api::EmptyResult; @@ -263,6 +263,7 @@ impl User { } } + Send::delete_all_by_user(&self.uuid, conn)?; UserOrganization::delete_all_by_user(&self.uuid, conn)?; Cipher::delete_all_by_user(&self.uuid, conn)?; Favorite::delete_all_by_user(&self.uuid, conn)?; diff --git a/src/db/schemas/mysql/schema.rs b/src/db/schemas/mysql/schema.rs index d1a9962a..7f1f4805 100644 --- a/src/db/schemas/mysql/schema.rs +++ b/src/db/schemas/mysql/schema.rs @@ -102,6 +102,29 @@ table! { } } +table! { + sends (uuid) { + uuid -> Text, + user_uuid -> Nullable, + organization_uuid -> Nullable, + name -> Text, + notes -> Nullable, + atype -> Integer, + data -> Text, + key -> Text, + password_hash -> Nullable, + password_salt -> Nullable, + password_iter -> Nullable, + max_access_count -> Nullable, + access_count -> Integer, + creation_date -> Datetime, + revision_date -> Datetime, + expiration_date -> Nullable, + deletion_date -> Datetime, + disabled -> Bool, + } +} + table! { twofactor (uuid) { uuid -> Text, @@ -176,6 +199,8 @@ joinable!(folders -> users (user_uuid)); joinable!(folders_ciphers -> ciphers (cipher_uuid)); joinable!(folders_ciphers -> folders (folder_uuid)); joinable!(org_policies -> organizations (org_uuid)); +joinable!(sends -> organizations (organization_uuid)); +joinable!(sends -> users (user_uuid)); joinable!(twofactor -> users (user_uuid)); joinable!(users_collections -> collections (collection_uuid)); joinable!(users_collections -> users (user_uuid)); @@ -193,6 +218,7 @@ allow_tables_to_appear_in_same_query!( invitations, org_policies, organizations, + sends, twofactor, users, users_collections, diff --git a/src/db/schemas/postgresql/schema.rs b/src/db/schemas/postgresql/schema.rs index 5af0ece6..3eb94518 100644 --- a/src/db/schemas/postgresql/schema.rs +++ b/src/db/schemas/postgresql/schema.rs @@ -102,6 +102,29 @@ table! { } } +table! { + sends (uuid) { + uuid -> Text, + user_uuid -> Nullable, + organization_uuid -> Nullable, + name -> Text, + notes -> Nullable, + atype -> Integer, + data -> Text, + key -> Text, + password_hash -> Nullable, + password_salt -> Nullable, + password_iter -> Nullable, + max_access_count -> Nullable, + access_count -> Integer, + creation_date -> Timestamp, + revision_date -> Timestamp, + expiration_date -> Nullable, + deletion_date -> Timestamp, + disabled -> Bool, + } +} + table! { twofactor (uuid) { uuid -> Text, @@ -176,6 +199,8 @@ joinable!(folders -> users (user_uuid)); joinable!(folders_ciphers -> ciphers (cipher_uuid)); joinable!(folders_ciphers -> folders (folder_uuid)); joinable!(org_policies -> organizations (org_uuid)); +joinable!(sends -> organizations (organization_uuid)); +joinable!(sends -> users (user_uuid)); joinable!(twofactor -> users (user_uuid)); joinable!(users_collections -> collections (collection_uuid)); joinable!(users_collections -> users (user_uuid)); @@ -193,6 +218,7 @@ allow_tables_to_appear_in_same_query!( invitations, org_policies, organizations, + sends, twofactor, users, users_collections, diff --git a/src/db/schemas/sqlite/schema.rs b/src/db/schemas/sqlite/schema.rs index 5af0ece6..3eb94518 100644 --- a/src/db/schemas/sqlite/schema.rs +++ b/src/db/schemas/sqlite/schema.rs @@ -102,6 +102,29 @@ table! { } } +table! { + sends (uuid) { + uuid -> Text, + user_uuid -> Nullable, + organization_uuid -> Nullable, + name -> Text, + notes -> Nullable, + atype -> Integer, + data -> Text, + key -> Text, + password_hash -> Nullable, + password_salt -> Nullable, + password_iter -> Nullable, + max_access_count -> Nullable, + access_count -> Integer, + creation_date -> Timestamp, + revision_date -> Timestamp, + expiration_date -> Nullable, + deletion_date -> Timestamp, + disabled -> Bool, + } +} + table! { twofactor (uuid) { uuid -> Text, @@ -176,6 +199,8 @@ joinable!(folders -> users (user_uuid)); joinable!(folders_ciphers -> ciphers (cipher_uuid)); joinable!(folders_ciphers -> folders (folder_uuid)); joinable!(org_policies -> organizations (org_uuid)); +joinable!(sends -> organizations (organization_uuid)); +joinable!(sends -> users (user_uuid)); joinable!(twofactor -> users (user_uuid)); joinable!(users_collections -> collections (collection_uuid)); joinable!(users_collections -> users (user_uuid)); @@ -193,6 +218,7 @@ allow_tables_to_appear_in_same_query!( invitations, org_policies, organizations, + sends, twofactor, users, users_collections, diff --git a/src/error.rs b/src/error.rs index 80f9dafc..fa90f1d3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -220,6 +220,18 @@ macro_rules! err { }}; } +#[macro_export] +macro_rules! err_code { + ($msg:expr, $err_code: literal) => {{ + error!("{}", $msg); + return Err(crate::error::Error::new($msg, $msg).with_code($err_code)); + }}; + ($usr_msg:expr, $log_value:expr, $err_code: literal) => {{ + error!("{}. {}", $usr_msg, $log_value); + return Err(crate::error::Error::new($usr_msg, $log_value).with_code($err_code)); + }}; +} + #[macro_export] macro_rules! err_discard { ($msg:expr, $data:expr) => {{ From 7436b454db5734a225afa88db96fcb62b187bb4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Sun, 14 Mar 2021 23:36:49 +0100 Subject: [PATCH 5/7] Update web vault to 2.19.0 --- docker/Dockerfile.j2 | 4 ++-- docker/amd64/Dockerfile | 12 ++++++------ docker/amd64/Dockerfile.alpine | 12 ++++++------ docker/arm64/Dockerfile | 12 ++++++------ docker/armv6/Dockerfile | 12 ++++++------ docker/armv7/Dockerfile | 12 ++++++------ docker/armv7/Dockerfile.alpine | 12 ++++++------ 7 files changed, 38 insertions(+), 38 deletions(-) diff --git a/docker/Dockerfile.j2 b/docker/Dockerfile.j2 index 37f65c51..ec8e2301 100644 --- a/docker/Dockerfile.j2 +++ b/docker/Dockerfile.j2 @@ -44,8 +44,8 @@ # https://docs.docker.com/develop/develop-images/multistage-build/ # https://whitfin.io/speeding-up-rust-docker-builds/ ####################### VAULT BUILD IMAGE ####################### -{% set vault_version = "2.18.2" %} -{% set vault_image_digest = "sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5" %} +{% set vault_version = "2.19.0" %} +{% set vault_image_digest = "sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4" %} # The web-vault digest specifies a particular web-vault build on Docker Hub. # Using the digest instead of the tag name provides better security, # as the digest of an image is immutable, whereas a tag name can later diff --git a/docker/amd64/Dockerfile b/docker/amd64/Dockerfile index b7f7a7d8..08cdb1a8 100644 --- a/docker/amd64/Dockerfile +++ b/docker/amd64/Dockerfile @@ -14,15 +14,15 @@ # - From https://hub.docker.com/r/bitwardenrs/web-vault/tags, # click the tag name to view the digest of the image it currently points to. # - From the command line: -# $ docker pull bitwardenrs/web-vault:v2.18.2 -# $ docker image inspect --format "{{.RepoDigests}}" bitwardenrs/web-vault:v2.18.2 -# [bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5] +# $ docker pull bitwardenrs/web-vault:v2.19.0 +# $ docker image inspect --format "{{.RepoDigests}}" bitwardenrs/web-vault:v2.19.0 +# [bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4] # # - Conversely, to get the tag name from the digest: -# $ docker image inspect --format "{{.RepoTags}}" bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5 -# [bitwardenrs/web-vault:v2.18.2] +# $ docker image inspect --format "{{.RepoTags}}" bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4 +# [bitwardenrs/web-vault:v2.19.0] # -FROM bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5 as vault +FROM bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4 as vault ########################## BUILD IMAGE ########################## FROM rust:1.50 as build diff --git a/docker/amd64/Dockerfile.alpine b/docker/amd64/Dockerfile.alpine index f242bd56..71d63132 100644 --- a/docker/amd64/Dockerfile.alpine +++ b/docker/amd64/Dockerfile.alpine @@ -14,15 +14,15 @@ # - From https://hub.docker.com/r/bitwardenrs/web-vault/tags, # click the tag name to view the digest of the image it currently points to. # - From the command line: -# $ docker pull bitwardenrs/web-vault:v2.18.2 -# $ docker image inspect --format "{{.RepoDigests}}" bitwardenrs/web-vault:v2.18.2 -# [bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5] +# $ docker pull bitwardenrs/web-vault:v2.19.0 +# $ docker image inspect --format "{{.RepoDigests}}" bitwardenrs/web-vault:v2.19.0 +# [bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4] # # - Conversely, to get the tag name from the digest: -# $ docker image inspect --format "{{.RepoTags}}" bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5 -# [bitwardenrs/web-vault:v2.18.2] +# $ docker image inspect --format "{{.RepoTags}}" bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4 +# [bitwardenrs/web-vault:v2.19.0] # -FROM bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5 as vault +FROM bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4 as vault ########################## BUILD IMAGE ########################## FROM clux/muslrust:nightly-2021-02-22 as build diff --git a/docker/arm64/Dockerfile b/docker/arm64/Dockerfile index 43cfbfcf..c6faf743 100644 --- a/docker/arm64/Dockerfile +++ b/docker/arm64/Dockerfile @@ -14,15 +14,15 @@ # - From https://hub.docker.com/r/bitwardenrs/web-vault/tags, # click the tag name to view the digest of the image it currently points to. # - From the command line: -# $ docker pull bitwardenrs/web-vault:v2.18.2 -# $ docker image inspect --format "{{.RepoDigests}}" bitwardenrs/web-vault:v2.18.2 -# [bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5] +# $ docker pull bitwardenrs/web-vault:v2.19.0 +# $ docker image inspect --format "{{.RepoDigests}}" bitwardenrs/web-vault:v2.19.0 +# [bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4] # # - Conversely, to get the tag name from the digest: -# $ docker image inspect --format "{{.RepoTags}}" bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5 -# [bitwardenrs/web-vault:v2.18.2] +# $ docker image inspect --format "{{.RepoTags}}" bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4 +# [bitwardenrs/web-vault:v2.19.0] # -FROM bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5 as vault +FROM bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4 as vault ########################## BUILD IMAGE ########################## FROM rust:1.50 as build diff --git a/docker/armv6/Dockerfile b/docker/armv6/Dockerfile index 4768bff3..c095e8c9 100644 --- a/docker/armv6/Dockerfile +++ b/docker/armv6/Dockerfile @@ -14,15 +14,15 @@ # - From https://hub.docker.com/r/bitwardenrs/web-vault/tags, # click the tag name to view the digest of the image it currently points to. # - From the command line: -# $ docker pull bitwardenrs/web-vault:v2.18.2 -# $ docker image inspect --format "{{.RepoDigests}}" bitwardenrs/web-vault:v2.18.2 -# [bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5] +# $ docker pull bitwardenrs/web-vault:v2.19.0 +# $ docker image inspect --format "{{.RepoDigests}}" bitwardenrs/web-vault:v2.19.0 +# [bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4] # # - Conversely, to get the tag name from the digest: -# $ docker image inspect --format "{{.RepoTags}}" bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5 -# [bitwardenrs/web-vault:v2.18.2] +# $ docker image inspect --format "{{.RepoTags}}" bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4 +# [bitwardenrs/web-vault:v2.19.0] # -FROM bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5 as vault +FROM bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4 as vault ########################## BUILD IMAGE ########################## FROM rust:1.50 as build diff --git a/docker/armv7/Dockerfile b/docker/armv7/Dockerfile index 60fc1fbf..a880d061 100644 --- a/docker/armv7/Dockerfile +++ b/docker/armv7/Dockerfile @@ -14,15 +14,15 @@ # - From https://hub.docker.com/r/bitwardenrs/web-vault/tags, # click the tag name to view the digest of the image it currently points to. # - From the command line: -# $ docker pull bitwardenrs/web-vault:v2.18.2 -# $ docker image inspect --format "{{.RepoDigests}}" bitwardenrs/web-vault:v2.18.2 -# [bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5] +# $ docker pull bitwardenrs/web-vault:v2.19.0 +# $ docker image inspect --format "{{.RepoDigests}}" bitwardenrs/web-vault:v2.19.0 +# [bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4] # # - Conversely, to get the tag name from the digest: -# $ docker image inspect --format "{{.RepoTags}}" bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5 -# [bitwardenrs/web-vault:v2.18.2] +# $ docker image inspect --format "{{.RepoTags}}" bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4 +# [bitwardenrs/web-vault:v2.19.0] # -FROM bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5 as vault +FROM bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4 as vault ########################## BUILD IMAGE ########################## FROM rust:1.50 as build diff --git a/docker/armv7/Dockerfile.alpine b/docker/armv7/Dockerfile.alpine index 768d5db0..8e656354 100644 --- a/docker/armv7/Dockerfile.alpine +++ b/docker/armv7/Dockerfile.alpine @@ -14,15 +14,15 @@ # - From https://hub.docker.com/r/bitwardenrs/web-vault/tags, # click the tag name to view the digest of the image it currently points to. # - From the command line: -# $ docker pull bitwardenrs/web-vault:v2.18.2 -# $ docker image inspect --format "{{.RepoDigests}}" bitwardenrs/web-vault:v2.18.2 -# [bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5] +# $ docker pull bitwardenrs/web-vault:v2.19.0 +# $ docker image inspect --format "{{.RepoDigests}}" bitwardenrs/web-vault:v2.19.0 +# [bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4] # # - Conversely, to get the tag name from the digest: -# $ docker image inspect --format "{{.RepoTags}}" bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5 -# [bitwardenrs/web-vault:v2.18.2] +# $ docker image inspect --format "{{.RepoTags}}" bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4 +# [bitwardenrs/web-vault:v2.19.0] # -FROM bitwardenrs/web-vault@sha256:c287301264c7dc86d89aa80487fd7960cc24048390d2bef9ef910dfc77d2c7d5 as vault +FROM bitwardenrs/web-vault@sha256:8747cfaa2c6d87d1749e119dd884697e8099389aa9aca30a4d73d4ff796fe0e4 as vault ########################## BUILD IMAGE ########################## FROM messense/rust-musl-cross:armv7-musleabihf as build From 00d56d7295fc60c3f4d2cc43d2431dce7ed3edd5 Mon Sep 17 00:00:00 2001 From: Jeremy Lin Date: Sun, 14 Mar 2021 23:20:49 -0700 Subject: [PATCH 6/7] Send access check fixes Adjust checks for max access count, expiration date, and deletion date. The date checks aren't that important, but the access count check currently allows one more access than it should. --- src/api/core/sends.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/api/core/sends.rs b/src/api/core/sends.rs index 6fc1dcbc..34e46b68 100644 --- a/src/api/core/sends.rs +++ b/src/api/core/sends.rs @@ -197,18 +197,18 @@ fn post_access(access_id: String, data: JsonUpcase, conn: DbConn }; if let Some(max_access_count) = send.max_access_count { - if send.access_count > max_access_count { + if send.access_count >= max_access_count { err_code!("Max access count reached", 404); } } if let Some(expiration) = send.expiration_date { - if Utc::now().naive_utc() > expiration { + if Utc::now().naive_utc() >= expiration { err_code!("Send has expired", 404) } } - if Utc::now().naive_utc() > send.deletion_date { + if Utc::now().naive_utc() >= send.deletion_date { err_code!("Send has been deleted", 404) } @@ -248,18 +248,18 @@ fn post_access_file( }; if let Some(max_access_count) = send.max_access_count { - if send.access_count > max_access_count { + if send.access_count >= max_access_count { err_code!("Max access count reached", 404); } } if let Some(expiration) = send.expiration_date { - if Utc::now().naive_utc() > expiration { + if Utc::now().naive_utc() >= expiration { err_code!("Send has expired", 404) } } - if Utc::now().naive_utc() > send.deletion_date { + if Utc::now().naive_utc() >= send.deletion_date { err_code!("Send has been deleted", 404) } From 95e24ffc51db2f6834142ec86568c2d244562006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 15 Mar 2021 16:42:20 +0100 Subject: [PATCH 7/7] rename send key -> akey --- migrations/mysql/2021-03-11-190243_add_sends/up.sql | 2 +- .../postgresql/2021-03-15-163412_rename_send_key/down.sql | 0 .../postgresql/2021-03-15-163412_rename_send_key/up.sql | 1 + .../sqlite/2021-03-15-163412_rename_send_key/down.sql | 0 .../sqlite/2021-03-15-163412_rename_send_key/up.sql | 1 + src/api/core/sends.rs | 2 +- src/db/models/send.rs | 8 ++++---- src/db/schemas/mysql/schema.rs | 2 +- src/db/schemas/postgresql/schema.rs | 2 +- src/db/schemas/sqlite/schema.rs | 2 +- 10 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 migrations/postgresql/2021-03-15-163412_rename_send_key/down.sql create mode 100644 migrations/postgresql/2021-03-15-163412_rename_send_key/up.sql create mode 100644 migrations/sqlite/2021-03-15-163412_rename_send_key/down.sql create mode 100644 migrations/sqlite/2021-03-15-163412_rename_send_key/up.sql diff --git a/migrations/mysql/2021-03-11-190243_add_sends/up.sql b/migrations/mysql/2021-03-11-190243_add_sends/up.sql index ccc457dc..65b818a4 100644 --- a/migrations/mysql/2021-03-11-190243_add_sends/up.sql +++ b/migrations/mysql/2021-03-11-190243_add_sends/up.sql @@ -8,7 +8,7 @@ CREATE TABLE sends ( atype INTEGER NOT NULL, data TEXT NOT NULL, - key TEXT NOT NULL, + akey TEXT NOT NULL, password_hash BLOB, password_salt BLOB, password_iter INTEGER, diff --git a/migrations/postgresql/2021-03-15-163412_rename_send_key/down.sql b/migrations/postgresql/2021-03-15-163412_rename_send_key/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/postgresql/2021-03-15-163412_rename_send_key/up.sql b/migrations/postgresql/2021-03-15-163412_rename_send_key/up.sql new file mode 100644 index 00000000..08339fac --- /dev/null +++ b/migrations/postgresql/2021-03-15-163412_rename_send_key/up.sql @@ -0,0 +1 @@ +ALTER TABLE sends RENAME COLUMN key TO akey; diff --git a/migrations/sqlite/2021-03-15-163412_rename_send_key/down.sql b/migrations/sqlite/2021-03-15-163412_rename_send_key/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/sqlite/2021-03-15-163412_rename_send_key/up.sql b/migrations/sqlite/2021-03-15-163412_rename_send_key/up.sql new file mode 100644 index 00000000..08339fac --- /dev/null +++ b/migrations/sqlite/2021-03-15-163412_rename_send_key/up.sql @@ -0,0 +1 @@ +ALTER TABLE sends RENAME COLUMN key TO akey; diff --git a/src/api/core/sends.rs b/src/api/core/sends.rs index 6fc1dcbc..d14dc57d 100644 --- a/src/api/core/sends.rs +++ b/src/api/core/sends.rs @@ -325,7 +325,7 @@ fn put_send(id: String, data: JsonUpcase, headers: Headers, conn: DbCo } send.data = data_str; send.name = data.Name; - send.key = data.Key; + send.akey = data.Key; send.deletion_date = data.DeletionDate.naive_utc(); send.notes = data.Notes; send.max_access_count = data.MaxAccessCount; diff --git a/src/db/models/send.rs b/src/db/models/send.rs index 674337ed..d7a7a872 100644 --- a/src/db/models/send.rs +++ b/src/db/models/send.rs @@ -22,7 +22,7 @@ db_object! { pub atype: i32, pub data: String, - pub key: String, + pub akey: String, pub password_hash: Option>, password_salt: Option>, password_iter: Option, @@ -46,7 +46,7 @@ pub enum SendType { } impl Send { - pub fn new(atype: i32, name: String, data: String, key: String, deletion_date: NaiveDateTime) -> Self { + pub fn new(atype: i32, name: String, data: String, akey: String, deletion_date: NaiveDateTime) -> Self { let now = Utc::now().naive_utc(); Self { @@ -59,7 +59,7 @@ impl Send { atype, data, - key, + akey, password_hash: None, password_salt: None, password_iter: None, @@ -118,7 +118,7 @@ impl Send { "Text": if self.atype == SendType::Text as i32 { Some(&data) } else { None }, "File": if self.atype == SendType::File as i32 { Some(&data) } else { None }, - "Key": self.key, + "Key": self.akey, "MaxAccessCount": self.max_access_count, "AccessCount": self.access_count, "Password": self.password_hash.as_deref().map(|h| BASE64URL_NOPAD.encode(h)), diff --git a/src/db/schemas/mysql/schema.rs b/src/db/schemas/mysql/schema.rs index 7f1f4805..346b2959 100644 --- a/src/db/schemas/mysql/schema.rs +++ b/src/db/schemas/mysql/schema.rs @@ -111,7 +111,7 @@ table! { notes -> Nullable, atype -> Integer, data -> Text, - key -> Text, + akey -> Text, password_hash -> Nullable, password_salt -> Nullable, password_iter -> Nullable, diff --git a/src/db/schemas/postgresql/schema.rs b/src/db/schemas/postgresql/schema.rs index 3eb94518..f8e1e9fe 100644 --- a/src/db/schemas/postgresql/schema.rs +++ b/src/db/schemas/postgresql/schema.rs @@ -111,7 +111,7 @@ table! { notes -> Nullable, atype -> Integer, data -> Text, - key -> Text, + akey -> Text, password_hash -> Nullable, password_salt -> Nullable, password_iter -> Nullable, diff --git a/src/db/schemas/sqlite/schema.rs b/src/db/schemas/sqlite/schema.rs index 3eb94518..f8e1e9fe 100644 --- a/src/db/schemas/sqlite/schema.rs +++ b/src/db/schemas/sqlite/schema.rs @@ -111,7 +111,7 @@ table! { notes -> Nullable, atype -> Integer, data -> Text, - key -> Text, + akey -> Text, password_hash -> Nullable, password_salt -> Nullable, password_iter -> Nullable,