@antelopejs/dms 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/dist/db/models/notification-feed-filter.d.ts +0 -1
- package/dist/db/models/notification-feed-filter.js +0 -4
- package/dist/db/models/notification-feed-filter.js.map +1 -1
- package/dist/db/models/signInAttempts.model.d.ts +18 -0
- package/dist/db/models/signInAttempts.model.js +83 -12
- package/dist/db/models/signInAttempts.model.js.map +1 -1
- package/dist/db/models/userEmailChanges.model.d.ts +8 -1
- package/dist/db/models/userEmailChanges.model.js +27 -2
- package/dist/db/models/userEmailChanges.model.js.map +1 -1
- package/dist/db/models/userNotificationPreferences.model.d.ts +0 -2
- package/dist/db/models/userNotificationPreferences.model.js +0 -13
- package/dist/db/models/userNotificationPreferences.model.js.map +1 -1
- package/dist/db/models/userNotifications.model.d.ts +5 -2
- package/dist/db/models/userNotifications.model.js +19 -2
- package/dist/db/models/userNotifications.model.js.map +1 -1
- package/dist/db/tables/signInAttempts.table.d.ts +2 -1
- package/dist/db/tables/signInAttempts.table.js +4 -0
- package/dist/db/tables/signInAttempts.table.js.map +1 -1
- package/dist/db/tables/userEmailChanges.table.d.ts +2 -1
- package/dist/db/tables/userEmailChanges.table.js +6 -1
- package/dist/db/tables/userEmailChanges.table.js.map +1 -1
- package/dist/db/tables/userNotificationPreferences.table.d.ts +0 -1
- package/dist/db/tables/userNotificationPreferences.table.js +0 -4
- package/dist/db/tables/userNotificationPreferences.table.js.map +1 -1
- package/dist/implementations/dms/layout-banners.d.ts +4 -1
- package/dist/implementations/dms/layout-banners.js +33 -18
- package/dist/implementations/dms/layout-banners.js.map +1 -1
- package/dist/implementations/dms/nav-badges.d.ts +6 -4
- package/dist/implementations/dms/nav-badges.js +6 -5
- package/dist/implementations/dms/nav-badges.js.map +1 -1
- package/dist/implementations/dms/page.d.ts +1 -0
- package/dist/implementations/dms/page.js +46 -8
- package/dist/implementations/dms/page.js.map +1 -1
- package/dist/implementations/dms/permission-preview.d.ts +1 -1
- package/dist/implementations/dms/permission-preview.js +9 -4
- package/dist/implementations/dms/permission-preview.js.map +1 -1
- package/dist/implementations/dms-auth/index.d.ts +3 -2
- package/dist/implementations/dms-auth/index.js +39 -35
- package/dist/implementations/dms-auth/index.js.map +1 -1
- package/dist/implementations/dms-auth/token-session.d.ts +3 -0
- package/dist/implementations/dms-auth/token-session.js +22 -0
- package/dist/implementations/dms-auth/token-session.js.map +1 -0
- package/dist/implementations/dms-notifications/index.d.ts +0 -1
- package/dist/implementations/dms-notifications/index.js +0 -7
- package/dist/implementations/dms-notifications/index.js.map +1 -1
- package/dist/pages/settings/settings-index.js +3 -2
- package/dist/pages/settings/settings-index.js.map +1 -1
- package/dist/pages/settings/users/account-activity-feed.d.ts +1 -1
- package/dist/pages/settings/users/account-activity-feed.js +1 -1
- package/dist/pages/settings/users/account-activity-feed.js.map +1 -1
- package/dist/pages/settings/users/account-activity.d.ts +1 -1
- package/dist/pages/settings/users/account-activity.js +1 -1
- package/dist/pages/settings/users/account-activity.js.map +1 -1
- package/dist/pages/settings/users/account-credentials.d.ts +3 -0
- package/dist/pages/settings/users/account-credentials.js +2 -0
- package/dist/pages/settings/users/account-credentials.js.map +1 -1
- package/dist/pages/settings/users/current-password.d.ts +1 -1
- package/dist/pages/settings/users/current-password.js +23 -2
- package/dist/pages/settings/users/current-password.js.map +1 -1
- package/dist/pages/settings/users/email-change.d.ts +1 -1
- package/dist/pages/settings/users/email-change.js +33 -26
- package/dist/pages/settings/users/email-change.js.map +1 -1
- package/dist/pages/settings/users/invite-resend.js +0 -1
- package/dist/pages/settings/users/invite-resend.js.map +1 -1
- package/dist/pages/settings/users/invites.d.ts +1 -2
- package/dist/pages/settings/users/invites.js +21 -19
- package/dist/pages/settings/users/invites.js.map +1 -1
- package/dist/pages/settings/users/member-invite-batch.js +0 -1
- package/dist/pages/settings/users/member-invite-batch.js.map +1 -1
- package/dist/pages/settings/users/member-invite-form.js +10 -22
- package/dist/pages/settings/users/member-invite-form.js.map +1 -1
- package/dist/pages/settings/users/member-role-options.d.ts +6 -4
- package/dist/pages/settings/users/member-role-options.js +15 -4
- package/dist/pages/settings/users/member-role-options.js.map +1 -1
- package/dist/pages/settings/users/members.d.ts +2 -3
- package/dist/pages/settings/users/members.js +7 -12
- package/dist/pages/settings/users/members.js.map +1 -1
- package/dist/pages/settings/users/notifications.d.ts +1 -8
- package/dist/pages/settings/users/notifications.js +6 -38
- package/dist/pages/settings/users/notifications.js.map +1 -1
- package/dist/pages/settings/users/permission-tree-nodes.d.ts +1 -1
- package/dist/pages/settings/users/permission-tree-nodes.js +23 -9
- package/dist/pages/settings/users/permission-tree-nodes.js.map +1 -1
- package/dist/pages/settings/users/permission-warnings.d.ts +7 -0
- package/dist/pages/settings/users/permission-warnings.js +42 -0
- package/dist/pages/settings/users/permission-warnings.js.map +1 -0
- package/dist/pages/settings/users/profile-helpers.d.ts +1 -3
- package/dist/pages/settings/users/profile-helpers.js +0 -16
- package/dist/pages/settings/users/profile-helpers.js.map +1 -1
- package/dist/pages/settings/users/role-editor-store.js +6 -3
- package/dist/pages/settings/users/role-editor-store.js.map +1 -1
- package/dist/pages/settings/users/role-editor.d.ts +2 -1
- package/dist/pages/settings/users/role-editor.js +8 -4
- package/dist/pages/settings/users/role-editor.js.map +1 -1
- package/dist/pages/settings/users/role-preview.js +2 -1
- package/dist/pages/settings/users/role-preview.js.map +1 -1
- package/dist/pages/settings/users/roles.js +5 -1
- package/dist/pages/settings/users/roles.js.map +1 -1
- package/dist/pages/settings/users/security-attention.d.ts +4 -0
- package/dist/pages/settings/users/security-attention.js +23 -7
- package/dist/pages/settings/users/security-attention.js.map +1 -1
- package/dist/pages/settings/users/security.d.ts +2 -1
- package/dist/pages/settings/users/security.js +13 -2
- package/dist/pages/settings/users/security.js.map +1 -1
- package/dist/pages/settings/users/two-factor-operations.d.ts +2 -1
- package/dist/pages/settings/users/two-factor-operations.js +28 -29
- package/dist/pages/settings/users/two-factor-operations.js.map +1 -1
- package/dist/routes/auth/forgot-password.js +3 -0
- package/dist/routes/auth/forgot-password.js.map +1 -1
- package/dist/routes/auth/index.d.ts +1 -0
- package/dist/routes/auth/index.js +1 -0
- package/dist/routes/auth/index.js.map +1 -1
- package/dist/routes/auth/invite.js +28 -4
- package/dist/routes/auth/invite.js.map +1 -1
- package/dist/routes/auth/login-throttle.d.ts +2 -0
- package/dist/routes/auth/login-throttle.js +5 -4
- package/dist/routes/auth/login-throttle.js.map +1 -1
- package/dist/routes/auth/request-2fa-email.js +6 -18
- package/dist/routes/auth/request-2fa-email.js.map +1 -1
- package/dist/routes/auth/reset-code.d.ts +3 -0
- package/dist/routes/auth/reset-code.js +37 -0
- package/dist/routes/auth/reset-code.js.map +1 -0
- package/dist/routes/auth/reset-password.d.ts +2 -2
- package/dist/routes/auth/reset-password.js +5 -10
- package/dist/routes/auth/reset-password.js.map +1 -1
- package/dist/routes/auth/signup.js +10 -32
- package/dist/routes/auth/signup.js.map +1 -1
- package/dist/routes/auth/two-factor-throttle.d.ts +5 -0
- package/dist/routes/auth/two-factor-throttle.js +81 -0
- package/dist/routes/auth/two-factor-throttle.js.map +1 -0
- package/dist/routes/auth/validate-forgot-password-token.js +2 -8
- package/dist/routes/auth/validate-forgot-password-token.js.map +1 -1
- package/dist/routes/auth/validate-invite-token.d.ts +1 -0
- package/dist/routes/auth/validate-invite-token.js +11 -0
- package/dist/routes/auth/validate-invite-token.js.map +1 -0
- package/dist/routes/auth/verify-2fa.js +10 -13
- package/dist/routes/auth/verify-2fa.js.map +1 -1
- package/dist/routes/auth.d.ts +1 -0
- package/dist/routes/auth.js +11 -1
- package/dist/routes/auth.js.map +1 -1
- package/dist/test/helpers/auth.d.ts +0 -1
- package/dist/test/helpers/auth.js +0 -1
- package/dist/test/helpers/auth.js.map +1 -1
- package/dist/test/helpers/emails.d.ts +10 -0
- package/dist/test/helpers/emails.js +36 -0
- package/dist/test/helpers/emails.js.map +1 -0
- package/dist/test/helpers/fixtures.d.ts +0 -1
- package/dist/test/helpers/fixtures.js +1 -2
- package/dist/test/helpers/fixtures.js.map +1 -1
- package/dist/test/helpers/page-access.d.ts +1 -0
- package/dist/test/helpers/page-access.js +6 -1
- package/dist/test/helpers/page-access.js.map +1 -1
- package/dist/test/integration/auth/current-password.test.d.ts +1 -0
- package/dist/test/integration/auth/current-password.test.js +65 -0
- package/dist/test/integration/auth/current-password.test.js.map +1 -0
- package/dist/test/integration/auth/password-reset.test.d.ts +1 -0
- package/dist/test/integration/auth/password-reset.test.js +126 -0
- package/dist/test/integration/auth/password-reset.test.js.map +1 -0
- package/dist/test/integration/auth/session-revocation.test.d.ts +1 -0
- package/dist/test/integration/auth/session-revocation.test.js +45 -0
- package/dist/test/integration/auth/session-revocation.test.js.map +1 -0
- package/dist/test/integration/auth/two-factor-codes.test.d.ts +1 -0
- package/dist/test/integration/auth/two-factor-codes.test.js +335 -0
- package/dist/test/integration/auth/two-factor-codes.test.js.map +1 -0
- package/dist/test/integration/auth/two-factor-password.test.js +5 -1
- package/dist/test/integration/auth/two-factor-password.test.js.map +1 -1
- package/dist/test/integration/auth/two-factor-token.test.d.ts +1 -0
- package/dist/test/integration/auth/two-factor-token.test.js +92 -0
- package/dist/test/integration/auth/two-factor-token.test.js.map +1 -0
- package/dist/test/integration/email-change.test.js +36 -0
- package/dist/test/integration/email-change.test.js.map +1 -1
- package/dist/test/integration/invite-extension-edit.test.js +0 -1
- package/dist/test/integration/invite-extension-edit.test.js.map +1 -1
- package/dist/test/integration/invite-link-status.test.d.ts +1 -0
- package/dist/test/integration/invite-link-status.test.js +110 -0
- package/dist/test/integration/invite-link-status.test.js.map +1 -0
- package/dist/test/integration/invite-resolution.test.js +0 -3
- package/dist/test/integration/invite-resolution.test.js.map +1 -1
- package/dist/test/integration/member-settings-access.test.js +17 -0
- package/dist/test/integration/member-settings-access.test.js.map +1 -1
- package/dist/test/integration/notification-unread-badge.test.d.ts +1 -0
- package/dist/test/integration/notification-unread-badge.test.js +92 -0
- package/dist/test/integration/notification-unread-badge.test.js.map +1 -0
- package/dist/test/integration/permission-warnings.test.d.ts +1 -0
- package/dist/test/integration/permission-warnings.test.js +71 -0
- package/dist/test/integration/permission-warnings.test.js.map +1 -0
- package/dist/test/integration/removed-member-notifications.test.d.ts +1 -0
- package/dist/test/integration/removed-member-notifications.test.js +80 -0
- package/dist/test/integration/removed-member-notifications.test.js.map +1 -0
- package/dist/test/integration/role-permission-ancestors.test.d.ts +1 -0
- package/dist/test/integration/role-permission-ancestors.test.js +146 -0
- package/dist/test/integration/role-permission-ancestors.test.js.map +1 -0
- package/dist/test/integration/tenant-lifecycle.test.js +0 -4
- package/dist/test/integration/tenant-lifecycle.test.js.map +1 -1
- package/dist/test/unit/auth-session-revocation.test.d.ts +1 -0
- package/dist/test/unit/auth-session-revocation.test.js +105 -0
- package/dist/test/unit/auth-session-revocation.test.js.map +1 -0
- package/dist/test/unit/db/email-normalization.test.js +0 -1
- package/dist/test/unit/db/email-normalization.test.js.map +1 -1
- package/dist/test/unit/db/notification-feed-filter.test.js +0 -16
- package/dist/test/unit/db/notification-feed-filter.test.js.map +1 -1
- package/dist/test/unit/db/notification-inbox.test.js +63 -13
- package/dist/test/unit/db/notification-inbox.test.js.map +1 -1
- package/dist/test/unit/db/notification-preferences.test.js +0 -17
- package/dist/test/unit/db/notification-preferences.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/empty-menu-group.test.d.ts +1 -0
- package/dist/test/unit/implementations/dms/empty-menu-group.test.js +133 -0
- package/dist/test/unit/implementations/dms/empty-menu-group.test.js.map +1 -0
- package/dist/test/unit/implementations/dms/layout-banners.test.js +78 -1
- package/dist/test/unit/implementations/dms/layout-banners.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/menu-hidden-blocks.test.d.ts +1 -0
- package/dist/test/unit/implementations/dms/menu-hidden-blocks.test.js +149 -0
- package/dist/test/unit/implementations/dms/menu-hidden-blocks.test.js.map +1 -0
- package/dist/test/unit/implementations/dms/nav-badges.test.js +55 -4
- package/dist/test/unit/implementations/dms/nav-badges.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/page-all-components-hidden.test.d.ts +1 -0
- package/dist/test/unit/implementations/dms/page-all-components-hidden.test.js +118 -0
- package/dist/test/unit/implementations/dms/page-all-components-hidden.test.js.map +1 -0
- package/dist/test/unit/implementations/dms/permission-preview-aggregate.test.js +16 -0
- package/dist/test/unit/implementations/dms/permission-preview-aggregate.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/permission-preview-cost.test.js +5 -3
- package/dist/test/unit/implementations/dms/permission-preview-cost.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/permission-preview-menu.test.js +29 -3
- package/dist/test/unit/implementations/dms/permission-preview-menu.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/quick-actions-button.test.js +4 -2
- package/dist/test/unit/implementations/dms/quick-actions-button.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/user-permissions-gate.test.js +2 -1
- package/dist/test/unit/implementations/dms/user-permissions-gate.test.js.map +1 -1
- package/dist/test/unit/implementations/dms-base/table-view-shared-controller.test.js +2 -1
- package/dist/test/unit/implementations/dms-base/table-view-shared-controller.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/component-children-permissions.test.js +7 -2
- package/dist/test/unit/interfaces/dms/component-children-permissions.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/form-watch-permissions.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/form-watch-permissions.test.js +133 -0
- package/dist/test/unit/interfaces/dms/form-watch-permissions.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms/has-permission-ancestors.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/has-permission-ancestors.test.js +149 -0
- package/dist/test/unit/interfaces/dms/has-permission-ancestors.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms/invite-extension.test.js +13 -0
- package/dist/test/unit/interfaces/dms/invite-extension.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/member-access.test.js +27 -1
- package/dist/test/unit/interfaces/dms/member-access.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/nav-badge-tones.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/nav-badge-tones.test.js +31 -0
- package/dist/test/unit/interfaces/dms/nav-badge-tones.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms/page-extension.test.js +4 -1
- package/dist/test/unit/interfaces/dms/page-extension.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/permission-requirements.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/permission-requirements.test.js +144 -0
- package/dist/test/unit/interfaces/dms/permission-requirements.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms-base/column-display.test.js +70 -0
- package/dist/test/unit/interfaces/dms-base/column-display.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/display-blocks-catalog.test.js +38 -0
- package/dist/test/unit/interfaces/dms-base/display-blocks-catalog.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/layout-header-actions.test.js +6 -2
- package/dist/test/unit/interfaces/dms-base/layout-header-actions.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/lists-and-settings-catalog.test.js +1 -1
- package/dist/test/unit/interfaces/dms-base/lists-and-settings-catalog.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-export-permission.test.js +2 -1
- package/dist/test/unit/interfaces/dms-base/table-view-export-permission.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.js +2 -1
- package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-shared-controller-permissions.test.js +2 -1
- package/dist/test/unit/interfaces/dms-base/table-view-shared-controller-permissions.test.js.map +1 -1
- package/dist/test/unit/pages/settings/account-activity-feed.test.js +2 -2
- package/dist/test/unit/pages/settings/account-activity-feed.test.js.map +1 -1
- package/dist/test/unit/pages/settings/account-activity.test.js +11 -2
- package/dist/test/unit/pages/settings/account-activity.test.js.map +1 -1
- package/dist/test/unit/pages/settings/invite-email-delivery.test.js +0 -1
- package/dist/test/unit/pages/settings/invite-email-delivery.test.js.map +1 -1
- package/dist/test/unit/pages/settings/invite-email-validation-option.test.d.ts +1 -0
- package/dist/test/unit/pages/settings/invite-email-validation-option.test.js +33 -0
- package/dist/test/unit/pages/settings/invite-email-validation-option.test.js.map +1 -0
- package/dist/test/unit/pages/settings/member-lists-page-size.test.d.ts +1 -0
- package/dist/test/unit/pages/settings/member-lists-page-size.test.js +22 -0
- package/dist/test/unit/pages/settings/member-lists-page-size.test.js.map +1 -0
- package/dist/test/unit/pages/settings/member-table-widths.test.js +2 -2
- package/dist/test/unit/pages/settings/member-table-widths.test.js.map +1 -1
- package/dist/test/unit/pages/settings/members-page.test.js +7 -10
- package/dist/test/unit/pages/settings/members-page.test.js.map +1 -1
- package/dist/test/unit/pages/settings/notifications-access-gate.test.js +3 -10
- package/dist/test/unit/pages/settings/notifications-access-gate.test.js.map +1 -1
- package/dist/test/unit/pages/settings/permission-tree-nodes.test.js +57 -0
- package/dist/test/unit/pages/settings/permission-tree-nodes.test.js.map +1 -1
- package/dist/test/unit/pages/settings/permission-warnings.test.d.ts +1 -0
- package/dist/test/unit/pages/settings/permission-warnings.test.js +49 -0
- package/dist/test/unit/pages/settings/permission-warnings.test.js.map +1 -0
- package/dist/test/unit/pages/settings/role-editor.test.js +16 -0
- package/dist/test/unit/pages/settings/role-editor.test.js.map +1 -1
- package/dist/test/unit/pages/settings/role-preview.test.js +7 -0
- package/dist/test/unit/pages/settings/role-preview.test.js.map +1 -1
- package/dist/test/unit/pages/settings/security-attention.test.d.ts +1 -0
- package/dist/test/unit/pages/settings/security-attention.test.js +74 -0
- package/dist/test/unit/pages/settings/security-attention.test.js.map +1 -0
- package/dist/test/unit/sanitize-user.test.d.ts +1 -0
- package/dist/test/unit/sanitize-user.test.js +21 -0
- package/dist/test/unit/sanitize-user.test.js.map +1 -0
- package/dist/test/unit/signup-email-validation.test.d.ts +1 -0
- package/dist/test/unit/signup-email-validation.test.js +79 -0
- package/dist/test/unit/signup-email-validation.test.js.map +1 -0
- package/dist/test/unit/validation/member-invite.schema.test.js +14 -52
- package/dist/test/unit/validation/member-invite.schema.test.js.map +1 -1
- package/dist/utils/account-notifications.d.ts +5 -0
- package/dist/utils/account-notifications.js +8 -0
- package/dist/utils/account-notifications.js.map +1 -1
- package/dist/utils/notification-emitter.d.ts +1 -1
- package/dist/utils/notification-emitter.js +1 -1
- package/dist/utils/notification-emitter.js.map +1 -1
- package/dist/utils/notification-tones.d.ts +2 -1
- package/dist/utils/notification-tones.js +5 -1
- package/dist/utils/notification-tones.js.map +1 -1
- package/dist/utils/one-time-code.d.ts +3 -0
- package/dist/utils/one-time-code.js +21 -0
- package/dist/utils/one-time-code.js.map +1 -0
- package/dist/utils/sign-in-monitor.d.ts +1 -0
- package/dist/utils/sign-in-monitor.js +3 -2
- package/dist/utils/sign-in-monitor.js.map +1 -1
- package/dist/utils/two-factor-codes.d.ts +10 -0
- package/dist/utils/two-factor-codes.js +76 -0
- package/dist/utils/two-factor-codes.js.map +1 -0
- package/dist/validation/auth.schema.d.ts +17 -0
- package/dist/validation/auth.schema.js +17 -6
- package/dist/validation/auth.schema.js.map +1 -1
- package/dist/validation/issue-message.d.ts +1 -0
- package/dist/validation/issue-message.js +9 -0
- package/dist/validation/issue-message.js.map +1 -0
- package/dist/validation/member-invite.schema.d.ts +1 -25
- package/dist/validation/member-invite.schema.js +2 -23
- package/dist/validation/member-invite.schema.js.map +1 -1
- package/frontend-vue/dms.frontend.ts +2 -0
- package/frontend-vue/layers/dms-auth/app/custom-pages/auth/forgot-validation.vue +3 -0
- package/frontend-vue/layers/dms-auth/app/custom-pages/auth/signup.vue +105 -5
- package/frontend-vue/layers/dms-auth/i18n/locales/auth-en-GB.json +20 -4
- package/frontend-vue/layers/dms-auth/i18n/locales/auth-fr-FR.json +20 -4
- package/frontend-vue/layers/dms-core/app/composables/translation/useComposedText.ts +25 -0
- package/frontend-vue/layers/dms-core/app/composables/useFieldErrors.ts +3 -2
- package/frontend-vue/layers/dms-core/app/types/composed-text.ts +64 -0
- package/frontend-vue/layers/dms-core/app/types/menu.ts +15 -0
- package/frontend-vue/layers/dms-core/app/utils/composedText.ts +227 -0
- package/frontend-vue/layers/dms-core/app/utils/formatter.ts +49 -0
- package/frontend-vue/layers/dms-core/i18n/locales/core-en-GB.json +4 -1
- package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +4 -1
- package/frontend-vue/layers/dms-layout/app/assets/css/main.css +20 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/CommandPaletteAssistantAnswer.vue +75 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardBanners.vue +17 -3
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardFrame.vue +22 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +24 -10
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidePanel.vue +139 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/Footer.vue +4 -2
- package/frontend-vue/layers/dms-layout/app/build/components/layout/GithubStarPrompt.vue +90 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/SidePanelHost.vue +17 -0
- package/frontend-vue/layers/dms-layout/app/build/components/notification/NotificationPopover.vue +25 -43
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/members/MemberRolePicker.vue +24 -2
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationMatrixCategory.vue +70 -25
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationPreferencesForm.vue +25 -10
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/notificationDisplay.ts +41 -5
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfilePreferencesSummary.vue +2 -1
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfileSecuritySummary.vue +20 -4
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RoleEditor.vue +21 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionArea.vue +16 -2
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionBranch.vue +1 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionLeaf.vue +13 -1
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionTree.vue +9 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionWarning.vue +46 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-permissions.ts +108 -29
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-types.ts +2 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityDialogFrame.vue +6 -6
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityEmail.vue +7 -1
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecuritySessions.vue +5 -4
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityStatus.vue +4 -3
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityTwoFactor.vue +54 -18
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/shell/SettingsNav.vue +13 -8
- package/frontend-vue/layers/dms-layout/app/build/composables/command-palette/assistantGroups.ts +143 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/command-palette/useCommandPaletteAssistantMode.ts +249 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/general/useGithubStarPrompt.ts +178 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/layout/sidePanelState.ts +191 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/layout/useHeaderActionControls.ts +51 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/layout/useSidePanelWidth.ts +113 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/navigation/useCategoryNavCards.ts +17 -10
- package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationGroupsOpen.ts +45 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/settings/profile/useProfilePreferences.ts +8 -1
- package/frontend-vue/layers/dms-layout/app/build/composables/settings/security/useSecurityOverview.ts +50 -3
- package/frontend-vue/layers/dms-layout/app/build/composables/settings/useSettingsNavigation.ts +3 -0
- package/frontend-vue/layers/dms-layout/app/build/utils/categoryPages.ts +1 -2
- package/frontend-vue/layers/dms-layout/app/build/utils/github-repository.ts +5 -0
- package/frontend-vue/layers/dms-layout/app/components/layout/DashboardSearch.vue +109 -7
- package/frontend-vue/layers/dms-layout/app/components/navigation/NavigationMenu.vue +19 -9
- package/frontend-vue/layers/dms-layout/app/composables/notification/useNotifications.ts +22 -40
- package/frontend-vue/layers/dms-layout/app/composables/useAppSidePanels.ts +96 -0
- package/frontend-vue/layers/dms-layout/app/composables/useCommandPaletteAssistant.ts +129 -0
- package/frontend-vue/layers/dms-layout/app/composables/useHeaderActions.ts +33 -11
- package/frontend-vue/layers/dms-layout/app/composables/useSidePanel.ts +41 -0
- package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +15 -0
- package/frontend-vue/layers/dms-layout/app/plugins/notification-stream.client.ts +1 -7
- package/frontend-vue/layers/dms-layout/app/plugins/side-panel-host.ts +13 -0
- package/frontend-vue/layers/dms-layout/app/types/page.ts +11 -1
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +43 -13
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +43 -13
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormLoadError.vue +45 -0
- package/frontend-vue/layers/dms-ui/app/build/components/modal/ModalEscHint.vue +28 -0
- package/frontend-vue/layers/dms-ui/app/build/components/table-view/IdentityCell.vue +36 -7
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/cellHelpers.ts +57 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/metricCells.ts +19 -5
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +22 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/twoLineCell.ts +118 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/useColumnValueRenderer.ts +5 -3
- package/frontend-vue/layers/dms-ui/app/build/composables/form/floatingSaveBars.ts +38 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/formRecordLoad.ts +66 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/navigation/useNavBadges.ts +50 -9
- package/frontend-vue/layers/dms-ui/app/build/composables/table/useTable.ts +7 -1
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/chrome.ts +2 -2
- package/frontend-vue/layers/dms-ui/app/build/types/tree.ts +14 -10
- package/frontend-vue/layers/dms-ui/app/build/utils/navBadge.ts +12 -0
- package/frontend-vue/layers/dms-ui/app/build/utils/relativeDate.ts +4 -35
- package/frontend-vue/layers/dms-ui/app/build/utils/tone.ts +22 -0
- package/frontend-vue/layers/dms-ui/app/components/activity-feed/ActivityFeed.vue +117 -82
- package/frontend-vue/layers/dms-ui/app/components/blocks/BannerBlock.vue +8 -5
- package/frontend-vue/layers/dms-ui/app/components/blocks/KeyValueListBlock.vue +38 -18
- package/frontend-vue/layers/dms-ui/app/components/blocks/NavCardGridBlock.vue +12 -1
- package/frontend-vue/layers/dms-ui/app/components/blocks/StatGroupBlock.vue +26 -23
- package/frontend-vue/layers/dms-ui/app/components/card/NavCard.vue +16 -1
- package/frontend-vue/layers/dms-ui/app/components/confirm/ConfirmModal.vue +7 -8
- package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +28 -6
- package/frontend-vue/layers/dms-ui/app/components/form/components/Display.vue +5 -1
- package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveBar.vue +4 -0
- package/frontend-vue/layers/dms-ui/app/components/status-pill/StatusPill.vue +7 -2
- package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +7 -2
- package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +48 -34
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +13 -3
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +16 -14
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +16 -14
- package/frontend-vue/package.json +2 -2
- package/frontend-vue/pnpm-lock.yaml +5 -5
- package/frontend-vue/tests/activity-feed-fill-height.test.ts +107 -0
- package/frontend-vue/tests/category-nav-cards.test.ts +21 -13
- package/frontend-vue/tests/command-palette-assistant.test.ts +344 -0
- package/frontend-vue/tests/composed-text-blocks.test.ts +205 -0
- package/frontend-vue/tests/composed-text.test.ts +265 -0
- package/frontend-vue/tests/fixtures/dashboard-search-stub.ts +91 -0
- package/frontend-vue/tests/forgot-validation-resend.test.ts +234 -0
- package/frontend-vue/tests/form-display-options.test.ts +64 -0
- package/frontend-vue/tests/form-load-error.test.ts +160 -0
- package/frontend-vue/tests/form-saved-before-success.test.ts +110 -0
- package/frontend-vue/tests/github-star-prompt.test.ts +328 -0
- package/frontend-vue/tests/header-actions.test.ts +191 -0
- package/frontend-vue/tests/invites-edit-modal.test.ts +157 -0
- package/frontend-vue/tests/layout-banners.test.ts +56 -0
- package/frontend-vue/tests/member-role-picker.test.ts +26 -0
- package/frontend-vue/tests/menu-hidden-page.test.ts +93 -0
- package/frontend-vue/tests/nav-badge-tones.test.ts +274 -0
- package/frontend-vue/tests/nav-card-badge.test.ts +69 -0
- package/frontend-vue/tests/nav-card-grid-empty-category.test.ts +163 -0
- package/frontend-vue/tests/notification-popover-errors.test.ts +71 -37
- package/frontend-vue/tests/notification-preferences-groups.test.ts +268 -0
- package/frontend-vue/tests/notification-tone-contract.test.ts +70 -0
- package/frontend-vue/tests/page-fill-height.test.ts +9 -1
- package/frontend-vue/tests/page-no-visible-blocks.test.ts +202 -0
- package/frontend-vue/tests/profile-preferences-summary.test.ts +26 -2
- package/frontend-vue/tests/profile-security-summary.test.ts +121 -0
- package/frontend-vue/tests/role-permission-tree.test.ts +102 -8
- package/frontend-vue/tests/role-permissions.test.ts +178 -56
- package/frontend-vue/tests/side-panels.test.ts +470 -0
- package/frontend-vue/tests/signup-invitation-link.test.ts +71 -2
- package/frontend-vue/tests/table-actions-column-width.test.ts +51 -1
- package/frontend-vue/tests/table-cell-sublines.test.ts +466 -0
- package/frontend-vue/tests/table-metric-cells.test.ts +4 -0
- package/frontend-vue/tests/table-view-chrome.test.ts +2 -2
- package/frontend-vue/tests/vue-inventory.test.ts +1 -1
- package/package.json +2 -2
- package/skills/dms/REFERENCE.md +1 -1
- package/skills/dms/SKILL.md +7 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { afterEach, beforeEach, expect, it, vi } from "vitest";
|
|
3
|
+
import {
|
|
4
|
+
computed,
|
|
5
|
+
createApp,
|
|
6
|
+
defineComponent,
|
|
7
|
+
h,
|
|
8
|
+
nextTick,
|
|
9
|
+
onMounted,
|
|
10
|
+
ref,
|
|
11
|
+
type App,
|
|
12
|
+
} from "vue";
|
|
13
|
+
import ProfileSecuritySummary from "../layers/dms-layout/app/build/components/pages/settings/profile/ProfileSecuritySummary.vue";
|
|
14
|
+
|
|
15
|
+
// The profile's "Sign-in and security" row takes the tone of the Security
|
|
16
|
+
// page's navigation badge, the one the server weighs what needs attention
|
|
17
|
+
// with: red when the backup codes run low, amber for two-factor off or codes
|
|
18
|
+
// not saved, quiet when nothing needs attention.
|
|
19
|
+
|
|
20
|
+
const overview = ref<Record<string, unknown> | null>(null);
|
|
21
|
+
const attention = ref<string[]>([]);
|
|
22
|
+
const attentionTone = ref<string | undefined>(undefined);
|
|
23
|
+
|
|
24
|
+
vi.mock(
|
|
25
|
+
"../layers/dms-layout/app/build/composables/settings/security/useSecurityOverview",
|
|
26
|
+
() => ({
|
|
27
|
+
SECURITY_PAGE_PATH: "/settings/user/security",
|
|
28
|
+
useSecurityOverview: () => ({
|
|
29
|
+
overview,
|
|
30
|
+
attention,
|
|
31
|
+
attentionTone,
|
|
32
|
+
isUnavailable: ref(false),
|
|
33
|
+
refresh: vi.fn(),
|
|
34
|
+
}),
|
|
35
|
+
}),
|
|
36
|
+
);
|
|
37
|
+
vi.mock("#dms-ui/app/components/icon-well/IconWell.vue", async () => {
|
|
38
|
+
const { defineComponent, h } = await import("vue");
|
|
39
|
+
return {
|
|
40
|
+
default: defineComponent({
|
|
41
|
+
props: { icon: String, tone: String },
|
|
42
|
+
setup: (props) => () =>
|
|
43
|
+
h("span", { "data-icon": props.icon, "data-tone": props.tone }),
|
|
44
|
+
}),
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
let app: App | undefined;
|
|
49
|
+
let host: HTMLDivElement;
|
|
50
|
+
|
|
51
|
+
const OVERVIEW = {
|
|
52
|
+
activeSessions: 9,
|
|
53
|
+
twoFactor: { methods: ["totp"] },
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const wellTone = () =>
|
|
57
|
+
host.querySelector("[data-icon]")?.getAttribute("data-tone");
|
|
58
|
+
|
|
59
|
+
function show(items: string[], tone: string | undefined): void {
|
|
60
|
+
overview.value = OVERVIEW;
|
|
61
|
+
attention.value = items;
|
|
62
|
+
attentionTone.value = tone;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
beforeEach(() => {
|
|
66
|
+
overview.value = null;
|
|
67
|
+
attention.value = [];
|
|
68
|
+
attentionTone.value = undefined;
|
|
69
|
+
Object.entries({ computed, onMounted }).forEach(([key, value]) =>
|
|
70
|
+
vi.stubGlobal(key, value),
|
|
71
|
+
);
|
|
72
|
+
vi.stubGlobal("useI18n", () => ({
|
|
73
|
+
t: (key: string) => key,
|
|
74
|
+
locale: ref("en-GB"),
|
|
75
|
+
}));
|
|
76
|
+
host = document.createElement("div");
|
|
77
|
+
document.body.append(host);
|
|
78
|
+
app = createApp(ProfileSecuritySummary);
|
|
79
|
+
app.component(
|
|
80
|
+
"USkeleton",
|
|
81
|
+
defineComponent({ setup: () => () => h("span", { "data-skeleton": "" }) }),
|
|
82
|
+
);
|
|
83
|
+
app.component("UButton", defineComponent({ setup: () => () => h("a") }));
|
|
84
|
+
app.mount(host);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
afterEach(() => {
|
|
88
|
+
app?.unmount();
|
|
89
|
+
app = undefined;
|
|
90
|
+
host.remove();
|
|
91
|
+
vi.unstubAllGlobals();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("turns red when the server weighs the attention an error", async () => {
|
|
95
|
+
show(["backup_codes_low", "backup_codes_unsaved"], "error");
|
|
96
|
+
await nextTick();
|
|
97
|
+
expect(wellTone()).toBe("error");
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("stays amber for two-factor off", async () => {
|
|
101
|
+
show(["two_factor_off"], "warning");
|
|
102
|
+
await nextTick();
|
|
103
|
+
expect(wellTone()).toBe("warning");
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("is quiet when nothing needs attention", async () => {
|
|
107
|
+
show([], undefined);
|
|
108
|
+
await nextTick();
|
|
109
|
+
expect(wellTone()).toBe("muted");
|
|
110
|
+
expect(host.querySelector("[data-icon]")?.getAttribute("data-icon")).toBe(
|
|
111
|
+
"i-ph-shield-check",
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("names every point that needs attention, not only the first", async () => {
|
|
116
|
+
show(["backup_codes_low", "backup_codes_unsaved"], "error");
|
|
117
|
+
await nextTick();
|
|
118
|
+
expect(host.textContent).toContain(
|
|
119
|
+
"page.settings.profile.security_attention — page.settings.security.attention.backup_codes_low and page.settings.security.attention.backup_codes_unsaved.",
|
|
120
|
+
);
|
|
121
|
+
});
|
|
@@ -132,10 +132,10 @@ beforeAll(async () => {
|
|
|
132
132
|
|
|
133
133
|
afterEach(() => app?.unmount());
|
|
134
134
|
|
|
135
|
-
function mountTree() {
|
|
135
|
+
function mountTree(tree = TREE, selection = new Set<string>()) {
|
|
136
136
|
const host = document.createElement("div");
|
|
137
|
-
const index = helpers.buildPermissionIndex(
|
|
138
|
-
const areas = helpers.buildPermissionAreas(
|
|
137
|
+
const index = helpers.buildPermissionIndex(tree);
|
|
138
|
+
const areas = helpers.buildPermissionAreas(tree, (label) => label);
|
|
139
139
|
const expanded = ref(new Set<string>());
|
|
140
140
|
const toggles: Array<[string, boolean]> = [];
|
|
141
141
|
app = createApp({
|
|
@@ -143,7 +143,6 @@ function mountTree() {
|
|
|
143
143
|
h(RolePermissionTree, {
|
|
144
144
|
areas,
|
|
145
145
|
index,
|
|
146
|
-
selection: new Set<string>(),
|
|
147
146
|
saved: new Set<string>(),
|
|
148
147
|
autoAdded: new Map(),
|
|
149
148
|
expanded: expanded.value,
|
|
@@ -151,6 +150,7 @@ function mountTree() {
|
|
|
151
150
|
query: "",
|
|
152
151
|
canGrant: () => true,
|
|
153
152
|
readonly: false,
|
|
153
|
+
selection,
|
|
154
154
|
onToggle: (id: string, checked: boolean) => toggles.push([id, checked]),
|
|
155
155
|
"onToggle-area": (id: string) => {
|
|
156
156
|
const next = new Set(expanded.value);
|
|
@@ -292,10 +292,19 @@ const slotStub = defineComponent({
|
|
|
292
292
|
h("div", slots.default?.()),
|
|
293
293
|
});
|
|
294
294
|
|
|
295
|
-
|
|
295
|
+
// DmsBanner: its title and description as text.
|
|
296
|
+
const BannerStub = defineComponent({
|
|
297
|
+
props: { title: String, description: String },
|
|
298
|
+
setup:
|
|
299
|
+
(props, { attrs }) =>
|
|
300
|
+
() =>
|
|
301
|
+
h("div", attrs, `${props.title} ${props.description}`),
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
function mountEditor(tree = TREE, selection = new Set<string>()) {
|
|
296
305
|
const host = document.createElement("div");
|
|
297
|
-
const index = helpers.buildPermissionIndex(
|
|
298
|
-
const areas = helpers.buildPermissionAreas(
|
|
306
|
+
const index = helpers.buildPermissionIndex(tree);
|
|
307
|
+
const areas = helpers.buildPermissionAreas(tree, (label) => label);
|
|
299
308
|
app = createApp({
|
|
300
309
|
setup: () => () =>
|
|
301
310
|
h(RoleEditor, {
|
|
@@ -304,7 +313,7 @@ function mountEditor() {
|
|
|
304
313
|
members: [],
|
|
305
314
|
areas,
|
|
306
315
|
index,
|
|
307
|
-
selection
|
|
316
|
+
selection,
|
|
308
317
|
saved: new Set<string>(),
|
|
309
318
|
autoAdded: new Map(),
|
|
310
319
|
totalPermissions: index.allIds.length,
|
|
@@ -328,6 +337,7 @@ function mountEditor() {
|
|
|
328
337
|
app.component("DmsMeter", stub("span"));
|
|
329
338
|
app.component("DmsIconWell", stub("span"));
|
|
330
339
|
app.component("DmsSaveBar", stub("div"));
|
|
340
|
+
app.component("DmsBanner", BannerStub);
|
|
331
341
|
app.mount(host);
|
|
332
342
|
return { host };
|
|
333
343
|
}
|
|
@@ -468,3 +478,87 @@ describe("role editor level buttons", () => {
|
|
|
468
478
|
expect(levelButton(host, "collapse").disabled).toBe(false);
|
|
469
479
|
});
|
|
470
480
|
});
|
|
481
|
+
|
|
482
|
+
const WARNING = "$page.settings.roles.warning.members";
|
|
483
|
+
const WARNED_TREE: RolePermissionNode[] = [
|
|
484
|
+
{
|
|
485
|
+
id: "settings",
|
|
486
|
+
label: "Settings",
|
|
487
|
+
children: [
|
|
488
|
+
{
|
|
489
|
+
id: "settings.members",
|
|
490
|
+
label: "Members",
|
|
491
|
+
children: [
|
|
492
|
+
{
|
|
493
|
+
id: "settings.members.table",
|
|
494
|
+
label: "Members table",
|
|
495
|
+
children: [
|
|
496
|
+
{ id: "settings.members.table.list", label: "List" },
|
|
497
|
+
{
|
|
498
|
+
id: "settings.members.table.edit",
|
|
499
|
+
label: "Edit",
|
|
500
|
+
warning: WARNING,
|
|
501
|
+
},
|
|
502
|
+
],
|
|
503
|
+
},
|
|
504
|
+
],
|
|
505
|
+
},
|
|
506
|
+
],
|
|
507
|
+
},
|
|
508
|
+
];
|
|
509
|
+
const WITHOUT_EDIT = [
|
|
510
|
+
"settings",
|
|
511
|
+
"settings.members",
|
|
512
|
+
"settings.members.table",
|
|
513
|
+
"settings.members.table.list",
|
|
514
|
+
];
|
|
515
|
+
const ALL_WARNED = new Set([...WITHOUT_EDIT, "settings.members.table.edit"]);
|
|
516
|
+
|
|
517
|
+
const textOf = (host: HTMLElement, selector: string) =>
|
|
518
|
+
[...host.querySelectorAll(selector)].map((element) =>
|
|
519
|
+
element.textContent?.trim(),
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
describe("owner-level warnings in the roles editor", () => {
|
|
523
|
+
it("shows a permission's warning on its row, ticked or not", async () => {
|
|
524
|
+
const { host } = mountTree(WARNED_TREE);
|
|
525
|
+
caretOf(host, "settings.members").click();
|
|
526
|
+
await nextTick();
|
|
527
|
+
caretOf(host, "settings.members.table").click();
|
|
528
|
+
await nextTick();
|
|
529
|
+
|
|
530
|
+
expect(
|
|
531
|
+
textOf(
|
|
532
|
+
rowOf(host, "settings.members.table.edit"),
|
|
533
|
+
"[data-permission-warning]",
|
|
534
|
+
),
|
|
535
|
+
).toEqual([WARNING]);
|
|
536
|
+
expect(
|
|
537
|
+
host.querySelectorAll("[data-permission-warning-below]"),
|
|
538
|
+
).toHaveLength(0);
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
it("flags the closed row hiding a warned permission a parent ticked", async () => {
|
|
542
|
+
const { host } = mountTree(WARNED_TREE, ALL_WARNED);
|
|
543
|
+
const below = (id: string) =>
|
|
544
|
+
rowOf(host, id).querySelector("[data-permission-warning-below]");
|
|
545
|
+
expect(below("settings.members")?.getAttribute("title")).toBe(WARNING);
|
|
546
|
+
|
|
547
|
+
caretOf(host, "settings.members").click();
|
|
548
|
+
await nextTick();
|
|
549
|
+
expect(below("settings.members")).toBeNull();
|
|
550
|
+
expect(below("settings.members.table")).not.toBeNull();
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
it("sums up in the editor the warned permissions the role holds", () => {
|
|
554
|
+
const { host } = mountEditor(WARNED_TREE, ALL_WARNED);
|
|
555
|
+
expect(textOf(host, "[data-role-owner-level]")).toEqual([
|
|
556
|
+
"page.settings.roles.editor.owner_level_title page.settings.roles.editor.owner_level_description Members › Edit",
|
|
557
|
+
]);
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
it("says nothing while the role holds none of them", () => {
|
|
561
|
+
const { host } = mountEditor(WARNED_TREE, new Set(WITHOUT_EDIT));
|
|
562
|
+
expect(host.querySelector("[data-role-owner-level]")).toBeNull();
|
|
563
|
+
});
|
|
564
|
+
});
|
|
@@ -10,13 +10,14 @@ import {
|
|
|
10
10
|
expandOneLevel,
|
|
11
11
|
grantPermission,
|
|
12
12
|
highlightSegments,
|
|
13
|
-
idPrefixes,
|
|
14
13
|
nextCollapseDepth,
|
|
15
14
|
nextExpandDepth,
|
|
16
15
|
openDepth,
|
|
17
16
|
type PermissionIndex,
|
|
18
17
|
revokePermission,
|
|
19
18
|
searchPermissions,
|
|
19
|
+
selectedWarningLabels,
|
|
20
|
+
selectedWarningsBelow,
|
|
20
21
|
selectionState,
|
|
21
22
|
} from "../layers/dms-layout/app/build/components/pages/settings/roles/role-permissions";
|
|
22
23
|
import type { RolePermissionNode } from "../layers/dms-layout/app/build/components/pages/settings/roles/role-types";
|
|
@@ -56,15 +57,20 @@ const TREE: RolePermissionNode[] = [
|
|
|
56
57
|
label: "User settings",
|
|
57
58
|
children: [
|
|
58
59
|
{
|
|
59
|
-
id: "settings.
|
|
60
|
+
id: "settings.user.roles",
|
|
60
61
|
label: "Roles",
|
|
61
62
|
children: [
|
|
62
63
|
{
|
|
63
|
-
id: "settings.
|
|
64
|
+
id: "settings.user.roles.table",
|
|
64
65
|
label: "Roles list",
|
|
65
66
|
children: [
|
|
66
|
-
{ id: "settings.
|
|
67
|
-
{
|
|
67
|
+
{ id: "settings.user.roles.table.list", label: "List" },
|
|
68
|
+
{
|
|
69
|
+
id: "settings.user.roles.table.edit",
|
|
70
|
+
label: "Edit",
|
|
71
|
+
dependencies: ["settings.user.roles.table.view"],
|
|
72
|
+
},
|
|
73
|
+
{ id: "settings.user.roles.table.view", label: "View" },
|
|
68
74
|
],
|
|
69
75
|
},
|
|
70
76
|
],
|
|
@@ -194,6 +200,15 @@ function seeded(seed: number): () => number {
|
|
|
194
200
|
|
|
195
201
|
const sorted = (ids: Iterable<string>) => [...new Set(ids)].sort();
|
|
196
202
|
|
|
203
|
+
function withoutDependencies(
|
|
204
|
+
nodes: RolePermissionNode[],
|
|
205
|
+
): RolePermissionNode[] {
|
|
206
|
+
return nodes.map(({ dependencies: _dependencies, children, ...node }) => ({
|
|
207
|
+
...node,
|
|
208
|
+
...(children ? { children: withoutDependencies(children) } : {}),
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
|
|
197
212
|
describe("role permissions", () => {
|
|
198
213
|
const index = buildPermissionIndex(TREE);
|
|
199
214
|
|
|
@@ -217,25 +232,16 @@ describe("role permissions", () => {
|
|
|
217
232
|
// without children (`media.upload.form`, `examples`) never open.
|
|
218
233
|
expect(levels).toEqual([
|
|
219
234
|
["pages.sales", "settings.user"],
|
|
220
|
-
[
|
|
221
|
-
|
|
222
|
-
"settings.workspace.roles",
|
|
223
|
-
"settings.user.profile",
|
|
224
|
-
],
|
|
225
|
-
["settings.workspace.roles.table"],
|
|
235
|
+
["pages.sales.orders", "settings.user.roles", "settings.user.profile"],
|
|
236
|
+
["settings.user.roles.table"],
|
|
226
237
|
]);
|
|
227
|
-
expect(parents.get("settings.
|
|
228
|
-
"settings.
|
|
238
|
+
expect(parents.get("settings.user.roles.table")).toBe(
|
|
239
|
+
"settings.user.roles",
|
|
229
240
|
);
|
|
230
241
|
expect(parents.has("settings.user")).toBe(false);
|
|
231
242
|
});
|
|
232
243
|
|
|
233
|
-
it("
|
|
234
|
-
expect(idPrefixes("a.b.c")).toEqual(["a.b.c", "a.b", "a"]);
|
|
235
|
-
expect(idPrefixes("pages")).toEqual(["pages"]);
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it("grants a permission with the ids it sits under, not its dependencies", () => {
|
|
244
|
+
it("grants a permission with the nodes above it and what it depends on", () => {
|
|
239
245
|
const grant = grantPermission(
|
|
240
246
|
index,
|
|
241
247
|
new Set(),
|
|
@@ -246,23 +252,47 @@ describe("role permissions", () => {
|
|
|
246
252
|
"pages",
|
|
247
253
|
"pages.sales",
|
|
248
254
|
"pages.sales.orders",
|
|
255
|
+
"pages.sales.orders.read",
|
|
249
256
|
"pages.sales.orders.refund",
|
|
250
257
|
]);
|
|
251
258
|
expect(sorted(grant.autoAdded)).toEqual([
|
|
252
259
|
"pages",
|
|
253
260
|
"pages.sales",
|
|
254
261
|
"pages.sales.orders",
|
|
262
|
+
"pages.sales.orders.read",
|
|
255
263
|
]);
|
|
256
264
|
});
|
|
257
265
|
|
|
258
|
-
it("grants
|
|
266
|
+
it("grants a table's view with its edit, where the form loads the row", () => {
|
|
267
|
+
const grant = grantPermission(
|
|
268
|
+
index,
|
|
269
|
+
new Set(),
|
|
270
|
+
"settings.user.roles.table.edit",
|
|
271
|
+
anyone,
|
|
272
|
+
);
|
|
273
|
+
expect(grant.selection.has("settings.user.roles.table.view")).toBe(true);
|
|
274
|
+
expect(grant.autoAdded).toContain("settings.user.roles.table.view");
|
|
275
|
+
expect(grant.selection.has("settings.user.roles.table.list")).toBe(false);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it("leaves a dependency the user may not grant", () => {
|
|
279
|
+
const grant = grantPermission(
|
|
280
|
+
index,
|
|
281
|
+
new Set(),
|
|
282
|
+
"pages.sales.orders.refund",
|
|
283
|
+
(id) => id !== "pages.sales.orders.read",
|
|
284
|
+
);
|
|
285
|
+
expect(grant.selection.has("pages.sales.orders.read")).toBe(false);
|
|
286
|
+
expect(grant.selection.has("pages.sales.orders.refund")).toBe(true);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it("leaves the unregistered id a lifted permission sits under to the server", () => {
|
|
259
290
|
const grant = grantPermission(index, new Set(), "media.upload", anyone);
|
|
291
|
+
// `media` is no node of the tree: the server adds it when the role is saved.
|
|
260
292
|
expect(sorted(grant.selection)).toEqual([
|
|
261
|
-
"media",
|
|
262
293
|
"media.upload",
|
|
263
294
|
"media.upload.form",
|
|
264
295
|
]);
|
|
265
|
-
// Not a node: no "added automatically" hint to label.
|
|
266
296
|
expect(grant.autoAdded).toEqual([]);
|
|
267
297
|
});
|
|
268
298
|
|
|
@@ -277,18 +307,35 @@ describe("role permissions", () => {
|
|
|
277
307
|
expect(grant.selection.has("pages.sales.orders.read")).toBe(true);
|
|
278
308
|
});
|
|
279
309
|
|
|
280
|
-
it("revokes
|
|
310
|
+
it("revokes what depends on a revoked permission, then the emptied ancestors", () => {
|
|
281
311
|
const all = new Set(index.allIds);
|
|
282
312
|
const afterRead = revokePermission(index, all, "pages.sales.orders.read");
|
|
283
|
-
expect(afterRead.has("pages.sales.orders.refund")).toBe(
|
|
284
|
-
expect(afterRead.has("pages.sales.orders")).toBe(
|
|
285
|
-
|
|
313
|
+
expect(afterRead.has("pages.sales.orders.refund")).toBe(false);
|
|
314
|
+
expect(afterRead.has("pages.sales.orders")).toBe(false);
|
|
315
|
+
expect(afterRead.has("pages.sales")).toBe(true);
|
|
316
|
+
const afterRefund = revokePermission(
|
|
286
317
|
index,
|
|
287
|
-
|
|
318
|
+
all,
|
|
288
319
|
"pages.sales.orders.refund",
|
|
289
320
|
);
|
|
290
|
-
expect(
|
|
291
|
-
expect(
|
|
321
|
+
expect(afterRefund.has("pages.sales.orders.read")).toBe(true);
|
|
322
|
+
expect(afterRefund.has("pages.sales.orders")).toBe(true);
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
it("revokes a table's edit with its view", () => {
|
|
326
|
+
const granted = grantPermission(
|
|
327
|
+
index,
|
|
328
|
+
new Set(),
|
|
329
|
+
"settings.user.roles.table.edit",
|
|
330
|
+
anyone,
|
|
331
|
+
).selection;
|
|
332
|
+
const revoked = revokePermission(
|
|
333
|
+
index,
|
|
334
|
+
new Set([...granted, "settings.user.roles.table.list"]),
|
|
335
|
+
"settings.user.roles.table.view",
|
|
336
|
+
);
|
|
337
|
+
expect(revoked.has("settings.user.roles.table.edit")).toBe(false);
|
|
338
|
+
expect(revoked.has("settings.user.roles.table.list")).toBe(true);
|
|
292
339
|
});
|
|
293
340
|
|
|
294
341
|
it("judges every ancestor before dropping any, like the original form", () => {
|
|
@@ -297,18 +344,18 @@ describe("role permissions", () => {
|
|
|
297
344
|
new Set([
|
|
298
345
|
"settings",
|
|
299
346
|
"settings.user",
|
|
300
|
-
"settings.
|
|
301
|
-
"settings.
|
|
302
|
-
"settings.
|
|
347
|
+
"settings.user.roles",
|
|
348
|
+
"settings.user.roles.table",
|
|
349
|
+
"settings.user.roles.table.list",
|
|
303
350
|
]),
|
|
304
|
-
"settings.
|
|
351
|
+
"settings.user.roles.table.list",
|
|
305
352
|
);
|
|
306
|
-
// Only `settings.
|
|
353
|
+
// Only `settings.user.roles.table` is judged emptied: the ancestors above
|
|
307
354
|
// it still saw it selected, so they stay.
|
|
308
355
|
expect(sorted(next)).toEqual([
|
|
309
356
|
"settings",
|
|
310
357
|
"settings.user",
|
|
311
|
-
"settings.
|
|
358
|
+
"settings.user.roles",
|
|
312
359
|
]);
|
|
313
360
|
});
|
|
314
361
|
|
|
@@ -349,9 +396,12 @@ describe("role permissions", () => {
|
|
|
349
396
|
).toBe(false);
|
|
350
397
|
});
|
|
351
398
|
|
|
352
|
-
it("stores
|
|
399
|
+
it("stores what the original form stored for the same clicks", () => {
|
|
400
|
+
// The original form knew no dependencies: the editor matches it on a
|
|
401
|
+
// tree that declares none.
|
|
402
|
+
const plain = buildPermissionIndex(withoutDependencies(TREE));
|
|
353
403
|
const random = seeded(20261001);
|
|
354
|
-
const ids =
|
|
404
|
+
const ids = plain.allIds;
|
|
355
405
|
for (let run = 0; run < 200; run++) {
|
|
356
406
|
// Start from arbitrary saved roles, legacy and unknown ids included.
|
|
357
407
|
const start = ids.filter(() => random() < 0.3);
|
|
@@ -360,12 +410,17 @@ describe("role permissions", () => {
|
|
|
360
410
|
let after = new Set(start);
|
|
361
411
|
for (let click = 0; click < 12; click++) {
|
|
362
412
|
const id = ids[Math.floor(random() * ids.length)]!;
|
|
363
|
-
const node =
|
|
413
|
+
const node = plain.nodes.get(id)!;
|
|
364
414
|
const originalState = original.checkbox(before, node);
|
|
365
|
-
expect(checkboxState(
|
|
415
|
+
expect(checkboxState(plain, id, after)).toBe(originalState);
|
|
366
416
|
before = original.check(before, node, clickedValue(originalState));
|
|
367
|
-
after = editorClick(
|
|
368
|
-
|
|
417
|
+
after = editorClick(plain, after, id);
|
|
418
|
+
// Bar the unregistered ids the original form added above a lifted
|
|
419
|
+
// node (`media`), which the server now adds when the role is saved.
|
|
420
|
+
const known = before.filter(
|
|
421
|
+
(kept) => plain.nodes.has(kept) || start.includes(kept),
|
|
422
|
+
);
|
|
423
|
+
expect(sorted(after)).toEqual(sorted(known));
|
|
369
424
|
}
|
|
370
425
|
}
|
|
371
426
|
});
|
|
@@ -409,11 +464,7 @@ describe("role permissions", () => {
|
|
|
409
464
|
expect.arrayContaining([
|
|
410
465
|
["settings", "", "settings"],
|
|
411
466
|
["settings.user", "Settings", "settings.user"],
|
|
412
|
-
[
|
|
413
|
-
"settings.workspace.roles",
|
|
414
|
-
"Settings › User settings",
|
|
415
|
-
"settings.user",
|
|
416
|
-
],
|
|
467
|
+
["settings.user.roles", "Settings › User settings", "settings.user"],
|
|
417
468
|
]),
|
|
418
469
|
);
|
|
419
470
|
});
|
|
@@ -455,15 +506,15 @@ describe("permission tree levels", () => {
|
|
|
455
506
|
"pages.sales.orders",
|
|
456
507
|
"settings.user",
|
|
457
508
|
"settings.user.profile",
|
|
458
|
-
"settings.
|
|
509
|
+
"settings.user.roles",
|
|
459
510
|
],
|
|
460
511
|
[
|
|
461
512
|
"pages.sales",
|
|
462
513
|
"pages.sales.orders",
|
|
463
514
|
"settings.user",
|
|
464
515
|
"settings.user.profile",
|
|
465
|
-
"settings.
|
|
466
|
-
"settings.
|
|
516
|
+
"settings.user.roles",
|
|
517
|
+
"settings.user.roles.table",
|
|
467
518
|
],
|
|
468
519
|
]);
|
|
469
520
|
expect(openDepth(levels, expanded)).toBe(3);
|
|
@@ -487,33 +538,33 @@ describe("permission tree levels", () => {
|
|
|
487
538
|
|
|
488
539
|
it("fills the shallowest incomplete depth of a tree opened by hand", () => {
|
|
489
540
|
// One area and one of its rows opened by hand, the other area closed.
|
|
490
|
-
let expanded = open("settings.user", "settings.
|
|
541
|
+
let expanded = open("settings.user", "settings.user.roles");
|
|
491
542
|
expect(openDepth(levels, expanded)).toBe(0);
|
|
492
543
|
expect(nextExpandDepth(levels, expanded)).toBe(1);
|
|
493
544
|
expanded = expandOneLevel(levels, expanded);
|
|
494
545
|
expect(sorted(expanded)).toEqual([
|
|
495
546
|
"pages.sales",
|
|
496
547
|
"settings.user",
|
|
497
|
-
"settings.
|
|
548
|
+
"settings.user.roles",
|
|
498
549
|
]);
|
|
499
550
|
expect(nextExpandDepth(levels, expanded)).toBe(2);
|
|
500
551
|
// Depth 3 is opened by hand, but depth 2 is still incomplete: it comes first.
|
|
501
552
|
expanded = open(
|
|
502
553
|
"pages.sales",
|
|
503
554
|
"settings.user",
|
|
504
|
-
"settings.
|
|
505
|
-
"settings.
|
|
555
|
+
"settings.user.roles",
|
|
556
|
+
"settings.user.roles.table",
|
|
506
557
|
);
|
|
507
558
|
expect(nextExpandDepth(levels, expanded)).toBe(2);
|
|
508
559
|
expect(openDepth(levels, expanded)).toBe(1);
|
|
509
560
|
});
|
|
510
561
|
|
|
511
562
|
it("collapses the deepest depth shown open, not a hidden open row", () => {
|
|
512
|
-
// `settings.
|
|
563
|
+
// `settings.user.roles.table` is open but hidden under a closed area.
|
|
513
564
|
const expanded = open(
|
|
514
565
|
"pages.sales",
|
|
515
|
-
"settings.
|
|
516
|
-
"settings.
|
|
566
|
+
"settings.user.roles",
|
|
567
|
+
"settings.user.roles.table",
|
|
517
568
|
);
|
|
518
569
|
expect(nextCollapseDepth(levels, expanded)).toBe(1);
|
|
519
570
|
// The hidden open rows below that depth close with it.
|
|
@@ -537,3 +588,74 @@ describe("permission tree levels", () => {
|
|
|
537
588
|
expect(openDepth(flat, open())).toBe(0);
|
|
538
589
|
});
|
|
539
590
|
});
|
|
591
|
+
|
|
592
|
+
describe("owner-level warnings", () => {
|
|
593
|
+
const WARNING = "$warning.members";
|
|
594
|
+
const WARNED: RolePermissionNode[] = [
|
|
595
|
+
{
|
|
596
|
+
id: "settings",
|
|
597
|
+
label: "Settings",
|
|
598
|
+
children: [
|
|
599
|
+
{
|
|
600
|
+
id: "settings.members",
|
|
601
|
+
label: "Members",
|
|
602
|
+
children: [
|
|
603
|
+
{
|
|
604
|
+
id: "settings.members.table",
|
|
605
|
+
label: "Members table",
|
|
606
|
+
children: [
|
|
607
|
+
{ id: "settings.members.table.list", label: "List" },
|
|
608
|
+
{
|
|
609
|
+
id: "settings.members.table.edit",
|
|
610
|
+
label: "Edit",
|
|
611
|
+
warning: WARNING,
|
|
612
|
+
},
|
|
613
|
+
],
|
|
614
|
+
},
|
|
615
|
+
],
|
|
616
|
+
},
|
|
617
|
+
],
|
|
618
|
+
},
|
|
619
|
+
];
|
|
620
|
+
const index = buildPermissionIndex(WARNED);
|
|
621
|
+
const areas = buildPermissionAreas(WARNED, (label) => label);
|
|
622
|
+
|
|
623
|
+
it("tells a closed row the warnings of what it holds selected", () => {
|
|
624
|
+
const granted = grantPermission(
|
|
625
|
+
index,
|
|
626
|
+
new Set(),
|
|
627
|
+
"settings.members",
|
|
628
|
+
() => true,
|
|
629
|
+
).selection;
|
|
630
|
+
|
|
631
|
+
expect(selectedWarningsBelow(index, "settings.members", granted)).toEqual([
|
|
632
|
+
WARNING,
|
|
633
|
+
]);
|
|
634
|
+
expect(
|
|
635
|
+
selectedWarningsBelow(index, "settings.members.table.edit", granted),
|
|
636
|
+
).toEqual([]);
|
|
637
|
+
expect(
|
|
638
|
+
selectedWarningsBelow(
|
|
639
|
+
index,
|
|
640
|
+
"settings.members",
|
|
641
|
+
new Set(["settings.members", "settings.members.table.list"]),
|
|
642
|
+
),
|
|
643
|
+
).toEqual([]);
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
it("names the selected warned permissions under their area", () => {
|
|
647
|
+
const granted = grantPermission(
|
|
648
|
+
index,
|
|
649
|
+
new Set(),
|
|
650
|
+
"settings",
|
|
651
|
+
() => true,
|
|
652
|
+
).selection;
|
|
653
|
+
|
|
654
|
+
expect(
|
|
655
|
+
selectedWarningLabels(index, areas, granted, (label) => label),
|
|
656
|
+
).toEqual(["Members › Edit"]);
|
|
657
|
+
expect(
|
|
658
|
+
selectedWarningLabels(index, areas, new Set(), (label) => label),
|
|
659
|
+
).toEqual([]);
|
|
660
|
+
});
|
|
661
|
+
});
|