nestlens 0.1.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/LICENSE +21 -0
- package/README.md +145 -0
- package/dist/__tests__/api/api.controller.spec.d.ts +2 -0
- package/dist/__tests__/api/api.controller.spec.d.ts.map +1 -0
- package/dist/__tests__/api/api.controller.spec.js +982 -0
- package/dist/__tests__/api/api.controller.spec.js.map +1 -0
- package/dist/__tests__/api/api.guard.spec.d.ts +2 -0
- package/dist/__tests__/api/api.guard.spec.d.ts.map +1 -0
- package/dist/__tests__/api/api.guard.spec.js +572 -0
- package/dist/__tests__/api/api.guard.spec.js.map +1 -0
- package/dist/__tests__/api/dashboard.controller.spec.d.ts +2 -0
- package/dist/__tests__/api/dashboard.controller.spec.d.ts.map +1 -0
- package/dist/__tests__/api/dashboard.controller.spec.js +474 -0
- package/dist/__tests__/api/dashboard.controller.spec.js.map +1 -0
- package/dist/__tests__/api/tag.controller.spec.d.ts +2 -0
- package/dist/__tests__/api/tag.controller.spec.d.ts.map +1 -0
- package/dist/__tests__/api/tag.controller.spec.js +280 -0
- package/dist/__tests__/api/tag.controller.spec.js.map +1 -0
- package/dist/__tests__/collector.service.spec.d.ts +2 -0
- package/dist/__tests__/collector.service.spec.d.ts.map +1 -0
- package/dist/__tests__/collector.service.spec.js +240 -0
- package/dist/__tests__/collector.service.spec.js.map +1 -0
- package/dist/__tests__/core/collector.service.spec.d.ts +2 -0
- package/dist/__tests__/core/collector.service.spec.d.ts.map +1 -0
- package/dist/__tests__/core/collector.service.spec.js +526 -0
- package/dist/__tests__/core/collector.service.spec.js.map +1 -0
- package/dist/__tests__/core/family-hash.service.spec.d.ts +2 -0
- package/dist/__tests__/core/family-hash.service.spec.d.ts.map +1 -0
- package/dist/__tests__/core/family-hash.service.spec.js +1117 -0
- package/dist/__tests__/core/family-hash.service.spec.js.map +1 -0
- package/dist/__tests__/core/pruning.service.spec.d.ts +2 -0
- package/dist/__tests__/core/pruning.service.spec.d.ts.map +1 -0
- package/dist/__tests__/core/pruning.service.spec.js +224 -0
- package/dist/__tests__/core/pruning.service.spec.js.map +1 -0
- package/dist/__tests__/core/storage/sqlite.storage.spec.d.ts +2 -0
- package/dist/__tests__/core/storage/sqlite.storage.spec.d.ts.map +1 -0
- package/dist/__tests__/core/storage/sqlite.storage.spec.js +853 -0
- package/dist/__tests__/core/storage/sqlite.storage.spec.js.map +1 -0
- package/dist/__tests__/core/tag.service.spec.d.ts +2 -0
- package/dist/__tests__/core/tag.service.spec.d.ts.map +1 -0
- package/dist/__tests__/core/tag.service.spec.js +994 -0
- package/dist/__tests__/core/tag.service.spec.js.map +1 -0
- package/dist/__tests__/family-hash.service.spec.d.ts +2 -0
- package/dist/__tests__/family-hash.service.spec.d.ts.map +1 -0
- package/dist/__tests__/family-hash.service.spec.js +325 -0
- package/dist/__tests__/family-hash.service.spec.js.map +1 -0
- package/dist/__tests__/filters/api-filters.spec.d.ts +2 -0
- package/dist/__tests__/filters/api-filters.spec.d.ts.map +1 -0
- package/dist/__tests__/filters/api-filters.spec.js +172 -0
- package/dist/__tests__/filters/api-filters.spec.js.map +1 -0
- package/dist/__tests__/filters/entry-factories.d.ts +20 -0
- package/dist/__tests__/filters/entry-factories.d.ts.map +1 -0
- package/dist/__tests__/filters/entry-factories.js +288 -0
- package/dist/__tests__/filters/entry-factories.js.map +1 -0
- package/dist/__tests__/filters/filter-contract.spec.d.ts +2 -0
- package/dist/__tests__/filters/filter-contract.spec.d.ts.map +1 -0
- package/dist/__tests__/filters/filter-contract.spec.js +230 -0
- package/dist/__tests__/filters/filter-contract.spec.js.map +1 -0
- package/dist/__tests__/filters/filter-test-data.d.ts +26 -0
- package/dist/__tests__/filters/filter-test-data.d.ts.map +1 -0
- package/dist/__tests__/filters/filter-test-data.js +374 -0
- package/dist/__tests__/filters/filter-test-data.js.map +1 -0
- package/dist/__tests__/filters/storage-filters.spec.d.ts +2 -0
- package/dist/__tests__/filters/storage-filters.spec.d.ts.map +1 -0
- package/dist/__tests__/filters/storage-filters.spec.js +699 -0
- package/dist/__tests__/filters/storage-filters.spec.js.map +1 -0
- package/dist/__tests__/filters/test-utils.d.ts +23 -0
- package/dist/__tests__/filters/test-utils.d.ts.map +1 -0
- package/dist/__tests__/filters/test-utils.js +54 -0
- package/dist/__tests__/filters/test-utils.js.map +1 -0
- package/dist/__tests__/nestlens.module.spec.d.ts +2 -0
- package/dist/__tests__/nestlens.module.spec.d.ts.map +1 -0
- package/dist/__tests__/nestlens.module.spec.js +620 -0
- package/dist/__tests__/nestlens.module.spec.js.map +1 -0
- package/dist/__tests__/pruning.service.spec.d.ts +2 -0
- package/dist/__tests__/pruning.service.spec.d.ts.map +1 -0
- package/dist/__tests__/pruning.service.spec.js +142 -0
- package/dist/__tests__/pruning.service.spec.js.map +1 -0
- package/dist/__tests__/setup.d.ts +7 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/setup.js +24 -0
- package/dist/__tests__/setup.js.map +1 -0
- package/dist/__tests__/tag.service.spec.d.ts +2 -0
- package/dist/__tests__/tag.service.spec.d.ts.map +1 -0
- package/dist/__tests__/tag.service.spec.js +482 -0
- package/dist/__tests__/tag.service.spec.js.map +1 -0
- package/dist/__tests__/watchers/batch.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/batch.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/batch.watcher.spec.js +515 -0
- package/dist/__tests__/watchers/batch.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/cache.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/cache.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/cache.watcher.spec.js +395 -0
- package/dist/__tests__/watchers/cache.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/command.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/command.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/command.watcher.spec.js +598 -0
- package/dist/__tests__/watchers/command.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/dump.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/dump.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/dump.watcher.spec.js +724 -0
- package/dist/__tests__/watchers/dump.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/event.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/event.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/event.watcher.spec.js +316 -0
- package/dist/__tests__/watchers/event.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/exception.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/exception.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/exception.watcher.spec.js +495 -0
- package/dist/__tests__/watchers/exception.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/gate.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/gate.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/gate.watcher.spec.js +683 -0
- package/dist/__tests__/watchers/gate.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/http-client.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/http-client.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/http-client.watcher.spec.js +888 -0
- package/dist/__tests__/watchers/http-client.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/job.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/job.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/job.watcher.spec.js +513 -0
- package/dist/__tests__/watchers/job.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/log.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/log.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/log.watcher.spec.js +428 -0
- package/dist/__tests__/watchers/log.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/mail.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/mail.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/mail.watcher.spec.js +425 -0
- package/dist/__tests__/watchers/mail.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/model.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/model.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/model.watcher.spec.js +675 -0
- package/dist/__tests__/watchers/model.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/notification.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/notification.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/notification.watcher.spec.js +595 -0
- package/dist/__tests__/watchers/notification.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/query/types.spec.d.ts +2 -0
- package/dist/__tests__/watchers/query/types.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/query/types.spec.js +292 -0
- package/dist/__tests__/watchers/query/types.spec.js.map +1 -0
- package/dist/__tests__/watchers/query.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/query.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/query.watcher.spec.js +597 -0
- package/dist/__tests__/watchers/query.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/redis.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/redis.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/redis.watcher.spec.js +634 -0
- package/dist/__tests__/watchers/redis.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/request.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/request.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/request.watcher.spec.js +1017 -0
- package/dist/__tests__/watchers/request.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/schedule.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/schedule.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/schedule.watcher.spec.js +338 -0
- package/dist/__tests__/watchers/schedule.watcher.spec.js.map +1 -0
- package/dist/__tests__/watchers/view.watcher.spec.d.ts +2 -0
- package/dist/__tests__/watchers/view.watcher.spec.d.ts.map +1 -0
- package/dist/__tests__/watchers/view.watcher.spec.js +564 -0
- package/dist/__tests__/watchers/view.watcher.spec.js.map +1 -0
- package/dist/api/api.controller.d.ts +193 -0
- package/dist/api/api.controller.d.ts.map +1 -0
- package/dist/api/api.controller.js +562 -0
- package/dist/api/api.controller.js.map +1 -0
- package/dist/api/api.guard.d.ts +77 -0
- package/dist/api/api.guard.d.ts.map +1 -0
- package/dist/api/api.guard.js +294 -0
- package/dist/api/api.guard.js.map +1 -0
- package/dist/api/dashboard.controller.d.ts +49 -0
- package/dist/api/dashboard.controller.d.ts.map +1 -0
- package/dist/api/dashboard.controller.js +472 -0
- package/dist/api/dashboard.controller.js.map +1 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +21 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/tag.controller.d.ts +65 -0
- package/dist/api/tag.controller.d.ts.map +1 -0
- package/dist/api/tag.controller.js +149 -0
- package/dist/api/tag.controller.js.map +1 -0
- package/dist/core/collector.service.d.ts +80 -0
- package/dist/core/collector.service.d.ts.map +1 -0
- package/dist/core/collector.service.js +255 -0
- package/dist/core/collector.service.js.map +1 -0
- package/dist/core/family-hash.service.d.ts +64 -0
- package/dist/core/family-hash.service.d.ts.map +1 -0
- package/dist/core/family-hash.service.js +281 -0
- package/dist/core/family-hash.service.js.map +1 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +20 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/pruning.service.d.ts +16 -0
- package/dist/core/pruning.service.d.ts.map +1 -0
- package/dist/core/pruning.service.js +71 -0
- package/dist/core/pruning.service.js.map +1 -0
- package/dist/core/storage/index.d.ts +3 -0
- package/dist/core/storage/index.d.ts.map +1 -0
- package/dist/core/storage/index.js +19 -0
- package/dist/core/storage/index.js.map +1 -0
- package/dist/core/storage/sqlite.storage.d.ts +60 -0
- package/dist/core/storage/sqlite.storage.d.ts.map +1 -0
- package/dist/core/storage/sqlite.storage.js +929 -0
- package/dist/core/storage/sqlite.storage.js.map +1 -0
- package/dist/core/storage/storage.interface.d.ts +122 -0
- package/dist/core/storage/storage.interface.d.ts.map +1 -0
- package/dist/core/storage/storage.interface.js +5 -0
- package/dist/core/storage/storage.interface.js.map +1 -0
- package/dist/core/tag.service.d.ts +71 -0
- package/dist/core/tag.service.d.ts.map +1 -0
- package/dist/core/tag.service.js +568 -0
- package/dist/core/tag.service.js.map +1 -0
- package/dist/dashboard/public/assets/BatchesPage-DFT4fKlJ.js +1 -0
- package/dist/dashboard/public/assets/CachePage-CRy1Tjb8.js +1 -0
- package/dist/dashboard/public/assets/ClickableBadge-CV5J3THx.js +1 -0
- package/dist/dashboard/public/assets/CommandsPage-DdRnTm-W.js +1 -0
- package/dist/dashboard/public/assets/DashboardPage-CjaRZXYy.js +26 -0
- package/dist/dashboard/public/assets/DataTable-B6o9H8lh.js +88 -0
- package/dist/dashboard/public/assets/DumpsPage-DO8y1RTg.js +1 -0
- package/dist/dashboard/public/assets/EntryDetailPage-By-YcAGL.js +125 -0
- package/dist/dashboard/public/assets/EventsPage-u-r4AiT4.js +1 -0
- package/dist/dashboard/public/assets/ExceptionsPage-DXUcARr1.js +6 -0
- package/dist/dashboard/public/assets/GatesPage-DpeP7CDZ.js +1 -0
- package/dist/dashboard/public/assets/HttpClientPage-BJ4-5E6t.js +1 -0
- package/dist/dashboard/public/assets/JobsPage-Dv3KaX2x.js +1 -0
- package/dist/dashboard/public/assets/LogsPage-D0Q3yDb1.js +1 -0
- package/dist/dashboard/public/assets/MailPage-Bf8C6WF6.js +1 -0
- package/dist/dashboard/public/assets/ModelsPage-BMHncI5y.js +1 -0
- package/dist/dashboard/public/assets/NotificationsPage-D5-I-Oxb.js +1 -0
- package/dist/dashboard/public/assets/QueriesPage-oNp0i6Gt.js +1 -0
- package/dist/dashboard/public/assets/RedisPage-_GeS2OD8.js +1 -0
- package/dist/dashboard/public/assets/RequestsPage-BCwqu9US.js +1 -0
- package/dist/dashboard/public/assets/SchedulePage-CR0P-oX6.js +1 -0
- package/dist/dashboard/public/assets/ViewsPage-Dsy5ECRA.js +1 -0
- package/dist/dashboard/public/assets/calendar-DfK3x-6B.js +6 -0
- package/dist/dashboard/public/assets/circle-check-big-DcsYW8y8.js +6 -0
- package/dist/dashboard/public/assets/format-BFldcnCk.js +1 -0
- package/dist/dashboard/public/assets/index-DmeA1maE.css +1 -0
- package/dist/dashboard/public/assets/index-rkbGYdU7.js +351 -0
- package/dist/dashboard/public/assets/types-Cldoe2db.js +1 -0
- package/dist/dashboard/public/assets/vendor-B2nVRih0.js +43 -0
- package/dist/dashboard/public/assets/zap-DqtRi0JM.js +6 -0
- package/dist/dashboard/public/index.html +15 -0
- package/dist/dashboard/public/nestlens-icon.svg +9 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/dist/nestlens.config.d.ts +216 -0
- package/dist/nestlens.config.d.ts.map +1 -0
- package/dist/nestlens.config.js +57 -0
- package/dist/nestlens.config.js.map +1 -0
- package/dist/nestlens.module.d.ts +10 -0
- package/dist/nestlens.module.d.ts.map +1 -0
- package/dist/nestlens.module.js +211 -0
- package/dist/nestlens.module.js.map +1 -0
- package/dist/types/entry.types.d.ts +368 -0
- package/dist/types/entry.types.d.ts.map +1 -0
- package/dist/types/entry.types.js +3 -0
- package/dist/types/entry.types.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +20 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/request.types.d.ts +9 -0
- package/dist/types/request.types.d.ts.map +1 -0
- package/dist/types/request.types.js +3 -0
- package/dist/types/request.types.js.map +1 -0
- package/dist/types/tag.types.d.ts +32 -0
- package/dist/types/tag.types.d.ts.map +1 -0
- package/dist/types/tag.types.js +3 -0
- package/dist/types/tag.types.js.map +1 -0
- package/dist/watchers/batch.watcher.d.ts +48 -0
- package/dist/watchers/batch.watcher.d.ts.map +1 -0
- package/dist/watchers/batch.watcher.js +185 -0
- package/dist/watchers/batch.watcher.js.map +1 -0
- package/dist/watchers/cache.watcher.d.ts +19 -0
- package/dist/watchers/cache.watcher.d.ts.map +1 -0
- package/dist/watchers/cache.watcher.js +158 -0
- package/dist/watchers/cache.watcher.js.map +1 -0
- package/dist/watchers/command.watcher.d.ts +32 -0
- package/dist/watchers/command.watcher.d.ts.map +1 -0
- package/dist/watchers/command.watcher.js +174 -0
- package/dist/watchers/command.watcher.js.map +1 -0
- package/dist/watchers/dump.watcher.d.ts +52 -0
- package/dist/watchers/dump.watcher.d.ts.map +1 -0
- package/dist/watchers/dump.watcher.js +234 -0
- package/dist/watchers/dump.watcher.js.map +1 -0
- package/dist/watchers/event.watcher.d.ts +20 -0
- package/dist/watchers/event.watcher.d.ts.map +1 -0
- package/dist/watchers/event.watcher.js +123 -0
- package/dist/watchers/event.watcher.js.map +1 -0
- package/dist/watchers/exception.watcher.d.ts +15 -0
- package/dist/watchers/exception.watcher.d.ts.map +1 -0
- package/dist/watchers/exception.watcher.js +117 -0
- package/dist/watchers/exception.watcher.js.map +1 -0
- package/dist/watchers/gate.watcher.d.ts +40 -0
- package/dist/watchers/gate.watcher.d.ts.map +1 -0
- package/dist/watchers/gate.watcher.js +200 -0
- package/dist/watchers/gate.watcher.js.map +1 -0
- package/dist/watchers/http-client.watcher.d.ts +34 -0
- package/dist/watchers/http-client.watcher.d.ts.map +1 -0
- package/dist/watchers/http-client.watcher.js +259 -0
- package/dist/watchers/http-client.watcher.js.map +1 -0
- package/dist/watchers/index.d.ts +19 -0
- package/dist/watchers/index.d.ts.map +1 -0
- package/dist/watchers/index.js +35 -0
- package/dist/watchers/index.js.map +1 -0
- package/dist/watchers/job.watcher.d.ts +27 -0
- package/dist/watchers/job.watcher.d.ts.map +1 -0
- package/dist/watchers/job.watcher.js +190 -0
- package/dist/watchers/job.watcher.js.map +1 -0
- package/dist/watchers/log.watcher.d.ts +26 -0
- package/dist/watchers/log.watcher.d.ts.map +1 -0
- package/dist/watchers/log.watcher.js +122 -0
- package/dist/watchers/log.watcher.js.map +1 -0
- package/dist/watchers/mail.watcher.d.ts +26 -0
- package/dist/watchers/mail.watcher.d.ts.map +1 -0
- package/dist/watchers/mail.watcher.js +154 -0
- package/dist/watchers/mail.watcher.js.map +1 -0
- package/dist/watchers/model.watcher.d.ts +54 -0
- package/dist/watchers/model.watcher.d.ts.map +1 -0
- package/dist/watchers/model.watcher.js +343 -0
- package/dist/watchers/model.watcher.js.map +1 -0
- package/dist/watchers/notification.watcher.d.ts +48 -0
- package/dist/watchers/notification.watcher.d.ts.map +1 -0
- package/dist/watchers/notification.watcher.js +215 -0
- package/dist/watchers/notification.watcher.js.map +1 -0
- package/dist/watchers/query/index.d.ts +3 -0
- package/dist/watchers/query/index.d.ts.map +1 -0
- package/dist/watchers/query/index.js +19 -0
- package/dist/watchers/query/index.js.map +1 -0
- package/dist/watchers/query/query.watcher.d.ts +27 -0
- package/dist/watchers/query/query.watcher.d.ts.map +1 -0
- package/dist/watchers/query/query.watcher.js +167 -0
- package/dist/watchers/query/query.watcher.js.map +1 -0
- package/dist/watchers/query/types.d.ts +60 -0
- package/dist/watchers/query/types.d.ts.map +1 -0
- package/dist/watchers/query/types.js +55 -0
- package/dist/watchers/query/types.js.map +1 -0
- package/dist/watchers/redis.watcher.d.ts +43 -0
- package/dist/watchers/redis.watcher.d.ts.map +1 -0
- package/dist/watchers/redis.watcher.js +225 -0
- package/dist/watchers/redis.watcher.js.map +1 -0
- package/dist/watchers/request.watcher.d.ts +21 -0
- package/dist/watchers/request.watcher.d.ts.map +1 -0
- package/dist/watchers/request.watcher.js +287 -0
- package/dist/watchers/request.watcher.js.map +1 -0
- package/dist/watchers/schedule.watcher.d.ts +25 -0
- package/dist/watchers/schedule.watcher.d.ts.map +1 -0
- package/dist/watchers/schedule.watcher.js +168 -0
- package/dist/watchers/schedule.watcher.js.map +1 -0
- package/dist/watchers/view.watcher.d.ts +51 -0
- package/dist/watchers/view.watcher.d.ts.map +1 -0
- package/dist/watchers/view.watcher.js +219 -0
- package/dist/watchers/view.watcher.js.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,683 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* GateWatcher Tests
|
|
5
|
+
*
|
|
6
|
+
* Tests for the gate watcher that monitors authorization checks.
|
|
7
|
+
* Follows AAA (Arrange-Act-Assert) pattern.
|
|
8
|
+
*/
|
|
9
|
+
const testing_1 = require("@nestjs/testing");
|
|
10
|
+
const collector_service_1 = require("../../core/collector.service");
|
|
11
|
+
const nestlens_config_1 = require("../../nestlens.config");
|
|
12
|
+
const gate_watcher_1 = require("../../watchers/gate.watcher");
|
|
13
|
+
describe('GateWatcher', () => {
|
|
14
|
+
let watcher;
|
|
15
|
+
let mockCollector;
|
|
16
|
+
let mockConfig;
|
|
17
|
+
const createGateService = (overrides = {}) => ({
|
|
18
|
+
check: jest.fn().mockResolvedValue(true),
|
|
19
|
+
allows: jest.fn().mockResolvedValue(true),
|
|
20
|
+
denies: jest.fn().mockResolvedValue(false),
|
|
21
|
+
authorize: jest.fn().mockResolvedValue(true),
|
|
22
|
+
can: jest.fn().mockResolvedValue(true),
|
|
23
|
+
...overrides,
|
|
24
|
+
});
|
|
25
|
+
const createWatcher = async (config, gateService) => {
|
|
26
|
+
const providers = [
|
|
27
|
+
gate_watcher_1.GateWatcher,
|
|
28
|
+
{ provide: collector_service_1.CollectorService, useValue: mockCollector },
|
|
29
|
+
{ provide: nestlens_config_1.NESTLENS_CONFIG, useValue: config },
|
|
30
|
+
];
|
|
31
|
+
if (gateService !== undefined) {
|
|
32
|
+
providers.push({ provide: gate_watcher_1.NESTLENS_GATE_SERVICE, useValue: gateService });
|
|
33
|
+
}
|
|
34
|
+
const module = await testing_1.Test.createTestingModule({
|
|
35
|
+
providers,
|
|
36
|
+
}).compile();
|
|
37
|
+
return module.get(gate_watcher_1.GateWatcher);
|
|
38
|
+
};
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
jest.clearAllMocks();
|
|
41
|
+
mockCollector = {
|
|
42
|
+
collect: jest.fn(),
|
|
43
|
+
collectImmediate: jest.fn(),
|
|
44
|
+
};
|
|
45
|
+
mockConfig = {
|
|
46
|
+
enabled: true,
|
|
47
|
+
watchers: {
|
|
48
|
+
gate: { enabled: true },
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// Config Handling
|
|
54
|
+
// ============================================================================
|
|
55
|
+
describe('Config Handling', () => {
|
|
56
|
+
it('should be enabled when gate watcher config is true', async () => {
|
|
57
|
+
// Arrange
|
|
58
|
+
mockConfig.watchers = { gate: true };
|
|
59
|
+
const service = createGateService();
|
|
60
|
+
watcher = await createWatcher(mockConfig, service);
|
|
61
|
+
// Assert
|
|
62
|
+
expect(watcher.config.enabled).toBe(true);
|
|
63
|
+
});
|
|
64
|
+
it('should be disabled when gate watcher config is false', async () => {
|
|
65
|
+
// Arrange
|
|
66
|
+
mockConfig.watchers = { gate: false };
|
|
67
|
+
const service = createGateService();
|
|
68
|
+
watcher = await createWatcher(mockConfig, service);
|
|
69
|
+
// Assert
|
|
70
|
+
expect(watcher.config.enabled).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
it('should be enabled by default when watchers config is undefined', async () => {
|
|
73
|
+
// Arrange
|
|
74
|
+
mockConfig.watchers = undefined;
|
|
75
|
+
const service = createGateService();
|
|
76
|
+
watcher = await createWatcher(mockConfig, service);
|
|
77
|
+
// Assert
|
|
78
|
+
expect(watcher.config.enabled).toBe(true);
|
|
79
|
+
});
|
|
80
|
+
it('should use object config when provided', async () => {
|
|
81
|
+
// Arrange
|
|
82
|
+
mockConfig.watchers = { gate: { enabled: true, captureContext: false } };
|
|
83
|
+
const service = createGateService();
|
|
84
|
+
watcher = await createWatcher(mockConfig, service);
|
|
85
|
+
// Assert
|
|
86
|
+
expect(watcher.config.captureContext).toBe(false);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
// ============================================================================
|
|
90
|
+
// Module Initialization
|
|
91
|
+
// ============================================================================
|
|
92
|
+
describe('Module Initialization', () => {
|
|
93
|
+
it('should handle missing gate service gracefully', async () => {
|
|
94
|
+
// Arrange
|
|
95
|
+
watcher = await createWatcher(mockConfig, undefined);
|
|
96
|
+
// Act & Assert - should not throw
|
|
97
|
+
expect(() => watcher.onModuleInit()).not.toThrow();
|
|
98
|
+
});
|
|
99
|
+
it('should setup interceptors when service is available', async () => {
|
|
100
|
+
// Arrange
|
|
101
|
+
const service = createGateService();
|
|
102
|
+
watcher = await createWatcher(mockConfig, service);
|
|
103
|
+
// Act
|
|
104
|
+
watcher.onModuleInit();
|
|
105
|
+
// Assert - methods should be wrapped
|
|
106
|
+
expect(typeof service.check).toBe('function');
|
|
107
|
+
});
|
|
108
|
+
it('should not setup interceptors when disabled', async () => {
|
|
109
|
+
// Arrange
|
|
110
|
+
mockConfig.watchers = { gate: false };
|
|
111
|
+
const service = createGateService();
|
|
112
|
+
const originalCheck = service.check;
|
|
113
|
+
watcher = await createWatcher(mockConfig, service);
|
|
114
|
+
// Act
|
|
115
|
+
watcher.onModuleInit();
|
|
116
|
+
// Assert - original method should remain unchanged
|
|
117
|
+
expect(service.check).toBe(originalCheck);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// Authorization Check - Allowed
|
|
122
|
+
// ============================================================================
|
|
123
|
+
describe('Authorization Check - Allowed', () => {
|
|
124
|
+
it('should collect allowed authorization check', async () => {
|
|
125
|
+
// Arrange
|
|
126
|
+
const service = createGateService({
|
|
127
|
+
check: jest.fn().mockResolvedValue(true),
|
|
128
|
+
});
|
|
129
|
+
watcher = await createWatcher(mockConfig, service);
|
|
130
|
+
watcher.onModuleInit();
|
|
131
|
+
// Act
|
|
132
|
+
await service.check('PostPolicy', 'edit', { id: 1 });
|
|
133
|
+
// Assert
|
|
134
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
135
|
+
gate: 'PostPolicy',
|
|
136
|
+
action: 'edit',
|
|
137
|
+
allowed: true,
|
|
138
|
+
}));
|
|
139
|
+
});
|
|
140
|
+
it('should calculate check duration', async () => {
|
|
141
|
+
// Arrange
|
|
142
|
+
const service = createGateService({
|
|
143
|
+
check: jest.fn().mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve(true), 50))),
|
|
144
|
+
});
|
|
145
|
+
watcher = await createWatcher(mockConfig, service);
|
|
146
|
+
watcher.onModuleInit();
|
|
147
|
+
// Act
|
|
148
|
+
await service.check('SlowPolicy', 'check');
|
|
149
|
+
// Assert
|
|
150
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
151
|
+
duration: expect.any(Number),
|
|
152
|
+
}));
|
|
153
|
+
const call = mockCollector.collect.mock.calls[0][1];
|
|
154
|
+
expect(call.duration).toBeGreaterThanOrEqual(40);
|
|
155
|
+
});
|
|
156
|
+
it('should return original result', async () => {
|
|
157
|
+
// Arrange
|
|
158
|
+
const service = createGateService({
|
|
159
|
+
check: jest.fn().mockResolvedValue(true),
|
|
160
|
+
});
|
|
161
|
+
watcher = await createWatcher(mockConfig, service);
|
|
162
|
+
watcher.onModuleInit();
|
|
163
|
+
// Act
|
|
164
|
+
const result = await service.check('Policy', 'action');
|
|
165
|
+
// Assert
|
|
166
|
+
expect(result).toBe(true);
|
|
167
|
+
});
|
|
168
|
+
it('should use default action when not provided', async () => {
|
|
169
|
+
// Arrange
|
|
170
|
+
const service = createGateService();
|
|
171
|
+
watcher = await createWatcher(mockConfig, service);
|
|
172
|
+
watcher.onModuleInit();
|
|
173
|
+
// Act
|
|
174
|
+
await service.check('OnlyGate');
|
|
175
|
+
// Assert
|
|
176
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
177
|
+
action: 'check',
|
|
178
|
+
}));
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
// ============================================================================
|
|
182
|
+
// Authorization Check - Denied
|
|
183
|
+
// ============================================================================
|
|
184
|
+
describe('Authorization Check - Denied', () => {
|
|
185
|
+
it('should collect denied authorization check', async () => {
|
|
186
|
+
// Arrange
|
|
187
|
+
const service = createGateService({
|
|
188
|
+
check: jest.fn().mockResolvedValue(false),
|
|
189
|
+
});
|
|
190
|
+
watcher = await createWatcher(mockConfig, service);
|
|
191
|
+
watcher.onModuleInit();
|
|
192
|
+
// Act
|
|
193
|
+
await service.check('AdminPolicy', 'delete', { type: 'Post' });
|
|
194
|
+
// Assert
|
|
195
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
196
|
+
gate: 'AdminPolicy',
|
|
197
|
+
action: 'delete',
|
|
198
|
+
allowed: false,
|
|
199
|
+
}));
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
// ============================================================================
|
|
203
|
+
// Authorization Check - Error
|
|
204
|
+
// ============================================================================
|
|
205
|
+
describe('Authorization Check - Error', () => {
|
|
206
|
+
it('should collect failed check on error', async () => {
|
|
207
|
+
// Arrange
|
|
208
|
+
const service = createGateService({
|
|
209
|
+
check: jest.fn().mockRejectedValue(new Error('Policy evaluation failed')),
|
|
210
|
+
});
|
|
211
|
+
watcher = await createWatcher(mockConfig, service);
|
|
212
|
+
watcher.onModuleInit();
|
|
213
|
+
// Act & Assert
|
|
214
|
+
await expect(service.check('ErrorPolicy', 'action'))
|
|
215
|
+
.rejects.toThrow('Policy evaluation failed');
|
|
216
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
217
|
+
allowed: false,
|
|
218
|
+
reason: 'Policy evaluation failed',
|
|
219
|
+
}));
|
|
220
|
+
});
|
|
221
|
+
it('should re-throw the error', async () => {
|
|
222
|
+
// Arrange
|
|
223
|
+
const service = createGateService({
|
|
224
|
+
check: jest.fn().mockRejectedValue(new Error('Auth error')),
|
|
225
|
+
});
|
|
226
|
+
watcher = await createWatcher(mockConfig, service);
|
|
227
|
+
watcher.onModuleInit();
|
|
228
|
+
// Act & Assert
|
|
229
|
+
await expect(service.check('Policy', 'action'))
|
|
230
|
+
.rejects.toThrow('Auth error');
|
|
231
|
+
});
|
|
232
|
+
it('should handle non-Error objects', async () => {
|
|
233
|
+
// Arrange
|
|
234
|
+
const service = createGateService({
|
|
235
|
+
check: jest.fn().mockRejectedValue('String error'),
|
|
236
|
+
});
|
|
237
|
+
watcher = await createWatcher(mockConfig, service);
|
|
238
|
+
watcher.onModuleInit();
|
|
239
|
+
// Act
|
|
240
|
+
try {
|
|
241
|
+
await service.check('Policy', 'action');
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
// Expected
|
|
245
|
+
}
|
|
246
|
+
// Assert
|
|
247
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
248
|
+
reason: 'String error',
|
|
249
|
+
}));
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
// ============================================================================
|
|
253
|
+
// Multiple Methods
|
|
254
|
+
// ============================================================================
|
|
255
|
+
describe('Multiple Methods', () => {
|
|
256
|
+
it('should wrap allows method', async () => {
|
|
257
|
+
// Arrange
|
|
258
|
+
const service = createGateService();
|
|
259
|
+
watcher = await createWatcher(mockConfig, service);
|
|
260
|
+
watcher.onModuleInit();
|
|
261
|
+
// Act
|
|
262
|
+
await service.allows('CanEdit', 'edit');
|
|
263
|
+
// Assert
|
|
264
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
265
|
+
gate: 'CanEdit',
|
|
266
|
+
}));
|
|
267
|
+
});
|
|
268
|
+
it('should wrap denies method', async () => {
|
|
269
|
+
// Arrange
|
|
270
|
+
const service = createGateService();
|
|
271
|
+
watcher = await createWatcher(mockConfig, service);
|
|
272
|
+
watcher.onModuleInit();
|
|
273
|
+
// Act
|
|
274
|
+
await service.denies('NoAccess', 'view');
|
|
275
|
+
// Assert
|
|
276
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
277
|
+
gate: 'NoAccess',
|
|
278
|
+
}));
|
|
279
|
+
});
|
|
280
|
+
it('should wrap authorize method', async () => {
|
|
281
|
+
// Arrange
|
|
282
|
+
const service = createGateService();
|
|
283
|
+
watcher = await createWatcher(mockConfig, service);
|
|
284
|
+
watcher.onModuleInit();
|
|
285
|
+
// Act
|
|
286
|
+
await service.authorize('AuthorizePolicy', 'execute');
|
|
287
|
+
// Assert
|
|
288
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
289
|
+
gate: 'AuthorizePolicy',
|
|
290
|
+
}));
|
|
291
|
+
});
|
|
292
|
+
it('should wrap can method', async () => {
|
|
293
|
+
// Arrange
|
|
294
|
+
const service = createGateService();
|
|
295
|
+
watcher = await createWatcher(mockConfig, service);
|
|
296
|
+
watcher.onModuleInit();
|
|
297
|
+
// Act
|
|
298
|
+
await service.can('CanPolicy', 'do');
|
|
299
|
+
// Assert
|
|
300
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
301
|
+
gate: 'CanPolicy',
|
|
302
|
+
}));
|
|
303
|
+
});
|
|
304
|
+
it('should skip non-function methods', async () => {
|
|
305
|
+
// Arrange
|
|
306
|
+
const service = {
|
|
307
|
+
...createGateService(),
|
|
308
|
+
notAMethod: 'value',
|
|
309
|
+
};
|
|
310
|
+
watcher = await createWatcher(mockConfig, service);
|
|
311
|
+
// Act & Assert - should not throw
|
|
312
|
+
expect(() => watcher.onModuleInit()).not.toThrow();
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
// ============================================================================
|
|
316
|
+
// User ID Extraction
|
|
317
|
+
// ============================================================================
|
|
318
|
+
describe('User ID Extraction', () => {
|
|
319
|
+
it('should extract id from user object', async () => {
|
|
320
|
+
// Arrange
|
|
321
|
+
const service = createGateService();
|
|
322
|
+
watcher = await createWatcher(mockConfig, service);
|
|
323
|
+
watcher.onModuleInit();
|
|
324
|
+
const user = { id: 123, email: 'test@example.com' };
|
|
325
|
+
// Act
|
|
326
|
+
await service.check('Policy', 'action', null, user);
|
|
327
|
+
// Assert
|
|
328
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
329
|
+
userId: 123,
|
|
330
|
+
}));
|
|
331
|
+
});
|
|
332
|
+
it('should extract userId from user object', async () => {
|
|
333
|
+
// Arrange
|
|
334
|
+
const service = createGateService();
|
|
335
|
+
watcher = await createWatcher(mockConfig, service);
|
|
336
|
+
watcher.onModuleInit();
|
|
337
|
+
const user = { userId: 456 };
|
|
338
|
+
// Act
|
|
339
|
+
await service.check('Policy', 'action', null, user);
|
|
340
|
+
// Assert
|
|
341
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
342
|
+
userId: 456,
|
|
343
|
+
}));
|
|
344
|
+
});
|
|
345
|
+
it('should extract sub from JWT user object', async () => {
|
|
346
|
+
// Arrange
|
|
347
|
+
const service = createGateService();
|
|
348
|
+
watcher = await createWatcher(mockConfig, service);
|
|
349
|
+
watcher.onModuleInit();
|
|
350
|
+
const user = { sub: 'user-789' };
|
|
351
|
+
// Act
|
|
352
|
+
await service.check('Policy', 'action', null, user);
|
|
353
|
+
// Assert
|
|
354
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
355
|
+
userId: 'user-789',
|
|
356
|
+
}));
|
|
357
|
+
});
|
|
358
|
+
it('should extract _id from MongoDB user object', async () => {
|
|
359
|
+
// Arrange
|
|
360
|
+
const service = createGateService();
|
|
361
|
+
watcher = await createWatcher(mockConfig, service);
|
|
362
|
+
watcher.onModuleInit();
|
|
363
|
+
const user = { _id: 'mongo-id' };
|
|
364
|
+
// Act
|
|
365
|
+
await service.check('Policy', 'action', null, user);
|
|
366
|
+
// Assert
|
|
367
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
368
|
+
userId: 'mongo-id',
|
|
369
|
+
}));
|
|
370
|
+
});
|
|
371
|
+
it('should use string user directly', async () => {
|
|
372
|
+
// Arrange
|
|
373
|
+
const service = createGateService();
|
|
374
|
+
watcher = await createWatcher(mockConfig, service);
|
|
375
|
+
watcher.onModuleInit();
|
|
376
|
+
// Act
|
|
377
|
+
await service.check('Policy', 'action', null, 'user-string');
|
|
378
|
+
// Assert
|
|
379
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
380
|
+
userId: 'user-string',
|
|
381
|
+
}));
|
|
382
|
+
});
|
|
383
|
+
it('should use number user directly', async () => {
|
|
384
|
+
// Arrange
|
|
385
|
+
const service = createGateService();
|
|
386
|
+
watcher = await createWatcher(mockConfig, service);
|
|
387
|
+
watcher.onModuleInit();
|
|
388
|
+
// Act
|
|
389
|
+
await service.check('Policy', 'action', null, 42);
|
|
390
|
+
// Assert
|
|
391
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
392
|
+
userId: 42,
|
|
393
|
+
}));
|
|
394
|
+
});
|
|
395
|
+
it('should return undefined for null user', async () => {
|
|
396
|
+
// Arrange
|
|
397
|
+
const service = createGateService();
|
|
398
|
+
watcher = await createWatcher(mockConfig, service);
|
|
399
|
+
watcher.onModuleInit();
|
|
400
|
+
// Act
|
|
401
|
+
await service.check('Policy', 'action', null, null);
|
|
402
|
+
// Assert
|
|
403
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
404
|
+
userId: undefined,
|
|
405
|
+
}));
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
// ============================================================================
|
|
409
|
+
// Subject Name Extraction
|
|
410
|
+
// ============================================================================
|
|
411
|
+
describe('Subject Name Extraction', () => {
|
|
412
|
+
it('should use string subject directly', async () => {
|
|
413
|
+
// Arrange
|
|
414
|
+
const service = createGateService();
|
|
415
|
+
watcher = await createWatcher(mockConfig, service);
|
|
416
|
+
watcher.onModuleInit();
|
|
417
|
+
// Act
|
|
418
|
+
await service.check('Policy', 'action', 'Post');
|
|
419
|
+
// Assert
|
|
420
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
421
|
+
subject: 'Post',
|
|
422
|
+
}));
|
|
423
|
+
});
|
|
424
|
+
it('should extract name from subject object', async () => {
|
|
425
|
+
// Arrange
|
|
426
|
+
const service = createGateService();
|
|
427
|
+
watcher = await createWatcher(mockConfig, service);
|
|
428
|
+
watcher.onModuleInit();
|
|
429
|
+
// Act
|
|
430
|
+
await service.check('Policy', 'action', { name: 'Article' });
|
|
431
|
+
// Assert
|
|
432
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
433
|
+
subject: 'Article',
|
|
434
|
+
}));
|
|
435
|
+
});
|
|
436
|
+
it('should extract type from subject object', async () => {
|
|
437
|
+
// Arrange
|
|
438
|
+
const service = createGateService();
|
|
439
|
+
watcher = await createWatcher(mockConfig, service);
|
|
440
|
+
watcher.onModuleInit();
|
|
441
|
+
// Act
|
|
442
|
+
await service.check('Policy', 'action', { type: 'Comment' });
|
|
443
|
+
// Assert
|
|
444
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
445
|
+
subject: 'Comment',
|
|
446
|
+
}));
|
|
447
|
+
});
|
|
448
|
+
it('should use constructor name from class instance', async () => {
|
|
449
|
+
// Arrange
|
|
450
|
+
class Post {
|
|
451
|
+
}
|
|
452
|
+
const service = createGateService();
|
|
453
|
+
watcher = await createWatcher(mockConfig, service);
|
|
454
|
+
watcher.onModuleInit();
|
|
455
|
+
// Act
|
|
456
|
+
await service.check('Policy', 'action', new Post());
|
|
457
|
+
// Assert
|
|
458
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
459
|
+
subject: 'Post',
|
|
460
|
+
}));
|
|
461
|
+
});
|
|
462
|
+
it('should return undefined for null subject', async () => {
|
|
463
|
+
// Arrange
|
|
464
|
+
const service = createGateService();
|
|
465
|
+
watcher = await createWatcher(mockConfig, service);
|
|
466
|
+
watcher.onModuleInit();
|
|
467
|
+
// Act
|
|
468
|
+
await service.check('Policy', 'action', null);
|
|
469
|
+
// Assert
|
|
470
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
471
|
+
subject: undefined,
|
|
472
|
+
}));
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
// ============================================================================
|
|
476
|
+
// Context Capture
|
|
477
|
+
// ============================================================================
|
|
478
|
+
describe('Context Capture', () => {
|
|
479
|
+
it('should capture subject id in context', async () => {
|
|
480
|
+
// Arrange
|
|
481
|
+
const service = createGateService();
|
|
482
|
+
watcher = await createWatcher(mockConfig, service);
|
|
483
|
+
watcher.onModuleInit();
|
|
484
|
+
// Act
|
|
485
|
+
await service.check('Policy', 'action', { id: 123, type: 'Post' });
|
|
486
|
+
// Assert
|
|
487
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
488
|
+
context: expect.objectContaining({
|
|
489
|
+
subjectId: 123,
|
|
490
|
+
subjectType: 'Post',
|
|
491
|
+
}),
|
|
492
|
+
}));
|
|
493
|
+
});
|
|
494
|
+
it('should capture user details in context', async () => {
|
|
495
|
+
// Arrange
|
|
496
|
+
const service = createGateService();
|
|
497
|
+
watcher = await createWatcher(mockConfig, service);
|
|
498
|
+
watcher.onModuleInit();
|
|
499
|
+
const user = { id: 1, email: 'admin@example.com', name: 'Admin', roles: ['admin'] };
|
|
500
|
+
// Act
|
|
501
|
+
await service.check('Policy', 'action', null, user);
|
|
502
|
+
// Assert
|
|
503
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
504
|
+
context: expect.objectContaining({
|
|
505
|
+
userEmail: 'admin@example.com',
|
|
506
|
+
userName: 'Admin',
|
|
507
|
+
userRoles: ['admin'],
|
|
508
|
+
}),
|
|
509
|
+
}));
|
|
510
|
+
});
|
|
511
|
+
it('should not capture context when disabled', async () => {
|
|
512
|
+
// Arrange
|
|
513
|
+
mockConfig.watchers = { gate: { enabled: true, captureContext: false } };
|
|
514
|
+
const service = createGateService();
|
|
515
|
+
watcher = await createWatcher(mockConfig, service);
|
|
516
|
+
watcher.onModuleInit();
|
|
517
|
+
// Act
|
|
518
|
+
await service.check('Policy', 'action', { id: 1 }, { id: 2, email: 'test@example.com' });
|
|
519
|
+
// Assert
|
|
520
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
521
|
+
context: undefined,
|
|
522
|
+
}));
|
|
523
|
+
});
|
|
524
|
+
it('should return undefined context when no details available', async () => {
|
|
525
|
+
// Arrange
|
|
526
|
+
const service = createGateService();
|
|
527
|
+
watcher = await createWatcher(mockConfig, service);
|
|
528
|
+
watcher.onModuleInit();
|
|
529
|
+
// Act
|
|
530
|
+
await service.check('Policy', 'action', {}, {});
|
|
531
|
+
// Assert
|
|
532
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
533
|
+
context: undefined,
|
|
534
|
+
}));
|
|
535
|
+
});
|
|
536
|
+
});
|
|
537
|
+
// ============================================================================
|
|
538
|
+
// Ignore Abilities
|
|
539
|
+
// ============================================================================
|
|
540
|
+
describe('Ignore Abilities', () => {
|
|
541
|
+
it('should ignore gate by name', async () => {
|
|
542
|
+
// Arrange
|
|
543
|
+
mockConfig.watchers = {
|
|
544
|
+
gate: { enabled: true, ignoreAbilities: ['viewDashboard'] },
|
|
545
|
+
};
|
|
546
|
+
const service = createGateService();
|
|
547
|
+
watcher = await createWatcher(mockConfig, service);
|
|
548
|
+
watcher.onModuleInit();
|
|
549
|
+
// Act
|
|
550
|
+
await service.check('viewDashboard', 'view');
|
|
551
|
+
// Assert
|
|
552
|
+
expect(mockCollector.collect).not.toHaveBeenCalled();
|
|
553
|
+
});
|
|
554
|
+
it('should ignore action by name', async () => {
|
|
555
|
+
// Arrange
|
|
556
|
+
mockConfig.watchers = {
|
|
557
|
+
gate: { enabled: true, ignoreAbilities: ['healthCheck'] },
|
|
558
|
+
};
|
|
559
|
+
const service = createGateService();
|
|
560
|
+
watcher = await createWatcher(mockConfig, service);
|
|
561
|
+
watcher.onModuleInit();
|
|
562
|
+
// Act
|
|
563
|
+
await service.check('SystemGate', 'healthCheck');
|
|
564
|
+
// Assert
|
|
565
|
+
expect(mockCollector.collect).not.toHaveBeenCalled();
|
|
566
|
+
});
|
|
567
|
+
it('should ignore gate:action combination', async () => {
|
|
568
|
+
// Arrange
|
|
569
|
+
mockConfig.watchers = {
|
|
570
|
+
gate: { enabled: true, ignoreAbilities: ['AdminPolicy:viewLogs'] },
|
|
571
|
+
};
|
|
572
|
+
const service = createGateService();
|
|
573
|
+
watcher = await createWatcher(mockConfig, service);
|
|
574
|
+
watcher.onModuleInit();
|
|
575
|
+
// Act
|
|
576
|
+
await service.check('AdminPolicy', 'viewLogs');
|
|
577
|
+
// Assert
|
|
578
|
+
expect(mockCollector.collect).not.toHaveBeenCalled();
|
|
579
|
+
});
|
|
580
|
+
it('should not ignore non-matching abilities', async () => {
|
|
581
|
+
// Arrange
|
|
582
|
+
mockConfig.watchers = {
|
|
583
|
+
gate: { enabled: true, ignoreAbilities: ['viewDashboard', 'healthCheck'] },
|
|
584
|
+
};
|
|
585
|
+
const service = createGateService();
|
|
586
|
+
watcher = await createWatcher(mockConfig, service);
|
|
587
|
+
watcher.onModuleInit();
|
|
588
|
+
// Act
|
|
589
|
+
await service.check('PostPolicy', 'edit');
|
|
590
|
+
// Assert
|
|
591
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
592
|
+
gate: 'PostPolicy',
|
|
593
|
+
action: 'edit',
|
|
594
|
+
}));
|
|
595
|
+
});
|
|
596
|
+
it('should ignore multiple abilities', async () => {
|
|
597
|
+
// Arrange
|
|
598
|
+
mockConfig.watchers = {
|
|
599
|
+
gate: { enabled: true, ignoreAbilities: ['viewDashboard', 'healthCheck', 'ping'] },
|
|
600
|
+
};
|
|
601
|
+
const service = createGateService();
|
|
602
|
+
watcher = await createWatcher(mockConfig, service);
|
|
603
|
+
watcher.onModuleInit();
|
|
604
|
+
// Act
|
|
605
|
+
await service.check('SystemGate', 'viewDashboard');
|
|
606
|
+
await service.check('HealthGate', 'healthCheck');
|
|
607
|
+
await service.check('PingGate', 'ping');
|
|
608
|
+
await service.check('ImportantGate', 'action');
|
|
609
|
+
// Assert - only the last one should be collected
|
|
610
|
+
expect(mockCollector.collect).toHaveBeenCalledTimes(1);
|
|
611
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
612
|
+
gate: 'ImportantGate',
|
|
613
|
+
}));
|
|
614
|
+
});
|
|
615
|
+
it('should work with empty ignore list', async () => {
|
|
616
|
+
// Arrange
|
|
617
|
+
mockConfig.watchers = {
|
|
618
|
+
gate: { enabled: true, ignoreAbilities: [] },
|
|
619
|
+
};
|
|
620
|
+
const service = createGateService();
|
|
621
|
+
watcher = await createWatcher(mockConfig, service);
|
|
622
|
+
watcher.onModuleInit();
|
|
623
|
+
// Act
|
|
624
|
+
await service.check('AnyGate', 'anyAction');
|
|
625
|
+
// Assert
|
|
626
|
+
expect(mockCollector.collect).toHaveBeenCalled();
|
|
627
|
+
});
|
|
628
|
+
it('should work without ignore list', async () => {
|
|
629
|
+
// Arrange
|
|
630
|
+
mockConfig.watchers = {
|
|
631
|
+
gate: { enabled: true },
|
|
632
|
+
};
|
|
633
|
+
const service = createGateService();
|
|
634
|
+
watcher = await createWatcher(mockConfig, service);
|
|
635
|
+
watcher.onModuleInit();
|
|
636
|
+
// Act
|
|
637
|
+
await service.check('AnyGate', 'anyAction');
|
|
638
|
+
// Assert
|
|
639
|
+
expect(mockCollector.collect).toHaveBeenCalled();
|
|
640
|
+
});
|
|
641
|
+
it('should also ignore in manual trackCheck', async () => {
|
|
642
|
+
// Arrange
|
|
643
|
+
mockConfig.watchers = {
|
|
644
|
+
gate: { enabled: true, ignoreAbilities: ['ignoredGate'] },
|
|
645
|
+
};
|
|
646
|
+
watcher = await createWatcher(mockConfig, undefined);
|
|
647
|
+
// Act
|
|
648
|
+
watcher.trackCheck('ignoredGate', 'action', 'subject', true);
|
|
649
|
+
// Assert
|
|
650
|
+
expect(mockCollector.collect).not.toHaveBeenCalled();
|
|
651
|
+
});
|
|
652
|
+
});
|
|
653
|
+
// ============================================================================
|
|
654
|
+
// Manual Tracking
|
|
655
|
+
// ============================================================================
|
|
656
|
+
describe('Manual Tracking (trackCheck)', () => {
|
|
657
|
+
it('should track allowed check', async () => {
|
|
658
|
+
// Arrange
|
|
659
|
+
watcher = await createWatcher(mockConfig, undefined);
|
|
660
|
+
// Act
|
|
661
|
+
watcher.trackCheck('ManualGate', 'view', 'Post', true, { id: 1 });
|
|
662
|
+
// Assert
|
|
663
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
664
|
+
gate: 'ManualGate',
|
|
665
|
+
action: 'view',
|
|
666
|
+
subject: 'Post',
|
|
667
|
+
allowed: true,
|
|
668
|
+
}));
|
|
669
|
+
});
|
|
670
|
+
it('should track denied check with reason', async () => {
|
|
671
|
+
// Arrange
|
|
672
|
+
watcher = await createWatcher(mockConfig, undefined);
|
|
673
|
+
// Act
|
|
674
|
+
watcher.trackCheck('ManualGate', 'delete', 'Comment', false, { id: 2 }, 'Not owner');
|
|
675
|
+
// Assert
|
|
676
|
+
expect(mockCollector.collect).toHaveBeenCalledWith('gate', expect.objectContaining({
|
|
677
|
+
allowed: false,
|
|
678
|
+
reason: 'Not owner',
|
|
679
|
+
}));
|
|
680
|
+
});
|
|
681
|
+
});
|
|
682
|
+
});
|
|
683
|
+
//# sourceMappingURL=gate.watcher.spec.js.map
|