@synopackageland/cli 0.3.10 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +57 -9
- package/dist/bin.js +1 -2
- package/dist/build-spk/generator.d.ts +0 -3
- package/dist/build-spk/generator.js +138 -287
- package/dist/build-spk/native-lifecycle.js +0 -3
- package/dist/build-spk/native-payload.js +0 -1
- package/dist/build-spk/notices.d.ts +5 -0
- package/dist/build-spk/notices.js +60 -0
- package/dist/cli.js +178 -151
- package/dist/compose/analyze.d.ts +1 -2
- package/dist/compose/analyze.js +5 -48
- package/dist/contract/unsupported-types.d.ts +10 -0
- package/dist/contract/unsupported-types.js +49 -0
- package/dist/contract/validate.js +25 -2
- package/dist/contract/web-launch.js +0 -2
- package/dist/deploy/deploy.d.ts +1 -4
- package/dist/deploy/deploy.js +45 -156
- package/dist/deploy/homes-values.js +1 -1
- package/dist/deploy/plan.d.ts +18 -0
- package/dist/deploy/plan.js +54 -0
- package/dist/deploy/spk-version.d.ts +2 -14
- package/dist/deploy/spk-version.js +25 -111
- package/dist/dev.d.ts +1 -3
- package/dist/dev.js +14 -28
- package/dist/error-registry.js +830 -862
- package/dist/host/dsm-client.js +12 -272
- package/dist/host/dsm-port-profile.d.ts +0 -1
- package/dist/host/dsm-port-profile.js +0 -2
- package/dist/host/types.d.ts +1 -83
- package/dist/index.d.ts +0 -9
- package/dist/index.js +0 -6
- package/dist/info.d.ts +0 -1
- package/dist/info.js +3 -10
- package/dist/init.d.ts +15 -1
- package/dist/init.js +128 -12
- package/dist/log.js +2 -3
- package/dist/native/validate.js +0 -1
- package/dist/standalone/binary.d.ts +9 -0
- package/dist/standalone/binary.js +67 -0
- package/dist/standalone/build.d.ts +25 -0
- package/dist/standalone/build.js +110 -0
- package/dist/standalone/daemon.d.ts +23 -0
- package/dist/standalone/daemon.js +114 -0
- package/dist/standalone/dsm-window.d.ts +26 -0
- package/dist/standalone/dsm-window.js +291 -0
- package/dist/standalone/helper-inventory.d.ts +16 -0
- package/dist/standalone/helper-inventory.js +2 -0
- package/dist/standalone/helper.d.ts +21 -0
- package/dist/standalone/helper.js +105 -0
- package/dist/standalone/host-adapter.d.ts +5 -0
- package/dist/standalone/host-adapter.js +148 -0
- package/dist/standalone/host-platform.d.ts +13 -0
- package/dist/standalone/host-platform.js +42 -0
- package/dist/standalone/host-types.d.ts +49 -0
- package/dist/standalone/host-types.js +1 -0
- package/dist/standalone/i18n.d.ts +28 -0
- package/dist/standalone/i18n.js +161 -0
- package/dist/standalone/inspect-helper.d.ts +6 -0
- package/dist/standalone/inspect-helper.js +88 -0
- package/dist/standalone/inspect-spk.d.ts +23 -0
- package/dist/standalone/inspect-spk.js +209 -0
- package/dist/standalone/lifecycle-helper.d.ts +2 -0
- package/dist/standalone/lifecycle-helper.js +12 -0
- package/dist/standalone/lifecycle.d.ts +3 -0
- package/dist/standalone/lifecycle.js +53 -0
- package/dist/standalone/manifest.d.ts +73 -0
- package/dist/standalone/manifest.js +279 -0
- package/dist/standalone/reopen-events.d.ts +2 -0
- package/dist/standalone/reopen-events.js +28 -0
- package/dist/standalone/root-messages.d.ts +7 -0
- package/dist/standalone/root-messages.js +259 -0
- package/dist/standalone/root-ops.d.ts +42 -0
- package/dist/standalone/root-ops.js +101 -0
- package/dist/standalone/root-window.d.ts +36 -0
- package/dist/standalone/root-window.js +302 -0
- package/dist/standalone/spk.d.ts +23 -0
- package/dist/standalone/spk.js +192 -0
- package/dist/template-paths.d.ts +2 -0
- package/dist/template-paths.js +9 -0
- package/dist/templates/_daemon/fixture_linux_test.go +15 -0
- package/dist/templates/_daemon/fixture_other_test.go +7 -0
- package/dist/templates/_daemon/go.mod +3 -0
- package/dist/templates/_daemon/main.go +608 -0
- package/dist/templates/_daemon/main_test.go +242 -0
- package/dist/templates/_daemon/process_linux.go +55 -0
- package/dist/templates/_daemon/process_linux_test.go +161 -0
- package/dist/templates/_daemon/process_other.go +14 -0
- package/dist/templates/_daemon/testdata/child.go +41 -0
- package/dist/templates/_shared/GO-LICENSE +27 -0
- package/dist/templates/_shared/GO-PATENTS +22 -0
- package/dist/templates/_shared/LICENSES/TEMPLATE.txt +21 -0
- package/dist/templates/_shared/notice-overrides/index.json +14 -0
- package/dist/templates/_shared/notice-overrides/utils-0.4.2-LICENSE +21 -0
- package/dist/templates/_shared/notice-overrides/utils-0.5.0-LICENSE +21 -0
- package/dist/templates/_shared/third-party-notices.mjs +51 -0
- package/dist/templates/binary/synology-app.yaml +7 -0
- package/dist/templates/hello-files/compose.yaml +0 -1
- package/dist/templates/hello-web/compose.yaml +13 -10
- package/dist/templates/hello-web/html/app.js +1 -23
- package/dist/templates/hello-web/html/index.html +1 -3
- package/dist/templates/hello-web-page/compose.yaml +13 -10
- package/dist/templates/hello-web-page/html/app.js +1 -23
- package/dist/templates/hello-web-page/html/index.html +1 -3
- package/dist/templates/native-go/README.md +324 -0
- package/dist/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +59 -0
- package/dist/templates/native-go/backend/cmd/app/main.go +49 -0
- package/dist/templates/native-go/backend/cmd/dsm-readonly-probe/main_linux.go +46 -0
- package/dist/templates/native-go/backend/cmd/helper/main.go +38 -0
- package/dist/templates/native-go/backend/go.mod +7 -0
- package/dist/templates/native-go/backend/go.sum +4 -0
- package/dist/templates/native-go/backend/internal/api/binary.go +154 -0
- package/dist/templates/native-go/backend/internal/api/binary_test.go +165 -0
- package/dist/templates/native-go/backend/internal/api/errors.go +33 -0
- package/dist/templates/native-go/backend/internal/api/registry.go +104 -0
- package/dist/templates/native-go/backend/internal/api/registry_test.go +329 -0
- package/dist/templates/native-go/backend/internal/api/server.go +159 -0
- package/dist/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +121 -0
- package/dist/templates/native-go/backend/internal/app/nas_refusal_test.go +46 -0
- package/dist/templates/native-go/backend/internal/app/root_none.go +9 -0
- package/dist/templates/native-go/backend/internal/app/routes.go +138 -0
- package/dist/templates/native-go/backend/internal/app/routes_test.go +172 -0
- package/dist/templates/native-go/backend/internal/dsm/auth.go +118 -0
- package/dist/templates/native-go/backend/internal/dsm/auth_test.go +139 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/collector_linux.go +335 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/collector_linux_test.go +41 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/protocol.go +179 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/protocol_test.go +29 -0
- package/dist/templates/native-go/backend/internal/helper/cohort.go +393 -0
- package/dist/templates/native-go/backend/internal/helper/cohort_publication.go +18 -0
- package/dist/templates/native-go/backend/internal/helper/cohort_publication_test.go +105 -0
- package/dist/templates/native-go/backend/internal/helper/cohort_test.go +372 -0
- package/dist/templates/native-go/backend/internal/helper/control.go +424 -0
- package/dist/templates/native-go/backend/internal/helper/control_test.go +250 -0
- package/dist/templates/native-go/backend/internal/helper/data_contract.go +242 -0
- package/dist/templates/native-go/backend/internal/helper/data_contract_test.go +51 -0
- package/dist/templates/native-go/backend/internal/helper/data_decode.go +184 -0
- package/dist/templates/native-go/backend/internal/helper/data_decode_pointer_test.go +30 -0
- package/dist/templates/native-go/backend/internal/helper/data_protocol.go +416 -0
- package/dist/templates/native-go/backend/internal/helper/data_protocol_test.go +449 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_linux.go +139 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_linux_test.go +121 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux.go +95 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux_test.go +56 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_bridge_linux.go +144 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_bridge_linux_test.go +89 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_home_linux.go +107 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_home_linux_test.go +82 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_probe_transport_linux.go +151 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_probe_transport_linux_test.go +66 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority.go +516 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority_contract.go +88 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority_test.go +510 -0
- package/dist/templates/native-go/backend/internal/helper/grant_cohort.go +389 -0
- package/dist/templates/native-go/backend/internal/helper/grant_cohort_test.go +239 -0
- package/dist/templates/native-go/backend/internal/helper/grant_delivery.go +49 -0
- package/dist/templates/native-go/backend/internal/helper/grant_delivery_methods.go +273 -0
- package/dist/templates/native-go/backend/internal/helper/grant_delivery_test.go +322 -0
- package/dist/templates/native-go/backend/internal/helper/grant_operation_contract.go +47 -0
- package/dist/templates/native-go/backend/internal/helper/grant_readonly_test.go +180 -0
- package/dist/templates/native-go/backend/internal/helper/grant_repository_linux.go +415 -0
- package/dist/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +468 -0
- package/dist/templates/native-go/backend/internal/helper/grant_rpc.go +147 -0
- package/dist/templates/native-go/backend/internal/helper/grant_rpc_test.go +51 -0
- package/dist/templates/native-go/backend/internal/helper/grant_snapshot.go +75 -0
- package/dist/templates/native-go/backend/internal/helper/grant_supervisor_linux.go +134 -0
- package/dist/templates/native-go/backend/internal/helper/grant_supervisor_linux_test.go +254 -0
- package/dist/templates/native-go/backend/internal/helper/lease.go +112 -0
- package/dist/templates/native-go/backend/internal/helper/lease_linux.go +44 -0
- package/dist/templates/native-go/backend/internal/helper/lease_other.go +8 -0
- package/dist/templates/native-go/backend/internal/helper/lifecycle.go +234 -0
- package/dist/templates/native-go/backend/internal/helper/lifecycle_test.go +473 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot.go +284 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot_repository_linux.go +74 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot_repository_linux_test.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot_test.go +210 -0
- package/dist/templates/native-go/backend/internal/helper/nas_shipped_refusal_linux_test.go +97 -0
- package/dist/templates/native-go/backend/internal/helper/native_discovery.go +79 -0
- package/dist/templates/native-go/backend/internal/helper/native_identity.go +89 -0
- package/dist/templates/native-go/backend/internal/helper/native_provider.go +159 -0
- package/dist/templates/native-go/backend/internal/helper/native_provider_test.go +421 -0
- package/dist/templates/native-go/backend/internal/helper/observation.go +204 -0
- package/dist/templates/native-go/backend/internal/helper/observation_health_test.go +115 -0
- package/dist/templates/native-go/backend/internal/helper/observation_reload_budget_test.go +117 -0
- package/dist/templates/native-go/backend/internal/helper/observation_test.go +196 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic.go +109 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux.go +76 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +124 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_test.go +98 -0
- package/dist/templates/native-go/backend/internal/helper/operation_bootstrap_linux.go +193 -0
- package/dist/templates/native-go/backend/internal/helper/operation_credentials_linux.go +56 -0
- package/dist/templates/native-go/backend/internal/helper/operation_linux.go +480 -0
- package/dist/templates/native-go/backend/internal/helper/operation_linux_test.go +528 -0
- package/dist/templates/native-go/backend/internal/helper/peer_linux.go +44 -0
- package/dist/templates/native-go/backend/internal/helper/peer_other.go +7 -0
- package/dist/templates/native-go/backend/internal/helper/process_linux.go +177 -0
- package/dist/templates/native-go/backend/internal/helper/process_other.go +5 -0
- package/dist/templates/native-go/backend/internal/helper/publication_test.go +178 -0
- package/dist/templates/native-go/backend/internal/helper/read_stream_cohort_linux_test.go +156 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer_linux.go +109 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer_linux_test.go +118 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer_test.go +177 -0
- package/dist/templates/native-go/backend/internal/helper/readonly.go +105 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_admission.go +85 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_cohort_linux_test.go +253 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_linux_test.go +378 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_mount_linux.go +65 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_mount_proxy_linux.go +113 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_operations_linux.go +168 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_resolver_linux.go +241 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_test.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_identity.go +252 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_identity_contract.go +105 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_identity_test.go +406 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_invalidation.go +200 -0
- package/dist/templates/native-go/backend/internal/helper/repair.go +132 -0
- package/dist/templates/native-go/backend/internal/helper/repair_test.go +271 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_acl_linux_test.go +303 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_fixture_linux_test.go +184 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +231 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_fixture_contract_linux_test.go +18 -0
- package/dist/templates/native-go/backend/internal/helper/server_linux.go +124 -0
- package/dist/templates/native-go/backend/internal/helper/status.go +334 -0
- package/dist/templates/native-go/backend/internal/helper/status_test.go +288 -0
- package/dist/templates/native-go/backend/internal/helper/supervision.go +107 -0
- package/dist/templates/native-go/backend/internal/helper/supervision_test.go +124 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame.go +76 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame_linux_test.go +69 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame_test.go +107 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_linux.go +363 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_linux_test.go +913 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_socket_eof_test.go +74 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_socket_test.go +45 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/create.json +23 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/frames.json +67 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/grant-store.json +52 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/intent.json +20 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/list.json +20 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/publish.json +20 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/read.json +22 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/stat.json +22 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/write-stream.json +22 -0
- package/dist/templates/native-go/backend/internal/helper/unit_connection.go +75 -0
- package/dist/templates/native-go/backend/internal/helper/unit_connection_linux_test.go +135 -0
- package/dist/templates/native-go/backend/internal/helper/unit_connection_test.go +133 -0
- package/dist/templates/native-go/backend/internal/helper/unit_frame_test.go +32 -0
- package/dist/templates/native-go/backend/internal/helper/unit_linux.go +364 -0
- package/dist/templates/native-go/backend/internal/helper/unit_linux_test.go +46 -0
- package/dist/templates/native-go/backend/internal/helper/unit_mechanisms_linux_test.go +217 -0
- package/dist/templates/native-go/backend/internal/helper/unit_padding_linux_test.go +178 -0
- package/dist/templates/native-go/backend/internal/helper/unit_query_linux.go +111 -0
- package/dist/templates/native-go/backend/internal/helper/unit_reload_linux_test.go +372 -0
- package/dist/templates/native-go/backend/internal/helper/unit_reload_sequence_linux_test.go +232 -0
- package/dist/templates/native-go/backend/internal/helper/write.go +77 -0
- package/dist/templates/native-go/backend/internal/helper/write_admission.go +260 -0
- package/dist/templates/native-go/backend/internal/helper/write_admission_test.go +135 -0
- package/dist/templates/native-go/backend/internal/helper/write_cohort_linux_test.go +218 -0
- package/dist/templates/native-go/backend/internal/helper/write_files_linux.go +202 -0
- package/dist/templates/native-go/backend/internal/helper/write_files_linux_test.go +199 -0
- package/dist/templates/native-go/backend/internal/helper/write_intent_linux.go +116 -0
- package/dist/templates/native-go/backend/internal/helper/write_intent_linux_test.go +74 -0
- package/dist/templates/native-go/backend/internal/helper/write_operation_linux.go +245 -0
- package/dist/templates/native-go/backend/internal/helper/write_test.go +53 -0
- package/dist/templates/native-go/dsm-package.yaml +58 -0
- package/dist/templates/native-go/gitignore +1 -0
- package/dist/templates/native-go/i18n/glossary.json +662 -0
- package/dist/templates/native-go/i18n/messages/de.json +28 -0
- package/dist/templates/native-go/i18n/messages/en.json +28 -0
- package/dist/templates/native-go/i18n/messages/es.json +28 -0
- package/dist/templates/native-go/i18n/messages/fr.json +28 -0
- package/dist/templates/native-go/i18n/messages/it.json +28 -0
- package/dist/templates/native-go/i18n/messages/ja.json +28 -0
- package/dist/templates/native-go/i18n/messages/ko.json +28 -0
- package/dist/templates/native-go/i18n/messages/zh-CN.json +28 -0
- package/dist/templates/native-go/i18n/messages/zh-TW.json +28 -0
- package/dist/templates/native-go/ui/app.css +35 -0
- package/dist/templates/native-go/ui/app.js +101 -0
- package/dist/templates/native-go-better-auth/backend/internal/app/identity.go +208 -0
- package/dist/templates/native-go-better-auth/backend/internal/app/identity_test.go +113 -0
- package/dist/templates/native-go-better-auth/node/app.mjs +72 -0
- package/dist/templates/native-go-better-auth/node/build.mjs +4 -0
- package/dist/templates/native-go-better-auth/node/package-lock.json +862 -0
- package/dist/templates/native-go-better-auth/node/package.json +1 -0
- package/dist/templates/native-go-better-auth/node/test/auth.test.mjs +31 -0
- package/dist/templates/native-go-integration/backend/internal/app/identity_none.go +6 -0
- package/dist/templates/native-go-integration/backend/internal/app/personal.go +203 -0
- package/dist/templates/native-go-integration/backend/internal/app/personal_test.go +119 -0
- package/dist/templates/native-go-root/backend/internal/app/root.go +107 -0
- package/dist/templates/native-go-root/backend/internal/app/root_test.go +124 -0
- package/dist/templates/native-go-root/root/whoami.sh +6 -0
- package/dist/templates/native-go-vue/README.md +224 -0
- package/dist/templates/native-go-vue/frontend/DESIGN.md +78 -0
- package/dist/templates/native-go-vue/frontend/package-lock.json +2410 -0
- package/dist/templates/native-go-vue/frontend/package.json +6 -0
- package/dist/templates/native-go-vue/frontend/src/App.vue +159 -0
- package/dist/templates/native-go-vue/frontend/src/context.ts +56 -0
- package/dist/templates/native-go-vue/frontend/src/main.ts +29 -0
- package/dist/templates/native-go-vue/frontend/src/nas/NasGrantSettings.vue +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/NasPathPicker.vue +106 -0
- package/dist/templates/native-go-vue/frontend/src/nas/NasUnavailable.vue +20 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/de.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/en.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/es.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/fr.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/it.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/ja.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/ko.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/zh-CN.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/zh-TW.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n.ts +38 -0
- package/dist/templates/native-go-vue/frontend/src/nas/mock-provider.ts +119 -0
- package/dist/templates/native-go-vue/frontend/src/nas/provider.ts +59 -0
- package/dist/templates/native-go-vue/frontend/src/nas/use-request.ts +27 -0
- package/dist/templates/native-go-vue/frontend/src/style.css +31 -0
- package/dist/templates/native-go-vue/frontend/test/apps.test.ts +190 -0
- package/dist/templates/native-go-vue/frontend/test/nas-provider.test.ts +81 -0
- package/dist/templates/native-go-vue/frontend/test/nas-request.test.ts +21 -0
- package/dist/templates/native-go-vue/frontend/test/nas-ui.test.ts +261 -0
- package/dist/templates/native-go-vue/frontend/tsconfig.json +1 -0
- package/dist/templates/native-go-vue/frontend/vite.config.ts +10 -0
- package/dist/templates/native-go-vue/gitignore +2 -0
- package/dist/types.d.ts +1 -1
- package/dist/validate.js +11 -7
- package/package.json +5 -8
- package/schema/synology-app.schema.json +36 -37
- package/skills/SKILL.md +4 -48
- package/skills/reference/create.md +11 -83
- package/skills/reference/deploy.md +7 -78
- package/skills/reference/diagnose.md +4 -101
- package/skills/reference/files.md +5 -41
- package/skills/reference/identity.md +3 -29
- package/skills/reference/wrap.md +0 -2
- package/templates/_daemon/fixture_linux_test.go +15 -0
- package/templates/_daemon/fixture_other_test.go +7 -0
- package/templates/_daemon/go.mod +3 -0
- package/templates/_daemon/main.go +608 -0
- package/templates/_daemon/main_test.go +242 -0
- package/templates/_daemon/process_linux.go +55 -0
- package/templates/_daemon/process_linux_test.go +161 -0
- package/templates/_daemon/process_other.go +14 -0
- package/templates/_daemon/testdata/child.go +41 -0
- package/templates/_shared/GO-LICENSE +27 -0
- package/templates/_shared/GO-PATENTS +22 -0
- package/templates/_shared/LICENSES/TEMPLATE.txt +21 -0
- package/templates/_shared/notice-overrides/index.json +14 -0
- package/templates/_shared/notice-overrides/utils-0.4.2-LICENSE +21 -0
- package/templates/_shared/notice-overrides/utils-0.5.0-LICENSE +21 -0
- package/templates/_shared/third-party-notices.mjs +51 -0
- package/templates/binary/synology-app.yaml +7 -0
- package/templates/hello-files/compose.yaml +0 -1
- package/templates/hello-web/compose.yaml +13 -10
- package/templates/hello-web/html/app.js +1 -23
- package/templates/hello-web/html/index.html +1 -3
- package/templates/hello-web-page/compose.yaml +13 -10
- package/templates/hello-web-page/html/app.js +1 -23
- package/templates/hello-web-page/html/index.html +1 -3
- package/templates/native-go/README.md +324 -0
- package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +59 -0
- package/templates/native-go/backend/cmd/app/main.go +49 -0
- package/templates/native-go/backend/cmd/dsm-readonly-probe/main_linux.go +46 -0
- package/templates/native-go/backend/cmd/helper/main.go +38 -0
- package/templates/native-go/backend/go.mod +7 -0
- package/templates/native-go/backend/go.sum +4 -0
- package/templates/native-go/backend/internal/api/binary.go +154 -0
- package/templates/native-go/backend/internal/api/binary_test.go +165 -0
- package/templates/native-go/backend/internal/api/errors.go +33 -0
- package/templates/native-go/backend/internal/api/registry.go +104 -0
- package/templates/native-go/backend/internal/api/registry_test.go +329 -0
- package/templates/native-go/backend/internal/api/server.go +159 -0
- package/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +121 -0
- package/templates/native-go/backend/internal/app/nas_refusal_test.go +46 -0
- package/templates/native-go/backend/internal/app/root_none.go +9 -0
- package/templates/native-go/backend/internal/app/routes.go +138 -0
- package/templates/native-go/backend/internal/app/routes_test.go +172 -0
- package/templates/native-go/backend/internal/dsm/auth.go +118 -0
- package/templates/native-go/backend/internal/dsm/auth_test.go +139 -0
- package/templates/native-go/backend/internal/dsmprobe/collector_linux.go +335 -0
- package/templates/native-go/backend/internal/dsmprobe/collector_linux_test.go +41 -0
- package/templates/native-go/backend/internal/dsmprobe/protocol.go +179 -0
- package/templates/native-go/backend/internal/dsmprobe/protocol_test.go +29 -0
- package/templates/native-go/backend/internal/helper/cohort.go +393 -0
- package/templates/native-go/backend/internal/helper/cohort_publication.go +18 -0
- package/templates/native-go/backend/internal/helper/cohort_publication_test.go +105 -0
- package/templates/native-go/backend/internal/helper/cohort_test.go +372 -0
- package/templates/native-go/backend/internal/helper/control.go +424 -0
- package/templates/native-go/backend/internal/helper/control_test.go +250 -0
- package/templates/native-go/backend/internal/helper/data_contract.go +242 -0
- package/templates/native-go/backend/internal/helper/data_contract_test.go +51 -0
- package/templates/native-go/backend/internal/helper/data_decode.go +184 -0
- package/templates/native-go/backend/internal/helper/data_decode_pointer_test.go +30 -0
- package/templates/native-go/backend/internal/helper/data_protocol.go +416 -0
- package/templates/native-go/backend/internal/helper/data_protocol_test.go +449 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_linux.go +139 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_linux_test.go +121 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux.go +95 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux_test.go +56 -0
- package/templates/native-go/backend/internal/helper/dsm_bridge_linux.go +144 -0
- package/templates/native-go/backend/internal/helper/dsm_bridge_linux_test.go +89 -0
- package/templates/native-go/backend/internal/helper/dsm_home_linux.go +107 -0
- package/templates/native-go/backend/internal/helper/dsm_home_linux_test.go +82 -0
- package/templates/native-go/backend/internal/helper/dsm_probe_transport_linux.go +151 -0
- package/templates/native-go/backend/internal/helper/dsm_probe_transport_linux_test.go +66 -0
- package/templates/native-go/backend/internal/helper/grant_authority.go +516 -0
- package/templates/native-go/backend/internal/helper/grant_authority_contract.go +88 -0
- package/templates/native-go/backend/internal/helper/grant_authority_test.go +510 -0
- package/templates/native-go/backend/internal/helper/grant_cohort.go +389 -0
- package/templates/native-go/backend/internal/helper/grant_cohort_test.go +239 -0
- package/templates/native-go/backend/internal/helper/grant_delivery.go +49 -0
- package/templates/native-go/backend/internal/helper/grant_delivery_methods.go +273 -0
- package/templates/native-go/backend/internal/helper/grant_delivery_test.go +322 -0
- package/templates/native-go/backend/internal/helper/grant_operation_contract.go +47 -0
- package/templates/native-go/backend/internal/helper/grant_readonly_test.go +180 -0
- package/templates/native-go/backend/internal/helper/grant_repository_linux.go +415 -0
- package/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +468 -0
- package/templates/native-go/backend/internal/helper/grant_rpc.go +147 -0
- package/templates/native-go/backend/internal/helper/grant_rpc_test.go +51 -0
- package/templates/native-go/backend/internal/helper/grant_snapshot.go +75 -0
- package/templates/native-go/backend/internal/helper/grant_supervisor_linux.go +134 -0
- package/templates/native-go/backend/internal/helper/grant_supervisor_linux_test.go +254 -0
- package/templates/native-go/backend/internal/helper/lease.go +112 -0
- package/templates/native-go/backend/internal/helper/lease_linux.go +44 -0
- package/templates/native-go/backend/internal/helper/lease_other.go +8 -0
- package/templates/native-go/backend/internal/helper/lifecycle.go +234 -0
- package/templates/native-go/backend/internal/helper/lifecycle_test.go +473 -0
- package/templates/native-go/backend/internal/helper/managed_pilot.go +284 -0
- package/templates/native-go/backend/internal/helper/managed_pilot_repository_linux.go +74 -0
- package/templates/native-go/backend/internal/helper/managed_pilot_repository_linux_test.go +40 -0
- package/templates/native-go/backend/internal/helper/managed_pilot_test.go +210 -0
- package/templates/native-go/backend/internal/helper/nas_shipped_refusal_linux_test.go +97 -0
- package/templates/native-go/backend/internal/helper/native_discovery.go +79 -0
- package/templates/native-go/backend/internal/helper/native_identity.go +89 -0
- package/templates/native-go/backend/internal/helper/native_provider.go +159 -0
- package/templates/native-go/backend/internal/helper/native_provider_test.go +421 -0
- package/templates/native-go/backend/internal/helper/observation.go +204 -0
- package/templates/native-go/backend/internal/helper/observation_health_test.go +115 -0
- package/templates/native-go/backend/internal/helper/observation_reload_budget_test.go +117 -0
- package/templates/native-go/backend/internal/helper/observation_test.go +196 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic.go +109 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_linux.go +76 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +124 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_test.go +98 -0
- package/templates/native-go/backend/internal/helper/operation_bootstrap_linux.go +193 -0
- package/templates/native-go/backend/internal/helper/operation_credentials_linux.go +56 -0
- package/templates/native-go/backend/internal/helper/operation_linux.go +480 -0
- package/templates/native-go/backend/internal/helper/operation_linux_test.go +528 -0
- package/templates/native-go/backend/internal/helper/peer_linux.go +44 -0
- package/templates/native-go/backend/internal/helper/peer_other.go +7 -0
- package/templates/native-go/backend/internal/helper/process_linux.go +177 -0
- package/templates/native-go/backend/internal/helper/process_other.go +5 -0
- package/templates/native-go/backend/internal/helper/publication_test.go +178 -0
- package/templates/native-go/backend/internal/helper/read_stream_cohort_linux_test.go +156 -0
- package/templates/native-go/backend/internal/helper/read_transfer.go +40 -0
- package/templates/native-go/backend/internal/helper/read_transfer_linux.go +109 -0
- package/templates/native-go/backend/internal/helper/read_transfer_linux_test.go +118 -0
- package/templates/native-go/backend/internal/helper/read_transfer_test.go +177 -0
- package/templates/native-go/backend/internal/helper/readonly.go +105 -0
- package/templates/native-go/backend/internal/helper/readonly_admission.go +85 -0
- package/templates/native-go/backend/internal/helper/readonly_cohort_linux_test.go +253 -0
- package/templates/native-go/backend/internal/helper/readonly_linux_test.go +378 -0
- package/templates/native-go/backend/internal/helper/readonly_mount_linux.go +65 -0
- package/templates/native-go/backend/internal/helper/readonly_mount_proxy_linux.go +113 -0
- package/templates/native-go/backend/internal/helper/readonly_operations_linux.go +168 -0
- package/templates/native-go/backend/internal/helper/readonly_resolver_linux.go +241 -0
- package/templates/native-go/backend/internal/helper/readonly_test.go +40 -0
- package/templates/native-go/backend/internal/helper/relaxed_identity.go +252 -0
- package/templates/native-go/backend/internal/helper/relaxed_identity_contract.go +105 -0
- package/templates/native-go/backend/internal/helper/relaxed_identity_test.go +406 -0
- package/templates/native-go/backend/internal/helper/relaxed_invalidation.go +200 -0
- package/templates/native-go/backend/internal/helper/repair.go +132 -0
- package/templates/native-go/backend/internal/helper/repair_test.go +271 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_acl_linux_test.go +303 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_fixture_linux_test.go +184 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +231 -0
- package/templates/native-go/backend/internal/helper/s1r_fixture_contract_linux_test.go +18 -0
- package/templates/native-go/backend/internal/helper/server_linux.go +124 -0
- package/templates/native-go/backend/internal/helper/status.go +334 -0
- package/templates/native-go/backend/internal/helper/status_test.go +288 -0
- package/templates/native-go/backend/internal/helper/supervision.go +107 -0
- package/templates/native-go/backend/internal/helper/supervision_test.go +124 -0
- package/templates/native-go/backend/internal/helper/supervisor_frame.go +76 -0
- package/templates/native-go/backend/internal/helper/supervisor_frame_linux_test.go +69 -0
- package/templates/native-go/backend/internal/helper/supervisor_frame_test.go +107 -0
- package/templates/native-go/backend/internal/helper/supervisor_linux.go +363 -0
- package/templates/native-go/backend/internal/helper/supervisor_linux_test.go +913 -0
- package/templates/native-go/backend/internal/helper/supervisor_socket_eof_test.go +74 -0
- package/templates/native-go/backend/internal/helper/supervisor_socket_test.go +45 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/create.json +23 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/frames.json +67 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/grant-store.json +52 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/intent.json +20 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/list.json +20 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/publish.json +20 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/read.json +22 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/stat.json +22 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/write-stream.json +22 -0
- package/templates/native-go/backend/internal/helper/unit_connection.go +75 -0
- package/templates/native-go/backend/internal/helper/unit_connection_linux_test.go +135 -0
- package/templates/native-go/backend/internal/helper/unit_connection_test.go +133 -0
- package/templates/native-go/backend/internal/helper/unit_frame_test.go +32 -0
- package/templates/native-go/backend/internal/helper/unit_linux.go +364 -0
- package/templates/native-go/backend/internal/helper/unit_linux_test.go +46 -0
- package/templates/native-go/backend/internal/helper/unit_mechanisms_linux_test.go +217 -0
- package/templates/native-go/backend/internal/helper/unit_padding_linux_test.go +178 -0
- package/templates/native-go/backend/internal/helper/unit_query_linux.go +111 -0
- package/templates/native-go/backend/internal/helper/unit_reload_linux_test.go +372 -0
- package/templates/native-go/backend/internal/helper/unit_reload_sequence_linux_test.go +232 -0
- package/templates/native-go/backend/internal/helper/write.go +77 -0
- package/templates/native-go/backend/internal/helper/write_admission.go +260 -0
- package/templates/native-go/backend/internal/helper/write_admission_test.go +135 -0
- package/templates/native-go/backend/internal/helper/write_cohort_linux_test.go +218 -0
- package/templates/native-go/backend/internal/helper/write_files_linux.go +202 -0
- package/templates/native-go/backend/internal/helper/write_files_linux_test.go +199 -0
- package/templates/native-go/backend/internal/helper/write_intent_linux.go +116 -0
- package/templates/native-go/backend/internal/helper/write_intent_linux_test.go +74 -0
- package/templates/native-go/backend/internal/helper/write_operation_linux.go +245 -0
- package/templates/native-go/backend/internal/helper/write_test.go +53 -0
- package/templates/native-go/dsm-package.yaml +58 -0
- package/templates/native-go/gitignore +1 -0
- package/templates/native-go/i18n/glossary.json +662 -0
- package/templates/native-go/i18n/messages/de.json +28 -0
- package/templates/native-go/i18n/messages/en.json +28 -0
- package/templates/native-go/i18n/messages/es.json +28 -0
- package/templates/native-go/i18n/messages/fr.json +28 -0
- package/templates/native-go/i18n/messages/it.json +28 -0
- package/templates/native-go/i18n/messages/ja.json +28 -0
- package/templates/native-go/i18n/messages/ko.json +28 -0
- package/templates/native-go/i18n/messages/zh-CN.json +28 -0
- package/templates/native-go/i18n/messages/zh-TW.json +28 -0
- package/templates/native-go/ui/app.css +35 -0
- package/templates/native-go/ui/app.js +101 -0
- package/templates/native-go-better-auth/backend/internal/app/identity.go +208 -0
- package/templates/native-go-better-auth/backend/internal/app/identity_test.go +113 -0
- package/templates/native-go-better-auth/node/app.mjs +72 -0
- package/templates/native-go-better-auth/node/build.mjs +4 -0
- package/templates/native-go-better-auth/node/package-lock.json +862 -0
- package/templates/native-go-better-auth/node/package.json +1 -0
- package/templates/native-go-better-auth/node/test/auth.test.mjs +31 -0
- package/templates/native-go-integration/backend/internal/app/identity_none.go +6 -0
- package/templates/native-go-integration/backend/internal/app/personal.go +203 -0
- package/templates/native-go-integration/backend/internal/app/personal_test.go +119 -0
- package/templates/native-go-root/backend/internal/app/root.go +107 -0
- package/templates/native-go-root/backend/internal/app/root_test.go +124 -0
- package/templates/native-go-root/root/whoami.sh +6 -0
- package/templates/native-go-vue/README.md +224 -0
- package/templates/native-go-vue/frontend/DESIGN.md +78 -0
- package/templates/native-go-vue/frontend/package-lock.json +2410 -0
- package/templates/native-go-vue/frontend/package.json +6 -0
- package/templates/native-go-vue/frontend/src/App.vue +159 -0
- package/templates/native-go-vue/frontend/src/context.ts +56 -0
- package/templates/native-go-vue/frontend/src/main.ts +29 -0
- package/templates/native-go-vue/frontend/src/nas/NasGrantSettings.vue +74 -0
- package/templates/native-go-vue/frontend/src/nas/NasPathPicker.vue +106 -0
- package/templates/native-go-vue/frontend/src/nas/NasUnavailable.vue +20 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/de.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/en.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/es.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/fr.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/it.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/ja.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/ko.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/zh-CN.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/zh-TW.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n.ts +38 -0
- package/templates/native-go-vue/frontend/src/nas/mock-provider.ts +119 -0
- package/templates/native-go-vue/frontend/src/nas/provider.ts +59 -0
- package/templates/native-go-vue/frontend/src/nas/use-request.ts +27 -0
- package/templates/native-go-vue/frontend/src/style.css +31 -0
- package/templates/native-go-vue/frontend/test/apps.test.ts +190 -0
- package/templates/native-go-vue/frontend/test/nas-provider.test.ts +81 -0
- package/templates/native-go-vue/frontend/test/nas-request.test.ts +21 -0
- package/templates/native-go-vue/frontend/test/nas-ui.test.ts +261 -0
- package/templates/native-go-vue/frontend/tsconfig.json +1 -0
- package/templates/native-go-vue/frontend/vite.config.ts +10 -0
- package/templates/native-go-vue/gitignore +2 -0
- package/dist/attestation/app-package.d.ts +0 -86
- package/dist/attestation/app-package.js +0 -206
- package/dist/attestation/install-on-host.d.ts +0 -14
- package/dist/attestation/install-on-host.js +0 -52
- package/dist/attestation/keyring.d.ts +0 -21
- package/dist/attestation/keyring.js +0 -168
- package/dist/attestation/platform-service.d.ts +0 -70
- package/dist/attestation/platform-service.js +0 -250
- package/dist/build-spk/broker-glue.d.ts +0 -16
- package/dist/build-spk/broker-glue.js +0 -40
- package/dist/deploy/catalog-publish.d.ts +0 -3
- package/dist/deploy/catalog-publish.js +0 -7
- package/dist/doctor.d.ts +0 -22
- package/dist/doctor.js +0 -822
- package/dist/error-collector.d.ts +0 -2
- package/dist/error-collector.js +0 -46
- package/dist/host/broker-paths.d.ts +0 -1
- package/dist/host/broker-paths.js +0 -1
- package/dist/host/broker-upgrade-preflight.d.ts +0 -61
- package/dist/host/broker-upgrade-preflight.js +0 -156
- package/dist/host/digests.d.ts +0 -5
- package/dist/host/digests.js +0 -63
- package/dist/host/fake-nas.d.ts +0 -49
- package/dist/host/fake-nas.js +0 -193
- package/dist/mock-broker/bootstrap.d.ts +0 -2
- package/dist/mock-broker/bootstrap.js +0 -8
- package/dist/mock-broker/files.d.ts +0 -60
- package/dist/mock-broker/files.js +0 -408
- package/dist/mock-broker/oidc.d.ts +0 -31
- package/dist/mock-broker/oidc.js +0 -161
- package/dist/mock-broker/path.d.ts +0 -9
- package/dist/mock-broker/path.js +0 -50
- package/dist/mock-broker/server.d.ts +0 -19
- package/dist/mock-broker/server.js +0 -350
- package/dist/publish/build-ledger.d.ts +0 -22
- package/dist/publish/build-ledger.js +0 -26
- package/dist/publish/community-path.d.ts +0 -6
- package/dist/publish/community-path.js +0 -41
- package/dist/publish/curated-release.d.ts +0 -78
- package/dist/publish/curated-release.js +0 -883
- package/dist/publish/file-build-ledger.d.ts +0 -18
- package/dist/publish/file-build-ledger.js +0 -268
- package/dist/publish/github-pr.d.ts +0 -25
- package/dist/publish/github-pr.js +0 -85
- package/dist/publish/github-repo.d.ts +0 -8
- package/dist/publish/github-repo.js +0 -21
- package/dist/publish/platform-service-release.d.ts +0 -60
- package/dist/publish/platform-service-release.js +0 -333
- package/dist/publish/preflight.d.ts +0 -24
- package/dist/publish/preflight.js +0 -138
- package/dist/publish/publish.d.ts +0 -27
- package/dist/publish/publish.js +0 -136
- package/dist/publish/sync-definition.d.ts +0 -4
- package/dist/publish/sync-definition.js +0 -48
- package/dist/release-bin.d.ts +0 -2
- package/dist/release-bin.js +0 -23
- package/dist/templates/hello-web/html/sdk.js +0 -68
- package/dist/templates/hello-web-page/html/sdk.js +0 -68
- package/dist/templates/native/synology-app.yaml +0 -7
- package/dist/test-host.d.ts +0 -15
- package/dist/test-host.js +0 -37
- package/templates/hello-web/html/sdk.js +0 -68
- package/templates/hello-web-page/html/sdk.js +0 -68
- package/templates/native/synology-app.yaml +0 -7
- /package/dist/templates/{native → binary}/native.yaml +0 -0
- /package/templates/{native → binary}/native.yaml +0 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Package app holds this package's business operations. Add a route here and
|
|
2
|
+
// pick its policy: api.User (any signed-in DSM user), api.Admin (DSM
|
|
3
|
+
// administrators only) or, rarely, api.Public (no sign-in at all).
|
|
4
|
+
package app
|
|
5
|
+
|
|
6
|
+
import (
|
|
7
|
+
"bytes"
|
|
8
|
+
"context"
|
|
9
|
+
"encoding/json"
|
|
10
|
+
"errors"
|
|
11
|
+
"io/fs"
|
|
12
|
+
"net/http"
|
|
13
|
+
"os"
|
|
14
|
+
"path/filepath"
|
|
15
|
+
"runtime"
|
|
16
|
+
"time"
|
|
17
|
+
"unicode/utf8"
|
|
18
|
+
|
|
19
|
+
"dsmapp/internal/api"
|
|
20
|
+
"dsmapp/internal/helper"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
// Config is fixed at build time and startup, never taken from a request.
|
|
24
|
+
type Config struct {
|
|
25
|
+
PackageID string
|
|
26
|
+
Version string
|
|
27
|
+
HelperInventory helper.Inventory
|
|
28
|
+
// Staged trusted adapter. Nil refuses; no production data transport is installed.
|
|
29
|
+
NASBinaryRead api.BinaryReadHandler
|
|
30
|
+
// DataDir is the package's persistent, package-owned directory
|
|
31
|
+
// (/var/packages/<package>/var). It survives upgrades.
|
|
32
|
+
DataDir string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
func Routes(cfg Config) []api.Route {
|
|
36
|
+
routes := []api.Route{
|
|
37
|
+
api.User("integration.status", cfg.integrationStatus),
|
|
38
|
+
api.BoundedRead(cfg.binaryRead),
|
|
39
|
+
api.User("app.status", cfg.status),
|
|
40
|
+
api.User("greeting.get", cfg.getGreeting),
|
|
41
|
+
api.Admin("greeting.set", cfg.setGreeting),
|
|
42
|
+
}
|
|
43
|
+
return append(routes, cfg.rootRoutes()...)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
func (cfg Config) integrationStatus(ctx context.Context, _ api.Caller, params json.RawMessage) (any, error) {
|
|
47
|
+
if err := decodeParams(params, &struct{}{}); err != nil {
|
|
48
|
+
return nil, err
|
|
49
|
+
}
|
|
50
|
+
return helper.NewClient(cfg.HelperInventory).Status(ctx), nil
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
func (cfg Config) status(_ context.Context, caller api.Caller, _ json.RawMessage) (any, error) {
|
|
54
|
+
return map[string]any{
|
|
55
|
+
"package": cfg.PackageID,
|
|
56
|
+
"version": cfg.Version,
|
|
57
|
+
"user": caller.User(),
|
|
58
|
+
"admin": caller.Admin(),
|
|
59
|
+
"process": map[string]int{"uid": os.Getuid(), "gid": os.Getgid()},
|
|
60
|
+
"go_version": runtime.Version(),
|
|
61
|
+
"platform": runtime.GOOS + "/" + runtime.GOARCH,
|
|
62
|
+
"time": time.Now().UTC().Format(time.RFC3339),
|
|
63
|
+
}, nil
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type greeting struct {
|
|
67
|
+
Text string `json:"text"`
|
|
68
|
+
UpdatedBy string `json:"updated_by,omitempty"`
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
func (cfg Config) greetingPath() string { return filepath.Join(cfg.DataDir, "greeting.json") }
|
|
72
|
+
|
|
73
|
+
func (cfg Config) getGreeting(context.Context, api.Caller, json.RawMessage) (any, error) {
|
|
74
|
+
data, err := os.ReadFile(cfg.greetingPath())
|
|
75
|
+
if errors.Is(err, fs.ErrNotExist) {
|
|
76
|
+
return greeting{Text: "Hello"}, nil
|
|
77
|
+
}
|
|
78
|
+
if err != nil {
|
|
79
|
+
return nil, err
|
|
80
|
+
}
|
|
81
|
+
var g greeting
|
|
82
|
+
return g, json.Unmarshal(data, &g)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
func (cfg Config) setGreeting(_ context.Context, caller api.Caller, params json.RawMessage) (any, error) {
|
|
86
|
+
var in struct {
|
|
87
|
+
Text string `json:"text"`
|
|
88
|
+
}
|
|
89
|
+
if err := decodeParams(params, &in); err != nil {
|
|
90
|
+
return nil, err
|
|
91
|
+
}
|
|
92
|
+
if n := utf8.RuneCountInString(in.Text); n < 1 || n > 200 {
|
|
93
|
+
return nil, api.BadRequest("text must be 1 to 200 characters")
|
|
94
|
+
}
|
|
95
|
+
g := greeting{Text: in.Text, UpdatedBy: caller.User()}
|
|
96
|
+
data, err := json.Marshal(g)
|
|
97
|
+
if err != nil {
|
|
98
|
+
return nil, err
|
|
99
|
+
}
|
|
100
|
+
return g, writeFileAtomic(cfg.greetingPath(), data)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// decodeParams decodes params strictly: unknown fields are an error.
|
|
104
|
+
func decodeParams(params json.RawMessage, into any) error {
|
|
105
|
+
if len(params) == 0 {
|
|
106
|
+
params = json.RawMessage(`{}`)
|
|
107
|
+
}
|
|
108
|
+
dec := json.NewDecoder(bytes.NewReader(params))
|
|
109
|
+
dec.DisallowUnknownFields()
|
|
110
|
+
if err := dec.Decode(into); err != nil {
|
|
111
|
+
return api.BadRequest("invalid params: " + err.Error())
|
|
112
|
+
}
|
|
113
|
+
return nil
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// writeFileAtomic replaces path in one rename, so readers never see half a file.
|
|
117
|
+
func writeFileAtomic(path string, data []byte) error {
|
|
118
|
+
tmp, err := os.CreateTemp(filepath.Dir(path), ".tmp-*")
|
|
119
|
+
if err != nil {
|
|
120
|
+
return err
|
|
121
|
+
}
|
|
122
|
+
defer os.Remove(tmp.Name())
|
|
123
|
+
if _, err := tmp.Write(data); err != nil {
|
|
124
|
+
tmp.Close()
|
|
125
|
+
return err
|
|
126
|
+
}
|
|
127
|
+
if err := tmp.Close(); err != nil {
|
|
128
|
+
return err
|
|
129
|
+
}
|
|
130
|
+
return os.Rename(tmp.Name(), path)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
func (cfg Config) binaryRead(ctx context.Context, c api.Caller, r *http.Request, p json.RawMessage) (api.BinaryRead, error) {
|
|
134
|
+
if cfg.NASBinaryRead == nil {
|
|
135
|
+
return api.BinaryRead{}, &api.Error{Code: "unsupported", Message: "NAS binary read is unavailable"}
|
|
136
|
+
}
|
|
137
|
+
return cfg.NASBinaryRead(ctx, c, r, p)
|
|
138
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
package app
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"net/http"
|
|
6
|
+
"net/http/httptest"
|
|
7
|
+
"os"
|
|
8
|
+
"strings"
|
|
9
|
+
"testing"
|
|
10
|
+
|
|
11
|
+
"dsmapp/internal/api"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
type stubAuth struct {
|
|
15
|
+
identity api.Identity
|
|
16
|
+
err error
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
func (s stubAuth) Authenticate(*http.Request) (api.Identity, error) { return s.identity, s.err }
|
|
20
|
+
|
|
21
|
+
func testConfig(t *testing.T) Config {
|
|
22
|
+
return Config{PackageID: "HelloGo", Version: "0.1.0-0001", DataDir: t.TempDir()}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// call returns the envelope's error code ("" on success) and the envelope.
|
|
26
|
+
func call(t *testing.T, cfg Config, auth api.Authenticator, method, params string) (string, map[string]any) {
|
|
27
|
+
t.Helper()
|
|
28
|
+
srv, err := api.NewServer(auth, Routes(cfg)...)
|
|
29
|
+
if err != nil {
|
|
30
|
+
t.Fatal(err)
|
|
31
|
+
}
|
|
32
|
+
body := `{"method":"` + method + `","params":` + params + `}`
|
|
33
|
+
req := httptest.NewRequest(http.MethodPost, "/api.cgi", strings.NewReader(body))
|
|
34
|
+
req.Header.Set("Content-Type", "application/json")
|
|
35
|
+
rec := httptest.NewRecorder()
|
|
36
|
+
srv.ServeHTTP(rec, req)
|
|
37
|
+
var out map[string]any
|
|
38
|
+
if err := json.Unmarshal(rec.Body.Bytes(), &out); err != nil {
|
|
39
|
+
t.Fatalf("not JSON: %s", rec.Body.String())
|
|
40
|
+
}
|
|
41
|
+
if rec.Code != http.StatusOK {
|
|
42
|
+
t.Fatalf("HTTP %d: DSM replaces non-200 CGI bodies", rec.Code)
|
|
43
|
+
}
|
|
44
|
+
code := ""
|
|
45
|
+
if e, ok := out["error"].(map[string]any); ok {
|
|
46
|
+
code, _ = e["code"].(string)
|
|
47
|
+
}
|
|
48
|
+
return code, out
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
var (
|
|
52
|
+
alice = stubAuth{identity: api.Identity{User: "alice", Admin: true}}
|
|
53
|
+
bob = stubAuth{identity: api.Identity{User: "bob"}}
|
|
54
|
+
nobody = stubAuth{err: api.ErrNoSession}
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
// sampleParams holds valid params for every route, so the denial test below
|
|
58
|
+
// proves the refusal came from the policy and not from bad input.
|
|
59
|
+
var sampleParams = map[string]string{
|
|
60
|
+
"integration.status": `{}`,
|
|
61
|
+
"nas.files.read.binary": `{"operationId":"` + strings.Repeat("a", 64) + `","epoch":"` + strings.Repeat("b", 64) + `","token":"` + strings.Repeat("c", 64) + `"}`,
|
|
62
|
+
"app.status": `{}`,
|
|
63
|
+
"greeting.get": `{}`,
|
|
64
|
+
"greeting.set": `{"text":"Hi"}`,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
func TestIntegrationStatusIsReadableByOrdinaryUsers(t *testing.T) {
|
|
68
|
+
code, out := call(t, testConfig(t), bob, "integration.status", `{}`)
|
|
69
|
+
if code != "" || out["data"].(map[string]any)["state"] != "not-enabled" {
|
|
70
|
+
t.Fatalf("%s: %v", code, out)
|
|
71
|
+
}
|
|
72
|
+
code, _ = call(t, testConfig(t), bob, "integration.status", `{"state":"ready"}`)
|
|
73
|
+
if code != "bad_request" {
|
|
74
|
+
t.Fatal("browser cannot supply readiness")
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
func TestEveryRouteHasSampleParamsAndNoneIsPublic(t *testing.T) {
|
|
79
|
+
routes := Routes(testConfig(t))
|
|
80
|
+
if len(routes) != len(sampleParams) {
|
|
81
|
+
t.Fatalf("%d routes but %d sample params: add the new route to sampleParams", len(routes), len(sampleParams))
|
|
82
|
+
}
|
|
83
|
+
for _, r := range routes {
|
|
84
|
+
if _, ok := sampleParams[r.Method()]; !ok {
|
|
85
|
+
t.Errorf("route %s has no sample params", r.Method())
|
|
86
|
+
}
|
|
87
|
+
if r.Public() {
|
|
88
|
+
t.Errorf("route %s is public; this template ships none", r.Method())
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
func TestEveryRouteRefusesCallersWithoutASessionAndChangesNothing(t *testing.T) {
|
|
94
|
+
for _, r := range Routes(testConfig(t)) {
|
|
95
|
+
cfg := testConfig(t)
|
|
96
|
+
code, _ := call(t, cfg, nobody, r.Method(), sampleParams[r.Method()])
|
|
97
|
+
if code != "session_required" {
|
|
98
|
+
t.Errorf("%s: %q, want session_required", r.Method(), code)
|
|
99
|
+
}
|
|
100
|
+
assertDataDirEmpty(t, cfg)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
func TestEveryAdminRouteRefusesOrdinaryUsersAndChangesNothing(t *testing.T) {
|
|
105
|
+
for _, r := range Routes(testConfig(t)) {
|
|
106
|
+
if !r.AdminOnly() {
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
109
|
+
cfg := testConfig(t)
|
|
110
|
+
code, _ := call(t, cfg, bob, r.Method(), sampleParams[r.Method()])
|
|
111
|
+
if code != "admin_required" {
|
|
112
|
+
t.Errorf("%s: %q, want admin_required", r.Method(), code)
|
|
113
|
+
}
|
|
114
|
+
assertDataDirEmpty(t, cfg)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
func TestEveryRouteSucceedsForAnAdmin(t *testing.T) {
|
|
119
|
+
for _, r := range Routes(testConfig(t)) {
|
|
120
|
+
code, out := call(t, testConfig(t), alice, r.Method(), sampleParams[r.Method()])
|
|
121
|
+
want := ""
|
|
122
|
+
if r.Method() == "nas.files.read.binary" {
|
|
123
|
+
want = "unsupported"
|
|
124
|
+
}
|
|
125
|
+
if code != want {
|
|
126
|
+
t.Errorf("%s: %q %v", r.Method(), code, out)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
func TestStatusReportsPackageAndCaller(t *testing.T) {
|
|
132
|
+
code, out := call(t, testConfig(t), bob, "app.status", `{}`)
|
|
133
|
+
data := out["data"].(map[string]any)
|
|
134
|
+
if code != "" || data["package"] != "HelloGo" || data["version"] != "0.1.0-0001" || data["user"] != "bob" || data["admin"] != false {
|
|
135
|
+
t.Fatalf("got %q %v", code, out)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
func TestGreetingDefaultsAndAdminCanChangeIt(t *testing.T) {
|
|
140
|
+
cfg := testConfig(t)
|
|
141
|
+
_, out := call(t, cfg, bob, "greeting.get", `{}`)
|
|
142
|
+
if got := out["data"].(map[string]any)["text"]; got != "Hello" {
|
|
143
|
+
t.Fatalf("default greeting = %v", got)
|
|
144
|
+
}
|
|
145
|
+
if code, out := call(t, cfg, alice, "greeting.set", `{"text":"Hi from DSM"}`); code != "" {
|
|
146
|
+
t.Fatalf("set: %q %v", code, out)
|
|
147
|
+
}
|
|
148
|
+
_, out = call(t, cfg, bob, "greeting.get", `{}`)
|
|
149
|
+
data := out["data"].(map[string]any)
|
|
150
|
+
if data["text"] != "Hi from DSM" || data["updated_by"] != "alice" {
|
|
151
|
+
t.Fatalf("after set: %v", data)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
func TestGreetingSetValidatesText(t *testing.T) {
|
|
156
|
+
for _, params := range []string{`{}`, `{"text":""}`, `{"text":"` + strings.Repeat("x", 201) + `"}`, `{"text":7}`, `{"text":"ok","extra":1}`} {
|
|
157
|
+
cfg := testConfig(t)
|
|
158
|
+
code, _ := call(t, cfg, alice, "greeting.set", params)
|
|
159
|
+
if code != "bad_request" {
|
|
160
|
+
t.Errorf("%s: %q, want bad_request", params, code)
|
|
161
|
+
}
|
|
162
|
+
assertDataDirEmpty(t, cfg)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
func assertDataDirEmpty(t *testing.T, cfg Config) {
|
|
167
|
+
t.Helper()
|
|
168
|
+
entries, err := os.ReadDir(cfg.DataDir)
|
|
169
|
+
if err != nil || len(entries) != 0 {
|
|
170
|
+
t.Fatalf("data dir changed: %v %v", entries, err)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Package dsm verifies the DSM login behind a package CGI request.
|
|
2
|
+
//
|
|
3
|
+
// DSM runs a package's CGI as the package account and forwards the browser's
|
|
4
|
+
// cookies. This package hands only the session carriers (cookie, SynoToken,
|
|
5
|
+
// client address) to DSM's own authenticate.cgi, which prints the signed-in
|
|
6
|
+
// user name, then reads administrators membership from DSM's group file. It
|
|
7
|
+
// never parses the session cookie or trusts a user name from the request.
|
|
8
|
+
package dsm
|
|
9
|
+
|
|
10
|
+
import (
|
|
11
|
+
"bufio"
|
|
12
|
+
"context"
|
|
13
|
+
"errors"
|
|
14
|
+
"fmt"
|
|
15
|
+
"net"
|
|
16
|
+
"net/http"
|
|
17
|
+
"net/url"
|
|
18
|
+
"os"
|
|
19
|
+
"os/exec"
|
|
20
|
+
"regexp"
|
|
21
|
+
"slices"
|
|
22
|
+
"strings"
|
|
23
|
+
"time"
|
|
24
|
+
|
|
25
|
+
"dsmapp/internal/api"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
// AuthenticateCGI is DSM's session check for third-party CGIs.
|
|
29
|
+
const AuthenticateCGI = "/usr/syno/synoman/webman/modules/authenticate.cgi"
|
|
30
|
+
|
|
31
|
+
// Authenticator implements api.Authenticator against DSM.
|
|
32
|
+
type Authenticator struct {
|
|
33
|
+
GroupFile string
|
|
34
|
+
AdminGroup string
|
|
35
|
+
Timeout time.Duration
|
|
36
|
+
run func(ctx context.Context, path string, env []string) ([]byte, error)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
func NewAuthenticator() *Authenticator {
|
|
40
|
+
return &Authenticator{
|
|
41
|
+
GroupFile: "/etc/group",
|
|
42
|
+
AdminGroup: "administrators",
|
|
43
|
+
Timeout: 10 * time.Second,
|
|
44
|
+
run: runCGI,
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
var userName = regexp.MustCompile(`^[A-Za-z0-9._@\\-]{1,64}$`)
|
|
49
|
+
|
|
50
|
+
func (a *Authenticator) Authenticate(r *http.Request) (api.Identity, error) {
|
|
51
|
+
cookie := r.Header.Get("Cookie")
|
|
52
|
+
if cookie == "" {
|
|
53
|
+
return api.Identity{}, api.ErrNoSession
|
|
54
|
+
}
|
|
55
|
+
ctx, cancel := context.WithTimeout(r.Context(), a.Timeout)
|
|
56
|
+
defer cancel()
|
|
57
|
+
out, err := a.run(ctx, AuthenticateCGI, sessionEnv(r, cookie))
|
|
58
|
+
var exit interface{ ExitCode() int }
|
|
59
|
+
if errors.As(err, &exit) {
|
|
60
|
+
return api.Identity{}, api.ErrNoSession
|
|
61
|
+
}
|
|
62
|
+
if err != nil {
|
|
63
|
+
return api.Identity{}, fmt.Errorf("run %s: %w", AuthenticateCGI, err)
|
|
64
|
+
}
|
|
65
|
+
user := strings.TrimSpace(string(out))
|
|
66
|
+
if !userName.MatchString(user) {
|
|
67
|
+
return api.Identity{}, api.ErrNoSession
|
|
68
|
+
}
|
|
69
|
+
admin, err := a.isMember(user)
|
|
70
|
+
if err != nil {
|
|
71
|
+
return api.Identity{}, err
|
|
72
|
+
}
|
|
73
|
+
return api.Identity{User: user, Admin: admin}, nil
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// sessionEnv is the complete environment authenticate.cgi sees: nothing from
|
|
77
|
+
// this process and no request header besides the session carriers.
|
|
78
|
+
func sessionEnv(r *http.Request, cookie string) []string {
|
|
79
|
+
token := r.Header.Get("X-SYNO-TOKEN")
|
|
80
|
+
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
|
81
|
+
if err != nil {
|
|
82
|
+
host = r.RemoteAddr
|
|
83
|
+
}
|
|
84
|
+
return []string{
|
|
85
|
+
"REQUEST_METHOD=GET",
|
|
86
|
+
"HTTP_COOKIE=" + cookie,
|
|
87
|
+
"HTTP_X_SYNO_TOKEN=" + token,
|
|
88
|
+
"QUERY_STRING=SynoToken=" + url.QueryEscape(token),
|
|
89
|
+
"REMOTE_ADDR=" + host,
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
func runCGI(ctx context.Context, path string, env []string) ([]byte, error) {
|
|
94
|
+
cmd := exec.CommandContext(ctx, path)
|
|
95
|
+
cmd.Env = env
|
|
96
|
+
return cmd.Output()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// isMember reads the group file fresh on every request, so removing someone
|
|
100
|
+
// from administrators takes effect immediately.
|
|
101
|
+
func (a *Authenticator) isMember(user string) (bool, error) {
|
|
102
|
+
f, err := os.Open(a.GroupFile)
|
|
103
|
+
if err != nil {
|
|
104
|
+
return false, fmt.Errorf("read groups: %w", err)
|
|
105
|
+
}
|
|
106
|
+
defer f.Close()
|
|
107
|
+
scanner := bufio.NewScanner(f)
|
|
108
|
+
for scanner.Scan() {
|
|
109
|
+
fields := strings.Split(scanner.Text(), ":")
|
|
110
|
+
if len(fields) == 4 && fields[0] == a.AdminGroup {
|
|
111
|
+
return slices.Contains(strings.Split(fields[3], ","), user), nil
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if err := scanner.Err(); err != nil {
|
|
115
|
+
return false, fmt.Errorf("read groups: %w", err)
|
|
116
|
+
}
|
|
117
|
+
return false, nil
|
|
118
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
package dsm
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"errors"
|
|
6
|
+
"net/http"
|
|
7
|
+
"net/http/httptest"
|
|
8
|
+
"os"
|
|
9
|
+
"path/filepath"
|
|
10
|
+
"slices"
|
|
11
|
+
"strings"
|
|
12
|
+
"testing"
|
|
13
|
+
|
|
14
|
+
"dsmapp/internal/api"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
const groupFile = `root:x:0:
|
|
18
|
+
users:x:100:
|
|
19
|
+
administrators:x:101:admin,alice
|
|
20
|
+
http:x:1023:
|
|
21
|
+
`
|
|
22
|
+
|
|
23
|
+
type fakeRunner struct {
|
|
24
|
+
out string
|
|
25
|
+
err error
|
|
26
|
+
env []string
|
|
27
|
+
path string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
func (f *fakeRunner) run(_ context.Context, path string, env []string) ([]byte, error) {
|
|
31
|
+
f.path, f.env = path, env
|
|
32
|
+
return []byte(f.out), f.err
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
func newTestAuth(t *testing.T, runner *fakeRunner) *Authenticator {
|
|
36
|
+
t.Helper()
|
|
37
|
+
groups := filepath.Join(t.TempDir(), "group")
|
|
38
|
+
if err := os.WriteFile(groups, []byte(groupFile), 0o644); err != nil {
|
|
39
|
+
t.Fatal(err)
|
|
40
|
+
}
|
|
41
|
+
a := NewAuthenticator()
|
|
42
|
+
a.GroupFile = groups
|
|
43
|
+
a.run = runner.run
|
|
44
|
+
return a
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func sessionRequest() *http.Request {
|
|
48
|
+
r := httptest.NewRequest(http.MethodPost, "/webman/3rdparty/App/cgi/api.cgi", nil)
|
|
49
|
+
r.RemoteAddr = "192.0.2.7:51234"
|
|
50
|
+
r.Header.Set("Cookie", "id=abc; did=xyz")
|
|
51
|
+
r.Header.Set("X-SYNO-TOKEN", "tok+en/=")
|
|
52
|
+
r.Header.Set("User-Agent", "should-not-pass")
|
|
53
|
+
return r
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
func TestAdminUserIsResolvedFromAuthenticateCGIAndGroupFile(t *testing.T) {
|
|
57
|
+
runner := &fakeRunner{out: "alice\n"}
|
|
58
|
+
id, err := newTestAuth(t, runner).Authenticate(sessionRequest())
|
|
59
|
+
if err != nil || id.User != "alice" || !id.Admin {
|
|
60
|
+
t.Fatalf("got %+v, %v", id, err)
|
|
61
|
+
}
|
|
62
|
+
if runner.path != AuthenticateCGI {
|
|
63
|
+
t.Errorf("ran %q", runner.path)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
func TestOrdinaryUserIsNotAdmin(t *testing.T) {
|
|
68
|
+
id, err := newTestAuth(t, &fakeRunner{out: "bob\n"}).Authenticate(sessionRequest())
|
|
69
|
+
if err != nil || id.User != "bob" || id.Admin {
|
|
70
|
+
t.Fatalf("got %+v, %v", id, err)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
func TestOnlySessionCarriersReachAuthenticateCGI(t *testing.T) {
|
|
75
|
+
runner := &fakeRunner{out: "alice"}
|
|
76
|
+
if _, err := newTestAuth(t, runner).Authenticate(sessionRequest()); err != nil {
|
|
77
|
+
t.Fatal(err)
|
|
78
|
+
}
|
|
79
|
+
want := []string{
|
|
80
|
+
"HTTP_COOKIE=id=abc; did=xyz",
|
|
81
|
+
"HTTP_X_SYNO_TOKEN=tok+en/=",
|
|
82
|
+
"QUERY_STRING=SynoToken=tok%2Ben%2F%3D",
|
|
83
|
+
"REMOTE_ADDR=192.0.2.7",
|
|
84
|
+
"REQUEST_METHOD=GET",
|
|
85
|
+
}
|
|
86
|
+
got := slices.Clone(runner.env)
|
|
87
|
+
slices.Sort(got)
|
|
88
|
+
if !slices.Equal(got, want) {
|
|
89
|
+
t.Fatalf("env = %q\nwant %q", got, want)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
func TestMissingCookieNeverRunsAuthenticateCGI(t *testing.T) {
|
|
94
|
+
runner := &fakeRunner{out: "alice"}
|
|
95
|
+
r := sessionRequest()
|
|
96
|
+
r.Header.Del("Cookie")
|
|
97
|
+
_, err := newTestAuth(t, runner).Authenticate(r)
|
|
98
|
+
if !errors.Is(err, api.ErrNoSession) || runner.path != "" {
|
|
99
|
+
t.Fatalf("err=%v ran=%q", err, runner.path)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
func TestRejectedOrMalformedSessionsAreNoSession(t *testing.T) {
|
|
104
|
+
for name, runner := range map[string]*fakeRunner{
|
|
105
|
+
"exit status": {err: &exitError{}},
|
|
106
|
+
"empty output": {out: "\n"},
|
|
107
|
+
"two lines": {out: "alice\nadmin\n"},
|
|
108
|
+
"html output": {out: "<html>login</html>"},
|
|
109
|
+
"overlong name": {out: strings.Repeat("a", 200)},
|
|
110
|
+
"space in name": {out: "alice admin"},
|
|
111
|
+
} {
|
|
112
|
+
t.Run(name, func(t *testing.T) {
|
|
113
|
+
_, err := newTestAuth(t, runner).Authenticate(sessionRequest())
|
|
114
|
+
if !errors.Is(err, api.ErrNoSession) {
|
|
115
|
+
t.Fatalf("err = %v", err)
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
func TestBrokenAuthenticatorIsUnavailableNotNoSession(t *testing.T) {
|
|
122
|
+
_, err := newTestAuth(t, &fakeRunner{err: errors.New("exec: not found")}).Authenticate(sessionRequest())
|
|
123
|
+
if err == nil || errors.Is(err, api.ErrNoSession) {
|
|
124
|
+
t.Fatalf("err = %v", err)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
func TestUnreadableGroupFileFailsClosed(t *testing.T) {
|
|
129
|
+
a := newTestAuth(t, &fakeRunner{out: "alice"})
|
|
130
|
+
a.GroupFile = filepath.Join(t.TempDir(), "missing")
|
|
131
|
+
if _, err := a.Authenticate(sessionRequest()); err == nil || errors.Is(err, api.ErrNoSession) {
|
|
132
|
+
t.Fatalf("err = %v, want unavailable", err)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
type exitError struct{}
|
|
137
|
+
|
|
138
|
+
func (*exitError) Error() string { return "exit status 1" }
|
|
139
|
+
func (*exitError) ExitCode() int { return 1 }
|