@lenne.tech/ng-base 18.1.3 → 22.0.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/CLAUDE.md +55 -0
- package/LICENSE +2 -2
- package/README.md +237 -44
- package/fesm2022/lenne.tech-ng-base-ai.mjs +767 -0
- package/fesm2022/lenne.tech-ng-base-ai.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-auth-provide.mjs +939 -0
- package/fesm2022/lenne.tech-ng-base-auth-provide.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-auth.mjs +454 -0
- package/fesm2022/lenne.tech-ng-base-auth.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-bug-report-dialog-BRzVmKJr.mjs +825 -0
- package/fesm2022/lenne.tech-ng-base-bug-bug-report-dialog-BRzVmKJr.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-bug-report-service-DWoTb_iw.mjs +351 -0
- package/fesm2022/lenne.tech-ng-base-bug-bug-report-service-DWoTb_iw.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-capture-engine-TkjMDdqj.mjs +1046 -0
- package/fesm2022/lenne.tech-ng-base-bug-capture-engine-TkjMDdqj.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-constants-Brm2KGHi.mjs +4 -0
- package/fesm2022/lenne.tech-ng-base-bug-constants-Brm2KGHi.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-messages-BsP4fRQU.mjs +179 -0
- package/fesm2022/lenne.tech-ng-base-bug-messages-BsP4fRQU.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-provide.mjs +26 -0
- package/fesm2022/lenne.tech-ng-base-bug-provide.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-report-Tzlhe1Cm.mjs +62 -0
- package/fesm2022/lenne.tech-ng-base-bug-report-Tzlhe1Cm.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-server.mjs +818 -0
- package/fesm2022/lenne.tech-ng-base-bug-server.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug.mjs +196 -0
- package/fesm2022/lenne.tech-ng-base-bug.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-files-ui.mjs +445 -0
- package/fesm2022/lenne.tech-ng-base-files-ui.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-files.mjs +474 -0
- package/fesm2022/lenne.tech-ng-base-files.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-server.mjs +408 -0
- package/fesm2022/lenne.tech-ng-base-server.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-share.mjs +76 -0
- package/fesm2022/lenne.tech-ng-base-share.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-sync.mjs +1096 -0
- package/fesm2022/lenne.tech-ng-base-sync.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-testing.mjs +171 -0
- package/fesm2022/lenne.tech-ng-base-testing.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-ui-provide.mjs +124 -0
- package/fesm2022/lenne.tech-ng-base-ui-provide.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-ui.mjs +34611 -0
- package/fesm2022/lenne.tech-ng-base-ui.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-utils.mjs +287 -0
- package/fesm2022/lenne.tech-ng-base-utils.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base.mjs +615 -910
- package/fesm2022/lenne.tech-ng-base.mjs.map +1 -1
- package/i18n/auth/de.json +17 -0
- package/i18n/auth/en.json +17 -0
- package/i18n/bug/de.json +85 -0
- package/i18n/bug/en.json +85 -0
- package/i18n/de.json +8 -0
- package/i18n/en.json +8 -0
- package/i18n/files/de.json +27 -0
- package/i18n/files/en.json +27 -0
- package/i18n/share/de.json +8 -0
- package/i18n/share/en.json +8 -0
- package/i18n/ui/de.json +38 -0
- package/i18n/ui/en.json +38 -0
- package/package.json +127 -58
- package/types/lenne.tech-ng-base-ai.d.ts +830 -0
- package/types/lenne.tech-ng-base-auth-provide.d.ts +603 -0
- package/types/lenne.tech-ng-base-auth.d.ts +320 -0
- package/types/lenne.tech-ng-base-bug-provide.d.ts +272 -0
- package/types/lenne.tech-ng-base-bug-rolldown-runtime-C25Le4-w.d.ts +1 -0
- package/types/lenne.tech-ng-base-bug-server.d.ts +316 -0
- package/types/lenne.tech-ng-base-bug.d.ts +202 -0
- package/types/lenne.tech-ng-base-files-ui.d.ts +116 -0
- package/types/lenne.tech-ng-base-files.d.ts +288 -0
- package/types/lenne.tech-ng-base-server.d.ts +262 -0
- package/types/lenne.tech-ng-base-share.d.ts +21 -0
- package/types/lenne.tech-ng-base-sync.d.ts +380 -0
- package/types/lenne.tech-ng-base-testing.d.ts +327 -0
- package/types/lenne.tech-ng-base-ui-provide.d.ts +65 -0
- package/types/lenne.tech-ng-base-ui.d.ts +7732 -0
- package/types/lenne.tech-ng-base-utils.d.ts +150 -0
- package/types/lenne.tech-ng-base.d.ts +503 -0
- package/ui/styles/components/accordion.css +3 -0
- package/ui/styles/components/alert-dialog.css +4 -0
- package/ui/styles/components/alert.css +3 -0
- package/ui/styles/components/aspect-ratio.css +3 -0
- package/ui/styles/components/attachment.css +4 -0
- package/ui/styles/components/autocomplete.css +4 -0
- package/ui/styles/components/avatar.css +3 -0
- package/ui/styles/components/badge.css +3 -0
- package/ui/styles/components/breadcrumb.css +3 -0
- package/ui/styles/components/bubble.css +3 -0
- package/ui/styles/components/button-group.css +3 -0
- package/ui/styles/components/button.css +3 -0
- package/ui/styles/components/calendar.css +5 -0
- package/ui/styles/components/card.css +3 -0
- package/ui/styles/components/checkbox.css +3 -0
- package/ui/styles/components/code-block.css +4 -0
- package/ui/styles/components/collapsible.css +3 -0
- package/ui/styles/components/combobox.css +5 -0
- package/ui/styles/components/command.css +5 -0
- package/ui/styles/components/context-menu.css +3 -0
- package/ui/styles/components/date-picker.css +7 -0
- package/ui/styles/components/dialog.css +4 -0
- package/ui/styles/components/drawer.css +3 -0
- package/ui/styles/components/dropdown-menu.css +3 -0
- package/ui/styles/components/empty.css +3 -0
- package/ui/styles/components/field.css +5 -0
- package/ui/styles/components/hover-card.css +3 -0
- package/ui/styles/components/index.css +91 -0
- package/ui/styles/components/input-group.css +6 -0
- package/ui/styles/components/input-otp.css +3 -0
- package/ui/styles/components/input.css +3 -0
- package/ui/styles/components/item.css +4 -0
- package/ui/styles/components/kbd.css +3 -0
- package/ui/styles/components/label.css +3 -0
- package/ui/styles/components/lt-breadcrumb.css +3 -0
- package/ui/styles/components/lt-bug-attachments.css +5 -0
- package/ui/styles/components/lt-bug-journey-timeline.css +5 -0
- package/ui/styles/components/lt-bug-report-dialog.css +15 -0
- package/ui/styles/components/lt-bug-report.css +4 -0
- package/ui/styles/components/lt-color-mode-button.css +3 -0
- package/ui/styles/components/lt-confirm-dialog.css +4 -0
- package/ui/styles/components/lt-data-view.css +5 -0
- package/ui/styles/components/lt-date-picker.css +3 -0
- package/ui/styles/components/lt-date-time-picker.css +5 -0
- package/ui/styles/components/lt-enter-action.css +2 -0
- package/ui/styles/components/lt-footer.css +3 -0
- package/ui/styles/components/lt-form-field.css +4 -0
- package/ui/styles/components/lt-header.css +5 -0
- package/ui/styles/components/lt-imports.css +21 -0
- package/ui/styles/components/lt-navigation-menu.css +3 -0
- package/ui/styles/components/lt-notice.css +3 -0
- package/ui/styles/components/lt-overlay-defaults.css +3 -0
- package/ui/styles/components/lt-page-card.css +3 -0
- package/ui/styles/components/lt-page-title.css +2 -0
- package/ui/styles/components/lt-password-input.css +4 -0
- package/ui/styles/components/lt-readonly-field.css +2 -0
- package/ui/styles/components/lt-select.css +4 -0
- package/ui/styles/components/lt-text-field.css +5 -0
- package/ui/styles/components/lt-toolbar-item.css +2 -0
- package/ui/styles/components/lt-toolbar.css +3 -0
- package/ui/styles/components/lt-tus-upload-component.css +5 -0
- package/ui/styles/components/marker.css +3 -0
- package/ui/styles/components/menubar.css +3 -0
- package/ui/styles/components/message-scroller.css +4 -0
- package/ui/styles/components/message.css +3 -0
- package/ui/styles/components/native-select.css +3 -0
- package/ui/styles/components/navigation-menu.css +3 -0
- package/ui/styles/components/pagination.css +4 -0
- package/ui/styles/components/popover.css +3 -0
- package/ui/styles/components/progress.css +3 -0
- package/ui/styles/components/questionnaire.css +4 -0
- package/ui/styles/components/radio-group.css +3 -0
- package/ui/styles/components/resizable.css +3 -0
- package/ui/styles/components/select.css +3 -0
- package/ui/styles/components/separator.css +3 -0
- package/ui/styles/components/sheet.css +4 -0
- package/ui/styles/components/sidebar.css +9 -0
- package/ui/styles/components/skeleton.css +3 -0
- package/ui/styles/components/slider.css +3 -0
- package/ui/styles/components/sonner.css +4 -0
- package/ui/styles/components/spinner.css +3 -0
- package/ui/styles/components/switch.css +3 -0
- package/ui/styles/components/table.css +3 -0
- package/ui/styles/components/tabs.css +4 -0
- package/ui/styles/components/textarea.css +3 -0
- package/ui/styles/components/toggle-group.css +4 -0
- package/ui/styles/components/toggle.css +3 -0
- package/ui/styles/components/tooltip.css +3 -0
- package/ui/styles/components/trace.css +3 -0
- package/ui/styles/components/typography.css +3 -0
- package/ui/styles/components/utils.css +2 -0
- package/ui/styles/core.css +137 -0
- package/ui/styles/palette.css +94 -0
- package/ui/styles/theme.css +14 -0
- package/ui/styles/transitions.css +131 -0
- package/base-cms/index.d.ts +0 -5
- package/base-cms/interfaces/base-cms-module-config.interface.d.ts +0 -16
- package/base-cms/pages/base-cms/base-cms.component.d.ts +0 -92
- package/base-cms/public-api.d.ts +0 -5
- package/base-components/components/breadcrumb/breadcrumb.component.d.ts +0 -10
- package/base-components/components/change-password/change-password.component.d.ts +0 -24
- package/base-components/components/checkbox/checkbox.component.d.ts +0 -12
- package/base-components/components/delete-account/delete-account.component.d.ts +0 -15
- package/base-components/components/fab-button/fab-button.component.d.ts +0 -16
- package/base-components/components/input/input.component.d.ts +0 -27
- package/base-components/components/loading-bar/loading-bar.component.d.ts +0 -17
- package/base-components/components/model-form/model-form-base.component.d.ts +0 -64
- package/base-components/components/model-form/model-form.component.d.ts +0 -139
- package/base-components/components/model-form-sub/model-form-sub.component.d.ts +0 -56
- package/base-components/components/model-table/model-table.component.d.ts +0 -115
- package/base-components/components/refence-input/refence-input.component.d.ts +0 -84
- package/base-components/components/select/select.component.d.ts +0 -25
- package/base-components/components/skeleton-loader/skeleton-loader.component.d.ts +0 -10
- package/base-components/components/tags/tags.component.d.ts +0 -60
- package/base-components/components/textarea/textarea.component.d.ts +0 -21
- package/base-components/components/toast/toast.component.d.ts +0 -19
- package/base-components/components/upload-image/upload-image.component.d.ts +0 -111
- package/base-components/directives/back-button.directive.d.ts +0 -9
- package/base-components/directives/context-menu.directive.d.ts +0 -22
- package/base-components/directives/sort.directive.d.ts +0 -15
- package/base-components/directives/stop-propagation.directive.d.ts +0 -10
- package/base-components/index.d.ts +0 -5
- package/base-components/pipes/ellipses.pipe.d.ts +0 -10
- package/base-components/public-api.d.ts +0 -26
- package/base-prototype/index.d.ts +0 -5
- package/base-prototype/pages/email-verification/email-verification.component.d.ts +0 -18
- package/base-prototype/pages/forgot-password/forgot-password.component.d.ts +0 -26
- package/base-prototype/pages/login/login.component.d.ts +0 -33
- package/base-prototype/pages/profile/profile.component.d.ts +0 -24
- package/base-prototype/pages/register/register.component.d.ts +0 -31
- package/base-prototype/pages/set-password/set-password.component.d.ts +0 -29
- package/base-prototype/public-api.d.ts +0 -9
- package/esm2022/base-cms/interfaces/base-cms-module-config.interface.mjs +0 -3
- package/esm2022/base-cms/lenne.tech-ng-base-base-cms.mjs +0 -5
- package/esm2022/base-cms/pages/base-cms/base-cms.component.mjs +0 -238
- package/esm2022/base-cms/public-api.mjs +0 -8
- package/esm2022/base-components/components/breadcrumb/breadcrumb.component.mjs +0 -23
- package/esm2022/base-components/components/change-password/change-password.component.mjs +0 -97
- package/esm2022/base-components/components/checkbox/checkbox.component.mjs +0 -38
- package/esm2022/base-components/components/delete-account/delete-account.component.mjs +0 -59
- package/esm2022/base-components/components/fab-button/fab-button.component.mjs +0 -24
- package/esm2022/base-components/components/input/input.component.mjs +0 -75
- package/esm2022/base-components/components/loading-bar/loading-bar.component.mjs +0 -37
- package/esm2022/base-components/components/model-form/model-form-base.component.mjs +0 -145
- package/esm2022/base-components/components/model-form/model-form.component.mjs +0 -591
- package/esm2022/base-components/components/model-form-sub/model-form-sub.component.mjs +0 -117
- package/esm2022/base-components/components/model-table/model-table.component.mjs +0 -478
- package/esm2022/base-components/components/refence-input/refence-input.component.mjs +0 -278
- package/esm2022/base-components/components/select/select.component.mjs +0 -62
- package/esm2022/base-components/components/skeleton-loader/skeleton-loader.component.mjs +0 -33
- package/esm2022/base-components/components/tags/tags.component.mjs +0 -227
- package/esm2022/base-components/components/textarea/textarea.component.mjs +0 -79
- package/esm2022/base-components/components/toast/toast.component.mjs +0 -69
- package/esm2022/base-components/components/upload-image/upload-image.component.mjs +0 -346
- package/esm2022/base-components/directives/back-button.directive.mjs +0 -25
- package/esm2022/base-components/directives/context-menu.directive.mjs +0 -112
- package/esm2022/base-components/directives/sort.directive.mjs +0 -61
- package/esm2022/base-components/directives/stop-propagation.directive.mjs +0 -24
- package/esm2022/base-components/lenne.tech-ng-base-base-components.mjs +0 -5
- package/esm2022/base-components/pipes/ellipses.pipe.mjs +0 -23
- package/esm2022/base-components/public-api.mjs +0 -30
- package/esm2022/base-prototype/lenne.tech-ng-base-base-prototype.mjs +0 -5
- package/esm2022/base-prototype/pages/email-verification/email-verification.component.mjs +0 -60
- package/esm2022/base-prototype/pages/forgot-password/forgot-password.component.mjs +0 -78
- package/esm2022/base-prototype/pages/login/login.component.mjs +0 -114
- package/esm2022/base-prototype/pages/profile/profile.component.mjs +0 -87
- package/esm2022/base-prototype/pages/register/register.component.mjs +0 -100
- package/esm2022/base-prototype/pages/set-password/set-password.component.mjs +0 -91
- package/esm2022/base-prototype/public-api.mjs +0 -11
- package/esm2022/lenne.tech-ng-base.mjs +0 -5
- package/esm2022/public-api.mjs +0 -25
- package/esm2022/shared/classes/auth.class.mjs +0 -14
- package/esm2022/shared/classes/basic-user.class.mjs +0 -49
- package/esm2022/shared/classes/graphql-enum.class.mjs +0 -10
- package/esm2022/shared/classes/graphql-meta.class.mjs +0 -345
- package/esm2022/shared/classes/graphql-type.class.mjs +0 -14
- package/esm2022/shared/classes/helper.class.mjs +0 -307
- package/esm2022/shared/classes/sort.class.mjs +0 -38
- package/esm2022/shared/classes/standard.class.mjs +0 -40
- package/esm2022/shared/decorators/debounce.decorator.mjs +0 -12
- package/esm2022/shared/enums/comparison-operator.enum.mjs +0 -16
- package/esm2022/shared/enums/graphql-request-type.enum.mjs +0 -10
- package/esm2022/shared/enums/logical-operator.enum.mjs +0 -10
- package/esm2022/shared/enums/skeleton-type.enum.mjs +0 -7
- package/esm2022/shared/enums/sort-order.enum.mjs +0 -6
- package/esm2022/shared/enums/toast-type.enum.mjs +0 -8
- package/esm2022/shared/functions/ws-client.function.mjs +0 -39
- package/esm2022/shared/interfaces/base-module-config.interface.mjs +0 -3
- package/esm2022/shared/interfaces/breadcrumb.interface.mjs +0 -2
- package/esm2022/shared/interfaces/can-component-deactivate.interface.mjs +0 -2
- package/esm2022/shared/interfaces/cms-enum-values.interface.mjs +0 -2
- package/esm2022/shared/interfaces/cms-field-config.interface.mjs +0 -2
- package/esm2022/shared/interfaces/cms-model-config.interface.mjs +0 -2
- package/esm2022/shared/interfaces/cms-table-field.interface.mjs +0 -2
- package/esm2022/shared/interfaces/combined-filter-input.interface.mjs +0 -2
- package/esm2022/shared/interfaces/compress-options.interface.mjs +0 -2
- package/esm2022/shared/interfaces/cropping-options.interface.mjs +0 -2
- package/esm2022/shared/interfaces/field-object.interface.mjs +0 -2
- package/esm2022/shared/interfaces/field.interface.mjs +0 -2
- package/esm2022/shared/interfaces/filter-input.interface.mjs +0 -2
- package/esm2022/shared/interfaces/find-args.interface.mjs +0 -2
- package/esm2022/shared/interfaces/graphql-crud-type.interface.mjs +0 -2
- package/esm2022/shared/interfaces/graphql-fields-object.interface.mjs +0 -2
- package/esm2022/shared/interfaces/graphql-options.interface.mjs +0 -2
- package/esm2022/shared/interfaces/graphql-plus-options.interfacen.mjs +0 -2
- package/esm2022/shared/interfaces/graphql-type-collection.interface.mjs +0 -2
- package/esm2022/shared/interfaces/login-config.interface.mjs +0 -2
- package/esm2022/shared/interfaces/register-config.interface.mjs +0 -2
- package/esm2022/shared/interfaces/single-filter-input.interface.mjs +0 -2
- package/esm2022/shared/interfaces/sort-input.interface.mjs +0 -2
- package/esm2022/shared/interfaces/time-components.interface.mjs +0 -2
- package/esm2022/shared/interfaces/toast.interface.mjs +0 -2
- package/esm2022/shared/lenne.tech-ng-base-shared.mjs +0 -5
- package/esm2022/shared/public-api.mjs +0 -74
- package/esm2022/shared/services/auth.service.mjs +0 -152
- package/esm2022/shared/services/breadcrumb.service.mjs +0 -69
- package/esm2022/shared/services/cms.service.mjs +0 -82
- package/esm2022/shared/services/file.service.mjs +0 -86
- package/esm2022/shared/services/forms.service.mjs +0 -61
- package/esm2022/shared/services/graphql-meta.service.mjs +0 -132
- package/esm2022/shared/services/graphql-plus.service.mjs +0 -93
- package/esm2022/shared/services/graphql.service.mjs +0 -510
- package/esm2022/shared/services/image.service.mjs +0 -102
- package/esm2022/shared/services/loader.service.mjs +0 -78
- package/esm2022/shared/services/navigation.service.mjs +0 -38
- package/esm2022/shared/services/scroll.service.mjs +0 -207
- package/esm2022/shared/services/storage.service.mjs +0 -149
- package/esm2022/shared/services/toast.service.mjs +0 -39
- package/esm2022/shared/services/user.service.mjs +0 -160
- package/esm2022/shared/services/ws.service.mjs +0 -17
- package/esm2022/shared/types/graphql-fields.type.mjs +0 -2
- package/esm2022/shared/types/storage.type.mjs +0 -2
- package/esm2022/shared/validators/email.validator.mjs +0 -7
- package/esm2022/shared/validators/match.validator.mjs +0 -22
- package/esm2022/shared/validators/secure-password.validator.mjs +0 -7
- package/esm2022/src/base.module.mjs +0 -64
- package/esm2022/src/decorators/auto-unsubscribe.decorator.mjs +0 -23
- package/esm2022/src/directives/lazy-load.directive.mjs +0 -48
- package/esm2022/src/directives/match-height.directive.mjs +0 -92
- package/esm2022/src/directives/resizable.directive.mjs +0 -92
- package/esm2022/src/factories/apollo-options.factory.mjs +0 -108
- package/esm2022/src/functions/extract-files.function.mjs +0 -87
- package/esm2022/src/guards/auth.guard.mjs +0 -91
- package/esm2022/src/guards/can-deactivate.guard.mjs +0 -16
- package/esm2022/src/guards/logout.guard.mjs +0 -34
- package/esm2022/src/pipes/date-ago.pipe.mjs +0 -64
- package/esm2022/src/pipes/safe-html.pipe.mjs +0 -22
- package/esm2022/src/services/fullscreen.service.mjs +0 -51
- package/esm2022/src/services/seo.service.mjs +0 -117
- package/esm2022/src/services/theme.service.mjs +0 -44
- package/fesm2022/lenne.tech-ng-base-base-cms.mjs +0 -251
- package/fesm2022/lenne.tech-ng-base-base-cms.mjs.map +0 -1
- package/fesm2022/lenne.tech-ng-base-base-components.mjs +0 -2917
- package/fesm2022/lenne.tech-ng-base-base-components.mjs.map +0 -1
- package/fesm2022/lenne.tech-ng-base-base-prototype.mjs +0 -505
- package/fesm2022/lenne.tech-ng-base-base-prototype.mjs.map +0 -1
- package/fesm2022/lenne.tech-ng-base-shared.mjs +0 -2863
- package/fesm2022/lenne.tech-ng-base-shared.mjs.map +0 -1
- package/index.d.ts +0 -5
- package/public-api.d.ts +0 -17
- package/shared/classes/auth.class.d.ts +0 -10
- package/shared/classes/basic-user.class.d.ts +0 -27
- package/shared/classes/graphql-enum.class.d.ts +0 -7
- package/shared/classes/graphql-meta.class.d.ts +0 -66
- package/shared/classes/graphql-type.class.d.ts +0 -13
- package/shared/classes/helper.class.d.ts +0 -99
- package/shared/classes/sort.class.d.ts +0 -12
- package/shared/classes/standard.class.d.ts +0 -32
- package/shared/decorators/debounce.decorator.d.ts +0 -1
- package/shared/enums/comparison-operator.enum.d.ts +0 -14
- package/shared/enums/graphql-request-type.enum.d.ts +0 -8
- package/shared/enums/logical-operator.enum.d.ts +0 -8
- package/shared/enums/skeleton-type.enum.d.ts +0 -5
- package/shared/enums/sort-order.enum.d.ts +0 -4
- package/shared/enums/toast-type.enum.d.ts +0 -6
- package/shared/functions/ws-client.function.d.ts +0 -5
- package/shared/index.d.ts +0 -5
- package/shared/interfaces/base-module-config.interface.d.ts +0 -61
- package/shared/interfaces/breadcrumb.interface.d.ts +0 -4
- package/shared/interfaces/can-component-deactivate.interface.d.ts +0 -7
- package/shared/interfaces/cms-enum-values.interface.d.ts +0 -4
- package/shared/interfaces/cms-field-config.interface.d.ts +0 -45
- package/shared/interfaces/cms-model-config.interface.d.ts +0 -14
- package/shared/interfaces/cms-table-field.interface.d.ts +0 -10
- package/shared/interfaces/combined-filter-input.interface.d.ts +0 -9
- package/shared/interfaces/compress-options.interface.d.ts +0 -15
- package/shared/interfaces/cropping-options.interface.d.ts +0 -12
- package/shared/interfaces/field-object.interface.d.ts +0 -6
- package/shared/interfaces/field.interface.d.ts +0 -5
- package/shared/interfaces/filter-input.interface.d.ts +0 -9
- package/shared/interfaces/find-args.interface.d.ts +0 -11
- package/shared/interfaces/graphql-crud-type.interface.d.ts +0 -7
- package/shared/interfaces/graphql-fields-object.interface.d.ts +0 -6
- package/shared/interfaces/graphql-options.interface.d.ts +0 -11
- package/shared/interfaces/graphql-plus-options.interfacen.d.ts +0 -9
- package/shared/interfaces/graphql-type-collection.interface.d.ts +0 -7
- package/shared/interfaces/login-config.interface.d.ts +0 -6
- package/shared/interfaces/register-config.interface.d.ts +0 -4
- package/shared/interfaces/single-filter-input.interface.d.ts +0 -11
- package/shared/interfaces/sort-input.interface.d.ts +0 -5
- package/shared/interfaces/time-components.interface.d.ts +0 -6
- package/shared/interfaces/toast.interface.d.ts +0 -8
- package/shared/public-api.d.ts +0 -65
- package/shared/services/auth.service.d.ts +0 -44
- package/shared/services/breadcrumb.service.d.ts +0 -32
- package/shared/services/cms.service.d.ts +0 -27
- package/shared/services/file.service.d.ts +0 -22
- package/shared/services/forms.service.d.ts +0 -14
- package/shared/services/graphql-meta.service.d.ts +0 -45
- package/shared/services/graphql-plus.service.d.ts +0 -27
- package/shared/services/graphql.service.d.ts +0 -71
- package/shared/services/image.service.d.ts +0 -27
- package/shared/services/loader.service.d.ts +0 -32
- package/shared/services/navigation.service.d.ts +0 -15
- package/shared/services/scroll.service.d.ts +0 -85
- package/shared/services/storage.service.d.ts +0 -49
- package/shared/services/toast.service.d.ts +0 -15
- package/shared/services/user.service.d.ts +0 -77
- package/shared/services/ws.service.d.ts +0 -8
- package/shared/types/graphql-fields.type.d.ts +0 -5
- package/shared/types/storage.type.d.ts +0 -4
- package/shared/validators/email.validator.d.ts +0 -1
- package/shared/validators/match.validator.d.ts +0 -4
- package/shared/validators/secure-password.validator.d.ts +0 -1
- package/src/base.module.d.ts +0 -16
- package/src/decorators/auto-unsubscribe.decorator.d.ts +0 -5
- package/src/directives/lazy-load.directive.d.ts +0 -17
- package/src/directives/match-height.directive.d.ts +0 -20
- package/src/directives/resizable.directive.d.ts +0 -26
- package/src/factories/apollo-options.factory.d.ts +0 -16
- package/src/functions/extract-files.function.d.ts +0 -15
- package/src/guards/auth.guard.d.ts +0 -27
- package/src/guards/can-deactivate.guard.d.ts +0 -10
- package/src/guards/logout.guard.d.ts +0 -16
- package/src/pipes/date-ago.pipe.d.ts +0 -34
- package/src/pipes/safe-html.pipe.d.ts +0 -13
- package/src/services/fullscreen.service.d.ts +0 -18
- package/src/services/seo.service.d.ts +0 -61
- package/src/services/theme.service.d.ts +0 -17
|
@@ -0,0 +1,939 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { InjectionToken, Injector, PLATFORM_ID, Service, TransferState, computed, inject, makeEnvironmentProviders, makeStateKey, provideAppInitializer, signal } from "@angular/core";
|
|
3
|
+
import { Router } from "@angular/router";
|
|
4
|
+
import { LT_FETCH, LT_RUNTIME_CONFIG, LtApiUrlService, LtCookieService, isLtAbsoluteUrl, ltCredentialsFetch, ltSha256, mergeLtFeatureOptions } from "@lenne.tech/ng-base";
|
|
5
|
+
import { DOCUMENT, isPlatformServer } from "@angular/common";
|
|
6
|
+
import { HttpErrorResponse } from "@angular/common/http";
|
|
7
|
+
import { catchError, from, switchMap, throwError } from "rxjs";
|
|
8
|
+
const LT_AUTH_STATE_COOKIE_DEFAULT = "lt-auth-state";
|
|
9
|
+
const LT_JWT_TOKEN_COOKIE_DEFAULT = "lt-jwt-token";
|
|
10
|
+
const LT_AUTH_DEFAULTS = {
|
|
11
|
+
basePath: "/iam",
|
|
12
|
+
cookieNames: {
|
|
13
|
+
state: LT_AUTH_STATE_COOKIE_DEFAULT,
|
|
14
|
+
token: LT_JWT_TOKEN_COOKIE_DEFAULT
|
|
15
|
+
},
|
|
16
|
+
enableAdmin: false,
|
|
17
|
+
enablePasskey: true,
|
|
18
|
+
enableTwoFactor: true,
|
|
19
|
+
interceptor: {
|
|
20
|
+
enabled: true,
|
|
21
|
+
publicPaths: []
|
|
22
|
+
},
|
|
23
|
+
loginPath: "/auth/login",
|
|
24
|
+
plugins: [],
|
|
25
|
+
systemSetup: {
|
|
26
|
+
enabled: false,
|
|
27
|
+
setupPath: "/auth/setup"
|
|
28
|
+
},
|
|
29
|
+
twoFactorRedirectPath: "/auth/2fa"
|
|
30
|
+
};
|
|
31
|
+
const LT_AUTH_INPUT_OPTIONS = new InjectionToken("LT_AUTH_INPUT_OPTIONS", { factory: () => ({}) });
|
|
32
|
+
const LT_AUTH_OPTIONS = new InjectionToken("LT_AUTH_OPTIONS", { factory: () => {
|
|
33
|
+
const runtime = inject(LT_RUNTIME_CONFIG, { optional: true });
|
|
34
|
+
const merged = mergeLtFeatureOptions(LT_AUTH_DEFAULTS, inject(LT_AUTH_INPUT_OPTIONS), runtime?.lt.auth);
|
|
35
|
+
return {
|
|
36
|
+
...merged,
|
|
37
|
+
cookieNames: resolveLtAuthCookieNames(merged.cookieNames, runtime?.cookiePrefix)
|
|
38
|
+
};
|
|
39
|
+
} });
|
|
40
|
+
function resolveLtCookiePrefix(raw) {
|
|
41
|
+
return typeof raw === "string" ? raw.trim().replace(/[^A-Za-z0-9._-]/g, "") : "";
|
|
42
|
+
}
|
|
43
|
+
function resolveLtAuthCookieNames(configured, cookiePrefix) {
|
|
44
|
+
const prefix = resolveLtCookiePrefix(cookiePrefix);
|
|
45
|
+
return {
|
|
46
|
+
state: configured?.state && configured.state !== "lt-auth-state" ? configured.state : prefix ? `${prefix}-auth-state` : LT_AUTH_STATE_COOKIE_DEFAULT,
|
|
47
|
+
token: configured?.token && configured.token !== "lt-jwt-token" ? configured.token : prefix ? `${prefix}-jwt-token` : LT_JWT_TOKEN_COOKIE_DEFAULT
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const LT_AUTH_COOKIE_MAX_AGE = 604800;
|
|
51
|
+
const BETTER_AUTH_COOKIES = [
|
|
52
|
+
"better-auth.session_token",
|
|
53
|
+
"better-auth.session",
|
|
54
|
+
"__Secure-better-auth.session_token",
|
|
55
|
+
"session_token",
|
|
56
|
+
"session"
|
|
57
|
+
];
|
|
58
|
+
const BETTER_AUTH_COOKIE_PATHS = [
|
|
59
|
+
"/",
|
|
60
|
+
"/api",
|
|
61
|
+
"/api/iam",
|
|
62
|
+
"/iam"
|
|
63
|
+
];
|
|
64
|
+
function resolveLtAuthState(cookieString, stateCookieName) {
|
|
65
|
+
const prefix = `${stateCookieName}=`;
|
|
66
|
+
let fallback = null;
|
|
67
|
+
for (const entry of (cookieString || "").split(/;\s*/)) {
|
|
68
|
+
if (!entry.startsWith(prefix)) continue;
|
|
69
|
+
try {
|
|
70
|
+
const state = JSON.parse(decodeURIComponent(entry.slice(prefix.length)));
|
|
71
|
+
if (state?.user) return state;
|
|
72
|
+
if (state) fallback = state;
|
|
73
|
+
} catch {}
|
|
74
|
+
}
|
|
75
|
+
return fallback;
|
|
76
|
+
}
|
|
77
|
+
var LtAuthStateService = class LtAuthStateService {
|
|
78
|
+
cookies = inject(LtCookieService);
|
|
79
|
+
options = inject(LT_AUTH_OPTIONS);
|
|
80
|
+
document = inject(DOCUMENT);
|
|
81
|
+
isServer = isPlatformServer(inject(PLATFORM_ID));
|
|
82
|
+
get cookieNames() {
|
|
83
|
+
return this.options.cookieNames;
|
|
84
|
+
}
|
|
85
|
+
readState() {
|
|
86
|
+
return resolveLtAuthState(this.cookies.raw(), this.cookieNames.state);
|
|
87
|
+
}
|
|
88
|
+
writeState(state) {
|
|
89
|
+
if (this.isServer) return;
|
|
90
|
+
const encoded = JSON.stringify(state);
|
|
91
|
+
if (encodeURIComponent(encoded).length > 3500 && typeof ngDevMode !== "undefined" && ngDevMode) console.warn(`[@lenne.tech/ng-base] The auth-state cookie is ${encodeURIComponent(encoded).length} bytes; browsers drop cookies over 4 KB.`);
|
|
92
|
+
this.cookies.set(this.cookieNames.state, encoded, { maxAge: LT_AUTH_COOKIE_MAX_AGE });
|
|
93
|
+
}
|
|
94
|
+
getAuthMode() {
|
|
95
|
+
return this.readState()?.authMode === "jwt" ? "jwt" : "cookie";
|
|
96
|
+
}
|
|
97
|
+
setAuthMode(mode) {
|
|
98
|
+
const current = this.readState();
|
|
99
|
+
this.writeState({
|
|
100
|
+
authMode: mode,
|
|
101
|
+
user: current?.user ?? null
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
getJwtToken() {
|
|
105
|
+
if (this.isServer) return null;
|
|
106
|
+
let invalid = false;
|
|
107
|
+
for (const raw of this.cookies.getAll(this.cookieNames.token)) {
|
|
108
|
+
const token = parseToken(raw);
|
|
109
|
+
if (isLtJwtShaped(token)) return token;
|
|
110
|
+
invalid ||= !!token;
|
|
111
|
+
}
|
|
112
|
+
if (invalid) this.deleteEverywhere(this.cookieNames.token);
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
setJwtToken(token) {
|
|
116
|
+
if (this.isServer) return false;
|
|
117
|
+
if (!token) {
|
|
118
|
+
this.deleteEverywhere(this.cookieNames.token);
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
if (!isLtJwtShaped(token)) {
|
|
122
|
+
this.deleteEverywhere(this.cookieNames.token);
|
|
123
|
+
console.warn("[@lenne.tech/ng-base] Refused to store a token that is not a JWT as JWT.");
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
this.cookies.set(this.cookieNames.token, JSON.stringify(token), { maxAge: LT_AUTH_COOKIE_MAX_AGE });
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
purgeInvalidJwt() {
|
|
130
|
+
if (this.isServer) return false;
|
|
131
|
+
if (!this.cookies.getAll(this.cookieNames.token).map(parseToken).some((token) => token && !isLtJwtShaped(token))) return false;
|
|
132
|
+
this.deleteEverywhere(this.cookieNames.token);
|
|
133
|
+
const state = this.readState();
|
|
134
|
+
if (state?.authMode === "jwt") this.writeState({
|
|
135
|
+
authMode: "cookie",
|
|
136
|
+
user: state.user
|
|
137
|
+
});
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
isAuthenticated() {
|
|
141
|
+
return !!this.readState()?.user;
|
|
142
|
+
}
|
|
143
|
+
readUser() {
|
|
144
|
+
return this.readState()?.user ?? null;
|
|
145
|
+
}
|
|
146
|
+
clearAuthCookies() {
|
|
147
|
+
if (this.isServer) return;
|
|
148
|
+
this.deleteEverywhere(this.cookieNames.state);
|
|
149
|
+
this.deleteEverywhere(this.cookieNames.token);
|
|
150
|
+
for (const name of BETTER_AUTH_COOKIES) for (const path of BETTER_AUTH_COOKIE_PATHS) this.cookies.delete(name, { path });
|
|
151
|
+
}
|
|
152
|
+
deleteEverywhere(name) {
|
|
153
|
+
const host = this.document.location?.hostname;
|
|
154
|
+
this.cookies.delete(name, { path: "/" });
|
|
155
|
+
if (host) this.cookies.delete(name, {
|
|
156
|
+
domain: host,
|
|
157
|
+
path: "/"
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
161
|
+
minVersion: "12.0.0",
|
|
162
|
+
version: "22.2.4",
|
|
163
|
+
ngImport: i0,
|
|
164
|
+
type: LtAuthStateService,
|
|
165
|
+
deps: [],
|
|
166
|
+
target: i0.ɵɵFactoryTarget.Service
|
|
167
|
+
});
|
|
168
|
+
static ɵprov = i0.ɵɵngDeclareService({
|
|
169
|
+
minVersion: "22.0.0",
|
|
170
|
+
version: "22.2.4",
|
|
171
|
+
ngImport: i0,
|
|
172
|
+
type: LtAuthStateService
|
|
173
|
+
});
|
|
174
|
+
};
|
|
175
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
176
|
+
minVersion: "12.0.0",
|
|
177
|
+
version: "22.2.4",
|
|
178
|
+
ngImport: i0,
|
|
179
|
+
type: LtAuthStateService,
|
|
180
|
+
decorators: [{ type: Service }]
|
|
181
|
+
});
|
|
182
|
+
function isLtJwtShaped(value) {
|
|
183
|
+
return typeof value === "string" && value.startsWith("eyJ") && value.split(".").length === 3 && value.split(".").every((part) => part.length > 0);
|
|
184
|
+
}
|
|
185
|
+
function ltJwtExpiresWithin(token, marginMs, now = Date.now()) {
|
|
186
|
+
const payload = token.split(".")[1];
|
|
187
|
+
if (!payload) return false;
|
|
188
|
+
try {
|
|
189
|
+
const base64 = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
190
|
+
const claims = JSON.parse(atob(base64.padEnd(base64.length + (4 - base64.length % 4) % 4, "=")));
|
|
191
|
+
return typeof claims.exp === "number" && claims.exp * 1e3 - now <= marginMs;
|
|
192
|
+
} catch {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function parseToken(raw) {
|
|
197
|
+
if (!raw) return null;
|
|
198
|
+
try {
|
|
199
|
+
const parsed = JSON.parse(raw);
|
|
200
|
+
return typeof parsed === "string" && parsed ? parsed : null;
|
|
201
|
+
} catch {
|
|
202
|
+
return raw;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const LT_AUTH_PUBLIC_PATHS = [
|
|
206
|
+
"/auth/login",
|
|
207
|
+
"/auth/register",
|
|
208
|
+
"/auth/forgot-password",
|
|
209
|
+
"/auth/reset-password",
|
|
210
|
+
"/auth/2fa",
|
|
211
|
+
"/auth/setup",
|
|
212
|
+
"/auth/verify-email"
|
|
213
|
+
];
|
|
214
|
+
const LT_AUTH_ENDPOINT_FRAGMENTS = [
|
|
215
|
+
"/sign-in",
|
|
216
|
+
"/sign-up",
|
|
217
|
+
"/sign-out",
|
|
218
|
+
"/forgot-password",
|
|
219
|
+
"/reset-password",
|
|
220
|
+
"/verify-email",
|
|
221
|
+
"/get-session",
|
|
222
|
+
"/list-sessions",
|
|
223
|
+
"/revoke-session",
|
|
224
|
+
"/revoke-other-sessions",
|
|
225
|
+
"/token",
|
|
226
|
+
"/passkey/",
|
|
227
|
+
"/list-user-passkeys",
|
|
228
|
+
"/generate-register-options",
|
|
229
|
+
"/verify-registration",
|
|
230
|
+
"/generate-authenticate-options",
|
|
231
|
+
"/verify-authentication",
|
|
232
|
+
"/two-factor/"
|
|
233
|
+
];
|
|
234
|
+
const LT_AUTH_COOKIE_PATHS = [
|
|
235
|
+
"/passkey/",
|
|
236
|
+
"/two-factor/",
|
|
237
|
+
"/2fa/",
|
|
238
|
+
"/get-session"
|
|
239
|
+
];
|
|
240
|
+
function isLtAuthEndpoint(url) {
|
|
241
|
+
return LT_AUTH_ENDPOINT_FRAGMENTS.some((fragment) => url.includes(fragment));
|
|
242
|
+
}
|
|
243
|
+
function ltUrlRequiresCookies(url) {
|
|
244
|
+
return LT_AUTH_COOKIE_PATHS.some((path) => url.includes(path));
|
|
245
|
+
}
|
|
246
|
+
function ltRequestUrl(input) {
|
|
247
|
+
if (typeof input === "string") return input;
|
|
248
|
+
return input instanceof URL ? input.href : input.url;
|
|
249
|
+
}
|
|
250
|
+
function ltPathOf(url) {
|
|
251
|
+
return url.split(/[?#]/)[0] || "/";
|
|
252
|
+
}
|
|
253
|
+
function isLtApiRequest(url, baseUrl, origin) {
|
|
254
|
+
if (baseUrl && hasPrefix(url, baseUrl)) return true;
|
|
255
|
+
let path = url;
|
|
256
|
+
if (origin && origin !== "null" && hasPrefix(url, origin)) path = url.slice(origin.length) || "/";
|
|
257
|
+
if (!path.startsWith("/") || path.startsWith("//")) return false;
|
|
258
|
+
if (hasPrefix(path, "/api")) return true;
|
|
259
|
+
if (!baseUrl) return true;
|
|
260
|
+
return baseUrl.startsWith("/") && hasPrefix(path, baseUrl);
|
|
261
|
+
}
|
|
262
|
+
function hasPrefix(value, prefix) {
|
|
263
|
+
if (!value.startsWith(prefix)) return false;
|
|
264
|
+
const next = value.charAt(prefix.length);
|
|
265
|
+
return next === "" || next === "/" || next === "?" || next === "#" || prefix.endsWith("/");
|
|
266
|
+
}
|
|
267
|
+
const LT_SESSION_ALIVE_TTL_MS = 1e3;
|
|
268
|
+
const LT_SESSION_LOSS_GUARD_MS = 1e3;
|
|
269
|
+
function createLtSessionLossDetector(host, config) {
|
|
270
|
+
let handling = false;
|
|
271
|
+
let aliveUntil = 0;
|
|
272
|
+
const isPublicRoute = () => {
|
|
273
|
+
const current = host.currentUrl();
|
|
274
|
+
if (!current) return false;
|
|
275
|
+
const path = ltPathOf(current);
|
|
276
|
+
return config.publicPaths.some((publicPath) => path.startsWith(publicPath));
|
|
277
|
+
};
|
|
278
|
+
const probe = async () => {
|
|
279
|
+
if (Date.now() < aliveUntil) return true;
|
|
280
|
+
let verdict;
|
|
281
|
+
try {
|
|
282
|
+
const response = await host.probeSession();
|
|
283
|
+
if (response.status === 401 || response.status === 403) return false;
|
|
284
|
+
if (!response.ok) return null;
|
|
285
|
+
const data = await response.json().catch(() => null);
|
|
286
|
+
verdict = Boolean(data && (data.user || data.session));
|
|
287
|
+
if (verdict && host.isJwtMode()) await host.switchToJwtMode().catch(() => false);
|
|
288
|
+
} catch {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
if (verdict) aliveUntil = Date.now() + LT_SESSION_ALIVE_TTL_MS;
|
|
292
|
+
return verdict;
|
|
293
|
+
};
|
|
294
|
+
return { async handle(url) {
|
|
295
|
+
if (!config.enabled || handling || url && isLtAuthEndpoint(url) || isPublicRoute() || !host.isAuthenticated()) return false;
|
|
296
|
+
handling = true;
|
|
297
|
+
let loggedOut = false;
|
|
298
|
+
try {
|
|
299
|
+
if (await probe() !== false) return false;
|
|
300
|
+
loggedOut = true;
|
|
301
|
+
host.clearUser();
|
|
302
|
+
const current = host.currentUrl();
|
|
303
|
+
const redirect = current && ltPathOf(current) !== config.loginPath ? `?redirect=${encodeURIComponent(current)}` : "";
|
|
304
|
+
host.navigate(`${config.loginPath}${redirect}`);
|
|
305
|
+
return true;
|
|
306
|
+
} catch (error) {
|
|
307
|
+
console.error("[@lenne.tech/ng-base] Handling a 401 failed:", error);
|
|
308
|
+
return loggedOut;
|
|
309
|
+
} finally {
|
|
310
|
+
if (loggedOut) setTimeout(() => {
|
|
311
|
+
handling = false;
|
|
312
|
+
}, LT_SESSION_LOSS_GUARD_MS);
|
|
313
|
+
else handling = false;
|
|
314
|
+
}
|
|
315
|
+
} };
|
|
316
|
+
}
|
|
317
|
+
const LT_AUTH_SIGN_OUT_HOOKS = new InjectionToken("LT_AUTH_SIGN_OUT_HOOKS", { factory: () => [] });
|
|
318
|
+
const LT_AUTH_FEATURES_STATE_KEY = makeStateKey("lt-auth-features");
|
|
319
|
+
const LT_VALIDATE_SESSION_TIMEOUT_MS = 1e4;
|
|
320
|
+
const FEATURES_TIMEOUT_MS = 5e3;
|
|
321
|
+
const AUTHZ_KEYS = [
|
|
322
|
+
"banExpires",
|
|
323
|
+
"banReason",
|
|
324
|
+
"banned",
|
|
325
|
+
"emailVerified",
|
|
326
|
+
"role",
|
|
327
|
+
"roles",
|
|
328
|
+
"twoFactorEnabled"
|
|
329
|
+
];
|
|
330
|
+
function readLtAuthAnswer(result) {
|
|
331
|
+
const outer = result && typeof result === "object" ? result : {};
|
|
332
|
+
const data = outer["data"] && typeof outer["data"] === "object" ? outer["data"] : {};
|
|
333
|
+
const pick = (key) => data[key] ?? outer[key];
|
|
334
|
+
const token = pick("token");
|
|
335
|
+
const user = pick("user");
|
|
336
|
+
const sessionObject = pick("session");
|
|
337
|
+
const failed = !!outer["error"] || pick("success") === false;
|
|
338
|
+
const proven = pick("success") === true || typeof token === "string" && !!token || !!sessionObject && typeof sessionObject === "object";
|
|
339
|
+
return {
|
|
340
|
+
emailVerificationRequired: pick("emailVerificationRequired") === true,
|
|
341
|
+
jwt: isLtJwtShaped(token) ? token : null,
|
|
342
|
+
session: proven && !failed,
|
|
343
|
+
twoFactor: pick("requiresTwoFactor") === true || pick("twoFactorRedirect") === true,
|
|
344
|
+
user: user && typeof user === "object" ? user : null
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
var LtAuthStore = class LtAuthStore {
|
|
348
|
+
api = inject(LtApiUrlService);
|
|
349
|
+
authState = inject(LtAuthStateService);
|
|
350
|
+
options = inject(LT_AUTH_OPTIONS);
|
|
351
|
+
runtimeConfig = inject(LT_RUNTIME_CONFIG, { optional: true });
|
|
352
|
+
transferState = inject(TransferState);
|
|
353
|
+
injector = inject(Injector);
|
|
354
|
+
document = inject(DOCUMENT);
|
|
355
|
+
signOutHooks = inject(LT_AUTH_SIGN_OUT_HOOKS);
|
|
356
|
+
isServer = isPlatformServer(inject(PLATFORM_ID));
|
|
357
|
+
purgedInvalidJwt = this.authState.purgeInvalidJwt();
|
|
358
|
+
initialState = this.authState.readState();
|
|
359
|
+
transferredFeatures = this.isServer ? null : this.transferState.get(LT_AUTH_FEATURES_STATE_KEY, null);
|
|
360
|
+
userState = signal(this.initialState?.user ?? null, ...ngDevMode ? [{ debugName: "userState" }] : /* istanbul ignore next */ []);
|
|
361
|
+
modeState = signal(this.initialState?.authMode === "jwt" ? "jwt" : "cookie", ...ngDevMode ? [{ debugName: "modeState" }] : /* istanbul ignore next */ []);
|
|
362
|
+
loadingState = signal(false, ...ngDevMode ? [{ debugName: "loadingState" }] : /* istanbul ignore next */ []);
|
|
363
|
+
featuresState = signal(this.transferredFeatures ?? {}, ...ngDevMode ? [{ debugName: "featuresState" }] : /* istanbul ignore next */ []);
|
|
364
|
+
featuresLoaded = this.transferredFeatures !== null;
|
|
365
|
+
featuresRequest = null;
|
|
366
|
+
jwtMint = null;
|
|
367
|
+
sessionLoss = createLtSessionLossDetector({
|
|
368
|
+
clearUser: () => this.clearUser(),
|
|
369
|
+
currentUrl: () => this.currentUrl(),
|
|
370
|
+
isAuthenticated: () => this.isAuthenticated(),
|
|
371
|
+
isJwtMode: () => this.isJwtMode(),
|
|
372
|
+
navigate: (url) => this.navigate(url),
|
|
373
|
+
probeSession: () => this.fetchWithAuth(this.authUrl("/get-session"), { method: "GET" }),
|
|
374
|
+
switchToJwtMode: () => this.switchToJwtMode()
|
|
375
|
+
}, {
|
|
376
|
+
enabled: this.options.interceptor.enabled,
|
|
377
|
+
loginPath: this.options.loginPath,
|
|
378
|
+
publicPaths: [.../* @__PURE__ */ new Set([
|
|
379
|
+
...LT_AUTH_PUBLIC_PATHS,
|
|
380
|
+
...this.options.interceptor.publicPaths,
|
|
381
|
+
this.options.loginPath,
|
|
382
|
+
this.options.twoFactorRedirectPath,
|
|
383
|
+
this.options.systemSetup.setupPath
|
|
384
|
+
])]
|
|
385
|
+
});
|
|
386
|
+
user = this.userState.asReadonly();
|
|
387
|
+
isAuthenticated = computed(() => !!this.userState(), ...ngDevMode ? [{ debugName: "isAuthenticated" }] : /* istanbul ignore next */ []);
|
|
388
|
+
authMode = this.modeState.asReadonly();
|
|
389
|
+
isJwtMode = computed(() => this.modeState() === "jwt", ...ngDevMode ? [{ debugName: "isJwtMode" }] : /* istanbul ignore next */ []);
|
|
390
|
+
isLoading = this.loadingState.asReadonly();
|
|
391
|
+
isAdmin = computed(() => hasLtRole(this.userState(), "admin"), ...ngDevMode ? [{ debugName: "isAdmin" }] : /* istanbul ignore next */ []);
|
|
392
|
+
is2FAEnabled = computed(() => !!this.userState()?.twoFactorEnabled, ...ngDevMode ? [{ debugName: "is2FAEnabled" }] : /* istanbul ignore next */ []);
|
|
393
|
+
features = this.featuresState.asReadonly();
|
|
394
|
+
passkeySupported = computed(() => this.options.enablePasskey && !!this.featuresState()["passkey"] && typeof globalThis.PublicKeyCredential !== "undefined", ...ngDevMode ? [{ debugName: "passkeySupported" }] : /* istanbul ignore next */ []);
|
|
395
|
+
jwtToken() {
|
|
396
|
+
return this.isJwtMode() ? this.authState.getJwtToken() : null;
|
|
397
|
+
}
|
|
398
|
+
hasRole(role) {
|
|
399
|
+
return hasLtRole(this.userState(), role);
|
|
400
|
+
}
|
|
401
|
+
hasAnyRole(...roles) {
|
|
402
|
+
return roles.some((role) => hasLtRole(this.userState(), role));
|
|
403
|
+
}
|
|
404
|
+
fetchFeatures() {
|
|
405
|
+
if (this.isServer && this.api.resolve().missing) return Promise.resolve(this.featuresState());
|
|
406
|
+
if (!this.featuresRequest) this.featuresRequest = this.loadFeatures().finally(() => {
|
|
407
|
+
this.featuresRequest = null;
|
|
408
|
+
});
|
|
409
|
+
return this.featuresRequest;
|
|
410
|
+
}
|
|
411
|
+
ensureFeatures() {
|
|
412
|
+
return this.featuresLoaded ? Promise.resolve(this.featuresState()) : this.fetchFeatures();
|
|
413
|
+
}
|
|
414
|
+
setUser(user, mode = "cookie") {
|
|
415
|
+
const normalised = user ? {
|
|
416
|
+
...user,
|
|
417
|
+
image: user.image ?? void 0
|
|
418
|
+
} : null;
|
|
419
|
+
this.userState.set(normalised);
|
|
420
|
+
this.modeState.set(mode);
|
|
421
|
+
this.authState.writeState({
|
|
422
|
+
authMode: mode,
|
|
423
|
+
user: normalised
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
clearUser() {
|
|
427
|
+
this.userState.set(null);
|
|
428
|
+
this.modeState.set("cookie");
|
|
429
|
+
this.authState.clearAuthCookies();
|
|
430
|
+
}
|
|
431
|
+
async signOut(options) {
|
|
432
|
+
this.loadingState.set(true);
|
|
433
|
+
try {
|
|
434
|
+
const userId = this.userState()?.id;
|
|
435
|
+
for (const hook of this.signOutHooks) await runHook(() => hook.beforeSignOut?.(userId ? String(userId) : null), "beforeSignOut");
|
|
436
|
+
try {
|
|
437
|
+
await this.fetchWithAuth(this.authUrl("/sign-out"), {
|
|
438
|
+
body: "{}",
|
|
439
|
+
credentials: "include",
|
|
440
|
+
headers: {
|
|
441
|
+
...options?.headers,
|
|
442
|
+
"content-type": "application/json"
|
|
443
|
+
},
|
|
444
|
+
method: "POST",
|
|
445
|
+
signal: options?.signal
|
|
446
|
+
});
|
|
447
|
+
} catch (error) {
|
|
448
|
+
console.error("[@lenne.tech/ng-base] The sign-out request failed; the local session is cleared anyway:", error);
|
|
449
|
+
}
|
|
450
|
+
this.clearUser();
|
|
451
|
+
for (const hook of this.signOutHooks) await runHook(() => hook.afterSignOut?.(), "afterSignOut");
|
|
452
|
+
} finally {
|
|
453
|
+
this.loadingState.set(false);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
async validateSession() {
|
|
457
|
+
if (this.isServer) return !!this.cachedUser();
|
|
458
|
+
try {
|
|
459
|
+
const sessionUser = (await withTimeout(this.fetchSession(), LT_VALIDATE_SESSION_TIMEOUT_MS))?.user;
|
|
460
|
+
if (sessionUser) {
|
|
461
|
+
this.setUser(this.mergeSessionUser(sessionUser), this.modeState());
|
|
462
|
+
if (!this.isJwtMode()) this.prefetchJwt();
|
|
463
|
+
return true;
|
|
464
|
+
}
|
|
465
|
+
const cached = this.cachedUser();
|
|
466
|
+
if (cached) {
|
|
467
|
+
if (!this.userState()) this.userState.set(cached);
|
|
468
|
+
this.prefetchJwt();
|
|
469
|
+
return true;
|
|
470
|
+
}
|
|
471
|
+
return false;
|
|
472
|
+
} catch {
|
|
473
|
+
return !!this.cachedUser();
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
async fetchWithAuth(input, init = {}) {
|
|
477
|
+
const url = ltRequestUrl(input);
|
|
478
|
+
if (!isLtApiRequest(url, this.api.resolve().baseUrl, this.document.location?.origin)) return ltCredentialsFetch(input, init);
|
|
479
|
+
const ownAuthorization = new Headers(init.headers ?? (input instanceof Request ? input.headers : void 0)).has("Authorization");
|
|
480
|
+
const sentToken = !ownAuthorization && this.isJwtMode() ? await this.currentJwt() : null;
|
|
481
|
+
const retryInput = input instanceof Request ? input.clone() : input;
|
|
482
|
+
const response = await this.send(input, init, url, sentToken, this.isJwtMode());
|
|
483
|
+
if (response.status !== 401) return response;
|
|
484
|
+
const freshToken = ownAuthorization ? null : await this.recoverFrom401(url, sentToken);
|
|
485
|
+
const final = freshToken ? await this.send(retryInput, init, url, freshToken, true) : response;
|
|
486
|
+
if (final.status === 401) this.handleUnauthorized(url);
|
|
487
|
+
return final;
|
|
488
|
+
}
|
|
489
|
+
async recoverFrom401(url, sentToken) {
|
|
490
|
+
if (this.isServer || isLtAuthEndpoint(url) || !this.isAuthenticated()) return null;
|
|
491
|
+
if (sentToken && ltUrlRequiresCookies(url)) return null;
|
|
492
|
+
const current = this.jwtToken();
|
|
493
|
+
if (current && current !== sentToken) return current;
|
|
494
|
+
return this.mintJwt();
|
|
495
|
+
}
|
|
496
|
+
handleUnauthorized(url) {
|
|
497
|
+
if (this.isServer) return Promise.resolve(false);
|
|
498
|
+
return this.sessionLoss.handle(url);
|
|
499
|
+
}
|
|
500
|
+
async switchToJwtMode() {
|
|
501
|
+
return !!await this.mintJwt();
|
|
502
|
+
}
|
|
503
|
+
async refreshJwtToken() {
|
|
504
|
+
if (!this.isJwtMode() || !this.authState.getJwtToken()) return false;
|
|
505
|
+
return !!await this.mintJwt();
|
|
506
|
+
}
|
|
507
|
+
absoluteAppUrl(path) {
|
|
508
|
+
if (isLtAbsoluteUrl(path)) return path;
|
|
509
|
+
const origin = this.isServer ? "" : this.document.location?.origin;
|
|
510
|
+
const base = (this.runtimeConfig?.siteUrl || (origin && origin !== "null" ? origin : "")).replace(/\/+$/, "");
|
|
511
|
+
if (!base) throw new Error("[@lenne.tech/ng-base] absoluteAppUrl: no site URL known. Set NG_PUBLIC_SITE_URL.");
|
|
512
|
+
return `${base}${path.startsWith("/") ? path : `/${path}`}`;
|
|
513
|
+
}
|
|
514
|
+
authUrl(path) {
|
|
515
|
+
const basePath = (this.options.basePath || "/iam").replace(/\/+$/, "");
|
|
516
|
+
return this.api.buildUrl(`${basePath.startsWith("/") ? basePath : `/${basePath}`}${path}`);
|
|
517
|
+
}
|
|
518
|
+
async withLoading(task) {
|
|
519
|
+
this.loadingState.set(true);
|
|
520
|
+
try {
|
|
521
|
+
return await task();
|
|
522
|
+
} finally {
|
|
523
|
+
this.loadingState.set(false);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
applyAuthResult(result) {
|
|
527
|
+
const answer = readLtAuthAnswer(result);
|
|
528
|
+
if (answer.twoFactor || answer.emailVerificationRequired || !answer.session || !answer.user) return false;
|
|
529
|
+
if (answer.jwt) {
|
|
530
|
+
this.authState.setJwtToken(answer.jwt);
|
|
531
|
+
this.setUser(answer.user, "jwt");
|
|
532
|
+
return true;
|
|
533
|
+
}
|
|
534
|
+
this.setUser(answer.user, "cookie");
|
|
535
|
+
this.prefetchJwt();
|
|
536
|
+
return true;
|
|
537
|
+
}
|
|
538
|
+
async adoptVerifiedSession(result) {
|
|
539
|
+
const { jwt, user } = readLtAuthAnswer(result);
|
|
540
|
+
const mode = jwt && this.authState.setJwtToken(jwt) ? "jwt" : "cookie";
|
|
541
|
+
if (user) {
|
|
542
|
+
this.setUser(user, mode);
|
|
543
|
+
if (mode === "cookie") this.prefetchJwt();
|
|
544
|
+
return this.userState() ?? void 0;
|
|
545
|
+
}
|
|
546
|
+
this.modeState.set(mode);
|
|
547
|
+
const loaded = await this.loadSessionUser(mode);
|
|
548
|
+
if (!loaded) this.clearUser();
|
|
549
|
+
return loaded;
|
|
550
|
+
}
|
|
551
|
+
async loadSessionUser(mode = this.modeState()) {
|
|
552
|
+
try {
|
|
553
|
+
const data = await this.fetchSession();
|
|
554
|
+
if (!data?.user) return;
|
|
555
|
+
this.setUser(this.mergeSessionUser(data.user), mode);
|
|
556
|
+
if (mode === "cookie") this.prefetchJwt();
|
|
557
|
+
return this.userState() ?? void 0;
|
|
558
|
+
} catch {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
async currentJwt() {
|
|
563
|
+
const token = this.jwtToken();
|
|
564
|
+
return this.jwtNeedsRefresh() ? await this.mintJwt() ?? token : token;
|
|
565
|
+
}
|
|
566
|
+
jwtNeedsRefresh() {
|
|
567
|
+
const token = this.jwtToken();
|
|
568
|
+
return !!token && !this.isServer && ltJwtExpiresWithin(token, 6e4);
|
|
569
|
+
}
|
|
570
|
+
navigateKeepingRedirect(path) {
|
|
571
|
+
const router = this.injector.get(Router, null);
|
|
572
|
+
const current = router ? router.parseUrl(router.url).queryParams["redirect"] : new URLSearchParams(this.document.location?.search ?? "").get("redirect");
|
|
573
|
+
const redirect = typeof current === "string" && current.startsWith("/") && !current.startsWith("//") ? current : null;
|
|
574
|
+
if (!redirect || /[?&]redirect=/.test(path)) {
|
|
575
|
+
this.navigate(path);
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
this.navigate(`${path}${path.includes("?") ? "&" : "?"}redirect=${encodeURIComponent(redirect)}`);
|
|
579
|
+
}
|
|
580
|
+
navigate(url) {
|
|
581
|
+
const router = this.injector.get(Router, null);
|
|
582
|
+
if (router) {
|
|
583
|
+
router.navigateByUrl(url).catch((error) => console.error("[@lenne.tech/ng-base] Navigation failed:", error));
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
if (!this.isServer) this.document.location.assign(url);
|
|
587
|
+
}
|
|
588
|
+
mergeSessionUser(sessionUser) {
|
|
589
|
+
const cached = this.cachedUser();
|
|
590
|
+
if (!cached?.id || !sessionUser?.id || cached.id !== sessionUser.id) return sessionUser;
|
|
591
|
+
const merged = {
|
|
592
|
+
...cached,
|
|
593
|
+
...sessionUser
|
|
594
|
+
};
|
|
595
|
+
for (const key of AUTHZ_KEYS) if (!(key in sessionUser)) delete merged[key];
|
|
596
|
+
return merged;
|
|
597
|
+
}
|
|
598
|
+
cachedUser() {
|
|
599
|
+
return this.authState.readUser() ?? this.userState();
|
|
600
|
+
}
|
|
601
|
+
async fetchSession() {
|
|
602
|
+
const response = await this.fetchWithAuth(this.authUrl("/get-session"), { method: "GET" });
|
|
603
|
+
if (!response.ok) return null;
|
|
604
|
+
return await response.json().catch(() => null) ?? null;
|
|
605
|
+
}
|
|
606
|
+
mintJwt() {
|
|
607
|
+
if (this.isServer) return Promise.resolve(null);
|
|
608
|
+
if (!this.jwtMint) this.jwtMint = this.requestJwt().then((token) => {
|
|
609
|
+
if (token && this.authState.setJwtToken(token)) {
|
|
610
|
+
this.modeState.set("jwt");
|
|
611
|
+
this.persistState();
|
|
612
|
+
return token;
|
|
613
|
+
}
|
|
614
|
+
return null;
|
|
615
|
+
}).finally(() => {
|
|
616
|
+
this.jwtMint = null;
|
|
617
|
+
});
|
|
618
|
+
return this.jwtMint;
|
|
619
|
+
}
|
|
620
|
+
prefetchJwt() {
|
|
621
|
+
if (this.isServer) return;
|
|
622
|
+
this.requestJwt().then((token) => {
|
|
623
|
+
if (token && this.userState()) this.authState.setJwtToken(token);
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
async requestJwt() {
|
|
627
|
+
const current = this.jwtToken();
|
|
628
|
+
const bearer = current && !ltJwtExpiresWithin(current, 0) ? current : null;
|
|
629
|
+
try {
|
|
630
|
+
const response = await fetch(this.authUrl("/token"), {
|
|
631
|
+
credentials: "include",
|
|
632
|
+
headers: bearer ? { Authorization: `Bearer ${bearer}` } : void 0,
|
|
633
|
+
method: "GET"
|
|
634
|
+
});
|
|
635
|
+
if (!response.ok) return null;
|
|
636
|
+
return stringOrNull((await response.json())?.token);
|
|
637
|
+
} catch {
|
|
638
|
+
return null;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
async loadFeatures() {
|
|
642
|
+
const controller = new AbortController();
|
|
643
|
+
const timer = setTimeout(() => controller.abort(), FEATURES_TIMEOUT_MS);
|
|
644
|
+
try {
|
|
645
|
+
const response = await fetch(this.authUrl("/features"), {
|
|
646
|
+
headers: { accept: "application/json" },
|
|
647
|
+
signal: controller.signal
|
|
648
|
+
});
|
|
649
|
+
if (response.ok) {
|
|
650
|
+
const body = await response.json();
|
|
651
|
+
if (body && typeof body === "object" && !Array.isArray(body)) {
|
|
652
|
+
this.featuresState.set(body);
|
|
653
|
+
this.featuresLoaded = true;
|
|
654
|
+
if (this.isServer) this.transferState.set(LT_AUTH_FEATURES_STATE_KEY, body);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
} catch {} finally {
|
|
658
|
+
clearTimeout(timer);
|
|
659
|
+
}
|
|
660
|
+
return this.featuresState();
|
|
661
|
+
}
|
|
662
|
+
send(input, init, url, token, jwtMode) {
|
|
663
|
+
const headers = new Headers(init.headers ?? (input instanceof Request ? input.headers : void 0));
|
|
664
|
+
if (token && !headers.has("Authorization")) headers.set("Authorization", `Bearer ${token}`);
|
|
665
|
+
const credentials = init.credentials ?? (jwtMode && !ltUrlRequiresCookies(url) ? "omit" : "include");
|
|
666
|
+
return fetch(input, {
|
|
667
|
+
...init,
|
|
668
|
+
credentials,
|
|
669
|
+
headers
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
persistState() {
|
|
673
|
+
this.authState.writeState({
|
|
674
|
+
authMode: this.modeState(),
|
|
675
|
+
user: this.userState()
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
currentUrl() {
|
|
679
|
+
const router = this.injector.get(Router, null);
|
|
680
|
+
if (router) return router.url;
|
|
681
|
+
const location = this.document.location;
|
|
682
|
+
return location ? `${location.pathname}${location.search}${location.hash}` : null;
|
|
683
|
+
}
|
|
684
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
685
|
+
minVersion: "12.0.0",
|
|
686
|
+
version: "22.2.4",
|
|
687
|
+
ngImport: i0,
|
|
688
|
+
type: LtAuthStore,
|
|
689
|
+
deps: [],
|
|
690
|
+
target: i0.ɵɵFactoryTarget.Service
|
|
691
|
+
});
|
|
692
|
+
static ɵprov = i0.ɵɵngDeclareService({
|
|
693
|
+
minVersion: "22.0.0",
|
|
694
|
+
version: "22.2.4",
|
|
695
|
+
ngImport: i0,
|
|
696
|
+
type: LtAuthStore
|
|
697
|
+
});
|
|
698
|
+
};
|
|
699
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
700
|
+
minVersion: "12.0.0",
|
|
701
|
+
version: "22.2.4",
|
|
702
|
+
ngImport: i0,
|
|
703
|
+
type: LtAuthStore,
|
|
704
|
+
decorators: [{ type: Service }]
|
|
705
|
+
});
|
|
706
|
+
function hasLtRole(user, role) {
|
|
707
|
+
if (!user || !role) return false;
|
|
708
|
+
return user.role === role || Array.isArray(user.roles) && user.roles.includes(role);
|
|
709
|
+
}
|
|
710
|
+
function stringOrNull(value) {
|
|
711
|
+
return typeof value === "string" && value ? value : null;
|
|
712
|
+
}
|
|
713
|
+
async function runHook(hook, name) {
|
|
714
|
+
try {
|
|
715
|
+
await hook();
|
|
716
|
+
} catch (error) {
|
|
717
|
+
console.error(`[@lenne.tech/ng-base] A sign-out hook (${name}) failed:`, error);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
function withTimeout(promise, ms) {
|
|
721
|
+
let timer;
|
|
722
|
+
const timeout = new Promise((resolve) => {
|
|
723
|
+
timer = setTimeout(() => resolve(null), ms);
|
|
724
|
+
});
|
|
725
|
+
return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
|
|
726
|
+
}
|
|
727
|
+
const LT_SYSTEM_SETUP_STATE_KEY = makeStateKey("lt-system-setup");
|
|
728
|
+
const LT_SYSTEM_SETUP_TOKEN_HEADER = "X-System-Setup-Token";
|
|
729
|
+
var LtSystemSetupService = class LtSystemSetupService {
|
|
730
|
+
api = inject(LtApiUrlService);
|
|
731
|
+
fetch = inject(LT_FETCH);
|
|
732
|
+
transferState = inject(TransferState);
|
|
733
|
+
isServer = isPlatformServer(inject(PLATFORM_ID));
|
|
734
|
+
transferred = this.isServer ? null : this.transferState.get(LT_SYSTEM_SETUP_STATE_KEY, null);
|
|
735
|
+
needsSetupState = signal(this.transferred ? this.transferred.needsSetup : null, ...ngDevMode ? [{ debugName: "needsSetupState" }] : /* istanbul ignore next */ []);
|
|
736
|
+
httpInitEnabledState = signal(this.transferred ? this.transferred.httpInitEnabled !== false : null, ...ngDevMode ? [{ debugName: "httpInitEnabledState" }] : /* istanbul ignore next */ []);
|
|
737
|
+
httpInitTokenRequiredState = signal(this.transferred ? this.transferred.httpInitTokenRequired === true : null, ...ngDevMode ? [{ debugName: "httpInitTokenRequiredState" }] : /* istanbul ignore next */ []);
|
|
738
|
+
statusRequest = null;
|
|
739
|
+
needsSetup = this.needsSetupState.asReadonly();
|
|
740
|
+
httpInitEnabled = this.httpInitEnabledState.asReadonly();
|
|
741
|
+
httpInitTokenRequired = this.httpInitTokenRequiredState.asReadonly();
|
|
742
|
+
checkSetupStatus() {
|
|
743
|
+
if (this.isServer && this.api.resolve().missing) {
|
|
744
|
+
this.api.reportMissing();
|
|
745
|
+
return Promise.resolve({ needsSetup: false });
|
|
746
|
+
}
|
|
747
|
+
if (!this.statusRequest) this.statusRequest = this.loadStatus().finally(() => {
|
|
748
|
+
this.statusRequest = null;
|
|
749
|
+
});
|
|
750
|
+
return this.statusRequest;
|
|
751
|
+
}
|
|
752
|
+
async initSetup(input) {
|
|
753
|
+
const url = this.api.buildUrl("/system-setup/init");
|
|
754
|
+
const password = await ltSha256(input.password);
|
|
755
|
+
const token = input.token?.trim();
|
|
756
|
+
const headers = {
|
|
757
|
+
accept: "application/json",
|
|
758
|
+
"content-type": "application/json"
|
|
759
|
+
};
|
|
760
|
+
if (token) headers[LT_SYSTEM_SETUP_TOKEN_HEADER] = token;
|
|
761
|
+
const response = await this.fetch(url, {
|
|
762
|
+
body: JSON.stringify({
|
|
763
|
+
email: input.email,
|
|
764
|
+
name: input.name,
|
|
765
|
+
password
|
|
766
|
+
}),
|
|
767
|
+
headers,
|
|
768
|
+
method: "POST"
|
|
769
|
+
});
|
|
770
|
+
if (!response.ok) {
|
|
771
|
+
const error = await toSetupError(response);
|
|
772
|
+
if (response.status === 403) await this.checkSetupStatus();
|
|
773
|
+
throw error;
|
|
774
|
+
}
|
|
775
|
+
this.needsSetupState.set(false);
|
|
776
|
+
}
|
|
777
|
+
async loadStatus() {
|
|
778
|
+
try {
|
|
779
|
+
const response = await this.fetch(this.api.buildUrl("/system-setup/status"), { headers: { accept: "application/json" } });
|
|
780
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
781
|
+
const data = await response.json() ?? {};
|
|
782
|
+
const status = {
|
|
783
|
+
httpInitEnabled: typeof data["httpInitEnabled"] === "boolean" ? data["httpInitEnabled"] : true,
|
|
784
|
+
httpInitTokenRequired: data["httpInitTokenRequired"] === true,
|
|
785
|
+
needsSetup: data["needsSetup"] === true
|
|
786
|
+
};
|
|
787
|
+
this.needsSetupState.set(status.needsSetup);
|
|
788
|
+
this.httpInitEnabledState.set(status.httpInitEnabled ?? true);
|
|
789
|
+
this.httpInitTokenRequiredState.set(status.httpInitTokenRequired ?? false);
|
|
790
|
+
if (this.isServer) this.transferState.set(LT_SYSTEM_SETUP_STATE_KEY, status);
|
|
791
|
+
return status;
|
|
792
|
+
} catch {
|
|
793
|
+
this.needsSetupState.set(false);
|
|
794
|
+
return { needsSetup: false };
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
798
|
+
minVersion: "12.0.0",
|
|
799
|
+
version: "22.2.4",
|
|
800
|
+
ngImport: i0,
|
|
801
|
+
type: LtSystemSetupService,
|
|
802
|
+
deps: [],
|
|
803
|
+
target: i0.ɵɵFactoryTarget.Service
|
|
804
|
+
});
|
|
805
|
+
static ɵprov = i0.ɵɵngDeclareService({
|
|
806
|
+
minVersion: "22.0.0",
|
|
807
|
+
version: "22.2.4",
|
|
808
|
+
ngImport: i0,
|
|
809
|
+
type: LtSystemSetupService
|
|
810
|
+
});
|
|
811
|
+
};
|
|
812
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
813
|
+
minVersion: "12.0.0",
|
|
814
|
+
version: "22.2.4",
|
|
815
|
+
ngImport: i0,
|
|
816
|
+
type: LtSystemSetupService,
|
|
817
|
+
decorators: [{ type: Service }]
|
|
818
|
+
});
|
|
819
|
+
async function toSetupError(response) {
|
|
820
|
+
const text = await response.text().catch(() => "");
|
|
821
|
+
let data = text;
|
|
822
|
+
try {
|
|
823
|
+
data = text ? JSON.parse(text) : null;
|
|
824
|
+
} catch {}
|
|
825
|
+
const bodyMessage = data && typeof data === "object" ? data.message : data;
|
|
826
|
+
const message = typeof bodyMessage === "string" && bodyMessage ? bodyMessage : `[POST] /system-setup/init: ${response.status} ${response.statusText}`.trim();
|
|
827
|
+
return Object.assign(new Error(message), {
|
|
828
|
+
data,
|
|
829
|
+
status: response.status,
|
|
830
|
+
statusCode: response.status
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
const ltAuthGuard = (_route, state) => inject(LtAuthStore).isAuthenticated() ? true : loginTree(state);
|
|
834
|
+
function ltGuestGuard(redirectTo = "/app") {
|
|
835
|
+
return () => inject(LtAuthStore).isAuthenticated() ? inject(Router).parseUrl(redirectTo) : true;
|
|
836
|
+
}
|
|
837
|
+
function ltRoleGuard(roles, redirectTo = "/") {
|
|
838
|
+
const wanted = Array.isArray(roles) ? roles : [roles];
|
|
839
|
+
return (_route, state) => {
|
|
840
|
+
const auth = inject(LtAuthStore);
|
|
841
|
+
if (!auth.isAuthenticated()) return loginTree(state);
|
|
842
|
+
const user = auth.user();
|
|
843
|
+
return wanted.some((role) => hasLtRole(user, role)) ? true : inject(Router).parseUrl(redirectTo);
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
const ltSystemSetupGuard = async (_route, state) => {
|
|
847
|
+
const options = inject(LT_AUTH_OPTIONS);
|
|
848
|
+
if (!options.systemSetup.enabled) return true;
|
|
849
|
+
const setup = inject(LtSystemSetupService);
|
|
850
|
+
const router = inject(Router);
|
|
851
|
+
try {
|
|
852
|
+
if (setup.needsSetup() === null) await setup.checkSetupStatus();
|
|
853
|
+
const path = ltPathOf(state.url);
|
|
854
|
+
const setupPath = options.systemSetup.setupPath;
|
|
855
|
+
if (setup.needsSetup() === true && setup.httpInitEnabled() !== false && path !== setupPath) return router.parseUrl(setupPath);
|
|
856
|
+
if (setup.needsSetup() === false && path === setupPath) return router.parseUrl(options.loginPath);
|
|
857
|
+
} catch {}
|
|
858
|
+
return true;
|
|
859
|
+
};
|
|
860
|
+
function loginTree(state) {
|
|
861
|
+
const options = inject(LT_AUTH_OPTIONS);
|
|
862
|
+
return inject(Router).createUrlTree([options.loginPath], { queryParams: { redirect: state.url } });
|
|
863
|
+
}
|
|
864
|
+
var LtUnauthorizedHandler = class LtUnauthorizedHandler {
|
|
865
|
+
auth = inject(LtAuthStore);
|
|
866
|
+
handle(url) {
|
|
867
|
+
return this.auth.handleUnauthorized(url);
|
|
868
|
+
}
|
|
869
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
870
|
+
minVersion: "12.0.0",
|
|
871
|
+
version: "22.2.4",
|
|
872
|
+
ngImport: i0,
|
|
873
|
+
type: LtUnauthorizedHandler,
|
|
874
|
+
deps: [],
|
|
875
|
+
target: i0.ɵɵFactoryTarget.Service
|
|
876
|
+
});
|
|
877
|
+
static ɵprov = i0.ɵɵngDeclareService({
|
|
878
|
+
minVersion: "22.0.0",
|
|
879
|
+
version: "22.2.4",
|
|
880
|
+
ngImport: i0,
|
|
881
|
+
type: LtUnauthorizedHandler
|
|
882
|
+
});
|
|
883
|
+
};
|
|
884
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
885
|
+
minVersion: "12.0.0",
|
|
886
|
+
version: "22.2.4",
|
|
887
|
+
ngImport: i0,
|
|
888
|
+
type: LtUnauthorizedHandler,
|
|
889
|
+
decorators: [{ type: Service }]
|
|
890
|
+
});
|
|
891
|
+
const ltAuthInterceptor = (request, next) => {
|
|
892
|
+
if (isPlatformServer(inject(PLATFORM_ID))) return next(request);
|
|
893
|
+
const api = inject(LtApiUrlService);
|
|
894
|
+
if (!isLtApiRequest(request.url, api.resolve().baseUrl, inject(DOCUMENT).location?.origin)) return next(request);
|
|
895
|
+
const auth = inject(LtAuthStore);
|
|
896
|
+
const handler = inject(LtUnauthorizedHandler);
|
|
897
|
+
const url = request.urlWithParams;
|
|
898
|
+
const ownAuthorization = request.headers.has("Authorization");
|
|
899
|
+
const authorize = (token) => request.clone(token && !ownAuthorization ? {
|
|
900
|
+
setHeaders: { Authorization: `Bearer ${token}` },
|
|
901
|
+
withCredentials: true
|
|
902
|
+
} : { withCredentials: true });
|
|
903
|
+
const reportAndRethrow = (error) => {
|
|
904
|
+
if (isUnauthorized(error)) handler.handle(url);
|
|
905
|
+
return throwError(() => error);
|
|
906
|
+
};
|
|
907
|
+
const send = (sentToken) => next(authorize(sentToken)).pipe(catchError((error) => {
|
|
908
|
+
if (!isUnauthorized(error) || ownAuthorization) return reportAndRethrow(error);
|
|
909
|
+
return from(auth.recoverFrom401(url, sentToken)).pipe(switchMap((token) => token ? next(authorize(token)).pipe(catchError(reportAndRethrow)) : reportAndRethrow(error)));
|
|
910
|
+
}));
|
|
911
|
+
return !ownAuthorization && auth.jwtNeedsRefresh() ? from(auth.currentJwt()).pipe(switchMap(send)) : send(ownAuthorization ? null : auth.jwtToken());
|
|
912
|
+
};
|
|
913
|
+
function isUnauthorized(error) {
|
|
914
|
+
return error instanceof HttpErrorResponse && error.status === 401;
|
|
915
|
+
}
|
|
916
|
+
function provideLtAuth(options = {}) {
|
|
917
|
+
return makeEnvironmentProviders([
|
|
918
|
+
{
|
|
919
|
+
provide: LT_AUTH_INPUT_OPTIONS,
|
|
920
|
+
useValue: options
|
|
921
|
+
},
|
|
922
|
+
{
|
|
923
|
+
provide: LT_FETCH,
|
|
924
|
+
useFactory: () => {
|
|
925
|
+
const auth = inject(LtAuthStore);
|
|
926
|
+
return (input, init) => auth.fetchWithAuth(input, init);
|
|
927
|
+
}
|
|
928
|
+
},
|
|
929
|
+
provideAppInitializer(() => {
|
|
930
|
+
const auth = inject(LtAuthStore);
|
|
931
|
+
if (isPlatformServer(inject(PLATFORM_ID))) return auth.ensureFeatures().then(() => void 0);
|
|
932
|
+
auth.ensureFeatures();
|
|
933
|
+
auth.validateSession();
|
|
934
|
+
})
|
|
935
|
+
]);
|
|
936
|
+
}
|
|
937
|
+
export { LT_AUTH_COOKIE_MAX_AGE, LT_AUTH_COOKIE_PATHS, LT_AUTH_DEFAULTS, LT_AUTH_ENDPOINT_FRAGMENTS, LT_AUTH_FEATURES_STATE_KEY, LT_AUTH_INPUT_OPTIONS, LT_AUTH_OPTIONS, LT_AUTH_PUBLIC_PATHS, LT_AUTH_SIGN_OUT_HOOKS, LT_AUTH_STATE_COOKIE_DEFAULT, LT_JWT_TOKEN_COOKIE_DEFAULT, LT_SYSTEM_SETUP_STATE_KEY, LT_SYSTEM_SETUP_TOKEN_HEADER, LT_VALIDATE_SESSION_TIMEOUT_MS, LtAuthStateService, LtAuthStore, LtSystemSetupService, LtUnauthorizedHandler, hasLtRole, isLtApiRequest, isLtAuthEndpoint, ltAuthGuard, ltAuthInterceptor, ltGuestGuard, ltRoleGuard, ltSystemSetupGuard, provideLtAuth, readLtAuthAnswer, resolveLtAuthCookieNames, resolveLtAuthState, resolveLtCookiePrefix };
|
|
938
|
+
|
|
939
|
+
//# sourceMappingURL=lenne.tech-ng-base-auth-provide.mjs.map
|