diff --git a/.env.template b/.env.template index 140a4ccc..6cf3e92f 100644 --- a/.env.template +++ b/.env.template @@ -63,6 +63,12 @@ ## - https://docs.diesel.rs/2.1.x/diesel/pg/struct.PgConnection.html ## - https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING # DATABASE_URL=postgresql://user:password@host[:port]/database_name +## When using CockroachDB, specify in the same way you would with PostgreSQL +## with protocol either "cockroachdb" or "cockroach" +## Details: +## - https://docs.diesel.rs/2.1.x/diesel/pg/struct.PgConnection.html +## - https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING +# DATABASE_URL=cockroachdb://user:password@host[:port]/database_name ## Enable WAL for the DB ## Set to false to avoid enabling WAL during startup. @@ -99,6 +105,7 @@ ## - SQLite: "PRAGMA busy_timeout = 5000; PRAGMA synchronous = NORMAL;" ## - MySQL: "" ## - PostgreSQL: "" +## - CockroachDB: "" # DATABASE_CONN_INIT="" ################# diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..60af40a5 --- /dev/null +++ b/.envrc @@ -0,0 +1,2 @@ +use flake . --show-trace +dotenv_if_exists .env diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7ed85943..14e5fa4b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -77,8 +77,6 @@ jobs: fi echo "RUST_TOOLCHAIN=${RUST_TOOLCHAIN}" | tee -a "${GITHUB_OUTPUT}" # End Determine rust-toolchain version - - # Only install the clippy and rustfmt components on the default rust-toolchain - name: "Install rust-toolchain version" uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master @ Aug 23, 2025, 3:20 AM GMT+2 @@ -88,7 +86,6 @@ jobs: components: clippy, rustfmt # End Uses the rust-toolchain file to determine version - # Install the any other channel to be used for which we do not execute clippy and rustfmt - name: "Install MSRV version" uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master @ Aug 23, 2025, 3:20 AM GMT+2 @@ -113,7 +110,6 @@ jobs: rustc -vV cargo -vV # End Show environment - # Enable Rust Caching - name: Rust Caching uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0 @@ -126,23 +122,23 @@ jobs: # Run cargo tests # First test all features together, afterwards test them separately. - - name: "test features: sqlite,mysql,postgresql,enable_mimalloc,query_logger" - id: test_sqlite_mysql_postgresql_mimalloc_logger + - name: "test features: sqlite,mysql,postgresql,cockroachdb,enable_mimalloc,query_logger" + id: test_sqlite_mysql_postgresql_cockroachdb_mimalloc_logger if: ${{ !cancelled() }} run: | - cargo test --features sqlite,mysql,postgresql,enable_mimalloc,query_logger + cargo test --features sqlite,mysql,postgresql,cockroachdb,enable_mimalloc,query_logger - - name: "test features: sqlite,mysql,postgresql,enable_mimalloc" - id: test_sqlite_mysql_postgresql_mimalloc + - name: "test features: sqlite,mysql,postgresql,cockroachdb,enable_mimalloc" + id: test_sqlite_mysql_postgresql_cockroachdb_mimalloc if: ${{ !cancelled() }} run: | - cargo test --features sqlite,mysql,postgresql,enable_mimalloc + cargo test --features sqlite,mysql,postgresql,cockroachdb,enable_mimalloc - name: "test features: sqlite,mysql,postgresql" - id: test_sqlite_mysql_postgresql + id: test_sqlite_mysql_postgresql_cockroachdb if: ${{ !cancelled() }} run: | - cargo test --features sqlite,mysql,postgresql + cargo test --features sqlite,mysql,postgresql,cockroachdb - name: "test features: sqlite" id: test_sqlite @@ -161,18 +157,20 @@ jobs: if: ${{ !cancelled() }} run: | cargo test --features postgresql - # End Run cargo tests - + - name: "test features: cockroachdb" + id: test_cockroachdb + if: ${{ !cancelled() }} + run: | + cargo test --features cockroachdb + # End Run cargo tests # Run cargo clippy, and fail on warnings - - name: "clippy features: sqlite,mysql,postgresql,enable_mimalloc" + - name: "clippy features: sqlite,mysql,postgresql,cockroachdb,enable_mimalloc" id: clippy if: ${{ !cancelled() && matrix.channel == 'rust-toolchain' }} run: | - cargo clippy --features sqlite,mysql,postgresql,enable_mimalloc + cargo clippy --features sqlite,mysql,postgresql,cockroachdb,enable_mimalloc # End Run cargo clippy - - # Run cargo fmt (Only run on rust-toolchain defined version) - name: "check formatting" id: formatting @@ -180,19 +178,18 @@ jobs: run: | cargo fmt --all -- --check # End Run cargo fmt - - # Check for any previous failures, if there are stop, else continue. # This is useful so all test/clippy/fmt actions are done, and they can all be addressed - name: "Some checks failed" if: ${{ failure() }} env: - TEST_DB_M_L: ${{ steps.test_sqlite_mysql_postgresql_mimalloc_logger.outcome }} - TEST_DB_M: ${{ steps.test_sqlite_mysql_postgresql_mimalloc.outcome }} - TEST_DB: ${{ steps.test_sqlite_mysql_postgresql.outcome }} + TEST_DB_M_L: ${{ steps.test_sqlite_mysql_postgresql_cockroachdb_mimalloc_logger.outcome }} + TEST_DB_M: ${{ steps.test_sqlite_mysql_postgresql_cockroachdb_mimalloc.outcome }} + TEST_DB: ${{ steps.test_sqlite_mysql_postgresql_cockroachdb.outcome }} TEST_SQLITE: ${{ steps.test_sqlite.outcome }} TEST_MYSQL: ${{ steps.test_mysql.outcome }} TEST_POSTGRESQL: ${{ steps.test_postgresql.outcome }} + TEST_COCKROACHDB: ${{ steps.test_cockroachdb.outcome }} CLIPPY: ${{ steps.clippy.outcome }} FMT: ${{ steps.formatting.outcome }} run: | @@ -200,20 +197,20 @@ jobs: echo "" >> "${GITHUB_STEP_SUMMARY}" echo "|Job|Status|" >> "${GITHUB_STEP_SUMMARY}" echo "|---|------|" >> "${GITHUB_STEP_SUMMARY}" - echo "|test (sqlite,mysql,postgresql,enable_mimalloc,query_logger)|${TEST_DB_M_L}|" >> "${GITHUB_STEP_SUMMARY}" - echo "|test (sqlite,mysql,postgresql,enable_mimalloc)|${TEST_DB_M}|" >> "${GITHUB_STEP_SUMMARY}" - echo "|test (sqlite,mysql,postgresql)|${TEST_DB}|" >> "${GITHUB_STEP_SUMMARY}" + echo "|test (sqlite,mysql,postgresql,cockroachdb,enable_mimalloc,query_logger)|${TEST_DB_M_L}|" >> "${GITHUB_STEP_SUMMARY}" + echo "|test (sqlite,mysql,postgresql,cockroachdb,enable_mimalloc)|${TEST_DB_M}|" >> "${GITHUB_STEP_SUMMARY}" + echo "|test (sqlite,mysql,postgresql,cockroachdb)|${TEST_DB}|" >> "${GITHUB_STEP_SUMMARY}" echo "|test (sqlite)|${TEST_SQLITE}|" >> "${GITHUB_STEP_SUMMARY}" echo "|test (mysql)|${TEST_MYSQL}|" >> "${GITHUB_STEP_SUMMARY}" echo "|test (postgresql)|${TEST_POSTGRESQL}|" >> "${GITHUB_STEP_SUMMARY}" - echo "|clippy (sqlite,mysql,postgresql,enable_mimalloc)|${CLIPPY}|" >> "${GITHUB_STEP_SUMMARY}" + echo "|test (cockroachdb)|${TEST_COCKROACHDB}|" >> "${GITHUB_STEP_SUMMARY}" + echo "|clippy (sqlite,mysql,postgresql,cockroachdb,enable_mimalloc)|${CLIPPY}|" >> "${GITHUB_STEP_SUMMARY}" echo "|fmt|${FMT}|" >> "${GITHUB_STEP_SUMMARY}" echo "" >> "${GITHUB_STEP_SUMMARY}" echo "Please check the failed jobs and fix where needed." >> "${GITHUB_STEP_SUMMARY}" echo "" >> "${GITHUB_STEP_SUMMARY}" exit 1 - # Check for any previous failures, if there are stop, else continue. # This is useful so all test/clippy/fmt actions are done, and they can all be addressed - name: "All checks passed" diff --git a/.gitignore b/.gitignore index e991430e..86d104c6 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ data # Web vault web-vault + +# Direnv +.direnv/ diff --git a/.helix/languages.toml b/.helix/languages.toml new file mode 100644 index 00000000..fd927e4c --- /dev/null +++ b/.helix/languages.toml @@ -0,0 +1,56 @@ +[language-server] +nil = { command = "nil" } +taplo = { command = "taplo", args = ["lsp", "stdio"] } +yaml-language-server = { command = "yaml-language-server", args = ["--stdio"] } +marksman = { command = "marksman", args = ["server"] } +vscode-json-language-server = { command = "vscode-json-language-server", args = [ + "--stdio", +], config = { json = { validate = { enable = true } } } } + +[language-server.rust-analyzer] +command = "rust-analyzer" + +[language-server.rust-analyzer.config] +inlayHints.bindingModeHints.enable = false +inlayHints.closingBraceHints.minLines = 10 +inlayHints.closureReturnTypeHints.enable = "with_block" +inlayHints.discriminantHints.enable = "fieldless" +inlayHints.lifetimeElisionHints.enable = "skip_trivial" +inlayHints.typeHints.hideClosureInitialization = false +procMacro.enable = true +cargo.features = "rust-analyzer-stable" +check.features = "rust-analyzer-stable" + +[[language]] +name = "nix" +auto-format = true +formatter = { command = "nixpkgs-fmt" } +language-servers = ["nil"] + +[[language]] +name = "toml" +auto-format = true +language-servers = ["taplo"] + +[[language]] +name = "yaml" +auto-format = true +formatter = { command = "prettier", args = ["--parser", "yaml"] } +language-servers = ["yaml-language-server"] + +[[language]] +name = "json" +auto-format = true +formatter = { command = "prettier", args = ["--parser", "json"] } +language-servers = ["vscode-json-language-server"] + +[[language]] +name = "markdown" +auto-format = true +formatter = { command = "prettier", args = ["--parser", "markdown"] } +language-servers = ["marksman"] + +[[language]] +name = "rust" +auto-format = true +language-servers = ["rust-analyzer"] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a967edbf..8a3a1d33 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,52 +1,64 @@ --- repos: -- repo: https://github.com/pre-commit/pre-commit-hooks + - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 hooks: - - id: check-yaml - - id: check-json - - id: check-toml - - id: mixed-line-ending - args: ["--fix=no"] - - id: end-of-file-fixer - exclude: "(.*js$|.*css$)" - - id: check-case-conflict - - id: check-merge-conflict - - id: detect-private-key - - id: check-symlinks - - id: forbid-submodules -- repo: local + - id: check-yaml + - id: check-json + - id: check-toml + - id: mixed-line-ending + args: ["--fix=no"] + - id: end-of-file-fixer + exclude: "(.*js$|.*css$)" + - id: check-case-conflict + - id: check-merge-conflict + - id: detect-private-key + - id: check-symlinks + - id: forbid-submodules + - repo: local hooks: - - id: fmt - name: fmt - description: Format files with cargo fmt. - entry: cargo fmt - language: system - types: [rust] - args: ["--", "--check"] - - id: cargo-test - name: cargo test - description: Test the package for errors. - entry: cargo test - language: system - args: ["--features", "sqlite,mysql,postgresql,enable_mimalloc", "--"] - types_or: [rust, file] - files: (Cargo.toml|Cargo.lock|rust-toolchain.toml|rustfmt.toml|.*\.rs$) - pass_filenames: false - - id: cargo-clippy - name: cargo clippy - description: Lint Rust sources - entry: cargo clippy - language: system - args: ["--features", "sqlite,mysql,postgresql,enable_mimalloc", "--", "-D", "warnings"] - types_or: [rust, file] - files: (Cargo.toml|Cargo.lock|rust-toolchain.toml|rustfmt.toml|.*\.rs$) - pass_filenames: false - - id: check-docker-templates - name: check docker templates - description: Check if the Docker templates are updated - language: system - entry: sh - args: - - "-c" - - "cd docker && make" + - id: fmt + name: fmt + description: Format files with cargo fmt. + entry: cargo fmt + language: system + types: [rust] + args: ["--", "--check"] + - id: cargo-test + name: cargo test + description: Test the package for errors. + entry: cargo test + language: system + args: + [ + "--features", + "sqlite,mysql,postgresql,cockroachdb,enable_mimalloc", + "--", + ] + types_or: [rust, file] + files: (Cargo.toml|Cargo.lock|rust-toolchain.toml|rustfmt.toml|.*\.rs$) + pass_filenames: false + - id: cargo-clippy + name: cargo clippy + description: Lint Rust sources + entry: cargo clippy + language: system + args: + [ + "--features", + "sqlite,mysql,postgresql,cockroachdb,enable_mimalloc", + "--", + "-D", + "warnings", + ] + types_or: [rust, file] + files: (Cargo.toml|Cargo.lock|rust-toolchain.toml|rustfmt.toml|.*\.rs$) + pass_filenames: false + - id: check-docker-templates + name: check docker templates + description: Check if the Docker templates are updated + language: system + entry: sh + args: + - "-c" + - "cd docker && make" diff --git a/Cargo.toml b/Cargo.toml index c62bc929..03aca529 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ build = "build.rs" enable_syslog = [] mysql = ["diesel/mysql", "diesel_migrations/mysql"] postgresql = ["diesel/postgres", "diesel_migrations/postgres"] +cockroachdb = ["diesel/postgres", "diesel_migrations/postgres"] sqlite = ["diesel/sqlite", "diesel_migrations/sqlite", "dep:libsqlite3-sys"] # Enable to use a vendored and statically linked openssl vendored_openssl = ["openssl/vendored"] @@ -32,7 +33,15 @@ enable_mimalloc = ["dep:mimalloc"] # You also need to set an env variable `QUERY_LOGGER=1` to fully activate this so you do not have to re-compile # if you want to turn off the logging for a specific run. query_logger = ["dep:diesel_logger"] -s3 = ["opendal/services-s3", "dep:aws-config", "dep:aws-credential-types", "dep:aws-smithy-runtime-api", "dep:anyhow", "dep:http", "dep:reqsign"] +s3 = [ + "opendal/services-s3", + "dep:aws-config", + "dep:aws-credential-types", + "dep:aws-smithy-runtime-api", + "dep:anyhow", + "dep:http", + "dep:reqsign", +] # OIDC specific features oidc-accept-rfc3339-timestamps = ["openidconnect/accept-rfc3339-timestamps"] @@ -42,6 +51,21 @@ oidc-accept-string-booleans = ["openidconnect/accept-string-booleans"] # Currently only used to enable rusts official ip support unstable = [] +# Aggregator feature that has everything except unstable so nightly is not needed for most development +rust-analyzer-stable = [ + "enable_syslog", + "mysql", + "postgresql", + "cockroachdb", + "sqlite", + "vendored_openssl", + "enable_mimalloc", + "query_logger", + "s3", + "oidc-accept-rfc3339-timestamps", + "oidc-accept-string-booleans", +] + [target."cfg(unix)".dependencies] # Logging syslog = "7.0.0" @@ -52,7 +76,9 @@ macros = { path = "./macros" } # Logging log = "0.4.27" fern = { version = "0.7.1", features = ["syslog-7", "reopen-1"] } -tracing = { version = "0.1.41", features = ["log"] } # Needed to have lettre and webauthn-rs trace logging to work +tracing = { version = "0.1.41", features = [ + "log", +] } # Needed to have lettre and webauthn-rs trace logging to work # A `dotenv` implementation for Rust dotenvy = { version = "0.15.7", default-features = false } @@ -66,8 +92,11 @@ num-derive = "0.4.2" bigdecimal = "0.4.8" # Web framework -rocket = { version = "0.5.1", features = ["tls", "json"], default-features = false } -rocket_ws = { version ="0.1.1" } +rocket = { version = "0.5.1", features = [ + "tls", + "json", +], default-features = false } +rocket_ws = { version = "0.1.1" } # WebSockets libraries rmpv = "1.3.0" # MessagePack library @@ -77,8 +106,16 @@ dashmap = "6.1.0" # Async futures futures = "0.3.31" -tokio = { version = "1.47.1", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time", "signal", "net"] } -tokio-util = { version = "0.7.16", features = ["compat"]} +tokio = { version = "1.47.1", features = [ + "rt-multi-thread", + "fs", + "io-util", + "parking_lot", + "time", + "signal", + "net", +] } +tokio-util = { version = "0.7.16", features = ["compat"] } # A generic serialization/deserialization framework serde = { version = "1.0.219", features = ["derive"] } @@ -89,7 +126,13 @@ diesel = { version = "2.2.12", features = ["chrono", "r2d2", "numeric"] } diesel_migrations = "2.2.0" diesel_logger = { version = "0.4.0", optional = true } -derive_more = { version = "2.0.1", features = ["from", "into", "as_ref", "deref", "display"] } +derive_more = { version = "2.0.1", features = [ + "from", + "into", + "as_ref", + "deref", + "display", +] } diesel-derive-newtype = "2.1.2" # Bundled/Static SQLite @@ -104,7 +147,10 @@ subtle = "2.6.1" uuid = { version = "1.18.0", features = ["v4"] } # Date and time libraries -chrono = { version = "0.4.41", features = ["clock", "serde"], default-features = false } +chrono = { version = "0.4.41", features = [ + "clock", + "serde", +], default-features = false } chrono-tz = "0.10.4" time = "0.3.41" @@ -121,12 +167,17 @@ jsonwebtoken = "9.3.1" totp-lite = "2.0.1" # Yubico Library -yubico = { package = "yubico_ng", version = "0.14.1", features = ["online-tokio"], default-features = false } +yubico = { package = "yubico_ng", version = "0.14.1", features = [ + "online-tokio", +], default-features = false } # WebAuthn libraries # danger-allow-state-serialisation is needed to save the state in the db # danger-credential-internals is needed to support U2F to Webauthn migration -webauthn-rs = { version = "0.5.2", features = ["danger-allow-state-serialisation", "danger-credential-internals"] } +webauthn-rs = { version = "0.5.2", features = [ + "danger-allow-state-serialisation", + "danger-credential-internals", +] } webauthn-rs-proto = "0.5.2" webauthn-rs-core = "0.5.2" @@ -134,7 +185,17 @@ webauthn-rs-core = "0.5.2" url = "2.5.7" # Email libraries -lettre = { version = "0.11.18", features = ["smtp-transport", "sendmail-transport", "builder", "serde", "hostname", "tracing", "tokio1-rustls", "ring", "rustls-native-certs"], default-features = false } +lettre = { version = "0.11.18", features = [ + "smtp-transport", + "sendmail-transport", + "builder", + "serde", + "hostname", + "tracing", + "tokio1-rustls", + "ring", + "rustls-native-certs", +], default-features = false } percent-encoding = "2.3.2" # URL encoding library used for URL's in the emails email_address = "0.2.9" @@ -142,12 +203,30 @@ email_address = "0.2.9" handlebars = { version = "6.3.2", features = ["dir_source"] } # HTTP client (Used for favicons, version check, DUO and HIBP API) -reqwest = { version = "0.12.23", features = ["rustls-tls", "rustls-tls-native-roots", "stream", "json", "deflate", "gzip", "brotli", "zstd", "socks", "cookies", "charset", "http2", "system-proxy"], default-features = false} +reqwest = { version = "0.12.23", features = [ + "rustls-tls", + "rustls-tls-native-roots", + "stream", + "json", + "deflate", + "gzip", + "brotli", + "zstd", + "socks", + "cookies", + "charset", + "http2", + "system-proxy", +], default-features = false } hickory-resolver = "0.25.2" # Favicon extraction libraries html5gum = "0.8.0" -regex = { version = "1.11.2", features = ["std", "perf", "unicode-perl"], default-features = false } +regex = { version = "1.11.2", features = [ + "std", + "perf", + "unicode-perl", +], default-features = false } data-url = "0.3.2" bytes = "1.10.1" svg-hush = "0.9.5" @@ -159,7 +238,7 @@ cached = { version = "0.56.0", features = ["async"] } cookie = "0.18.1" cookie_store = "0.21.1" -# Used by U2F, JWT and PostgreSQL +# Used by U2F, JWT, PostgreSQL and CockroachDB openssl = "0.10.73" # CLI argument parsing @@ -178,7 +257,9 @@ semver = "1.0.26" # Allow overriding the default memory allocator # Mainly used for the musl builds, since the default musl malloc is very slow -mimalloc = { version = "0.1.48", features = ["secure"], default-features = false, optional = true } +mimalloc = { version = "0.1.48", features = [ + "secure", +], default-features = false, optional = true } which = "8.0.0" @@ -192,11 +273,18 @@ rpassword = "7.4.0" grass_compiler = { version = "0.13.4", default-features = false } # File are accessed through Apache OpenDAL -opendal = { version = "0.54.0", features = ["services-fs"], default-features = false } +opendal = { version = "0.54.0", features = [ + "services-fs", +], default-features = false } # For retrieving AWS credentials, including temporary SSO credentials anyhow = { version = "1.0.99", optional = true } -aws-config = { version = "1.8.5", features = ["behavior-version-latest", "rt-tokio", "credentials-process", "sso"], default-features = false, optional = true } +aws-config = { version = "1.8.5", features = [ + "behavior-version-latest", + "rt-tokio", + "credentials-process", + "sso", +], default-features = false, optional = true } aws-credential-types = { version = "1.2.5", optional = true } aws-smithy-runtime-api = { version = "1.9.0", optional = true } http = { version = "1.3.1", optional = true } @@ -253,7 +341,7 @@ refining_impl_trait = { level = "deny", priority = -1 } rust_2018_idioms = { level = "deny", priority = -1 } rust_2021_compatibility = { level = "deny", priority = -1 } rust_2024_compatibility = { level = "deny", priority = -1 } -edition_2024_expr_fragment_specifier = "allow" # Once changed to Rust 2024 this should be removed and macro's should be validated again +edition_2024_expr_fragment_specifier = "allow" # Once changed to Rust 2024 this should be removed and macro's should be validated again single_use_lifetimes = "deny" trivial_casts = "deny" trivial_numeric_casts = "deny" diff --git a/build.rs b/build.rs index 1dbb1a0b..226a52e6 100644 --- a/build.rs +++ b/build.rs @@ -9,12 +9,14 @@ fn main() { println!("cargo:rustc-cfg=mysql"); #[cfg(feature = "postgresql")] println!("cargo:rustc-cfg=postgresql"); + #[cfg(feature = "cockroachdb")] + println!("cargo:rustc-cfg=cockroachdb"); #[cfg(feature = "query_logger")] println!("cargo:rustc-cfg=query_logger"); #[cfg(feature = "s3")] println!("cargo:rustc-cfg=s3"); - #[cfg(not(any(feature = "sqlite", feature = "mysql", feature = "postgresql")))] + #[cfg(not(any(feature = "sqlite", feature = "mysql", feature = "postgresql", feature = "cockroachdb")))] compile_error!( "You need to enable one DB backend. To build with previous defaults do: cargo build --features sqlite" ); @@ -24,6 +26,7 @@ fn main() { println!("cargo::rustc-check-cfg=cfg(sqlite)"); println!("cargo::rustc-check-cfg=cfg(mysql)"); println!("cargo::rustc-check-cfg=cfg(postgresql)"); + println!("cargo::rustc-check-cfg=cfg(cockroachdb)"); println!("cargo::rustc-check-cfg=cfg(query_logger)"); println!("cargo::rustc-check-cfg=cfg(s3)"); diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine index 09477b3e..20506ddb 100644 --- a/docker/Dockerfile.alpine +++ b/docker/Dockerfile.alpine @@ -82,7 +82,7 @@ ARG CARGO_PROFILE=release # Configure the DB ARG as late as possible to not invalidate the cached layers above # Enable MiMalloc to improve performance on Alpine builds -ARG DB=sqlite,mysql,postgresql,enable_mimalloc +ARG DB=sqlite,mysql,postgresql,cockroachdb,enable_mimalloc # Builds your dependencies and removes the # dummy project, except the target folder diff --git a/docker/Dockerfile.debian b/docker/Dockerfile.debian index 9d1af57f..4b97d130 100644 --- a/docker/Dockerfile.debian +++ b/docker/Dockerfile.debian @@ -117,7 +117,7 @@ COPY ./macros ./macros ARG CARGO_PROFILE=release # Configure the DB ARG as late as possible to not invalidate the cached layers above -ARG DB=sqlite,mysql,postgresql +ARG DB=sqlite,mysql,postgresql,cockroachdb # Builds your dependencies and removes the # dummy project, except the target folder diff --git a/docker/Dockerfile.j2 b/docker/Dockerfile.j2 index 98a3a3f9..3e7cd3d6 100644 --- a/docker/Dockerfile.j2 +++ b/docker/Dockerfile.j2 @@ -145,10 +145,10 @@ ARG CARGO_PROFILE=release # Configure the DB ARG as late as possible to not invalidate the cached layers above {% if base == "debian" %} -ARG DB=sqlite,mysql,postgresql +ARG DB=sqlite,mysql,postgresql,cockroachdb {% elif base == "alpine" %} # Enable MiMalloc to improve performance on Alpine builds -ARG DB=sqlite,mysql,postgresql,enable_mimalloc +ARG DB=sqlite,mysql,postgresql,cockroachdb,enable_mimalloc {% endif %} # Builds your dependencies and removes the diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..4e9c80f4 --- /dev/null +++ b/flake.lock @@ -0,0 +1,60 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1757746433, + "narHash": "sha256-fEvTiU4s9lWgW7mYEU/1QUPirgkn+odUBTaindgiziY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6d7ec06d6868ac6d94c371458fc2391ded9ff13d", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixpkgs-unstable", + "type": "indirect" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "utils": "utils" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..8eca0d01 --- /dev/null +++ b/flake.nix @@ -0,0 +1,55 @@ +{ + inputs = { + nixpkgs.url = "nixpkgs/nixpkgs-unstable"; + utils.url = "github:numtide/flake-utils"; + }; + + outputs = + { + self, + nixpkgs, + utils, + }: + utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs.outPath { + inherit system; + }; + in + { + devShells.default = pkgs.mkShell rec { + RUST_BACKTRACE = "full"; + LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath buildInputs}"; + + buildInputs = with pkgs; [ + pkg-config + openssl + libpq + libmysqlclient + ]; + + packages = with pkgs; [ + git + + nil + nixfmt-rfc-style + + rustc + cargo + clippy + rustfmt + rust-analyzer + + nodePackages.prettier + nodePackages.yaml-language-server + nodePackages.vscode-langservers-extracted + markdownlint-cli + nodePackages.markdown-link-check + marksman + taplo + ]; + }; + } + ); +} diff --git a/migrations/cockroachdb/2019-09-12-100000_create_tables/down.sql b/migrations/cockroachdb/2019-09-12-100000_create_tables/down.sql new file mode 100644 index 00000000..e4561c37 --- /dev/null +++ b/migrations/cockroachdb/2019-09-12-100000_create_tables/down.sql @@ -0,0 +1,13 @@ +DROP TABLE devices; +DROP TABLE attachments; +DROP TABLE users_collections; +DROP TABLE users_organizations; +DROP TABLE folders_ciphers; +DROP TABLE ciphers_collections; +DROP TABLE twofactor; +DROP TABLE invitations; +DROP TABLE collections; +DROP TABLE folders; +DROP TABLE ciphers; +DROP TABLE users; +DROP TABLE organizations; diff --git a/migrations/cockroachdb/2019-09-12-100000_create_tables/up.sql b/migrations/cockroachdb/2019-09-12-100000_create_tables/up.sql new file mode 100644 index 00000000..7b30d02b --- /dev/null +++ b/migrations/cockroachdb/2019-09-12-100000_create_tables/up.sql @@ -0,0 +1,121 @@ +CREATE TABLE users ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + created_at TIMESTAMP NOT NULL, + updated_at TIMESTAMP NOT NULL, + email VARCHAR(255) NOT NULL UNIQUE, + name TEXT NOT NULL, + password_hash BYTEA NOT NULL, + salt BYTEA NOT NULL, + password_iterations INT4 NOT NULL, + password_hint TEXT, + akey TEXT NOT NULL, + private_key TEXT, + public_key TEXT, + totp_secret TEXT, + totp_recover TEXT, + security_stamp TEXT NOT NULL, + equivalent_domains TEXT NOT NULL, + excluded_globals TEXT NOT NULL, + client_kdf_type INT4 NOT NULL DEFAULT 0, + client_kdf_iter INT4 NOT NULL DEFAULT 100000 +); + +CREATE TABLE devices ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + created_at TIMESTAMP NOT NULL, + updated_at TIMESTAMP NOT NULL, + user_uuid CHAR(36) NOT NULL REFERENCES users (uuid), + name TEXT NOT NULL, + atype INT4 NOT NULL, + push_token TEXT, + refresh_token TEXT NOT NULL, + twofactor_remember TEXT +); + +CREATE TABLE organizations ( + uuid VARCHAR(40) NOT NULL PRIMARY KEY, + name TEXT NOT NULL, + billing_email TEXT NOT NULL +); + +CREATE TABLE ciphers ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + created_at TIMESTAMP NOT NULL, + updated_at TIMESTAMP NOT NULL, + user_uuid CHAR(36) REFERENCES users (uuid), + organization_uuid CHAR(36) REFERENCES organizations (uuid), + atype INT4 NOT NULL, + name TEXT NOT NULL, + notes TEXT, + fields TEXT, + data TEXT NOT NULL, + favorite BOOLEAN NOT NULL, + password_history TEXT +); + +CREATE TABLE attachments ( + id CHAR(36) NOT NULL PRIMARY KEY, + cipher_uuid CHAR(36) NOT NULL REFERENCES ciphers (uuid), + file_name TEXT NOT NULL, + file_size INT4 NOT NULL, + akey TEXT +); + +CREATE TABLE folders ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + created_at TIMESTAMP NOT NULL, + updated_at TIMESTAMP NOT NULL, + user_uuid CHAR(36) NOT NULL REFERENCES users (uuid), + name TEXT NOT NULL +); + +CREATE TABLE collections ( + uuid VARCHAR(40) NOT NULL PRIMARY KEY, + org_uuid VARCHAR(40) NOT NULL REFERENCES organizations (uuid), + name TEXT NOT NULL +); + +CREATE TABLE users_collections ( + user_uuid CHAR(36) NOT NULL REFERENCES users (uuid), + collection_uuid CHAR(36) NOT NULL REFERENCES collections (uuid), + read_only BOOLEAN NOT NULL DEFAULT false, + PRIMARY KEY (user_uuid, collection_uuid) +); + +CREATE TABLE users_organizations ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + user_uuid CHAR(36) NOT NULL REFERENCES users (uuid), + org_uuid CHAR(36) NOT NULL REFERENCES organizations (uuid), + + access_all BOOLEAN NOT NULL, + akey TEXT NOT NULL, + status INT4 NOT NULL, + atype INT4 NOT NULL, + + UNIQUE (user_uuid, org_uuid) +); + +CREATE TABLE folders_ciphers ( + cipher_uuid CHAR(36) NOT NULL REFERENCES ciphers (uuid), + folder_uuid CHAR(36) NOT NULL REFERENCES folders (uuid), + PRIMARY KEY (cipher_uuid, folder_uuid) +); + +CREATE TABLE ciphers_collections ( + cipher_uuid CHAR(36) NOT NULL REFERENCES ciphers (uuid), + collection_uuid CHAR(36) NOT NULL REFERENCES collections (uuid), + PRIMARY KEY (cipher_uuid, collection_uuid) +); + +CREATE TABLE twofactor ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + user_uuid CHAR(36) NOT NULL REFERENCES users (uuid), + atype INT4 NOT NULL, + enabled BOOLEAN NOT NULL, + data TEXT NOT NULL, + UNIQUE (user_uuid, atype) +); + +CREATE TABLE invitations ( + email VARCHAR(255) NOT NULL PRIMARY KEY +); \ No newline at end of file diff --git a/migrations/cockroachdb/2019-09-16-150000_fix_attachments/down.sql b/migrations/cockroachdb/2019-09-16-150000_fix_attachments/down.sql new file mode 100644 index 00000000..f26824d1 --- /dev/null +++ b/migrations/cockroachdb/2019-09-16-150000_fix_attachments/down.sql @@ -0,0 +1,26 @@ +ALTER TABLE attachments ALTER COLUMN id TYPE CHAR(36); +ALTER TABLE attachments ALTER COLUMN cipher_uuid TYPE CHAR(36); +ALTER TABLE users ALTER COLUMN uuid TYPE CHAR(36); +ALTER TABLE users ALTER COLUMN email TYPE VARCHAR(255); +ALTER TABLE devices ALTER COLUMN uuid TYPE CHAR(36); +ALTER TABLE devices ALTER COLUMN user_uuid TYPE CHAR(36); +ALTER TABLE organizations ALTER COLUMN uuid TYPE CHAR(40); +ALTER TABLE ciphers ALTER COLUMN uuid TYPE CHAR(36); +ALTER TABLE ciphers ALTER COLUMN user_uuid TYPE CHAR(36); +ALTER TABLE ciphers ALTER COLUMN organization_uuid TYPE CHAR(36); +ALTER TABLE folders ALTER COLUMN uuid TYPE CHAR(36); +ALTER TABLE folders ALTER COLUMN user_uuid TYPE CHAR(36); +ALTER TABLE collections ALTER COLUMN uuid TYPE CHAR(40); +ALTER TABLE collections ALTER COLUMN org_uuid TYPE CHAR(40); +ALTER TABLE users_collections ALTER COLUMN user_uuid TYPE CHAR(36); +ALTER TABLE users_collections ALTER COLUMN collection_uuid TYPE CHAR(36); +ALTER TABLE users_organizations ALTER COLUMN uuid TYPE CHAR(36); +ALTER TABLE users_organizations ALTER COLUMN user_uuid TYPE CHAR(36); +ALTER TABLE users_organizations ALTER COLUMN org_uuid TYPE CHAR(36); +ALTER TABLE folders_ciphers ALTER COLUMN cipher_uuid TYPE CHAR(36); +ALTER TABLE folders_ciphers ALTER COLUMN folder_uuid TYPE CHAR(36); +ALTER TABLE ciphers_collections ALTER COLUMN cipher_uuid TYPE CHAR(36); +ALTER TABLE ciphers_collections ALTER COLUMN collection_uuid TYPE CHAR(36); +ALTER TABLE twofactor ALTER COLUMN uuid TYPE CHAR(36); +ALTER TABLE twofactor ALTER COLUMN user_uuid TYPE CHAR(36); +ALTER TABLE invitations ALTER COLUMN email TYPE VARCHAR(255); \ No newline at end of file diff --git a/migrations/cockroachdb/2019-09-16-150000_fix_attachments/up.sql b/migrations/cockroachdb/2019-09-16-150000_fix_attachments/up.sql new file mode 100644 index 00000000..388f2915 --- /dev/null +++ b/migrations/cockroachdb/2019-09-16-150000_fix_attachments/up.sql @@ -0,0 +1,27 @@ +-- Switch from CHAR() types to VARCHAR() types to avoid padding issues. +ALTER TABLE attachments ALTER COLUMN id TYPE TEXT; +ALTER TABLE attachments ALTER COLUMN cipher_uuid TYPE VARCHAR(40); +ALTER TABLE users ALTER COLUMN uuid TYPE VARCHAR(40); +ALTER TABLE users ALTER COLUMN email TYPE TEXT; +ALTER TABLE devices ALTER COLUMN uuid TYPE VARCHAR(40); +ALTER TABLE devices ALTER COLUMN user_uuid TYPE VARCHAR(40); +ALTER TABLE organizations ALTER COLUMN uuid TYPE VARCHAR(40); +ALTER TABLE ciphers ALTER COLUMN uuid TYPE VARCHAR(40); +ALTER TABLE ciphers ALTER COLUMN user_uuid TYPE VARCHAR(40); +ALTER TABLE ciphers ALTER COLUMN organization_uuid TYPE VARCHAR(40); +ALTER TABLE folders ALTER COLUMN uuid TYPE VARCHAR(40); +ALTER TABLE folders ALTER COLUMN user_uuid TYPE VARCHAR(40); +ALTER TABLE collections ALTER COLUMN uuid TYPE VARCHAR(40); +ALTER TABLE collections ALTER COLUMN org_uuid TYPE VARCHAR(40); +ALTER TABLE users_collections ALTER COLUMN user_uuid TYPE VARCHAR(40); +ALTER TABLE users_collections ALTER COLUMN collection_uuid TYPE VARCHAR(40); +ALTER TABLE users_organizations ALTER COLUMN uuid TYPE VARCHAR(40); +ALTER TABLE users_organizations ALTER COLUMN user_uuid TYPE VARCHAR(40); +ALTER TABLE users_organizations ALTER COLUMN org_uuid TYPE VARCHAR(40); +ALTER TABLE folders_ciphers ALTER COLUMN cipher_uuid TYPE VARCHAR(40); +ALTER TABLE folders_ciphers ALTER COLUMN folder_uuid TYPE VARCHAR(40); +ALTER TABLE ciphers_collections ALTER COLUMN cipher_uuid TYPE VARCHAR(40); +ALTER TABLE ciphers_collections ALTER COLUMN collection_uuid TYPE VARCHAR(40); +ALTER TABLE twofactor ALTER COLUMN uuid TYPE VARCHAR(40); +ALTER TABLE twofactor ALTER COLUMN user_uuid TYPE VARCHAR(40); +ALTER TABLE invitations ALTER COLUMN email TYPE TEXT; \ No newline at end of file diff --git a/migrations/cockroachdb/2019-10-10-083032_add_column_to_twofactor/down.sql b/migrations/cockroachdb/2019-10-10-083032_add_column_to_twofactor/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2019-10-10-083032_add_column_to_twofactor/up.sql b/migrations/cockroachdb/2019-10-10-083032_add_column_to_twofactor/up.sql new file mode 100644 index 00000000..93ba6aa1 --- /dev/null +++ b/migrations/cockroachdb/2019-10-10-083032_add_column_to_twofactor/up.sql @@ -0,0 +1 @@ +ALTER TABLE twofactor ADD COLUMN last_used INT4 NOT NULL DEFAULT 0; \ No newline at end of file diff --git a/migrations/cockroachdb/2019-11-17-011009_add_email_verification/down.sql b/migrations/cockroachdb/2019-11-17-011009_add_email_verification/down.sql new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/migrations/cockroachdb/2019-11-17-011009_add_email_verification/down.sql @@ -0,0 +1 @@ + diff --git a/migrations/cockroachdb/2019-11-17-011009_add_email_verification/up.sql b/migrations/cockroachdb/2019-11-17-011009_add_email_verification/up.sql new file mode 100644 index 00000000..b430cd06 --- /dev/null +++ b/migrations/cockroachdb/2019-11-17-011009_add_email_verification/up.sql @@ -0,0 +1,5 @@ +ALTER TABLE users ADD COLUMN verified_at TIMESTAMP DEFAULT NULL; +ALTER TABLE users ADD COLUMN last_verifying_at TIMESTAMP DEFAULT NULL; +ALTER TABLE users ADD COLUMN login_verify_count INT4 NOT NULL DEFAULT 0; +ALTER TABLE users ADD COLUMN email_new VARCHAR(255) DEFAULT NULL; +ALTER TABLE users ADD COLUMN email_new_token VARCHAR(16) DEFAULT NULL; diff --git a/migrations/cockroachdb/2020-03-13-205045_add_policy_table/down.sql b/migrations/cockroachdb/2020-03-13-205045_add_policy_table/down.sql new file mode 100644 index 00000000..8dc1826a --- /dev/null +++ b/migrations/cockroachdb/2020-03-13-205045_add_policy_table/down.sql @@ -0,0 +1 @@ +DROP TABLE org_policies; diff --git a/migrations/cockroachdb/2020-03-13-205045_add_policy_table/up.sql b/migrations/cockroachdb/2020-03-13-205045_add_policy_table/up.sql new file mode 100644 index 00000000..1f2c0016 --- /dev/null +++ b/migrations/cockroachdb/2020-03-13-205045_add_policy_table/up.sql @@ -0,0 +1,9 @@ +CREATE TABLE org_policies ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + org_uuid CHAR(36) NOT NULL REFERENCES organizations (uuid), + atype INT4 NOT NULL, + enabled BOOLEAN NOT NULL, + data TEXT NOT NULL, + + UNIQUE (org_uuid, atype) +); diff --git a/migrations/cockroachdb/2020-04-09-235005_add_cipher_delete_date/down.sql b/migrations/cockroachdb/2020-04-09-235005_add_cipher_delete_date/down.sql new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/migrations/cockroachdb/2020-04-09-235005_add_cipher_delete_date/down.sql @@ -0,0 +1 @@ + diff --git a/migrations/cockroachdb/2020-04-09-235005_add_cipher_delete_date/up.sql b/migrations/cockroachdb/2020-04-09-235005_add_cipher_delete_date/up.sql new file mode 100644 index 00000000..1a2edde4 --- /dev/null +++ b/migrations/cockroachdb/2020-04-09-235005_add_cipher_delete_date/up.sql @@ -0,0 +1,3 @@ +ALTER TABLE ciphers + ADD COLUMN + deleted_at TIMESTAMP; diff --git a/migrations/cockroachdb/2020-07-01-214531_add_hide_passwords/down.sql b/migrations/cockroachdb/2020-07-01-214531_add_hide_passwords/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2020-07-01-214531_add_hide_passwords/up.sql b/migrations/cockroachdb/2020-07-01-214531_add_hide_passwords/up.sql new file mode 100644 index 00000000..4587232e --- /dev/null +++ b/migrations/cockroachdb/2020-07-01-214531_add_hide_passwords/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE users_collections +ADD COLUMN hide_passwords BOOLEAN NOT NULL DEFAULT FALSE; diff --git a/migrations/cockroachdb/2020-08-02-025025_add_favorites_table/down.sql b/migrations/cockroachdb/2020-08-02-025025_add_favorites_table/down.sql new file mode 100644 index 00000000..c79a61de --- /dev/null +++ b/migrations/cockroachdb/2020-08-02-025025_add_favorites_table/down.sql @@ -0,0 +1 @@ +DROP TABLE favorites; diff --git a/migrations/cockroachdb/2020-08-02-025025_add_favorites_table/up.sql b/migrations/cockroachdb/2020-08-02-025025_add_favorites_table/up.sql new file mode 100644 index 00000000..d5a02bfa --- /dev/null +++ b/migrations/cockroachdb/2020-08-02-025025_add_favorites_table/up.sql @@ -0,0 +1,6 @@ +CREATE TABLE favorites ( + user_uuid VARCHAR(40) NOT NULL REFERENCES users(uuid), + cipher_uuid VARCHAR(40) NOT NULL REFERENCES ciphers(uuid), + + PRIMARY KEY (user_uuid, cipher_uuid) +); diff --git a/migrations/cockroachdb/2020-08-02-025026_add_favorites_table_fix/down.sql b/migrations/cockroachdb/2020-08-02-025026_add_favorites_table_fix/down.sql new file mode 100644 index 00000000..af5669fa --- /dev/null +++ b/migrations/cockroachdb/2020-08-02-025026_add_favorites_table_fix/down.sql @@ -0,0 +1,11 @@ +ALTER TABLE ciphers +ADD COLUMN favorite BOOLEAN NOT NULL DEFAULT FALSE; + +-- Transfer favorite status for user-owned ciphers. +UPDATE ciphers +SET favorite = TRUE +WHERE EXISTS ( + SELECT * FROM favorites + WHERE favorites.user_uuid = ciphers.user_uuid + AND favorites.cipher_uuid = ciphers.uuid +); diff --git a/migrations/cockroachdb/2020-08-02-025026_add_favorites_table_fix/up.sql b/migrations/cockroachdb/2020-08-02-025026_add_favorites_table_fix/up.sql new file mode 100644 index 00000000..af67e7b5 --- /dev/null +++ b/migrations/cockroachdb/2020-08-02-025026_add_favorites_table_fix/up.sql @@ -0,0 +1,9 @@ +-- Transfer favorite status for user-owned ciphers. +INSERT INTO favorites(user_uuid, cipher_uuid) +SELECT user_uuid, uuid +FROM ciphers +WHERE favorite = TRUE + AND user_uuid IS NOT NULL; + +ALTER TABLE ciphers +DROP COLUMN favorite; diff --git a/migrations/cockroachdb/2020-11-30-224000_add_user_enabled/down.sql b/migrations/cockroachdb/2020-11-30-224000_add_user_enabled/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2020-11-30-224000_add_user_enabled/up.sql b/migrations/cockroachdb/2020-11-30-224000_add_user_enabled/up.sql new file mode 100644 index 00000000..1f13c203 --- /dev/null +++ b/migrations/cockroachdb/2020-11-30-224000_add_user_enabled/up.sql @@ -0,0 +1 @@ +ALTER TABLE users ADD COLUMN enabled BOOLEAN NOT NULL DEFAULT true; diff --git a/migrations/cockroachdb/2020-12-09-173101_add_stamp_exception/down.sql b/migrations/cockroachdb/2020-12-09-173101_add_stamp_exception/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2020-12-09-173101_add_stamp_exception/up.sql b/migrations/cockroachdb/2020-12-09-173101_add_stamp_exception/up.sql new file mode 100644 index 00000000..bcad3922 --- /dev/null +++ b/migrations/cockroachdb/2020-12-09-173101_add_stamp_exception/up.sql @@ -0,0 +1 @@ +ALTER TABLE users ADD COLUMN stamp_exception TEXT DEFAULT NULL; \ No newline at end of file diff --git a/migrations/cockroachdb/2021-03-11-190243_add_sends/down.sql b/migrations/cockroachdb/2021-03-11-190243_add_sends/down.sql new file mode 100644 index 00000000..b843b76a --- /dev/null +++ b/migrations/cockroachdb/2021-03-11-190243_add_sends/down.sql @@ -0,0 +1 @@ +DROP TABLE sends; diff --git a/migrations/cockroachdb/2021-03-11-190243_add_sends/up.sql b/migrations/cockroachdb/2021-03-11-190243_add_sends/up.sql new file mode 100644 index 00000000..8a69fe78 --- /dev/null +++ b/migrations/cockroachdb/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 INT4 NOT NULL, + data TEXT NOT NULL, + key TEXT NOT NULL, + password_hash BYTEA, + password_salt BYTEA, + password_iter INT4, + + max_access_count INT4, + access_count INT4 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/cockroachdb/2021-03-15-163412_rename_send_key/down.sql b/migrations/cockroachdb/2021-03-15-163412_rename_send_key/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2021-03-15-163412_rename_send_key/up.sql b/migrations/cockroachdb/2021-03-15-163412_rename_send_key/up.sql new file mode 100644 index 00000000..08339fac --- /dev/null +++ b/migrations/cockroachdb/2021-03-15-163412_rename_send_key/up.sql @@ -0,0 +1 @@ +ALTER TABLE sends RENAME COLUMN key TO akey; diff --git a/migrations/cockroachdb/2021-04-30-233251_add_reprompt/down.sql b/migrations/cockroachdb/2021-04-30-233251_add_reprompt/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2021-04-30-233251_add_reprompt/up.sql b/migrations/cockroachdb/2021-04-30-233251_add_reprompt/up.sql new file mode 100644 index 00000000..d6070a08 --- /dev/null +++ b/migrations/cockroachdb/2021-04-30-233251_add_reprompt/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE ciphers +ADD COLUMN reprompt INT4; diff --git a/migrations/cockroachdb/2021-05-11-205202_add_hide_email/down.sql b/migrations/cockroachdb/2021-05-11-205202_add_hide_email/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2021-05-11-205202_add_hide_email/up.sql b/migrations/cockroachdb/2021-05-11-205202_add_hide_email/up.sql new file mode 100644 index 00000000..4d6e0225 --- /dev/null +++ b/migrations/cockroachdb/2021-05-11-205202_add_hide_email/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE sends +ADD COLUMN hide_email BOOLEAN; diff --git a/migrations/cockroachdb/2021-07-01-203140_add_password_reset_keys/down.sql b/migrations/cockroachdb/2021-07-01-203140_add_password_reset_keys/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2021-07-01-203140_add_password_reset_keys/up.sql b/migrations/cockroachdb/2021-07-01-203140_add_password_reset_keys/up.sql new file mode 100644 index 00000000..2e83860c --- /dev/null +++ b/migrations/cockroachdb/2021-07-01-203140_add_password_reset_keys/up.sql @@ -0,0 +1,5 @@ +ALTER TABLE organizations + ADD COLUMN private_key TEXT; + +ALTER TABLE organizations + ADD COLUMN public_key TEXT; diff --git a/migrations/cockroachdb/2021-08-30-193501_create_emergency_access/down.sql b/migrations/cockroachdb/2021-08-30-193501_create_emergency_access/down.sql new file mode 100644 index 00000000..f9d18f1e --- /dev/null +++ b/migrations/cockroachdb/2021-08-30-193501_create_emergency_access/down.sql @@ -0,0 +1 @@ +DROP TABLE emergency_access; diff --git a/migrations/cockroachdb/2021-08-30-193501_create_emergency_access/up.sql b/migrations/cockroachdb/2021-08-30-193501_create_emergency_access/up.sql new file mode 100644 index 00000000..4cadeb04 --- /dev/null +++ b/migrations/cockroachdb/2021-08-30-193501_create_emergency_access/up.sql @@ -0,0 +1,14 @@ +CREATE TABLE emergency_access ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + grantor_uuid CHAR(36) REFERENCES users (uuid), + grantee_uuid CHAR(36) REFERENCES users (uuid), + email VARCHAR(255), + key_encrypted TEXT, + atype INT4 NOT NULL, + status INT4 NOT NULL, + wait_time_days INT4 NOT NULL, + recovery_initiated_at TIMESTAMP, + last_notification_at TIMESTAMP, + updated_at TIMESTAMP NOT NULL, + created_at TIMESTAMP NOT NULL +); diff --git a/migrations/cockroachdb/2021-10-24-164321_add_2fa_incomplete/down.sql b/migrations/cockroachdb/2021-10-24-164321_add_2fa_incomplete/down.sql new file mode 100644 index 00000000..31165c92 --- /dev/null +++ b/migrations/cockroachdb/2021-10-24-164321_add_2fa_incomplete/down.sql @@ -0,0 +1 @@ +DROP TABLE twofactor_incomplete; diff --git a/migrations/cockroachdb/2021-10-24-164321_add_2fa_incomplete/up.sql b/migrations/cockroachdb/2021-10-24-164321_add_2fa_incomplete/up.sql new file mode 100644 index 00000000..52a1d773 --- /dev/null +++ b/migrations/cockroachdb/2021-10-24-164321_add_2fa_incomplete/up.sql @@ -0,0 +1,9 @@ +CREATE TABLE twofactor_incomplete ( + user_uuid VARCHAR(40) NOT NULL REFERENCES users(uuid), + device_uuid VARCHAR(40) NOT NULL, + device_name TEXT NOT NULL, + login_time TIMESTAMP NOT NULL, + ip_address TEXT NOT NULL, + + PRIMARY KEY (user_uuid, device_uuid) +); diff --git a/migrations/cockroachdb/2022-01-17-234911_add_api_key/down.sql b/migrations/cockroachdb/2022-01-17-234911_add_api_key/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2022-01-17-234911_add_api_key/up.sql b/migrations/cockroachdb/2022-01-17-234911_add_api_key/up.sql new file mode 100644 index 00000000..b1117556 --- /dev/null +++ b/migrations/cockroachdb/2022-01-17-234911_add_api_key/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE users +ADD COLUMN api_key TEXT; diff --git a/migrations/cockroachdb/2022-03-02-210038_update_devices_primary_key/down.sql b/migrations/cockroachdb/2022-03-02-210038_update_devices_primary_key/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2022-03-02-210038_update_devices_primary_key/up.sql b/migrations/cockroachdb/2022-03-02-210038_update_devices_primary_key/up.sql new file mode 100644 index 00000000..0dc9ea67 --- /dev/null +++ b/migrations/cockroachdb/2022-03-02-210038_update_devices_primary_key/up.sql @@ -0,0 +1,4 @@ +-- First remove the previous primary key +ALTER TABLE devices DROP CONSTRAINT devices_pkey; +-- Add a new combined one +ALTER TABLE devices ADD PRIMARY KEY (uuid, user_uuid); diff --git a/migrations/cockroachdb/2022-07-27-110000_add_group_support/down.sql b/migrations/cockroachdb/2022-07-27-110000_add_group_support/down.sql new file mode 100644 index 00000000..9a12d694 --- /dev/null +++ b/migrations/cockroachdb/2022-07-27-110000_add_group_support/down.sql @@ -0,0 +1,3 @@ +DROP TABLE groups; +DROP TABLE groups_users; +DROP TABLE collections_groups; \ No newline at end of file diff --git a/migrations/cockroachdb/2022-07-27-110000_add_group_support/up.sql b/migrations/cockroachdb/2022-07-27-110000_add_group_support/up.sql new file mode 100644 index 00000000..5eed1df3 --- /dev/null +++ b/migrations/cockroachdb/2022-07-27-110000_add_group_support/up.sql @@ -0,0 +1,23 @@ +CREATE TABLE groups ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + organizations_uuid VARCHAR(40) NOT NULL REFERENCES organizations (uuid), + name VARCHAR(100) NOT NULL, + access_all BOOLEAN NOT NULL, + external_id VARCHAR(300) NULL, + creation_date TIMESTAMP NOT NULL, + revision_date TIMESTAMP NOT NULL +); + +CREATE TABLE groups_users ( + groups_uuid CHAR(36) NOT NULL REFERENCES groups (uuid), + users_organizations_uuid VARCHAR(36) NOT NULL REFERENCES users_organizations (uuid), + PRIMARY KEY (groups_uuid, users_organizations_uuid) +); + +CREATE TABLE collections_groups ( + collections_uuid VARCHAR(40) NOT NULL REFERENCES collections (uuid), + groups_uuid CHAR(36) NOT NULL REFERENCES groups (uuid), + read_only BOOLEAN NOT NULL, + hide_passwords BOOLEAN NOT NULL, + PRIMARY KEY (collections_uuid, groups_uuid) +); \ No newline at end of file diff --git a/migrations/cockroachdb/2022-10-18-170602_add_events/down.sql b/migrations/cockroachdb/2022-10-18-170602_add_events/down.sql new file mode 100644 index 00000000..8b975bc3 --- /dev/null +++ b/migrations/cockroachdb/2022-10-18-170602_add_events/down.sql @@ -0,0 +1 @@ +DROP TABLE event; diff --git a/migrations/cockroachdb/2022-10-18-170602_add_events/up.sql b/migrations/cockroachdb/2022-10-18-170602_add_events/up.sql new file mode 100644 index 00000000..9a6d9689 --- /dev/null +++ b/migrations/cockroachdb/2022-10-18-170602_add_events/up.sql @@ -0,0 +1,19 @@ +CREATE TABLE event ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + event_type INT4 NOT NULL, + user_uuid CHAR(36), + org_uuid CHAR(36), + cipher_uuid CHAR(36), + collection_uuid CHAR(36), + group_uuid CHAR(36), + org_user_uuid CHAR(36), + act_user_uuid CHAR(36), + device_type INT4, + ip_address TEXT, + event_date TIMESTAMP NOT NULL, + policy_uuid CHAR(36), + provider_uuid CHAR(36), + provider_user_uuid CHAR(36), + provider_org_uuid CHAR(36), + UNIQUE (uuid) +); diff --git a/migrations/cockroachdb/2023-01-06-151600_add_reset_password_support/down.sql b/migrations/cockroachdb/2023-01-06-151600_add_reset_password_support/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2023-01-06-151600_add_reset_password_support/up.sql b/migrations/cockroachdb/2023-01-06-151600_add_reset_password_support/up.sql new file mode 100644 index 00000000..326b3106 --- /dev/null +++ b/migrations/cockroachdb/2023-01-06-151600_add_reset_password_support/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE users_organizations +ADD COLUMN reset_password_key TEXT; diff --git a/migrations/cockroachdb/2023-01-11-205851_add_avatar_color/down.sql b/migrations/cockroachdb/2023-01-11-205851_add_avatar_color/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2023-01-11-205851_add_avatar_color/up.sql b/migrations/cockroachdb/2023-01-11-205851_add_avatar_color/up.sql new file mode 100644 index 00000000..cf3ef9f7 --- /dev/null +++ b/migrations/cockroachdb/2023-01-11-205851_add_avatar_color/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE users +ADD COLUMN avatar_color TEXT; diff --git a/migrations/cockroachdb/2023-01-31-222222_add_argon2/down.sql b/migrations/cockroachdb/2023-01-31-222222_add_argon2/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2023-01-31-222222_add_argon2/up.sql b/migrations/cockroachdb/2023-01-31-222222_add_argon2/up.sql new file mode 100644 index 00000000..2912d623 --- /dev/null +++ b/migrations/cockroachdb/2023-01-31-222222_add_argon2/up.sql @@ -0,0 +1,7 @@ +ALTER TABLE users + ADD COLUMN + client_kdf_memory INT4 DEFAULT NULL; + +ALTER TABLE users + ADD COLUMN + client_kdf_parallelism INT4 DEFAULT NULL; diff --git a/migrations/cockroachdb/2023-02-18-125735_push_uuid_table/down.sql b/migrations/cockroachdb/2023-02-18-125735_push_uuid_table/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2023-02-18-125735_push_uuid_table/up.sql b/migrations/cockroachdb/2023-02-18-125735_push_uuid_table/up.sql new file mode 100644 index 00000000..b2a3ea11 --- /dev/null +++ b/migrations/cockroachdb/2023-02-18-125735_push_uuid_table/up.sql @@ -0,0 +1 @@ +ALTER TABLE devices ADD COLUMN push_uuid TEXT; \ No newline at end of file diff --git a/migrations/cockroachdb/2023-06-02-200424_create_organization_api_key/down.sql b/migrations/cockroachdb/2023-06-02-200424_create_organization_api_key/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2023-06-02-200424_create_organization_api_key/up.sql b/migrations/cockroachdb/2023-06-02-200424_create_organization_api_key/up.sql new file mode 100644 index 00000000..400804e6 --- /dev/null +++ b/migrations/cockroachdb/2023-06-02-200424_create_organization_api_key/up.sql @@ -0,0 +1,10 @@ +CREATE TABLE organization_api_key ( + uuid CHAR(36) NOT NULL, + org_uuid CHAR(36) NOT NULL REFERENCES organizations(uuid), + atype INT4 NOT NULL, + api_key VARCHAR(255), + revision_date TIMESTAMP NOT NULL, + PRIMARY KEY(uuid, org_uuid) +); + +ALTER TABLE users ADD COLUMN external_id TEXT; diff --git a/migrations/cockroachdb/2023-06-17-200424_create_auth_requests_table/down.sql b/migrations/cockroachdb/2023-06-17-200424_create_auth_requests_table/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2023-06-17-200424_create_auth_requests_table/up.sql b/migrations/cockroachdb/2023-06-17-200424_create_auth_requests_table/up.sql new file mode 100644 index 00000000..c2c51598 --- /dev/null +++ b/migrations/cockroachdb/2023-06-17-200424_create_auth_requests_table/up.sql @@ -0,0 +1,19 @@ +CREATE TABLE auth_requests ( + uuid CHAR(36) NOT NULL PRIMARY KEY, + user_uuid CHAR(36) NOT NULL, + organization_uuid CHAR(36), + request_device_identifier CHAR(36) NOT NULL, + device_type INT4 NOT NULL, + request_ip TEXT NOT NULL, + response_device_id CHAR(36), + access_code TEXT NOT NULL, + public_key TEXT NOT NULL, + enc_key TEXT NOT NULL, + master_password_hash TEXT NOT NULL, + approved BOOLEAN, + creation_date TIMESTAMP NOT NULL, + response_date TIMESTAMP, + authentication_date TIMESTAMP, + FOREIGN KEY(user_uuid) REFERENCES users(uuid), + FOREIGN KEY(organization_uuid) REFERENCES organizations(uuid) +); \ No newline at end of file diff --git a/migrations/cockroachdb/2023-06-28-133700_add_collection_external_id/down.sql b/migrations/cockroachdb/2023-06-28-133700_add_collection_external_id/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2023-06-28-133700_add_collection_external_id/up.sql b/migrations/cockroachdb/2023-06-28-133700_add_collection_external_id/up.sql new file mode 100644 index 00000000..7f44709b --- /dev/null +++ b/migrations/cockroachdb/2023-06-28-133700_add_collection_external_id/up.sql @@ -0,0 +1 @@ +ALTER TABLE collections ADD COLUMN external_id TEXT; diff --git a/migrations/cockroachdb/2023-09-01-170620_update_auth_request_table/down.sql b/migrations/cockroachdb/2023-09-01-170620_update_auth_request_table/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2023-09-01-170620_update_auth_request_table/up.sql b/migrations/cockroachdb/2023-09-01-170620_update_auth_request_table/up.sql new file mode 100644 index 00000000..5715316d --- /dev/null +++ b/migrations/cockroachdb/2023-09-01-170620_update_auth_request_table/up.sql @@ -0,0 +1,5 @@ +ALTER TABLE auth_requests +ALTER COLUMN master_password_hash DROP NOT NULL; + +ALTER TABLE auth_requests +ALTER COLUMN enc_key DROP NOT NULL; diff --git a/migrations/cockroachdb/2023-09-02-212336_move_user_external_id/down.sql b/migrations/cockroachdb/2023-09-02-212336_move_user_external_id/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2023-09-02-212336_move_user_external_id/up.sql b/migrations/cockroachdb/2023-09-02-212336_move_user_external_id/up.sql new file mode 100644 index 00000000..5adacf95 --- /dev/null +++ b/migrations/cockroachdb/2023-09-02-212336_move_user_external_id/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE users_organizations +ADD COLUMN external_id TEXT; diff --git a/migrations/cockroachdb/2023-09-10-133000_add_sso/down.sql b/migrations/cockroachdb/2023-09-10-133000_add_sso/down.sql new file mode 100644 index 00000000..2c946dc5 --- /dev/null +++ b/migrations/cockroachdb/2023-09-10-133000_add_sso/down.sql @@ -0,0 +1 @@ +DROP TABLE sso_nonce; diff --git a/migrations/cockroachdb/2023-09-10-133000_add_sso/up.sql b/migrations/cockroachdb/2023-09-10-133000_add_sso/up.sql new file mode 100644 index 00000000..1321e246 --- /dev/null +++ b/migrations/cockroachdb/2023-09-10-133000_add_sso/up.sql @@ -0,0 +1,4 @@ +CREATE TABLE sso_nonce ( + nonce CHAR(36) NOT NULL PRIMARY KEY, + created_at TIMESTAMP NOT NULL DEFAULT now() +); diff --git a/migrations/cockroachdb/2023-09-14-133000_add_users_organizations_invited_by_email/down.sql b/migrations/cockroachdb/2023-09-14-133000_add_users_organizations_invited_by_email/down.sql new file mode 100644 index 00000000..3a708927 --- /dev/null +++ b/migrations/cockroachdb/2023-09-14-133000_add_users_organizations_invited_by_email/down.sql @@ -0,0 +1 @@ +ALTER TABLE users_organizations DROP COLUMN invited_by_email; diff --git a/migrations/cockroachdb/2023-09-14-133000_add_users_organizations_invited_by_email/up.sql b/migrations/cockroachdb/2023-09-14-133000_add_users_organizations_invited_by_email/up.sql new file mode 100644 index 00000000..c94e1131 --- /dev/null +++ b/migrations/cockroachdb/2023-09-14-133000_add_users_organizations_invited_by_email/up.sql @@ -0,0 +1 @@ +ALTER TABLE users_organizations ADD COLUMN invited_by_email TEXT DEFAULT NULL; diff --git a/migrations/cockroachdb/2023-10-21-221242_add_cipher_key/down.sql b/migrations/cockroachdb/2023-10-21-221242_add_cipher_key/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2023-10-21-221242_add_cipher_key/up.sql b/migrations/cockroachdb/2023-10-21-221242_add_cipher_key/up.sql new file mode 100644 index 00000000..1b060b60 --- /dev/null +++ b/migrations/cockroachdb/2023-10-21-221242_add_cipher_key/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE ciphers +ADD COLUMN "key" TEXT; diff --git a/migrations/cockroachdb/2024-01-12-210182_change_attachment_size/down.sql b/migrations/cockroachdb/2024-01-12-210182_change_attachment_size/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2024-01-12-210182_change_attachment_size/up.sql b/migrations/cockroachdb/2024-01-12-210182_change_attachment_size/up.sql new file mode 100644 index 00000000..fcd7189c --- /dev/null +++ b/migrations/cockroachdb/2024-01-12-210182_change_attachment_size/up.sql @@ -0,0 +1,3 @@ +ALTER TABLE attachments +ALTER COLUMN file_size TYPE BIGINT, +ALTER COLUMN file_size SET NOT NULL; diff --git a/migrations/cockroachdb/2024-02-14-135953_change_time_stamp_data_type/down.sql b/migrations/cockroachdb/2024-02-14-135953_change_time_stamp_data_type/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2024-02-14-135953_change_time_stamp_data_type/up.sql b/migrations/cockroachdb/2024-02-14-135953_change_time_stamp_data_type/up.sql new file mode 100644 index 00000000..efc6dc6e --- /dev/null +++ b/migrations/cockroachdb/2024-02-14-135953_change_time_stamp_data_type/up.sql @@ -0,0 +1,3 @@ +ALTER TABLE twofactor +ALTER COLUMN last_used TYPE BIGINT, +ALTER COLUMN last_used SET NOT NULL; diff --git a/migrations/cockroachdb/2024-02-14-170000_add_state_to_sso_nonce/down.sql b/migrations/cockroachdb/2024-02-14-170000_add_state_to_sso_nonce/down.sql new file mode 100644 index 00000000..7cf4d9d6 --- /dev/null +++ b/migrations/cockroachdb/2024-02-14-170000_add_state_to_sso_nonce/down.sql @@ -0,0 +1,6 @@ +DROP TABLE sso_nonce; + +CREATE TABLE sso_nonce ( + nonce CHAR(36) NOT NULL PRIMARY KEY, + created_at TIMESTAMP NOT NULL DEFAULT now() +); diff --git a/migrations/cockroachdb/2024-02-14-170000_add_state_to_sso_nonce/up.sql b/migrations/cockroachdb/2024-02-14-170000_add_state_to_sso_nonce/up.sql new file mode 100644 index 00000000..f7402460 --- /dev/null +++ b/migrations/cockroachdb/2024-02-14-170000_add_state_to_sso_nonce/up.sql @@ -0,0 +1,8 @@ +DROP TABLE sso_nonce; + +CREATE TABLE sso_nonce ( + state TEXT NOT NULL PRIMARY KEY, + nonce TEXT NOT NULL, + redirect_uri TEXT NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT now() +); diff --git a/migrations/cockroachdb/2024-02-26-170000_add_pkce_to_sso_nonce/down.sql b/migrations/cockroachdb/2024-02-26-170000_add_pkce_to_sso_nonce/down.sql new file mode 100644 index 00000000..ef209a45 --- /dev/null +++ b/migrations/cockroachdb/2024-02-26-170000_add_pkce_to_sso_nonce/down.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS sso_nonce; + +CREATE TABLE sso_nonce ( + state TEXT NOT NULL PRIMARY KEY, + nonce TEXT NOT NULL, + redirect_uri TEXT NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT now() +); diff --git a/migrations/cockroachdb/2024-02-26-170000_add_pkce_to_sso_nonce/up.sql b/migrations/cockroachdb/2024-02-26-170000_add_pkce_to_sso_nonce/up.sql new file mode 100644 index 00000000..f2dedfc9 --- /dev/null +++ b/migrations/cockroachdb/2024-02-26-170000_add_pkce_to_sso_nonce/up.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS sso_nonce; + +CREATE TABLE sso_nonce ( + state TEXT NOT NULL PRIMARY KEY, + nonce TEXT NOT NULL, + verifier TEXT, + redirect_uri TEXT NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT now() +); diff --git a/migrations/cockroachdb/2024-03-06-170000_add_sso_users/down.sql b/migrations/cockroachdb/2024-03-06-170000_add_sso_users/down.sql new file mode 100644 index 00000000..f2f92f68 --- /dev/null +++ b/migrations/cockroachdb/2024-03-06-170000_add_sso_users/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS sso_users; diff --git a/migrations/cockroachdb/2024-03-06-170000_add_sso_users/up.sql b/migrations/cockroachdb/2024-03-06-170000_add_sso_users/up.sql new file mode 100644 index 00000000..b74b5728 --- /dev/null +++ b/migrations/cockroachdb/2024-03-06-170000_add_sso_users/up.sql @@ -0,0 +1,7 @@ +CREATE TABLE sso_users ( + user_uuid CHAR(36) NOT NULL PRIMARY KEY, + identifier TEXT NOT NULL UNIQUE, + created_at TIMESTAMP NOT NULL DEFAULT now(), + + FOREIGN KEY(user_uuid) REFERENCES users(uuid) +); diff --git a/migrations/cockroachdb/2024-03-13-170000_sso_users_cascade/down.sql b/migrations/cockroachdb/2024-03-13-170000_sso_users_cascade/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2024-03-13-170000_sso_users_cascade/up.sql b/migrations/cockroachdb/2024-03-13-170000_sso_users_cascade/up.sql new file mode 100644 index 00000000..38f97b4d --- /dev/null +++ b/migrations/cockroachdb/2024-03-13-170000_sso_users_cascade/up.sql @@ -0,0 +1,3 @@ +ALTER TABLE sso_users + DROP CONSTRAINT "sso_users_user_uuid_fkey", + ADD CONSTRAINT "sso_users_user_uuid_fkey" FOREIGN KEY(user_uuid) REFERENCES users(uuid) ON UPDATE CASCADE ON DELETE CASCADE; diff --git a/migrations/cockroachdb/2024-06-05-131359_add_2fa_duo_store/down.sql b/migrations/cockroachdb/2024-06-05-131359_add_2fa_duo_store/down.sql new file mode 100644 index 00000000..0b5d4cd8 --- /dev/null +++ b/migrations/cockroachdb/2024-06-05-131359_add_2fa_duo_store/down.sql @@ -0,0 +1 @@ +DROP TABLE twofactor_duo_ctx; diff --git a/migrations/cockroachdb/2024-06-05-131359_add_2fa_duo_store/up.sql b/migrations/cockroachdb/2024-06-05-131359_add_2fa_duo_store/up.sql new file mode 100644 index 00000000..ebc8be1b --- /dev/null +++ b/migrations/cockroachdb/2024-06-05-131359_add_2fa_duo_store/up.sql @@ -0,0 +1,8 @@ +CREATE TABLE twofactor_duo_ctx ( + state VARCHAR(64) NOT NULL, + user_email VARCHAR(255) NOT NULL, + nonce VARCHAR(64) NOT NULL, + exp BIGINT NOT NULL, + + PRIMARY KEY (state) +); \ No newline at end of file diff --git a/migrations/cockroachdb/2024-09-04-091351_use_device_type_for_mails/down.sql b/migrations/cockroachdb/2024-09-04-091351_use_device_type_for_mails/down.sql new file mode 100644 index 00000000..72fc20e8 --- /dev/null +++ b/migrations/cockroachdb/2024-09-04-091351_use_device_type_for_mails/down.sql @@ -0,0 +1 @@ +ALTER TABLE twofactor_incomplete DROP COLUMN device_type; diff --git a/migrations/cockroachdb/2024-09-04-091351_use_device_type_for_mails/up.sql b/migrations/cockroachdb/2024-09-04-091351_use_device_type_for_mails/up.sql new file mode 100644 index 00000000..a07c3aba --- /dev/null +++ b/migrations/cockroachdb/2024-09-04-091351_use_device_type_for_mails/up.sql @@ -0,0 +1 @@ +ALTER TABLE twofactor_incomplete ADD COLUMN device_type INT4 NOT NULL DEFAULT 14; -- 14 = Unknown Browser diff --git a/migrations/cockroachdb/2025-01-09-172300_add_manage/down.sql b/migrations/cockroachdb/2025-01-09-172300_add_manage/down.sql new file mode 100644 index 00000000..e69de29b diff --git a/migrations/cockroachdb/2025-01-09-172300_add_manage/up.sql b/migrations/cockroachdb/2025-01-09-172300_add_manage/up.sql new file mode 100644 index 00000000..e234cc6e --- /dev/null +++ b/migrations/cockroachdb/2025-01-09-172300_add_manage/up.sql @@ -0,0 +1,5 @@ +ALTER TABLE users_collections +ADD COLUMN manage BOOLEAN NOT NULL DEFAULT FALSE; + +ALTER TABLE collections_groups +ADD COLUMN manage BOOLEAN NOT NULL DEFAULT FALSE; diff --git a/playwright/.env.template b/playwright/.env.template index a6696aab..54a65434 100644 --- a/playwright/.env.template +++ b/playwright/.env.template @@ -62,3 +62,4 @@ SMTP_FROM_NAME=Vaultwarden MARIADB_PORT=3305 MYSQL_PORT=3307 POSTGRES_PORT=5432 +COCKROACH_PORT=26257 diff --git a/playwright/README.md b/playwright/README.md index c8bcceda..a752aa97 100644 --- a/playwright/README.md +++ b/playwright/README.md @@ -7,7 +7,7 @@ It uses its own `test.env` with different ports to not collide with a running de ## Install This relies on `docker` and the `compose` [plugin](https://docs.docker.com/compose/install/). -Databases (`Mariadb`, `Mysql` and `Postgres`) and `Playwright` will run in containers. +Databases (`Mariadb`, `Mysql`, `Postgres` and `Cockroach`) and `Playwright` will run in containers. ### Running Playwright outside docker @@ -29,6 +29,7 @@ DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env run Pl ``` To force a rebuild of the Playwright image: + ```bash DOCKER_BUILDKIT=1 docker compose --env-file test.env build Playwright ``` @@ -49,6 +50,7 @@ You can use: DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env run Playwright test --project=mariadb DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env run Playwright test --project=mysql DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env run Playwright test --project=postgres +DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env run Playwright test --project=cockroach DOCKER_BUILDKIT=1 docker compose --profile playwright --env-file test.env run Playwright test --project=sqlite ``` @@ -154,6 +156,7 @@ You can run just `Keycloak` with `--profile keycloak`: ```bash > docker compose --profile keycloak --env-file .env up ``` + When running with a local Vaultwarden, you can use a front-end build from [dani-garcia/bw_web_builds](https://github.com/dani-garcia/bw_web_builds/releases). ## Rebuilding the Vaultwarden diff --git a/playwright/docker-compose.yml b/playwright/docker-compose.yml index 3e56477c..27eee3bd 100644 --- a/playwright/docker-compose.yml +++ b/playwright/docker-compose.yml @@ -85,10 +85,22 @@ services: healthcheck: test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] start_period: 20s - interval: 30s ports: - ${POSTGRES_PORT}:5432 + Cockroach: + profiles: ["playwright"] + container_name: playwright_cockroach + image: cockroachdb/cockroach:v23.2.28 + env_file: test.env + healthcheck: + test: ["CMD-SHELL", "cockroach sql --insecure --host=localhost:26257 -d $${COCKROACH_DB} -e 'select 1' >/dev/null 2>&1"] + start_period: 20s + interval: 30s + command: "start-single-node" + ports: + - ${COCKROACH_PORT}:26257 + Maildev: profiles: ["vaultwarden", "maildev"] container_name: maildev diff --git a/playwright/global-utils.ts b/playwright/global-utils.ts index e9d8008f..2ff9ea07 100644 --- a/playwright/global-utils.ts +++ b/playwright/global-utils.ts @@ -152,11 +152,37 @@ async function wipePostgres(){ } } +async function wipeCockroach(){ + const { Client } = require('pg'); + + const client = new Client({ + user: process.env.COCKROACH_USER, + host: "127.0.0.1", + database: "cockroach", + password: process.env.COCKROACH_PASSWORD, + port: process.env.COCKROACH_PORT, + }); + + try { + await client.connect(); + await client.query(`DROP DATABASE ${process.env.COCKROACH_DB}`); + await client.query(`CREATE DATABASE ${process.env.COCKROACH_DB}`); + console.log('Successfully wiped cockroach'); + } catch (err) { + console.log(`Error when wiping cockroach: ${err}`); + } finally { + client.end(); + } +} + function dbConfig(testInfo: TestInfo){ switch(testInfo.project.name) { case "postgres": + case "cockroach": case "sso-postgres": return { DATABASE_URL: `postgresql://${process.env.POSTGRES_USER}:${process.env.POSTGRES_PASSWORD}@127.0.0.1:${process.env.POSTGRES_PORT}/${process.env.POSTGRES_DB}` }; + case "sso-cockroach": + return { DATABASE_URL: `cockroachdb://${process.env.COCKROACH_USER}:${process.env.COCKROACH_PASSWORD}@127.0.0.1:${process.env.COCKROACH_PORT}/${process.env.COCKROACH_DB}` }; case "mariadb": case "sso-mariadb": return { DATABASE_URL: `mysql://${process.env.MARIADB_USER}:${process.env.MARIADB_PASSWORD}@127.0.0.1:${process.env.MARIADB_PORT}/${process.env.MARIADB_DATABASE}` }; @@ -181,6 +207,9 @@ export async function startVault(browser: Browser, testInfo: TestInfo, env = {}, case "sso-postgres": await wipePostgres(); break; + case "sso-cockroach": + await wipeCockroach(); + break; case "mariadb": case "sso-mariadb": await wipeMariaDB(); diff --git a/playwright/playwright.config.ts b/playwright/playwright.config.ts index de721aa3..8ddfd728 100644 --- a/playwright/playwright.config.ts +++ b/playwright/playwright.config.ts @@ -67,6 +67,12 @@ export default defineConfig({ use: { serviceName: "Postgres" }, teardown: 'postgres-teardown', }, + { + name: 'cockroach-setup', + testMatch: 'tests/setups/db-setup.ts', + use: { serviceName: "Cockroach" }, + teardown: 'cockroach-teardown', + }, { name: 'sso-setup', testMatch: 'tests/setups/sso-setup.ts', @@ -91,6 +97,12 @@ export default defineConfig({ testIgnore: 'tests/sso_*.spec.ts', dependencies: ['postgres-setup'], }, + { + name: 'cockroach', + testMatch: 'tests/*.spec.ts', + testIgnore: 'tests/sso_*.spec.ts', + dependencies: ['cockroach-setup'], + }, { name: 'sqlite', testMatch: 'tests/*.spec.ts', @@ -112,6 +124,11 @@ export default defineConfig({ testMatch: 'tests/sso_*.spec.ts', dependencies: ['sso-setup', 'postgres-setup'], }, + { + name: 'sso-cockroach', + testMatch: 'tests/sso_*.spec.ts', + dependencies: ['sso-setup', 'cockroach-setup'], + }, { name: 'sso-sqlite', testMatch: 'tests/sso_*.spec.ts', @@ -133,6 +150,11 @@ export default defineConfig({ testMatch: 'tests/setups/db-teardown.ts', use: { serviceName: "Postgres" }, }, + { + name: 'cockroach-teardown', + testMatch: 'tests/setups/db-teardown.ts', + use: { serviceName: "Cockroach" }, + }, { name: 'sso-teardown', testMatch: 'tests/setups/sso-teardown.ts', diff --git a/playwright/test.env b/playwright/test.env index d97c08d1..bc8a84ec 100644 --- a/playwright/test.env +++ b/playwright/test.env @@ -95,3 +95,11 @@ POSTGRES_PORT=5433 POSTGRES_USER=warden POSTGRES_PASSWORD=warden POSTGRES_DB=warden + +############################# +# Docker Cockroach container# +############################# +COCKROACH_PORT=26257 +COCKROACH_USER=warden +COCKROACH_PASSWORD=warden +COCKROACH_DB=warden diff --git a/src/api/admin.rs b/src/api/admin.rs index d52e24ef..c29fe412 100644 --- a/src/api/admin.rs +++ b/src/api/admin.rs @@ -81,6 +81,7 @@ static DB_TYPE: Lazy<&str> = Lazy::new(|| { DbConnType::sqlite => "SQLite", DbConnType::mysql => "MySQL", DbConnType::postgresql => "PostgreSQL", + DbConnType::cockroachdb => "CockroachDB", }) .unwrap_or("Unknown") }); diff --git a/src/api/core/two_factor/duo_oidc.rs b/src/api/core/two_factor/duo_oidc.rs index ad948a75..a48dd5b5 100644 --- a/src/api/core/two_factor/duo_oidc.rs +++ b/src/api/core/two_factor/duo_oidc.rs @@ -38,7 +38,7 @@ const JWT_SIGNATURE_ALG: Algorithm = Algorithm::HS512; // Size of random strings for state and nonce. Must be at least 16 characters and at most 1024 characters. // If increasing this above 64, also increase the size of the twofactor_duo_ctx.state and -// twofactor_duo_ctx.nonce database columns for postgres and mariadb. +// twofactor_duo_ctx.nonce database columns for postgres, cockroachdb and mariadb. const STATE_LENGTH: usize = 64; // client_assertion payload for health checks and obtaining MFA results. diff --git a/src/db/mod.rs b/src/db/mod.rs index 9f5bb150..2f39fc2c 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,9 +1,6 @@ use std::{sync::Arc, time::Duration}; -use diesel::{ - connection::SimpleConnection, - r2d2::{ConnectionManager, CustomizeConnection, Pool, PooledConnection}, -}; +use diesel::r2d2::{ConnectionManager, CustomizeConnection, Pool, PooledConnection}; use rocket::{ http::Status, @@ -33,6 +30,10 @@ pub mod __mysql_schema; #[path = "schemas/postgresql/schema.rs"] pub mod __postgresql_schema; +#[cfg(cockroachdb)] +#[path = "schemas/cockroachdb/schema.rs"] +pub mod __cockroachdb_schema; + // These changes are based on Rocket 0.5-rc wrapper of Diesel: https://github.com/SergioBenitez/Rocket/blob/v0.5-rc/contrib/sync_db_pools // A wrapper around spawn_blocking that propagates panics to the calling code. @@ -70,16 +71,18 @@ macro_rules! generate_connections { pub init_stmts: String, } - $( // Based on . - #[cfg($name)] - impl CustomizeConnection<$ty, diesel::r2d2::Error> for DbConnOptions { - fn on_acquire(&self, conn: &mut $ty) -> Result<(), diesel::r2d2::Error> { + // generic because the cockroachdb and postgresql implementations clash when both turned on + impl CustomizeConnection for DbConnOptions + where + T: diesel::connection::SimpleConnection + { + fn on_acquire(&self, conn: &mut T) -> Result<(), diesel::r2d2::Error> { if !self.init_stmts.is_empty() { conn.batch_execute(&self.init_stmts).map_err(diesel::r2d2::Error::QueryError)?; } Ok(()) } - })+ + } #[derive(Clone)] pub struct DbPool { @@ -183,14 +186,16 @@ macro_rules! generate_connections { generate_connections! { sqlite: diesel::sqlite::SqliteConnection, mysql: diesel::mysql::MysqlConnection, - postgresql: diesel::pg::PgConnection + postgresql: diesel::pg::PgConnection, + cockroachdb: diesel::pg::PgConnection } #[cfg(query_logger)] generate_connections! { sqlite: diesel_logger::LoggingConnection, mysql: diesel_logger::LoggingConnection, - postgresql: diesel_logger::LoggingConnection + postgresql: diesel_logger::LoggingConnection, + cockroachdb: diesel_logger::LoggingConnection } impl DbConnType { @@ -211,6 +216,14 @@ impl DbConnType { #[cfg(not(postgresql))] err!("`DATABASE_URL` is a PostgreSQL URL, but the 'postgresql' feature is not enabled") + // Cockroach + } else if url.starts_with("cockroachdb:") || url.starts_with("cockroach:") { + #[cfg(cockroachdb)] + return Ok(DbConnType::cockroachdb); + + #[cfg(not(cockroachdb))] + err!("`DATABASE_URL` is a CockroachDB URL, but the 'cockroachdb' feature is not enabled") + //Sqlite } else { #[cfg(sqlite)] @@ -235,6 +248,7 @@ impl DbConnType { Self::sqlite => "PRAGMA busy_timeout = 5000; PRAGMA synchronous = NORMAL;".to_string(), Self::mysql => String::new(), Self::postgresql => String::new(), + Self::cockroachdb => String::new(), } } } @@ -243,11 +257,11 @@ impl DbConnType { macro_rules! db_run { // Same for all dbs ( $conn:ident: $body:block ) => { - db_run! { $conn: sqlite, mysql, postgresql $body } + db_run! { $conn: sqlite, mysql, postgresql, cockroachdb $body } }; ( @raw $conn:ident: $body:block ) => { - db_run! { @raw $conn: sqlite, mysql, postgresql $body } + db_run! { @raw $conn: sqlite, mysql, postgresql, cockroachdb $body } }; // Different code for each db @@ -316,7 +330,7 @@ impl FromDb for Option { } } -// For each struct eg. Cipher, we create a CipherDb inside a module named __$db_model (where $db is sqlite, mysql or postgresql), +// For each struct eg. Cipher, we create a CipherDb inside a module named __$db_model (where $db is sqlite, mysql, postgresql or cockroachdb), // to implement the Diesel traits. We also provide methods to convert between them and the basic structs. Later, that module will be auto imported when using db_run! #[macro_export] macro_rules! db_object { @@ -331,11 +345,13 @@ macro_rules! db_object { $( pub struct $name { $( /*$( #[$field_attr] )**/ $vis $field : $typ, )+ } )+ #[cfg(sqlite)] - pub mod __sqlite_model { $( db_object! { @db sqlite | $( #[$attr] )* | $name | $( $( #[$field_attr] )* $field : $typ ),+ } )+ } + pub mod __sqlite_model { $( db_object! { @db sqlite | $( #[$attr] )* | $name | $( $( #[$field_attr] )* $field : $typ ),+ } )+ } #[cfg(mysql)] - pub mod __mysql_model { $( db_object! { @db mysql | $( #[$attr] )* | $name | $( $( #[$field_attr] )* $field : $typ ),+ } )+ } + pub mod __mysql_model { $( db_object! { @db mysql | $( #[$attr] )* | $name | $( $( #[$field_attr] )* $field : $typ ),+ } )+ } #[cfg(postgresql)] - pub mod __postgresql_model { $( db_object! { @db postgresql | $( #[$attr] )* | $name | $( $( #[$field_attr] )* $field : $typ ),+ } )+ } + pub mod __postgresql_model { $( db_object! { @db postgresql | $( #[$attr] )* | $name | $( $( #[$field_attr] )* $field : $typ ),+ } )+ } + #[cfg(cockroachdb)] + pub mod __cockroachdb_model { $( db_object! { @db cockroachdb | $( #[$attr] )* | $name | $( $( #[$field_attr] )* $field : $typ ),+ } )+ } }; ( @db $db:ident | $( #[$attr:meta] )* | $name:ident | $( $( #[$field_attr:meta] )* $vis:vis $field:ident : $typ:ty),+) => { @@ -370,9 +386,9 @@ pub mod models; /// MySQL/MariaDB and PostgreSQL are not supported. pub async fn backup_database(conn: &mut DbConn) -> Result { db_run! {@raw conn: - postgresql, mysql { + postgresql, mysql, cockroachdb { let _ = conn; - err!("PostgreSQL and MySQL/MariaDB do not support this backup feature"); + err!("PostgreSQL, MySQL/MariaDB and CockroachDB do not support this backup feature"); } sqlite { let db_url = CONFIG.database_url(); @@ -390,7 +406,7 @@ pub async fn backup_database(conn: &mut DbConn) -> Result { /// Get the SQL Server version pub async fn get_sql_server_version(conn: &mut DbConn) -> String { db_run! {@raw conn: - postgresql, mysql { + postgresql, cockroachdb, mysql { define_sql_function!{ fn version() -> diesel::sql_types::Text; } @@ -490,3 +506,17 @@ mod postgresql_migrations { Ok(()) } } + +#[cfg(cockroachdb)] +mod cockroachdb_migrations { + use diesel_migrations::{EmbeddedMigrations, MigrationHarness}; + pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations/cockroachdb"); + + pub fn run_migrations() -> Result<(), super::Error> { + use diesel::Connection; + // Make sure the database is up to date (create if it doesn't exist, or run the migrations) + let mut connection = diesel::pg::PgConnection::establish(&crate::CONFIG.database_url())?; + connection.run_pending_migrations(MIGRATIONS).expect("Error running migrations"); + Ok(()) + } +} diff --git a/src/db/models/attachment.rs b/src/db/models/attachment.rs index aafb8766..3ae021a0 100644 --- a/src/db/models/attachment.rs +++ b/src/db/models/attachment.rs @@ -95,7 +95,7 @@ impl Attachment { Err(e) => Err(e.into()), }.map_res("Error saving attachment") } - postgresql { + postgresql, cockroachdb { let value = AttachmentDb::to_db(self); diesel::insert_into(attachments::table) .values(&value) diff --git a/src/db/models/auth_request.rs b/src/db/models/auth_request.rs index 31e7e66e..f03fc860 100644 --- a/src/db/models/auth_request.rs +++ b/src/db/models/auth_request.rs @@ -99,7 +99,7 @@ impl AuthRequest { Err(e) => Err(e.into()), }.map_res("Error auth_request") } - postgresql { + postgresql, cockroachdb { let value = AuthRequestDb::to_db(self); diesel::insert_into(auth_requests::table) .values(&value) diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs index 8cbad4b7..01177e9d 100644 --- a/src/db/models/cipher.rs +++ b/src/db/models/cipher.rs @@ -452,7 +452,7 @@ impl Cipher { Err(e) => Err(e.into()), }.map_res("Error saving cipher") } - postgresql { + postgresql, cockroachdb { let value = CipherDb::to_db(self); diesel::insert_into(ciphers::table) .values(&value) diff --git a/src/db/models/collection.rs b/src/db/models/collection.rs index c14c5946..b0ee0d3b 100644 --- a/src/db/models/collection.rs +++ b/src/db/models/collection.rs @@ -173,7 +173,7 @@ impl Collection { Err(e) => Err(e.into()), }.map_res("Error saving collection") } - postgresql { + postgresql, cockroachdb { let value = CollectionDb::to_db(self); diesel::insert_into(collections::table) .values(&value) @@ -642,7 +642,7 @@ impl CollectionUser { Err(e) => Err(e.into()), }.map_res("Error adding user to collection") } - postgresql { + postgresql, cockroachdb { diesel::insert_into(users_collections::table) .values(( users_collections::user_uuid.eq(user_uuid), @@ -793,7 +793,7 @@ impl CollectionCipher { .execute(conn) .map_res("Error adding cipher to collection") } - postgresql { + postgresql, cockroachdb { diesel::insert_into(ciphers_collections::table) .values(( ciphers_collections::cipher_uuid.eq(cipher_uuid), diff --git a/src/db/models/device.rs b/src/db/models/device.rs index 005d942d..3cfdd79b 100644 --- a/src/db/models/device.rs +++ b/src/db/models/device.rs @@ -150,7 +150,7 @@ impl Device { 10, ).map_res("Error saving device") } - postgresql { + postgresql, cockroachdb { let value = DeviceDb::to_db(self); crate::util::retry( || diesel::insert_into(devices::table).values(&value).on_conflict((devices::uuid, devices::user_uuid)).do_update().set(&value).execute(conn), diff --git a/src/db/models/emergency_access.rs b/src/db/models/emergency_access.rs index e3803b1a..95906255 100644 --- a/src/db/models/emergency_access.rs +++ b/src/db/models/emergency_access.rs @@ -162,7 +162,7 @@ impl EmergencyAccess { Err(e) => Err(e.into()), }.map_res("Error saving emergency access") } - postgresql { + postgresql, cockroachdb { let value = EmergencyAccessDb::to_db(self); diesel::insert_into(emergency_access::table) .values(&value) diff --git a/src/db/models/event.rs b/src/db/models/event.rs index 7e6bdf34..8374ce1e 100644 --- a/src/db/models/event.rs +++ b/src/db/models/event.rs @@ -201,7 +201,7 @@ impl Event { .execute(conn) .map_res("Error saving event") } - postgresql { + postgresql, cockroachdb { diesel::insert_into(event::table) .values(EventDb::to_db(self)) .on_conflict(event::uuid) @@ -216,7 +216,7 @@ impl Event { pub async fn save_user_event(events: Vec, conn: &mut DbConn) -> EmptyResult { // Special save function which is able to handle multiple events. // SQLite doesn't support the DEFAULT argument, and does not support inserting multiple values at the same time. - // MySQL and PostgreSQL do. + // MySQL, PostgreSQL and CockroachDB do. // We also ignore duplicate if they ever will exists, else it could break the whole flow. db_run! { conn: // Unfortunately SQLite does not support inserting multiple records at the same time @@ -238,7 +238,7 @@ impl Event { .unwrap_or_default(); Ok(()) } - postgresql { + postgresql, cockroachdb { let events: Vec = events.iter().map(EventDb::to_db).collect(); diesel::insert_into(event::table) .values(&events) diff --git a/src/db/models/folder.rs b/src/db/models/folder.rs index 654ccd6d..ceb1711e 100644 --- a/src/db/models/folder.rs +++ b/src/db/models/folder.rs @@ -91,7 +91,7 @@ impl Folder { Err(e) => Err(e.into()), }.map_res("Error saving folder") } - postgresql { + postgresql, cockroachdb { let value = FolderDb::to_db(self); diesel::insert_into(folders::table) .values(&value) @@ -156,7 +156,7 @@ impl FolderCipher { .execute(conn) .map_res("Error adding cipher to folder") } - postgresql { + postgresql, cockroachdb { diesel::insert_into(folders_ciphers::table) .values(FolderCipherDb::to_db(self)) .on_conflict((folders_ciphers::cipher_uuid, folders_ciphers::folder_uuid)) diff --git a/src/db/models/group.rs b/src/db/models/group.rs index 310576c4..deb18d14 100644 --- a/src/db/models/group.rs +++ b/src/db/models/group.rs @@ -177,7 +177,7 @@ impl Group { Err(e) => Err(e.into()), }.map_res("Error saving group") } - postgresql { + postgresql, cockroachdb { let value = GroupDb::to_db(self); diesel::insert_into(groups::table) .values(&value) @@ -347,7 +347,7 @@ impl CollectionGroup { Err(e) => Err(e.into()), }.map_res("Error adding group to collection") } - postgresql { + postgresql, cockroachdb { diesel::insert_into(collections_groups::table) .values(( collections_groups::collections_uuid.eq(&self.collections_uuid), @@ -483,7 +483,7 @@ impl GroupUser { Err(e) => Err(e.into()), }.map_res("Error adding user to group") } - postgresql { + postgresql, cockroachdb { diesel::insert_into(groups_users::table) .values(( groups_users::users_organizations_uuid.eq(&self.users_organizations_uuid), diff --git a/src/db/models/org_policy.rs b/src/db/models/org_policy.rs index aac145cb..6d77533f 100644 --- a/src/db/models/org_policy.rs +++ b/src/db/models/org_policy.rs @@ -125,7 +125,7 @@ impl OrgPolicy { Err(e) => Err(e.into()), }.map_res("Error saving org_policy") } - postgresql { + postgresql, cockroachdb { let value = OrgPolicyDb::to_db(self); // We need to make sure we're not going to violate the unique constraint on org_uuid and atype. // This happens automatically on other DBMS backends due to replace_into(). PostgreSQL does diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs index 77cf91c0..792baded 100644 --- a/src/db/models/organization.rs +++ b/src/db/models/organization.rs @@ -353,7 +353,7 @@ impl Organization { }.map_res("Error saving organization") } - postgresql { + postgresql, cockroachdb { let value = OrganizationDb::to_db(self); diesel::insert_into(organizations::table) .values(&value) @@ -763,7 +763,7 @@ impl Membership { Err(e) => Err(e.into()), }.map_res("Error adding user to organization") } - postgresql { + postgresql, cockroachdb { let value = MembershipDb::to_db(self); diesel::insert_into(users_organizations::table) .values(&value) @@ -1195,7 +1195,7 @@ impl OrganizationApiKey { }.map_res("Error saving organization") } - postgresql { + postgresql, cockroachdb { let value = OrganizationApiKeyDb::to_db(self); diesel::insert_into(organization_api_key::table) .values(&value) diff --git a/src/db/models/send.rs b/src/db/models/send.rs index bf82c181..e8d3e426 100644 --- a/src/db/models/send.rs +++ b/src/db/models/send.rs @@ -209,7 +209,7 @@ impl Send { Err(e) => Err(e.into()), }.map_res("Error saving send") } - postgresql { + postgresql, cockroachdb { let value = SendDb::to_db(self); diesel::insert_into(sends::table) .values(&value) diff --git a/src/db/models/sso_nonce.rs b/src/db/models/sso_nonce.rs index 2246a437..35eac150 100644 --- a/src/db/models/sso_nonce.rs +++ b/src/db/models/sso_nonce.rs @@ -43,7 +43,7 @@ impl SsoNonce { .execute(conn) .map_res("Error saving SSO nonce") } - postgresql { + postgresql, cockroachdb { let value = SsoNonceDb::to_db(self); diesel::insert_into(sso_nonce::table) .values(&value) diff --git a/src/db/models/two_factor.rs b/src/db/models/two_factor.rs index 46b097bb..f0f9fc04 100644 --- a/src/db/models/two_factor.rs +++ b/src/db/models/two_factor.rs @@ -95,7 +95,7 @@ impl TwoFactor { Err(e) => Err(e.into()), }.map_res("Error saving twofactor") } - postgresql { + postgresql, cockroachdb { let value = TwoFactorDb::to_db(self); // We need to make sure we're not going to violate the unique constraint on user_uuid and atype. // This happens automatically on other DBMS backends due to replace_into(). PostgreSQL does diff --git a/src/db/models/user.rs b/src/db/models/user.rs index 3a3b5157..c3a2cabb 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -300,7 +300,7 @@ impl User { Err(e) => Err(e.into()), }.map_res("Error saving user") } - postgresql { + postgresql, cockroachdb { let value = UserDb::to_db(self); diesel::insert_into(users::table) // Insert or update .values(&value) @@ -449,7 +449,7 @@ impl Invitation { .execute(conn) .map_res("Error saving invitation") } - postgresql { + postgresql, cockroachdb { diesel::insert_into(invitations::table) .values(InvitationDb::to_db(self)) .on_conflict(invitations::email) @@ -516,7 +516,7 @@ impl SsoUser { .execute(conn) .map_res("Error saving SSO user") } - postgresql { + postgresql, cockroachdb { let value = SsoUserDb::to_db(self); diesel::insert_into(sso_users::table) .values(&value) diff --git a/src/db/schemas/cockroachdb/schema.rs b/src/db/schemas/cockroachdb/schema.rs new file mode 100644 index 00000000..a0f31f1e --- /dev/null +++ b/src/db/schemas/cockroachdb/schema.rs @@ -0,0 +1,395 @@ +table! { + attachments (id) { + id -> Text, + cipher_uuid -> Text, + file_name -> Text, + file_size -> BigInt, + akey -> Nullable, + } +} + +table! { + ciphers (uuid) { + uuid -> Text, + created_at -> Timestamp, + updated_at -> Timestamp, + user_uuid -> Nullable, + organization_uuid -> Nullable, + key -> Nullable, + atype -> Integer, + name -> Text, + notes -> Nullable, + fields -> Nullable, + data -> Text, + password_history -> Nullable, + deleted_at -> Nullable, + reprompt -> Nullable, + } +} + +table! { + ciphers_collections (cipher_uuid, collection_uuid) { + cipher_uuid -> Text, + collection_uuid -> Text, + } +} + +table! { + collections (uuid) { + uuid -> Text, + org_uuid -> Text, + name -> Text, + external_id -> Nullable, + } +} + +table! { + devices (uuid, user_uuid) { + uuid -> Text, + created_at -> Timestamp, + updated_at -> Timestamp, + user_uuid -> Text, + name -> Text, + atype -> Integer, + push_uuid -> Nullable, + push_token -> Nullable, + refresh_token -> Text, + twofactor_remember -> Nullable, + } +} + +table! { + event (uuid) { + uuid -> Text, + event_type -> Integer, + user_uuid -> Nullable, + org_uuid -> Nullable, + cipher_uuid -> Nullable, + collection_uuid -> Nullable, + group_uuid -> Nullable, + org_user_uuid -> Nullable, + act_user_uuid -> Nullable, + device_type -> Nullable, + ip_address -> Nullable, + event_date -> Timestamp, + policy_uuid -> Nullable, + provider_uuid -> Nullable, + provider_user_uuid -> Nullable, + provider_org_uuid -> Nullable, + } +} + +table! { + favorites (user_uuid, cipher_uuid) { + user_uuid -> Text, + cipher_uuid -> Text, + } +} + +table! { + folders (uuid) { + uuid -> Text, + created_at -> Timestamp, + updated_at -> Timestamp, + user_uuid -> Text, + name -> Text, + } +} + +table! { + folders_ciphers (cipher_uuid, folder_uuid) { + cipher_uuid -> Text, + folder_uuid -> Text, + } +} + +table! { + invitations (email) { + email -> Text, + } +} + +table! { + org_policies (uuid) { + uuid -> Text, + org_uuid -> Text, + atype -> Integer, + enabled -> Bool, + data -> Text, + } +} + +table! { + organizations (uuid) { + uuid -> Text, + name -> Text, + billing_email -> Text, + private_key -> Nullable, + public_key -> Nullable, + } +} + +table! { + sends (uuid) { + uuid -> Text, + user_uuid -> Nullable, + organization_uuid -> Nullable, + name -> Text, + notes -> Nullable, + atype -> Integer, + data -> Text, + akey -> 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, + hide_email -> Nullable, + } +} + +table! { + twofactor (uuid) { + uuid -> Text, + user_uuid -> Text, + atype -> Integer, + enabled -> Bool, + data -> Text, + last_used -> BigInt, + } +} + +table! { + twofactor_incomplete (user_uuid, device_uuid) { + user_uuid -> Text, + device_uuid -> Text, + device_name -> Text, + device_type -> Integer, + login_time -> Timestamp, + ip_address -> Text, + } +} + +table! { + twofactor_duo_ctx (state) { + state -> Text, + user_email -> Text, + nonce -> Text, + exp -> BigInt, + } +} + +table! { + users (uuid) { + uuid -> Text, + enabled -> Bool, + created_at -> Timestamp, + updated_at -> Timestamp, + verified_at -> Nullable, + last_verifying_at -> Nullable, + login_verify_count -> Integer, + email -> Text, + email_new -> Nullable, + email_new_token -> Nullable, + name -> Text, + password_hash -> Binary, + salt -> Binary, + password_iterations -> Integer, + password_hint -> Nullable, + akey -> Text, + private_key -> Nullable, + public_key -> Nullable, + totp_secret -> Nullable, + totp_recover -> Nullable, + security_stamp -> Text, + stamp_exception -> Nullable, + equivalent_domains -> Text, + excluded_globals -> Text, + client_kdf_type -> Integer, + client_kdf_iter -> Integer, + client_kdf_memory -> Nullable, + client_kdf_parallelism -> Nullable, + api_key -> Nullable, + avatar_color -> Nullable, + external_id -> Nullable, + } +} + +table! { + users_collections (user_uuid, collection_uuid) { + user_uuid -> Text, + collection_uuid -> Text, + read_only -> Bool, + hide_passwords -> Bool, + manage -> Bool, + } +} + +table! { + users_organizations (uuid) { + uuid -> Text, + user_uuid -> Text, + org_uuid -> Text, + invited_by_email -> Nullable, + access_all -> Bool, + akey -> Text, + status -> Integer, + atype -> Integer, + reset_password_key -> Nullable, + external_id -> Nullable, + } +} + +table! { + organization_api_key (uuid, org_uuid) { + uuid -> Text, + org_uuid -> Text, + atype -> Integer, + api_key -> Text, + revision_date -> Timestamp, + } +} + +table! { + sso_nonce (state) { + state -> Text, + nonce -> Text, + verifier -> Nullable, + redirect_uri -> Text, + created_at -> Timestamp, + } +} + +table! { + sso_users (user_uuid) { + user_uuid -> Text, + identifier -> Text, + } +} + +table! { + emergency_access (uuid) { + uuid -> Text, + grantor_uuid -> Text, + grantee_uuid -> Nullable, + email -> Nullable, + key_encrypted -> Nullable, + atype -> Integer, + status -> Integer, + wait_time_days -> Integer, + recovery_initiated_at -> Nullable, + last_notification_at -> Nullable, + updated_at -> Timestamp, + created_at -> Timestamp, + } +} + +table! { + groups (uuid) { + uuid -> Text, + organizations_uuid -> Text, + name -> Text, + access_all -> Bool, + external_id -> Nullable, + creation_date -> Timestamp, + revision_date -> Timestamp, + } +} + +table! { + groups_users (groups_uuid, users_organizations_uuid) { + groups_uuid -> Text, + users_organizations_uuid -> Text, + } +} + +table! { + collections_groups (collections_uuid, groups_uuid) { + collections_uuid -> Text, + groups_uuid -> Text, + read_only -> Bool, + hide_passwords -> Bool, + manage -> Bool, + } +} + +table! { + auth_requests (uuid) { + uuid -> Text, + user_uuid -> Text, + organization_uuid -> Nullable, + request_device_identifier -> Text, + device_type -> Integer, + request_ip -> Text, + response_device_id -> Nullable, + access_code -> Text, + public_key -> Text, + enc_key -> Nullable, + master_password_hash -> Nullable, + approved -> Nullable, + creation_date -> Timestamp, + response_date -> Nullable, + authentication_date -> Nullable, + } +} + +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!(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)); +joinable!(users_organizations -> organizations (org_uuid)); +joinable!(users_organizations -> users (user_uuid)); +joinable!(users_organizations -> ciphers (org_uuid)); +joinable!(organization_api_key -> organizations (org_uuid)); +joinable!(emergency_access -> users (grantor_uuid)); +joinable!(groups -> organizations (organizations_uuid)); +joinable!(groups_users -> users_organizations (users_organizations_uuid)); +joinable!(groups_users -> groups (groups_uuid)); +joinable!(collections_groups -> collections (collections_uuid)); +joinable!(collections_groups -> groups (groups_uuid)); +joinable!(event -> users_organizations (uuid)); +joinable!(auth_requests -> users (user_uuid)); +joinable!(sso_users -> users (user_uuid)); + +allow_tables_to_appear_in_same_query!( + attachments, + ciphers, + ciphers_collections, + collections, + devices, + folders, + folders_ciphers, + invitations, + org_policies, + organizations, + sends, + sso_users, + twofactor, + users, + users_collections, + users_organizations, + organization_api_key, + emergency_access, + groups, + groups_users, + collections_groups, + event, + auth_requests, +);