@synopackageland/cli 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +613 -0
- package/README.md +81 -89
- package/dist/add.js +39 -16
- package/dist/build-spk/delegate-scope.d.ts +6 -0
- package/dist/build-spk/delegate-scope.js +34 -0
- package/dist/build-spk/dsm-arch.d.ts +7 -1
- package/dist/build-spk/dsm-arch.js +24 -28
- package/dist/build-spk/dsm-platforms.json +39 -0
- package/dist/build-spk/dsm-version.d.ts +11 -0
- package/dist/build-spk/dsm-version.js +17 -0
- package/dist/build-spk/gateway.d.ts +1 -1
- package/dist/build-spk/gateway.js +2 -2
- package/dist/build-spk/generator.js +30 -5
- package/dist/build-spk/notices.js +4 -1
- package/dist/build-spk/resource-worker.js +3 -0
- package/dist/build-spk/wizard-messages.d.ts +66 -0
- package/dist/build-spk/wizard-messages.js +75 -9
- package/dist/cli.js +15 -7
- package/dist/contract/schema-validate.js +8 -0
- package/dist/contract/validate.js +30 -0
- package/dist/deploy/deploy.d.ts +1 -1
- package/dist/deploy/deploy.js +8 -0
- package/dist/deploy/plan.js +1 -1
- package/dist/deploy/spk-version.js +1 -1
- package/dist/error-registry.js +43 -15
- package/dist/host/dsm-client.d.ts +8 -4
- package/dist/host/dsm-client.js +10 -4
- package/dist/host/types.d.ts +2 -1
- package/dist/info.js +18 -2
- package/dist/init.d.ts +3 -0
- package/dist/init.js +49 -18
- package/dist/package-metadata.d.ts +21 -0
- package/dist/package-metadata.js +101 -0
- package/dist/portal/alias.d.ts +25 -0
- package/dist/portal/alias.js +48 -0
- package/dist/portal/package.d.ts +33 -0
- package/dist/portal/package.js +116 -0
- package/dist/runtime/delegate-contract.d.ts +79 -0
- package/dist/runtime/delegate-contract.js +27 -0
- package/dist/runtime/executor-build.d.ts +1 -1
- package/dist/runtime/executor-build.js +5 -4
- package/dist/runtime/executor-inspect.d.ts +3 -0
- package/dist/runtime/executor-inspect.js +11 -5
- package/dist/runtime/executor-policy.d.ts +12 -0
- package/dist/runtime/executor-policy.js +43 -3
- package/dist/runtime/executor-scope-task.d.ts +4 -0
- package/dist/runtime/executor-scope-task.js +21 -0
- package/dist/runtime/executor-tasks.d.ts +2 -1
- package/dist/runtime/executor-tasks.js +4 -4
- package/dist/skill.js +1 -0
- package/dist/standalone/api-permissions.d.ts +10 -0
- package/dist/standalone/api-permissions.js +19 -2
- package/dist/standalone/background.d.ts +16 -0
- package/dist/standalone/background.js +69 -2
- package/dist/standalone/binary.d.ts +1 -1
- package/dist/standalone/binary.js +22 -8
- package/dist/standalone/build.d.ts +1 -1
- package/dist/standalone/build.js +38 -8
- package/dist/standalone/daemon.d.ts +1 -1
- package/dist/standalone/daemon.js +2 -1
- package/dist/standalone/dsm-window.d.ts +3 -1
- package/dist/standalone/dsm-window.js +72 -15
- package/dist/standalone/inspect-spk.d.ts +8 -0
- package/dist/standalone/inspect-spk.js +105 -26
- package/dist/standalone/lifecycle.js +86 -8
- package/dist/standalone/manifest.d.ts +13 -0
- package/dist/standalone/manifest.js +57 -8
- package/dist/standalone/native-authorization-window.d.ts +1 -1
- package/dist/standalone/native-authorization-window.js +2 -0
- package/dist/standalone/native-layout.d.ts +3 -0
- package/dist/standalone/native-layout.js +37 -5
- package/dist/standalone/portal-window.d.ts +21 -0
- package/dist/standalone/portal-window.js +155 -0
- package/dist/standalone/portal.d.ts +4 -0
- package/dist/standalone/portal.js +4 -0
- package/dist/standalone/resource.d.ts +5 -3
- package/dist/standalone/resource.js +6 -3
- package/dist/standalone/root-window.js +62 -15
- package/dist/standalone/spk.d.ts +1 -1
- package/dist/standalone/spk.js +25 -7
- package/dist/templates/_daemon/main_test.go +61 -8
- package/dist/templates/_executor/README.md +127 -16
- package/dist/templates/_executor/anchor.go +146 -0
- package/dist/templates/_executor/anchor_test.go +126 -0
- package/dist/templates/_executor/apppriv_review_test.go +1 -1
- package/dist/templates/_executor/cancel_contract_test.go +236 -0
- package/dist/templates/_executor/copy.go +64 -0
- package/dist/templates/_executor/copy_test.go +88 -0
- package/dist/templates/_executor/dsm.go +23 -10
- package/dist/templates/_executor/dsm_test.go +95 -1
- package/dist/templates/_executor/executor.go +260 -49
- package/dist/templates/_executor/executor_test.go +36 -6
- package/dist/templates/_executor/identity.go +27 -1
- package/dist/templates/_executor/identity_kernel_linux_test.go +60 -0
- package/dist/templates/_executor/identity_linux.go +82 -0
- package/dist/templates/_executor/identity_security_test.go +43 -0
- package/dist/templates/_executor/internal/lifecycle/lifecycle.go +5 -0
- package/dist/templates/_executor/internal/lifecycle/lifecycle_test.go +61 -3
- package/dist/templates/_executor/internal/taskscript/boot.sh +9 -9
- package/dist/templates/_executor/internal/taskscript/cmd/main.go +2 -2
- package/dist/templates/_executor/internal/taskscript/control.sh +15 -10
- package/dist/templates/_executor/internal/taskscript/tasks.go +5 -3
- package/dist/templates/_executor/lifecycle_test.go +11 -0
- package/dist/templates/_executor/link_linux.go +28 -0
- package/dist/templates/_executor/long_running_test.go +530 -0
- package/dist/templates/_executor/main.go +72 -20
- package/dist/templates/_executor/move_linux.go +490 -0
- package/dist/templates/_executor/move_linux_test.go +460 -0
- package/dist/templates/_executor/move_validation.go +46 -0
- package/dist/templates/_executor/move_validation_test.go +187 -0
- package/dist/templates/_executor/operations.go +926 -0
- package/dist/templates/_executor/platform_linux.go +24 -173
- package/dist/templates/_executor/platform_linux_test.go +9 -65
- package/dist/templates/_executor/platform_other.go +30 -4
- package/dist/templates/_executor/process.go +3 -0
- package/dist/templates/_executor/records.go +242 -0
- package/dist/templates/_executor/scope_cancel_contract_test.go +91 -0
- package/dist/templates/_executor/scope_client.go +37 -0
- package/dist/templates/_executor/scope_contract.go +12 -0
- package/dist/templates/_executor/selected_scope.go +146 -0
- package/dist/templates/_executor/selected_scope_test.go +186 -0
- package/dist/templates/_executor/status_disabled_test.go +33 -0
- package/dist/templates/_executor/store.go +4 -3
- package/dist/templates/_executor/supervise.go +109 -0
- package/dist/templates/_executor/supervise_test.go +130 -0
- package/dist/templates/_executor/task_race_review_test.go +1 -1
- package/dist/templates/_executor/tasks.go +7 -8
- package/dist/templates/_executor/tasks_review_test.go +1 -1
- package/dist/templates/_executor/tasks_test.go +4 -4
- package/dist/templates/_executor/watch.go +8 -0
- package/dist/templates/_executor/watch_test.go +23 -2
- package/dist/templates/_executor/write_review_linux_test.go +4 -12
- package/dist/templates/_shared/AGENTS.md +129 -0
- package/dist/templates/binary/dsm-package.yaml +24 -0
- package/dist/templates/binary/i18n/messages/de.json +4 -0
- package/dist/templates/binary/i18n/messages/en.json +4 -0
- package/dist/templates/binary/i18n/messages/es.json +4 -0
- package/dist/templates/binary/i18n/messages/fr.json +4 -0
- package/dist/templates/binary/i18n/messages/it.json +4 -0
- package/dist/templates/binary/i18n/messages/ja.json +4 -0
- package/dist/templates/binary/i18n/messages/ko.json +4 -0
- package/dist/templates/binary/i18n/messages/zh-CN.json +4 -0
- package/dist/templates/binary/i18n/messages/zh-TW.json +4 -0
- package/dist/templates/binary/ui/app.js +19 -4
- package/dist/templates/native-authorization/AuthorizationGate.vue +5 -3
- package/dist/templates/native-authorization/i18n/de.json +1 -0
- package/dist/templates/native-authorization/i18n/en.json +1 -0
- package/dist/templates/native-authorization/i18n/es.json +2 -1
- package/dist/templates/native-authorization/i18n/fr.json +1 -0
- package/dist/templates/native-authorization/i18n/it.json +11 -10
- package/dist/templates/native-authorization/i18n/ja.json +1 -0
- package/dist/templates/native-authorization/i18n/ko.json +10 -9
- package/dist/templates/native-authorization/i18n/zh-CN.json +6 -5
- package/dist/templates/native-authorization/i18n/zh-TW.json +6 -5
- package/dist/templates/native-go/README.md +43 -10
- package/dist/templates/native-go/backend/cmd/app/main.go +27 -7
- package/dist/templates/native-go/backend/internal/api/entry_test.go +47 -0
- package/dist/templates/native-go/backend/internal/api/permissions_test.go +3 -3
- package/dist/templates/native-go/backend/internal/api/registry.go +11 -0
- package/dist/templates/native-go/backend/internal/api/sdk-permissions.json +14 -1
- package/dist/templates/native-go/backend/internal/api/server.go +18 -5
- package/dist/templates/native-go/backend/internal/app/delegate_config.go +57 -0
- package/dist/templates/native-go/backend/internal/app/delegate_config_test.go +28 -0
- package/dist/templates/native-go/backend/internal/app/portal.go +30 -0
- package/dist/templates/native-go/backend/internal/app/portal_test.go +55 -0
- package/dist/templates/native-go/backend/internal/app/routes.go +8 -2
- package/dist/templates/native-go/backend/internal/background/runner.go +1 -1
- package/dist/templates/native-go/backend/internal/background/store.go +16 -14
- package/dist/templates/native-go/backend/internal/dsm/admin.go +8 -2
- package/dist/templates/native-go/backend/internal/dsm/admin_linux.go +43 -13
- package/dist/templates/native-go/backend/internal/dsm/admin_linux_test.go +56 -0
- package/dist/templates/native-go/backend/internal/dsm/admin_other.go +4 -1
- package/dist/templates/native-go/backend/internal/dsm/apppriv.go +30 -0
- package/dist/templates/native-go/backend/internal/dsm/bridge_file.go +75 -0
- package/dist/templates/native-go/backend/internal/dsm/bridge_file_test.go +57 -0
- package/dist/templates/native-go/backend/internal/dsm/entry.go +177 -0
- package/dist/templates/native-go/backend/internal/dsm/entry_test.go +315 -0
- package/dist/templates/native-go/backend/internal/dsm/native/admin-armv7.elf +0 -0
- package/dist/templates/native-go/backend/internal/dsm/native/apppriv-aarch64.elf +0 -0
- package/dist/templates/native-go/backend/internal/dsm/native/apppriv-armv7.elf +0 -0
- package/dist/templates/native-go/backend/internal/dsm/native/apppriv-x86_64.elf +0 -0
- package/dist/templates/native-go/backend/internal/dsm/native/apppriv_check.c +33 -0
- package/dist/templates/native-go/backend/internal/dsm/native/build.sh +13 -4
- package/dist/templates/native-go/backend/internal/dsm/native/provenance.json +9 -3
- package/dist/templates/native-go/backend/internal/filestation/check_permission.go +71 -0
- package/dist/templates/native-go/backend/internal/filestation/check_permission_test.go +77 -0
- package/dist/templates/native-go/backend/internal/filestation/sdk_policy_test.go +39 -0
- package/dist/templates/native-go/backend/internal/filestation/service.go +1 -1
- package/dist/templates/native-go/backend/internal/portal/portal.go +138 -0
- package/dist/templates/native-go/backend/internal/portal/portal_test.go +89 -0
- package/dist/templates/native-go/dsm-package.yaml +20 -1
- package/dist/templates/native-go/i18n/glossary.json +2 -1
- package/dist/templates/native-go/i18n/messages/de.json +1 -0
- package/dist/templates/native-go/i18n/messages/en.json +1 -0
- package/dist/templates/native-go/i18n/messages/es.json +1 -0
- package/dist/templates/native-go/i18n/messages/fr.json +1 -0
- package/dist/templates/native-go/i18n/messages/it.json +1 -0
- package/dist/templates/native-go/i18n/messages/ja.json +1 -0
- package/dist/templates/native-go/i18n/messages/ko.json +1 -0
- package/dist/templates/native-go/i18n/messages/zh-CN.json +1 -0
- package/dist/templates/native-go/i18n/messages/zh-TW.json +1 -0
- package/dist/templates/native-go/ui/app.css +10 -0
- package/dist/templates/native-go/ui/app.js +11 -1
- package/dist/templates/native-go-delegate/DELEGATE.md +126 -5
- package/dist/templates/native-go-delegate/backend/cmd/background-worker/main.go +7 -0
- package/dist/templates/native-go-delegate/backend/internal/app/delegate.go +11 -1
- package/dist/templates/native-go-delegate/backend/internal/app/delegate_routes_test.go +14 -0
- package/dist/templates/native-go-delegate/backend/internal/background/delegated_moves.go +270 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/admission_recovery_test.go +410 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/cancel_contract_test.go +95 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/client.go +8 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/destination.go +110 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/destination_state.go +117 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/destination_state_test.go +60 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/destination_test.go +116 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/example.go +81 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/example_test.go +91 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/executor_contract_test.go +511 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/files.go +1 -1
- package/dist/templates/native-go-delegate/backend/internal/delegate/long_running_routes.go +92 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/long_running_routes_test.go +99 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/move.go +348 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/move_test.go +351 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/operations_list.go +65 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/operations_list_test.go +114 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/retry_test.go +1 -1
- package/dist/templates/native-go-delegate/backend/internal/delegate/service.go +58 -17
- package/dist/templates/native-go-delegate/backend/internal/delegate/staging.go +121 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/status_disabled_test.go +51 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/testdata/executor_contract.txt +112 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/transient_contract_test.go +137 -0
- package/dist/templates/native-go-delegate/backend/internal/filestation/files.go +1 -31
- package/dist/templates/native-go-delegate/frontend/src/CapabilityPanels.vue +30 -3
- package/dist/templates/native-go-delegate/frontend/src/delegate/BackgroundSavePanel.vue +113 -0
- package/dist/templates/native-go-delegate/frontend/src/delegate/copy.ts +5 -6
- package/dist/templates/native-go-delegate/frontend/test/background-save.test.ts +121 -0
- package/dist/templates/native-go-delegate/frontend/test/scope-settings.test.ts +49 -0
- package/dist/templates/native-go-delegate/test.sh +1 -0
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/de.json +2 -2
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/en.json +2 -2
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/es.json +12 -12
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/fr.json +4 -4
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/it.json +17 -17
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/ja.json +7 -7
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/ko.json +15 -15
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/zh-CN.json +3 -3
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/zh-TW.json +2 -2
- package/dist/templates/native-go-jobs/frontend/test/background.test.ts +25 -28
- package/dist/templates/native-go-vue/README.md +4 -0
- package/dist/templates/native-go-vue/frontend/package-lock.json +4 -4
- package/dist/templates/native-go-vue/frontend/package.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/App.vue +18 -13
- package/dist/templates/native-go-vue/frontend/src/context.ts +31 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/ExecutorSettings.vue +52 -8
- package/dist/templates/native-go-vue/frontend/src/delegate/catalogs.ts +11 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/copy.test.ts +12 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/copy.ts +4 -4
- package/dist/templates/native-go-vue/frontend/src/delegate/executor-setup.ts +4 -2
- package/dist/templates/native-go-vue/frontend/src/delegate/facade.test.ts +100 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/facade.ts +85 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/de.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/en.json +12 -2
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/es.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/fr.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/it.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/ja.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/ko.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/de.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/en.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/es.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/fr.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/it.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/ja.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/ko.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-CN.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-TW.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/zh-CN.json +46 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/zh-TW.json +15 -5
- package/dist/templates/native-go-vue/frontend/src/delegate/long-running.ts +57 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/save-copy.test.ts +12 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/save-copy.ts +24 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/scoped-picker.test.ts +12 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/scoped-picker.ts +21 -0
- package/dist/templates/native-go-vue/frontend/src/files/files.test.ts +7 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/de.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/en.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/es.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/fr.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/it.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/ja.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/ko.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/zh-CN.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/zh-TW.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n.ts +13 -0
- package/dist/templates/native-go-vue/frontend/src/identity/LoginPage.vue +16 -14
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/de.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/en.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/es.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/fr.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/it.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/ja.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/ko.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/zh-CN.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/zh-TW.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n.ts +14 -0
- package/dist/templates/native-go-vue/frontend/src/identity/session.test.ts +4 -0
- package/dist/templates/native-go-vue/frontend/src/identity/session.ts +9 -8
- package/dist/templates/native-go-vue/frontend/src/nas/NasPicker.vue +31 -12
- package/dist/templates/native-go-vue/frontend/src/nas/destination.test.ts +48 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/de.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/en.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/es.json +10 -10
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/fr.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/it.json +12 -12
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/ja.json +15 -15
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/ko.json +12 -12
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/zh-CN.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/zh-TW.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/portal/PortalSettings.vue +39 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/fr.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/ja.json +1 -1
- package/dist/templates/native-go-vue/frontend/test/apps.test.ts +14 -0
- package/dist/templates/native-go-vue/frontend/test/portal-settings.test.ts +71 -0
- package/dist/templates/native-go-vue/frontend/test/shell-i18n.test.ts +50 -0
- package/package.json +5 -1
- package/schema/package-metadata.schema.json +101 -0
- package/schema/synology-app.schema.json +112 -0
- package/skills/SKILL.md +106 -4
- package/skills/reference/create.md +101 -2
- package/skills/reference/deploy.md +2 -2
- package/skills/reference/files.md +113 -2
- package/skills/reference/identity.md +70 -1
- package/skills/reference/portal.md +17 -0
- package/skills/reference/ui-vue.md +12 -0
- package/templates/_daemon/main_test.go +61 -8
- package/templates/_executor/README.md +127 -16
- package/templates/_executor/anchor.go +146 -0
- package/templates/_executor/anchor_test.go +126 -0
- package/templates/_executor/apppriv_review_test.go +1 -1
- package/templates/_executor/cancel_contract_test.go +236 -0
- package/templates/_executor/copy.go +64 -0
- package/templates/_executor/copy_test.go +88 -0
- package/templates/_executor/dsm.go +23 -10
- package/templates/_executor/dsm_test.go +95 -1
- package/templates/_executor/executor.go +260 -49
- package/templates/_executor/executor_test.go +36 -6
- package/templates/_executor/identity.go +27 -1
- package/templates/_executor/identity_kernel_linux_test.go +60 -0
- package/templates/_executor/identity_linux.go +82 -0
- package/templates/_executor/identity_security_test.go +43 -0
- package/templates/_executor/internal/lifecycle/lifecycle.go +5 -0
- package/templates/_executor/internal/lifecycle/lifecycle_test.go +61 -3
- package/templates/_executor/internal/taskscript/boot.sh +9 -9
- package/templates/_executor/internal/taskscript/cmd/main.go +2 -2
- package/templates/_executor/internal/taskscript/control.sh +15 -10
- package/templates/_executor/internal/taskscript/tasks.go +5 -3
- package/templates/_executor/lifecycle_test.go +11 -0
- package/templates/_executor/link_linux.go +28 -0
- package/templates/_executor/long_running_test.go +530 -0
- package/templates/_executor/main.go +72 -20
- package/templates/_executor/move_linux.go +490 -0
- package/templates/_executor/move_linux_test.go +460 -0
- package/templates/_executor/move_validation.go +46 -0
- package/templates/_executor/move_validation_test.go +187 -0
- package/templates/_executor/operations.go +926 -0
- package/templates/_executor/platform_linux.go +24 -173
- package/templates/_executor/platform_linux_test.go +9 -65
- package/templates/_executor/platform_other.go +30 -4
- package/templates/_executor/process.go +3 -0
- package/templates/_executor/records.go +242 -0
- package/templates/_executor/scope_cancel_contract_test.go +91 -0
- package/templates/_executor/scope_client.go +37 -0
- package/templates/_executor/scope_contract.go +12 -0
- package/templates/_executor/selected_scope.go +146 -0
- package/templates/_executor/selected_scope_test.go +186 -0
- package/templates/_executor/status_disabled_test.go +33 -0
- package/templates/_executor/store.go +4 -3
- package/templates/_executor/supervise.go +109 -0
- package/templates/_executor/supervise_test.go +130 -0
- package/templates/_executor/task_race_review_test.go +1 -1
- package/templates/_executor/tasks.go +7 -8
- package/templates/_executor/tasks_review_test.go +1 -1
- package/templates/_executor/tasks_test.go +4 -4
- package/templates/_executor/watch.go +8 -0
- package/templates/_executor/watch_test.go +23 -2
- package/templates/_executor/write_review_linux_test.go +4 -12
- package/templates/_shared/AGENTS.md +129 -0
- package/templates/binary/dsm-package.yaml +24 -0
- package/templates/binary/i18n/messages/de.json +4 -0
- package/templates/binary/i18n/messages/en.json +4 -0
- package/templates/binary/i18n/messages/es.json +4 -0
- package/templates/binary/i18n/messages/fr.json +4 -0
- package/templates/binary/i18n/messages/it.json +4 -0
- package/templates/binary/i18n/messages/ja.json +4 -0
- package/templates/binary/i18n/messages/ko.json +4 -0
- package/templates/binary/i18n/messages/zh-CN.json +4 -0
- package/templates/binary/i18n/messages/zh-TW.json +4 -0
- package/templates/binary/ui/app.js +19 -4
- package/templates/native-authorization/AuthorizationGate.vue +5 -3
- package/templates/native-authorization/i18n/de.json +1 -0
- package/templates/native-authorization/i18n/en.json +1 -0
- package/templates/native-authorization/i18n/es.json +2 -1
- package/templates/native-authorization/i18n/fr.json +1 -0
- package/templates/native-authorization/i18n/it.json +11 -10
- package/templates/native-authorization/i18n/ja.json +1 -0
- package/templates/native-authorization/i18n/ko.json +10 -9
- package/templates/native-authorization/i18n/zh-CN.json +6 -5
- package/templates/native-authorization/i18n/zh-TW.json +6 -5
- package/templates/native-go/README.md +43 -10
- package/templates/native-go/backend/cmd/app/main.go +27 -7
- package/templates/native-go/backend/internal/api/entry_test.go +47 -0
- package/templates/native-go/backend/internal/api/permissions_test.go +3 -3
- package/templates/native-go/backend/internal/api/registry.go +11 -0
- package/templates/native-go/backend/internal/api/sdk-permissions.json +14 -1
- package/templates/native-go/backend/internal/api/server.go +18 -5
- package/templates/native-go/backend/internal/app/delegate_config.go +57 -0
- package/templates/native-go/backend/internal/app/delegate_config_test.go +28 -0
- package/templates/native-go/backend/internal/app/portal.go +30 -0
- package/templates/native-go/backend/internal/app/portal_test.go +55 -0
- package/templates/native-go/backend/internal/app/routes.go +8 -2
- package/templates/native-go/backend/internal/background/runner.go +1 -1
- package/templates/native-go/backend/internal/background/store.go +16 -14
- package/templates/native-go/backend/internal/dsm/admin.go +8 -2
- package/templates/native-go/backend/internal/dsm/admin_linux.go +43 -13
- package/templates/native-go/backend/internal/dsm/admin_linux_test.go +56 -0
- package/templates/native-go/backend/internal/dsm/admin_other.go +4 -1
- package/templates/native-go/backend/internal/dsm/apppriv.go +30 -0
- package/templates/native-go/backend/internal/dsm/bridge_file.go +75 -0
- package/templates/native-go/backend/internal/dsm/bridge_file_test.go +57 -0
- package/templates/native-go/backend/internal/dsm/entry.go +177 -0
- package/templates/native-go/backend/internal/dsm/entry_test.go +315 -0
- package/templates/native-go/backend/internal/dsm/native/admin-armv7.elf +0 -0
- package/templates/native-go/backend/internal/dsm/native/apppriv-aarch64.elf +0 -0
- package/templates/native-go/backend/internal/dsm/native/apppriv-armv7.elf +0 -0
- package/templates/native-go/backend/internal/dsm/native/apppriv-x86_64.elf +0 -0
- package/templates/native-go/backend/internal/dsm/native/apppriv_check.c +33 -0
- package/templates/native-go/backend/internal/dsm/native/build.sh +13 -4
- package/templates/native-go/backend/internal/dsm/native/provenance.json +9 -3
- package/templates/native-go/backend/internal/filestation/check_permission.go +71 -0
- package/templates/native-go/backend/internal/filestation/check_permission_test.go +77 -0
- package/templates/native-go/backend/internal/filestation/sdk_policy_test.go +39 -0
- package/templates/native-go/backend/internal/filestation/service.go +1 -1
- package/templates/native-go/backend/internal/portal/portal.go +138 -0
- package/templates/native-go/backend/internal/portal/portal_test.go +89 -0
- package/templates/native-go/dsm-package.yaml +20 -1
- package/templates/native-go/i18n/glossary.json +2 -1
- package/templates/native-go/i18n/messages/de.json +1 -0
- package/templates/native-go/i18n/messages/en.json +1 -0
- package/templates/native-go/i18n/messages/es.json +1 -0
- package/templates/native-go/i18n/messages/fr.json +1 -0
- package/templates/native-go/i18n/messages/it.json +1 -0
- package/templates/native-go/i18n/messages/ja.json +1 -0
- package/templates/native-go/i18n/messages/ko.json +1 -0
- package/templates/native-go/i18n/messages/zh-CN.json +1 -0
- package/templates/native-go/i18n/messages/zh-TW.json +1 -0
- package/templates/native-go/ui/app.css +10 -0
- package/templates/native-go/ui/app.js +11 -1
- package/templates/native-go-delegate/DELEGATE.md +126 -5
- package/templates/native-go-delegate/backend/cmd/background-worker/main.go +7 -0
- package/templates/native-go-delegate/backend/internal/app/delegate.go +11 -1
- package/templates/native-go-delegate/backend/internal/app/delegate_routes_test.go +14 -0
- package/templates/native-go-delegate/backend/internal/background/delegated_moves.go +270 -0
- package/templates/native-go-delegate/backend/internal/delegate/admission_recovery_test.go +410 -0
- package/templates/native-go-delegate/backend/internal/delegate/cancel_contract_test.go +95 -0
- package/templates/native-go-delegate/backend/internal/delegate/client.go +8 -0
- package/templates/native-go-delegate/backend/internal/delegate/destination.go +110 -0
- package/templates/native-go-delegate/backend/internal/delegate/destination_state.go +117 -0
- package/templates/native-go-delegate/backend/internal/delegate/destination_state_test.go +60 -0
- package/templates/native-go-delegate/backend/internal/delegate/destination_test.go +116 -0
- package/templates/native-go-delegate/backend/internal/delegate/example.go +81 -0
- package/templates/native-go-delegate/backend/internal/delegate/example_test.go +91 -0
- package/templates/native-go-delegate/backend/internal/delegate/executor_contract_test.go +511 -0
- package/templates/native-go-delegate/backend/internal/delegate/files.go +1 -1
- package/templates/native-go-delegate/backend/internal/delegate/long_running_routes.go +92 -0
- package/templates/native-go-delegate/backend/internal/delegate/long_running_routes_test.go +99 -0
- package/templates/native-go-delegate/backend/internal/delegate/move.go +348 -0
- package/templates/native-go-delegate/backend/internal/delegate/move_test.go +351 -0
- package/templates/native-go-delegate/backend/internal/delegate/operations_list.go +65 -0
- package/templates/native-go-delegate/backend/internal/delegate/operations_list_test.go +114 -0
- package/templates/native-go-delegate/backend/internal/delegate/retry_test.go +1 -1
- package/templates/native-go-delegate/backend/internal/delegate/service.go +58 -17
- package/templates/native-go-delegate/backend/internal/delegate/staging.go +121 -0
- package/templates/native-go-delegate/backend/internal/delegate/status_disabled_test.go +51 -0
- package/templates/native-go-delegate/backend/internal/delegate/testdata/executor_contract.txt +112 -0
- package/templates/native-go-delegate/backend/internal/delegate/transient_contract_test.go +137 -0
- package/templates/native-go-delegate/backend/internal/filestation/files.go +1 -31
- package/templates/native-go-delegate/frontend/src/CapabilityPanels.vue +30 -3
- package/templates/native-go-delegate/frontend/src/delegate/BackgroundSavePanel.vue +113 -0
- package/templates/native-go-delegate/frontend/src/delegate/copy.ts +5 -6
- package/templates/native-go-delegate/frontend/test/background-save.test.ts +121 -0
- package/templates/native-go-delegate/frontend/test/scope-settings.test.ts +49 -0
- package/templates/native-go-delegate/test.sh +1 -0
- package/templates/native-go-jobs/frontend/src/background/i18n/de.json +2 -2
- package/templates/native-go-jobs/frontend/src/background/i18n/en.json +2 -2
- package/templates/native-go-jobs/frontend/src/background/i18n/es.json +12 -12
- package/templates/native-go-jobs/frontend/src/background/i18n/fr.json +4 -4
- package/templates/native-go-jobs/frontend/src/background/i18n/it.json +17 -17
- package/templates/native-go-jobs/frontend/src/background/i18n/ja.json +7 -7
- package/templates/native-go-jobs/frontend/src/background/i18n/ko.json +15 -15
- package/templates/native-go-jobs/frontend/src/background/i18n/zh-CN.json +3 -3
- package/templates/native-go-jobs/frontend/src/background/i18n/zh-TW.json +2 -2
- package/templates/native-go-jobs/frontend/test/background.test.ts +25 -28
- package/templates/native-go-vue/README.md +4 -0
- package/templates/native-go-vue/frontend/package-lock.json +4 -4
- package/templates/native-go-vue/frontend/package.json +1 -1
- package/templates/native-go-vue/frontend/src/App.vue +18 -13
- package/templates/native-go-vue/frontend/src/context.ts +31 -0
- package/templates/native-go-vue/frontend/src/delegate/ExecutorSettings.vue +52 -8
- package/templates/native-go-vue/frontend/src/delegate/catalogs.ts +11 -0
- package/templates/native-go-vue/frontend/src/delegate/copy.test.ts +12 -0
- package/templates/native-go-vue/frontend/src/delegate/copy.ts +4 -4
- package/templates/native-go-vue/frontend/src/delegate/executor-setup.ts +4 -2
- package/templates/native-go-vue/frontend/src/delegate/facade.test.ts +100 -0
- package/templates/native-go-vue/frontend/src/delegate/facade.ts +85 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/de.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/en.json +12 -2
- package/templates/native-go-vue/frontend/src/delegate/i18n/es.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/fr.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/it.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/ja.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/ko.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/de.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/en.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/es.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/fr.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/it.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/ja.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/ko.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-CN.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-TW.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/zh-CN.json +46 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/zh-TW.json +15 -5
- package/templates/native-go-vue/frontend/src/delegate/long-running.ts +57 -0
- package/templates/native-go-vue/frontend/src/delegate/save-copy.test.ts +12 -0
- package/templates/native-go-vue/frontend/src/delegate/save-copy.ts +24 -0
- package/templates/native-go-vue/frontend/src/delegate/scoped-picker.test.ts +12 -0
- package/templates/native-go-vue/frontend/src/delegate/scoped-picker.ts +21 -0
- package/templates/native-go-vue/frontend/src/files/files.test.ts +7 -0
- package/templates/native-go-vue/frontend/src/i18n/de.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/en.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/es.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/fr.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/it.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/ja.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/ko.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/zh-CN.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/zh-TW.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n.ts +13 -0
- package/templates/native-go-vue/frontend/src/identity/LoginPage.vue +16 -14
- package/templates/native-go-vue/frontend/src/identity/i18n/de.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/en.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/es.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/fr.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/it.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/ja.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/ko.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/zh-CN.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/zh-TW.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n.ts +14 -0
- package/templates/native-go-vue/frontend/src/identity/session.test.ts +4 -0
- package/templates/native-go-vue/frontend/src/identity/session.ts +9 -8
- package/templates/native-go-vue/frontend/src/nas/NasPicker.vue +31 -12
- package/templates/native-go-vue/frontend/src/nas/destination.test.ts +48 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/files/de.json +1 -1
- package/templates/native-go-vue/frontend/src/nas/i18n/files/en.json +1 -1
- package/templates/native-go-vue/frontend/src/nas/i18n/files/es.json +10 -10
- package/templates/native-go-vue/frontend/src/nas/i18n/files/fr.json +1 -1
- package/templates/native-go-vue/frontend/src/nas/i18n/files/it.json +12 -12
- package/templates/native-go-vue/frontend/src/nas/i18n/files/ja.json +15 -15
- package/templates/native-go-vue/frontend/src/nas/i18n/files/ko.json +12 -12
- package/templates/native-go-vue/frontend/src/nas/i18n/files/zh-CN.json +1 -1
- package/templates/native-go-vue/frontend/src/nas/i18n/files/zh-TW.json +1 -1
- package/templates/native-go-vue/frontend/src/portal/PortalSettings.vue +39 -0
- package/templates/native-go-vue/frontend/src/shell/i18n/fr.json +1 -1
- package/templates/native-go-vue/frontend/src/shell/i18n/ja.json +1 -1
- package/templates/native-go-vue/frontend/test/apps.test.ts +14 -0
- package/templates/native-go-vue/frontend/test/portal-settings.test.ts +71 -0
- package/templates/native-go-vue/frontend/test/shell-i18n.test.ts +50 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
package filestation
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"fmt"
|
|
6
|
+
"net/http"
|
|
7
|
+
"net/http/httptest"
|
|
8
|
+
"testing"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
func TestCheckPermissionRequiresVerifiedSessionAndExplicitWriteResult(t *testing.T) {
|
|
12
|
+
for _, body := range []string{`{"blSkip":false}`, `{}`, `{"blSkip":true}`, `{"blSkip":null}`, `{"blSkip":false,"errors":[{"code":407}]}`} {
|
|
13
|
+
t.Run(body, func(t *testing.T) {
|
|
14
|
+
checks := 0
|
|
15
|
+
client := fakeClient(t, func(w http.ResponseWriter, r *http.Request) {
|
|
16
|
+
r.ParseForm()
|
|
17
|
+
switch r.Form.Get("api") {
|
|
18
|
+
case "SYNO.Core.NormalUser":
|
|
19
|
+
fmt.Fprint(w, `{"success":true,"data":{"username":"alice"}}`)
|
|
20
|
+
case "SYNO.FileStation.CheckPermission":
|
|
21
|
+
checks++
|
|
22
|
+
if r.Form.Get("version") != "3" || r.Form.Get("method") != "write" || r.Form.Get("path") != "/home" || r.Form.Get("filename") != ".synopkgland-permission-probe" || r.Form.Get("overwrite") != "false" || r.Form.Get("size") != "0" || r.Header.Get("Cookie") != "id=test-session" || r.Header.Get("X-SYNO-TOKEN") != "test-token" {
|
|
23
|
+
t.Error("incorrect permission check transport")
|
|
24
|
+
}
|
|
25
|
+
fmt.Fprintf(w, `{"success":true,"data":%s}`, body)
|
|
26
|
+
default:
|
|
27
|
+
t.Error("unexpected API")
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
service := NewService(client)
|
|
31
|
+
err := service.CheckPermission(context.Background(), callerFor(t, "alice"), sessionRequest(), "/home")
|
|
32
|
+
if (err == nil) != (body == `{"blSkip":false}`) || checks != 1 {
|
|
33
|
+
t.Fatalf("checks=%d err=%v", checks, err)
|
|
34
|
+
}
|
|
35
|
+
checks = 0
|
|
36
|
+
if err := service.CheckPermission(context.Background(), callerFor(t, "bob"), sessionRequest(), "/home"); err == nil || checks != 0 {
|
|
37
|
+
t.Fatal("mismatched subject checked write permission")
|
|
38
|
+
}
|
|
39
|
+
if err := service.CheckPermission(context.Background(), callerFor(t, "alice"), sessionRequest(), "/home/../etc"); err == nil || checks != 0 {
|
|
40
|
+
t.Fatal("invalid path checked")
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
func TestCheckPermissionValidatesCredentialPairBeforeDSM(t *testing.T) {
|
|
47
|
+
calls := 0
|
|
48
|
+
client := fakeClient(t, func(w http.ResponseWriter, r *http.Request) {
|
|
49
|
+
calls++
|
|
50
|
+
r.ParseForm()
|
|
51
|
+
if r.Form.Get("api") == "SYNO.Core.NormalUser" {
|
|
52
|
+
fmt.Fprint(w, `{"success":true,"data":{"username":"alice"}}`)
|
|
53
|
+
} else {
|
|
54
|
+
fmt.Fprint(w, `{"success":true,"data":{"blSkip":false}}`)
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
service := NewService(client)
|
|
58
|
+
for index, r := range []*http.Request{nil, httptest.NewRequest("POST", "/", nil), sessionRequest(), sessionRequest()} {
|
|
59
|
+
if r != nil && r.Header.Get("X-SYNO-TOKEN") != "" {
|
|
60
|
+
if index == 2 {
|
|
61
|
+
r.Header.Del("X-SYNO-TOKEN")
|
|
62
|
+
} else {
|
|
63
|
+
r.Header.Set("SynoToken", "different")
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
before := calls
|
|
67
|
+
if err := service.CheckPermission(context.Background(), callerFor(t, "alice"), r, "/home"); err == nil || calls != before {
|
|
68
|
+
t.Fatal("invalid session reached DSM", err, calls)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
r := sessionRequest()
|
|
72
|
+
r.Header.Del("X-SYNO-TOKEN")
|
|
73
|
+
r.Header.Set("SynoToken", "test-token")
|
|
74
|
+
if err := service.CheckPermission(context.Background(), callerFor(t, "alice"), r, "/home"); err != nil {
|
|
75
|
+
t.Fatal("canonical alias refused", err)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package filestation
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"os"
|
|
6
|
+
"sort"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// Every files entry in the SDK policy must name a route this package serves.
|
|
11
|
+
func TestSDKPolicyListsExactlyTheFileRoutes(t *testing.T) {
|
|
12
|
+
raw, err := os.ReadFile("../api/sdk-permissions.json")
|
|
13
|
+
if err != nil {
|
|
14
|
+
t.Fatal(err)
|
|
15
|
+
}
|
|
16
|
+
var policy struct {
|
|
17
|
+
Files map[string]string `json:"files"`
|
|
18
|
+
}
|
|
19
|
+
if err := json.Unmarshal(raw, &policy); err != nil {
|
|
20
|
+
t.Fatal(err)
|
|
21
|
+
}
|
|
22
|
+
var declared, routed []string
|
|
23
|
+
for method := range policy.Files {
|
|
24
|
+
declared = append(declared, method)
|
|
25
|
+
}
|
|
26
|
+
for _, route := range (&Service{}).Routes() {
|
|
27
|
+
routed = append(routed, route.Method())
|
|
28
|
+
}
|
|
29
|
+
sort.Strings(declared)
|
|
30
|
+
sort.Strings(routed)
|
|
31
|
+
if len(declared) != len(routed) {
|
|
32
|
+
t.Fatalf("policy %v, routes %v", declared, routed)
|
|
33
|
+
}
|
|
34
|
+
for i := range declared {
|
|
35
|
+
if declared[i] != routed[i] {
|
|
36
|
+
t.Fatalf("policy %v, routes %v", declared, routed)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -204,7 +204,7 @@ func (s *Service) discover(ctx context.Context, r *http.Request, folder string,
|
|
|
204
204
|
// Browse lists share roots (empty folder) or one folder through the caller's
|
|
205
205
|
// own DSM session, so File Station's current permissions decide what is
|
|
206
206
|
// visible. It is read-only metadata and stores no grant; background jobs use it
|
|
207
|
-
// to let an
|
|
207
|
+
// to let an authenticated caller pick the file that ReadFile will then import.
|
|
208
208
|
func (s *Service) Browse(ctx context.Context, c api.Caller, r *http.Request, folder string, offset int) (Page, error) {
|
|
209
209
|
if !c.Authenticated() {
|
|
210
210
|
return Page{}, fail("session_required")
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Package portal reads the DSM Application Portal alias an administrator set
|
|
2
|
+
// for this package. DSM owns the setting: the package never writes it, and
|
|
3
|
+
// anything this reader does not fully understand reads as Unavailable.
|
|
4
|
+
package portal
|
|
5
|
+
|
|
6
|
+
import (
|
|
7
|
+
"bytes"
|
|
8
|
+
"encoding/json"
|
|
9
|
+
"errors"
|
|
10
|
+
"io"
|
|
11
|
+
"io/fs"
|
|
12
|
+
"os"
|
|
13
|
+
"regexp"
|
|
14
|
+
"syscall"
|
|
15
|
+
"unicode/utf8"
|
|
16
|
+
|
|
17
|
+
"dsmapp/internal/jsonlimits"
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
// MaxConfigBytes bounds DSM's saved setting; its real size is a few hundred bytes.
|
|
21
|
+
const MaxConfigBytes = 64 << 10
|
|
22
|
+
|
|
23
|
+
const (
|
|
24
|
+
// Active means users can open the app at /<alias>/ after DSM sign-in.
|
|
25
|
+
Active = "active"
|
|
26
|
+
// Inactive means no administrator has set an alias yet.
|
|
27
|
+
Inactive = "inactive"
|
|
28
|
+
// Unavailable means the setting could not be read safely.
|
|
29
|
+
Unavailable = "unavailable"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
// Status is what portal.status returns; Alias is set only when Active.
|
|
33
|
+
type Status struct {
|
|
34
|
+
State string `json:"state"`
|
|
35
|
+
Alias string `json:"alias,omitempty"`
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// A single URL path segment; DSM's own validation is looser than this.
|
|
39
|
+
var aliasPattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$`)
|
|
40
|
+
|
|
41
|
+
// ConfigPath is where DSM saves the package's portal setting
|
|
42
|
+
// (/var/packages/<package>/etc is the package's @appconf directory).
|
|
43
|
+
func ConfigPath(packageID string) string {
|
|
44
|
+
return "/var/packages/" + packageID + "/etc/AppPortal.json"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Read returns the saved alias when the setting belongs to appID.
|
|
48
|
+
func Read(path, appID string) Status {
|
|
49
|
+
raw, err := readBounded(path)
|
|
50
|
+
if errors.Is(err, fs.ErrNotExist) {
|
|
51
|
+
return Status{State: Inactive}
|
|
52
|
+
}
|
|
53
|
+
if err != nil {
|
|
54
|
+
return Status{State: Unavailable}
|
|
55
|
+
}
|
|
56
|
+
id, alias, ok := parse(raw)
|
|
57
|
+
if !ok || id != appID {
|
|
58
|
+
return Status{State: Unavailable}
|
|
59
|
+
}
|
|
60
|
+
if alias == "" {
|
|
61
|
+
return Status{State: Inactive}
|
|
62
|
+
}
|
|
63
|
+
if !aliasPattern.MatchString(alias) {
|
|
64
|
+
return Status{State: Unavailable}
|
|
65
|
+
}
|
|
66
|
+
return Status{State: Active, Alias: alias}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
func readBounded(path string) ([]byte, error) {
|
|
70
|
+
f, err := os.OpenFile(path, os.O_RDONLY|syscall.O_NOFOLLOW|syscall.O_NONBLOCK, 0)
|
|
71
|
+
if err != nil {
|
|
72
|
+
return nil, err
|
|
73
|
+
}
|
|
74
|
+
defer f.Close()
|
|
75
|
+
info, err := f.Stat()
|
|
76
|
+
if err != nil {
|
|
77
|
+
return nil, err
|
|
78
|
+
}
|
|
79
|
+
if !info.Mode().IsRegular() {
|
|
80
|
+
return nil, errors.New("not a regular file")
|
|
81
|
+
}
|
|
82
|
+
raw, err := io.ReadAll(io.LimitReader(f, MaxConfigBytes+1))
|
|
83
|
+
if err != nil {
|
|
84
|
+
return nil, err
|
|
85
|
+
}
|
|
86
|
+
if len(raw) > MaxConfigBytes {
|
|
87
|
+
return nil, errors.New("too large")
|
|
88
|
+
}
|
|
89
|
+
return raw, nil
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// parse accepts exactly one JSON object with unique top-level keys, a string
|
|
93
|
+
// id and a string or null alias; other DSM fields are skipped unread.
|
|
94
|
+
func parse(raw []byte) (id, alias string, ok bool) {
|
|
95
|
+
if !utf8.Valid(raw) || !jsonlimits.WithinLimits(raw) {
|
|
96
|
+
return "", "", false
|
|
97
|
+
}
|
|
98
|
+
d := json.NewDecoder(bytes.NewReader(raw))
|
|
99
|
+
if token, err := d.Token(); err != nil || token != json.Delim('{') {
|
|
100
|
+
return "", "", false
|
|
101
|
+
}
|
|
102
|
+
seen := map[string]bool{}
|
|
103
|
+
hasID := false
|
|
104
|
+
for d.More() {
|
|
105
|
+
token, err := d.Token()
|
|
106
|
+
key, isKey := token.(string)
|
|
107
|
+
if err != nil || !isKey || seen[key] {
|
|
108
|
+
return "", "", false
|
|
109
|
+
}
|
|
110
|
+
seen[key] = true
|
|
111
|
+
var value json.RawMessage
|
|
112
|
+
if err := d.Decode(&value); err != nil {
|
|
113
|
+
return "", "", false
|
|
114
|
+
}
|
|
115
|
+
switch key {
|
|
116
|
+
case "id":
|
|
117
|
+
if json.Unmarshal(value, &id) != nil || id == "" {
|
|
118
|
+
return "", "", false
|
|
119
|
+
}
|
|
120
|
+
hasID = true
|
|
121
|
+
case "alias":
|
|
122
|
+
var text *string
|
|
123
|
+
if json.Unmarshal(value, &text) != nil {
|
|
124
|
+
return "", "", false
|
|
125
|
+
}
|
|
126
|
+
if text != nil {
|
|
127
|
+
alias = *text
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if token, err := d.Token(); err != nil || token != json.Delim('}') {
|
|
132
|
+
return "", "", false
|
|
133
|
+
}
|
|
134
|
+
if _, err := d.Token(); err != io.EOF {
|
|
135
|
+
return "", "", false
|
|
136
|
+
}
|
|
137
|
+
return id, alias, hasID
|
|
138
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
package portal
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"path/filepath"
|
|
6
|
+
"strings"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
const appID = "SYNO.SDS.HelloGo.Instance"
|
|
11
|
+
|
|
12
|
+
// saved mirrors DSM 7.4's AppPortal.json after an administrator sets an alias.
|
|
13
|
+
func saved(alias string) string {
|
|
14
|
+
return "{\n\t\"acl\" : \"\",\n\t\"alias\" : " + alias + ",\n\t\"alternatePort\" : null,\n\t\"application\" : \"Hello Go\",\n\t\"fqdn\" : null,\n\t\"https\" : \n\t{\n\t\t\"hsts\" : false\n\t},\n\t\"id\" : \"" + appID + "\",\n\t\"version\" : 3\n}\n"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func write(t *testing.T, content string) string {
|
|
18
|
+
t.Helper()
|
|
19
|
+
path := filepath.Join(t.TempDir(), "AppPortal.json")
|
|
20
|
+
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
|
21
|
+
t.Fatal(err)
|
|
22
|
+
}
|
|
23
|
+
return path
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
func TestActiveAlias(t *testing.T) {
|
|
27
|
+
got := Read(write(t, saved(`"hello-go"`)), appID)
|
|
28
|
+
if got != (Status{State: Active, Alias: "hello-go"}) {
|
|
29
|
+
t.Fatalf("got %+v", got)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
func TestNoSavedSettingIsInactive(t *testing.T) {
|
|
34
|
+
if got := Read(filepath.Join(t.TempDir(), "AppPortal.json"), appID); got != (Status{State: Inactive}) {
|
|
35
|
+
t.Fatalf("missing file: %+v", got)
|
|
36
|
+
}
|
|
37
|
+
for _, alias := range []string{`null`, `""`} {
|
|
38
|
+
if got := Read(write(t, saved(alias)), appID); got != (Status{State: Inactive}) {
|
|
39
|
+
t.Fatalf("alias %s: %+v", alias, got)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func TestAnythingElseFailsClosed(t *testing.T) {
|
|
45
|
+
other := strings.Replace(saved(`"hello-go"`), appID, "SYNO.SDS.Other.Instance", 1)
|
|
46
|
+
cases := map[string]string{
|
|
47
|
+
"another app": other,
|
|
48
|
+
"no id": `{"alias":"hello-go"}`,
|
|
49
|
+
"duplicate alias": `{"alias":"hello-go","alias":"evil","id":"` + appID + `"}`,
|
|
50
|
+
"duplicate id": `{"id":"SYNO.SDS.Other.Instance","alias":"hello-go","id":"` + appID + `"}`,
|
|
51
|
+
"alias number": saved(`1`),
|
|
52
|
+
"alias path": saved(`"a/b"`),
|
|
53
|
+
"alias dots": saved(`".."`),
|
|
54
|
+
"alias query": saved(`"a?b"`),
|
|
55
|
+
"alias too long": saved(`"` + strings.Repeat("a", 65) + `"`),
|
|
56
|
+
"array": `[]`,
|
|
57
|
+
"trailing value": saved(`"hello-go"`) + `{}`,
|
|
58
|
+
"not json": `alias=hello-go`,
|
|
59
|
+
"not utf8": "{\"alias\":\"\xff\",\"id\":\"" + appID + "\"}",
|
|
60
|
+
"too large": saved(`"hello-go"`) + strings.Repeat(" ", MaxConfigBytes),
|
|
61
|
+
"too deep": strings.Replace(saved(`"hello-go"`), `"acl" : ""`, `"acl" : `+strings.Repeat("[", 64)+strings.Repeat("]", 64), 1),
|
|
62
|
+
}
|
|
63
|
+
for name, content := range cases {
|
|
64
|
+
if got := Read(write(t, content), appID); got != (Status{State: Unavailable}) {
|
|
65
|
+
t.Errorf("%s: %+v", name, got)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
func TestOnlyARegularFileIsRead(t *testing.T) {
|
|
71
|
+
dir := t.TempDir()
|
|
72
|
+
target := write(t, saved(`"hello-go"`))
|
|
73
|
+
link := filepath.Join(dir, "AppPortal.json")
|
|
74
|
+
if err := os.Symlink(target, link); err != nil {
|
|
75
|
+
t.Fatal(err)
|
|
76
|
+
}
|
|
77
|
+
if got := Read(link, appID); got != (Status{State: Unavailable}) {
|
|
78
|
+
t.Fatalf("symlink: %+v", got)
|
|
79
|
+
}
|
|
80
|
+
if got := Read(dir, appID); got != (Status{State: Unavailable}) {
|
|
81
|
+
t.Fatalf("directory: %+v", got)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
func TestConfigPathIsThePackagesOwnSetting(t *testing.T) {
|
|
86
|
+
if got := ConfigPath("HelloGo"); got != "/var/packages/HelloGo/etc/AppPortal.json" {
|
|
87
|
+
t.Fatal(got)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -11,9 +11,28 @@ build: 1
|
|
|
11
11
|
displayname: __DISPLAY_NAME__
|
|
12
12
|
description: A native DSM package with a Go backend and a DSM window UI.
|
|
13
13
|
maintainer: Your Name
|
|
14
|
+
# Optional INFO/website metadata. Omit fields you do not need.
|
|
15
|
+
# metadata:
|
|
16
|
+
# contact_email: you@example.com
|
|
17
|
+
# support_email: support@example.com
|
|
18
|
+
# homepage: https://example.com
|
|
19
|
+
# source_url: https://github.com/you/your-app
|
|
20
|
+
# issues_url: https://github.com/you/your-app/issues
|
|
21
|
+
# license: MIT
|
|
22
|
+
# long_description:
|
|
23
|
+
# en: |-
|
|
24
|
+
# Explain what the app does and how to use it.
|
|
25
|
+
# zh-TW: Translated description.
|
|
26
|
+
# changelog: # text, or per-language like long_description
|
|
27
|
+
# en: |-
|
|
28
|
+
# - Most important change first. Omit to use Release notes.
|
|
29
|
+
# zh-TW: |-
|
|
30
|
+
# - Translated changes.
|
|
31
|
+
# screenshots: [https://example.com/screenshot.png]
|
|
14
32
|
os_min_ver: "7.1-42661"
|
|
15
33
|
|
|
16
|
-
# One SPK per architecture. Supported: x86_64, aarch64
|
|
34
|
+
# One SPK per architecture. Supported: x86_64, aarch64, armv7 (add it here to
|
|
35
|
+
# build it; armv7 jobs/delegate/root-ops/daemon are built but not NAS-verified).
|
|
17
36
|
arches: [x86_64, aarch64]
|
|
18
37
|
|
|
19
38
|
backend:
|
|
@@ -580,7 +580,8 @@
|
|
|
580
580
|
"it": "Siamo spiacenti, a questo account utente non sono stati assegnati privilegi appropriati per eseguire questa azione."
|
|
581
581
|
},
|
|
582
582
|
"keys": [
|
|
583
|
-
"error.admin_required"
|
|
583
|
+
"error.admin_required",
|
|
584
|
+
"error.app_privilege_denied"
|
|
584
585
|
]
|
|
585
586
|
},
|
|
586
587
|
{
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"app.refresh": "Aktualisieren",
|
|
4
4
|
"app.title": "Es funktioniert",
|
|
5
5
|
"error.admin_required": "Dieses Benutzerkonto verfügt nicht über die erforderlichen Berechtigungen, um diese Aktion durchzuführen.",
|
|
6
|
+
"error.app_privilege_denied": "Dieses Benutzerkonto verfügt nicht über die erforderlichen Berechtigungen, um diese Aktion durchzuführen.",
|
|
6
7
|
"error.auth_unavailable": "Dieser Vorgang kann nicht ausgeführt werden. Bitte versuchen Sie es später erneut.",
|
|
7
8
|
"error.bad_request": "Überprüfen Sie den eingegebenen Wert und versuchen Sie es erneut.",
|
|
8
9
|
"error.bad_response": "Dieser Vorgang kann nicht ausgeführt werden. Bitte versuchen Sie es später erneut.",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"app.refresh": "Refresh",
|
|
4
4
|
"app.title": "It works",
|
|
5
5
|
"error.admin_required": "Sorry, this user account has not been assigned proper privileges to perform this action.",
|
|
6
|
+
"error.app_privilege_denied": "Sorry, this user account has not been assigned proper privileges to perform this action.",
|
|
6
7
|
"error.auth_unavailable": "Unable to perform this operation. Please try again later.",
|
|
7
8
|
"error.bad_request": "Check the entered value and try again.",
|
|
8
9
|
"error.bad_response": "Unable to perform this operation. Please try again later.",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"app.refresh": "Actualizar",
|
|
4
4
|
"app.title": "Funciona",
|
|
5
5
|
"error.admin_required": "A esta cuenta de usuario no se le han asignado los privilegios adecuados para realizar esta acción.",
|
|
6
|
+
"error.app_privilege_denied": "A esta cuenta de usuario no se le han asignado los privilegios adecuados para realizar esta acción.",
|
|
6
7
|
"error.auth_unavailable": "No se puede realizar esta operación. Vuelva a intentarlo más tarde.",
|
|
7
8
|
"error.bad_request": "Compruebe el valor introducido y vuelva a intentarlo.",
|
|
8
9
|
"error.bad_response": "No se puede realizar esta operación. Vuelva a intentarlo más tarde.",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"app.refresh": "Actualiser",
|
|
4
4
|
"app.title": "Ça fonctionne",
|
|
5
5
|
"error.admin_required": "Désolé, ce compte utilisateur ne dispose pas des droits nécessaires pour accomplir cette action.",
|
|
6
|
+
"error.app_privilege_denied": "Désolé, ce compte utilisateur ne dispose pas des droits nécessaires pour accomplir cette action.",
|
|
6
7
|
"error.auth_unavailable": "Impossible d'effectuer cette opération. Veuillez réessayer ultérieurement.",
|
|
7
8
|
"error.bad_request": "Vérifiez la valeur saisie et réessayez.",
|
|
8
9
|
"error.bad_response": "Impossible d'effectuer cette opération. Veuillez réessayer ultérieurement.",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"app.refresh": "Aggiorna",
|
|
4
4
|
"app.title": "Funziona",
|
|
5
5
|
"error.admin_required": "Siamo spiacenti, a questo account utente non sono stati assegnati privilegi appropriati per eseguire questa azione.",
|
|
6
|
+
"error.app_privilege_denied": "Siamo spiacenti, a questo account utente non sono stati assegnati privilegi appropriati per eseguire questa azione.",
|
|
6
7
|
"error.auth_unavailable": "Impossibile eseguire questa operazione. Riprovare più tardi.",
|
|
7
8
|
"error.bad_request": "Controllare il valore inserito e riprovare.",
|
|
8
9
|
"error.bad_response": "Impossibile eseguire questa operazione. Riprovare più tardi.",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"app.refresh": "最新の情報に更新",
|
|
4
4
|
"app.title": "動作しています",
|
|
5
5
|
"error.admin_required": "申し訳ありませんが、このユーザー アカウントにはこの操作を行うための権限が与えられていません。",
|
|
6
|
+
"error.app_privilege_denied": "申し訳ありませんが、このユーザー アカウントにはこの操作を行うための権限が与えられていません。",
|
|
6
7
|
"error.auth_unavailable": "この操作は実行できません。後でもう一度お試しください。",
|
|
7
8
|
"error.bad_request": "入力した値を確認して、もう一度お試しください。",
|
|
8
9
|
"error.bad_response": "この操作は実行できません。後でもう一度お試しください。",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"app.refresh": "새로 고침",
|
|
4
4
|
"app.title": "정상적으로 작동합니다",
|
|
5
5
|
"error.admin_required": "죄송합니다. 이 사용자 계정에는 이 작업을 수행하기에 적절한 권한이 할당되지 않았습니다.",
|
|
6
|
+
"error.app_privilege_denied": "죄송합니다. 이 사용자 계정에는 이 작업을 수행하기에 적절한 권한이 할당되지 않았습니다.",
|
|
6
7
|
"error.auth_unavailable": "이 작업을 수행할 수 없습니다. 나중에 다시 시도하십시오.",
|
|
7
8
|
"error.bad_request": "입력한 값을 확인한 후 다시 시도하십시오.",
|
|
8
9
|
"error.bad_response": "이 작업을 수행할 수 없습니다. 나중에 다시 시도하십시오.",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"app.refresh": "刷新",
|
|
4
4
|
"app.title": "运行成功",
|
|
5
5
|
"error.admin_required": "抱歉,此用户帐户权限不足,无法执行此操作。",
|
|
6
|
+
"error.app_privilege_denied": "抱歉,此用户帐户权限不足,无法执行此操作。",
|
|
6
7
|
"error.auth_unavailable": "无法执行此操作。请稍后再试。",
|
|
7
8
|
"error.bad_request": "请检查输入的值后重试。",
|
|
8
9
|
"error.bad_response": "无法执行此操作。请稍后再试。",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"app.refresh": "重新整理",
|
|
4
4
|
"app.title": "成功運作了",
|
|
5
5
|
"error.admin_required": "抱歉,此使用者帳號權限不足,無法執行此動作。",
|
|
6
|
+
"error.app_privilege_denied": "抱歉,此使用者帳號權限不足,無法執行此動作。",
|
|
6
7
|
"error.auth_unavailable": "無法執行此操作。請稍後再試。",
|
|
7
8
|
"error.bad_request": "請檢查輸入的值後再試一次。",
|
|
8
9
|
"error.bad_response": "無法執行此操作。請稍後再試。",
|
|
@@ -33,3 +33,13 @@
|
|
|
33
33
|
.dsmapp-facts { display: grid; grid-template-columns: max-content 1fr; gap: 4px 16px; margin: 0; }
|
|
34
34
|
.dsmapp-facts dt { color: #5d6b7a; }
|
|
35
35
|
.dsmapp-facts dd { margin: 0; }
|
|
36
|
+
/* SDK portal panel (ctx.portal.mountPanel). */
|
|
37
|
+
.dsmapp-portal-form { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; max-width: 560px; }
|
|
38
|
+
.dsmapp-portal input { height: 28px; padding: 0 8px; border: 1px solid #c8d0da; border-radius: 3px; font: inherit; }
|
|
39
|
+
.dsmapp-portal button {
|
|
40
|
+
height: 30px; padding: 0 12px; border: 1px solid #c8d0da; border-radius: 3px;
|
|
41
|
+
background: #fff; color: inherit; font: inherit; cursor: pointer; margin-top: 8px;
|
|
42
|
+
}
|
|
43
|
+
.dsmapp-portal-form button { margin-top: 0; }
|
|
44
|
+
.dsmapp-portal-form button[type="submit"] { border-color: #0086e5; background: #0086e5; color: #fff; }
|
|
45
|
+
.dsmapp-portal-error { color: #c0392b; }
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
// host-theme/language-change unsupported
|
|
16
16
|
// ctx.host.openFileManager(path) / revealFile(path) -> File Station virtual path
|
|
17
17
|
// request only; preview/details/settings return unsupported, never a grant
|
|
18
|
+
// ctx.portal -> only with `portal:` in dsm-package.yaml;
|
|
19
|
+
// mountPanel(element) shows the DSM Application
|
|
20
|
+
// Portal link, or the alias form to administrators
|
|
18
21
|
// Replace everything below with your own UI (plain JS, or a bundle you build
|
|
19
22
|
// with Vite/Vue into this folder -- see README.md).
|
|
20
23
|
(function () {
|
|
@@ -40,6 +43,7 @@
|
|
|
40
43
|
var message = el("p", { class: "dsmapp-message", role: "status" });
|
|
41
44
|
var form = el("form", { class: "dsmapp-form", hidden: "" }, [input, save]);
|
|
42
45
|
var adminOnly = el("p", { class: "dsmapp-note", hidden: "", text: t("greeting.adminOnly") });
|
|
46
|
+
var portal = ctx.portal ? el("section", { class: "dsmapp-portal" }) : null;
|
|
43
47
|
|
|
44
48
|
root.classList.add("dsmapp");
|
|
45
49
|
root.replaceChildren(
|
|
@@ -51,6 +55,7 @@
|
|
|
51
55
|
el("h2", { text: t("status.heading") }),
|
|
52
56
|
status
|
|
53
57
|
);
|
|
58
|
+
var portalPanel = portal && (root.appendChild(portal), ctx.portal.mountPanel(portal));
|
|
54
59
|
|
|
55
60
|
// Errors arrive as { code }; the backend's English message is only a fallback.
|
|
56
61
|
function showError(error) {
|
|
@@ -93,7 +98,12 @@
|
|
|
93
98
|
|
|
94
99
|
ctx.reopen(refresh);
|
|
95
100
|
refresh();
|
|
96
|
-
return {
|
|
101
|
+
return {
|
|
102
|
+
unmount: function () {
|
|
103
|
+
if (portalPanel) portalPanel.dispose();
|
|
104
|
+
root.replaceChildren();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
97
107
|
}
|
|
98
108
|
|
|
99
109
|
window.DsmPackageApps = window.DsmPackageApps || {};
|