From 1a7c27663abefef9554c47b2fef171dd8d3773e4 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Fri, 7 Feb 2025 07:59:48 -0800 Subject: [PATCH] Git support (#143) --- package-lock.json | 8 +- package.json | 1 + src-tauri/Cargo.lock | 92 ++- src-tauri/Cargo.toml | 9 +- src-tauri/capabilities/capabilities.json | 1 + src-tauri/gen/schemas/acl-manifests.json | 2 +- src-tauri/gen/schemas/capabilities.json | 2 +- src-tauri/gen/schemas/desktop-schema.json | 125 ++++ src-tauri/gen/schemas/macOS-schema.json | 125 ++++ ...14160022_remove-workspace-sync-setting.sql | 2 + src-tauri/src/analytics.rs | 1 + src-tauri/src/lib.rs | 1 + src-tauri/yaak-git/Cargo.toml | 25 + src-tauri/yaak-git/bindings/gen_git.ts | 18 + src-tauri/yaak-git/bindings/gen_models.ts | 23 + src-tauri/yaak-git/build.rs | 18 + src-tauri/yaak-git/index.ts | 75 ++ src-tauri/yaak-git/package.json | 6 + .../autogenerated/commands/add.toml | 13 + .../autogenerated/commands/branch.toml | 13 + .../autogenerated/commands/checkout.toml | 13 + .../autogenerated/commands/commit.toml | 13 + .../autogenerated/commands/delete_branch.toml | 13 + .../autogenerated/commands/initialize.toml | 13 + .../autogenerated/commands/log.toml | 13 + .../autogenerated/commands/merge_branch.toml | 13 + .../autogenerated/commands/pull.toml | 13 + .../autogenerated/commands/push.toml | 13 + .../autogenerated/commands/status.toml | 13 + .../autogenerated/commands/unstage.toml | 13 + .../permissions/autogenerated/reference.md | 338 +++++++++ src-tauri/yaak-git/permissions/default.toml | 16 + .../yaak-git/permissions/schemas/schema.json | 425 +++++++++++ src-tauri/yaak-git/src/branch.rs | 90 +++ src-tauri/yaak-git/src/callbacks.rs | 76 ++ src-tauri/yaak-git/src/commands.rs | 76 ++ src-tauri/yaak-git/src/error.rs | 55 ++ src-tauri/yaak-git/src/git.rs | 670 ++++++++++++++++++ src-tauri/yaak-git/src/lib.rs | 36 + src-tauri/yaak-git/src/merge.rs | 135 ++++ src-tauri/yaak-git/src/pull.rs | 54 ++ src-tauri/yaak-git/src/push.rs | 74 ++ src-tauri/yaak-git/src/repository.rs | 11 + src-tauri/yaak-git/src/util.rs | 107 +++ src-tauri/yaak-models/src/models.rs | 20 +- src-tauri/yaak-models/src/queries.rs | 18 +- src-tauri/yaak-sync/bindings/git.ts | 7 + src-tauri/yaak-sync/index.ts | 49 +- src-tauri/yaak-sync/src/lib.rs | 4 +- src-tauri/yaak-sync/src/models.rs | 26 +- src-tauri/yaak-sync/src/sync.rs | 8 +- src-tauri/yaak-sync/src/watch.rs | 12 +- src-tauri/yaak-ws/src/{cmd.rs => commands.rs} | 0 src-tauri/yaak-ws/src/lib.rs | 4 +- src-web/commands/commands.tsx | 124 ++-- src-web/commands/deleteWebsocketRequest.tsx | 7 +- src-web/commands/openSettings.ts | 27 + src-web/commands/openWorkspaceSettings.tsx | 25 + src-web/components/CommandPaletteDialog.tsx | 8 +- src-web/components/CookieDropdown.tsx | 6 +- src-web/components/CreateWorkspaceDialog.tsx | 22 +- src-web/components/EnvironmentEditDialog.tsx | 2 - src-web/components/GitCommitDialog.tsx | 312 ++++++++ src-web/components/GitDropdown.tsx | 406 +++++++++++ .../components/GrpcConnectionMessagesPane.tsx | 12 +- .../components/GrpcConnectionSetupPane.tsx | 4 +- src-web/components/LicenseBadge.tsx | 19 +- .../Settings/SettingsAppearance.tsx | 2 +- .../components/Settings/SettingsPlugins.tsx | 1 - src-web/components/SettingsDropdown.tsx | 15 +- .../components/SyncToFilesystemSetting.tsx | 28 +- src-web/components/Toasts.tsx | 28 +- src-web/components/UrlBar.tsx | 1 + src-web/components/WebsocketRequestPane.tsx | 1 + src-web/components/WebsocketResponsePane.tsx | 4 +- .../components/WorkspaceActionsDropdown.tsx | 19 +- src-web/components/WorkspaceHeader.tsx | 3 +- .../components/WorkspaceSettingsDialog.tsx | 12 +- src-web/components/core/Button.tsx | 18 +- src-web/components/core/Checkbox.tsx | 6 +- src-web/components/core/Confirm.tsx | 20 +- src-web/components/core/Dropdown.tsx | 63 +- src-web/components/core/Icon.tsx | 29 +- src-web/components/core/IconButton.tsx | 10 +- src-web/components/core/Input.tsx | 14 +- src-web/components/core/JsonAttributeTree.tsx | 2 +- src-web/components/core/PairOrBulkEditor.tsx | 2 +- src-web/components/core/PlainInput.tsx | 2 +- src-web/components/core/SegmentedControl.tsx | 2 +- src-web/components/core/Table.tsx | 64 ++ src-web/components/core/Tabs/Tabs.tsx | 2 +- src-web/components/core/Toast.tsx | 4 +- .../components/git/BranchSelectionDialog.tsx | 43 ++ src-web/components/git/HistoryDialog.tsx | 40 ++ .../responseViewers/EventStreamViewer.tsx | 2 +- src-web/components/sidebar/Sidebar.tsx | 2 + src-web/components/sidebar/SidebarActions.tsx | 3 +- src-web/components/sidebar/SidebarItem.tsx | 2 +- src-web/components/sidebar/SidebarItems.tsx | 2 +- src-web/hooks/useDeleteActiveWorkspace.tsx | 5 +- src-web/hooks/useDeleteAnyGrpcRequest.tsx | 5 +- src-web/hooks/useDeleteAnyHttpRequest.tsx | 5 +- src-web/hooks/useDeleteCookieJar.tsx | 5 +- src-web/hooks/useDeleteEnvironment.tsx | 5 +- src-web/hooks/useDeleteFolder.tsx | 7 +- src-web/hooks/useDeleteSendHistory.tsx | 5 +- src-web/hooks/useNotificationToast.tsx | 4 +- src-web/hooks/useOpenSettings.tsx | 30 - src-web/init/sync.ts | 93 +-- src-web/lib/confirm.ts | 16 +- src-web/lib/toast.ts | 35 +- 111 files changed, 4264 insertions(+), 372 deletions(-) create mode 100644 src-tauri/migrations/20250114160022_remove-workspace-sync-setting.sql create mode 100644 src-tauri/yaak-git/Cargo.toml create mode 100644 src-tauri/yaak-git/bindings/gen_git.ts create mode 100644 src-tauri/yaak-git/bindings/gen_models.ts create mode 100644 src-tauri/yaak-git/build.rs create mode 100644 src-tauri/yaak-git/index.ts create mode 100644 src-tauri/yaak-git/package.json create mode 100644 src-tauri/yaak-git/permissions/autogenerated/commands/add.toml create mode 100644 src-tauri/yaak-git/permissions/autogenerated/commands/branch.toml create mode 100644 src-tauri/yaak-git/permissions/autogenerated/commands/checkout.toml create mode 100644 src-tauri/yaak-git/permissions/autogenerated/commands/commit.toml create mode 100644 src-tauri/yaak-git/permissions/autogenerated/commands/delete_branch.toml create mode 100644 src-tauri/yaak-git/permissions/autogenerated/commands/initialize.toml create mode 100644 src-tauri/yaak-git/permissions/autogenerated/commands/log.toml create mode 100644 src-tauri/yaak-git/permissions/autogenerated/commands/merge_branch.toml create mode 100644 src-tauri/yaak-git/permissions/autogenerated/commands/pull.toml create mode 100644 src-tauri/yaak-git/permissions/autogenerated/commands/push.toml create mode 100644 src-tauri/yaak-git/permissions/autogenerated/commands/status.toml create mode 100644 src-tauri/yaak-git/permissions/autogenerated/commands/unstage.toml create mode 100644 src-tauri/yaak-git/permissions/autogenerated/reference.md create mode 100644 src-tauri/yaak-git/permissions/default.toml create mode 100644 src-tauri/yaak-git/permissions/schemas/schema.json create mode 100644 src-tauri/yaak-git/src/branch.rs create mode 100644 src-tauri/yaak-git/src/callbacks.rs create mode 100644 src-tauri/yaak-git/src/commands.rs create mode 100644 src-tauri/yaak-git/src/error.rs create mode 100644 src-tauri/yaak-git/src/git.rs create mode 100644 src-tauri/yaak-git/src/lib.rs create mode 100644 src-tauri/yaak-git/src/merge.rs create mode 100644 src-tauri/yaak-git/src/pull.rs create mode 100644 src-tauri/yaak-git/src/push.rs create mode 100644 src-tauri/yaak-git/src/repository.rs create mode 100644 src-tauri/yaak-git/src/util.rs create mode 100644 src-tauri/yaak-sync/bindings/git.ts rename src-tauri/yaak-ws/src/{cmd.rs => commands.rs} (100%) create mode 100644 src-web/commands/openSettings.ts create mode 100644 src-web/commands/openWorkspaceSettings.tsx create mode 100644 src-web/components/GitCommitDialog.tsx create mode 100644 src-web/components/GitDropdown.tsx create mode 100644 src-web/components/core/Table.tsx create mode 100644 src-web/components/git/BranchSelectionDialog.tsx create mode 100644 src-web/components/git/HistoryDialog.tsx delete mode 100644 src-web/hooks/useOpenSettings.tsx diff --git a/package-lock.json b/package-lock.json index 406f630b..9c911154 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "packages/plugin-runtime-types", "packages/common-lib", "src-tauri/yaak-license", + "src-tauri/yaak-git", "src-tauri/yaak-models", "src-tauri/yaak-plugins", "src-tauri/yaak-sse", @@ -3501,6 +3502,10 @@ "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==", "license": "MIT" }, + "node_modules/@yaakapp-internal/git": { + "resolved": "src-tauri/yaak-git", + "link": true + }, "node_modules/@yaakapp-internal/lib": { "resolved": "packages/common-lib", "link": true @@ -15582,8 +15587,7 @@ }, "src-tauri/yaak-git": { "name": "@yaakapp-internal/git", - "version": "1.0.0", - "extraneous": true + "version": "1.0.0" }, "src-tauri/yaak-license": { "name": "@yaakapp-internal/license", diff --git a/package.json b/package.json index 18f27fbc..73bc76df 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "packages/plugin-runtime-types", "packages/common-lib", "src-tauri/yaak-license", + "src-tauri/yaak-git", "src-tauri/yaak-models", "src-tauri/yaak-plugins", "src-tauri/yaak-sse", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 24a229eb..72e8bd29 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -730,6 +730,10 @@ name = "cc" version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "504bdec147f2cc13c8b57ed9401fd8a147cc66b67ad5cb241394244f2c947549" +dependencies = [ + "jobserver", + "libc", +] [[package]] name = "cesu8" @@ -1986,6 +1990,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "git2" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fda788993cc341f69012feba8bf45c0ba4f3291fcc08e214b4d5a7332d88aff" +dependencies = [ + "bitflags 2.6.0", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", +] + [[package]] name = "glib" version = "0.18.5" @@ -2611,6 +2630,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "jpeg-decoder" version = "0.3.1" @@ -2731,6 +2759,20 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "libgit2-sys" +version = "0.18.0+1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a117465e7e1597e8febea8bb0c410f1c7fb93b1e1cddf34363f8390367ffec" +dependencies = [ + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + [[package]] name = "libloading" version = "0.7.4" @@ -2779,6 +2821,32 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libssh2-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-sys" +version = "1.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -3486,9 +3554,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" dependencies = [ "cc", "libc", @@ -7620,6 +7688,7 @@ dependencies = [ "tokio-stream", "ts-rs", "uuid", + "yaak-git", "yaak-grpc", "yaak-http", "yaak-license", @@ -7631,6 +7700,25 @@ dependencies = [ "yaak-ws", ] +[[package]] +name = "yaak-git" +version = "0.1.0" +dependencies = [ + "chrono", + "git2", + "log", + "openssl-sys", + "serde", + "serde_json", + "serde_yaml", + "tauri", + "tauri-plugin", + "thiserror 2.0.11", + "ts-rs", + "yaak-models", + "yaak-sync", +] + [[package]] name = "yaak-grpc" version = "0.1.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ba88c6b6..08d864f5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "yaak-git", "yaak-grpc", "yaak-http", "yaak-license", @@ -37,7 +38,7 @@ objc = "0.2.7" cocoa = "0.26.0" [target.'cfg(target_os = "linux")'.dependencies] -openssl-sys = { version = "0.9", features = ["vendored"] } # For Ubuntu installation to work +openssl-sys = { version = "0.9.105", features = ["vendored"] } # For Ubuntu installation to work [dependencies] chrono = { version = "0.4.31", features = ["serde"] } @@ -72,13 +73,14 @@ tokio = { version = "1.43.0", features = ["sync"] } tokio-stream = "0.1.17" ts-rs = { workspace = true } uuid = "1.12.1" +yaak-git = { path = "yaak-git" } yaak-grpc = { path = "yaak-grpc" } yaak-http = { workspace = true } yaak-license = { path = "yaak-license" } yaak-models = { workspace = true } yaak-plugins = { workspace = true } yaak-sse = { workspace = true } -yaak-sync = { path = "yaak-sync" } +yaak-sync = { workspace = true } yaak-templates = { workspace = true } yaak-ws = { path = "yaak-ws" } @@ -91,8 +93,9 @@ tauri-plugin = "2.0.4" tauri-plugin-shell = "2.2.0" thiserror = "2.0.3" ts-rs = "10.0.0" +yaak-http = { path = "yaak-http" } yaak-models = { path = "yaak-models" } yaak-plugins = { path = "yaak-plugins" } -yaak-http = { path = "yaak-http" } +yaak-sync = { path = "yaak-sync" } yaak-sse = { path = "yaak-sse" } yaak-templates = { path = "yaak-templates" } diff --git a/src-tauri/capabilities/capabilities.json b/src-tauri/capabilities/capabilities.json index 16096f02..841be667 100644 --- a/src-tauri/capabilities/capabilities.json +++ b/src-tauri/capabilities/capabilities.json @@ -51,6 +51,7 @@ "opener:allow-reveal-item-in-dir", "shell:allow-open", "yaak-license:default", + "yaak-git:default", "yaak-sync:default", "yaak-ws:default" ] diff --git a/src-tauri/gen/schemas/acl-manifests.json b/src-tauri/gen/schemas/acl-manifests.json index ef6f8109..fa679a13 100644 --- a/src-tauri/gen/schemas/acl-manifests.json +++ b/src-tauri/gen/schemas/acl-manifests.json @@ -1 +1 @@ -{"clipboard-manager":{"default_permission":{"identifier":"default","description":"No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n","permissions":[]},"permissions":{"allow-clear":{"identifier":"allow-clear","description":"Enables the clear command without any pre-configured scope.","commands":{"allow":["clear"],"deny":[]}},"allow-read-image":{"identifier":"allow-read-image","description":"Enables the read_image command without any pre-configured scope.","commands":{"allow":["read_image"],"deny":[]}},"allow-read-text":{"identifier":"allow-read-text","description":"Enables the read_text command without any pre-configured scope.","commands":{"allow":["read_text"],"deny":[]}},"allow-write-html":{"identifier":"allow-write-html","description":"Enables the write_html command without any pre-configured scope.","commands":{"allow":["write_html"],"deny":[]}},"allow-write-image":{"identifier":"allow-write-image","description":"Enables the write_image command without any pre-configured scope.","commands":{"allow":["write_image"],"deny":[]}},"allow-write-text":{"identifier":"allow-write-text","description":"Enables the write_text command without any pre-configured scope.","commands":{"allow":["write_text"],"deny":[]}},"deny-clear":{"identifier":"deny-clear","description":"Denies the clear command without any pre-configured scope.","commands":{"allow":[],"deny":["clear"]}},"deny-read-image":{"identifier":"deny-read-image","description":"Denies the read_image command without any pre-configured scope.","commands":{"allow":[],"deny":["read_image"]}},"deny-read-text":{"identifier":"deny-read-text","description":"Denies the read_text command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text"]}},"deny-write-html":{"identifier":"deny-write-html","description":"Denies the write_html command without any pre-configured scope.","commands":{"allow":[],"deny":["write_html"]}},"deny-write-image":{"identifier":"deny-write-image","description":"Denies the write_image command without any pre-configured scope.","commands":{"allow":[],"deny":["write_image"]}},"deny-write-text":{"identifier":"deny-write-text","description":"Denies the write_text command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text"]}}},"permission_sets":{},"global_scope_schema":null},"core":{"default_permission":{"identifier":"default","description":"Default core plugins set which includes:\n- 'core:path:default'\n- 'core:event:default'\n- 'core:window:default'\n- 'core:webview:default'\n- 'core:app:default'\n- 'core:image:default'\n- 'core:resources:default'\n- 'core:menu:default'\n- 'core:tray:default'\n","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-internal-toggle-maximize"]},"permissions":{"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-ask","allow-confirm","allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope.","commands":{"allow":["ask"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope.","commands":{"allow":["confirm"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope.","commands":{"allow":[],"deny":["ask"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope.","commands":{"allow":[],"deny":["confirm"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"fs":{"default_permission":{"identifier":"default","description":"This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n","permissions":["create-app-specific-dirs","read-app-specific-dirs-recursive","deny-default"]},"permissions":{"allow-copy-file":{"identifier":"allow-copy-file","description":"Enables the copy_file command without any pre-configured scope.","commands":{"allow":["copy_file"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-exists":{"identifier":"allow-exists","description":"Enables the exists command without any pre-configured scope.","commands":{"allow":["exists"],"deny":[]}},"allow-fstat":{"identifier":"allow-fstat","description":"Enables the fstat command without any pre-configured scope.","commands":{"allow":["fstat"],"deny":[]}},"allow-ftruncate":{"identifier":"allow-ftruncate","description":"Enables the ftruncate command without any pre-configured scope.","commands":{"allow":["ftruncate"],"deny":[]}},"allow-lstat":{"identifier":"allow-lstat","description":"Enables the lstat command without any pre-configured scope.","commands":{"allow":["lstat"],"deny":[]}},"allow-mkdir":{"identifier":"allow-mkdir","description":"Enables the mkdir command without any pre-configured scope.","commands":{"allow":["mkdir"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-read":{"identifier":"allow-read","description":"Enables the read command without any pre-configured scope.","commands":{"allow":["read"],"deny":[]}},"allow-read-dir":{"identifier":"allow-read-dir","description":"Enables the read_dir command without any pre-configured scope.","commands":{"allow":["read_dir"],"deny":[]}},"allow-read-file":{"identifier":"allow-read-file","description":"Enables the read_file command without any pre-configured scope.","commands":{"allow":["read_file"],"deny":[]}},"allow-read-text-file":{"identifier":"allow-read-text-file","description":"Enables the read_text_file command without any pre-configured scope.","commands":{"allow":["read_text_file"],"deny":[]}},"allow-read-text-file-lines":{"identifier":"allow-read-text-file-lines","description":"Enables the read_text_file_lines command without any pre-configured scope.","commands":{"allow":["read_text_file_lines","read_text_file_lines_next"],"deny":[]}},"allow-read-text-file-lines-next":{"identifier":"allow-read-text-file-lines-next","description":"Enables the read_text_file_lines_next command without any pre-configured scope.","commands":{"allow":["read_text_file_lines_next"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-rename":{"identifier":"allow-rename","description":"Enables the rename command without any pre-configured scope.","commands":{"allow":["rename"],"deny":[]}},"allow-seek":{"identifier":"allow-seek","description":"Enables the seek command without any pre-configured scope.","commands":{"allow":["seek"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"allow-stat":{"identifier":"allow-stat","description":"Enables the stat command without any pre-configured scope.","commands":{"allow":["stat"],"deny":[]}},"allow-truncate":{"identifier":"allow-truncate","description":"Enables the truncate command without any pre-configured scope.","commands":{"allow":["truncate"],"deny":[]}},"allow-unwatch":{"identifier":"allow-unwatch","description":"Enables the unwatch command without any pre-configured scope.","commands":{"allow":["unwatch"],"deny":[]}},"allow-watch":{"identifier":"allow-watch","description":"Enables the watch command without any pre-configured scope.","commands":{"allow":["watch"],"deny":[]}},"allow-write":{"identifier":"allow-write","description":"Enables the write command without any pre-configured scope.","commands":{"allow":["write"],"deny":[]}},"allow-write-file":{"identifier":"allow-write-file","description":"Enables the write_file command without any pre-configured scope.","commands":{"allow":["write_file","open","write"],"deny":[]}},"allow-write-text-file":{"identifier":"allow-write-text-file","description":"Enables the write_text_file command without any pre-configured scope.","commands":{"allow":["write_text_file"],"deny":[]}},"create-app-specific-dirs":{"identifier":"create-app-specific-dirs","description":"This permissions allows to create the application specific directories.\n","commands":{"allow":["mkdir","scope-app-index"],"deny":[]}},"deny-copy-file":{"identifier":"deny-copy-file","description":"Denies the copy_file command without any pre-configured scope.","commands":{"allow":[],"deny":["copy_file"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-exists":{"identifier":"deny-exists","description":"Denies the exists command without any pre-configured scope.","commands":{"allow":[],"deny":["exists"]}},"deny-fstat":{"identifier":"deny-fstat","description":"Denies the fstat command without any pre-configured scope.","commands":{"allow":[],"deny":["fstat"]}},"deny-ftruncate":{"identifier":"deny-ftruncate","description":"Denies the ftruncate command without any pre-configured scope.","commands":{"allow":[],"deny":["ftruncate"]}},"deny-lstat":{"identifier":"deny-lstat","description":"Denies the lstat command without any pre-configured scope.","commands":{"allow":[],"deny":["lstat"]}},"deny-mkdir":{"identifier":"deny-mkdir","description":"Denies the mkdir command without any pre-configured scope.","commands":{"allow":[],"deny":["mkdir"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-read":{"identifier":"deny-read","description":"Denies the read command without any pre-configured scope.","commands":{"allow":[],"deny":["read"]}},"deny-read-dir":{"identifier":"deny-read-dir","description":"Denies the read_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["read_dir"]}},"deny-read-file":{"identifier":"deny-read-file","description":"Denies the read_file command without any pre-configured scope.","commands":{"allow":[],"deny":["read_file"]}},"deny-read-text-file":{"identifier":"deny-read-text-file","description":"Denies the read_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text_file"]}},"deny-read-text-file-lines":{"identifier":"deny-read-text-file-lines","description":"Denies the read_text_file_lines command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text_file_lines"]}},"deny-read-text-file-lines-next":{"identifier":"deny-read-text-file-lines-next","description":"Denies the read_text_file_lines_next command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text_file_lines_next"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-rename":{"identifier":"deny-rename","description":"Denies the rename command without any pre-configured scope.","commands":{"allow":[],"deny":["rename"]}},"deny-seek":{"identifier":"deny-seek","description":"Denies the seek command without any pre-configured scope.","commands":{"allow":[],"deny":["seek"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}},"deny-stat":{"identifier":"deny-stat","description":"Denies the stat command without any pre-configured scope.","commands":{"allow":[],"deny":["stat"]}},"deny-truncate":{"identifier":"deny-truncate","description":"Denies the truncate command without any pre-configured scope.","commands":{"allow":[],"deny":["truncate"]}},"deny-unwatch":{"identifier":"deny-unwatch","description":"Denies the unwatch command without any pre-configured scope.","commands":{"allow":[],"deny":["unwatch"]}},"deny-watch":{"identifier":"deny-watch","description":"Denies the watch command without any pre-configured scope.","commands":{"allow":[],"deny":["watch"]}},"deny-webview-data-linux":{"identifier":"deny-webview-data-linux","description":"This denies read access to the\n`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.","commands":{"allow":[],"deny":[]}},"deny-webview-data-windows":{"identifier":"deny-webview-data-windows","description":"This denies read access to the\n`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.","commands":{"allow":[],"deny":[]}},"deny-write":{"identifier":"deny-write","description":"Denies the write command without any pre-configured scope.","commands":{"allow":[],"deny":["write"]}},"deny-write-file":{"identifier":"deny-write-file","description":"Denies the write_file command without any pre-configured scope.","commands":{"allow":[],"deny":["write_file"]}},"deny-write-text-file":{"identifier":"deny-write-text-file","description":"Denies the write_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text_file"]}},"read-all":{"identifier":"read-all","description":"This enables all read related commands without any pre-configured accessible paths.","commands":{"allow":["read_dir","read_file","read","open","read_text_file","read_text_file_lines","read_text_file_lines_next","seek","stat","lstat","fstat","exists","watch","unwatch"],"deny":[]}},"read-app-specific-dirs-recursive":{"identifier":"read-app-specific-dirs-recursive","description":"This permission allows recursive read functionality on the application\nspecific base directories. \n","commands":{"allow":["read_dir","read_file","read_text_file","read_text_file_lines","read_text_file_lines_next","exists","scope-app-recursive"],"deny":[]}},"read-dirs":{"identifier":"read-dirs","description":"This enables directory read and file metadata related commands without any pre-configured accessible paths.","commands":{"allow":["read_dir","stat","lstat","fstat","exists"],"deny":[]}},"read-files":{"identifier":"read-files","description":"This enables file read related commands without any pre-configured accessible paths.","commands":{"allow":["read_file","read","open","read_text_file","read_text_file_lines","read_text_file_lines_next","seek","stat","lstat","fstat","exists"],"deny":[]}},"read-meta":{"identifier":"read-meta","description":"This enables all index or metadata related commands without any pre-configured accessible paths.","commands":{"allow":["read_dir","stat","lstat","fstat","exists","size"],"deny":[]}},"scope":{"identifier":"scope","description":"An empty permission you can use to modify the global scope.","commands":{"allow":[],"deny":[]}},"scope-app":{"identifier":"scope-app","description":"This scope permits access to all files and list content of top level directories in the application folders.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/*"},{"path":"$APPDATA"},{"path":"$APPDATA/*"},{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/*"},{"path":"$APPCACHE"},{"path":"$APPCACHE/*"},{"path":"$APPLOG"},{"path":"$APPLOG/*"}]}},"scope-app-index":{"identifier":"scope-app-index","description":"This scope permits to list all files and folders in the application directories.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPDATA"},{"path":"$APPLOCALDATA"},{"path":"$APPCACHE"},{"path":"$APPLOG"}]}},"scope-app-recursive":{"identifier":"scope-app-recursive","description":"This scope permits recursive access to the complete application folders, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/**"},{"path":"$APPDATA"},{"path":"$APPDATA/**"},{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/**"},{"path":"$APPCACHE"},{"path":"$APPCACHE/**"},{"path":"$APPLOG"},{"path":"$APPLOG/**"}]}},"scope-appcache":{"identifier":"scope-appcache","description":"This scope permits access to all files and list content of top level directories in the `$APPCACHE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCACHE"},{"path":"$APPCACHE/*"}]}},"scope-appcache-index":{"identifier":"scope-appcache-index","description":"This scope permits to list all files and folders in the `$APPCACHE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCACHE"}]}},"scope-appcache-recursive":{"identifier":"scope-appcache-recursive","description":"This scope permits recursive access to the complete `$APPCACHE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCACHE"},{"path":"$APPCACHE/**"}]}},"scope-appconfig":{"identifier":"scope-appconfig","description":"This scope permits access to all files and list content of top level directories in the `$APPCONFIG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/*"}]}},"scope-appconfig-index":{"identifier":"scope-appconfig-index","description":"This scope permits to list all files and folders in the `$APPCONFIG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"}]}},"scope-appconfig-recursive":{"identifier":"scope-appconfig-recursive","description":"This scope permits recursive access to the complete `$APPCONFIG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/**"}]}},"scope-appdata":{"identifier":"scope-appdata","description":"This scope permits access to all files and list content of top level directories in the `$APPDATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPDATA"},{"path":"$APPDATA/*"}]}},"scope-appdata-index":{"identifier":"scope-appdata-index","description":"This scope permits to list all files and folders in the `$APPDATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPDATA"}]}},"scope-appdata-recursive":{"identifier":"scope-appdata-recursive","description":"This scope permits recursive access to the complete `$APPDATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]}},"scope-applocaldata":{"identifier":"scope-applocaldata","description":"This scope permits access to all files and list content of top level directories in the `$APPLOCALDATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/*"}]}},"scope-applocaldata-index":{"identifier":"scope-applocaldata-index","description":"This scope permits to list all files and folders in the `$APPLOCALDATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOCALDATA"}]}},"scope-applocaldata-recursive":{"identifier":"scope-applocaldata-recursive","description":"This scope permits recursive access to the complete `$APPLOCALDATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/**"}]}},"scope-applog":{"identifier":"scope-applog","description":"This scope permits access to all files and list content of top level directories in the `$APPLOG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOG"},{"path":"$APPLOG/*"}]}},"scope-applog-index":{"identifier":"scope-applog-index","description":"This scope permits to list all files and folders in the `$APPLOG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOG"}]}},"scope-applog-recursive":{"identifier":"scope-applog-recursive","description":"This scope permits recursive access to the complete `$APPLOG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOG"},{"path":"$APPLOG/**"}]}},"scope-audio":{"identifier":"scope-audio","description":"This scope permits access to all files and list content of top level directories in the `$AUDIO` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$AUDIO"},{"path":"$AUDIO/*"}]}},"scope-audio-index":{"identifier":"scope-audio-index","description":"This scope permits to list all files and folders in the `$AUDIO`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$AUDIO"}]}},"scope-audio-recursive":{"identifier":"scope-audio-recursive","description":"This scope permits recursive access to the complete `$AUDIO` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$AUDIO"},{"path":"$AUDIO/**"}]}},"scope-cache":{"identifier":"scope-cache","description":"This scope permits access to all files and list content of top level directories in the `$CACHE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CACHE"},{"path":"$CACHE/*"}]}},"scope-cache-index":{"identifier":"scope-cache-index","description":"This scope permits to list all files and folders in the `$CACHE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CACHE"}]}},"scope-cache-recursive":{"identifier":"scope-cache-recursive","description":"This scope permits recursive access to the complete `$CACHE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CACHE"},{"path":"$CACHE/**"}]}},"scope-config":{"identifier":"scope-config","description":"This scope permits access to all files and list content of top level directories in the `$CONFIG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CONFIG"},{"path":"$CONFIG/*"}]}},"scope-config-index":{"identifier":"scope-config-index","description":"This scope permits to list all files and folders in the `$CONFIG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CONFIG"}]}},"scope-config-recursive":{"identifier":"scope-config-recursive","description":"This scope permits recursive access to the complete `$CONFIG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CONFIG"},{"path":"$CONFIG/**"}]}},"scope-data":{"identifier":"scope-data","description":"This scope permits access to all files and list content of top level directories in the `$DATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DATA"},{"path":"$DATA/*"}]}},"scope-data-index":{"identifier":"scope-data-index","description":"This scope permits to list all files and folders in the `$DATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DATA"}]}},"scope-data-recursive":{"identifier":"scope-data-recursive","description":"This scope permits recursive access to the complete `$DATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DATA"},{"path":"$DATA/**"}]}},"scope-desktop":{"identifier":"scope-desktop","description":"This scope permits access to all files and list content of top level directories in the `$DESKTOP` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DESKTOP"},{"path":"$DESKTOP/*"}]}},"scope-desktop-index":{"identifier":"scope-desktop-index","description":"This scope permits to list all files and folders in the `$DESKTOP`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DESKTOP"}]}},"scope-desktop-recursive":{"identifier":"scope-desktop-recursive","description":"This scope permits recursive access to the complete `$DESKTOP` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DESKTOP"},{"path":"$DESKTOP/**"}]}},"scope-document":{"identifier":"scope-document","description":"This scope permits access to all files and list content of top level directories in the `$DOCUMENT` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOCUMENT"},{"path":"$DOCUMENT/*"}]}},"scope-document-index":{"identifier":"scope-document-index","description":"This scope permits to list all files and folders in the `$DOCUMENT`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOCUMENT"}]}},"scope-document-recursive":{"identifier":"scope-document-recursive","description":"This scope permits recursive access to the complete `$DOCUMENT` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOCUMENT"},{"path":"$DOCUMENT/**"}]}},"scope-download":{"identifier":"scope-download","description":"This scope permits access to all files and list content of top level directories in the `$DOWNLOAD` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOWNLOAD"},{"path":"$DOWNLOAD/*"}]}},"scope-download-index":{"identifier":"scope-download-index","description":"This scope permits to list all files and folders in the `$DOWNLOAD`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOWNLOAD"}]}},"scope-download-recursive":{"identifier":"scope-download-recursive","description":"This scope permits recursive access to the complete `$DOWNLOAD` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOWNLOAD"},{"path":"$DOWNLOAD/**"}]}},"scope-exe":{"identifier":"scope-exe","description":"This scope permits access to all files and list content of top level directories in the `$EXE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$EXE"},{"path":"$EXE/*"}]}},"scope-exe-index":{"identifier":"scope-exe-index","description":"This scope permits to list all files and folders in the `$EXE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$EXE"}]}},"scope-exe-recursive":{"identifier":"scope-exe-recursive","description":"This scope permits recursive access to the complete `$EXE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$EXE"},{"path":"$EXE/**"}]}},"scope-font":{"identifier":"scope-font","description":"This scope permits access to all files and list content of top level directories in the `$FONT` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$FONT"},{"path":"$FONT/*"}]}},"scope-font-index":{"identifier":"scope-font-index","description":"This scope permits to list all files and folders in the `$FONT`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$FONT"}]}},"scope-font-recursive":{"identifier":"scope-font-recursive","description":"This scope permits recursive access to the complete `$FONT` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$FONT"},{"path":"$FONT/**"}]}},"scope-home":{"identifier":"scope-home","description":"This scope permits access to all files and list content of top level directories in the `$HOME` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$HOME"},{"path":"$HOME/*"}]}},"scope-home-index":{"identifier":"scope-home-index","description":"This scope permits to list all files and folders in the `$HOME`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$HOME"}]}},"scope-home-recursive":{"identifier":"scope-home-recursive","description":"This scope permits recursive access to the complete `$HOME` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$HOME"},{"path":"$HOME/**"}]}},"scope-localdata":{"identifier":"scope-localdata","description":"This scope permits access to all files and list content of top level directories in the `$LOCALDATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOCALDATA"},{"path":"$LOCALDATA/*"}]}},"scope-localdata-index":{"identifier":"scope-localdata-index","description":"This scope permits to list all files and folders in the `$LOCALDATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOCALDATA"}]}},"scope-localdata-recursive":{"identifier":"scope-localdata-recursive","description":"This scope permits recursive access to the complete `$LOCALDATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOCALDATA"},{"path":"$LOCALDATA/**"}]}},"scope-log":{"identifier":"scope-log","description":"This scope permits access to all files and list content of top level directories in the `$LOG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOG"},{"path":"$LOG/*"}]}},"scope-log-index":{"identifier":"scope-log-index","description":"This scope permits to list all files and folders in the `$LOG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOG"}]}},"scope-log-recursive":{"identifier":"scope-log-recursive","description":"This scope permits recursive access to the complete `$LOG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOG"},{"path":"$LOG/**"}]}},"scope-picture":{"identifier":"scope-picture","description":"This scope permits access to all files and list content of top level directories in the `$PICTURE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PICTURE"},{"path":"$PICTURE/*"}]}},"scope-picture-index":{"identifier":"scope-picture-index","description":"This scope permits to list all files and folders in the `$PICTURE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PICTURE"}]}},"scope-picture-recursive":{"identifier":"scope-picture-recursive","description":"This scope permits recursive access to the complete `$PICTURE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PICTURE"},{"path":"$PICTURE/**"}]}},"scope-public":{"identifier":"scope-public","description":"This scope permits access to all files and list content of top level directories in the `$PUBLIC` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PUBLIC"},{"path":"$PUBLIC/*"}]}},"scope-public-index":{"identifier":"scope-public-index","description":"This scope permits to list all files and folders in the `$PUBLIC`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PUBLIC"}]}},"scope-public-recursive":{"identifier":"scope-public-recursive","description":"This scope permits recursive access to the complete `$PUBLIC` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PUBLIC"},{"path":"$PUBLIC/**"}]}},"scope-resource":{"identifier":"scope-resource","description":"This scope permits access to all files and list content of top level directories in the `$RESOURCE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RESOURCE"},{"path":"$RESOURCE/*"}]}},"scope-resource-index":{"identifier":"scope-resource-index","description":"This scope permits to list all files and folders in the `$RESOURCE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RESOURCE"}]}},"scope-resource-recursive":{"identifier":"scope-resource-recursive","description":"This scope permits recursive access to the complete `$RESOURCE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RESOURCE"},{"path":"$RESOURCE/**"}]}},"scope-runtime":{"identifier":"scope-runtime","description":"This scope permits access to all files and list content of top level directories in the `$RUNTIME` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RUNTIME"},{"path":"$RUNTIME/*"}]}},"scope-runtime-index":{"identifier":"scope-runtime-index","description":"This scope permits to list all files and folders in the `$RUNTIME`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RUNTIME"}]}},"scope-runtime-recursive":{"identifier":"scope-runtime-recursive","description":"This scope permits recursive access to the complete `$RUNTIME` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RUNTIME"},{"path":"$RUNTIME/**"}]}},"scope-temp":{"identifier":"scope-temp","description":"This scope permits access to all files and list content of top level directories in the `$TEMP` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMP"},{"path":"$TEMP/*"}]}},"scope-temp-index":{"identifier":"scope-temp-index","description":"This scope permits to list all files and folders in the `$TEMP`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMP"}]}},"scope-temp-recursive":{"identifier":"scope-temp-recursive","description":"This scope permits recursive access to the complete `$TEMP` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMP"},{"path":"$TEMP/**"}]}},"scope-template":{"identifier":"scope-template","description":"This scope permits access to all files and list content of top level directories in the `$TEMPLATE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMPLATE"},{"path":"$TEMPLATE/*"}]}},"scope-template-index":{"identifier":"scope-template-index","description":"This scope permits to list all files and folders in the `$TEMPLATE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMPLATE"}]}},"scope-template-recursive":{"identifier":"scope-template-recursive","description":"This scope permits recursive access to the complete `$TEMPLATE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMPLATE"},{"path":"$TEMPLATE/**"}]}},"scope-video":{"identifier":"scope-video","description":"This scope permits access to all files and list content of top level directories in the `$VIDEO` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$VIDEO"},{"path":"$VIDEO/*"}]}},"scope-video-index":{"identifier":"scope-video-index","description":"This scope permits to list all files and folders in the `$VIDEO`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$VIDEO"}]}},"scope-video-recursive":{"identifier":"scope-video-recursive","description":"This scope permits recursive access to the complete `$VIDEO` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$VIDEO"},{"path":"$VIDEO/**"}]}},"write-all":{"identifier":"write-all","description":"This enables all write related commands without any pre-configured accessible paths.","commands":{"allow":["mkdir","create","copy_file","remove","rename","truncate","ftruncate","write","write_file","write_text_file"],"deny":[]}},"write-files":{"identifier":"write-files","description":"This enables all file write related commands without any pre-configured accessible paths.","commands":{"allow":["create","copy_file","remove","rename","truncate","ftruncate","write","write_file","write_text_file"],"deny":[]}}},"permission_sets":{"allow-app-meta":{"identifier":"allow-app-meta","description":"This allows non-recursive read access to metadata of the application folders, including file listing and statistics.","permissions":["read-meta","scope-app-index"]},"allow-app-meta-recursive":{"identifier":"allow-app-meta-recursive","description":"This allows full recursive read access to metadata of the application folders, including file listing and statistics.","permissions":["read-meta","scope-app-recursive"]},"allow-app-read":{"identifier":"allow-app-read","description":"This allows non-recursive read access to the application folders.","permissions":["read-all","scope-app"]},"allow-app-read-recursive":{"identifier":"allow-app-read-recursive","description":"This allows full recursive read access to the complete application folders, files and subdirectories.","permissions":["read-all","scope-app-recursive"]},"allow-app-write":{"identifier":"allow-app-write","description":"This allows non-recursive write access to the application folders.","permissions":["write-all","scope-app"]},"allow-app-write-recursive":{"identifier":"allow-app-write-recursive","description":"This allows full recursive write access to the complete application folders, files and subdirectories.","permissions":["write-all","scope-app-recursive"]},"allow-appcache-meta":{"identifier":"allow-appcache-meta","description":"This allows non-recursive read access to metadata of the `$APPCACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-appcache-index"]},"allow-appcache-meta-recursive":{"identifier":"allow-appcache-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPCACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-appcache-recursive"]},"allow-appcache-read":{"identifier":"allow-appcache-read","description":"This allows non-recursive read access to the `$APPCACHE` folder.","permissions":["read-all","scope-appcache"]},"allow-appcache-read-recursive":{"identifier":"allow-appcache-read-recursive","description":"This allows full recursive read access to the complete `$APPCACHE` folder, files and subdirectories.","permissions":["read-all","scope-appcache-recursive"]},"allow-appcache-write":{"identifier":"allow-appcache-write","description":"This allows non-recursive write access to the `$APPCACHE` folder.","permissions":["write-all","scope-appcache"]},"allow-appcache-write-recursive":{"identifier":"allow-appcache-write-recursive","description":"This allows full recursive write access to the complete `$APPCACHE` folder, files and subdirectories.","permissions":["write-all","scope-appcache-recursive"]},"allow-appconfig-meta":{"identifier":"allow-appconfig-meta","description":"This allows non-recursive read access to metadata of the `$APPCONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-appconfig-index"]},"allow-appconfig-meta-recursive":{"identifier":"allow-appconfig-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPCONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-appconfig-recursive"]},"allow-appconfig-read":{"identifier":"allow-appconfig-read","description":"This allows non-recursive read access to the `$APPCONFIG` folder.","permissions":["read-all","scope-appconfig"]},"allow-appconfig-read-recursive":{"identifier":"allow-appconfig-read-recursive","description":"This allows full recursive read access to the complete `$APPCONFIG` folder, files and subdirectories.","permissions":["read-all","scope-appconfig-recursive"]},"allow-appconfig-write":{"identifier":"allow-appconfig-write","description":"This allows non-recursive write access to the `$APPCONFIG` folder.","permissions":["write-all","scope-appconfig"]},"allow-appconfig-write-recursive":{"identifier":"allow-appconfig-write-recursive","description":"This allows full recursive write access to the complete `$APPCONFIG` folder, files and subdirectories.","permissions":["write-all","scope-appconfig-recursive"]},"allow-appdata-meta":{"identifier":"allow-appdata-meta","description":"This allows non-recursive read access to metadata of the `$APPDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-appdata-index"]},"allow-appdata-meta-recursive":{"identifier":"allow-appdata-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-appdata-recursive"]},"allow-appdata-read":{"identifier":"allow-appdata-read","description":"This allows non-recursive read access to the `$APPDATA` folder.","permissions":["read-all","scope-appdata"]},"allow-appdata-read-recursive":{"identifier":"allow-appdata-read-recursive","description":"This allows full recursive read access to the complete `$APPDATA` folder, files and subdirectories.","permissions":["read-all","scope-appdata-recursive"]},"allow-appdata-write":{"identifier":"allow-appdata-write","description":"This allows non-recursive write access to the `$APPDATA` folder.","permissions":["write-all","scope-appdata"]},"allow-appdata-write-recursive":{"identifier":"allow-appdata-write-recursive","description":"This allows full recursive write access to the complete `$APPDATA` folder, files and subdirectories.","permissions":["write-all","scope-appdata-recursive"]},"allow-applocaldata-meta":{"identifier":"allow-applocaldata-meta","description":"This allows non-recursive read access to metadata of the `$APPLOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-applocaldata-index"]},"allow-applocaldata-meta-recursive":{"identifier":"allow-applocaldata-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPLOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-applocaldata-recursive"]},"allow-applocaldata-read":{"identifier":"allow-applocaldata-read","description":"This allows non-recursive read access to the `$APPLOCALDATA` folder.","permissions":["read-all","scope-applocaldata"]},"allow-applocaldata-read-recursive":{"identifier":"allow-applocaldata-read-recursive","description":"This allows full recursive read access to the complete `$APPLOCALDATA` folder, files and subdirectories.","permissions":["read-all","scope-applocaldata-recursive"]},"allow-applocaldata-write":{"identifier":"allow-applocaldata-write","description":"This allows non-recursive write access to the `$APPLOCALDATA` folder.","permissions":["write-all","scope-applocaldata"]},"allow-applocaldata-write-recursive":{"identifier":"allow-applocaldata-write-recursive","description":"This allows full recursive write access to the complete `$APPLOCALDATA` folder, files and subdirectories.","permissions":["write-all","scope-applocaldata-recursive"]},"allow-applog-meta":{"identifier":"allow-applog-meta","description":"This allows non-recursive read access to metadata of the `$APPLOG` folder, including file listing and statistics.","permissions":["read-meta","scope-applog-index"]},"allow-applog-meta-recursive":{"identifier":"allow-applog-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPLOG` folder, including file listing and statistics.","permissions":["read-meta","scope-applog-recursive"]},"allow-applog-read":{"identifier":"allow-applog-read","description":"This allows non-recursive read access to the `$APPLOG` folder.","permissions":["read-all","scope-applog"]},"allow-applog-read-recursive":{"identifier":"allow-applog-read-recursive","description":"This allows full recursive read access to the complete `$APPLOG` folder, files and subdirectories.","permissions":["read-all","scope-applog-recursive"]},"allow-applog-write":{"identifier":"allow-applog-write","description":"This allows non-recursive write access to the `$APPLOG` folder.","permissions":["write-all","scope-applog"]},"allow-applog-write-recursive":{"identifier":"allow-applog-write-recursive","description":"This allows full recursive write access to the complete `$APPLOG` folder, files and subdirectories.","permissions":["write-all","scope-applog-recursive"]},"allow-audio-meta":{"identifier":"allow-audio-meta","description":"This allows non-recursive read access to metadata of the `$AUDIO` folder, including file listing and statistics.","permissions":["read-meta","scope-audio-index"]},"allow-audio-meta-recursive":{"identifier":"allow-audio-meta-recursive","description":"This allows full recursive read access to metadata of the `$AUDIO` folder, including file listing and statistics.","permissions":["read-meta","scope-audio-recursive"]},"allow-audio-read":{"identifier":"allow-audio-read","description":"This allows non-recursive read access to the `$AUDIO` folder.","permissions":["read-all","scope-audio"]},"allow-audio-read-recursive":{"identifier":"allow-audio-read-recursive","description":"This allows full recursive read access to the complete `$AUDIO` folder, files and subdirectories.","permissions":["read-all","scope-audio-recursive"]},"allow-audio-write":{"identifier":"allow-audio-write","description":"This allows non-recursive write access to the `$AUDIO` folder.","permissions":["write-all","scope-audio"]},"allow-audio-write-recursive":{"identifier":"allow-audio-write-recursive","description":"This allows full recursive write access to the complete `$AUDIO` folder, files and subdirectories.","permissions":["write-all","scope-audio-recursive"]},"allow-cache-meta":{"identifier":"allow-cache-meta","description":"This allows non-recursive read access to metadata of the `$CACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-cache-index"]},"allow-cache-meta-recursive":{"identifier":"allow-cache-meta-recursive","description":"This allows full recursive read access to metadata of the `$CACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-cache-recursive"]},"allow-cache-read":{"identifier":"allow-cache-read","description":"This allows non-recursive read access to the `$CACHE` folder.","permissions":["read-all","scope-cache"]},"allow-cache-read-recursive":{"identifier":"allow-cache-read-recursive","description":"This allows full recursive read access to the complete `$CACHE` folder, files and subdirectories.","permissions":["read-all","scope-cache-recursive"]},"allow-cache-write":{"identifier":"allow-cache-write","description":"This allows non-recursive write access to the `$CACHE` folder.","permissions":["write-all","scope-cache"]},"allow-cache-write-recursive":{"identifier":"allow-cache-write-recursive","description":"This allows full recursive write access to the complete `$CACHE` folder, files and subdirectories.","permissions":["write-all","scope-cache-recursive"]},"allow-config-meta":{"identifier":"allow-config-meta","description":"This allows non-recursive read access to metadata of the `$CONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-config-index"]},"allow-config-meta-recursive":{"identifier":"allow-config-meta-recursive","description":"This allows full recursive read access to metadata of the `$CONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-config-recursive"]},"allow-config-read":{"identifier":"allow-config-read","description":"This allows non-recursive read access to the `$CONFIG` folder.","permissions":["read-all","scope-config"]},"allow-config-read-recursive":{"identifier":"allow-config-read-recursive","description":"This allows full recursive read access to the complete `$CONFIG` folder, files and subdirectories.","permissions":["read-all","scope-config-recursive"]},"allow-config-write":{"identifier":"allow-config-write","description":"This allows non-recursive write access to the `$CONFIG` folder.","permissions":["write-all","scope-config"]},"allow-config-write-recursive":{"identifier":"allow-config-write-recursive","description":"This allows full recursive write access to the complete `$CONFIG` folder, files and subdirectories.","permissions":["write-all","scope-config-recursive"]},"allow-data-meta":{"identifier":"allow-data-meta","description":"This allows non-recursive read access to metadata of the `$DATA` folder, including file listing and statistics.","permissions":["read-meta","scope-data-index"]},"allow-data-meta-recursive":{"identifier":"allow-data-meta-recursive","description":"This allows full recursive read access to metadata of the `$DATA` folder, including file listing and statistics.","permissions":["read-meta","scope-data-recursive"]},"allow-data-read":{"identifier":"allow-data-read","description":"This allows non-recursive read access to the `$DATA` folder.","permissions":["read-all","scope-data"]},"allow-data-read-recursive":{"identifier":"allow-data-read-recursive","description":"This allows full recursive read access to the complete `$DATA` folder, files and subdirectories.","permissions":["read-all","scope-data-recursive"]},"allow-data-write":{"identifier":"allow-data-write","description":"This allows non-recursive write access to the `$DATA` folder.","permissions":["write-all","scope-data"]},"allow-data-write-recursive":{"identifier":"allow-data-write-recursive","description":"This allows full recursive write access to the complete `$DATA` folder, files and subdirectories.","permissions":["write-all","scope-data-recursive"]},"allow-desktop-meta":{"identifier":"allow-desktop-meta","description":"This allows non-recursive read access to metadata of the `$DESKTOP` folder, including file listing and statistics.","permissions":["read-meta","scope-desktop-index"]},"allow-desktop-meta-recursive":{"identifier":"allow-desktop-meta-recursive","description":"This allows full recursive read access to metadata of the `$DESKTOP` folder, including file listing and statistics.","permissions":["read-meta","scope-desktop-recursive"]},"allow-desktop-read":{"identifier":"allow-desktop-read","description":"This allows non-recursive read access to the `$DESKTOP` folder.","permissions":["read-all","scope-desktop"]},"allow-desktop-read-recursive":{"identifier":"allow-desktop-read-recursive","description":"This allows full recursive read access to the complete `$DESKTOP` folder, files and subdirectories.","permissions":["read-all","scope-desktop-recursive"]},"allow-desktop-write":{"identifier":"allow-desktop-write","description":"This allows non-recursive write access to the `$DESKTOP` folder.","permissions":["write-all","scope-desktop"]},"allow-desktop-write-recursive":{"identifier":"allow-desktop-write-recursive","description":"This allows full recursive write access to the complete `$DESKTOP` folder, files and subdirectories.","permissions":["write-all","scope-desktop-recursive"]},"allow-document-meta":{"identifier":"allow-document-meta","description":"This allows non-recursive read access to metadata of the `$DOCUMENT` folder, including file listing and statistics.","permissions":["read-meta","scope-document-index"]},"allow-document-meta-recursive":{"identifier":"allow-document-meta-recursive","description":"This allows full recursive read access to metadata of the `$DOCUMENT` folder, including file listing and statistics.","permissions":["read-meta","scope-document-recursive"]},"allow-document-read":{"identifier":"allow-document-read","description":"This allows non-recursive read access to the `$DOCUMENT` folder.","permissions":["read-all","scope-document"]},"allow-document-read-recursive":{"identifier":"allow-document-read-recursive","description":"This allows full recursive read access to the complete `$DOCUMENT` folder, files and subdirectories.","permissions":["read-all","scope-document-recursive"]},"allow-document-write":{"identifier":"allow-document-write","description":"This allows non-recursive write access to the `$DOCUMENT` folder.","permissions":["write-all","scope-document"]},"allow-document-write-recursive":{"identifier":"allow-document-write-recursive","description":"This allows full recursive write access to the complete `$DOCUMENT` folder, files and subdirectories.","permissions":["write-all","scope-document-recursive"]},"allow-download-meta":{"identifier":"allow-download-meta","description":"This allows non-recursive read access to metadata of the `$DOWNLOAD` folder, including file listing and statistics.","permissions":["read-meta","scope-download-index"]},"allow-download-meta-recursive":{"identifier":"allow-download-meta-recursive","description":"This allows full recursive read access to metadata of the `$DOWNLOAD` folder, including file listing and statistics.","permissions":["read-meta","scope-download-recursive"]},"allow-download-read":{"identifier":"allow-download-read","description":"This allows non-recursive read access to the `$DOWNLOAD` folder.","permissions":["read-all","scope-download"]},"allow-download-read-recursive":{"identifier":"allow-download-read-recursive","description":"This allows full recursive read access to the complete `$DOWNLOAD` folder, files and subdirectories.","permissions":["read-all","scope-download-recursive"]},"allow-download-write":{"identifier":"allow-download-write","description":"This allows non-recursive write access to the `$DOWNLOAD` folder.","permissions":["write-all","scope-download"]},"allow-download-write-recursive":{"identifier":"allow-download-write-recursive","description":"This allows full recursive write access to the complete `$DOWNLOAD` folder, files and subdirectories.","permissions":["write-all","scope-download-recursive"]},"allow-exe-meta":{"identifier":"allow-exe-meta","description":"This allows non-recursive read access to metadata of the `$EXE` folder, including file listing and statistics.","permissions":["read-meta","scope-exe-index"]},"allow-exe-meta-recursive":{"identifier":"allow-exe-meta-recursive","description":"This allows full recursive read access to metadata of the `$EXE` folder, including file listing and statistics.","permissions":["read-meta","scope-exe-recursive"]},"allow-exe-read":{"identifier":"allow-exe-read","description":"This allows non-recursive read access to the `$EXE` folder.","permissions":["read-all","scope-exe"]},"allow-exe-read-recursive":{"identifier":"allow-exe-read-recursive","description":"This allows full recursive read access to the complete `$EXE` folder, files and subdirectories.","permissions":["read-all","scope-exe-recursive"]},"allow-exe-write":{"identifier":"allow-exe-write","description":"This allows non-recursive write access to the `$EXE` folder.","permissions":["write-all","scope-exe"]},"allow-exe-write-recursive":{"identifier":"allow-exe-write-recursive","description":"This allows full recursive write access to the complete `$EXE` folder, files and subdirectories.","permissions":["write-all","scope-exe-recursive"]},"allow-font-meta":{"identifier":"allow-font-meta","description":"This allows non-recursive read access to metadata of the `$FONT` folder, including file listing and statistics.","permissions":["read-meta","scope-font-index"]},"allow-font-meta-recursive":{"identifier":"allow-font-meta-recursive","description":"This allows full recursive read access to metadata of the `$FONT` folder, including file listing and statistics.","permissions":["read-meta","scope-font-recursive"]},"allow-font-read":{"identifier":"allow-font-read","description":"This allows non-recursive read access to the `$FONT` folder.","permissions":["read-all","scope-font"]},"allow-font-read-recursive":{"identifier":"allow-font-read-recursive","description":"This allows full recursive read access to the complete `$FONT` folder, files and subdirectories.","permissions":["read-all","scope-font-recursive"]},"allow-font-write":{"identifier":"allow-font-write","description":"This allows non-recursive write access to the `$FONT` folder.","permissions":["write-all","scope-font"]},"allow-font-write-recursive":{"identifier":"allow-font-write-recursive","description":"This allows full recursive write access to the complete `$FONT` folder, files and subdirectories.","permissions":["write-all","scope-font-recursive"]},"allow-home-meta":{"identifier":"allow-home-meta","description":"This allows non-recursive read access to metadata of the `$HOME` folder, including file listing and statistics.","permissions":["read-meta","scope-home-index"]},"allow-home-meta-recursive":{"identifier":"allow-home-meta-recursive","description":"This allows full recursive read access to metadata of the `$HOME` folder, including file listing and statistics.","permissions":["read-meta","scope-home-recursive"]},"allow-home-read":{"identifier":"allow-home-read","description":"This allows non-recursive read access to the `$HOME` folder.","permissions":["read-all","scope-home"]},"allow-home-read-recursive":{"identifier":"allow-home-read-recursive","description":"This allows full recursive read access to the complete `$HOME` folder, files and subdirectories.","permissions":["read-all","scope-home-recursive"]},"allow-home-write":{"identifier":"allow-home-write","description":"This allows non-recursive write access to the `$HOME` folder.","permissions":["write-all","scope-home"]},"allow-home-write-recursive":{"identifier":"allow-home-write-recursive","description":"This allows full recursive write access to the complete `$HOME` folder, files and subdirectories.","permissions":["write-all","scope-home-recursive"]},"allow-localdata-meta":{"identifier":"allow-localdata-meta","description":"This allows non-recursive read access to metadata of the `$LOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-localdata-index"]},"allow-localdata-meta-recursive":{"identifier":"allow-localdata-meta-recursive","description":"This allows full recursive read access to metadata of the `$LOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-localdata-recursive"]},"allow-localdata-read":{"identifier":"allow-localdata-read","description":"This allows non-recursive read access to the `$LOCALDATA` folder.","permissions":["read-all","scope-localdata"]},"allow-localdata-read-recursive":{"identifier":"allow-localdata-read-recursive","description":"This allows full recursive read access to the complete `$LOCALDATA` folder, files and subdirectories.","permissions":["read-all","scope-localdata-recursive"]},"allow-localdata-write":{"identifier":"allow-localdata-write","description":"This allows non-recursive write access to the `$LOCALDATA` folder.","permissions":["write-all","scope-localdata"]},"allow-localdata-write-recursive":{"identifier":"allow-localdata-write-recursive","description":"This allows full recursive write access to the complete `$LOCALDATA` folder, files and subdirectories.","permissions":["write-all","scope-localdata-recursive"]},"allow-log-meta":{"identifier":"allow-log-meta","description":"This allows non-recursive read access to metadata of the `$LOG` folder, including file listing and statistics.","permissions":["read-meta","scope-log-index"]},"allow-log-meta-recursive":{"identifier":"allow-log-meta-recursive","description":"This allows full recursive read access to metadata of the `$LOG` folder, including file listing and statistics.","permissions":["read-meta","scope-log-recursive"]},"allow-log-read":{"identifier":"allow-log-read","description":"This allows non-recursive read access to the `$LOG` folder.","permissions":["read-all","scope-log"]},"allow-log-read-recursive":{"identifier":"allow-log-read-recursive","description":"This allows full recursive read access to the complete `$LOG` folder, files and subdirectories.","permissions":["read-all","scope-log-recursive"]},"allow-log-write":{"identifier":"allow-log-write","description":"This allows non-recursive write access to the `$LOG` folder.","permissions":["write-all","scope-log"]},"allow-log-write-recursive":{"identifier":"allow-log-write-recursive","description":"This allows full recursive write access to the complete `$LOG` folder, files and subdirectories.","permissions":["write-all","scope-log-recursive"]},"allow-picture-meta":{"identifier":"allow-picture-meta","description":"This allows non-recursive read access to metadata of the `$PICTURE` folder, including file listing and statistics.","permissions":["read-meta","scope-picture-index"]},"allow-picture-meta-recursive":{"identifier":"allow-picture-meta-recursive","description":"This allows full recursive read access to metadata of the `$PICTURE` folder, including file listing and statistics.","permissions":["read-meta","scope-picture-recursive"]},"allow-picture-read":{"identifier":"allow-picture-read","description":"This allows non-recursive read access to the `$PICTURE` folder.","permissions":["read-all","scope-picture"]},"allow-picture-read-recursive":{"identifier":"allow-picture-read-recursive","description":"This allows full recursive read access to the complete `$PICTURE` folder, files and subdirectories.","permissions":["read-all","scope-picture-recursive"]},"allow-picture-write":{"identifier":"allow-picture-write","description":"This allows non-recursive write access to the `$PICTURE` folder.","permissions":["write-all","scope-picture"]},"allow-picture-write-recursive":{"identifier":"allow-picture-write-recursive","description":"This allows full recursive write access to the complete `$PICTURE` folder, files and subdirectories.","permissions":["write-all","scope-picture-recursive"]},"allow-public-meta":{"identifier":"allow-public-meta","description":"This allows non-recursive read access to metadata of the `$PUBLIC` folder, including file listing and statistics.","permissions":["read-meta","scope-public-index"]},"allow-public-meta-recursive":{"identifier":"allow-public-meta-recursive","description":"This allows full recursive read access to metadata of the `$PUBLIC` folder, including file listing and statistics.","permissions":["read-meta","scope-public-recursive"]},"allow-public-read":{"identifier":"allow-public-read","description":"This allows non-recursive read access to the `$PUBLIC` folder.","permissions":["read-all","scope-public"]},"allow-public-read-recursive":{"identifier":"allow-public-read-recursive","description":"This allows full recursive read access to the complete `$PUBLIC` folder, files and subdirectories.","permissions":["read-all","scope-public-recursive"]},"allow-public-write":{"identifier":"allow-public-write","description":"This allows non-recursive write access to the `$PUBLIC` folder.","permissions":["write-all","scope-public"]},"allow-public-write-recursive":{"identifier":"allow-public-write-recursive","description":"This allows full recursive write access to the complete `$PUBLIC` folder, files and subdirectories.","permissions":["write-all","scope-public-recursive"]},"allow-resource-meta":{"identifier":"allow-resource-meta","description":"This allows non-recursive read access to metadata of the `$RESOURCE` folder, including file listing and statistics.","permissions":["read-meta","scope-resource-index"]},"allow-resource-meta-recursive":{"identifier":"allow-resource-meta-recursive","description":"This allows full recursive read access to metadata of the `$RESOURCE` folder, including file listing and statistics.","permissions":["read-meta","scope-resource-recursive"]},"allow-resource-read":{"identifier":"allow-resource-read","description":"This allows non-recursive read access to the `$RESOURCE` folder.","permissions":["read-all","scope-resource"]},"allow-resource-read-recursive":{"identifier":"allow-resource-read-recursive","description":"This allows full recursive read access to the complete `$RESOURCE` folder, files and subdirectories.","permissions":["read-all","scope-resource-recursive"]},"allow-resource-write":{"identifier":"allow-resource-write","description":"This allows non-recursive write access to the `$RESOURCE` folder.","permissions":["write-all","scope-resource"]},"allow-resource-write-recursive":{"identifier":"allow-resource-write-recursive","description":"This allows full recursive write access to the complete `$RESOURCE` folder, files and subdirectories.","permissions":["write-all","scope-resource-recursive"]},"allow-runtime-meta":{"identifier":"allow-runtime-meta","description":"This allows non-recursive read access to metadata of the `$RUNTIME` folder, including file listing and statistics.","permissions":["read-meta","scope-runtime-index"]},"allow-runtime-meta-recursive":{"identifier":"allow-runtime-meta-recursive","description":"This allows full recursive read access to metadata of the `$RUNTIME` folder, including file listing and statistics.","permissions":["read-meta","scope-runtime-recursive"]},"allow-runtime-read":{"identifier":"allow-runtime-read","description":"This allows non-recursive read access to the `$RUNTIME` folder.","permissions":["read-all","scope-runtime"]},"allow-runtime-read-recursive":{"identifier":"allow-runtime-read-recursive","description":"This allows full recursive read access to the complete `$RUNTIME` folder, files and subdirectories.","permissions":["read-all","scope-runtime-recursive"]},"allow-runtime-write":{"identifier":"allow-runtime-write","description":"This allows non-recursive write access to the `$RUNTIME` folder.","permissions":["write-all","scope-runtime"]},"allow-runtime-write-recursive":{"identifier":"allow-runtime-write-recursive","description":"This allows full recursive write access to the complete `$RUNTIME` folder, files and subdirectories.","permissions":["write-all","scope-runtime-recursive"]},"allow-temp-meta":{"identifier":"allow-temp-meta","description":"This allows non-recursive read access to metadata of the `$TEMP` folder, including file listing and statistics.","permissions":["read-meta","scope-temp-index"]},"allow-temp-meta-recursive":{"identifier":"allow-temp-meta-recursive","description":"This allows full recursive read access to metadata of the `$TEMP` folder, including file listing and statistics.","permissions":["read-meta","scope-temp-recursive"]},"allow-temp-read":{"identifier":"allow-temp-read","description":"This allows non-recursive read access to the `$TEMP` folder.","permissions":["read-all","scope-temp"]},"allow-temp-read-recursive":{"identifier":"allow-temp-read-recursive","description":"This allows full recursive read access to the complete `$TEMP` folder, files and subdirectories.","permissions":["read-all","scope-temp-recursive"]},"allow-temp-write":{"identifier":"allow-temp-write","description":"This allows non-recursive write access to the `$TEMP` folder.","permissions":["write-all","scope-temp"]},"allow-temp-write-recursive":{"identifier":"allow-temp-write-recursive","description":"This allows full recursive write access to the complete `$TEMP` folder, files and subdirectories.","permissions":["write-all","scope-temp-recursive"]},"allow-template-meta":{"identifier":"allow-template-meta","description":"This allows non-recursive read access to metadata of the `$TEMPLATE` folder, including file listing and statistics.","permissions":["read-meta","scope-template-index"]},"allow-template-meta-recursive":{"identifier":"allow-template-meta-recursive","description":"This allows full recursive read access to metadata of the `$TEMPLATE` folder, including file listing and statistics.","permissions":["read-meta","scope-template-recursive"]},"allow-template-read":{"identifier":"allow-template-read","description":"This allows non-recursive read access to the `$TEMPLATE` folder.","permissions":["read-all","scope-template"]},"allow-template-read-recursive":{"identifier":"allow-template-read-recursive","description":"This allows full recursive read access to the complete `$TEMPLATE` folder, files and subdirectories.","permissions":["read-all","scope-template-recursive"]},"allow-template-write":{"identifier":"allow-template-write","description":"This allows non-recursive write access to the `$TEMPLATE` folder.","permissions":["write-all","scope-template"]},"allow-template-write-recursive":{"identifier":"allow-template-write-recursive","description":"This allows full recursive write access to the complete `$TEMPLATE` folder, files and subdirectories.","permissions":["write-all","scope-template-recursive"]},"allow-video-meta":{"identifier":"allow-video-meta","description":"This allows non-recursive read access to metadata of the `$VIDEO` folder, including file listing and statistics.","permissions":["read-meta","scope-video-index"]},"allow-video-meta-recursive":{"identifier":"allow-video-meta-recursive","description":"This allows full recursive read access to metadata of the `$VIDEO` folder, including file listing and statistics.","permissions":["read-meta","scope-video-recursive"]},"allow-video-read":{"identifier":"allow-video-read","description":"This allows non-recursive read access to the `$VIDEO` folder.","permissions":["read-all","scope-video"]},"allow-video-read-recursive":{"identifier":"allow-video-read-recursive","description":"This allows full recursive read access to the complete `$VIDEO` folder, files and subdirectories.","permissions":["read-all","scope-video-recursive"]},"allow-video-write":{"identifier":"allow-video-write","description":"This allows non-recursive write access to the `$VIDEO` folder.","permissions":["write-all","scope-video"]},"allow-video-write-recursive":{"identifier":"allow-video-write-recursive","description":"This allows full recursive write access to the complete `$VIDEO` folder, files and subdirectories.","permissions":["write-all","scope-video-recursive"]},"deny-default":{"identifier":"deny-default","description":"This denies access to dangerous Tauri relevant files and folders by default.","permissions":["deny-webview-data-linux","deny-webview-data-windows"]}},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"description":"A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},{"properties":{"path":{"description":"A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"}},"required":["path"],"type":"object"}],"description":"FS scope entry.","title":"FsScopeEntry"}},"log":{"default_permission":{"identifier":"default","description":"Allows the log command","permissions":["allow-log"]},"permissions":{"allow-log":{"identifier":"allow-log","description":"Enables the log command without any pre-configured scope.","commands":{"allow":["log"],"deny":[]}},"deny-log":{"identifier":"deny-log","description":"Denies the log command without any pre-configured scope.","commands":{"allow":[],"deny":["log"]}}},"permission_sets":{},"global_scope_schema":null},"opener":{"default_permission":{"identifier":"default","description":"This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer","permissions":["allow-open-url","allow-reveal-item-in-dir","allow-default-urls"]},"permissions":{"allow-default-urls":{"identifier":"allow-default-urls","description":"This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"url":"mailto:*"},{"url":"tel:*"},{"url":"http://*"},{"url":"https://*"}]}},"allow-open-path":{"identifier":"allow-open-path","description":"Enables the open_path command without any pre-configured scope.","commands":{"allow":["open_path"],"deny":[]}},"allow-open-url":{"identifier":"allow-open-url","description":"Enables the open_url command without any pre-configured scope.","commands":{"allow":["open_url"],"deny":[]}},"allow-reveal-item-in-dir":{"identifier":"allow-reveal-item-in-dir","description":"Enables the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":["reveal_item_in_dir"],"deny":[]}},"deny-open-path":{"identifier":"deny-open-path","description":"Denies the open_path command without any pre-configured scope.","commands":{"allow":[],"deny":["open_path"]}},"deny-open-url":{"identifier":"deny-open-url","description":"Denies the open_url command without any pre-configured scope.","commands":{"allow":[],"deny":["open_url"]}},"deny-reveal-item-in-dir":{"identifier":"deny-reveal-item-in-dir","description":"Denies the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_item_in_dir"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this url with, for example: firefox."},"url":{"description":"A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"","type":"string"}},"required":["url"],"type":"object"},{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this path with, for example: xdg-open."},"path":{"description":"A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"}},"required":["path"],"type":"object"}],"definitions":{"Application":{"anyOf":[{"description":"Open in default application.","type":"null"},{"description":"If true, allow open with any application.","type":"boolean"},{"description":"Allow specific application to open with.","type":"string"}],"description":"Opener scope application."}},"description":"Opener scope entry.","title":"OpenerScopeEntry"}},"os":{"default_permission":{"identifier":"default","description":"This permission set configures which\noperating system information are available\nto gather from the frontend.\n\n#### Granted Permissions\n\nAll information except the host name are available.\n\n","permissions":["allow-arch","allow-exe-extension","allow-family","allow-locale","allow-os-type","allow-platform","allow-version"]},"permissions":{"allow-arch":{"identifier":"allow-arch","description":"Enables the arch command without any pre-configured scope.","commands":{"allow":["arch"],"deny":[]}},"allow-exe-extension":{"identifier":"allow-exe-extension","description":"Enables the exe_extension command without any pre-configured scope.","commands":{"allow":["exe_extension"],"deny":[]}},"allow-family":{"identifier":"allow-family","description":"Enables the family command without any pre-configured scope.","commands":{"allow":["family"],"deny":[]}},"allow-hostname":{"identifier":"allow-hostname","description":"Enables the hostname command without any pre-configured scope.","commands":{"allow":["hostname"],"deny":[]}},"allow-locale":{"identifier":"allow-locale","description":"Enables the locale command without any pre-configured scope.","commands":{"allow":["locale"],"deny":[]}},"allow-os-type":{"identifier":"allow-os-type","description":"Enables the os_type command without any pre-configured scope.","commands":{"allow":["os_type"],"deny":[]}},"allow-platform":{"identifier":"allow-platform","description":"Enables the platform command without any pre-configured scope.","commands":{"allow":["platform"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-arch":{"identifier":"deny-arch","description":"Denies the arch command without any pre-configured scope.","commands":{"allow":[],"deny":["arch"]}},"deny-exe-extension":{"identifier":"deny-exe-extension","description":"Denies the exe_extension command without any pre-configured scope.","commands":{"allow":[],"deny":["exe_extension"]}},"deny-family":{"identifier":"deny-family","description":"Denies the family command without any pre-configured scope.","commands":{"allow":[],"deny":["family"]}},"deny-hostname":{"identifier":"deny-hostname","description":"Denies the hostname command without any pre-configured scope.","commands":{"allow":[],"deny":["hostname"]}},"deny-locale":{"identifier":"deny-locale","description":"Denies the locale command without any pre-configured scope.","commands":{"allow":[],"deny":["locale"]}},"deny-os-type":{"identifier":"deny-os-type","description":"Denies the os_type command without any pre-configured scope.","commands":{"allow":[],"deny":["os_type"]}},"deny-platform":{"identifier":"deny-platform","description":"Denies the platform command without any pre-configured scope.","commands":{"allow":[],"deny":["platform"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"shell":{"default_permission":{"identifier":"default","description":"This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality without any specific\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n","permissions":["allow-open"]},"permissions":{"allow-execute":{"identifier":"allow-execute","description":"Enables the execute command without any pre-configured scope.","commands":{"allow":["execute"],"deny":[]}},"allow-kill":{"identifier":"allow-kill","description":"Enables the kill command without any pre-configured scope.","commands":{"allow":["kill"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-spawn":{"identifier":"allow-spawn","description":"Enables the spawn command without any pre-configured scope.","commands":{"allow":["spawn"],"deny":[]}},"allow-stdin-write":{"identifier":"allow-stdin-write","description":"Enables the stdin_write command without any pre-configured scope.","commands":{"allow":["stdin_write"],"deny":[]}},"deny-execute":{"identifier":"deny-execute","description":"Denies the execute command without any pre-configured scope.","commands":{"allow":[],"deny":["execute"]}},"deny-kill":{"identifier":"deny-kill","description":"Denies the kill command without any pre-configured scope.","commands":{"allow":[],"deny":["kill"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-spawn":{"identifier":"deny-spawn","description":"Denies the spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["spawn"]}},"deny-stdin-write":{"identifier":"deny-stdin-write","description":"Denies the stdin_write command without any pre-configured scope.","commands":{"allow":[],"deny":["stdin_write"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"cmd":{"description":"The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"}},"required":["cmd","name"],"type":"object"},{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"},"sidecar":{"description":"If this command is a sidecar command.","type":"boolean"}},"required":["name","sidecar"],"type":"object"}],"definitions":{"ShellScopeEntryAllowedArg":{"anyOf":[{"description":"A non-configurable argument that is passed to the command in the order it was specified.","type":"string"},{"additionalProperties":false,"description":"A variable that is set while calling the command from the webview API.","properties":{"raw":{"default":false,"description":"Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.","type":"boolean"},"validator":{"description":"[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: ","type":"string"}},"required":["validator"],"type":"object"}],"description":"A command argument allowed to be executed by the webview API."},"ShellScopeEntryAllowedArgs":{"anyOf":[{"description":"Use a simple boolean to allow all or disable all arguments to this command configuration.","type":"boolean"},{"description":"A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.","items":{"$ref":"#/definitions/ShellScopeEntryAllowedArg"},"type":"array"}],"description":"A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration."}},"description":"Shell scope entry.","title":"ShellScopeEntry"}},"updater":{"default_permission":{"identifier":"default","description":"This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n","permissions":["allow-check","allow-download","allow-install","allow-download-and-install"]},"permissions":{"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-download":{"identifier":"allow-download","description":"Enables the download command without any pre-configured scope.","commands":{"allow":["download"],"deny":[]}},"allow-download-and-install":{"identifier":"allow-download-and-install","description":"Enables the download_and_install command without any pre-configured scope.","commands":{"allow":["download_and_install"],"deny":[]}},"allow-install":{"identifier":"allow-install","description":"Enables the install command without any pre-configured scope.","commands":{"allow":["install"],"deny":[]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-download":{"identifier":"deny-download","description":"Denies the download command without any pre-configured scope.","commands":{"allow":[],"deny":["download"]}},"deny-download-and-install":{"identifier":"deny-download-and-install","description":"Denies the download_and_install command without any pre-configured scope.","commands":{"allow":[],"deny":["download_and_install"]}},"deny-install":{"identifier":"deny-install","description":"Denies the install command without any pre-configured scope.","commands":{"allow":[],"deny":["install"]}}},"permission_sets":{},"global_scope_schema":null},"window-state":{"default_permission":{"identifier":"default","description":"This permission set configures what kind of\noperations are available from the window state plugin.\n\n#### Granted Permissions\n\nAll operations are enabled by default.\n\n","permissions":["allow-filename","allow-restore-state","allow-save-window-state"]},"permissions":{"allow-filename":{"identifier":"allow-filename","description":"Enables the filename command without any pre-configured scope.","commands":{"allow":["filename"],"deny":[]}},"allow-restore-state":{"identifier":"allow-restore-state","description":"Enables the restore_state command without any pre-configured scope.","commands":{"allow":["restore_state"],"deny":[]}},"allow-save-window-state":{"identifier":"allow-save-window-state","description":"Enables the save_window_state command without any pre-configured scope.","commands":{"allow":["save_window_state"],"deny":[]}},"deny-filename":{"identifier":"deny-filename","description":"Denies the filename command without any pre-configured scope.","commands":{"allow":[],"deny":["filename"]}},"deny-restore-state":{"identifier":"deny-restore-state","description":"Denies the restore_state command without any pre-configured scope.","commands":{"allow":[],"deny":["restore_state"]}},"deny-save-window-state":{"identifier":"deny-save-window-state","description":"Denies the save_window_state command without any pre-configured scope.","commands":{"allow":[],"deny":["save_window_state"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-license":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-check","allow-activate"]},"permissions":{"allow-activate":{"identifier":"allow-activate","description":"Enables the activate command without any pre-configured scope.","commands":{"allow":["activate"],"deny":[]}},"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"deny-activate":{"identifier":"deny-activate","description":"Denies the activate command without any pre-configured scope.","commands":{"allow":[],"deny":["activate"]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-sync":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-calculate","allow-calculate-fs","allow-apply","allow-watch"]},"permissions":{"allow-apply":{"identifier":"allow-apply","description":"Enables the apply command without any pre-configured scope.","commands":{"allow":["apply"],"deny":[]}},"allow-calculate":{"identifier":"allow-calculate","description":"Enables the calculate command without any pre-configured scope.","commands":{"allow":["calculate"],"deny":[]}},"allow-calculate-fs":{"identifier":"allow-calculate-fs","description":"Enables the calculate_fs command without any pre-configured scope.","commands":{"allow":["calculate_fs"],"deny":[]}},"allow-watch":{"identifier":"allow-watch","description":"Enables the watch command without any pre-configured scope.","commands":{"allow":["watch"],"deny":[]}},"deny-apply":{"identifier":"deny-apply","description":"Denies the apply command without any pre-configured scope.","commands":{"allow":[],"deny":["apply"]}},"deny-calculate":{"identifier":"deny-calculate","description":"Denies the calculate command without any pre-configured scope.","commands":{"allow":[],"deny":["calculate"]}},"deny-calculate-fs":{"identifier":"deny-calculate-fs","description":"Denies the calculate_fs command without any pre-configured scope.","commands":{"allow":[],"deny":["calculate_fs"]}},"deny-watch":{"identifier":"deny-watch","description":"Denies the watch command without any pre-configured scope.","commands":{"allow":[],"deny":["watch"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-ws":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-close","allow-connect","allow-delete-connection","allow-delete-connections","allow-delete-request","allow-duplicate-request","allow-list-connections","allow-list-events","allow-list-requests","allow-send","allow-upsert-request"]},"permissions":{"allow-cancel":{"identifier":"allow-cancel","description":"Enables the cancel command without any pre-configured scope.","commands":{"allow":["cancel"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-connect":{"identifier":"allow-connect","description":"Enables the connect command without any pre-configured scope.","commands":{"allow":["connect"],"deny":[]}},"allow-delete-connection":{"identifier":"allow-delete-connection","description":"Enables the delete_connection command without any pre-configured scope.","commands":{"allow":["delete_connection"],"deny":[]}},"allow-delete-connections":{"identifier":"allow-delete-connections","description":"Enables the delete_connections command without any pre-configured scope.","commands":{"allow":["delete_connections"],"deny":[]}},"allow-delete-request":{"identifier":"allow-delete-request","description":"Enables the delete_request command without any pre-configured scope.","commands":{"allow":["delete_request"],"deny":[]}},"allow-duplicate-request":{"identifier":"allow-duplicate-request","description":"Enables the duplicate_request command without any pre-configured scope.","commands":{"allow":["duplicate_request"],"deny":[]}},"allow-list-connections":{"identifier":"allow-list-connections","description":"Enables the list_connections command without any pre-configured scope.","commands":{"allow":["list_connections"],"deny":[]}},"allow-list-events":{"identifier":"allow-list-events","description":"Enables the list_events command without any pre-configured scope.","commands":{"allow":["list_events"],"deny":[]}},"allow-list-requests":{"identifier":"allow-list-requests","description":"Enables the list_requests command without any pre-configured scope.","commands":{"allow":["list_requests"],"deny":[]}},"allow-list-websocket-connections":{"identifier":"allow-list-websocket-connections","description":"Enables the list_websocket_connections command without any pre-configured scope.","commands":{"allow":["list_websocket_connections"],"deny":[]}},"allow-list-websocket-requests":{"identifier":"allow-list-websocket-requests","description":"Enables the list_websocket_requests command without any pre-configured scope.","commands":{"allow":["list_websocket_requests"],"deny":[]}},"allow-send":{"identifier":"allow-send","description":"Enables the send command without any pre-configured scope.","commands":{"allow":["send"],"deny":[]}},"allow-upsert-request":{"identifier":"allow-upsert-request","description":"Enables the upsert_request command without any pre-configured scope.","commands":{"allow":["upsert_request"],"deny":[]}},"allow-upsert-websocket-request":{"identifier":"allow-upsert-websocket-request","description":"Enables the upsert_websocket_request command without any pre-configured scope.","commands":{"allow":["upsert_websocket_request"],"deny":[]}},"deny-cancel":{"identifier":"deny-cancel","description":"Denies the cancel command without any pre-configured scope.","commands":{"allow":[],"deny":["cancel"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-connect":{"identifier":"deny-connect","description":"Denies the connect command without any pre-configured scope.","commands":{"allow":[],"deny":["connect"]}},"deny-delete-connection":{"identifier":"deny-delete-connection","description":"Denies the delete_connection command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_connection"]}},"deny-delete-connections":{"identifier":"deny-delete-connections","description":"Denies the delete_connections command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_connections"]}},"deny-delete-request":{"identifier":"deny-delete-request","description":"Denies the delete_request command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_request"]}},"deny-duplicate-request":{"identifier":"deny-duplicate-request","description":"Denies the duplicate_request command without any pre-configured scope.","commands":{"allow":[],"deny":["duplicate_request"]}},"deny-list-connections":{"identifier":"deny-list-connections","description":"Denies the list_connections command without any pre-configured scope.","commands":{"allow":[],"deny":["list_connections"]}},"deny-list-events":{"identifier":"deny-list-events","description":"Denies the list_events command without any pre-configured scope.","commands":{"allow":[],"deny":["list_events"]}},"deny-list-requests":{"identifier":"deny-list-requests","description":"Denies the list_requests command without any pre-configured scope.","commands":{"allow":[],"deny":["list_requests"]}},"deny-list-websocket-connections":{"identifier":"deny-list-websocket-connections","description":"Denies the list_websocket_connections command without any pre-configured scope.","commands":{"allow":[],"deny":["list_websocket_connections"]}},"deny-list-websocket-requests":{"identifier":"deny-list-websocket-requests","description":"Denies the list_websocket_requests command without any pre-configured scope.","commands":{"allow":[],"deny":["list_websocket_requests"]}},"deny-send":{"identifier":"deny-send","description":"Denies the send command without any pre-configured scope.","commands":{"allow":[],"deny":["send"]}},"deny-upsert-request":{"identifier":"deny-upsert-request","description":"Denies the upsert_request command without any pre-configured scope.","commands":{"allow":[],"deny":["upsert_request"]}},"deny-upsert-websocket-request":{"identifier":"deny-upsert-websocket-request","description":"Denies the upsert_websocket_request command without any pre-configured scope.","commands":{"allow":[],"deny":["upsert_websocket_request"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file +{"clipboard-manager":{"default_permission":{"identifier":"default","description":"No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n","permissions":[]},"permissions":{"allow-clear":{"identifier":"allow-clear","description":"Enables the clear command without any pre-configured scope.","commands":{"allow":["clear"],"deny":[]}},"allow-read-image":{"identifier":"allow-read-image","description":"Enables the read_image command without any pre-configured scope.","commands":{"allow":["read_image"],"deny":[]}},"allow-read-text":{"identifier":"allow-read-text","description":"Enables the read_text command without any pre-configured scope.","commands":{"allow":["read_text"],"deny":[]}},"allow-write-html":{"identifier":"allow-write-html","description":"Enables the write_html command without any pre-configured scope.","commands":{"allow":["write_html"],"deny":[]}},"allow-write-image":{"identifier":"allow-write-image","description":"Enables the write_image command without any pre-configured scope.","commands":{"allow":["write_image"],"deny":[]}},"allow-write-text":{"identifier":"allow-write-text","description":"Enables the write_text command without any pre-configured scope.","commands":{"allow":["write_text"],"deny":[]}},"deny-clear":{"identifier":"deny-clear","description":"Denies the clear command without any pre-configured scope.","commands":{"allow":[],"deny":["clear"]}},"deny-read-image":{"identifier":"deny-read-image","description":"Denies the read_image command without any pre-configured scope.","commands":{"allow":[],"deny":["read_image"]}},"deny-read-text":{"identifier":"deny-read-text","description":"Denies the read_text command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text"]}},"deny-write-html":{"identifier":"deny-write-html","description":"Denies the write_html command without any pre-configured scope.","commands":{"allow":[],"deny":["write_html"]}},"deny-write-image":{"identifier":"deny-write-image","description":"Denies the write_image command without any pre-configured scope.","commands":{"allow":[],"deny":["write_image"]}},"deny-write-text":{"identifier":"deny-write-text","description":"Denies the write_text command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text"]}}},"permission_sets":{},"global_scope_schema":null},"core":{"default_permission":{"identifier":"default","description":"Default core plugins set which includes:\n- 'core:path:default'\n- 'core:event:default'\n- 'core:window:default'\n- 'core:webview:default'\n- 'core:app:default'\n- 'core:image:default'\n- 'core:resources:default'\n- 'core:menu:default'\n- 'core:tray:default'\n","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-internal-toggle-maximize"]},"permissions":{"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-ask","allow-confirm","allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope.","commands":{"allow":["ask"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope.","commands":{"allow":["confirm"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope.","commands":{"allow":[],"deny":["ask"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope.","commands":{"allow":[],"deny":["confirm"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"fs":{"default_permission":{"identifier":"default","description":"This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n","permissions":["create-app-specific-dirs","read-app-specific-dirs-recursive","deny-default"]},"permissions":{"allow-copy-file":{"identifier":"allow-copy-file","description":"Enables the copy_file command without any pre-configured scope.","commands":{"allow":["copy_file"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-exists":{"identifier":"allow-exists","description":"Enables the exists command without any pre-configured scope.","commands":{"allow":["exists"],"deny":[]}},"allow-fstat":{"identifier":"allow-fstat","description":"Enables the fstat command without any pre-configured scope.","commands":{"allow":["fstat"],"deny":[]}},"allow-ftruncate":{"identifier":"allow-ftruncate","description":"Enables the ftruncate command without any pre-configured scope.","commands":{"allow":["ftruncate"],"deny":[]}},"allow-lstat":{"identifier":"allow-lstat","description":"Enables the lstat command without any pre-configured scope.","commands":{"allow":["lstat"],"deny":[]}},"allow-mkdir":{"identifier":"allow-mkdir","description":"Enables the mkdir command without any pre-configured scope.","commands":{"allow":["mkdir"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-read":{"identifier":"allow-read","description":"Enables the read command without any pre-configured scope.","commands":{"allow":["read"],"deny":[]}},"allow-read-dir":{"identifier":"allow-read-dir","description":"Enables the read_dir command without any pre-configured scope.","commands":{"allow":["read_dir"],"deny":[]}},"allow-read-file":{"identifier":"allow-read-file","description":"Enables the read_file command without any pre-configured scope.","commands":{"allow":["read_file"],"deny":[]}},"allow-read-text-file":{"identifier":"allow-read-text-file","description":"Enables the read_text_file command without any pre-configured scope.","commands":{"allow":["read_text_file"],"deny":[]}},"allow-read-text-file-lines":{"identifier":"allow-read-text-file-lines","description":"Enables the read_text_file_lines command without any pre-configured scope.","commands":{"allow":["read_text_file_lines","read_text_file_lines_next"],"deny":[]}},"allow-read-text-file-lines-next":{"identifier":"allow-read-text-file-lines-next","description":"Enables the read_text_file_lines_next command without any pre-configured scope.","commands":{"allow":["read_text_file_lines_next"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-rename":{"identifier":"allow-rename","description":"Enables the rename command without any pre-configured scope.","commands":{"allow":["rename"],"deny":[]}},"allow-seek":{"identifier":"allow-seek","description":"Enables the seek command without any pre-configured scope.","commands":{"allow":["seek"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"allow-stat":{"identifier":"allow-stat","description":"Enables the stat command without any pre-configured scope.","commands":{"allow":["stat"],"deny":[]}},"allow-truncate":{"identifier":"allow-truncate","description":"Enables the truncate command without any pre-configured scope.","commands":{"allow":["truncate"],"deny":[]}},"allow-unwatch":{"identifier":"allow-unwatch","description":"Enables the unwatch command without any pre-configured scope.","commands":{"allow":["unwatch"],"deny":[]}},"allow-watch":{"identifier":"allow-watch","description":"Enables the watch command without any pre-configured scope.","commands":{"allow":["watch"],"deny":[]}},"allow-write":{"identifier":"allow-write","description":"Enables the write command without any pre-configured scope.","commands":{"allow":["write"],"deny":[]}},"allow-write-file":{"identifier":"allow-write-file","description":"Enables the write_file command without any pre-configured scope.","commands":{"allow":["write_file","open","write"],"deny":[]}},"allow-write-text-file":{"identifier":"allow-write-text-file","description":"Enables the write_text_file command without any pre-configured scope.","commands":{"allow":["write_text_file"],"deny":[]}},"create-app-specific-dirs":{"identifier":"create-app-specific-dirs","description":"This permissions allows to create the application specific directories.\n","commands":{"allow":["mkdir","scope-app-index"],"deny":[]}},"deny-copy-file":{"identifier":"deny-copy-file","description":"Denies the copy_file command without any pre-configured scope.","commands":{"allow":[],"deny":["copy_file"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-exists":{"identifier":"deny-exists","description":"Denies the exists command without any pre-configured scope.","commands":{"allow":[],"deny":["exists"]}},"deny-fstat":{"identifier":"deny-fstat","description":"Denies the fstat command without any pre-configured scope.","commands":{"allow":[],"deny":["fstat"]}},"deny-ftruncate":{"identifier":"deny-ftruncate","description":"Denies the ftruncate command without any pre-configured scope.","commands":{"allow":[],"deny":["ftruncate"]}},"deny-lstat":{"identifier":"deny-lstat","description":"Denies the lstat command without any pre-configured scope.","commands":{"allow":[],"deny":["lstat"]}},"deny-mkdir":{"identifier":"deny-mkdir","description":"Denies the mkdir command without any pre-configured scope.","commands":{"allow":[],"deny":["mkdir"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-read":{"identifier":"deny-read","description":"Denies the read command without any pre-configured scope.","commands":{"allow":[],"deny":["read"]}},"deny-read-dir":{"identifier":"deny-read-dir","description":"Denies the read_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["read_dir"]}},"deny-read-file":{"identifier":"deny-read-file","description":"Denies the read_file command without any pre-configured scope.","commands":{"allow":[],"deny":["read_file"]}},"deny-read-text-file":{"identifier":"deny-read-text-file","description":"Denies the read_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text_file"]}},"deny-read-text-file-lines":{"identifier":"deny-read-text-file-lines","description":"Denies the read_text_file_lines command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text_file_lines"]}},"deny-read-text-file-lines-next":{"identifier":"deny-read-text-file-lines-next","description":"Denies the read_text_file_lines_next command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text_file_lines_next"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-rename":{"identifier":"deny-rename","description":"Denies the rename command without any pre-configured scope.","commands":{"allow":[],"deny":["rename"]}},"deny-seek":{"identifier":"deny-seek","description":"Denies the seek command without any pre-configured scope.","commands":{"allow":[],"deny":["seek"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}},"deny-stat":{"identifier":"deny-stat","description":"Denies the stat command without any pre-configured scope.","commands":{"allow":[],"deny":["stat"]}},"deny-truncate":{"identifier":"deny-truncate","description":"Denies the truncate command without any pre-configured scope.","commands":{"allow":[],"deny":["truncate"]}},"deny-unwatch":{"identifier":"deny-unwatch","description":"Denies the unwatch command without any pre-configured scope.","commands":{"allow":[],"deny":["unwatch"]}},"deny-watch":{"identifier":"deny-watch","description":"Denies the watch command without any pre-configured scope.","commands":{"allow":[],"deny":["watch"]}},"deny-webview-data-linux":{"identifier":"deny-webview-data-linux","description":"This denies read access to the\n`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.","commands":{"allow":[],"deny":[]}},"deny-webview-data-windows":{"identifier":"deny-webview-data-windows","description":"This denies read access to the\n`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.","commands":{"allow":[],"deny":[]}},"deny-write":{"identifier":"deny-write","description":"Denies the write command without any pre-configured scope.","commands":{"allow":[],"deny":["write"]}},"deny-write-file":{"identifier":"deny-write-file","description":"Denies the write_file command without any pre-configured scope.","commands":{"allow":[],"deny":["write_file"]}},"deny-write-text-file":{"identifier":"deny-write-text-file","description":"Denies the write_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text_file"]}},"read-all":{"identifier":"read-all","description":"This enables all read related commands without any pre-configured accessible paths.","commands":{"allow":["read_dir","read_file","read","open","read_text_file","read_text_file_lines","read_text_file_lines_next","seek","stat","lstat","fstat","exists","watch","unwatch"],"deny":[]}},"read-app-specific-dirs-recursive":{"identifier":"read-app-specific-dirs-recursive","description":"This permission allows recursive read functionality on the application\nspecific base directories. \n","commands":{"allow":["read_dir","read_file","read_text_file","read_text_file_lines","read_text_file_lines_next","exists","scope-app-recursive"],"deny":[]}},"read-dirs":{"identifier":"read-dirs","description":"This enables directory read and file metadata related commands without any pre-configured accessible paths.","commands":{"allow":["read_dir","stat","lstat","fstat","exists"],"deny":[]}},"read-files":{"identifier":"read-files","description":"This enables file read related commands without any pre-configured accessible paths.","commands":{"allow":["read_file","read","open","read_text_file","read_text_file_lines","read_text_file_lines_next","seek","stat","lstat","fstat","exists"],"deny":[]}},"read-meta":{"identifier":"read-meta","description":"This enables all index or metadata related commands without any pre-configured accessible paths.","commands":{"allow":["read_dir","stat","lstat","fstat","exists","size"],"deny":[]}},"scope":{"identifier":"scope","description":"An empty permission you can use to modify the global scope.","commands":{"allow":[],"deny":[]}},"scope-app":{"identifier":"scope-app","description":"This scope permits access to all files and list content of top level directories in the application folders.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/*"},{"path":"$APPDATA"},{"path":"$APPDATA/*"},{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/*"},{"path":"$APPCACHE"},{"path":"$APPCACHE/*"},{"path":"$APPLOG"},{"path":"$APPLOG/*"}]}},"scope-app-index":{"identifier":"scope-app-index","description":"This scope permits to list all files and folders in the application directories.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPDATA"},{"path":"$APPLOCALDATA"},{"path":"$APPCACHE"},{"path":"$APPLOG"}]}},"scope-app-recursive":{"identifier":"scope-app-recursive","description":"This scope permits recursive access to the complete application folders, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/**"},{"path":"$APPDATA"},{"path":"$APPDATA/**"},{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/**"},{"path":"$APPCACHE"},{"path":"$APPCACHE/**"},{"path":"$APPLOG"},{"path":"$APPLOG/**"}]}},"scope-appcache":{"identifier":"scope-appcache","description":"This scope permits access to all files and list content of top level directories in the `$APPCACHE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCACHE"},{"path":"$APPCACHE/*"}]}},"scope-appcache-index":{"identifier":"scope-appcache-index","description":"This scope permits to list all files and folders in the `$APPCACHE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCACHE"}]}},"scope-appcache-recursive":{"identifier":"scope-appcache-recursive","description":"This scope permits recursive access to the complete `$APPCACHE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCACHE"},{"path":"$APPCACHE/**"}]}},"scope-appconfig":{"identifier":"scope-appconfig","description":"This scope permits access to all files and list content of top level directories in the `$APPCONFIG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/*"}]}},"scope-appconfig-index":{"identifier":"scope-appconfig-index","description":"This scope permits to list all files and folders in the `$APPCONFIG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"}]}},"scope-appconfig-recursive":{"identifier":"scope-appconfig-recursive","description":"This scope permits recursive access to the complete `$APPCONFIG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/**"}]}},"scope-appdata":{"identifier":"scope-appdata","description":"This scope permits access to all files and list content of top level directories in the `$APPDATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPDATA"},{"path":"$APPDATA/*"}]}},"scope-appdata-index":{"identifier":"scope-appdata-index","description":"This scope permits to list all files and folders in the `$APPDATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPDATA"}]}},"scope-appdata-recursive":{"identifier":"scope-appdata-recursive","description":"This scope permits recursive access to the complete `$APPDATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]}},"scope-applocaldata":{"identifier":"scope-applocaldata","description":"This scope permits access to all files and list content of top level directories in the `$APPLOCALDATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/*"}]}},"scope-applocaldata-index":{"identifier":"scope-applocaldata-index","description":"This scope permits to list all files and folders in the `$APPLOCALDATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOCALDATA"}]}},"scope-applocaldata-recursive":{"identifier":"scope-applocaldata-recursive","description":"This scope permits recursive access to the complete `$APPLOCALDATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/**"}]}},"scope-applog":{"identifier":"scope-applog","description":"This scope permits access to all files and list content of top level directories in the `$APPLOG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOG"},{"path":"$APPLOG/*"}]}},"scope-applog-index":{"identifier":"scope-applog-index","description":"This scope permits to list all files and folders in the `$APPLOG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOG"}]}},"scope-applog-recursive":{"identifier":"scope-applog-recursive","description":"This scope permits recursive access to the complete `$APPLOG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOG"},{"path":"$APPLOG/**"}]}},"scope-audio":{"identifier":"scope-audio","description":"This scope permits access to all files and list content of top level directories in the `$AUDIO` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$AUDIO"},{"path":"$AUDIO/*"}]}},"scope-audio-index":{"identifier":"scope-audio-index","description":"This scope permits to list all files and folders in the `$AUDIO`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$AUDIO"}]}},"scope-audio-recursive":{"identifier":"scope-audio-recursive","description":"This scope permits recursive access to the complete `$AUDIO` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$AUDIO"},{"path":"$AUDIO/**"}]}},"scope-cache":{"identifier":"scope-cache","description":"This scope permits access to all files and list content of top level directories in the `$CACHE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CACHE"},{"path":"$CACHE/*"}]}},"scope-cache-index":{"identifier":"scope-cache-index","description":"This scope permits to list all files and folders in the `$CACHE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CACHE"}]}},"scope-cache-recursive":{"identifier":"scope-cache-recursive","description":"This scope permits recursive access to the complete `$CACHE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CACHE"},{"path":"$CACHE/**"}]}},"scope-config":{"identifier":"scope-config","description":"This scope permits access to all files and list content of top level directories in the `$CONFIG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CONFIG"},{"path":"$CONFIG/*"}]}},"scope-config-index":{"identifier":"scope-config-index","description":"This scope permits to list all files and folders in the `$CONFIG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CONFIG"}]}},"scope-config-recursive":{"identifier":"scope-config-recursive","description":"This scope permits recursive access to the complete `$CONFIG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CONFIG"},{"path":"$CONFIG/**"}]}},"scope-data":{"identifier":"scope-data","description":"This scope permits access to all files and list content of top level directories in the `$DATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DATA"},{"path":"$DATA/*"}]}},"scope-data-index":{"identifier":"scope-data-index","description":"This scope permits to list all files and folders in the `$DATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DATA"}]}},"scope-data-recursive":{"identifier":"scope-data-recursive","description":"This scope permits recursive access to the complete `$DATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DATA"},{"path":"$DATA/**"}]}},"scope-desktop":{"identifier":"scope-desktop","description":"This scope permits access to all files and list content of top level directories in the `$DESKTOP` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DESKTOP"},{"path":"$DESKTOP/*"}]}},"scope-desktop-index":{"identifier":"scope-desktop-index","description":"This scope permits to list all files and folders in the `$DESKTOP`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DESKTOP"}]}},"scope-desktop-recursive":{"identifier":"scope-desktop-recursive","description":"This scope permits recursive access to the complete `$DESKTOP` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DESKTOP"},{"path":"$DESKTOP/**"}]}},"scope-document":{"identifier":"scope-document","description":"This scope permits access to all files and list content of top level directories in the `$DOCUMENT` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOCUMENT"},{"path":"$DOCUMENT/*"}]}},"scope-document-index":{"identifier":"scope-document-index","description":"This scope permits to list all files and folders in the `$DOCUMENT`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOCUMENT"}]}},"scope-document-recursive":{"identifier":"scope-document-recursive","description":"This scope permits recursive access to the complete `$DOCUMENT` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOCUMENT"},{"path":"$DOCUMENT/**"}]}},"scope-download":{"identifier":"scope-download","description":"This scope permits access to all files and list content of top level directories in the `$DOWNLOAD` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOWNLOAD"},{"path":"$DOWNLOAD/*"}]}},"scope-download-index":{"identifier":"scope-download-index","description":"This scope permits to list all files and folders in the `$DOWNLOAD`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOWNLOAD"}]}},"scope-download-recursive":{"identifier":"scope-download-recursive","description":"This scope permits recursive access to the complete `$DOWNLOAD` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOWNLOAD"},{"path":"$DOWNLOAD/**"}]}},"scope-exe":{"identifier":"scope-exe","description":"This scope permits access to all files and list content of top level directories in the `$EXE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$EXE"},{"path":"$EXE/*"}]}},"scope-exe-index":{"identifier":"scope-exe-index","description":"This scope permits to list all files and folders in the `$EXE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$EXE"}]}},"scope-exe-recursive":{"identifier":"scope-exe-recursive","description":"This scope permits recursive access to the complete `$EXE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$EXE"},{"path":"$EXE/**"}]}},"scope-font":{"identifier":"scope-font","description":"This scope permits access to all files and list content of top level directories in the `$FONT` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$FONT"},{"path":"$FONT/*"}]}},"scope-font-index":{"identifier":"scope-font-index","description":"This scope permits to list all files and folders in the `$FONT`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$FONT"}]}},"scope-font-recursive":{"identifier":"scope-font-recursive","description":"This scope permits recursive access to the complete `$FONT` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$FONT"},{"path":"$FONT/**"}]}},"scope-home":{"identifier":"scope-home","description":"This scope permits access to all files and list content of top level directories in the `$HOME` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$HOME"},{"path":"$HOME/*"}]}},"scope-home-index":{"identifier":"scope-home-index","description":"This scope permits to list all files and folders in the `$HOME`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$HOME"}]}},"scope-home-recursive":{"identifier":"scope-home-recursive","description":"This scope permits recursive access to the complete `$HOME` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$HOME"},{"path":"$HOME/**"}]}},"scope-localdata":{"identifier":"scope-localdata","description":"This scope permits access to all files and list content of top level directories in the `$LOCALDATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOCALDATA"},{"path":"$LOCALDATA/*"}]}},"scope-localdata-index":{"identifier":"scope-localdata-index","description":"This scope permits to list all files and folders in the `$LOCALDATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOCALDATA"}]}},"scope-localdata-recursive":{"identifier":"scope-localdata-recursive","description":"This scope permits recursive access to the complete `$LOCALDATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOCALDATA"},{"path":"$LOCALDATA/**"}]}},"scope-log":{"identifier":"scope-log","description":"This scope permits access to all files and list content of top level directories in the `$LOG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOG"},{"path":"$LOG/*"}]}},"scope-log-index":{"identifier":"scope-log-index","description":"This scope permits to list all files and folders in the `$LOG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOG"}]}},"scope-log-recursive":{"identifier":"scope-log-recursive","description":"This scope permits recursive access to the complete `$LOG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOG"},{"path":"$LOG/**"}]}},"scope-picture":{"identifier":"scope-picture","description":"This scope permits access to all files and list content of top level directories in the `$PICTURE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PICTURE"},{"path":"$PICTURE/*"}]}},"scope-picture-index":{"identifier":"scope-picture-index","description":"This scope permits to list all files and folders in the `$PICTURE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PICTURE"}]}},"scope-picture-recursive":{"identifier":"scope-picture-recursive","description":"This scope permits recursive access to the complete `$PICTURE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PICTURE"},{"path":"$PICTURE/**"}]}},"scope-public":{"identifier":"scope-public","description":"This scope permits access to all files and list content of top level directories in the `$PUBLIC` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PUBLIC"},{"path":"$PUBLIC/*"}]}},"scope-public-index":{"identifier":"scope-public-index","description":"This scope permits to list all files and folders in the `$PUBLIC`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PUBLIC"}]}},"scope-public-recursive":{"identifier":"scope-public-recursive","description":"This scope permits recursive access to the complete `$PUBLIC` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PUBLIC"},{"path":"$PUBLIC/**"}]}},"scope-resource":{"identifier":"scope-resource","description":"This scope permits access to all files and list content of top level directories in the `$RESOURCE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RESOURCE"},{"path":"$RESOURCE/*"}]}},"scope-resource-index":{"identifier":"scope-resource-index","description":"This scope permits to list all files and folders in the `$RESOURCE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RESOURCE"}]}},"scope-resource-recursive":{"identifier":"scope-resource-recursive","description":"This scope permits recursive access to the complete `$RESOURCE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RESOURCE"},{"path":"$RESOURCE/**"}]}},"scope-runtime":{"identifier":"scope-runtime","description":"This scope permits access to all files and list content of top level directories in the `$RUNTIME` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RUNTIME"},{"path":"$RUNTIME/*"}]}},"scope-runtime-index":{"identifier":"scope-runtime-index","description":"This scope permits to list all files and folders in the `$RUNTIME`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RUNTIME"}]}},"scope-runtime-recursive":{"identifier":"scope-runtime-recursive","description":"This scope permits recursive access to the complete `$RUNTIME` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RUNTIME"},{"path":"$RUNTIME/**"}]}},"scope-temp":{"identifier":"scope-temp","description":"This scope permits access to all files and list content of top level directories in the `$TEMP` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMP"},{"path":"$TEMP/*"}]}},"scope-temp-index":{"identifier":"scope-temp-index","description":"This scope permits to list all files and folders in the `$TEMP`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMP"}]}},"scope-temp-recursive":{"identifier":"scope-temp-recursive","description":"This scope permits recursive access to the complete `$TEMP` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMP"},{"path":"$TEMP/**"}]}},"scope-template":{"identifier":"scope-template","description":"This scope permits access to all files and list content of top level directories in the `$TEMPLATE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMPLATE"},{"path":"$TEMPLATE/*"}]}},"scope-template-index":{"identifier":"scope-template-index","description":"This scope permits to list all files and folders in the `$TEMPLATE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMPLATE"}]}},"scope-template-recursive":{"identifier":"scope-template-recursive","description":"This scope permits recursive access to the complete `$TEMPLATE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMPLATE"},{"path":"$TEMPLATE/**"}]}},"scope-video":{"identifier":"scope-video","description":"This scope permits access to all files and list content of top level directories in the `$VIDEO` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$VIDEO"},{"path":"$VIDEO/*"}]}},"scope-video-index":{"identifier":"scope-video-index","description":"This scope permits to list all files and folders in the `$VIDEO`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$VIDEO"}]}},"scope-video-recursive":{"identifier":"scope-video-recursive","description":"This scope permits recursive access to the complete `$VIDEO` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$VIDEO"},{"path":"$VIDEO/**"}]}},"write-all":{"identifier":"write-all","description":"This enables all write related commands without any pre-configured accessible paths.","commands":{"allow":["mkdir","create","copy_file","remove","rename","truncate","ftruncate","write","write_file","write_text_file"],"deny":[]}},"write-files":{"identifier":"write-files","description":"This enables all file write related commands without any pre-configured accessible paths.","commands":{"allow":["create","copy_file","remove","rename","truncate","ftruncate","write","write_file","write_text_file"],"deny":[]}}},"permission_sets":{"allow-app-meta":{"identifier":"allow-app-meta","description":"This allows non-recursive read access to metadata of the application folders, including file listing and statistics.","permissions":["read-meta","scope-app-index"]},"allow-app-meta-recursive":{"identifier":"allow-app-meta-recursive","description":"This allows full recursive read access to metadata of the application folders, including file listing and statistics.","permissions":["read-meta","scope-app-recursive"]},"allow-app-read":{"identifier":"allow-app-read","description":"This allows non-recursive read access to the application folders.","permissions":["read-all","scope-app"]},"allow-app-read-recursive":{"identifier":"allow-app-read-recursive","description":"This allows full recursive read access to the complete application folders, files and subdirectories.","permissions":["read-all","scope-app-recursive"]},"allow-app-write":{"identifier":"allow-app-write","description":"This allows non-recursive write access to the application folders.","permissions":["write-all","scope-app"]},"allow-app-write-recursive":{"identifier":"allow-app-write-recursive","description":"This allows full recursive write access to the complete application folders, files and subdirectories.","permissions":["write-all","scope-app-recursive"]},"allow-appcache-meta":{"identifier":"allow-appcache-meta","description":"This allows non-recursive read access to metadata of the `$APPCACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-appcache-index"]},"allow-appcache-meta-recursive":{"identifier":"allow-appcache-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPCACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-appcache-recursive"]},"allow-appcache-read":{"identifier":"allow-appcache-read","description":"This allows non-recursive read access to the `$APPCACHE` folder.","permissions":["read-all","scope-appcache"]},"allow-appcache-read-recursive":{"identifier":"allow-appcache-read-recursive","description":"This allows full recursive read access to the complete `$APPCACHE` folder, files and subdirectories.","permissions":["read-all","scope-appcache-recursive"]},"allow-appcache-write":{"identifier":"allow-appcache-write","description":"This allows non-recursive write access to the `$APPCACHE` folder.","permissions":["write-all","scope-appcache"]},"allow-appcache-write-recursive":{"identifier":"allow-appcache-write-recursive","description":"This allows full recursive write access to the complete `$APPCACHE` folder, files and subdirectories.","permissions":["write-all","scope-appcache-recursive"]},"allow-appconfig-meta":{"identifier":"allow-appconfig-meta","description":"This allows non-recursive read access to metadata of the `$APPCONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-appconfig-index"]},"allow-appconfig-meta-recursive":{"identifier":"allow-appconfig-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPCONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-appconfig-recursive"]},"allow-appconfig-read":{"identifier":"allow-appconfig-read","description":"This allows non-recursive read access to the `$APPCONFIG` folder.","permissions":["read-all","scope-appconfig"]},"allow-appconfig-read-recursive":{"identifier":"allow-appconfig-read-recursive","description":"This allows full recursive read access to the complete `$APPCONFIG` folder, files and subdirectories.","permissions":["read-all","scope-appconfig-recursive"]},"allow-appconfig-write":{"identifier":"allow-appconfig-write","description":"This allows non-recursive write access to the `$APPCONFIG` folder.","permissions":["write-all","scope-appconfig"]},"allow-appconfig-write-recursive":{"identifier":"allow-appconfig-write-recursive","description":"This allows full recursive write access to the complete `$APPCONFIG` folder, files and subdirectories.","permissions":["write-all","scope-appconfig-recursive"]},"allow-appdata-meta":{"identifier":"allow-appdata-meta","description":"This allows non-recursive read access to metadata of the `$APPDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-appdata-index"]},"allow-appdata-meta-recursive":{"identifier":"allow-appdata-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-appdata-recursive"]},"allow-appdata-read":{"identifier":"allow-appdata-read","description":"This allows non-recursive read access to the `$APPDATA` folder.","permissions":["read-all","scope-appdata"]},"allow-appdata-read-recursive":{"identifier":"allow-appdata-read-recursive","description":"This allows full recursive read access to the complete `$APPDATA` folder, files and subdirectories.","permissions":["read-all","scope-appdata-recursive"]},"allow-appdata-write":{"identifier":"allow-appdata-write","description":"This allows non-recursive write access to the `$APPDATA` folder.","permissions":["write-all","scope-appdata"]},"allow-appdata-write-recursive":{"identifier":"allow-appdata-write-recursive","description":"This allows full recursive write access to the complete `$APPDATA` folder, files and subdirectories.","permissions":["write-all","scope-appdata-recursive"]},"allow-applocaldata-meta":{"identifier":"allow-applocaldata-meta","description":"This allows non-recursive read access to metadata of the `$APPLOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-applocaldata-index"]},"allow-applocaldata-meta-recursive":{"identifier":"allow-applocaldata-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPLOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-applocaldata-recursive"]},"allow-applocaldata-read":{"identifier":"allow-applocaldata-read","description":"This allows non-recursive read access to the `$APPLOCALDATA` folder.","permissions":["read-all","scope-applocaldata"]},"allow-applocaldata-read-recursive":{"identifier":"allow-applocaldata-read-recursive","description":"This allows full recursive read access to the complete `$APPLOCALDATA` folder, files and subdirectories.","permissions":["read-all","scope-applocaldata-recursive"]},"allow-applocaldata-write":{"identifier":"allow-applocaldata-write","description":"This allows non-recursive write access to the `$APPLOCALDATA` folder.","permissions":["write-all","scope-applocaldata"]},"allow-applocaldata-write-recursive":{"identifier":"allow-applocaldata-write-recursive","description":"This allows full recursive write access to the complete `$APPLOCALDATA` folder, files and subdirectories.","permissions":["write-all","scope-applocaldata-recursive"]},"allow-applog-meta":{"identifier":"allow-applog-meta","description":"This allows non-recursive read access to metadata of the `$APPLOG` folder, including file listing and statistics.","permissions":["read-meta","scope-applog-index"]},"allow-applog-meta-recursive":{"identifier":"allow-applog-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPLOG` folder, including file listing and statistics.","permissions":["read-meta","scope-applog-recursive"]},"allow-applog-read":{"identifier":"allow-applog-read","description":"This allows non-recursive read access to the `$APPLOG` folder.","permissions":["read-all","scope-applog"]},"allow-applog-read-recursive":{"identifier":"allow-applog-read-recursive","description":"This allows full recursive read access to the complete `$APPLOG` folder, files and subdirectories.","permissions":["read-all","scope-applog-recursive"]},"allow-applog-write":{"identifier":"allow-applog-write","description":"This allows non-recursive write access to the `$APPLOG` folder.","permissions":["write-all","scope-applog"]},"allow-applog-write-recursive":{"identifier":"allow-applog-write-recursive","description":"This allows full recursive write access to the complete `$APPLOG` folder, files and subdirectories.","permissions":["write-all","scope-applog-recursive"]},"allow-audio-meta":{"identifier":"allow-audio-meta","description":"This allows non-recursive read access to metadata of the `$AUDIO` folder, including file listing and statistics.","permissions":["read-meta","scope-audio-index"]},"allow-audio-meta-recursive":{"identifier":"allow-audio-meta-recursive","description":"This allows full recursive read access to metadata of the `$AUDIO` folder, including file listing and statistics.","permissions":["read-meta","scope-audio-recursive"]},"allow-audio-read":{"identifier":"allow-audio-read","description":"This allows non-recursive read access to the `$AUDIO` folder.","permissions":["read-all","scope-audio"]},"allow-audio-read-recursive":{"identifier":"allow-audio-read-recursive","description":"This allows full recursive read access to the complete `$AUDIO` folder, files and subdirectories.","permissions":["read-all","scope-audio-recursive"]},"allow-audio-write":{"identifier":"allow-audio-write","description":"This allows non-recursive write access to the `$AUDIO` folder.","permissions":["write-all","scope-audio"]},"allow-audio-write-recursive":{"identifier":"allow-audio-write-recursive","description":"This allows full recursive write access to the complete `$AUDIO` folder, files and subdirectories.","permissions":["write-all","scope-audio-recursive"]},"allow-cache-meta":{"identifier":"allow-cache-meta","description":"This allows non-recursive read access to metadata of the `$CACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-cache-index"]},"allow-cache-meta-recursive":{"identifier":"allow-cache-meta-recursive","description":"This allows full recursive read access to metadata of the `$CACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-cache-recursive"]},"allow-cache-read":{"identifier":"allow-cache-read","description":"This allows non-recursive read access to the `$CACHE` folder.","permissions":["read-all","scope-cache"]},"allow-cache-read-recursive":{"identifier":"allow-cache-read-recursive","description":"This allows full recursive read access to the complete `$CACHE` folder, files and subdirectories.","permissions":["read-all","scope-cache-recursive"]},"allow-cache-write":{"identifier":"allow-cache-write","description":"This allows non-recursive write access to the `$CACHE` folder.","permissions":["write-all","scope-cache"]},"allow-cache-write-recursive":{"identifier":"allow-cache-write-recursive","description":"This allows full recursive write access to the complete `$CACHE` folder, files and subdirectories.","permissions":["write-all","scope-cache-recursive"]},"allow-config-meta":{"identifier":"allow-config-meta","description":"This allows non-recursive read access to metadata of the `$CONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-config-index"]},"allow-config-meta-recursive":{"identifier":"allow-config-meta-recursive","description":"This allows full recursive read access to metadata of the `$CONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-config-recursive"]},"allow-config-read":{"identifier":"allow-config-read","description":"This allows non-recursive read access to the `$CONFIG` folder.","permissions":["read-all","scope-config"]},"allow-config-read-recursive":{"identifier":"allow-config-read-recursive","description":"This allows full recursive read access to the complete `$CONFIG` folder, files and subdirectories.","permissions":["read-all","scope-config-recursive"]},"allow-config-write":{"identifier":"allow-config-write","description":"This allows non-recursive write access to the `$CONFIG` folder.","permissions":["write-all","scope-config"]},"allow-config-write-recursive":{"identifier":"allow-config-write-recursive","description":"This allows full recursive write access to the complete `$CONFIG` folder, files and subdirectories.","permissions":["write-all","scope-config-recursive"]},"allow-data-meta":{"identifier":"allow-data-meta","description":"This allows non-recursive read access to metadata of the `$DATA` folder, including file listing and statistics.","permissions":["read-meta","scope-data-index"]},"allow-data-meta-recursive":{"identifier":"allow-data-meta-recursive","description":"This allows full recursive read access to metadata of the `$DATA` folder, including file listing and statistics.","permissions":["read-meta","scope-data-recursive"]},"allow-data-read":{"identifier":"allow-data-read","description":"This allows non-recursive read access to the `$DATA` folder.","permissions":["read-all","scope-data"]},"allow-data-read-recursive":{"identifier":"allow-data-read-recursive","description":"This allows full recursive read access to the complete `$DATA` folder, files and subdirectories.","permissions":["read-all","scope-data-recursive"]},"allow-data-write":{"identifier":"allow-data-write","description":"This allows non-recursive write access to the `$DATA` folder.","permissions":["write-all","scope-data"]},"allow-data-write-recursive":{"identifier":"allow-data-write-recursive","description":"This allows full recursive write access to the complete `$DATA` folder, files and subdirectories.","permissions":["write-all","scope-data-recursive"]},"allow-desktop-meta":{"identifier":"allow-desktop-meta","description":"This allows non-recursive read access to metadata of the `$DESKTOP` folder, including file listing and statistics.","permissions":["read-meta","scope-desktop-index"]},"allow-desktop-meta-recursive":{"identifier":"allow-desktop-meta-recursive","description":"This allows full recursive read access to metadata of the `$DESKTOP` folder, including file listing and statistics.","permissions":["read-meta","scope-desktop-recursive"]},"allow-desktop-read":{"identifier":"allow-desktop-read","description":"This allows non-recursive read access to the `$DESKTOP` folder.","permissions":["read-all","scope-desktop"]},"allow-desktop-read-recursive":{"identifier":"allow-desktop-read-recursive","description":"This allows full recursive read access to the complete `$DESKTOP` folder, files and subdirectories.","permissions":["read-all","scope-desktop-recursive"]},"allow-desktop-write":{"identifier":"allow-desktop-write","description":"This allows non-recursive write access to the `$DESKTOP` folder.","permissions":["write-all","scope-desktop"]},"allow-desktop-write-recursive":{"identifier":"allow-desktop-write-recursive","description":"This allows full recursive write access to the complete `$DESKTOP` folder, files and subdirectories.","permissions":["write-all","scope-desktop-recursive"]},"allow-document-meta":{"identifier":"allow-document-meta","description":"This allows non-recursive read access to metadata of the `$DOCUMENT` folder, including file listing and statistics.","permissions":["read-meta","scope-document-index"]},"allow-document-meta-recursive":{"identifier":"allow-document-meta-recursive","description":"This allows full recursive read access to metadata of the `$DOCUMENT` folder, including file listing and statistics.","permissions":["read-meta","scope-document-recursive"]},"allow-document-read":{"identifier":"allow-document-read","description":"This allows non-recursive read access to the `$DOCUMENT` folder.","permissions":["read-all","scope-document"]},"allow-document-read-recursive":{"identifier":"allow-document-read-recursive","description":"This allows full recursive read access to the complete `$DOCUMENT` folder, files and subdirectories.","permissions":["read-all","scope-document-recursive"]},"allow-document-write":{"identifier":"allow-document-write","description":"This allows non-recursive write access to the `$DOCUMENT` folder.","permissions":["write-all","scope-document"]},"allow-document-write-recursive":{"identifier":"allow-document-write-recursive","description":"This allows full recursive write access to the complete `$DOCUMENT` folder, files and subdirectories.","permissions":["write-all","scope-document-recursive"]},"allow-download-meta":{"identifier":"allow-download-meta","description":"This allows non-recursive read access to metadata of the `$DOWNLOAD` folder, including file listing and statistics.","permissions":["read-meta","scope-download-index"]},"allow-download-meta-recursive":{"identifier":"allow-download-meta-recursive","description":"This allows full recursive read access to metadata of the `$DOWNLOAD` folder, including file listing and statistics.","permissions":["read-meta","scope-download-recursive"]},"allow-download-read":{"identifier":"allow-download-read","description":"This allows non-recursive read access to the `$DOWNLOAD` folder.","permissions":["read-all","scope-download"]},"allow-download-read-recursive":{"identifier":"allow-download-read-recursive","description":"This allows full recursive read access to the complete `$DOWNLOAD` folder, files and subdirectories.","permissions":["read-all","scope-download-recursive"]},"allow-download-write":{"identifier":"allow-download-write","description":"This allows non-recursive write access to the `$DOWNLOAD` folder.","permissions":["write-all","scope-download"]},"allow-download-write-recursive":{"identifier":"allow-download-write-recursive","description":"This allows full recursive write access to the complete `$DOWNLOAD` folder, files and subdirectories.","permissions":["write-all","scope-download-recursive"]},"allow-exe-meta":{"identifier":"allow-exe-meta","description":"This allows non-recursive read access to metadata of the `$EXE` folder, including file listing and statistics.","permissions":["read-meta","scope-exe-index"]},"allow-exe-meta-recursive":{"identifier":"allow-exe-meta-recursive","description":"This allows full recursive read access to metadata of the `$EXE` folder, including file listing and statistics.","permissions":["read-meta","scope-exe-recursive"]},"allow-exe-read":{"identifier":"allow-exe-read","description":"This allows non-recursive read access to the `$EXE` folder.","permissions":["read-all","scope-exe"]},"allow-exe-read-recursive":{"identifier":"allow-exe-read-recursive","description":"This allows full recursive read access to the complete `$EXE` folder, files and subdirectories.","permissions":["read-all","scope-exe-recursive"]},"allow-exe-write":{"identifier":"allow-exe-write","description":"This allows non-recursive write access to the `$EXE` folder.","permissions":["write-all","scope-exe"]},"allow-exe-write-recursive":{"identifier":"allow-exe-write-recursive","description":"This allows full recursive write access to the complete `$EXE` folder, files and subdirectories.","permissions":["write-all","scope-exe-recursive"]},"allow-font-meta":{"identifier":"allow-font-meta","description":"This allows non-recursive read access to metadata of the `$FONT` folder, including file listing and statistics.","permissions":["read-meta","scope-font-index"]},"allow-font-meta-recursive":{"identifier":"allow-font-meta-recursive","description":"This allows full recursive read access to metadata of the `$FONT` folder, including file listing and statistics.","permissions":["read-meta","scope-font-recursive"]},"allow-font-read":{"identifier":"allow-font-read","description":"This allows non-recursive read access to the `$FONT` folder.","permissions":["read-all","scope-font"]},"allow-font-read-recursive":{"identifier":"allow-font-read-recursive","description":"This allows full recursive read access to the complete `$FONT` folder, files and subdirectories.","permissions":["read-all","scope-font-recursive"]},"allow-font-write":{"identifier":"allow-font-write","description":"This allows non-recursive write access to the `$FONT` folder.","permissions":["write-all","scope-font"]},"allow-font-write-recursive":{"identifier":"allow-font-write-recursive","description":"This allows full recursive write access to the complete `$FONT` folder, files and subdirectories.","permissions":["write-all","scope-font-recursive"]},"allow-home-meta":{"identifier":"allow-home-meta","description":"This allows non-recursive read access to metadata of the `$HOME` folder, including file listing and statistics.","permissions":["read-meta","scope-home-index"]},"allow-home-meta-recursive":{"identifier":"allow-home-meta-recursive","description":"This allows full recursive read access to metadata of the `$HOME` folder, including file listing and statistics.","permissions":["read-meta","scope-home-recursive"]},"allow-home-read":{"identifier":"allow-home-read","description":"This allows non-recursive read access to the `$HOME` folder.","permissions":["read-all","scope-home"]},"allow-home-read-recursive":{"identifier":"allow-home-read-recursive","description":"This allows full recursive read access to the complete `$HOME` folder, files and subdirectories.","permissions":["read-all","scope-home-recursive"]},"allow-home-write":{"identifier":"allow-home-write","description":"This allows non-recursive write access to the `$HOME` folder.","permissions":["write-all","scope-home"]},"allow-home-write-recursive":{"identifier":"allow-home-write-recursive","description":"This allows full recursive write access to the complete `$HOME` folder, files and subdirectories.","permissions":["write-all","scope-home-recursive"]},"allow-localdata-meta":{"identifier":"allow-localdata-meta","description":"This allows non-recursive read access to metadata of the `$LOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-localdata-index"]},"allow-localdata-meta-recursive":{"identifier":"allow-localdata-meta-recursive","description":"This allows full recursive read access to metadata of the `$LOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-localdata-recursive"]},"allow-localdata-read":{"identifier":"allow-localdata-read","description":"This allows non-recursive read access to the `$LOCALDATA` folder.","permissions":["read-all","scope-localdata"]},"allow-localdata-read-recursive":{"identifier":"allow-localdata-read-recursive","description":"This allows full recursive read access to the complete `$LOCALDATA` folder, files and subdirectories.","permissions":["read-all","scope-localdata-recursive"]},"allow-localdata-write":{"identifier":"allow-localdata-write","description":"This allows non-recursive write access to the `$LOCALDATA` folder.","permissions":["write-all","scope-localdata"]},"allow-localdata-write-recursive":{"identifier":"allow-localdata-write-recursive","description":"This allows full recursive write access to the complete `$LOCALDATA` folder, files and subdirectories.","permissions":["write-all","scope-localdata-recursive"]},"allow-log-meta":{"identifier":"allow-log-meta","description":"This allows non-recursive read access to metadata of the `$LOG` folder, including file listing and statistics.","permissions":["read-meta","scope-log-index"]},"allow-log-meta-recursive":{"identifier":"allow-log-meta-recursive","description":"This allows full recursive read access to metadata of the `$LOG` folder, including file listing and statistics.","permissions":["read-meta","scope-log-recursive"]},"allow-log-read":{"identifier":"allow-log-read","description":"This allows non-recursive read access to the `$LOG` folder.","permissions":["read-all","scope-log"]},"allow-log-read-recursive":{"identifier":"allow-log-read-recursive","description":"This allows full recursive read access to the complete `$LOG` folder, files and subdirectories.","permissions":["read-all","scope-log-recursive"]},"allow-log-write":{"identifier":"allow-log-write","description":"This allows non-recursive write access to the `$LOG` folder.","permissions":["write-all","scope-log"]},"allow-log-write-recursive":{"identifier":"allow-log-write-recursive","description":"This allows full recursive write access to the complete `$LOG` folder, files and subdirectories.","permissions":["write-all","scope-log-recursive"]},"allow-picture-meta":{"identifier":"allow-picture-meta","description":"This allows non-recursive read access to metadata of the `$PICTURE` folder, including file listing and statistics.","permissions":["read-meta","scope-picture-index"]},"allow-picture-meta-recursive":{"identifier":"allow-picture-meta-recursive","description":"This allows full recursive read access to metadata of the `$PICTURE` folder, including file listing and statistics.","permissions":["read-meta","scope-picture-recursive"]},"allow-picture-read":{"identifier":"allow-picture-read","description":"This allows non-recursive read access to the `$PICTURE` folder.","permissions":["read-all","scope-picture"]},"allow-picture-read-recursive":{"identifier":"allow-picture-read-recursive","description":"This allows full recursive read access to the complete `$PICTURE` folder, files and subdirectories.","permissions":["read-all","scope-picture-recursive"]},"allow-picture-write":{"identifier":"allow-picture-write","description":"This allows non-recursive write access to the `$PICTURE` folder.","permissions":["write-all","scope-picture"]},"allow-picture-write-recursive":{"identifier":"allow-picture-write-recursive","description":"This allows full recursive write access to the complete `$PICTURE` folder, files and subdirectories.","permissions":["write-all","scope-picture-recursive"]},"allow-public-meta":{"identifier":"allow-public-meta","description":"This allows non-recursive read access to metadata of the `$PUBLIC` folder, including file listing and statistics.","permissions":["read-meta","scope-public-index"]},"allow-public-meta-recursive":{"identifier":"allow-public-meta-recursive","description":"This allows full recursive read access to metadata of the `$PUBLIC` folder, including file listing and statistics.","permissions":["read-meta","scope-public-recursive"]},"allow-public-read":{"identifier":"allow-public-read","description":"This allows non-recursive read access to the `$PUBLIC` folder.","permissions":["read-all","scope-public"]},"allow-public-read-recursive":{"identifier":"allow-public-read-recursive","description":"This allows full recursive read access to the complete `$PUBLIC` folder, files and subdirectories.","permissions":["read-all","scope-public-recursive"]},"allow-public-write":{"identifier":"allow-public-write","description":"This allows non-recursive write access to the `$PUBLIC` folder.","permissions":["write-all","scope-public"]},"allow-public-write-recursive":{"identifier":"allow-public-write-recursive","description":"This allows full recursive write access to the complete `$PUBLIC` folder, files and subdirectories.","permissions":["write-all","scope-public-recursive"]},"allow-resource-meta":{"identifier":"allow-resource-meta","description":"This allows non-recursive read access to metadata of the `$RESOURCE` folder, including file listing and statistics.","permissions":["read-meta","scope-resource-index"]},"allow-resource-meta-recursive":{"identifier":"allow-resource-meta-recursive","description":"This allows full recursive read access to metadata of the `$RESOURCE` folder, including file listing and statistics.","permissions":["read-meta","scope-resource-recursive"]},"allow-resource-read":{"identifier":"allow-resource-read","description":"This allows non-recursive read access to the `$RESOURCE` folder.","permissions":["read-all","scope-resource"]},"allow-resource-read-recursive":{"identifier":"allow-resource-read-recursive","description":"This allows full recursive read access to the complete `$RESOURCE` folder, files and subdirectories.","permissions":["read-all","scope-resource-recursive"]},"allow-resource-write":{"identifier":"allow-resource-write","description":"This allows non-recursive write access to the `$RESOURCE` folder.","permissions":["write-all","scope-resource"]},"allow-resource-write-recursive":{"identifier":"allow-resource-write-recursive","description":"This allows full recursive write access to the complete `$RESOURCE` folder, files and subdirectories.","permissions":["write-all","scope-resource-recursive"]},"allow-runtime-meta":{"identifier":"allow-runtime-meta","description":"This allows non-recursive read access to metadata of the `$RUNTIME` folder, including file listing and statistics.","permissions":["read-meta","scope-runtime-index"]},"allow-runtime-meta-recursive":{"identifier":"allow-runtime-meta-recursive","description":"This allows full recursive read access to metadata of the `$RUNTIME` folder, including file listing and statistics.","permissions":["read-meta","scope-runtime-recursive"]},"allow-runtime-read":{"identifier":"allow-runtime-read","description":"This allows non-recursive read access to the `$RUNTIME` folder.","permissions":["read-all","scope-runtime"]},"allow-runtime-read-recursive":{"identifier":"allow-runtime-read-recursive","description":"This allows full recursive read access to the complete `$RUNTIME` folder, files and subdirectories.","permissions":["read-all","scope-runtime-recursive"]},"allow-runtime-write":{"identifier":"allow-runtime-write","description":"This allows non-recursive write access to the `$RUNTIME` folder.","permissions":["write-all","scope-runtime"]},"allow-runtime-write-recursive":{"identifier":"allow-runtime-write-recursive","description":"This allows full recursive write access to the complete `$RUNTIME` folder, files and subdirectories.","permissions":["write-all","scope-runtime-recursive"]},"allow-temp-meta":{"identifier":"allow-temp-meta","description":"This allows non-recursive read access to metadata of the `$TEMP` folder, including file listing and statistics.","permissions":["read-meta","scope-temp-index"]},"allow-temp-meta-recursive":{"identifier":"allow-temp-meta-recursive","description":"This allows full recursive read access to metadata of the `$TEMP` folder, including file listing and statistics.","permissions":["read-meta","scope-temp-recursive"]},"allow-temp-read":{"identifier":"allow-temp-read","description":"This allows non-recursive read access to the `$TEMP` folder.","permissions":["read-all","scope-temp"]},"allow-temp-read-recursive":{"identifier":"allow-temp-read-recursive","description":"This allows full recursive read access to the complete `$TEMP` folder, files and subdirectories.","permissions":["read-all","scope-temp-recursive"]},"allow-temp-write":{"identifier":"allow-temp-write","description":"This allows non-recursive write access to the `$TEMP` folder.","permissions":["write-all","scope-temp"]},"allow-temp-write-recursive":{"identifier":"allow-temp-write-recursive","description":"This allows full recursive write access to the complete `$TEMP` folder, files and subdirectories.","permissions":["write-all","scope-temp-recursive"]},"allow-template-meta":{"identifier":"allow-template-meta","description":"This allows non-recursive read access to metadata of the `$TEMPLATE` folder, including file listing and statistics.","permissions":["read-meta","scope-template-index"]},"allow-template-meta-recursive":{"identifier":"allow-template-meta-recursive","description":"This allows full recursive read access to metadata of the `$TEMPLATE` folder, including file listing and statistics.","permissions":["read-meta","scope-template-recursive"]},"allow-template-read":{"identifier":"allow-template-read","description":"This allows non-recursive read access to the `$TEMPLATE` folder.","permissions":["read-all","scope-template"]},"allow-template-read-recursive":{"identifier":"allow-template-read-recursive","description":"This allows full recursive read access to the complete `$TEMPLATE` folder, files and subdirectories.","permissions":["read-all","scope-template-recursive"]},"allow-template-write":{"identifier":"allow-template-write","description":"This allows non-recursive write access to the `$TEMPLATE` folder.","permissions":["write-all","scope-template"]},"allow-template-write-recursive":{"identifier":"allow-template-write-recursive","description":"This allows full recursive write access to the complete `$TEMPLATE` folder, files and subdirectories.","permissions":["write-all","scope-template-recursive"]},"allow-video-meta":{"identifier":"allow-video-meta","description":"This allows non-recursive read access to metadata of the `$VIDEO` folder, including file listing and statistics.","permissions":["read-meta","scope-video-index"]},"allow-video-meta-recursive":{"identifier":"allow-video-meta-recursive","description":"This allows full recursive read access to metadata of the `$VIDEO` folder, including file listing and statistics.","permissions":["read-meta","scope-video-recursive"]},"allow-video-read":{"identifier":"allow-video-read","description":"This allows non-recursive read access to the `$VIDEO` folder.","permissions":["read-all","scope-video"]},"allow-video-read-recursive":{"identifier":"allow-video-read-recursive","description":"This allows full recursive read access to the complete `$VIDEO` folder, files and subdirectories.","permissions":["read-all","scope-video-recursive"]},"allow-video-write":{"identifier":"allow-video-write","description":"This allows non-recursive write access to the `$VIDEO` folder.","permissions":["write-all","scope-video"]},"allow-video-write-recursive":{"identifier":"allow-video-write-recursive","description":"This allows full recursive write access to the complete `$VIDEO` folder, files and subdirectories.","permissions":["write-all","scope-video-recursive"]},"deny-default":{"identifier":"deny-default","description":"This denies access to dangerous Tauri relevant files and folders by default.","permissions":["deny-webview-data-linux","deny-webview-data-windows"]}},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"description":"A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},{"properties":{"path":{"description":"A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"}},"required":["path"],"type":"object"}],"description":"FS scope entry.","title":"FsScopeEntry"}},"log":{"default_permission":{"identifier":"default","description":"Allows the log command","permissions":["allow-log"]},"permissions":{"allow-log":{"identifier":"allow-log","description":"Enables the log command without any pre-configured scope.","commands":{"allow":["log"],"deny":[]}},"deny-log":{"identifier":"deny-log","description":"Denies the log command without any pre-configured scope.","commands":{"allow":[],"deny":["log"]}}},"permission_sets":{},"global_scope_schema":null},"opener":{"default_permission":{"identifier":"default","description":"This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer","permissions":["allow-open-url","allow-reveal-item-in-dir","allow-default-urls"]},"permissions":{"allow-default-urls":{"identifier":"allow-default-urls","description":"This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"url":"mailto:*"},{"url":"tel:*"},{"url":"http://*"},{"url":"https://*"}]}},"allow-open-path":{"identifier":"allow-open-path","description":"Enables the open_path command without any pre-configured scope.","commands":{"allow":["open_path"],"deny":[]}},"allow-open-url":{"identifier":"allow-open-url","description":"Enables the open_url command without any pre-configured scope.","commands":{"allow":["open_url"],"deny":[]}},"allow-reveal-item-in-dir":{"identifier":"allow-reveal-item-in-dir","description":"Enables the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":["reveal_item_in_dir"],"deny":[]}},"deny-open-path":{"identifier":"deny-open-path","description":"Denies the open_path command without any pre-configured scope.","commands":{"allow":[],"deny":["open_path"]}},"deny-open-url":{"identifier":"deny-open-url","description":"Denies the open_url command without any pre-configured scope.","commands":{"allow":[],"deny":["open_url"]}},"deny-reveal-item-in-dir":{"identifier":"deny-reveal-item-in-dir","description":"Denies the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_item_in_dir"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this url with, for example: firefox."},"url":{"description":"A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"","type":"string"}},"required":["url"],"type":"object"},{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this path with, for example: xdg-open."},"path":{"description":"A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"}},"required":["path"],"type":"object"}],"definitions":{"Application":{"anyOf":[{"description":"Open in default application.","type":"null"},{"description":"If true, allow open with any application.","type":"boolean"},{"description":"Allow specific application to open with.","type":"string"}],"description":"Opener scope application."}},"description":"Opener scope entry.","title":"OpenerScopeEntry"}},"os":{"default_permission":{"identifier":"default","description":"This permission set configures which\noperating system information are available\nto gather from the frontend.\n\n#### Granted Permissions\n\nAll information except the host name are available.\n\n","permissions":["allow-arch","allow-exe-extension","allow-family","allow-locale","allow-os-type","allow-platform","allow-version"]},"permissions":{"allow-arch":{"identifier":"allow-arch","description":"Enables the arch command without any pre-configured scope.","commands":{"allow":["arch"],"deny":[]}},"allow-exe-extension":{"identifier":"allow-exe-extension","description":"Enables the exe_extension command without any pre-configured scope.","commands":{"allow":["exe_extension"],"deny":[]}},"allow-family":{"identifier":"allow-family","description":"Enables the family command without any pre-configured scope.","commands":{"allow":["family"],"deny":[]}},"allow-hostname":{"identifier":"allow-hostname","description":"Enables the hostname command without any pre-configured scope.","commands":{"allow":["hostname"],"deny":[]}},"allow-locale":{"identifier":"allow-locale","description":"Enables the locale command without any pre-configured scope.","commands":{"allow":["locale"],"deny":[]}},"allow-os-type":{"identifier":"allow-os-type","description":"Enables the os_type command without any pre-configured scope.","commands":{"allow":["os_type"],"deny":[]}},"allow-platform":{"identifier":"allow-platform","description":"Enables the platform command without any pre-configured scope.","commands":{"allow":["platform"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-arch":{"identifier":"deny-arch","description":"Denies the arch command without any pre-configured scope.","commands":{"allow":[],"deny":["arch"]}},"deny-exe-extension":{"identifier":"deny-exe-extension","description":"Denies the exe_extension command without any pre-configured scope.","commands":{"allow":[],"deny":["exe_extension"]}},"deny-family":{"identifier":"deny-family","description":"Denies the family command without any pre-configured scope.","commands":{"allow":[],"deny":["family"]}},"deny-hostname":{"identifier":"deny-hostname","description":"Denies the hostname command without any pre-configured scope.","commands":{"allow":[],"deny":["hostname"]}},"deny-locale":{"identifier":"deny-locale","description":"Denies the locale command without any pre-configured scope.","commands":{"allow":[],"deny":["locale"]}},"deny-os-type":{"identifier":"deny-os-type","description":"Denies the os_type command without any pre-configured scope.","commands":{"allow":[],"deny":["os_type"]}},"deny-platform":{"identifier":"deny-platform","description":"Denies the platform command without any pre-configured scope.","commands":{"allow":[],"deny":["platform"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"shell":{"default_permission":{"identifier":"default","description":"This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality without any specific\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n","permissions":["allow-open"]},"permissions":{"allow-execute":{"identifier":"allow-execute","description":"Enables the execute command without any pre-configured scope.","commands":{"allow":["execute"],"deny":[]}},"allow-kill":{"identifier":"allow-kill","description":"Enables the kill command without any pre-configured scope.","commands":{"allow":["kill"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-spawn":{"identifier":"allow-spawn","description":"Enables the spawn command without any pre-configured scope.","commands":{"allow":["spawn"],"deny":[]}},"allow-stdin-write":{"identifier":"allow-stdin-write","description":"Enables the stdin_write command without any pre-configured scope.","commands":{"allow":["stdin_write"],"deny":[]}},"deny-execute":{"identifier":"deny-execute","description":"Denies the execute command without any pre-configured scope.","commands":{"allow":[],"deny":["execute"]}},"deny-kill":{"identifier":"deny-kill","description":"Denies the kill command without any pre-configured scope.","commands":{"allow":[],"deny":["kill"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-spawn":{"identifier":"deny-spawn","description":"Denies the spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["spawn"]}},"deny-stdin-write":{"identifier":"deny-stdin-write","description":"Denies the stdin_write command without any pre-configured scope.","commands":{"allow":[],"deny":["stdin_write"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"cmd":{"description":"The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"}},"required":["cmd","name"],"type":"object"},{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"},"sidecar":{"description":"If this command is a sidecar command.","type":"boolean"}},"required":["name","sidecar"],"type":"object"}],"definitions":{"ShellScopeEntryAllowedArg":{"anyOf":[{"description":"A non-configurable argument that is passed to the command in the order it was specified.","type":"string"},{"additionalProperties":false,"description":"A variable that is set while calling the command from the webview API.","properties":{"raw":{"default":false,"description":"Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.","type":"boolean"},"validator":{"description":"[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: ","type":"string"}},"required":["validator"],"type":"object"}],"description":"A command argument allowed to be executed by the webview API."},"ShellScopeEntryAllowedArgs":{"anyOf":[{"description":"Use a simple boolean to allow all or disable all arguments to this command configuration.","type":"boolean"},{"description":"A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.","items":{"$ref":"#/definitions/ShellScopeEntryAllowedArg"},"type":"array"}],"description":"A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration."}},"description":"Shell scope entry.","title":"ShellScopeEntry"}},"updater":{"default_permission":{"identifier":"default","description":"This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n","permissions":["allow-check","allow-download","allow-install","allow-download-and-install"]},"permissions":{"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-download":{"identifier":"allow-download","description":"Enables the download command without any pre-configured scope.","commands":{"allow":["download"],"deny":[]}},"allow-download-and-install":{"identifier":"allow-download-and-install","description":"Enables the download_and_install command without any pre-configured scope.","commands":{"allow":["download_and_install"],"deny":[]}},"allow-install":{"identifier":"allow-install","description":"Enables the install command without any pre-configured scope.","commands":{"allow":["install"],"deny":[]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-download":{"identifier":"deny-download","description":"Denies the download command without any pre-configured scope.","commands":{"allow":[],"deny":["download"]}},"deny-download-and-install":{"identifier":"deny-download-and-install","description":"Denies the download_and_install command without any pre-configured scope.","commands":{"allow":[],"deny":["download_and_install"]}},"deny-install":{"identifier":"deny-install","description":"Denies the install command without any pre-configured scope.","commands":{"allow":[],"deny":["install"]}}},"permission_sets":{},"global_scope_schema":null},"window-state":{"default_permission":{"identifier":"default","description":"This permission set configures what kind of\noperations are available from the window state plugin.\n\n#### Granted Permissions\n\nAll operations are enabled by default.\n\n","permissions":["allow-filename","allow-restore-state","allow-save-window-state"]},"permissions":{"allow-filename":{"identifier":"allow-filename","description":"Enables the filename command without any pre-configured scope.","commands":{"allow":["filename"],"deny":[]}},"allow-restore-state":{"identifier":"allow-restore-state","description":"Enables the restore_state command without any pre-configured scope.","commands":{"allow":["restore_state"],"deny":[]}},"allow-save-window-state":{"identifier":"allow-save-window-state","description":"Enables the save_window_state command without any pre-configured scope.","commands":{"allow":["save_window_state"],"deny":[]}},"deny-filename":{"identifier":"deny-filename","description":"Denies the filename command without any pre-configured scope.","commands":{"allow":[],"deny":["filename"]}},"deny-restore-state":{"identifier":"deny-restore-state","description":"Denies the restore_state command without any pre-configured scope.","commands":{"allow":[],"deny":["restore_state"]}},"deny-save-window-state":{"identifier":"deny-save-window-state","description":"Denies the save_window_state command without any pre-configured scope.","commands":{"allow":[],"deny":["save_window_state"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-git":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-add","allow-branch","allow-checkout","allow-commit","allow-delete-branch","allow-initialize","allow-log","allow-merge-branch","allow-pull","allow-push","allow-status","allow-unstage"]},"permissions":{"allow-add":{"identifier":"allow-add","description":"Enables the add command without any pre-configured scope.","commands":{"allow":["add"],"deny":[]}},"allow-branch":{"identifier":"allow-branch","description":"Enables the branch command without any pre-configured scope.","commands":{"allow":["branch"],"deny":[]}},"allow-checkout":{"identifier":"allow-checkout","description":"Enables the checkout command without any pre-configured scope.","commands":{"allow":["checkout"],"deny":[]}},"allow-commit":{"identifier":"allow-commit","description":"Enables the commit command without any pre-configured scope.","commands":{"allow":["commit"],"deny":[]}},"allow-delete-branch":{"identifier":"allow-delete-branch","description":"Enables the delete_branch command without any pre-configured scope.","commands":{"allow":["delete_branch"],"deny":[]}},"allow-initialize":{"identifier":"allow-initialize","description":"Enables the initialize command without any pre-configured scope.","commands":{"allow":["initialize"],"deny":[]}},"allow-log":{"identifier":"allow-log","description":"Enables the log command without any pre-configured scope.","commands":{"allow":["log"],"deny":[]}},"allow-merge-branch":{"identifier":"allow-merge-branch","description":"Enables the merge_branch command without any pre-configured scope.","commands":{"allow":["merge_branch"],"deny":[]}},"allow-pull":{"identifier":"allow-pull","description":"Enables the pull command without any pre-configured scope.","commands":{"allow":["pull"],"deny":[]}},"allow-push":{"identifier":"allow-push","description":"Enables the push command without any pre-configured scope.","commands":{"allow":["push"],"deny":[]}},"allow-status":{"identifier":"allow-status","description":"Enables the status command without any pre-configured scope.","commands":{"allow":["status"],"deny":[]}},"allow-unstage":{"identifier":"allow-unstage","description":"Enables the unstage command without any pre-configured scope.","commands":{"allow":["unstage"],"deny":[]}},"deny-add":{"identifier":"deny-add","description":"Denies the add command without any pre-configured scope.","commands":{"allow":[],"deny":["add"]}},"deny-branch":{"identifier":"deny-branch","description":"Denies the branch command without any pre-configured scope.","commands":{"allow":[],"deny":["branch"]}},"deny-checkout":{"identifier":"deny-checkout","description":"Denies the checkout command without any pre-configured scope.","commands":{"allow":[],"deny":["checkout"]}},"deny-commit":{"identifier":"deny-commit","description":"Denies the commit command without any pre-configured scope.","commands":{"allow":[],"deny":["commit"]}},"deny-delete-branch":{"identifier":"deny-delete-branch","description":"Denies the delete_branch command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_branch"]}},"deny-initialize":{"identifier":"deny-initialize","description":"Denies the initialize command without any pre-configured scope.","commands":{"allow":[],"deny":["initialize"]}},"deny-log":{"identifier":"deny-log","description":"Denies the log command without any pre-configured scope.","commands":{"allow":[],"deny":["log"]}},"deny-merge-branch":{"identifier":"deny-merge-branch","description":"Denies the merge_branch command without any pre-configured scope.","commands":{"allow":[],"deny":["merge_branch"]}},"deny-pull":{"identifier":"deny-pull","description":"Denies the pull command without any pre-configured scope.","commands":{"allow":[],"deny":["pull"]}},"deny-push":{"identifier":"deny-push","description":"Denies the push command without any pre-configured scope.","commands":{"allow":[],"deny":["push"]}},"deny-status":{"identifier":"deny-status","description":"Denies the status command without any pre-configured scope.","commands":{"allow":[],"deny":["status"]}},"deny-unstage":{"identifier":"deny-unstage","description":"Denies the unstage command without any pre-configured scope.","commands":{"allow":[],"deny":["unstage"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-license":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-check","allow-activate"]},"permissions":{"allow-activate":{"identifier":"allow-activate","description":"Enables the activate command without any pre-configured scope.","commands":{"allow":["activate"],"deny":[]}},"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"deny-activate":{"identifier":"deny-activate","description":"Denies the activate command without any pre-configured scope.","commands":{"allow":[],"deny":["activate"]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-sync":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-calculate","allow-calculate-fs","allow-apply","allow-watch"]},"permissions":{"allow-apply":{"identifier":"allow-apply","description":"Enables the apply command without any pre-configured scope.","commands":{"allow":["apply"],"deny":[]}},"allow-calculate":{"identifier":"allow-calculate","description":"Enables the calculate command without any pre-configured scope.","commands":{"allow":["calculate"],"deny":[]}},"allow-calculate-fs":{"identifier":"allow-calculate-fs","description":"Enables the calculate_fs command without any pre-configured scope.","commands":{"allow":["calculate_fs"],"deny":[]}},"allow-watch":{"identifier":"allow-watch","description":"Enables the watch command without any pre-configured scope.","commands":{"allow":["watch"],"deny":[]}},"deny-apply":{"identifier":"deny-apply","description":"Denies the apply command without any pre-configured scope.","commands":{"allow":[],"deny":["apply"]}},"deny-calculate":{"identifier":"deny-calculate","description":"Denies the calculate command without any pre-configured scope.","commands":{"allow":[],"deny":["calculate"]}},"deny-calculate-fs":{"identifier":"deny-calculate-fs","description":"Denies the calculate_fs command without any pre-configured scope.","commands":{"allow":[],"deny":["calculate_fs"]}},"deny-watch":{"identifier":"deny-watch","description":"Denies the watch command without any pre-configured scope.","commands":{"allow":[],"deny":["watch"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-ws":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-close","allow-connect","allow-delete-connection","allow-delete-connections","allow-delete-request","allow-duplicate-request","allow-list-connections","allow-list-events","allow-list-requests","allow-send","allow-upsert-request"]},"permissions":{"allow-cancel":{"identifier":"allow-cancel","description":"Enables the cancel command without any pre-configured scope.","commands":{"allow":["cancel"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-connect":{"identifier":"allow-connect","description":"Enables the connect command without any pre-configured scope.","commands":{"allow":["connect"],"deny":[]}},"allow-delete-connection":{"identifier":"allow-delete-connection","description":"Enables the delete_connection command without any pre-configured scope.","commands":{"allow":["delete_connection"],"deny":[]}},"allow-delete-connections":{"identifier":"allow-delete-connections","description":"Enables the delete_connections command without any pre-configured scope.","commands":{"allow":["delete_connections"],"deny":[]}},"allow-delete-request":{"identifier":"allow-delete-request","description":"Enables the delete_request command without any pre-configured scope.","commands":{"allow":["delete_request"],"deny":[]}},"allow-duplicate-request":{"identifier":"allow-duplicate-request","description":"Enables the duplicate_request command without any pre-configured scope.","commands":{"allow":["duplicate_request"],"deny":[]}},"allow-list-connections":{"identifier":"allow-list-connections","description":"Enables the list_connections command without any pre-configured scope.","commands":{"allow":["list_connections"],"deny":[]}},"allow-list-events":{"identifier":"allow-list-events","description":"Enables the list_events command without any pre-configured scope.","commands":{"allow":["list_events"],"deny":[]}},"allow-list-requests":{"identifier":"allow-list-requests","description":"Enables the list_requests command without any pre-configured scope.","commands":{"allow":["list_requests"],"deny":[]}},"allow-list-websocket-connections":{"identifier":"allow-list-websocket-connections","description":"Enables the list_websocket_connections command without any pre-configured scope.","commands":{"allow":["list_websocket_connections"],"deny":[]}},"allow-list-websocket-requests":{"identifier":"allow-list-websocket-requests","description":"Enables the list_websocket_requests command without any pre-configured scope.","commands":{"allow":["list_websocket_requests"],"deny":[]}},"allow-send":{"identifier":"allow-send","description":"Enables the send command without any pre-configured scope.","commands":{"allow":["send"],"deny":[]}},"allow-upsert-request":{"identifier":"allow-upsert-request","description":"Enables the upsert_request command without any pre-configured scope.","commands":{"allow":["upsert_request"],"deny":[]}},"allow-upsert-websocket-request":{"identifier":"allow-upsert-websocket-request","description":"Enables the upsert_websocket_request command without any pre-configured scope.","commands":{"allow":["upsert_websocket_request"],"deny":[]}},"deny-cancel":{"identifier":"deny-cancel","description":"Denies the cancel command without any pre-configured scope.","commands":{"allow":[],"deny":["cancel"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-connect":{"identifier":"deny-connect","description":"Denies the connect command without any pre-configured scope.","commands":{"allow":[],"deny":["connect"]}},"deny-delete-connection":{"identifier":"deny-delete-connection","description":"Denies the delete_connection command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_connection"]}},"deny-delete-connections":{"identifier":"deny-delete-connections","description":"Denies the delete_connections command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_connections"]}},"deny-delete-request":{"identifier":"deny-delete-request","description":"Denies the delete_request command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_request"]}},"deny-duplicate-request":{"identifier":"deny-duplicate-request","description":"Denies the duplicate_request command without any pre-configured scope.","commands":{"allow":[],"deny":["duplicate_request"]}},"deny-list-connections":{"identifier":"deny-list-connections","description":"Denies the list_connections command without any pre-configured scope.","commands":{"allow":[],"deny":["list_connections"]}},"deny-list-events":{"identifier":"deny-list-events","description":"Denies the list_events command without any pre-configured scope.","commands":{"allow":[],"deny":["list_events"]}},"deny-list-requests":{"identifier":"deny-list-requests","description":"Denies the list_requests command without any pre-configured scope.","commands":{"allow":[],"deny":["list_requests"]}},"deny-list-websocket-connections":{"identifier":"deny-list-websocket-connections","description":"Denies the list_websocket_connections command without any pre-configured scope.","commands":{"allow":[],"deny":["list_websocket_connections"]}},"deny-list-websocket-requests":{"identifier":"deny-list-websocket-requests","description":"Denies the list_websocket_requests command without any pre-configured scope.","commands":{"allow":[],"deny":["list_websocket_requests"]}},"deny-send":{"identifier":"deny-send","description":"Denies the send command without any pre-configured scope.","commands":{"allow":[],"deny":["send"]}},"deny-upsert-request":{"identifier":"deny-upsert-request","description":"Denies the upsert_request command without any pre-configured scope.","commands":{"allow":[],"deny":["upsert_request"]}},"deny-upsert-websocket-request":{"identifier":"deny-upsert-websocket-request","description":"Denies the upsert_websocket_request command without any pre-configured scope.","commands":{"allow":[],"deny":["upsert_websocket_request"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file diff --git a/src-tauri/gen/schemas/capabilities.json b/src-tauri/gen/schemas/capabilities.json index 914c7a03..ee1e28ba 100644 --- a/src-tauri/gen/schemas/capabilities.json +++ b/src-tauri/gen/schemas/capabilities.json @@ -1 +1 @@ -{"main":{"identifier":"main","description":"Main permissions","local":true,"windows":["*"],"permissions":["core:event:allow-emit","core:event:allow-listen","core:event:allow-unlisten","os:allow-os-type","clipboard-manager:allow-clear","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","dialog:allow-open","dialog:allow-save","fs:allow-read-dir","fs:allow-read-file","fs:allow-read-text-file",{"identifier":"fs:scope","allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]},"clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:webview:allow-set-webview-zoom","core:window:allow-close","core:window:allow-internal-toggle-maximize","core:window:allow-is-fullscreen","core:window:allow-is-maximized","core:window:allow-maximize","core:window:allow-minimize","core:window:allow-set-decorations","core:window:allow-set-title","core:window:allow-show","core:window:allow-start-dragging","core:window:allow-theme","core:window:allow-unmaximize","opener:allow-default-urls","opener:allow-open-path","opener:allow-open-url","opener:allow-reveal-item-in-dir","shell:allow-open","yaak-license:default","yaak-sync:default","yaak-ws:default"]}} \ No newline at end of file +{"main":{"identifier":"main","description":"Main permissions","local":true,"windows":["*"],"permissions":["core:event:allow-emit","core:event:allow-listen","core:event:allow-unlisten","os:allow-os-type","clipboard-manager:allow-clear","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","dialog:allow-open","dialog:allow-save","fs:allow-read-dir","fs:allow-read-file","fs:allow-read-text-file",{"identifier":"fs:scope","allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]},"clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:webview:allow-set-webview-zoom","core:window:allow-close","core:window:allow-internal-toggle-maximize","core:window:allow-is-fullscreen","core:window:allow-is-maximized","core:window:allow-maximize","core:window:allow-minimize","core:window:allow-set-decorations","core:window:allow-set-title","core:window:allow-show","core:window:allow-start-dragging","core:window:allow-theme","core:window:allow-unmaximize","opener:allow-default-urls","opener:allow-open-path","opener:allow-open-url","opener:allow-reveal-item-in-dir","shell:allow-open","yaak-license:default","yaak-git:default","yaak-sync:default","yaak-ws:default"]}} \ No newline at end of file diff --git a/src-tauri/gen/schemas/desktop-schema.json b/src-tauri/gen/schemas/desktop-schema.json index b98fb185..b9b32d8c 100644 --- a/src-tauri/gen/schemas/desktop-schema.json +++ b/src-tauri/gen/schemas/desktop-schema.json @@ -5412,6 +5412,131 @@ "type": "string", "const": "window-state:deny-save-window-state" }, + { + "description": "Default permissions for the plugin", + "type": "string", + "const": "yaak-git:default" + }, + { + "description": "Enables the add command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-add" + }, + { + "description": "Enables the branch command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-branch" + }, + { + "description": "Enables the checkout command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-checkout" + }, + { + "description": "Enables the commit command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-commit" + }, + { + "description": "Enables the delete_branch command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-delete-branch" + }, + { + "description": "Enables the initialize command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-initialize" + }, + { + "description": "Enables the log command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-log" + }, + { + "description": "Enables the merge_branch command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-merge-branch" + }, + { + "description": "Enables the pull command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-pull" + }, + { + "description": "Enables the push command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-push" + }, + { + "description": "Enables the status command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-status" + }, + { + "description": "Enables the unstage command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-unstage" + }, + { + "description": "Denies the add command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-add" + }, + { + "description": "Denies the branch command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-branch" + }, + { + "description": "Denies the checkout command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-checkout" + }, + { + "description": "Denies the commit command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-commit" + }, + { + "description": "Denies the delete_branch command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-delete-branch" + }, + { + "description": "Denies the initialize command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-initialize" + }, + { + "description": "Denies the log command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-log" + }, + { + "description": "Denies the merge_branch command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-merge-branch" + }, + { + "description": "Denies the pull command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-pull" + }, + { + "description": "Denies the push command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-push" + }, + { + "description": "Denies the status command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-status" + }, + { + "description": "Denies the unstage command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-unstage" + }, { "description": "Default permissions for the plugin", "type": "string", diff --git a/src-tauri/gen/schemas/macOS-schema.json b/src-tauri/gen/schemas/macOS-schema.json index b98fb185..b9b32d8c 100644 --- a/src-tauri/gen/schemas/macOS-schema.json +++ b/src-tauri/gen/schemas/macOS-schema.json @@ -5412,6 +5412,131 @@ "type": "string", "const": "window-state:deny-save-window-state" }, + { + "description": "Default permissions for the plugin", + "type": "string", + "const": "yaak-git:default" + }, + { + "description": "Enables the add command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-add" + }, + { + "description": "Enables the branch command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-branch" + }, + { + "description": "Enables the checkout command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-checkout" + }, + { + "description": "Enables the commit command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-commit" + }, + { + "description": "Enables the delete_branch command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-delete-branch" + }, + { + "description": "Enables the initialize command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-initialize" + }, + { + "description": "Enables the log command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-log" + }, + { + "description": "Enables the merge_branch command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-merge-branch" + }, + { + "description": "Enables the pull command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-pull" + }, + { + "description": "Enables the push command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-push" + }, + { + "description": "Enables the status command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-status" + }, + { + "description": "Enables the unstage command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:allow-unstage" + }, + { + "description": "Denies the add command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-add" + }, + { + "description": "Denies the branch command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-branch" + }, + { + "description": "Denies the checkout command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-checkout" + }, + { + "description": "Denies the commit command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-commit" + }, + { + "description": "Denies the delete_branch command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-delete-branch" + }, + { + "description": "Denies the initialize command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-initialize" + }, + { + "description": "Denies the log command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-log" + }, + { + "description": "Denies the merge_branch command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-merge-branch" + }, + { + "description": "Denies the pull command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-pull" + }, + { + "description": "Denies the push command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-push" + }, + { + "description": "Denies the status command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-status" + }, + { + "description": "Denies the unstage command without any pre-configured scope.", + "type": "string", + "const": "yaak-git:deny-unstage" + }, { "description": "Default permissions for the plugin", "type": "string", diff --git a/src-tauri/migrations/20250114160022_remove-workspace-sync-setting.sql b/src-tauri/migrations/20250114160022_remove-workspace-sync-setting.sql new file mode 100644 index 00000000..1d8f8497 --- /dev/null +++ b/src-tauri/migrations/20250114160022_remove-workspace-sync-setting.sql @@ -0,0 +1,2 @@ +-- This setting was moved to the new workspace_metas table +ALTER TABLE workspaces DROP COLUMN setting_sync_dir; diff --git a/src-tauri/src/analytics.rs b/src-tauri/src/analytics.rs index cd65dc4b..15348dee 100644 --- a/src-tauri/src/analytics.rs +++ b/src-tauri/src/analytics.rs @@ -4,6 +4,7 @@ use log::{debug, info}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; use tauri::{Manager, Runtime, WebviewWindow}; + use ts_rs::TS; use yaak_models::queries::{ generate_id, get_key_value_int, get_key_value_string, get_or_create_settings, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index c31d8689..f276e375 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1819,6 +1819,7 @@ pub fn run() { .plugin(yaak_license::init()) .plugin(yaak_models::plugin::Builder::default().build()) .plugin(yaak_plugins::init()) + .plugin(yaak_git::init()) .plugin(yaak_ws::init()) .plugin(yaak_sync::init()); diff --git a/src-tauri/yaak-git/Cargo.toml b/src-tauri/yaak-git/Cargo.toml new file mode 100644 index 00000000..053408f4 --- /dev/null +++ b/src-tauri/yaak-git/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "yaak-git" +links = "yaak-git" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +chrono = { version = "0.4.38", features = ["serde"] } +git2 = { version = "0.20.0" } +log = "0.4.22" +serde = { version = "1.0.215", features = ["derive"] } +serde_json = "1.0.132" +serde_yaml = "0.9.34" +tauri = { workspace = true } +thiserror = { workspace = true } +ts-rs = { workspace = true, features = ["chrono-impl", "serde-json-impl"] } +yaak-models = { workspace = true } +yaak-sync = { workspace = true } + +[target.'cfg(target_os = "linux")'.dependencies] +openssl-sys = { version = "0.9.105", features = ["vendored"] } # For Ubuntu installation to work + +[build-dependencies] +tauri-plugin = { version = "2.0.3", features = ["build"] } diff --git a/src-tauri/yaak-git/bindings/gen_git.ts b/src-tauri/yaak-git/bindings/gen_git.ts new file mode 100644 index 00000000..5d04669e --- /dev/null +++ b/src-tauri/yaak-git/bindings/gen_git.ts @@ -0,0 +1,18 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SyncModel } from "./gen_models"; + +export type GitAuthor = { name: string | null, email: string | null, }; + +export type GitCommit = { author: GitAuthor, when: string, message: string | null, }; + +export type GitStatus = "added" | "conflict" | "current" | "modified" | "removed" | "renamed" | "type_change"; + +export type GitStatusEntry = { relaPath: string, status: GitStatus, staged: boolean, prev: SyncModel | null, next: SyncModel | null, }; + +export type GitStatusSummary = { path: string, headRef: string | null, headRefShorthand: string | null, entries: Array, origins: Array, branches: Array, }; + +export type PullResult = { receivedBytes: number, receivedObjects: number, }; + +export type PushResult = "success" | "nothing_to_push"; + +export type PushType = "branch" | "tag"; diff --git a/src-tauri/yaak-git/bindings/gen_models.ts b/src-tauri/yaak-git/bindings/gen_models.ts new file mode 100644 index 00000000..96156cd6 --- /dev/null +++ b/src-tauri/yaak-git/bindings/gen_models.ts @@ -0,0 +1,23 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Environment = { model: "environment", id: string, workspaceId: string, environmentId: string | null, createdAt: string, updatedAt: string, name: string, variables: Array, }; + +export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, id?: string, }; + +export type Folder = { model: "folder", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, name: string, description: string, sortPriority: number, }; + +export type GrpcMetadataEntry = { enabled?: boolean, name: string, value: string, id?: string, }; + +export type GrpcRequest = { model: "grpc_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authenticationType: string | null, authentication: Record, description: string, message: string, metadata: Array, method: string | null, name: string, service: string | null, sortPriority: number, url: string, }; + +export type HttpRequest = { model: "http_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record, authenticationType: string | null, body: Record, bodyType: string | null, description: string, headers: Array, method: string, name: string, sortPriority: number, url: string, urlParameters: Array, }; + +export type HttpRequestHeader = { enabled?: boolean, name: string, value: string, id?: string, }; + +export type HttpUrlParameter = { enabled?: boolean, name: string, value: string, id?: string, }; + +export type SyncModel = { "type": "workspace" } & Workspace | { "type": "environment" } & Environment | { "type": "folder" } & Folder | { "type": "http_request" } & HttpRequest | { "type": "grpc_request" } & GrpcRequest | { "type": "websocket_request" } & WebsocketRequest; + +export type WebsocketRequest = { model: "websocket_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record, authenticationType: string | null, description: string, headers: Array, message: string, name: string, sortPriority: number, url: string, urlParameters: Array, }; + +export type Workspace = { model: "workspace", id: string, createdAt: string, updatedAt: string, name: string, description: string, settingValidateCertificates: boolean, settingFollowRedirects: boolean, settingRequestTimeout: number, }; diff --git a/src-tauri/yaak-git/build.rs b/src-tauri/yaak-git/build.rs new file mode 100644 index 00000000..c7b18afe --- /dev/null +++ b/src-tauri/yaak-git/build.rs @@ -0,0 +1,18 @@ +const COMMANDS: &[&str] = &[ + "add", + "branch", + "checkout", + "commit", + "delete_branch", + "initialize", + "log", + "merge_branch", + "pull", + "push", + "status", + "unstage", +]; + +fn main() { + tauri_plugin::Builder::new(COMMANDS).build(); +} diff --git a/src-tauri/yaak-git/index.ts b/src-tauri/yaak-git/index.ts new file mode 100644 index 00000000..388c1dfd --- /dev/null +++ b/src-tauri/yaak-git/index.ts @@ -0,0 +1,75 @@ +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { invoke } from '@tauri-apps/api/core'; +import { GitCommit, GitStatusSummary, PullResult, PushResult } from './bindings/gen_git'; + +export * from './bindings/gen_git'; + +export function useGit(dir: string) { + const queryClient = useQueryClient(); + const onSuccess = () => queryClient.invalidateQueries({ queryKey: ['git'] }); + + return [ + { + log: useQuery({ + queryKey: ['git', 'log', dir], + queryFn: () => invoke('plugin:yaak-git|log', { dir }), + }), + status: useQuery({ + refetchOnMount: true, + queryKey: ['git', 'status', dir], + queryFn: () => invoke('plugin:yaak-git|status', { dir }), + }), + }, + { + add: useMutation({ + mutationKey: ['git', 'add', dir], + mutationFn: (args) => invoke('plugin:yaak-git|add', { dir, ...args }), + onSuccess, + }), + branch: useMutation({ + mutationKey: ['git', 'branch', dir], + mutationFn: (args) => invoke('plugin:yaak-git|branch', { dir, ...args }), + onSuccess, + }), + mergeBranch: useMutation({ + mutationKey: ['git', 'merge', dir], + mutationFn: (args) => invoke('plugin:yaak-git|merge_branch', { dir, ...args }), + onSuccess, + }), + deleteBranch: useMutation({ + mutationKey: ['git', 'delete-branch', dir], + mutationFn: (args) => invoke('plugin:yaak-git|delete_branch', { dir, ...args }), + onSuccess, + }), + checkout: useMutation({ + mutationKey: ['git', 'checkout', dir], + mutationFn: (args) => invoke('plugin:yaak-git|checkout', { dir, ...args }), + onSuccess, + }), + commit: useMutation({ + mutationKey: ['git', 'commit', dir], + mutationFn: (args) => invoke('plugin:yaak-git|commit', { dir, ...args }), + onSuccess, + }), + push: useMutation({ + mutationKey: ['git', 'push', dir], + mutationFn: () => invoke('plugin:yaak-git|push', { dir }), + onSuccess, + }), + pull: useMutation({ + mutationKey: ['git', 'pull', dir], + mutationFn: () => invoke('plugin:yaak-git|pull', { dir }), + onSuccess, + }), + unstage: useMutation({ + mutationKey: ['git', 'unstage', dir], + mutationFn: (args) => invoke('plugin:yaak-git|unstage', { dir, ...args }), + onSuccess, + }), + }, + ] as const; +} + +export async function gitInit(dir: string) { + await invoke('plugin:yaak-git|initialize', { dir }); +} diff --git a/src-tauri/yaak-git/package.json b/src-tauri/yaak-git/package.json new file mode 100644 index 00000000..2c5450b3 --- /dev/null +++ b/src-tauri/yaak-git/package.json @@ -0,0 +1,6 @@ +{ + "name": "@yaakapp-internal/git", + "private": true, + "version": "1.0.0", + "main": "index.ts" +} diff --git a/src-tauri/yaak-git/permissions/autogenerated/commands/add.toml b/src-tauri/yaak-git/permissions/autogenerated/commands/add.toml new file mode 100644 index 00000000..5ce53ad8 --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/commands/add.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-add" +description = "Enables the add command without any pre-configured scope." +commands.allow = ["add"] + +[[permission]] +identifier = "deny-add" +description = "Denies the add command without any pre-configured scope." +commands.deny = ["add"] diff --git a/src-tauri/yaak-git/permissions/autogenerated/commands/branch.toml b/src-tauri/yaak-git/permissions/autogenerated/commands/branch.toml new file mode 100644 index 00000000..23ead0ef --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/commands/branch.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-branch" +description = "Enables the branch command without any pre-configured scope." +commands.allow = ["branch"] + +[[permission]] +identifier = "deny-branch" +description = "Denies the branch command without any pre-configured scope." +commands.deny = ["branch"] diff --git a/src-tauri/yaak-git/permissions/autogenerated/commands/checkout.toml b/src-tauri/yaak-git/permissions/autogenerated/commands/checkout.toml new file mode 100644 index 00000000..c523af1a --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/commands/checkout.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-checkout" +description = "Enables the checkout command without any pre-configured scope." +commands.allow = ["checkout"] + +[[permission]] +identifier = "deny-checkout" +description = "Denies the checkout command without any pre-configured scope." +commands.deny = ["checkout"] diff --git a/src-tauri/yaak-git/permissions/autogenerated/commands/commit.toml b/src-tauri/yaak-git/permissions/autogenerated/commands/commit.toml new file mode 100644 index 00000000..b8600e92 --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/commands/commit.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-commit" +description = "Enables the commit command without any pre-configured scope." +commands.allow = ["commit"] + +[[permission]] +identifier = "deny-commit" +description = "Denies the commit command without any pre-configured scope." +commands.deny = ["commit"] diff --git a/src-tauri/yaak-git/permissions/autogenerated/commands/delete_branch.toml b/src-tauri/yaak-git/permissions/autogenerated/commands/delete_branch.toml new file mode 100644 index 00000000..34c55f96 --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/commands/delete_branch.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-delete-branch" +description = "Enables the delete_branch command without any pre-configured scope." +commands.allow = ["delete_branch"] + +[[permission]] +identifier = "deny-delete-branch" +description = "Denies the delete_branch command without any pre-configured scope." +commands.deny = ["delete_branch"] diff --git a/src-tauri/yaak-git/permissions/autogenerated/commands/initialize.toml b/src-tauri/yaak-git/permissions/autogenerated/commands/initialize.toml new file mode 100644 index 00000000..73961d13 --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/commands/initialize.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-initialize" +description = "Enables the initialize command without any pre-configured scope." +commands.allow = ["initialize"] + +[[permission]] +identifier = "deny-initialize" +description = "Denies the initialize command without any pre-configured scope." +commands.deny = ["initialize"] diff --git a/src-tauri/yaak-git/permissions/autogenerated/commands/log.toml b/src-tauri/yaak-git/permissions/autogenerated/commands/log.toml new file mode 100644 index 00000000..ba36eff5 --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/commands/log.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-log" +description = "Enables the log command without any pre-configured scope." +commands.allow = ["log"] + +[[permission]] +identifier = "deny-log" +description = "Denies the log command without any pre-configured scope." +commands.deny = ["log"] diff --git a/src-tauri/yaak-git/permissions/autogenerated/commands/merge_branch.toml b/src-tauri/yaak-git/permissions/autogenerated/commands/merge_branch.toml new file mode 100644 index 00000000..d496f957 --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/commands/merge_branch.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-merge-branch" +description = "Enables the merge_branch command without any pre-configured scope." +commands.allow = ["merge_branch"] + +[[permission]] +identifier = "deny-merge-branch" +description = "Denies the merge_branch command without any pre-configured scope." +commands.deny = ["merge_branch"] diff --git a/src-tauri/yaak-git/permissions/autogenerated/commands/pull.toml b/src-tauri/yaak-git/permissions/autogenerated/commands/pull.toml new file mode 100644 index 00000000..ffc5a48e --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/commands/pull.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-pull" +description = "Enables the pull command without any pre-configured scope." +commands.allow = ["pull"] + +[[permission]] +identifier = "deny-pull" +description = "Denies the pull command without any pre-configured scope." +commands.deny = ["pull"] diff --git a/src-tauri/yaak-git/permissions/autogenerated/commands/push.toml b/src-tauri/yaak-git/permissions/autogenerated/commands/push.toml new file mode 100644 index 00000000..2f0d1200 --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/commands/push.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-push" +description = "Enables the push command without any pre-configured scope." +commands.allow = ["push"] + +[[permission]] +identifier = "deny-push" +description = "Denies the push command without any pre-configured scope." +commands.deny = ["push"] diff --git a/src-tauri/yaak-git/permissions/autogenerated/commands/status.toml b/src-tauri/yaak-git/permissions/autogenerated/commands/status.toml new file mode 100644 index 00000000..c8ed433c --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/commands/status.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-status" +description = "Enables the status command without any pre-configured scope." +commands.allow = ["status"] + +[[permission]] +identifier = "deny-status" +description = "Denies the status command without any pre-configured scope." +commands.deny = ["status"] diff --git a/src-tauri/yaak-git/permissions/autogenerated/commands/unstage.toml b/src-tauri/yaak-git/permissions/autogenerated/commands/unstage.toml new file mode 100644 index 00000000..cbf33ce2 --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/commands/unstage.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-unstage" +description = "Enables the unstage command without any pre-configured scope." +commands.allow = ["unstage"] + +[[permission]] +identifier = "deny-unstage" +description = "Denies the unstage command without any pre-configured scope." +commands.deny = ["unstage"] diff --git a/src-tauri/yaak-git/permissions/autogenerated/reference.md b/src-tauri/yaak-git/permissions/autogenerated/reference.md new file mode 100644 index 00000000..0488e778 --- /dev/null +++ b/src-tauri/yaak-git/permissions/autogenerated/reference.md @@ -0,0 +1,338 @@ +## Default Permission + +Default permissions for the plugin + +- `allow-add` +- `allow-branch` +- `allow-checkout` +- `allow-commit` +- `allow-delete-branch` +- `allow-initialize` +- `allow-log` +- `allow-merge-branch` +- `allow-pull` +- `allow-push` +- `allow-status` +- `allow-unstage` + +## Permission Table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdentifierDescription
+ +`yaak-git:allow-add` + + + +Enables the add command without any pre-configured scope. + +
+ +`yaak-git:deny-add` + + + +Denies the add command without any pre-configured scope. + +
+ +`yaak-git:allow-branch` + + + +Enables the branch command without any pre-configured scope. + +
+ +`yaak-git:deny-branch` + + + +Denies the branch command without any pre-configured scope. + +
+ +`yaak-git:allow-checkout` + + + +Enables the checkout command without any pre-configured scope. + +
+ +`yaak-git:deny-checkout` + + + +Denies the checkout command without any pre-configured scope. + +
+ +`yaak-git:allow-commit` + + + +Enables the commit command without any pre-configured scope. + +
+ +`yaak-git:deny-commit` + + + +Denies the commit command without any pre-configured scope. + +
+ +`yaak-git:allow-delete-branch` + + + +Enables the delete_branch command without any pre-configured scope. + +
+ +`yaak-git:deny-delete-branch` + + + +Denies the delete_branch command without any pre-configured scope. + +
+ +`yaak-git:allow-initialize` + + + +Enables the initialize command without any pre-configured scope. + +
+ +`yaak-git:deny-initialize` + + + +Denies the initialize command without any pre-configured scope. + +
+ +`yaak-git:allow-log` + + + +Enables the log command without any pre-configured scope. + +
+ +`yaak-git:deny-log` + + + +Denies the log command without any pre-configured scope. + +
+ +`yaak-git:allow-merge-branch` + + + +Enables the merge_branch command without any pre-configured scope. + +
+ +`yaak-git:deny-merge-branch` + + + +Denies the merge_branch command without any pre-configured scope. + +
+ +`yaak-git:allow-pull` + + + +Enables the pull command without any pre-configured scope. + +
+ +`yaak-git:deny-pull` + + + +Denies the pull command without any pre-configured scope. + +
+ +`yaak-git:allow-push` + + + +Enables the push command without any pre-configured scope. + +
+ +`yaak-git:deny-push` + + + +Denies the push command without any pre-configured scope. + +
+ +`yaak-git:allow-status` + + + +Enables the status command without any pre-configured scope. + +
+ +`yaak-git:deny-status` + + + +Denies the status command without any pre-configured scope. + +
+ +`yaak-git:allow-unstage` + + + +Enables the unstage command without any pre-configured scope. + +
+ +`yaak-git:deny-unstage` + + + +Denies the unstage command without any pre-configured scope. + +
diff --git a/src-tauri/yaak-git/permissions/default.toml b/src-tauri/yaak-git/permissions/default.toml new file mode 100644 index 00000000..f0e0ce5e --- /dev/null +++ b/src-tauri/yaak-git/permissions/default.toml @@ -0,0 +1,16 @@ +[default] +description = "Default permissions for the plugin" +permissions = [ + "allow-add", + "allow-branch", + "allow-checkout", + "allow-commit", + "allow-delete-branch", + "allow-initialize", + "allow-log", + "allow-merge-branch", + "allow-pull", + "allow-push", + "allow-status", + "allow-unstage", +] diff --git a/src-tauri/yaak-git/permissions/schemas/schema.json b/src-tauri/yaak-git/permissions/schemas/schema.json new file mode 100644 index 00000000..b28e4e74 --- /dev/null +++ b/src-tauri/yaak-git/permissions/schemas/schema.json @@ -0,0 +1,425 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "PermissionFile", + "description": "Permission file that can define a default permission, a set of permissions or a list of inlined permissions.", + "type": "object", + "properties": { + "default": { + "description": "The default permission set for the plugin", + "anyOf": [ + { + "$ref": "#/definitions/DefaultPermission" + }, + { + "type": "null" + } + ] + }, + "set": { + "description": "A list of permissions sets defined", + "type": "array", + "items": { + "$ref": "#/definitions/PermissionSet" + } + }, + "permission": { + "description": "A list of inlined permissions", + "default": [], + "type": "array", + "items": { + "$ref": "#/definitions/Permission" + } + } + }, + "definitions": { + "DefaultPermission": { + "description": "The default permission set of the plugin.\n\nWorks similarly to a permission with the \"default\" identifier.", + "type": "object", + "required": [ + "permissions" + ], + "properties": { + "version": { + "description": "The version of the permission.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 1.0 + }, + "description": { + "description": "Human-readable description of what the permission does. Tauri convention is to use

headings in markdown content for Tauri documentation generation purposes.", + "type": [ + "string", + "null" + ] + }, + "permissions": { + "description": "All permissions this set contains.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "PermissionSet": { + "description": "A set of direct permissions grouped together under a new name.", + "type": "object", + "required": [ + "description", + "identifier", + "permissions" + ], + "properties": { + "identifier": { + "description": "A unique identifier for the permission.", + "type": "string" + }, + "description": { + "description": "Human-readable description of what the permission does.", + "type": "string" + }, + "permissions": { + "description": "All permissions this set contains.", + "type": "array", + "items": { + "$ref": "#/definitions/PermissionKind" + } + } + } + }, + "Permission": { + "description": "Descriptions of explicit privileges of commands.\n\nIt can enable commands to be accessible in the frontend of the application.\n\nIf the scope is defined it can be used to fine grain control the access of individual or multiple commands.", + "type": "object", + "required": [ + "identifier" + ], + "properties": { + "version": { + "description": "The version of the permission.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 1.0 + }, + "identifier": { + "description": "A unique identifier for the permission.", + "type": "string" + }, + "description": { + "description": "Human-readable description of what the permission does. Tauri internal convention is to use

headings in markdown content for Tauri documentation generation purposes.", + "type": [ + "string", + "null" + ] + }, + "commands": { + "description": "Allowed or denied commands when using this permission.", + "default": { + "allow": [], + "deny": [] + }, + "allOf": [ + { + "$ref": "#/definitions/Commands" + } + ] + }, + "scope": { + "description": "Allowed or denied scoped when using this permission.", + "allOf": [ + { + "$ref": "#/definitions/Scopes" + } + ] + }, + "platforms": { + "description": "Target platforms this permission applies. By default all platforms are affected by this permission.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Target" + } + } + } + }, + "Commands": { + "description": "Allowed and denied commands inside a permission.\n\nIf two commands clash inside of `allow` and `deny`, it should be denied by default.", + "type": "object", + "properties": { + "allow": { + "description": "Allowed command.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "deny": { + "description": "Denied command, which takes priority.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "Scopes": { + "description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```", + "type": "object", + "properties": { + "allow": { + "description": "Data that defines what is allowed by the scope.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Value" + } + }, + "deny": { + "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Value" + } + } + } + }, + "Value": { + "description": "All supported ACL values.", + "anyOf": [ + { + "description": "Represents a null JSON value.", + "type": "null" + }, + { + "description": "Represents a [`bool`].", + "type": "boolean" + }, + { + "description": "Represents a valid ACL [`Number`].", + "allOf": [ + { + "$ref": "#/definitions/Number" + } + ] + }, + { + "description": "Represents a [`String`].", + "type": "string" + }, + { + "description": "Represents a list of other [`Value`]s.", + "type": "array", + "items": { + "$ref": "#/definitions/Value" + } + }, + { + "description": "Represents a map of [`String`] keys to [`Value`]s.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/Value" + } + } + ] + }, + "Number": { + "description": "A valid ACL number.", + "anyOf": [ + { + "description": "Represents an [`i64`].", + "type": "integer", + "format": "int64" + }, + { + "description": "Represents a [`f64`].", + "type": "number", + "format": "double" + } + ] + }, + "Target": { + "description": "Platform target.", + "oneOf": [ + { + "description": "MacOS.", + "type": "string", + "enum": [ + "macOS" + ] + }, + { + "description": "Windows.", + "type": "string", + "enum": [ + "windows" + ] + }, + { + "description": "Linux.", + "type": "string", + "enum": [ + "linux" + ] + }, + { + "description": "Android.", + "type": "string", + "enum": [ + "android" + ] + }, + { + "description": "iOS.", + "type": "string", + "enum": [ + "iOS" + ] + } + ] + }, + "PermissionKind": { + "type": "string", + "oneOf": [ + { + "description": "Enables the add command without any pre-configured scope.", + "type": "string", + "const": "allow-add" + }, + { + "description": "Denies the add command without any pre-configured scope.", + "type": "string", + "const": "deny-add" + }, + { + "description": "Enables the branch command without any pre-configured scope.", + "type": "string", + "const": "allow-branch" + }, + { + "description": "Denies the branch command without any pre-configured scope.", + "type": "string", + "const": "deny-branch" + }, + { + "description": "Enables the checkout command without any pre-configured scope.", + "type": "string", + "const": "allow-checkout" + }, + { + "description": "Denies the checkout command without any pre-configured scope.", + "type": "string", + "const": "deny-checkout" + }, + { + "description": "Enables the commit command without any pre-configured scope.", + "type": "string", + "const": "allow-commit" + }, + { + "description": "Denies the commit command without any pre-configured scope.", + "type": "string", + "const": "deny-commit" + }, + { + "description": "Enables the delete_branch command without any pre-configured scope.", + "type": "string", + "const": "allow-delete-branch" + }, + { + "description": "Denies the delete_branch command without any pre-configured scope.", + "type": "string", + "const": "deny-delete-branch" + }, + { + "description": "Enables the initialize command without any pre-configured scope.", + "type": "string", + "const": "allow-initialize" + }, + { + "description": "Denies the initialize command without any pre-configured scope.", + "type": "string", + "const": "deny-initialize" + }, + { + "description": "Enables the log command without any pre-configured scope.", + "type": "string", + "const": "allow-log" + }, + { + "description": "Denies the log command without any pre-configured scope.", + "type": "string", + "const": "deny-log" + }, + { + "description": "Enables the merge_branch command without any pre-configured scope.", + "type": "string", + "const": "allow-merge-branch" + }, + { + "description": "Denies the merge_branch command without any pre-configured scope.", + "type": "string", + "const": "deny-merge-branch" + }, + { + "description": "Enables the pull command without any pre-configured scope.", + "type": "string", + "const": "allow-pull" + }, + { + "description": "Denies the pull command without any pre-configured scope.", + "type": "string", + "const": "deny-pull" + }, + { + "description": "Enables the push command without any pre-configured scope.", + "type": "string", + "const": "allow-push" + }, + { + "description": "Denies the push command without any pre-configured scope.", + "type": "string", + "const": "deny-push" + }, + { + "description": "Enables the status command without any pre-configured scope.", + "type": "string", + "const": "allow-status" + }, + { + "description": "Denies the status command without any pre-configured scope.", + "type": "string", + "const": "deny-status" + }, + { + "description": "Enables the unstage command without any pre-configured scope.", + "type": "string", + "const": "allow-unstage" + }, + { + "description": "Denies the unstage command without any pre-configured scope.", + "type": "string", + "const": "deny-unstage" + }, + { + "description": "Default permissions for the plugin", + "type": "string", + "const": "default" + } + ] + } + } +} \ No newline at end of file diff --git a/src-tauri/yaak-git/src/branch.rs b/src-tauri/yaak-git/src/branch.rs new file mode 100644 index 00000000..f26eb569 --- /dev/null +++ b/src-tauri/yaak-git/src/branch.rs @@ -0,0 +1,90 @@ +use crate::error::Error::GenericError; +use crate::error::Result; +use crate::merge::do_merge; +use crate::repository::open_repo; +use crate::util::{ + bytes_to_string, get_branch_by_name, get_current_branch, get_default_remote_for_push_in_repo, +}; +use git2::build::CheckoutBuilder; +use git2::{BranchType, Repository}; +use log::info; +use std::path::Path; + +pub(crate) fn branch_set_upstream_after_push(repo: &Repository, branch_name: &str) -> Result<()> { + let mut branch = repo.find_branch(branch_name, BranchType::Local)?; + + if branch.upstream().is_err() { + let remote = get_default_remote_for_push_in_repo(repo)?; + let upstream_name = format!("{remote}/{branch_name}"); + branch.set_upstream(Some(upstream_name.as_str()))?; + } + + Ok(()) +} + +pub(crate) fn git_checkout_branch(dir: &Path, branch: &str, force: bool) -> Result<()> { + let repo = open_repo(dir)?; + let branch = get_branch_by_name(&repo, branch)?; + let branch_ref = branch.into_reference(); + let branch_tree = branch_ref.peel_to_tree()?; + + let mut options = CheckoutBuilder::default(); + if force { + options.force(); + } + + repo.checkout_tree(branch_tree.as_object(), Some(&mut options))?; + repo.set_head(branch_ref.name().unwrap())?; + + Ok(()) +} + +pub(crate) fn git_create_branch(dir: &Path, name: &str) -> Result<()> { + let repo = open_repo(dir)?; + let head = match repo.head() { + Ok(h) => h, + Err(e) if e.code() == git2::ErrorCode::UnbornBranch => { + let msg = "Cannot create branch when there are no commits"; + return Err(GenericError(msg.into())); + } + Err(e) => return Err(e.into()), + }; + let head = head.peel_to_commit()?; + + repo.branch(name, &head, false)?; + + Ok(()) +} + +pub(crate) fn git_delete_branch(dir: &Path, name: &str) -> Result<()> { + let repo = open_repo(dir)?; + let mut branch = get_branch_by_name(&repo, name)?; + + if branch.is_head() { + info!("Deleting head branch"); + let branches = repo.branches(Some(BranchType::Local))?; + let other_branch = branches.into_iter().filter_map(|b| b.ok()).find(|b| !b.0.is_head()); + let other_branch = match other_branch { + None => return Err(GenericError("Cannot delete only branch".into())), + Some(b) => bytes_to_string(b.0.name_bytes()?)?, + }; + + git_checkout_branch(dir, &other_branch, true)?; + } + + branch.delete()?; + + Ok(()) +} + +pub(crate) fn git_merge_branch(dir: &Path, name: &str, _force: bool) -> Result<()> { + let repo = open_repo(dir)?; + let local_branch = get_current_branch(&repo)?.unwrap(); + + let commit_to_merge = get_branch_by_name(&repo, name)?.into_reference(); + let commit_to_merge = repo.reference_to_annotated_commit(&commit_to_merge)?; + + do_merge(&repo, &local_branch, &commit_to_merge)?; + + Ok(()) +} diff --git a/src-tauri/yaak-git/src/callbacks.rs b/src-tauri/yaak-git/src/callbacks.rs new file mode 100644 index 00000000..38e5a153 --- /dev/null +++ b/src-tauri/yaak-git/src/callbacks.rs @@ -0,0 +1,76 @@ +use git2::{Cred, RemoteCallbacks}; +use log::{debug, info}; +use crate::util::find_ssh_key; + +pub(crate) fn default_callbacks<'s>() -> RemoteCallbacks<'s> { + let mut callbacks = RemoteCallbacks::new(); + + let mut fail_next_call = false; + let mut tried_agent = false; + + callbacks.credentials(move |url, username_from_url, allowed_types| { + if fail_next_call { + info!("Failed to get credentials for push"); + return Err(git2::Error::from_str("Bad credentials.")); + } + + debug!("getting credentials {url} {username_from_url:?} {allowed_types:?}"); + match (allowed_types.is_ssh_key(), username_from_url) { + (true, Some(username)) => { + if !tried_agent { + tried_agent = true; + return Cred::ssh_key_from_agent(username); + } + + fail_next_call = true; // This is our last try + + // If the agent failed, try using the default SSH key + if let Some(key) = find_ssh_key() { + Cred::ssh_key(username, None, key.as_path(), None) + } else { + Err(git2::Error::from_str( + "Bad credentials. Ensure your key was added using ssh-add", + )) + } + } + (true, None) => Err(git2::Error::from_str("Couldn't get username from url")), + _ => { + todo!("Implement basic auth credential"); + } + } + }); + + callbacks.push_transfer_progress(|current, total, bytes| { + debug!("progress: {}/{} ({} B)", current, total, bytes,); + }); + + callbacks.transfer_progress(|p| { + debug!("transfer: {}/{}", p.received_objects(), p.total_objects()); + true + }); + + callbacks.pack_progress(|stage, current, total| { + debug!("packing: {:?} - {}/{}", stage, current, total); + }); + + callbacks.push_update_reference(|reference, msg| { + debug!("push_update_reference: '{}' {:?}", reference, msg); + Ok(()) + }); + + callbacks.update_tips(|name, a, b| { + debug!("update tips: '{}' {} -> {}", name, a, b); + if a != b { + // let mut push_result = push_result.lock().unwrap(); + // *push_result = PushResult::Success + } + true + }); + + callbacks.sideband_progress(|data| { + debug!("sideband transfer: '{}'", String::from_utf8_lossy(data).trim()); + true + }); + + callbacks +} \ No newline at end of file diff --git a/src-tauri/yaak-git/src/commands.rs b/src-tauri/yaak-git/src/commands.rs new file mode 100644 index 00000000..8429fcad --- /dev/null +++ b/src-tauri/yaak-git/src/commands.rs @@ -0,0 +1,76 @@ +use crate::branch::{git_checkout_branch, git_create_branch, git_delete_branch, git_merge_branch}; +use crate::error::Result; +use crate::git::{ + git_add, git_commit, git_init, git_log, git_status, git_unstage, GitCommit, GitStatusSummary, +}; +use crate::pull::{git_pull, PullResult}; +use crate::push::{git_push, PushResult}; +use std::path::{Path, PathBuf}; +use tauri::command; +// NOTE: All of these commands are async to prevent blocking work from locking up the UI + +#[command] +pub async fn checkout(dir: &Path, branch: &str, force: bool) -> Result<()> { + git_checkout_branch(dir, branch, force) +} + +#[command] +pub async fn branch(dir: &Path, branch: &str) -> Result<()> { + git_create_branch(dir, branch) +} + +#[command] +pub async fn delete_branch(dir: &Path, branch: &str) -> Result<()> { + git_delete_branch(dir, branch) +} + +#[command] +pub async fn merge_branch(dir: &Path, branch: &str, force: bool) -> Result<()> { + git_merge_branch(dir, branch, force) +} + +#[command] +pub async fn status(dir: &Path) -> Result { + git_status(dir) +} + +#[command] +pub async fn log(dir: &Path) -> Result> { + git_log(dir) +} + +#[command] +pub async fn initialize(dir: &Path) -> Result<()> { + git_init(dir) +} + +#[command] +pub async fn commit(dir: &Path, message: &str) -> Result<()> { + git_commit(dir, message) +} + +#[command] +pub async fn push(dir: &Path) -> Result { + git_push(dir) +} + +#[command] +pub async fn pull(dir: &Path) -> Result { + git_pull(dir) +} + +#[command] +pub async fn add(dir: &Path, rela_paths: Vec) -> Result<()> { + for path in rela_paths { + git_add(dir, &path)?; + } + Ok(()) +} + +#[command] +pub async fn unstage(dir: &Path, rela_paths: Vec) -> Result<()> { + for path in rela_paths { + git_unstage(dir, &path)?; + } + Ok(()) +} diff --git a/src-tauri/yaak-git/src/error.rs b/src-tauri/yaak-git/src/error.rs new file mode 100644 index 00000000..9651601e --- /dev/null +++ b/src-tauri/yaak-git/src/error.rs @@ -0,0 +1,55 @@ +use serde::{Serialize, Serializer}; +use std::io; +use std::path::PathBuf; +use std::string::FromUtf8Error; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error("Git repo not found {0}")] + GitRepoNotFound(PathBuf), + + #[error("Git error: {0}")] + GitUnknown(#[from] git2::Error), + + #[error("Yaml error: {0}")] + YamlParseError(#[from] serde_yaml::Error), + + #[error("Yaml error: {0}")] + ModelError(#[from] yaak_models::error::Error), + + #[error("Sync error: {0}")] + SyncError(#[from] yaak_sync::error::Error), + + #[error("I/o error: {0}")] + IoError(#[from] io::Error), + + #[error("Yaml error: {0}")] + JsonParseError(#[from] serde_json::Error), + + #[error("Yaml error: {0}")] + Utf8ConversionError(#[from] FromUtf8Error), + + #[error("Git error: {0}")] + GenericError(String), + + #[error("No default remote found")] + NoDefaultRemoteFound, + + #[error("Merge failed due to conflicts")] + MergeConflicts, + + #[error("No active branch")] + NoActiveBranch, +} + +impl Serialize for Error { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: Serializer, + { + serializer.serialize_str(self.to_string().as_ref()) + } +} + +pub type Result = std::result::Result; diff --git a/src-tauri/yaak-git/src/git.rs b/src-tauri/yaak-git/src/git.rs new file mode 100644 index 00000000..e61ae414 --- /dev/null +++ b/src-tauri/yaak-git/src/git.rs @@ -0,0 +1,670 @@ +use crate::error::Result; +use crate::repository::open_repo; +use crate::util::list_branch_names; +use chrono::{DateTime, Utc}; +use git2::IndexAddOption; +use log::{info, warn}; +use serde::{Deserialize, Serialize}; +use std::fs; +use std::path::Path; +use ts_rs::TS; +use yaak_sync::models::SyncModel; + +#[derive(Debug, Clone, Serialize, Deserialize, TS, PartialEq)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "gen_git.ts")] +pub struct GitStatusSummary { + pub path: String, + pub head_ref: Option, + pub head_ref_shorthand: Option, + pub entries: Vec, + pub origins: Vec, + pub branches: Vec, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "gen_git.ts")] +pub struct GitStatusEntry { + pub rela_path: String, + pub status: GitStatus, + pub staged: bool, + pub prev: Option, + pub next: Option, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)] +#[serde(rename_all = "snake_case")] +#[ts(export, export_to = "gen_git.ts")] +pub enum GitStatus { + Added, + Conflict, + Current, + Modified, + Removed, + Renamed, + TypeChange, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "gen_git.ts")] +pub struct GitCommit { + author: GitAuthor, + when: DateTime, + message: Option, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "gen_git.ts")] +pub struct GitAuthor { + name: Option, + email: Option, +} + +pub fn git_init(dir: &Path) -> Result<()> { + git2::Repository::init(dir)?; + let repo = open_repo(dir)?; + // Default to main instead of master, to align with + // the official Git and GitHub behavior + repo.set_head("refs/heads/main")?; + info!("Initialized {dir:?}"); + Ok(()) +} + +pub fn git_add(dir: &Path, rela_path: &Path) -> Result<()> { + let repo = open_repo(dir)?; + let mut index = repo.index()?; + + info!("Staging file {rela_path:?} to {dir:?}"); + index.add_all(&[rela_path], IndexAddOption::DEFAULT, None)?; + index.write()?; + + Ok(()) +} + +pub fn git_unstage(dir: &Path, rela_path: &Path) -> Result<()> { + let repo = open_repo(dir)?; + + let head = match repo.head() { + Ok(h) => h, + Err(e) if e.code() == git2::ErrorCode::UnbornBranch => { + info!("Unstaging file in empty branch {rela_path:?} to {dir:?}"); + // Repo has no commits, so "unstage" means remove from index + let mut index = repo.index()?; + index.remove_path(rela_path)?; + index.write()?; + return Ok(()); + } + Err(e) => return Err(e.into()), + }; + + // If repo has commits, update the index entry back to HEAD + info!("Unstaging file {rela_path:?} to {dir:?}"); + let commit = head.peel_to_commit()?; + repo.reset_default(Some(commit.as_object()), &[rela_path])?; + + Ok(()) +} + +pub fn git_commit(dir: &Path, message: &str) -> Result<()> { + let repo = open_repo(dir)?; + + // Clear the in-memory index, add the paths, and write the tree for committing + let tree_oid = repo.index()?.write_tree()?; + let tree = repo.find_tree(tree_oid)?; + + // Make the signature + let config = git2::Config::open_default()?.snapshot()?; + let name = config.get_str("user.name").unwrap_or("Change Me"); + let email = config.get_str("user.email").unwrap_or("change_me@example.com"); + let sig = git2::Signature::now(name, email)?; + + // Get the current HEAD commit (if it exists) + let parent_commit = match repo.head() { + Ok(head) => Some(head.peel_to_commit()?), + Err(_) => None, // No parent if no HEAD exists (initial commit) + }; + + let parents = parent_commit.as_ref().map(|p| vec![p]).unwrap_or_default(); + repo.commit(Some("HEAD"), &sig, &sig, message, &tree, parents.as_slice())?; + + info!("Committed to {dir:?}"); + + Ok(()) +} + +pub fn git_log(dir: &Path) -> Result> { + let repo = open_repo(dir)?; + + // Return empty if empty repo or no head (new repo) + if repo.is_empty()? || repo.head().is_err() { + return Ok(vec![]); + } + + let mut revwalk = repo.revwalk()?; + revwalk.push_head()?; + revwalk.set_sorting(git2::Sort::TIME)?; + + // Run git log + macro_rules! filter_try { + ($e:expr) => { + match $e { + Ok(t) => t, + Err(_) => return None, + } + }; + } + let log: Vec = revwalk + .filter_map(|oid| { + let oid = filter_try!(oid); + let commit = filter_try!(repo.find_commit(oid)); + let author = commit.author(); + Some(GitCommit { + author: GitAuthor { + name: author.name().map(|s| s.to_string()), + email: author.email().map(|s| s.to_string()), + }, + when: convert_git_time_to_date(author.when()), + message: commit.message().map(|m| m.to_string()), + }) + }) + .collect(); + + Ok(log) +} + +pub fn git_status(dir: &Path) -> Result { + let repo = open_repo(dir)?; + let (head_tree, head_ref, head_ref_shorthand) = match repo.head() { + Ok(head) => { + let tree = head.peel_to_tree().ok(); + let head_ref_shorthand = head.shorthand().map(|s| s.to_string()); + let head_ref = head.name().map(|s| s.to_string()); + + (tree, head_ref, head_ref_shorthand) + } + Err(_) => { + // For "unborn" repos, reading from HEAD is the only way to get the branch name + // See https://github.com/starship/starship/pull/1336 + let head_path = repo.path().join("HEAD"); + let head_ref = fs::read_to_string(&head_path) + .ok() + .unwrap_or_default() + .lines() + .next() + .map(|s| s.trim_start_matches("ref:").trim().to_string()); + let head_ref_shorthand = + head_ref.clone().map(|r| r.split('/').last().unwrap_or("unknown").to_string()); + (None, head_ref, head_ref_shorthand) + } + }; + + let mut opts = git2::StatusOptions::new(); + opts.include_ignored(false) + .include_untracked(true) // Include untracked + .recurse_untracked_dirs(true) // Show all untracked + .include_unmodified(true); // Include unchanged + + // TODO: Support renames + + let mut entries: Vec = Vec::new(); + for entry in repo.statuses(Some(&mut opts))?.into_iter() { + let rela_path = entry.path().unwrap().to_string(); + let status = entry.status(); + let index_status = match status { + // Note: order matters here, since we're checking a bitmap! + s if s.contains(git2::Status::CONFLICTED) => GitStatus::Conflict, + s if s.contains(git2::Status::INDEX_NEW) => GitStatus::Added, + s if s.contains(git2::Status::INDEX_MODIFIED) => GitStatus::Modified, + s if s.contains(git2::Status::INDEX_DELETED) => GitStatus::Removed, + s if s.contains(git2::Status::INDEX_RENAMED) => GitStatus::Renamed, + s if s.contains(git2::Status::INDEX_TYPECHANGE) => GitStatus::TypeChange, + s if s.contains(git2::Status::CURRENT) => GitStatus::Current, + s => { + warn!("Unknown index status {s:?}"); + continue; + } + }; + + let worktree_status = match status { + // Note: order matters here, since we're checking a bitmap! + s if s.contains(git2::Status::CONFLICTED) => GitStatus::Conflict, + s if s.contains(git2::Status::WT_NEW) => GitStatus::Added, + s if s.contains(git2::Status::WT_MODIFIED) => GitStatus::Modified, + s if s.contains(git2::Status::WT_DELETED) => GitStatus::Removed, + s if s.contains(git2::Status::WT_RENAMED) => GitStatus::Renamed, + s if s.contains(git2::Status::WT_TYPECHANGE) => GitStatus::TypeChange, + s if s.contains(git2::Status::CURRENT) => GitStatus::Current, + s => { + warn!("Unknown worktree status {s:?}"); + continue; + } + }; + + let status = if index_status == GitStatus::Current { + worktree_status.clone() + } else { + index_status.clone() + }; + + let staged = if index_status == GitStatus::Current && worktree_status == GitStatus::Current + { + // No change, so can't be added + false + } else if index_status != GitStatus::Current { + true + } else { + false + }; + + // Get previous content from Git, if it's in there + let prev = match head_tree.clone() { + None => None, + Some(t) => match t.get_path(&Path::new(&rela_path)) { + Ok(entry) => { + let obj = entry.to_object(&repo).unwrap(); + let content = obj.as_blob().unwrap().content(); + let name = Path::new(entry.name().unwrap_or_default()); + SyncModel::from_bytes(content.into(), name)?.map(|m| m.0) + } + Err(_) => None, + }, + }; + + let next = { + let full_path = repo.workdir().unwrap().join(rela_path.clone()); + SyncModel::from_file(full_path.as_path())?.map(|m| m.0) + }; + + entries.push(GitStatusEntry { + status, + staged, + rela_path, + prev: prev.clone(), + next: next.clone(), + }) + } + + let origins = repo.remotes()?.into_iter().filter_map(|o| Some(o?.to_string())).collect(); + let branches = list_branch_names(&repo)?; + + Ok(GitStatusSummary { + entries, + origins, + path: dir.to_string_lossy().to_string(), + head_ref, + head_ref_shorthand, + branches, + }) +} + +#[cfg(test)] +fn convert_git_time_to_date(_git_time: git2::Time) -> DateTime { + DateTime::from_timestamp(0, 0).unwrap() +} + +#[cfg(not(test))] +fn convert_git_time_to_date(git_time: git2::Time) -> DateTime { + let timestamp = git_time.seconds(); + DateTime::from_timestamp(timestamp, 0).unwrap() +} + +// // Write a test +// #[cfg(test)] +// mod test { +// use crate::error::Error::GitRepoNotFound; +// use crate::error::Result; +// use crate::git::{ +// git_add, git_commit, git_init, git_log, git_status, git_unstage, open_repo, GitStatus, +// GitStatusEntry, +// }; +// use std::fs::{create_dir_all, remove_file, File}; +// use std::io::Write; +// use std::path::{Path, PathBuf}; +// use tempdir::TempDir; +// +// fn new_dir() -> PathBuf { +// let p = TempDir::new("yaak-git").unwrap().into_path(); +// p +// } +// +// fn new_file(path: &Path, content: &str) { +// let parent = path.parent().unwrap(); +// create_dir_all(parent).unwrap(); +// File::create(path).unwrap().write_all(content.as_bytes()).unwrap(); +// } +// +// #[tokio::test] +// async fn test_status_no_repo() { +// let dir = &new_dir(); +// let result = git_status(dir).await; +// assert!(matches!(result, Err(GitRepoNotFound(_)))); +// } +// +// #[test] +// fn test_open_repo() -> Result<()> { +// let dir = &new_dir(); +// git_init(dir)?; +// open_repo(dir.as_path())?; +// Ok(()) +// } +// +// #[test] +// fn test_open_repo_from_subdir() -> Result<()> { +// let dir = &new_dir(); +// git_init(dir)?; +// +// let sub_dir = dir.join("a").join("b"); +// create_dir_all(sub_dir.as_path())?; // Create sub dir +// +// open_repo(sub_dir.as_path())?; +// Ok(()) +// } +// +// #[tokio::test] +// async fn test_status() -> Result<()> { +// let dir = &new_dir(); +// git_init(dir)?; +// +// assert_eq!(git_status(dir).await?.entries, Vec::new()); +// +// new_file(&dir.join("foo.txt"), "foo"); +// new_file(&dir.join("bar.txt"), "bar"); +// new_file(&dir.join("dir/baz.txt"), "baz"); +// assert_eq!( +// git_status(dir).await?.entries, +// vec![ +// GitStatusEntry { +// rela_path: "bar.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("bar".to_string()), +// }, +// GitStatusEntry { +// rela_path: "dir/baz.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("baz".to_string()), +// }, +// GitStatusEntry { +// rela_path: "foo.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("foo".to_string()), +// }, +// ], +// ); +// Ok(()) +// } +// +// #[tokio::test] +// fn test_add() -> Result<()> { +// let dir = &new_dir(); +// git_init(dir)?; +// +// new_file(&dir.join("foo.txt"), "foo"); +// new_file(&dir.join("bar.txt"), "bar"); +// +// git_add(dir, Path::new("foo.txt"))?; +// +// assert_eq!( +// git_status(dir).await?.entries, +// vec![ +// GitStatusEntry { +// rela_path: "bar.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("bar".to_string()), +// }, +// GitStatusEntry { +// rela_path: "foo.txt".to_string(), +// status: GitStatus::Added, +// staged: true, +// prev: None, +// next: Some("foo".to_string()), +// }, +// ], +// ); +// +// new_file(&dir.join("foo.txt"), "foo foo"); +// assert_eq!( +// git_status(dir).await?.entries, +// vec![ +// GitStatusEntry { +// rela_path: "bar.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("bar".to_string()), +// }, +// GitStatusEntry { +// rela_path: "foo.txt".to_string(), +// status: GitStatus::Added, +// staged: true, +// prev: None, +// next: Some("foo foo".to_string()), +// }, +// ], +// ); +// Ok(()) +// } +// +// #[tokio::test] +// fn test_unstage() -> Result<()> { +// let dir = &new_dir(); +// git_init(dir)?; +// +// new_file(&dir.join("foo.txt"), "foo"); +// new_file(&dir.join("bar.txt"), "bar"); +// +// git_add(dir, Path::new("foo.txt"))?; +// assert_eq!( +// git_status(dir).await?.entries, +// vec![ +// GitStatusEntry { +// rela_path: "bar.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("bar".to_string()), +// }, +// GitStatusEntry { +// rela_path: "foo.txt".to_string(), +// status: GitStatus::Added, +// staged: true, +// prev: None, +// next: Some("foo".to_string()), +// }, +// ] +// ); +// +// git_unstage(dir, Path::new("foo.txt"))?; +// assert_eq!( +// git_status(dir).await?.entries, +// vec![ +// GitStatusEntry { +// rela_path: "bar.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("bar".to_string()), +// }, +// GitStatusEntry { +// rela_path: "foo.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("foo".to_string()), +// } +// ] +// ); +// +// Ok(()) +// } +// +// #[tokio::test] +// fn test_commit() -> Result<()> { +// let dir = &new_dir(); +// git_init(dir)?; +// +// new_file(&dir.join("foo.txt"), "foo"); +// new_file(&dir.join("bar.txt"), "bar"); +// +// assert_eq!( +// git_status(dir).await?.entries, +// vec![ +// GitStatusEntry { +// rela_path: "bar.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("bar".to_string()), +// }, +// GitStatusEntry { +// rela_path: "foo.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("foo".to_string()), +// }, +// ] +// ); +// +// git_add(dir, Path::new("foo.txt"))?; +// git_commit(dir, "This is my message")?; +// +// assert_eq!( +// git_status(dir).await?.entries, +// vec![ +// GitStatusEntry { +// rela_path: "bar.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("bar".to_string()), +// }, +// GitStatusEntry { +// rela_path: "foo.txt".to_string(), +// status: GitStatus::Current, +// staged: false, +// prev: Some("foo".to_string()), +// next: Some("foo".to_string()), +// }, +// ] +// ); +// +// new_file(&dir.join("foo.txt"), "foo foo"); +// git_add(dir, Path::new("foo.txt"))?; +// assert_eq!( +// git_status(dir).await?.entries, +// vec![ +// GitStatusEntry { +// rela_path: "bar.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("bar".to_string()), +// }, +// GitStatusEntry { +// rela_path: "foo.txt".to_string(), +// status: GitStatus::Modified, +// staged: true, +// prev: Some("foo".to_string()), +// next: Some("foo foo".to_string()), +// }, +// ] +// ); +// Ok(()) +// } +// +// #[tokio::test] +// async fn test_add_removed_file() -> Result<()> { +// let dir = &new_dir(); +// git_init(dir)?; +// +// let foo_path = &dir.join("foo.txt"); +// let bar_path = &dir.join("bar.txt"); +// +// new_file(foo_path, "foo"); +// new_file(bar_path, "bar"); +// +// git_add(dir, Path::new("foo.txt"))?; +// git_commit(dir, "Initial commit")?; +// +// remove_file(foo_path)?; +// assert_eq!( +// git_status(dir).await?.entries, +// vec![ +// GitStatusEntry { +// rela_path: "bar.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("bar".to_string()), +// }, +// GitStatusEntry { +// rela_path: "foo.txt".to_string(), +// status: GitStatus::Removed, +// staged: false, +// prev: Some("foo".to_string()), +// next: None, +// }, +// ], +// ); +// +// git_add(dir, Path::new("foo.txt"))?; +// assert_eq!( +// git_status(dir).await?.entries, +// vec![ +// GitStatusEntry { +// rela_path: "bar.txt".to_string(), +// status: GitStatus::Added, +// staged: false, +// prev: None, +// next: Some("bar".to_string()), +// }, +// GitStatusEntry { +// rela_path: "foo.txt".to_string(), +// status: GitStatus::Removed, +// staged: true, +// prev: Some("foo".to_string()), +// next: None, +// }, +// ], +// ); +// Ok(()) +// } +// +// #[tokio::test] +// fn test_log_empty() -> Result<()> { +// let dir = &new_dir(); +// git_init(dir)?; +// +// let log = git_log(dir)?; +// assert_eq!(log.len(), 0); +// Ok(()) +// } +// +// #[test] +// fn test_log() -> Result<()> { +// let dir = &new_dir(); +// git_init(dir)?; +// +// new_file(&dir.join("foo.txt"), "foo"); +// new_file(&dir.join("bar.txt"), "bar"); +// +// git_add(dir, Path::new("foo.txt"))?; +// git_commit(dir, "This is my message")?; +// +// let log = git_log(dir)?; +// assert_eq!(log.len(), 1); +// assert_eq!(log.get(0).unwrap().message, Some("This is my message".to_string())); +// Ok(()) +// } +// } diff --git a/src-tauri/yaak-git/src/lib.rs b/src-tauri/yaak-git/src/lib.rs new file mode 100644 index 00000000..e2250ea5 --- /dev/null +++ b/src-tauri/yaak-git/src/lib.rs @@ -0,0 +1,36 @@ +use crate::commands::{add, branch, checkout, commit, delete_branch, initialize, log, merge_branch, pull, push, status, unstage}; +use tauri::{ + generate_handler, + plugin::{Builder, TauriPlugin}, + Runtime, +}; + +mod branch; +mod callbacks; +mod commands; +mod error; +mod git; +mod merge; +mod pull; +mod push; +mod repository; +mod util; + +pub fn init() -> TauriPlugin { + Builder::new("yaak-git") + .invoke_handler(generate_handler![ + add, + branch, + checkout, + commit, + delete_branch, + initialize, + log, + merge_branch, + pull, + push, + status, + unstage + ]) + .build() +} diff --git a/src-tauri/yaak-git/src/merge.rs b/src-tauri/yaak-git/src/merge.rs new file mode 100644 index 00000000..2c621141 --- /dev/null +++ b/src-tauri/yaak-git/src/merge.rs @@ -0,0 +1,135 @@ +use crate::error::Error::MergeConflicts; +use crate::util::bytes_to_string; +use git2::{AnnotatedCommit, Branch, IndexEntry, Reference, Repository}; +use log::{debug, info}; + +pub(crate) fn do_merge( + repo: &Repository, + local_branch: &Branch, + commit_to_merge: &AnnotatedCommit, +) -> crate::error::Result<()> { + debug!("Merging remote branches"); + let analysis = repo.merge_analysis(&[&commit_to_merge])?; + + if analysis.0.is_fast_forward() { + let refname = bytes_to_string(local_branch.get().name_bytes())?; + match repo.find_reference(&refname) { + Ok(mut r) => { + merge_fast_forward(repo, &mut r, &commit_to_merge)?; + } + Err(_) => { + // The branch doesn't exist, so set the reference to the commit directly. Usually + // this is because you are pulling into an empty repository. + repo.reference( + &refname, + commit_to_merge.id(), + true, + &format!("Setting {} to {}", refname, commit_to_merge.id()), + )?; + repo.set_head(&refname)?; + repo.checkout_head(Some( + git2::build::CheckoutBuilder::default() + .allow_conflicts(true) + .conflict_style_merge(true) + .force(), + ))?; + } + }; + } else if analysis.0.is_normal() { + let head_commit = repo.reference_to_annotated_commit(&repo.head()?)?; + merge_normal(repo, &head_commit, commit_to_merge)?; + } else { + debug!("Skipping merge. Nothing to do") + } + + Ok(()) +} + +pub(crate) fn merge_fast_forward( + repo: &Repository, + local_reference: &mut Reference, + remote_commit: &AnnotatedCommit, +) -> crate::error::Result<()> { + info!("Performing fast forward"); + let name = match local_reference.name() { + Some(s) => s.to_string(), + None => String::from_utf8_lossy(local_reference.name_bytes()).to_string(), + }; + let msg = format!("Fast-Forward: Setting {} to id: {}", name, remote_commit.id()); + local_reference.set_target(remote_commit.id(), &msg)?; + repo.set_head(&name)?; + repo.checkout_head(Some( + git2::build::CheckoutBuilder::default() + // For some reason, the force is required to make the working directory actually get + // updated I suspect we should be adding some logic to handle dirty working directory + // states, but this is just an example so maybe not. + .force(), + ))?; + Ok(()) +} + +pub(crate) fn merge_normal( + repo: &Repository, + local: &AnnotatedCommit, + remote: &AnnotatedCommit, +) -> crate::error::Result<()> { + info!("Performing normal merge"); + let local_tree = repo.find_commit(local.id())?.tree()?; + let remote_tree = repo.find_commit(remote.id())?.tree()?; + let ancestor = repo.find_commit(repo.merge_base(local.id(), remote.id())?)?.tree()?; + + let mut idx = repo.merge_trees(&ancestor, &local_tree, &remote_tree, None)?; + + if idx.has_conflicts() { + let conflicts = idx.conflicts()?; + for conflict in conflicts { + if let Ok(conflict) = conflict { + print_conflict(&conflict); + } + } + return Err(MergeConflicts); + } + + let result_tree = repo.find_tree(idx.write_tree_to(repo)?)?; + // now create the merge commit + let msg = format!("Merge: {} into {}", remote.id(), local.id()); + let sig = repo.signature()?; + let local_commit = repo.find_commit(local.id())?; + let remote_commit = repo.find_commit(remote.id())?; + + // Do our merge commit and set current branch head to that commit. + let _merge_commit = repo.commit( + Some("HEAD"), + &sig, + &sig, + &msg, + &result_tree, + &[&local_commit, &remote_commit], + )?; + + // Set working tree to match head. + repo.checkout_head(None)?; + + Ok(()) +} + +fn print_conflict(conflict: &git2::IndexConflict) { + let ancestor = conflict.ancestor.as_ref().map(path_from_index_entry); + let ours = conflict.our.as_ref().map(path_from_index_entry); + let theirs = conflict.their.as_ref().map(path_from_index_entry); + + println!("Conflict detected:"); + if let Some(path) = ancestor { + println!(" Common ancestor: {:?}", path); + } + if let Some(path) = ours { + println!(" Ours: {:?}", path); + } + if let Some(path) = theirs { + println!(" Theirs: {:?}", path); + } +} + +fn path_from_index_entry(entry: &IndexEntry) -> String { + String::from_utf8_lossy(entry.path.as_slice()).into_owned() +} diff --git a/src-tauri/yaak-git/src/pull.rs b/src-tauri/yaak-git/src/pull.rs new file mode 100644 index 00000000..b675b92e --- /dev/null +++ b/src-tauri/yaak-git/src/pull.rs @@ -0,0 +1,54 @@ +use crate::callbacks::default_callbacks; +use crate::error::Error::NoActiveBranch; +use crate::error::Result; +use crate::merge::do_merge; +use crate::repository::open_repo; +use crate::util::{bytes_to_string, get_current_branch}; +use git2::{FetchOptions, ProxyOptions}; +use log::debug; +use serde::{Deserialize, Serialize}; +use std::path::Path; +use ts_rs::TS; + +#[derive(Debug, Clone, Serialize, Deserialize, TS, PartialEq)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "gen_git.ts")] +pub(crate) struct PullResult { + received_bytes: usize, + received_objects: usize, +} + +pub(crate) fn git_pull(dir: &Path) -> Result { + let repo = open_repo(dir)?; + + let branch = get_current_branch(&repo)?.ok_or(NoActiveBranch)?; + let branch_ref = branch.get(); + let branch_ref = bytes_to_string(branch_ref.name_bytes())?; + + let remote_name = repo.branch_upstream_remote(&branch_ref)?; + let remote_name = bytes_to_string(&remote_name)?; + debug!("Pulling from {remote_name}"); + + let mut remote = repo.find_remote(&remote_name)?; + + let mut options = FetchOptions::new(); + let callbacks = default_callbacks(); + options.remote_callbacks(callbacks); + + let mut proxy = ProxyOptions::new(); + proxy.auto(); + options.proxy_options(proxy); + + remote.fetch(&[&branch_ref], Some(&mut options), None)?; + + let stats = remote.stats(); + + let fetch_head = repo.find_reference("FETCH_HEAD")?; + let fetch_commit = repo.reference_to_annotated_commit(&fetch_head)?; + do_merge(&repo, &branch, &fetch_commit)?; + + Ok(PullResult { + received_bytes: stats.received_bytes(), + received_objects: stats.received_objects(), + }) +} diff --git a/src-tauri/yaak-git/src/push.rs b/src-tauri/yaak-git/src/push.rs new file mode 100644 index 00000000..46d3693b --- /dev/null +++ b/src-tauri/yaak-git/src/push.rs @@ -0,0 +1,74 @@ +use crate::branch::branch_set_upstream_after_push; +use crate::callbacks::default_callbacks; +use crate::error::Result; +use crate::repository::open_repo; +use git2::{ProxyOptions, PushOptions}; +use serde::{Deserialize, Serialize}; +use std::path::Path; +use std::sync::Mutex; +use ts_rs::TS; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)] +#[serde(rename_all = "snake_case")] +#[ts(export, export_to = "gen_git.ts")] +pub(crate) enum PushType { + Branch, + Tag, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)] +#[serde(rename_all = "snake_case")] +#[ts(export, export_to = "gen_git.ts")] +pub(crate) enum PushResult { + Success, + NothingToPush, +} + +pub(crate) fn git_push(dir: &Path) -> Result { + let repo = open_repo(dir)?; + let head = repo.head()?; + let branch = head.shorthand().unwrap(); + let mut remote = repo.find_remote("origin")?; + + let mut options = PushOptions::new(); + options.packbuilder_parallelism(0); + + let push_result = Mutex::new(PushResult::NothingToPush); + + let mut callbacks = default_callbacks(); + callbacks.push_transfer_progress(|_current, _total, _bytes| { + let mut push_result = push_result.lock().unwrap(); + *push_result = PushResult::Success; + }); + + options.remote_callbacks(default_callbacks()); + + let mut proxy = ProxyOptions::new(); + proxy.auto(); + options.proxy_options(proxy); + + // Push the current branch + let force = false; + let delete = false; + let branch_modifier = match (force, delete) { + (true, true) => "+:", + (false, true) => ":", + (true, false) => "+", + (false, false) => "", + }; + + let ref_type = PushType::Branch; + + let ref_type = match ref_type { + PushType::Branch => "heads", + PushType::Tag => "tags", + }; + + let refspec = format!("{branch_modifier}refs/{ref_type}/{branch}"); + remote.push(&[refspec], Some(&mut options))?; + + branch_set_upstream_after_push(&repo, branch)?; + + let push_result = push_result.lock().unwrap(); + Ok(push_result.clone()) +} diff --git a/src-tauri/yaak-git/src/repository.rs b/src-tauri/yaak-git/src/repository.rs new file mode 100644 index 00000000..aeb05fcc --- /dev/null +++ b/src-tauri/yaak-git/src/repository.rs @@ -0,0 +1,11 @@ +use std::path::Path; +use crate::error::Error::{GitRepoNotFound, GitUnknown}; + +pub(crate) fn open_repo(dir: &Path) -> crate::error::Result { + match git2::Repository::discover(dir) { + Ok(r) => Ok(r), + Err(e) if e.code() == git2::ErrorCode::NotFound => Err(GitRepoNotFound(dir.to_path_buf())), + Err(e) => Err(GitUnknown(e)), + } +} + diff --git a/src-tauri/yaak-git/src/util.rs b/src-tauri/yaak-git/src/util.rs new file mode 100644 index 00000000..8a710e2a --- /dev/null +++ b/src-tauri/yaak-git/src/util.rs @@ -0,0 +1,107 @@ +use crate::error::Error::{GenericError, NoDefaultRemoteFound}; +use crate::error::Result; +use git2::{Branch, BranchType, Repository}; +use std::env; +use std::path::{Path, PathBuf}; + +const DEFAULT_REMOTE_NAME: &str = "origin"; + +pub(crate) fn find_ssh_key() -> Option { + let home_dir = env::var("HOME").ok()?; + let key_paths = [ + format!("{}/.ssh/id_ed25519", home_dir), + format!("{}/.ssh/id_rsa", home_dir), + format!("{}/.ssh/id_ecdsa", home_dir), + format!("{}/.ssh/id_dsa", home_dir), + ]; + + for key_path in key_paths.iter() { + let path = Path::new(key_path); + if path.exists() { + return Some(path.to_path_buf()); + } + } + None +} + +pub(crate) fn get_current_branch(repo: &Repository) -> Result> { + for b in repo.branches(None)? { + let branch = b?.0; + if branch.is_head() { + return Ok(Some(branch)); + } + } + Ok(None) +} + +pub(crate) fn list_branch_names(repo: &Repository) -> Result> { + let mut branches = Vec::new(); + for branch in repo.branches(Some(BranchType::Local))? { + let branch = branch?.0; + let name = branch.name_bytes()?; + let name = bytes_to_string(name)?; + branches.push(name); + } + Ok(branches) +} + +pub(crate) fn get_branch_by_name<'s>(repo: &'s Repository, name: &str) -> Result> { + Ok(repo.find_branch(name, BranchType::Local)?) +} + +pub(crate) fn bytes_to_string(bytes: &[u8]) -> Result { + Ok(String::from_utf8(bytes.to_vec())?) +} + +pub(crate) fn get_default_remote_for_push_in_repo(repo: &Repository) -> Result { + let config = repo.config()?; + + let branch = get_current_branch(repo)?; + + if let Some(branch) = branch { + let remote_name = bytes_to_string(branch.name_bytes()?)?; + + let entry_name = format!("branch.{}.pushRemote", &remote_name); + + if let Ok(entry) = config.get_entry(&entry_name) { + return bytes_to_string(entry.value_bytes()); + } + + if let Ok(entry) = config.get_entry("remote.pushDefault") { + return bytes_to_string(entry.value_bytes()); + } + + let entry_name = format!("branch.{}.remote", &remote_name); + + if let Ok(entry) = config.get_entry(&entry_name) { + return bytes_to_string(entry.value_bytes()); + } + } + + get_default_remote_in_repo(repo) +} + +pub(crate) fn get_default_remote_in_repo(repo: &Repository) -> Result { + let remotes = repo.remotes()?; + + // if `origin` exists return that + let found_origin = remotes.iter().any(|r| r.is_some_and(|r| r == DEFAULT_REMOTE_NAME)); + if found_origin { + return Ok(DEFAULT_REMOTE_NAME.into()); + } + + // if only one remote exists pick that + if remotes.len() == 1 { + let first_remote = remotes + .iter() + .next() + .flatten() + .map(String::from) + .ok_or_else(|| GenericError("no remote found".into()))?; + + return Ok(first_remote); + } + + // inconclusive + Err(NoDefaultRemoteFound) +} diff --git a/src-tauri/yaak-models/src/models.rs b/src-tauri/yaak-models/src/models.rs index 5d7d7d86..6320a455 100644 --- a/src-tauri/yaak-models/src/models.rs +++ b/src-tauri/yaak-models/src/models.rs @@ -147,7 +147,7 @@ impl<'s> TryFrom<&Row<'s>> for Settings { } } -#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)] #[serde(default, rename_all = "camelCase")] #[ts(export, export_to = "gen_models.ts")] pub struct Workspace { @@ -325,7 +325,7 @@ impl<'s> TryFrom<&Row<'s>> for CookieJar { } } -#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)] #[serde(default, rename_all = "camelCase")] #[ts(export, export_to = "gen_models.ts")] pub struct Environment { @@ -374,7 +374,7 @@ impl<'s> TryFrom<&Row<'s>> for Environment { } } -#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)] #[serde(default, rename_all = "camelCase")] #[ts(export, export_to = "gen_models.ts")] pub struct EnvironmentVariable { @@ -387,7 +387,7 @@ pub struct EnvironmentVariable { pub id: Option, } -#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)] #[serde(default, rename_all = "camelCase")] #[ts(export, export_to = "gen_models.ts")] pub struct Folder { @@ -438,7 +438,7 @@ impl<'s> TryFrom<&Row<'s>> for Folder { } } -#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)] #[serde(default, rename_all = "camelCase")] #[ts(export, export_to = "gen_models.ts")] pub struct HttpRequestHeader { @@ -451,7 +451,7 @@ pub struct HttpRequestHeader { pub id: Option, } -#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)] #[serde(default, rename_all = "camelCase")] #[ts(export, export_to = "gen_models.ts")] pub struct HttpUrlParameter { @@ -464,7 +464,7 @@ pub struct HttpUrlParameter { pub id: Option, } -#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)] #[serde(default, rename_all = "camelCase")] #[ts(export, export_to = "gen_models.ts")] pub struct HttpRequest { @@ -637,7 +637,7 @@ impl Default for WebsocketMessageType { } } -#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)] #[serde(default, rename_all = "camelCase")] #[ts(export, export_to = "gen_models.ts")] pub struct WebsocketRequest { @@ -895,7 +895,7 @@ impl HttpResponse { } } -#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)] #[serde(default, rename_all = "camelCase")] #[ts(export, export_to = "gen_models.ts")] pub struct GrpcMetadataEntry { @@ -908,7 +908,7 @@ pub struct GrpcMetadataEntry { pub id: Option, } -#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, TS)] #[serde(default, rename_all = "camelCase")] #[ts(export, export_to = "gen_models.ts")] pub struct GrpcRequest { diff --git a/src-tauri/yaak-models/src/queries.rs b/src-tauri/yaak-models/src/queries.rs index 9ee53565..1420f951 100644 --- a/src-tauri/yaak-models/src/queries.rs +++ b/src-tauri/yaak-models/src/queries.rs @@ -2569,20 +2569,22 @@ pub async fn batch_upsert( let mut imported_resources = BatchUpsertResult::default(); if workspaces.len() > 0 { + info!("Batch inserting {} workspaces", workspaces.len()); for v in workspaces { let x = upsert_workspace(&window, v, update_source).await?; imported_resources.workspaces.push(x.clone()); } - info!("Imported {} workspaces", imported_resources.workspaces.len()); } if environments.len() > 0 { while imported_resources.environments.len() < environments.len() { for v in environments.clone() { - if let Some(fid) = v.environment_id.clone() { + if let Some(id) = v.environment_id.clone() { + let has_parent_to_import = environments.iter().find(|m| m.id == id).is_some(); let imported_parent = - imported_resources.environments.iter().find(|f| f.id == fid); - if imported_parent.is_none() { + imported_resources.environments.iter().find(|m| m.id == id); + // If there's also a parent to upsert, wait for that one + if imported_parent.is_none() && has_parent_to_import { continue; } } @@ -2599,9 +2601,11 @@ pub async fn batch_upsert( if folders.len() > 0 { while imported_resources.folders.len() < folders.len() { for v in folders.clone() { - if let Some(fid) = v.folder_id.clone() { - let imported_parent = imported_resources.folders.iter().find(|f| f.id == fid); - if imported_parent.is_none() { + if let Some(id) = v.folder_id.clone() { + let has_parent_to_import = folders.iter().find(|m| m.id == id).is_some(); + let imported_parent = imported_resources.folders.iter().find(|m| m.id == id); + // If there's also a parent to upsert, wait for that one + if imported_parent.is_none() && has_parent_to_import { continue; } } diff --git a/src-tauri/yaak-sync/bindings/git.ts b/src-tauri/yaak-sync/bindings/git.ts new file mode 100644 index 00000000..50b23968 --- /dev/null +++ b/src-tauri/yaak-sync/bindings/git.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type GitCommit = { author: string, when: string, message: string | null, }; + +export type GitStatus = "added" | "conflict" | "current" | "modified" | "removed" | "renamed" | "type_change"; + +export type GitStatusEntry = { relaPath: string, status: GitStatus, staged: boolean, prev: string | null, next: string | null, }; diff --git a/src-tauri/yaak-sync/index.ts b/src-tauri/yaak-sync/index.ts index 88096765..233812bf 100644 --- a/src-tauri/yaak-sync/index.ts +++ b/src-tauri/yaak-sync/index.ts @@ -3,6 +3,8 @@ import { emit } from '@tauri-apps/api/event'; import { SyncOp } from './bindings/gen_sync'; import { WatchEvent, WatchResult } from './bindings/gen_watch'; +export * from './bindings/gen_models'; + export async function calculateSync(workspaceId: string, syncDir: string) { return invoke('plugin:yaak-sync|calculate', { workspaceId, @@ -27,20 +29,53 @@ export function watchWorkspaceFiles( syncDir: string, callback: (e: WatchEvent) => void, ) { + console.log('Watching workspace files', workspaceId, syncDir); const channel = new Channel(); channel.onmessage = callback; - const promise = invoke('plugin:yaak-sync|watch', { + const unlistenPromise = invoke('plugin:yaak-sync|watch', { workspaceId, syncDir, channel, }); - return () => { - promise - .then(({ unlistenEvent }) => { - console.log('Cancelling workspace watch', workspaceId, unlistenEvent); - return emit(unlistenEvent); + unlistenPromise.then(({ unlistenEvent }) => { + addWatchKey(unlistenEvent); + }); + + return () => + unlistenPromise + .then(async ({ unlistenEvent }) => { + console.log('Unwatching workspace files', workspaceId, syncDir); + unlistenToWatcher(unlistenEvent); }) .catch(console.error); - }; } + +function unlistenToWatcher(unlistenEvent: string) { + emit(unlistenEvent).then(() => { + removeWatchKey(unlistenEvent); + }); +} + +function getWatchKeys() { + return sessionStorage.getItem('workspace-file-watchers')?.split(',').filter(Boolean) ?? []; +} + +function setWatchKeys(keys: string[]) { + sessionStorage.setItem('workspace-file-watchers', keys.join(',')); +} + +function addWatchKey(key: string) { + const keys = getWatchKeys(); + setWatchKeys([...keys, key]); +} + +function removeWatchKey(key: string) { + const keys = getWatchKeys(); + setWatchKeys(keys.filter((k) => k !== key)); +} + +// On page load, unlisten to all zombie watchers +const keys = getWatchKeys(); +console.log('Unsubscribing to zombie file watchers', keys); +keys.forEach(unlistenToWatcher); diff --git a/src-tauri/yaak-sync/src/lib.rs b/src-tauri/yaak-sync/src/lib.rs index 1f6a93cc..4935a996 100644 --- a/src-tauri/yaak-sync/src/lib.rs +++ b/src-tauri/yaak-sync/src/lib.rs @@ -6,8 +6,8 @@ use tauri::{ }; mod commands; -mod error; -mod models; +pub mod error; +pub mod models; mod sync; mod watch; diff --git a/src-tauri/yaak-sync/src/models.rs b/src-tauri/yaak-sync/src/models.rs index 54257374..1463d271 100644 --- a/src-tauri/yaak-sync/src/models.rs +++ b/src-tauri/yaak-sync/src/models.rs @@ -3,14 +3,14 @@ use crate::error::Result; use chrono::NaiveDateTime; use serde::{Deserialize, Serialize}; use sha1::{Digest, Sha1}; +use std::fs; use std::path::Path; -use tokio::fs; use ts_rs::TS; use yaak_models::models::{ AnyModel, Environment, Folder, GrpcRequest, HttpRequest, WebsocketRequest, Workspace, }; -#[derive(Debug, Clone, Serialize, Deserialize, TS)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)] #[serde(rename_all = "snake_case", tag = "type")] #[ts(export, export_to = "gen_models.ts")] pub enum SyncModel { @@ -23,12 +23,10 @@ pub enum SyncModel { } impl SyncModel { - pub async fn from_file(file_path: &Path) -> Result, String)>> { - let content = match fs::read(file_path).await { - Ok(c) => c, - Err(_) => return Ok(None), - }; - + pub fn from_bytes( + content: Vec, + file_path: &Path, + ) -> Result, String)>> { let mut hasher = Sha1::new(); hasher.update(&content); let checksum = hex::encode(hasher.finalize()); @@ -39,10 +37,20 @@ impl SyncModel { } else if ext == "json" { Ok(Some((serde_json::from_reader(content.as_slice())?, content, checksum))) } else { - Err(InvalidSyncFile(file_path.to_str().unwrap().to_string())) + let p = file_path.to_str().unwrap().to_string(); + Err(InvalidSyncFile(format!("Unknown file extension {p}"))) } } + pub fn from_file(file_path: &Path) -> Result, String)>> { + let content = match fs::read(file_path) { + Ok(c) => c, + Err(_) => return Ok(None), + }; + + Self::from_bytes(content, file_path) + } + pub fn to_file_contents(&self, rel_path: &Path) -> Result<(Vec, String)> { let ext = rel_path.extension().unwrap_or_default(); let content = if ext == "yaml" || ext == "yml" { diff --git a/src-tauri/yaak-sync/src/sync.rs b/src-tauri/yaak-sync/src/sync.rs index 43e26b9f..ce127342 100644 --- a/src-tauri/yaak-sync/src/sync.rs +++ b/src-tauri/yaak-sync/src/sync.rs @@ -1,4 +1,3 @@ -use crate::error::Error::InvalidSyncFile; use crate::error::Result; use crate::models::SyncModel; use chrono::Utc; @@ -164,13 +163,12 @@ pub(crate) async fn get_fs_candidates(dir: &Path) -> Result> { }; let path = dir_entry.path(); - let (model, _, checksum) = match SyncModel::from_file(&path).await { + let (model, _, checksum) = match SyncModel::from_file(&path) { Ok(Some(m)) => m, Ok(None) => continue, - Err(InvalidSyncFile(_)) => continue, Err(e) => { warn!("Failed to read sync file {e}"); - continue; + return Err(e); } }; @@ -315,7 +313,7 @@ pub(crate) async fn apply_sync_ops( } debug!( - "Sync ops {}", + "Applying sync ops {}", sync_ops.iter().map(|op| op.to_string()).collect::>().join(", ") ); let mut sync_state_ops = Vec::new(); diff --git a/src-tauri/yaak-sync/src/watch.rs b/src-tauri/yaak-sync/src/watch.rs index 9d29ec6d..e155bc4b 100644 --- a/src-tauri/yaak-sync/src/watch.rs +++ b/src-tauri/yaak-sync/src/watch.rs @@ -45,9 +45,19 @@ pub(crate) async fn watch_directory( Some(event_res) = async_rx.recv() => { match event_res { Ok(event) => { + // Filter out any ignored directories and see if we still get a result + let paths = event.paths.into_iter() + .map(|p| p.strip_prefix(&dir).unwrap().to_path_buf()) + .filter(|p| !p.starts_with(".git") && !p.starts_with("node_modules")) + .collect::>(); + + if paths.is_empty() { + continue; + } + channel .send(WatchEvent { - paths: event.paths, + paths, kind: format!("{:?}", event.kind), }) .expect("Failed to send watch event"); diff --git a/src-tauri/yaak-ws/src/cmd.rs b/src-tauri/yaak-ws/src/commands.rs similarity index 100% rename from src-tauri/yaak-ws/src/cmd.rs rename to src-tauri/yaak-ws/src/commands.rs diff --git a/src-tauri/yaak-ws/src/lib.rs b/src-tauri/yaak-ws/src/lib.rs index 92aeb7e2..48026a8d 100644 --- a/src-tauri/yaak-ws/src/lib.rs +++ b/src-tauri/yaak-ws/src/lib.rs @@ -1,10 +1,10 @@ -mod cmd; +mod commands; mod connect; mod error; mod manager; mod render; -use crate::cmd::{ +use crate::commands::{ connect, close, delete_connection, delete_connections, delete_request, duplicate_request, list_connections, list_events, list_requests, send, upsert_request, }; diff --git a/src-web/commands/commands.tsx b/src-web/commands/commands.tsx index 7bf38884..259a914e 100644 --- a/src-web/commands/commands.tsx +++ b/src-web/commands/commands.tsx @@ -48,10 +48,10 @@ export const createFolder = createFastMutation< export const syncWorkspace = createFastMutation< void, void, - { workspaceId: string; syncDir: string } + { workspaceId: string; syncDir: string; force?: boolean } >({ mutationKey: [], - mutationFn: async ({ workspaceId, syncDir }) => { + mutationFn: async ({ workspaceId, syncDir, force }) => { const ops = (await calculateSync(workspaceId, syncDir)) ?? []; if (ops.length === 0) { console.log('Nothing to sync', workspaceId, syncDir); @@ -72,66 +72,68 @@ export const syncWorkspace = createFastMutation< console.log('Filesystem changes detected', { dbOps, ops }); - const confirmed = await showConfirm({ - id: 'commit-sync', - title: 'Filesystem Changes Detected', - confirmText: 'Apply Changes', - description: ( - - {isDeletingWorkspace && ( - - 🚨 Changes contain a workspace deletion! - - )} -

- {pluralizeCount('file', dbOps.length)} in the directory have changed. Do you want to - apply the updates to your workspace? -

-
- - - - - - - - - {dbOps.map((op, i) => { - let name = ''; - let label = ''; - let color = ''; - - if (op.type === 'dbCreate') { - label = 'create'; - name = fallbackRequestName(op.fs.model); - color = 'text-success'; - } else if (op.type === 'dbUpdate') { - label = 'update'; - name = fallbackRequestName(op.fs.model); - color = 'text-info'; - } else if (op.type === 'dbDelete') { - label = 'delete'; - name = fallbackRequestName(op.model); - color = 'text-danger'; - } else { - return null; - } - - return ( - - - + const confirmed = force + ? true + : await showConfirm({ + id: 'commit-sync', + title: 'Filesystem Changes Detected', + confirmText: 'Apply Changes', + description: ( + + {isDeletingWorkspace && ( + + 🚨 Changes contain a workspace deletion! + + )} +

+ {pluralizeCount('file', dbOps.length)} in the directory have changed. Do you want to + apply the updates to your workspace? +

+
+
NameOperation
{name} - {label} -
+ + + + - ); - })} - -
NameOperation
-
-
- ), - }); + + + {dbOps.map((op, i) => { + let name = ''; + let label = ''; + let color = ''; + + if (op.type === 'dbCreate') { + label = 'create'; + name = fallbackRequestName(op.fs.model); + color = 'text-success'; + } else if (op.type === 'dbUpdate') { + label = 'update'; + name = fallbackRequestName(op.fs.model); + color = 'text-info'; + } else if (op.type === 'dbDelete') { + label = 'delete'; + name = fallbackRequestName(op.model); + color = 'text-danger'; + } else { + return null; + } + + return ( + + {name} + + {label} + + + ); + })} + + + + + ), + }); if (confirmed) { await applySync(workspaceId, syncDir, ops); } diff --git a/src-web/commands/deleteWebsocketRequest.tsx b/src-web/commands/deleteWebsocketRequest.tsx index 8e4b63c2..1245633d 100644 --- a/src-web/commands/deleteWebsocketRequest.tsx +++ b/src-web/commands/deleteWebsocketRequest.tsx @@ -1,18 +1,17 @@ -import type {WebsocketRequest} from "@yaakapp-internal/models"; +import type { WebsocketRequest } from '@yaakapp-internal/models'; import { deleteWebsocketRequest as cmdDeleteWebsocketRequest } from '@yaakapp-internal/ws'; import { InlineCode } from '../components/core/InlineCode'; import { createFastMutation } from '../hooks/useFastMutation'; import { trackEvent } from '../lib/analytics'; -import { showConfirm } from '../lib/confirm'; +import { showConfirmDelete } from '../lib/confirm'; import { fallbackRequestName } from '../lib/fallbackRequestName'; export const deleteWebsocketRequest = createFastMutation({ mutationKey: ['delete_websocket_request'], mutationFn: async (request: WebsocketRequest) => { - const confirmed = await showConfirm({ + const confirmed = await showConfirmDelete({ id: 'delete-websocket-request', title: 'Delete WebSocket Request', - variant: 'delete', description: ( <> Permanently delete {fallbackRequestName(request)}? diff --git a/src-web/commands/openSettings.ts b/src-web/commands/openSettings.ts new file mode 100644 index 00000000..5a47fb3c --- /dev/null +++ b/src-web/commands/openSettings.ts @@ -0,0 +1,27 @@ +import { SettingsTab } from '../components/Settings/SettingsTab'; +import { getActiveWorkspaceId } from '../hooks/useActiveWorkspace'; +import { createFastMutation } from '../hooks/useFastMutation'; +import { trackEvent } from '../lib/analytics'; +import { router } from '../lib/router'; +import { invokeCmd } from '../lib/tauri'; + +export const openSettings = createFastMutation({ + mutationKey: ['open_settings'], + mutationFn: async function (tab) { + const workspaceId = getActiveWorkspaceId(); + if (workspaceId == null) return; + + trackEvent('dialog', 'show', { id: 'settings', tab: `${tab}` }); + const location = router.buildLocation({ + to: '/workspaces/$workspaceId/settings', + params: { workspaceId }, + search: { tab: tab ?? SettingsTab.General }, + }); + await invokeCmd('cmd_new_child_window', { + url: location.href, + label: 'settings', + title: 'Yaak Settings', + innerSize: [750, 600], + }); + }, +}); diff --git a/src-web/commands/openWorkspaceSettings.tsx b/src-web/commands/openWorkspaceSettings.tsx new file mode 100644 index 00000000..0b90e70d --- /dev/null +++ b/src-web/commands/openWorkspaceSettings.tsx @@ -0,0 +1,25 @@ +import { WorkspaceSettingsDialog } from '../components/WorkspaceSettingsDialog'; +import { getActiveWorkspaceId } from '../hooks/useActiveWorkspace'; +import { createFastMutation } from '../hooks/useFastMutation'; +import { showDialog } from '../lib/dialog'; + +export const openWorkspaceSettings = createFastMutation({ + mutationKey: ['open_workspace_settings'], + async mutationFn({ openSyncMenu }) { + const workspaceId = getActiveWorkspaceId(); + showDialog({ + id: 'workspace-settings', + title: 'Workspace Settings', + size: 'md', + render({ hide }) { + return ( + + ); + }, + }); + }, +}); diff --git a/src-web/components/CommandPaletteDialog.tsx b/src-web/components/CommandPaletteDialog.tsx index ecdac00a..eaf3980f 100644 --- a/src-web/components/CommandPaletteDialog.tsx +++ b/src-web/components/CommandPaletteDialog.tsx @@ -3,6 +3,7 @@ import { fuzzyFilter } from 'fuzzbunny'; import type { KeyboardEvent, ReactNode } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { createFolder } from '../commands/commands'; +import { openSettings } from '../commands/openSettings'; import { switchWorkspace } from '../commands/switchWorkspace'; import { useActiveCookieJar } from '../hooks/useActiveCookieJar'; import { useActiveEnvironment } from '../hooks/useActiveEnvironment'; @@ -17,7 +18,6 @@ import { useEnvironments } from '../hooks/useEnvironments'; import type { HotkeyAction } from '../hooks/useHotKey'; import { useHotKey } from '../hooks/useHotKey'; import { useHttpRequestActions } from '../hooks/useHttpRequestActions'; -import { useOpenSettings } from '../hooks/useOpenSettings'; import { useRecentEnvironments } from '../hooks/useRecentEnvironments'; import { useRecentRequests } from '../hooks/useRecentRequests'; import { useRecentWorkspaces } from '../hooks/useRecentWorkspaces'; @@ -71,7 +71,6 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) { const [recentRequests] = useRecentRequests(); const [, setSidebarHidden] = useSidebarHidden(); const { baseEnvironment } = useEnvironments(); - const { mutate: openSettings } = useOpenSettings(); const { mutate: createHttpRequest } = useCreateHttpRequest(); const { mutate: createGrpcRequest } = useCreateGrpcRequest(); const { mutate: createEnvironment } = useCreateEnvironment(); @@ -85,7 +84,7 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) { key: 'settings.open', label: 'Open Settings', action: 'settings.show', - onSelect: openSettings, + onSelect: () => openSettings.mutate(null), }, { key: 'app.create', @@ -193,7 +192,6 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) { createWorkspace, deleteRequest, httpRequestActions, - openSettings, renameRequest, sendRequest, setSidebarHidden, @@ -406,7 +404,7 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) { hideLabel leftSlot={
- +
} name="command" diff --git a/src-web/components/CookieDropdown.tsx b/src-web/components/CookieDropdown.tsx index 3044e30a..b57a4eb1 100644 --- a/src-web/components/CookieDropdown.tsx +++ b/src-web/components/CookieDropdown.tsx @@ -7,7 +7,7 @@ import { useDeleteCookieJar } from '../hooks/useDeleteCookieJar'; import { useUpdateCookieJar } from '../hooks/useUpdateCookieJar'; import { showDialog } from '../lib/dialog'; import { showPrompt } from '../lib/prompt'; -import {setWorkspaceSearchParams} from "../lib/setWorkspaceSearchParams"; +import { setWorkspaceSearchParams } from '../lib/setWorkspaceSearchParams'; import { CookieDialog } from './CookieDialog'; import { Dropdown, type DropdownItem } from './core/Dropdown'; import { Icon } from './core/Icon'; @@ -76,7 +76,7 @@ export const CookieDropdown = memo(function CookieDropdown() { label: 'Delete', leftSlot: , color: 'danger', - onSelect: () => deleteCookieJar.mutateAsync(), + onSelect: deleteCookieJar.mutate, }, ] : []) as DropdownItem[]), @@ -94,7 +94,7 @@ export const CookieDropdown = memo(function CookieDropdown() { return ( - + ); }); diff --git a/src-web/components/CreateWorkspaceDialog.tsx b/src-web/components/CreateWorkspaceDialog.tsx index 2ccbf4c7..2b80f4db 100644 --- a/src-web/components/CreateWorkspaceDialog.tsx +++ b/src-web/components/CreateWorkspaceDialog.tsx @@ -1,9 +1,11 @@ +import { gitInit } from '@yaakapp-internal/git'; import type { WorkspaceMeta } from '@yaakapp-internal/models'; import { useState } from 'react'; import { upsertWorkspace } from '../commands/upsertWorkspace'; import { upsertWorkspaceMeta } from '../commands/upsertWorkspaceMeta'; import { router } from '../lib/router'; import { invokeCmd } from '../lib/tauri'; +import { showErrorToast } from '../lib/toast'; import { Button } from './core/Button'; import { PlainInput } from './core/PlainInput'; import { VStack } from './core/Stacks'; @@ -15,7 +17,10 @@ interface Props { export function CreateWorkspaceDialog({ hide }: Props) { const [name, setName] = useState(''); - const [settingSyncDir, setSettingSyncDir] = useState(null); + const [syncConfig, setSyncConfig] = useState<{ + filePath: string | null; + initGit?: boolean; + }>({ filePath: null, initGit: true }); return ( ('cmd_get_workspace_meta', { workspaceId: workspace.id, }); - upsertWorkspaceMeta.mutate({ ...workspaceMeta, settingSyncDir }); + await upsertWorkspaceMeta.mutateAsync({ + ...workspaceMeta, + settingSyncDir: syncConfig.filePath, + }); + + if (syncConfig.initGit && syncConfig.filePath) { + gitInit(syncConfig.filePath).catch((err) => { + showErrorToast('git-init-error', String(err)); + }); + } // Navigate to workspace await router.navigate({ @@ -47,8 +61,8 @@ export function CreateWorkspaceDialog({ hide }: Props) { + + + + + )} + /> + + ); +} + +function TreeNodeChildren({ + node, + depth, + onCheck, +}: { + node: TreeNode | null; + depth: number; + onCheck: (node: TreeNode, checked: boolean) => void; +}) { + if (node === null) return null; + if (!isNodeRelevant(node)) return null; + + const checked = nodeCheckedStatus(node); + return ( +
0 && 'pl-1 ml-[10px] border-l border-dashed border-border-subtle', + )} + > +
+ onCheck(node, checked)} + title={ +
+ {node.model.model !== 'http_request' && + node.model.model !== 'grpc_request' && + node.model.model !== 'websocket_request' ? ( + + ) : ( + + )} +
+ {fallbackRequestName(node.model)} + {/*({node.model.model})*/} + {/*({node.status.staged ? 'Y' : 'N'})*/} +
+ {node.status.status !== 'current' && ( + + {node.status.status} + + )} +
+ } + /> +
+ + {node.children.map((childNode, i) => { + return ( + + ); + })} +
+ ); +} + +function nodeCheckedStatus(root: TreeNode): CheckboxProps['checked'] { + let numVisited = 0; + let numChecked = 0; + let numCurrent = 0; + + const visitChildren = (n: TreeNode) => { + numVisited += 1; + if (n.status.status === 'current') { + numCurrent += 1; + } else if (n.status.staged) { + numChecked += 1; + } + for (const child of n.children) { + visitChildren(child); + } + }; + + visitChildren(root); + + if (numVisited === numChecked + numCurrent) { + return true; + } else if (numChecked === 0) { + return false; + } else { + return 'indeterminate'; + } +} + +function setCheckedAndChildren( + node: TreeNode, + checked: boolean, + unstage: (args: { relaPaths: string[] }) => void, + add: (args: { relaPaths: string[] }) => void, +) { + const toAdd: string[] = []; + const toUnstage: string[] = []; + + const next = (node: TreeNode) => { + for (const child of node.children) { + next(child); + } + + if (node.status.status === 'current') { + // Nothing required + } else if (checked && !node.status.staged) { + toAdd.push(node.status.relaPath); + } else if (!checked && node.status.staged) { + toUnstage.push(node.status.relaPath); + } + }; + + next(node); + + if (toAdd.length > 0) add({ relaPaths: toAdd }); + if (toUnstage.length > 0) unstage({ relaPaths: toUnstage }); +} + +function isNodeRelevant(node: TreeNode): boolean { + if (node.status.status !== 'current') { + return true; + } + + // Recursively check children + return node.children.some((c) => isNodeRelevant(c)); +} diff --git a/src-web/components/GitDropdown.tsx b/src-web/components/GitDropdown.tsx new file mode 100644 index 00000000..b67af1af --- /dev/null +++ b/src-web/components/GitDropdown.tsx @@ -0,0 +1,406 @@ +import { gitInit, useGit } from '@yaakapp-internal/git'; +import type { WorkspaceMeta } from '@yaakapp-internal/models'; +import classNames from 'classnames'; +import type { HTMLAttributes } from 'react'; +import { forwardRef } from 'react'; +import { openWorkspaceSettings } from '../commands/openWorkspaceSettings'; +import { useActiveWorkspace } from '../hooks/useActiveWorkspace'; +import { useKeyValue } from '../hooks/useKeyValue'; +import { useWorkspaceMeta } from '../hooks/useWorkspaceMeta'; +import { sync } from '../init/sync'; +import { showConfirm, showConfirmDelete } from '../lib/confirm'; +import { showDialog } from '../lib/dialog'; +import { showPrompt } from '../lib/prompt'; +import { showErrorToast, showToast } from '../lib/toast'; +import { Banner } from './core/Banner'; +import type { DropdownItem } from './core/Dropdown'; +import { Dropdown } from './core/Dropdown'; +import { Icon } from './core/Icon'; +import { InlineCode } from './core/InlineCode'; +import { BranchSelectionDialog } from './git/BranchSelectionDialog'; +import { HistoryDialog } from './git/HistoryDialog'; +import { GitCommitDialog } from './GitCommitDialog'; + +export function GitDropdown() { + const workspaceMeta = useWorkspaceMeta(); + if (workspaceMeta == null) return null; + + if (workspaceMeta.settingSyncDir == null) { + return ; + } + + return ; +} + +function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) { + const workspace = useActiveWorkspace(); + const [{ status, log }, { branch, deleteBranch, mergeBranch, push, pull, checkout }] = + useGit(syncDir); + + if (workspace == null) { + return null; + } + + const noRepo = status.error?.includes('not found'); + if (noRepo) { + return gitInit(syncDir)} />; + } + + const tryCheckout = (branch: string, force: boolean) => { + checkout.mutate( + { branch, force }, + { + async onError(err) { + if (!force) { + // Checkout failed so ask user if they want to force it + const forceCheckout = await showConfirm({ + id: 'git-force-checkout', + title: 'Conflicts Detected', + description: + 'Your branch has conflicts. Either make a commit or force checkout to discard changes.', + confirmText: 'Force Checkout', + color: 'warning', + }); + if (forceCheckout) { + tryCheckout(branch, true); + } + } else { + // Checkout failed + showErrorToast('git-checkout-error', String(err)); + } + }, + async onSuccess() { + showToast({ + id: 'git-checkout-success', + message: ( + <> + Switched branch {branch} + + ), + color: 'success', + }); + await sync({ force: true }); + }, + }, + ); + }; + + const items: DropdownItem[] = [ + { + label: 'View History', + hidden: (log.data ?? []).length === 0, + leftSlot: , + onSelect: async () => { + showDialog({ + id: 'git-history', + size: 'md', + title: 'Commit History', + render: () => , + }); + }, + }, + { + label: 'New Branch', + leftSlot: , + async onSelect() { + const name = await showPrompt({ + id: 'git-branch-name', + title: 'Create Branch', + label: 'Branch Name', + }); + if (name) { + await branch.mutateAsync( + { branch: name }, + { + onError: (err) => { + showErrorToast('git-branch-error', String(err)); + }, + }, + ); + tryCheckout(name, false); + } + }, + }, + { + label: 'Merge Branch', + leftSlot: , + hidden: (status.data?.branches ?? []).length <= 1, + async onSelect() { + showDialog({ + id: 'git-merge', + title: 'Merge Branch', + size: 'sm', + description: ( + <> + Select a branch to merge into {status.data?.headRefShorthand} + + ), + render: ({ hide }) => ( + b !== status.data?.headRefShorthand, + )} + onCancel={hide} + onSelect={async (branch) => { + await mergeBranch.mutateAsync( + { branch, force: false }, + { + onSettled: hide, + onSuccess() { + showToast({ + id: 'git-merged-branch', + message: ( + <> + Merged {branch} into{' '} + {status.data?.headRefShorthand} + + ), + }); + sync({ force: true }); + }, + onError(err) { + showErrorToast('git-merged-branch-error', String(err)); + }, + }, + ); + }} + /> + ), + }); + }, + }, + { + label: 'Delete Branch', + leftSlot: , + hidden: (status.data?.branches ?? []).length <= 1, + color: 'danger', + async onSelect() { + const currentBranch = status.data?.headRefShorthand; + if (currentBranch == null) return; + + const confirmed = await showConfirmDelete({ + id: 'git-delete-branch', + title: 'Delete Branch', + description: ( + <> + Permanently delete {currentBranch}? + + ), + }); + if (confirmed) { + await deleteBranch.mutateAsync( + { branch: currentBranch }, + { + onError(err) { + showErrorToast('git-delete-branch-error', String(err)); + }, + async onSuccess() { + await sync({ force: true }); + }, + }, + ); + } + }, + }, + { type: 'separator' }, + { + label: 'Push', + hidden: (status.data?.origins ?? []).length === 0, + leftSlot: , + waitForOnSelect: true, + async onSelect() { + const message = await push.mutateAsync(); + if (message === 'nothing_to_push') { + showToast({ id: 'push-success', message: 'Nothing to push', color: 'info' }); + } else { + showToast({ id: 'push-success', message: 'Push successful', color: 'success' }); + } + }, + }, + { + label: 'Pull', + hidden: (status.data?.origins ?? []).length === 0, + leftSlot: , + waitForOnSelect: true, + async onSelect() { + const result = await pull.mutateAsync(undefined, { + onError(err) { + showErrorToast('git-pull-error', String(err)); + }, + }); + if (result.receivedObjects > 0) { + showToast({ + id: 'git-pull-success', + message: `Pulled ${result.receivedObjects} objects`, + color: 'success', + }); + await sync({ force: true }); + } else { + showToast({ id: 'git-pull-success', message: 'Already up to date', color: 'info' }); + } + }, + }, + { + label: 'Commit', + leftSlot: , + onSelect() { + showDialog({ + id: 'commit', + title: 'Commit Changes', + size: 'full', + className: '!max-h-[min(80vh,40rem)] !max-w-[min(50rem,90vw)]', + render: ({ hide }) => ( + + ), + }); + }, + }, + { type: 'separator', label: 'Branches', hidden: (status.data?.branches ?? []).length < 1 }, + ...(status.data?.branches ?? []).map((branch) => { + const isCurrent = status.data?.headRefShorthand === branch; + return { + label: branch, + leftSlot: , + onSelect: isCurrent ? undefined : () => tryCheckout(branch, false), + }; + }), + ]; + + return ( + + + {noRepo ? 'Configure Git' : {status.data?.headRefShorthand}} + + + + ); +} + +const GitMenuButton = forwardRef>( + function GitMenuButton({ className, ...props }: HTMLAttributes, ref) { + return ( + diff --git a/src-web/components/core/Input.tsx b/src-web/components/core/Input.tsx index f82a87f8..ddc01153 100644 --- a/src-web/components/core/Input.tsx +++ b/src-web/components/core/Input.tsx @@ -46,6 +46,7 @@ export type InputProps = Pick< required?: boolean; wrapLines?: boolean; multiLine?: boolean; + fullHeight?: boolean; stateKey: EditorProps['stateKey']; }; @@ -56,6 +57,7 @@ export const Input = forwardRef(function Input( inputWrapperClassName, defaultValue, forceUpdateKey, + fullHeight, hideLabel, label, labelClassName, @@ -148,8 +150,9 @@ export const Input = forwardRef(function Input(
(function Input( alignItems="stretch" className={classNames( containerClassName, + fullHeight && 'h-full', 'x-theme-input', 'relative w-full rounded-md text', 'border', @@ -182,6 +186,7 @@ export const Input = forwardRef(function Input( className={classNames( inputWrapperClassName, 'w-full min-w-0 px-2', + fullHeight && 'h-full', leftSlot && 'pl-0.5 -ml-2', rightSlot && 'pr-0.5 -mr-2', )} @@ -218,8 +223,11 @@ export const Input = forwardRef(function Input( setObscured((o) => !o)} diff --git a/src-web/components/core/JsonAttributeTree.tsx b/src-web/components/core/JsonAttributeTree.tsx index 5a67d3b4..743b27f5 100644 --- a/src-web/components/core/JsonAttributeTree.tsx +++ b/src-web/components/core/JsonAttributeTree.tsx @@ -104,7 +104,7 @@ export const JsonAttributeTree = ({ icon="chevron_right" className={classNames( 'left-0 absolute transition-transform flex items-center', - 'text-text-subtlest group-hover:text-text-subtle', + 'group-hover:text-text-subtle', isExpanded ? 'rotate-90' : '', )} /> diff --git a/src-web/components/core/PairOrBulkEditor.tsx b/src-web/components/core/PairOrBulkEditor.tsx index 065cecbf..05e864ec 100644 --- a/src-web/components/core/PairOrBulkEditor.tsx +++ b/src-web/components/core/PairOrBulkEditor.tsx @@ -30,7 +30,7 @@ export const PairOrBulkEditor = forwardRef(function PairOr title={useBulk ? 'Enable form edit' : 'Enable bulk edit'} className={classNames( 'transition-opacity opacity-0 group-hover:opacity-80 hover:!opacity-100 shadow', - 'bg-surface text-text-subtle hover:text group-hover/wrapper:opacity-100', + 'bg-surface hover:text group-hover/wrapper:opacity-100', )} onClick={() => setUseBulk((b) => !b)} icon={useBulk ? 'table' : 'file_code'} diff --git a/src-web/components/core/PlainInput.tsx b/src-web/components/core/PlainInput.tsx index cf717d0c..24a85448 100644 --- a/src-web/components/core/PlainInput.tsx +++ b/src-web/components/core/PlainInput.tsx @@ -148,7 +148,7 @@ export function PlainInput({ title={obscured ? `Show ${label}` : `Obscure ${label}`} size="xs" className="mr-0.5 group/obscure !h-auto my-0.5" - iconClassName="text-text-subtle group-hover/obscure:text" + iconClassName="group-hover/obscure:text" iconSize="sm" icon={obscured ? 'eye' : 'eye_closed'} onClick={() => setObscured((o) => !o)} diff --git a/src-web/components/core/SegmentedControl.tsx b/src-web/components/core/SegmentedControl.tsx index 3165d956..6716026e 100644 --- a/src-web/components/core/SegmentedControl.tsx +++ b/src-web/components/core/SegmentedControl.tsx @@ -45,7 +45,7 @@ export function SegmentedControl({ value, onChange, options, n + {children} + + ); +} + +export function TableBody({ children }: { children: ReactNode }) { + return {children}; +} + +export function TableHead({ children }: { children: ReactNode }) { + return {children}; +} + +export function TableRow({ children }: { children: ReactNode }) { + return {children}; +} + +export function TableCell({ children, className }: { children: ReactNode; className?: string }) { + return ( + + {children} + + ); +} + +export function TruncatedWideTableCell({ + children, + className, +}: { + children: ReactNode; + className?: string; +}) { + return ( + +
{children}
+
+ ); +} + +export function TableHeaderCell({ + children, + className, +}: { + children: ReactNode; + className?: string; +}) { + return ( + + {children} + + ); +} diff --git a/src-web/components/core/Tabs/Tabs.tsx b/src-web/components/core/Tabs/Tabs.tsx index f39360e3..d6909253 100644 --- a/src-web/components/core/Tabs/Tabs.tsx +++ b/src-web/components/core/Tabs/Tabs.tsx @@ -121,7 +121,7 @@ export function Tabs({ diff --git a/src-web/components/core/Toast.tsx b/src-web/components/core/Toast.tsx index 6f87eb4e..f73d753e 100644 --- a/src-web/components/core/Toast.tsx +++ b/src-web/components/core/Toast.tsx @@ -55,14 +55,14 @@ export function Toast({ children, open, onClose, timeout, action, icon, color }:
- {toastIcon && } + {toastIcon && }
{children}
{action?.({ hide: onClose })} diff --git a/src-web/components/git/BranchSelectionDialog.tsx b/src-web/components/git/BranchSelectionDialog.tsx new file mode 100644 index 00000000..e2287913 --- /dev/null +++ b/src-web/components/git/BranchSelectionDialog.tsx @@ -0,0 +1,43 @@ +import { useState } from 'react'; +import { Button } from '../core/Button'; +import { Select } from '../core/Select'; +import { HStack, VStack } from '../core/Stacks'; + +interface Props { + branches: string[]; + onCancel: () => void; + onSelect: (branch: string) => void; + selectText: string; +} + +export function BranchSelectionDialog({ branches, onCancel, onSelect, selectText }: Props) { + const [branch, setBranch] = useState('__NONE__'); + return ( + { + e.preventDefault(); + onSelect(branch); + }} + > +