From 73756d0d0895fafde27984b5121bb6089847e757 Mon Sep 17 00:00:00 2001 From: Mick Letofsky Date: Mon, 23 Feb 2026 12:01:05 +0100 Subject: [PATCH] Bring our QA Setup data files into the Seeder as presets (#7046) * Importing test fixtures from test repo into the Seeder * Needed to ensure that we assigned permission to collections; not just made them. --- util/Seeder/Seeds/README.md | 37 +++- .../ciphers/collection-permissions.json | 155 +++++++++++++++ .../fixtures/ciphers/enterprise-basic.json | 179 ++++++++++++++++++ .../Seeds/fixtures/ciphers/sso-vault.json | 13 ++ .../Seeds/fixtures/ciphers/tde-vault.json | 60 ++++++ .../qa-collection-permissions.json | 5 + .../fixtures/organizations/qa-enterprise.json | 5 + .../fixtures/organizations/qa-policy-org.json | 5 + .../fixtures/organizations/qa-sso-org.json | 5 + .../fixtures/organizations/qa-tde-org.json | 5 + .../collection-permissions-enterprise.json | 14 ++ .../fixtures/presets/enterprise-basic.json | 14 ++ .../fixtures/presets/policy-enterprise.json | 14 ++ .../fixtures/presets/sso-enterprise.json | 22 +++ .../fixtures/presets/tde-enterprise.json | 22 +++ .../rosters/collection-permissions.json | 78 ++++++++ .../fixtures/rosters/enterprise-basic.json | 64 +++++++ .../Seeds/fixtures/rosters/policy-org.json | 9 + .../Seeds/fixtures/rosters/sso-basic.json | 8 + .../Seeds/fixtures/rosters/tde-basic.json | 16 ++ util/Seeder/Seeds/schemas/cipher.schema.json | 76 +++++++- util/Seeder/Seeds/schemas/preset.schema.json | 43 +++++ util/Seeder/Seeds/schemas/roster.schema.json | 18 ++ .../Seeds/templates/cipher.template.json | 33 +++- .../Seeds/templates/preset.template.json | 7 +- .../Seeds/templates/roster.template.json | 10 + 26 files changed, 907 insertions(+), 10 deletions(-) create mode 100644 util/Seeder/Seeds/fixtures/ciphers/collection-permissions.json create mode 100644 util/Seeder/Seeds/fixtures/ciphers/enterprise-basic.json create mode 100644 util/Seeder/Seeds/fixtures/ciphers/sso-vault.json create mode 100644 util/Seeder/Seeds/fixtures/ciphers/tde-vault.json create mode 100644 util/Seeder/Seeds/fixtures/organizations/qa-collection-permissions.json create mode 100644 util/Seeder/Seeds/fixtures/organizations/qa-enterprise.json create mode 100644 util/Seeder/Seeds/fixtures/organizations/qa-policy-org.json create mode 100644 util/Seeder/Seeds/fixtures/organizations/qa-sso-org.json create mode 100644 util/Seeder/Seeds/fixtures/organizations/qa-tde-org.json create mode 100644 util/Seeder/Seeds/fixtures/presets/collection-permissions-enterprise.json create mode 100644 util/Seeder/Seeds/fixtures/presets/enterprise-basic.json create mode 100644 util/Seeder/Seeds/fixtures/presets/policy-enterprise.json create mode 100644 util/Seeder/Seeds/fixtures/presets/sso-enterprise.json create mode 100644 util/Seeder/Seeds/fixtures/presets/tde-enterprise.json create mode 100644 util/Seeder/Seeds/fixtures/rosters/collection-permissions.json create mode 100644 util/Seeder/Seeds/fixtures/rosters/enterprise-basic.json create mode 100644 util/Seeder/Seeds/fixtures/rosters/policy-org.json create mode 100644 util/Seeder/Seeds/fixtures/rosters/sso-basic.json create mode 100644 util/Seeder/Seeds/fixtures/rosters/tde-basic.json diff --git a/util/Seeder/Seeds/README.md b/util/Seeder/Seeds/README.md index 21f09a8586..a11ebcf850 100644 --- a/util/Seeder/Seeds/README.md +++ b/util/Seeder/Seeds/README.md @@ -13,13 +13,12 @@ Hand-crafted JSON fixtures for Bitwarden Seeder test data. ``` Seeds/ ├── fixtures/ Your seed data goes here -│ ├── ciphers/ Vault items (logins, cards, identities, notes) +│ ├── ciphers/ Vault items │ ├── organizations/ Organization definitions │ ├── rosters/ Users, groups, collections, permissions │ └── presets/ Complete seeding scenarios ├── schemas/ JSON Schema validation (auto-checked by editors) ├── templates/ Starter files - copy these -│ └── CONTRIBUTING.md Detailed guide for contributors └── README.md This file ``` @@ -27,8 +26,6 @@ Seeds/ ### Ciphers -Vault items - logins, cards, identities, secure notes. - | Type | Required Object | Description | | ------------ | --------------- | -------------------------- | | `login` | `login` | Website credentials + URIs | @@ -89,9 +86,39 @@ dotnet build util/Seeder/Seeder.csproj | User refs | firstName.lastName | `jane.doe` | | Org domains | Realistic or .test | `acme.com`, `test.local` | +## QA Test Fixture Migration Matrix + +These Seeds consolidate test data previously found across the `bitwarden/test` repo. +The table below maps existing QA fixtures to their Seeder equivalents. + +| QA Source (`test/Bitwarden.Web.Tests/TestData/SetupData/`) | Used By | Seeder Preset | Org Fixture | Roster Fixture | Cipher Fixture | +| ---------------------------------------------------------- | --------------------------------- | ----------------------------------- | --------------------------- | ------------------------ | ------------------------ | +| `CollectionPermissionsOrg.json` | Web, Extension | `collection-permissions-enterprise` | `qa-collection-permissions` | `collection-permissions` | `collection-permissions` | +| `EnterpriseOrg.json` | Web, Extension, Android, iOS, CLI | `enterprise-basic` | `qa-enterprise` | `enterprise-basic` | `enterprise-basic` | +| `SsoOrg.json` | Web | `sso-enterprise` | `qa-sso-org` | `sso-basic` | `sso-vault` | +| `TDEOrg.json` | Web, Extension, Android, iOS | `tde-enterprise` | `qa-tde-org` | `tde-basic` | `tde-vault` | +| _(Confluence: Policy Org guide)_ | QA manual setup | `policy-enterprise` | `qa-policy-org` | `policy-org` | — | + +### Not Yet Migrated + +| QA Source | Used By | Status | +| --------------------- | ---------------------------- | --------------------------------------------------------------------- | +| `FreeAccount.json` | All 7 platforms | Planned — `free-personal-vault` preset (separate PR due to file size) | +| `FamiliesOrg.json` | Web, Extension | Planned — `families-basic` preset | +| `PremiumAccount.json` | Web, Extension, Android, iOS | Planned — `premium-personal-vault` preset | +| `SecretsManager.json` | Web | Planned — `secrets-manager-enterprise` preset | +| `FreeOrg.json` | Web | Planned — `free-org-basic` preset | + +### Additional Sources + +| Source | Location | Status | +| ---------------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------------- | +| `bw_importer.py` | `github.com/bitwarden/qa-tools` | Superseded by generation-based presets (`"ciphers": {"count": N}`) | +| `mass_org_manager.py` | `github.com/bitwarden/qa-tools` | Superseded by roster fixtures with groups/members/collections | +| Admin Console Testing Setup guides | Confluence QA space | Codified as `collection-permissions-enterprise`, `policy-enterprise`, `sso-enterprise`, `tde-enterprise` presets | + ## Security -- Test password: See `UserSeeder.DefaultPassword` constant - Use fictional names/addresses - Never commit real passwords or PII - Never seed production databases diff --git a/util/Seeder/Seeds/fixtures/ciphers/collection-permissions.json b/util/Seeder/Seeds/fixtures/ciphers/collection-permissions.json new file mode 100644 index 0000000000..b80ceb132c --- /dev/null +++ b/util/Seeder/Seeds/fixtures/ciphers/collection-permissions.json @@ -0,0 +1,155 @@ +{ + "$schema": "../../schemas/cipher.schema.json", + "items": [ + { + "type": "login", + "name": "View-And-Manage-Login", + "fields": [ + { "name": "Hidden-Field", "value": "hiddenfield", "type": "hidden" } + ], + "login": { + "username": "username", + "password": "password", + "totp": "testing123", + "uris": [ + { "uri": "bitwarden.com" } + ] + } + }, + { + "type": "login", + "name": "View-Items-Login-Delete", + "fields": [ + { "name": "Hidden-Field", "value": "hiddenfield", "type": "hidden" } + ], + "login": { + "username": "username", + "password": "password", + "totp": "testing123", + "uris": [ + { "uri": "bitwarden.com" } + ] + } + }, + { + "type": "login", + "name": "Edit-Items-Login-Delete", + "fields": [ + { "name": "Hidden-Field", "value": "hiddenfield", "type": "hidden" } + ], + "login": { + "username": "username", + "password": "password", + "totp": "testing123", + "uris": [ + { "uri": "bitwarden.com" } + ] + } + }, + { + "type": "login", + "name": "Edit-Items-Hidden-Passwords-Login-Delete", + "fields": [ + { "name": "Hidden-Field", "value": "hiddenfield", "type": "hidden" } + ], + "login": { + "username": "username", + "password": "password", + "totp": "testing123", + "uris": [ + { "uri": "bitwarden.com" } + ] + } + }, + { + "type": "login", + "name": "View-Items-Hidden-Passwords-Login-Delete", + "fields": [ + { "name": "Hidden-Field", "value": "hiddenfield", "type": "hidden" } + ], + "login": { + "username": "username", + "password": "password", + "totp": "testing123", + "uris": [ + { "uri": "bitwarden.com" } + ] + } + }, + { + "type": "login", + "name": "Manage-Login", + "fields": [ + { "name": "Hidden-Field", "value": "hiddenfield", "type": "hidden" } + ], + "login": { + "username": "username", + "password": "password", + "totp": "testing123", + "uris": [ + { "uri": "bitwarden.com" } + ] + } + }, + { + "type": "login", + "name": "Edit-Items-Hidden-Passwords-Login", + "fields": [ + { "name": "Hidden-Field", "value": "hiddenfield", "type": "hidden" } + ], + "login": { + "username": "username", + "password": "password", + "totp": "testing123", + "uris": [ + { "uri": "bitwarden.com" } + ] + } + }, + { + "type": "login", + "name": "Edit-Items-Login", + "fields": [ + { "name": "Hidden-Field", "value": "hiddenfield", "type": "hidden" } + ], + "login": { + "username": "username", + "password": "password", + "totp": "testing123", + "uris": [ + { "uri": "bitwarden.com" } + ] + } + }, + { + "type": "login", + "name": "View-Items-Login", + "fields": [ + { "name": "Hidden-Field", "value": "hiddenfield", "type": "hidden" } + ], + "login": { + "username": "username", + "password": "password", + "totp": "testing123", + "uris": [ + { "uri": "bitwarden.com" } + ] + } + }, + { + "type": "login", + "name": "View-Items-Hidden-Passwords-Login", + "fields": [ + { "name": "Hidden-Field", "value": "hiddenfield", "type": "hidden" } + ], + "login": { + "username": "username", + "password": "password", + "totp": "testing123", + "uris": [ + { "uri": "bitwarden.com" } + ] + } + } + ] +} diff --git a/util/Seeder/Seeds/fixtures/ciphers/enterprise-basic.json b/util/Seeder/Seeds/fixtures/ciphers/enterprise-basic.json new file mode 100644 index 0000000000..0eb83b6632 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/ciphers/enterprise-basic.json @@ -0,0 +1,179 @@ +{ + "$schema": "../../schemas/cipher.schema.json", + "items": [ + { + "type": "login", + "name": "Cipher-997761-2", + "login": { + "username": "test", + "password": "123" + } + }, + { + "type": "login", + "name": "Cipher-1793363", + "login": { + "username": "test", + "password": "123" + } + }, + { + "type": "login", + "name": "Cipher-1867254-1", + "reprompt": 1, + "login": { + "username": "1867254 Username" + } + }, + { + "type": "login", + "name": "Cipher-997761-1", + "login": { + "username": "test", + "password": "123" + } + }, + { + "type": "login", + "name": "Cipher-19620", + "login": { + "username": "19620 Username" + } + }, + { + "type": "login", + "name": "Cipher-1793362", + "login": { + "username": "test", + "password": "123" + } + }, + { + "type": "secureNote", + "name": "test item" + }, + { + "type": "login", + "name": "Cipher-317432", + "login": { + "username": "test", + "password": "123" + } + }, + { + "type": "login", + "name": "Cipher-1867254-2", + "login": { + "username": "1867254 Username" + } + }, + { + "type": "login", + "name": "Cipher-842054", + "login": { + "username": "User-842054", + "password": "Password-842054" + } + }, + { + "type": "login", + "name": "Cipher-1892038", + "login": {} + }, + { + "type": "login", + "name": "Cipher-1892039", + "login": {} + }, + { + "type": "login", + "name": "Cipher-1892047-No-Access", + "login": {} + }, + { + "type": "login", + "name": "Cipher-1892047-View", + "login": {} + }, + { + "type": "login", + "name": "Cipher-1892047-Manage", + "login": {} + }, + { + "type": "login", + "name": "Cipher-2532597", + "login": {} + }, + { + "type": "login", + "name": "Cipher-1793366", + "login": {} + }, + { + "type": "login", + "name": "Cipher-3925830", + "login": {} + }, + { + "type": "login", + "name": "Cipher-3925831", + "login": {} + }, + { + "type": "card", + "name": "Cipher-ClientEventLog-Card", + "card": { + "cardholderName": "QA Testing", + "brand": "Visa", + "number": "4242424242424242", + "expMonth": "1", + "expYear": "2111", + "code": "123" + } + }, + { + "type": "login", + "name": "Cipher-ClientEventLog-Login", + "fields": [ + { "name": "Hidden-Field", "value": "hiddenfield", "type": "hidden" } + ], + "login": { + "username": "username", + "password": "password", + "totp": "testing123" + } + }, + { + "type": "login", + "name": "Cipher-5172094", + "login": { + "username": "username", + "password": "password", + "totp": "testing123" + } + }, + { + "type": "login", + "name": "Cipher-3392572", + "login": { + "username": "Cipher-3392572", + "password": "abc", + "uris": [ + { "uri": "https://coinbase.com" } + ] + } + }, + { + "type": "login", + "name": "Cipher-3171087", + "login": { + "username": "Cipher-3171087", + "password": "abc", + "uris": [ + { "uri": "webtests.dev" } + ] + } + } + ] +} diff --git a/util/Seeder/Seeds/fixtures/ciphers/sso-vault.json b/util/Seeder/Seeds/fixtures/ciphers/sso-vault.json new file mode 100644 index 0000000000..706c61d184 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/ciphers/sso-vault.json @@ -0,0 +1,13 @@ +{ + "$schema": "../../schemas/cipher.schema.json", + "items": [ + { + "type": "login", + "name": "Cipher-20606", + "login": { + "username": "Cipher-20606", + "password": "password" + } + } + ] +} diff --git a/util/Seeder/Seeds/fixtures/ciphers/tde-vault.json b/util/Seeder/Seeds/fixtures/ciphers/tde-vault.json new file mode 100644 index 0000000000..83919446e7 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/ciphers/tde-vault.json @@ -0,0 +1,60 @@ +{ + "$schema": "../../schemas/cipher.schema.json", + "items": [ + { + "type": "login", + "name": "Cipher-1867257", + "login": { + "username": "1867257 Username" + } + }, + { + "type": "login", + "name": "Cipher-1867257-2", + "reprompt": 1, + "login": { + "username": "1867257-2 Username" + } + }, + { + "type": "login", + "name": "Cipher-1867259", + "login": { + "username": "1867259 Username" + } + }, + { + "type": "login", + "name": "Cipher-1867259-2", + "reprompt": 1, + "login": { + "username": "1867259-2 Username" + } + }, + { + "type": "login", + "name": "Cipher-1867261", + "reprompt": 1, + "login": { + "username": "1867261 Username" + } + }, + { + "type": "login", + "name": "Cipher-1867262", + "reprompt": 1, + "login": { + "username": "1867262 Username" + } + }, + { + "type": "login", + "name": "Cipher-19503", + "reprompt": 1, + "login": { + "username": "19503 Username", + "password": "19503 Password" + } + } + ] +} diff --git a/util/Seeder/Seeds/fixtures/organizations/qa-collection-permissions.json b/util/Seeder/Seeds/fixtures/organizations/qa-collection-permissions.json new file mode 100644 index 0000000000..1c2b350bd4 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/organizations/qa-collection-permissions.json @@ -0,0 +1,5 @@ +{ + "$schema": "../../schemas/organization.schema.json", + "name": "Collection Permissions QA Org", + "domain": "qa-collperms.test" +} diff --git a/util/Seeder/Seeds/fixtures/organizations/qa-enterprise.json b/util/Seeder/Seeds/fixtures/organizations/qa-enterprise.json new file mode 100644 index 0000000000..2bcaa88c07 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/organizations/qa-enterprise.json @@ -0,0 +1,5 @@ +{ + "$schema": "../../schemas/organization.schema.json", + "name": "Enterprise QA Org", + "domain": "qa-enterprise.test" +} diff --git a/util/Seeder/Seeds/fixtures/organizations/qa-policy-org.json b/util/Seeder/Seeds/fixtures/organizations/qa-policy-org.json new file mode 100644 index 0000000000..0f044fb8a1 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/organizations/qa-policy-org.json @@ -0,0 +1,5 @@ +{ + "$schema": "../../schemas/organization.schema.json", + "name": "Policy Testing Org", + "domain": "qa-policy.test" +} diff --git a/util/Seeder/Seeds/fixtures/organizations/qa-sso-org.json b/util/Seeder/Seeds/fixtures/organizations/qa-sso-org.json new file mode 100644 index 0000000000..ea46853c52 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/organizations/qa-sso-org.json @@ -0,0 +1,5 @@ +{ + "$schema": "../../schemas/organization.schema.json", + "name": "SSO QA Org", + "domain": "qa-sso.test" +} diff --git a/util/Seeder/Seeds/fixtures/organizations/qa-tde-org.json b/util/Seeder/Seeds/fixtures/organizations/qa-tde-org.json new file mode 100644 index 0000000000..58052105f1 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/organizations/qa-tde-org.json @@ -0,0 +1,5 @@ +{ + "$schema": "../../schemas/organization.schema.json", + "name": "TDE QA Org", + "domain": "qa-tde.test" +} diff --git a/util/Seeder/Seeds/fixtures/presets/collection-permissions-enterprise.json b/util/Seeder/Seeds/fixtures/presets/collection-permissions-enterprise.json new file mode 100644 index 0000000000..ebb5eaee4d --- /dev/null +++ b/util/Seeder/Seeds/fixtures/presets/collection-permissions-enterprise.json @@ -0,0 +1,14 @@ +{ + "$schema": "../../schemas/preset.schema.json", + "organization": { + "fixture": "qa-collection-permissions", + "planType": "enterprise-annually", + "seats": 10 + }, + "roster": { + "fixture": "collection-permissions" + }, + "ciphers": { + "fixture": "collection-permissions" + } +} diff --git a/util/Seeder/Seeds/fixtures/presets/enterprise-basic.json b/util/Seeder/Seeds/fixtures/presets/enterprise-basic.json new file mode 100644 index 0000000000..f3a8e04fa6 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/presets/enterprise-basic.json @@ -0,0 +1,14 @@ +{ + "$schema": "../../schemas/preset.schema.json", + "organization": { + "fixture": "qa-enterprise", + "planType": "enterprise-annually", + "seats": 10 + }, + "roster": { + "fixture": "enterprise-basic" + }, + "ciphers": { + "fixture": "enterprise-basic" + } +} diff --git a/util/Seeder/Seeds/fixtures/presets/policy-enterprise.json b/util/Seeder/Seeds/fixtures/presets/policy-enterprise.json new file mode 100644 index 0000000000..bdc46841e8 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/presets/policy-enterprise.json @@ -0,0 +1,14 @@ +{ + "$schema": "../../schemas/preset.schema.json", + "organization": { + "fixture": "qa-policy-org", + "planType": "enterprise-annually" + }, + "roster": { + "fixture": "policy-org" + }, + "policies": { + "enableAll": true, + "except": ["requireSso", "require2fa"] + } +} diff --git a/util/Seeder/Seeds/fixtures/presets/sso-enterprise.json b/util/Seeder/Seeds/fixtures/presets/sso-enterprise.json new file mode 100644 index 0000000000..e88e78ea7f --- /dev/null +++ b/util/Seeder/Seeds/fixtures/presets/sso-enterprise.json @@ -0,0 +1,22 @@ +{ + "$schema": "../../schemas/preset.schema.json", + "organization": { + "fixture": "qa-sso-org", + "planType": "enterprise-annually", + "seats": 10 + }, + "roster": { + "fixture": "sso-basic" + }, + "ciphers": { + "fixture": "sso-vault" + }, + "policies": { + "enable": ["requireSso"] + }, + "sso": { + "identifier": "qa-sso-org", + "encryptionType": "masterPassword", + "provider": "oidc" + } +} diff --git a/util/Seeder/Seeds/fixtures/presets/tde-enterprise.json b/util/Seeder/Seeds/fixtures/presets/tde-enterprise.json new file mode 100644 index 0000000000..eb8f7c04a7 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/presets/tde-enterprise.json @@ -0,0 +1,22 @@ +{ + "$schema": "../../schemas/preset.schema.json", + "organization": { + "fixture": "qa-tde-org", + "planType": "enterprise-annually", + "seats": 10 + }, + "roster": { + "fixture": "tde-basic" + }, + "ciphers": { + "fixture": "tde-vault" + }, + "policies": { + "enable": ["requireSso"] + }, + "sso": { + "identifier": "qa-tde-org", + "encryptionType": "trustedDevices", + "provider": "oidc" + } +} diff --git a/util/Seeder/Seeds/fixtures/rosters/collection-permissions.json b/util/Seeder/Seeds/fixtures/rosters/collection-permissions.json new file mode 100644 index 0000000000..83ae14ce6c --- /dev/null +++ b/util/Seeder/Seeds/fixtures/rosters/collection-permissions.json @@ -0,0 +1,78 @@ +{ + "$schema": "../../schemas/roster.schema.json", + "users": [ + { "firstName": "CollPerms", "lastName": "Owner", "role": "owner" }, + { "firstName": "CollPerms", "lastName": "Admin", "role": "admin" }, + { "firstName": "CollPerms", "lastName": "User", "role": "user" }, + { "firstName": "CollPerms", "lastName": "Custom", "role": "custom" } + ], + "collections": [ + { + "name": "View-Items-Collection", + "externalId": "view", + "users": [ + { "user": "collperms.admin", "readOnly": true }, + { "user": "collperms.user", "readOnly": true }, + { "user": "collperms.custom", "readOnly": true } + ] + }, + { + "name": "View-Items-Hidden-Passwords-Collection", + "externalId": "viewhidden", + "users": [ + { "user": "collperms.admin", "readOnly": true, "hidePasswords": true }, + { "user": "collperms.user", "readOnly": true, "hidePasswords": true }, + { "user": "collperms.custom", "readOnly": true, "hidePasswords": true } + ] + }, + { + "name": "Edit-Items-Collection", + "externalId": "edit", + "users": [ + { "user": "collperms.admin" }, + { "user": "collperms.user" }, + { "user": "collperms.custom" } + ] + }, + { + "name": "Edit-Items-Hidden-Passwords-Collection", + "externalId": "edithidden", + "users": [ + { "user": "collperms.admin", "hidePasswords": true }, + { "user": "collperms.user", "hidePasswords": true }, + { "user": "collperms.custom", "hidePasswords": true } + ] + }, + { + "name": "Manage-Collection", + "externalId": "manage", + "users": [ + { "user": "collperms.admin", "manage": true }, + { "user": "collperms.user", "manage": true }, + { "user": "collperms.custom", "manage": true } + ] + }, + { + "name": "Collection-21891", + "externalId": "manage", + "users": [ + { "user": "collperms.admin", "manage": true }, + { "user": "collperms.user", "manage": true }, + { "user": "collperms.custom", "manage": true } + ] + }, + { "name": "Collection-19712" }, + { "name": "Collection-19713" }, + { "name": "Collection-19714" }, + { "name": "Collection-19716-1" }, + { "name": "Collection-19716-2" }, + { + "name": "Collection-842048-not-assigned", + "externalId": "Collection-842048-not-assigned" + }, + { + "name": "Collection-842048-assigned", + "externalId": "Collection-842048-assigned" + } + ] +} diff --git a/util/Seeder/Seeds/fixtures/rosters/enterprise-basic.json b/util/Seeder/Seeds/fixtures/rosters/enterprise-basic.json new file mode 100644 index 0000000000..63d37801c5 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/rosters/enterprise-basic.json @@ -0,0 +1,64 @@ +{ + "$schema": "../../schemas/roster.schema.json", + "users": [ + { "firstName": "Enterprise", "lastName": "Owner", "role": "owner" }, + { "firstName": "Enterprise", "lastName": "Admin", "role": "admin" }, + { "firstName": "Enterprise", "lastName": "User", "role": "user" }, + { "firstName": "Enterprise", "lastName": "Custom", "role": "custom" }, + { "firstName": "Enterprise", "lastName": "Custom-Two", "role": "custom" } + ], + "groups": [ + { + "name": "All Members", + "members": [ + "enterprise.owner", + "enterprise.admin", + "enterprise.user", + "enterprise.custom", + "enterprise.custom-two" + ] + } + ], + "collections": [ + { + "name": "Default collection", + "groups": [{ "group": "All Members" }], + "users": [{ "user": "enterprise.owner", "manage": true }] + }, + { "name": "Collection-20360", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-20356", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-1793363", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-21895", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-20319", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-317432", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-997761-2", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-1793362", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-20308", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-21896", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-20359", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-20358", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-19619", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-19711", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-21891", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-997761-1", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-1867254", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-383003", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-19620", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-19933", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-20306", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-20294", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-842054", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-1892038", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-1892039", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-1892047-No-Access" }, + { "name": "Collection-1892047-View", "groups": [{ "group": "All Members", "readOnly": true }] }, + { "name": "Collection-1892047-Manage", "groups": [{ "group": "All Members", "manage": true }] }, + { "name": "Collection-2532597", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-1793366", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-3925894", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-4204903", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-5172094", "externalId": "Collection-5172094", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-3392572", "groups": [{ "group": "All Members" }] }, + { "name": "Collection-3171087", "groups": [{ "group": "All Members" }] } + ] +} diff --git a/util/Seeder/Seeds/fixtures/rosters/policy-org.json b/util/Seeder/Seeds/fixtures/rosters/policy-org.json new file mode 100644 index 0000000000..bc92938ef4 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/rosters/policy-org.json @@ -0,0 +1,9 @@ +{ + "$schema": "../../schemas/roster.schema.json", + "users": [ + { "firstName": "Policy", "lastName": "Owner", "role": "owner" }, + { "firstName": "Policy", "lastName": "Admin", "role": "admin" }, + { "firstName": "Policy", "lastName": "Custom", "role": "custom" }, + { "firstName": "Policy", "lastName": "User", "role": "user" } + ] +} diff --git a/util/Seeder/Seeds/fixtures/rosters/sso-basic.json b/util/Seeder/Seeds/fixtures/rosters/sso-basic.json new file mode 100644 index 0000000000..e2ade019d5 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/rosters/sso-basic.json @@ -0,0 +1,8 @@ +{ + "$schema": "../../schemas/roster.schema.json", + "users": [ + { "firstName": "Sso", "lastName": "Owner", "role": "owner" }, + { "firstName": "Sso", "lastName": "User", "role": "user" }, + { "firstName": "Sso", "lastName": "Provisioning", "role": "user" } + ] +} diff --git a/util/Seeder/Seeds/fixtures/rosters/tde-basic.json b/util/Seeder/Seeds/fixtures/rosters/tde-basic.json new file mode 100644 index 0000000000..05ddf80878 --- /dev/null +++ b/util/Seeder/Seeds/fixtures/rosters/tde-basic.json @@ -0,0 +1,16 @@ +{ + "$schema": "../../schemas/roster.schema.json", + "users": [ + { "firstName": "Tde", "lastName": "Owner", "role": "owner" }, + { "firstName": "Tde", "lastName": "Mp-Non-Trusted", "role": "user" }, + { "firstName": "Tde", "lastName": "No-Mp-Non-Trusted", "role": "user" } + ], + "collections": [ + { + "name": "Default collection", + "users": [ + { "user": "tde.no-mp-non-trusted", "manage": true } + ] + } + ] +} diff --git a/util/Seeder/Seeds/schemas/cipher.schema.json b/util/Seeder/Seeds/schemas/cipher.schema.json index a094f00acd..82278660b0 100644 --- a/util/Seeder/Seeds/schemas/cipher.schema.json +++ b/util/Seeder/Seeds/schemas/cipher.schema.json @@ -26,11 +26,10 @@ "properties": { "type": { "type": "string", - "enum": ["login", "card", "identity", "secureNote"] + "enum": ["login", "card", "identity", "secureNote", "sshKey"] }, "name": { - "type": "string", - "minLength": 1 + "type": "string" }, "notes": { "type": "string" @@ -44,11 +43,31 @@ "identity": { "$ref": "#/$defs/identity" }, + "sshKey": { + "$ref": "#/$defs/sshKey" + }, + "reprompt": { + "type": "integer", + "enum": [0, 1], + "default": 0, + "description": "Master password re-prompt. 0=None, 1=Password." + }, + "favorite": { + "type": "boolean", + "default": false, + "description": "Whether the item is marked as a favorite." + }, "fields": { "type": "array", "items": { "$ref": "#/$defs/field" } + }, + "passwordHistory": { + "type": "array", + "items": { + "$ref": "#/$defs/passwordHistory" + } } }, "allOf": [ @@ -63,6 +82,10 @@ { "if": { "properties": { "type": { "const": "identity" } } }, "then": { "required": ["identity"] } + }, + { + "if": { "properties": { "type": { "const": "sshKey" } } }, + "then": { "required": ["sshKey"] } } ] }, @@ -73,11 +96,19 @@ "username": { "type": "string" }, "password": { "type": "string" }, "totp": { "type": "string" }, + "passwordRevisionDate": { "type": "string", "description": "ISO date when the password was last changed." }, + "autofillOnPageLoad": { "type": "boolean", "description": "Auto-populate credential on page load." }, "uris": { "type": "array", "items": { "$ref": "#/$defs/loginUri" } + }, + "fido2Credentials": { + "type": "array", + "items": { + "$ref": "#/$defs/fido2Credential" + } } } }, @@ -142,8 +173,47 @@ "type": "string", "enum": ["text", "hidden", "boolean", "linked"], "default": "text" + }, + "linkedId": { + "type": "integer", + "description": "Links to cipher property. Only valid when type='linked'. Login: Username=100, Password=101. Card: CardholderName=300, ExpMonth=301, ExpYear=302, Code=303, Brand=304, Number=305. Identity: Title=400 through FullName=418." } } + }, + "sshKey": { + "type": "object", + "additionalProperties": false, + "properties": { + "privateKey": { "type": "string" }, + "publicKey": { "type": "string" }, + "keyFingerprint": { "type": "string" } + } + }, + "passwordHistory": { + "type": "object", + "additionalProperties": false, + "properties": { + "password": { "type": "string" }, + "lastUsedDate": { "type": "string", "description": "ISO date when password was last used." } + } + }, + "fido2Credential": { + "type": "object", + "additionalProperties": false, + "properties": { + "credentialId": { "type": "string" }, + "keyType": { "type": "string", "default": "public-key" }, + "keyAlgorithm": { "type": "string", "default": "ECDSA" }, + "keyCurve": { "type": "string", "default": "P-256" }, + "keyValue": { "type": "string" }, + "rpId": { "type": "string" }, + "rpName": { "type": "string" }, + "userHandle": { "type": "string" }, + "userName": { "type": "string" }, + "userDisplayName": { "type": "string" }, + "counter": { "type": "integer" }, + "discoverable": { "type": "boolean", "default": false } + } } } } diff --git a/util/Seeder/Seeds/schemas/preset.schema.json b/util/Seeder/Seeds/schemas/preset.schema.json index 308d6e8922..4371d5c6b2 100644 --- a/util/Seeder/Seeds/schemas/preset.schema.json +++ b/util/Seeder/Seeds/schemas/preset.schema.json @@ -133,6 +133,49 @@ } }, "required": ["countPerUser"] + }, + "policies": { + "type": "object", + "description": "Organization policy configuration.", + "additionalProperties": false, + "properties": { + "enableAll": { + "type": "boolean", + "default": false, + "description": "When true, enables all policy types." + }, + "except": { + "type": "array", + "items": { "type": "string" }, + "description": "Policy types to exclude when enableAll is true." + }, + "enable": { + "type": "array", + "items": { "type": "string" }, + "description": "Specific policy types to enable (alternative to enableAll)." + } + } + }, + "sso": { + "type": "object", + "description": "Single Sign-On configuration for the organization.", + "additionalProperties": false, + "properties": { + "identifier": { + "type": "string", + "description": "SSO organization identifier used in login flows." + }, + "encryptionType": { + "type": "string", + "enum": ["masterPassword", "trustedDevices"], + "description": "How member keys are protected. 'masterPassword' = standard SSO, 'trustedDevices' = TDE (no master password)." + }, + "provider": { + "type": "string", + "enum": ["oidc", "saml"], + "description": "Identity provider protocol." + } + } } } } diff --git a/util/Seeder/Seeds/schemas/roster.schema.json b/util/Seeder/Seeds/schemas/roster.schema.json index 2ae31cb93d..46558bd85f 100644 --- a/util/Seeder/Seeds/schemas/roster.schema.json +++ b/util/Seeder/Seeds/schemas/roster.schema.json @@ -51,6 +51,16 @@ "default": "user", "description": "Organization role." }, + "status": { + "type": "string", + "enum": ["confirmed", "invited", "accepted", "revoked"], + "default": "confirmed", + "description": "Organization membership status." + }, + "email": { + "type": "string", + "description": "Override derived email (firstName.lastName@domain). Use for non-standard email patterns." + }, "branch": { "type": "string", "description": "Branch office for grouping." @@ -71,6 +81,10 @@ "minLength": 1, "description": "Group display name (not encrypted)." }, + "externalId": { + "type": "string", + "description": "External identifier for directory sync / API test compatibility." + }, "members": { "type": "array", "items": { @@ -90,6 +104,10 @@ "minLength": 1, "description": "Collection name. Use '/' for visual hierarchy (e.g., 'Departments/Sales')." }, + "externalId": { + "type": "string", + "description": "External identifier for directory sync / API test compatibility." + }, "groups": { "type": "array", "description": "Group permission assignments.", diff --git a/util/Seeder/Seeds/templates/cipher.template.json b/util/Seeder/Seeds/templates/cipher.template.json index ebdc9a68a4..92c2019ffd 100644 --- a/util/Seeder/Seeds/templates/cipher.template.json +++ b/util/Seeder/Seeds/templates/cipher.template.json @@ -4,16 +4,37 @@ { "type": "login", "name": "Example Login", + "favorite": true, + "reprompt": 0, "login": { "username": "user@example.com", "password": "ChangeMe123!", + "totp": "otpauth://totp/Example:user?secret=JBSWY3DPEHPK3PXP", "uris": [ { "uri": "https://example.com/login", "match": "domain" } ] - } + }, + "fields": [ + { + "name": "Recovery Code", + "value": "ABC-123-XYZ", + "type": "hidden" + }, + { + "name": "Linked Username", + "type": "linked", + "linkedId": 100 + } + ], + "passwordHistory": [ + { + "password": "OldPassword1!", + "lastUsedDate": "2024-01-15T00:00:00.000Z" + } + ] }, { "type": "card", @@ -45,6 +66,16 @@ "type": "secureNote", "name": "Example Secure Note", "notes": "This is a secure note with sensitive information." + }, + { + "type": "sshKey", + "name": "Example SSH Key", + "reprompt": 1, + "sshKey": { + "privateKey": "-----BEGIN OPENSSH PRIVATE KEY-----\n...\n-----END OPENSSH PRIVATE KEY-----\n", + "publicKey": "ssh-ed25519 AAAAC3...", + "keyFingerprint": "SHA256:..." + } } ] } diff --git a/util/Seeder/Seeds/templates/preset.template.json b/util/Seeder/Seeds/templates/preset.template.json index 2d0f95e301..1765993d9f 100644 --- a/util/Seeder/Seeds/templates/preset.template.json +++ b/util/Seeder/Seeds/templates/preset.template.json @@ -3,12 +3,17 @@ "organization": { "name": "Acme Corporation", "domain": "acme.example.com", - "seats": 50 + "seats": 50, + "planType": "enterprise-annually" }, "roster": { "fixture": "my-roster-fixture" }, "ciphers": { "fixture": "my-cipher-fixture" + }, + "policies": { + "enableAll": true, + "except": ["requireSso"] } } diff --git a/util/Seeder/Seeds/templates/roster.template.json b/util/Seeder/Seeds/templates/roster.template.json index 105d2591f9..88ffc9a884 100644 --- a/util/Seeder/Seeds/templates/roster.template.json +++ b/util/Seeder/Seeds/templates/roster.template.json @@ -14,9 +14,17 @@ "lastName": "User", "title": "Developer", "role": "user", + "status": "confirmed", "branch": "Headquarters", "department": "Engineering" }, + { + "firstName": "Dave", + "lastName": "Invited", + "role": "user", + "status": "invited", + "email": "dave.custom-email@external.com" + }, { "firstName": "Carol", "lastName": "Manager", @@ -36,6 +44,7 @@ }, { "name": "Engineering Team", + "externalId": "eng-team-001", "members": [ "bob.user", "carol.manager" @@ -64,6 +73,7 @@ }, { "name": "Engineering/Development", + "externalId": "eng-dev-collection", "groups": [ { "group": "Engineering Team",