mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
Merge branch 'main' into jj-fix-typo
This commit is contained in:
commit
cc7a14b424
247 changed files with 6074 additions and 2245 deletions
4
.github/workflows/loadtest-osquery-perf.yml
vendored
4
.github/workflows/loadtest-osquery-perf.yml
vendored
|
|
@ -13,7 +13,7 @@ on:
|
|||
default: "main"
|
||||
required: true
|
||||
loadtest_containers:
|
||||
description: "Deploys osquery-perf containers all at once. Total number of osquery-perf tasks to run (should be a multiple of 8, if setting loadtest_containers_starting_index). This is also used as the end index in enroll.sh"
|
||||
description: "Deploys osquery-perf containers all at once. Total number of osquery-perf tasks to run. This is also used as the end index in enroll.sh"
|
||||
type: string
|
||||
required: true
|
||||
loadtest_containers_starting_index:
|
||||
|
|
@ -22,7 +22,7 @@ on:
|
|||
default: 0
|
||||
required: true
|
||||
task_size:
|
||||
description: "CPU and Memory setting for osquery-perf containers. Example: {\"cpu\":\"4098\",\"memory\":\"8192\"}"
|
||||
description: "CPU and Memory setting for osquery-perf containers. Example: {\"cpu\":\"4096\",\"memory\":\"8192\"}"
|
||||
type: string
|
||||
default: "{\"cpu\":\"4096\",\"memory\":\"8192\"}"
|
||||
required: true
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
## Fleet 4.83.2 (Apr 13, 2026)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Fixed a crash on the "My device" page for Fleet Free instances. The page returned a 402 error when the host was assigned to a team because the device endpoint called a premium-only API, and also crashed when accessing undefined policies data.```
|
||||
|
||||
## Fleet 4.83.1 (Apr 10, 2026)
|
||||
|
||||
### Bug fixes
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM --platform=linux/amd64 golang:1.26.1-trixie@sha256:96b28783b99bcd265fbfe0b36a3ac6462416ce6bf1feac85d4c4ff533cbaa473
|
||||
FROM --platform=linux/amd64 golang:1.26.2-trixie@sha256:b53c282df83967299380adbd6a2dc67e750a58217f39285d6240f6f80b19eaad
|
||||
LABEL maintainer="Fleet Developers"
|
||||
|
||||
RUN apt-get update && apt-get install -y musl-tools && rm -rf /var/lib/apt/lists/*
|
||||
|
|
|
|||
63
Makefile
63
Makefile
|
|
@ -680,12 +680,62 @@ restore: $(SNAPSHOT_BINARY)
|
|||
# Generate osqueryd.app.tar.gz bundle from osquery.io.
|
||||
#
|
||||
# Usage:
|
||||
# To generate an osquery bundle for a released version of osquery:
|
||||
# make osqueryd-app-tar-gz version=5.1.0 out-path=.
|
||||
#
|
||||
# To generate an osquery bundle for a unreleased change in osquery in a pull request
|
||||
# (e.g. https://github.com/osquery/osquery/pull/8815):
|
||||
# make osqueryd-app-tar-gz pr=8815 out-path=.
|
||||
osqueryd-app-tar-gz:
|
||||
ifneq ($(shell uname), Darwin)
|
||||
@echo "Makefile target osqueryd-app-tar-gz is only supported on macOS"
|
||||
@exit 1
|
||||
endif
|
||||
ifdef pr
|
||||
$(eval TMP_DIR := $(shell mktemp -d))
|
||||
@echo "Fetching macos_unsigned_tgz_universal artifact from osquery/osquery PR $(pr)..."
|
||||
@PR_SHA=$$(gh pr view -R osquery/osquery $(pr) --json headRefOid -q .headRefOid) && \
|
||||
echo "PR head SHA: $$PR_SHA" && \
|
||||
RUN_IDS=$$(gh api "repos/osquery/osquery/actions/runs?head_sha=$$PR_SHA" \
|
||||
-q '[.workflow_runs[] | select(.conclusion == "success") | .id] | .[]') && \
|
||||
if [ -z "$$RUN_IDS" ]; then \
|
||||
echo "Error: no successful workflow runs found for PR $(pr)"; \
|
||||
rm -rf $(TMP_DIR); \
|
||||
exit 1; \
|
||||
fi && \
|
||||
DOWNLOADED=false && \
|
||||
for run_id in $$RUN_IDS; do \
|
||||
if gh run download -R osquery/osquery $$run_id -n macos_unsigned_tgz_universal -D $(TMP_DIR)/artifact 2>/dev/null; then \
|
||||
DOWNLOADED=true; \
|
||||
echo "Downloaded artifact from run $$run_id"; \
|
||||
break; \
|
||||
fi; \
|
||||
done && \
|
||||
if [ "$$DOWNLOADED" != "true" ]; then \
|
||||
echo "Error: macos_unsigned_tgz_universal artifact not found in any successful run for PR $(pr)"; \
|
||||
rm -rf $(TMP_DIR); \
|
||||
exit 1; \
|
||||
fi
|
||||
@INNER_TGZ=$$(find $(TMP_DIR)/artifact -name '*.tar.gz' -o -name '*.tgz' | head -1) && \
|
||||
if [ -z "$$INNER_TGZ" ]; then \
|
||||
echo "Error: no tarball found inside downloaded artifact"; \
|
||||
rm -rf $(TMP_DIR); \
|
||||
exit 1; \
|
||||
fi && \
|
||||
mkdir -p $(TMP_DIR)/extracted && \
|
||||
tar xf "$$INNER_TGZ" -C $(TMP_DIR)/extracted
|
||||
@OSQUERY_APP=$$(find $(TMP_DIR)/extracted -type d -name 'osquery.app' | head -1) && \
|
||||
if [ -z "$$OSQUERY_APP" ]; then \
|
||||
echo "Error: osquery.app not found in extracted artifact. Contents:"; \
|
||||
find $(TMP_DIR)/extracted -type f; \
|
||||
rm -rf $(TMP_DIR); \
|
||||
exit 1; \
|
||||
fi && \
|
||||
OSQUERY_APP_DIR=$$(dirname "$$OSQUERY_APP") && \
|
||||
"$$OSQUERY_APP/Contents/MacOS/osqueryd" --version && \
|
||||
tar czf $(out-path)/osqueryd.app.tar.gz -C "$$OSQUERY_APP_DIR" osquery.app
|
||||
rm -rf $(TMP_DIR)
|
||||
else
|
||||
$(eval TMP_DIR := $(shell mktemp -d))
|
||||
curl -L https://github.com/osquery/osquery/releases/download/$(version)/osquery-$(version).pkg --output $(TMP_DIR)/osquery-$(version).pkg
|
||||
pkgutil --expand $(TMP_DIR)/osquery-$(version).pkg $(TMP_DIR)/osquery_pkg_expanded
|
||||
|
|
@ -695,6 +745,7 @@ endif
|
|||
$(TMP_DIR)/osquery_pkg_payload_expanded/opt/osquery/lib/osquery.app/Contents/MacOS/osqueryd --version
|
||||
tar czf $(out-path)/osqueryd.app.tar.gz -C $(TMP_DIR)/osquery_pkg_payload_expanded/opt/osquery/lib osquery.app
|
||||
rm -r $(TMP_DIR)
|
||||
endif
|
||||
|
||||
# Generate nudge.app.tar.gz bundle from nudge repo.
|
||||
#
|
||||
|
|
@ -889,7 +940,17 @@ vex-report:
|
|||
|
||||
# make update-go version=1.24.4
|
||||
UPDATE_GO_DOCKERFILES := ./Dockerfile-desktop-linux ./infrastructure/loadtesting/terraform/docker/loadtest.Dockerfile ./tools/mdm/migration/mdmproxy/Dockerfile
|
||||
UPDATE_GO_MODS := go.mod ./tools/mdm/windows/bitlocker/go.mod ./tools/snapshot/go.mod ./tools/terraform/go.mod
|
||||
UPDATE_GO_MODS := \
|
||||
go.mod \
|
||||
./tools/mdm/windows/bitlocker/go.mod \
|
||||
./tools/snapshot/go.mod \
|
||||
./tools/terraform/go.mod \
|
||||
./third_party/vuln-check/go.mod \
|
||||
./tools/ci/setboolcheck/go.mod \
|
||||
./tools/github-manage/go.mod \
|
||||
./tools/qacheck/go.mod \
|
||||
./third_party/goval-dictionary/go.mod \
|
||||
./tools/fleet-mcp/go.mod
|
||||
update-go:
|
||||
@test $(version) || (echo "Mising 'version' argument, usage: 'make update-go version=1.24.4'" ; exit 1)
|
||||
@for dockerfile in $(UPDATE_GO_DOCKERFILES) ; do \
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import kotlinx.coroutines.flow.map
|
|||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.EncodeDefault
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
|
@ -438,6 +439,9 @@ object ApiClient : CertificateApiClient {
|
|||
)
|
||||
}
|
||||
|
||||
// @EncodeDefault is marked @ExperimentalSerializationApi, but it has shipped in kotlinx.serialization since 1.3 (2022)
|
||||
// and is widely used and reliable in production. The opt-in only acknowledges that the API shape could change in a future version.
|
||||
@OptIn(kotlinx.serialization.ExperimentalSerializationApi::class)
|
||||
@Serializable
|
||||
data class EnrollRequest(
|
||||
@SerialName("enroll_secret")
|
||||
|
|
@ -446,6 +450,7 @@ data class EnrollRequest(
|
|||
val hardwareUUID: String,
|
||||
@SerialName("hardware_serial")
|
||||
val hardwareSerial: String,
|
||||
@EncodeDefault(EncodeDefault.Mode.ALWAYS)
|
||||
@SerialName("platform")
|
||||
val platform: String = "android",
|
||||
@SerialName("computer_name")
|
||||
|
|
|
|||
|
|
@ -100,10 +100,15 @@ class ApiClientReenrollTest {
|
|||
assertTrue("First call should succeed", firstResult.isSuccess)
|
||||
assertEquals(2, mockWebServer.requestCount) // enroll + config
|
||||
|
||||
// Verify first enrollment used the enroll secret
|
||||
// Verify first enrollment used the enroll secret and sent platform="android" on the wire
|
||||
val firstEnroll = mockWebServer.takeRequest()
|
||||
assertEquals("/api/fleet/orbit/enroll", firstEnroll.path)
|
||||
assertTrue(firstEnroll.body.readUtf8().contains("test-enroll-secret"))
|
||||
val firstEnrollBody = firstEnroll.body.readUtf8()
|
||||
assertTrue(firstEnrollBody.contains("test-enroll-secret"))
|
||||
assertTrue(
|
||||
"Expected platform=\"android\" in enroll body, got: $firstEnrollBody",
|
||||
firstEnrollBody.contains("\"platform\":\"android\""),
|
||||
)
|
||||
|
||||
// Verify first config used first-node-key
|
||||
val firstConfig = mockWebServer.takeRequest()
|
||||
|
|
|
|||
1
android/changes/43807-android-enroll-platform
Normal file
1
android/changes/43807-android-enroll-platform
Normal file
|
|
@ -0,0 +1 @@
|
|||
- Fixed Android agent to always send the `platform` field on enrollment so the device is registered with the correct platform.
|
||||
54
articles/IT-leaders-guide-to-Linux-device-management.md
Normal file
54
articles/IT-leaders-guide-to-Linux-device-management.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
### Linux adoption is growing. Management hasn't kept up.
|
||||
|
||||
* macOS and Windows have mature management ecosystems. Linux does not.
|
||||
* Compliance frameworks don't grant exemptions by operating system.
|
||||
* Security audits don't skip Linux workstations.
|
||||
* These create the Linux gap.
|
||||
|
||||
### Unmanaged devices are unmanaged risk.
|
||||
|
||||
This guide helps IT leaders understand and close the Linux management gap.
|
||||
|
||||
### What you'll learn
|
||||
|
||||
You'll learn about a maturity model for planning your adoption path, a clear framework for defining your requirements, and a concrete evaluation scorecard for comparing management platforms. Whether you manage 50 Linux workstations or 5,000, this guide gives you the structure to make a defensible platform decision and explain it to your team.
|
||||
|
||||
### Chapter list
|
||||
|
||||
- **Why Linux devices are important**
|
||||
* What's driving enterprise Linux adoption and why management is no longer optional.
|
||||
- **The business case for managing Linux devices**
|
||||
* Cost, compliance, talent retention, and the price of inaction.
|
||||
- **Defining your Linux device management needs**
|
||||
* Key questions to ask and a maturity model to map your goals.
|
||||
- **Automated provisioning for Linux desktop in the enterprise**
|
||||
* The provisioning gap, enrollment approaches, and what zero-touch looks like on Linux.
|
||||
- **Security baselines for Linux**
|
||||
* Why baselines matter, what to enforce, and how to fight configuration drift.
|
||||
- **App and certificate management for Linux**
|
||||
* Software distribution challenges, the notarization gap, patching speed, and shrinking certificate lifetimes.
|
||||
- **Protecting the Linux device**
|
||||
* USB and Bluetooth threats, the sudo problem, and remote lock and wipe.
|
||||
- **Controlling your software and your data**
|
||||
* Software sovereignty, data sovereignty, and why your management tooling should reflect the values that made Linux worth adopting.
|
||||
- **Choosing the right solution**
|
||||
* Business and technical requirements, an evaluation criteria table, and a structured way to compare platforms.
|
||||
|
||||
|
||||
|
||||
<meta name="articleTitle" value="The IT leader's guide to Linux device management">
|
||||
|
||||
<meta name="authorFullName" value="n/a">
|
||||
<meta name="authorGitHubUsername" value="fleet-release">
|
||||
|
||||
<meta name="category" value="whitepaper">
|
||||
<meta name="publishedOn" value="2026-04-20">
|
||||
<meta name="description" value="Close the Linux management gap. A guide to help IT leaders understand the business case, security, compliance, and choosing the right solution.">
|
||||
|
||||
|
||||
<meta name="articleImageUrl" value="../website/assets/images/articles/IT-leaders-guide-to-Linux-device-management-cover-image-504x336@2x.png">
|
||||
<meta name="whitepaperFilename" value="IT-leaders-guide-to-Linux-device-management.pdf">
|
||||
<meta name="formHeadline" value="Learn how to close the Linux management gap">
|
||||
|
||||
<meta name="introductionTextBlockOne" value="Linux now exceeds 5% of desktop market share. Stack Overflow's 2025 developer survey shows nearly 30% of developers use Linux as their primary work OS.">
|
||||
<meta name="introductionTextBlockTwo" value="Your most important contributors, developers, engineers, and security practitioners, are choosing Linux. And in most organizations, those devices sit outside formal IT management.">
|
||||
|
|
@ -57,6 +57,7 @@ You will also see how treating device management as a software discipline helps
|
|||
|
||||
|
||||
<meta name="articleImageUrl" value="../website/assets/images/articles/modern-endpoint-management-managing-devices-as-code-cover-image-504x336@2x.png">
|
||||
<meta name="formHeadline" value="Learn how GitOps transforms device management">
|
||||
|
||||
<meta name="whitepaperFilename" value="fleet-modern-endpoint-device-management-managing-devices-as-code.pdf">
|
||||
<meta name="introductionTextBlockOne" value="Traditional device management does not scale. Teams still rely on manual updates, GUI tools, and scattered inventories.">
|
||||
|
|
|
|||
1
changes/42427-cleanup-stale-mdm-profiles
Normal file
1
changes/42427-cleanup-stale-mdm-profiles
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Fixed a bug where pending MDM profile rows persisted in the database after Apple or Windows MDM was turned off, causing stale profiles to reappear when MDM was re-enabled. Also fixed cleanup of pending Windows profile rows when a device unenrolls from MDM.
|
||||
1
changes/42879-api-only-user-management-ui
Normal file
1
changes/42879-api-only-user-management-ui
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Added UI pages for creating and editing API-only users with support for fleet assignment, role selection, and API endpoint access control.
|
||||
1
changes/43142-script-package-icon-gitops
Normal file
1
changes/43142-script-package-icon-gitops
Normal file
|
|
@ -0,0 +1 @@
|
|||
- Fixed an issue where adding a custom icon for a script-only package was not allowed in GitOps.
|
||||
1
changes/43222-support-fleet-variables-in-ddm
Normal file
1
changes/43222-support-fleet-variables-in-ddm
Normal file
|
|
@ -0,0 +1 @@
|
|||
- Added support for Fleet variables in Apple's declaration profiles (DDM).
|
||||
1
changes/43311-script-only-pkg-gitops
Normal file
1
changes/43311-script-only-pkg-gitops
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Fixed a bug where host environment variables in script-only packages would cause gitops to fail
|
||||
1
changes/update-go-1.26.2
Normal file
1
changes/update-go-1.26.2
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Updated go to 1.26.2
|
||||
|
|
@ -4,11 +4,11 @@ name: fleet
|
|||
keywords:
|
||||
- fleet
|
||||
- osquery
|
||||
version: v6.8.9
|
||||
version: v6.8.10
|
||||
home: https://github.com/fleetdm/fleet
|
||||
sources:
|
||||
- https://github.com/fleetdm/fleet.git
|
||||
appVersion: v4.83.1
|
||||
appVersion: v4.83.2
|
||||
dependencies:
|
||||
- name: mysql
|
||||
condition: mysql.enabled
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ hostName: fleet.localhost
|
|||
replicas: 3 # The number of Fleet instances to deploy
|
||||
revisionHistoryLimit: 10 # Number of old ReplicaSets for Fleet deployment to retain for rollback (set to 0 for unlimited)
|
||||
imageRepository: fleetdm/fleet
|
||||
imageTag: v4.83.1 # Version of Fleet to deploy
|
||||
imageTag: v4.83.2 # Version of Fleet to deploy
|
||||
# imagePullSecrets is optional.
|
||||
# imagePullSecrets:
|
||||
# - name: docker
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ func TestApplyAsGitOpsDeprecatedKeys(t *testing.T) {
|
|||
ds.SetAsideLabelsFunc = func(ctx context.Context, notOnTeamID *uint, names []string, user fleet.User) error {
|
||||
return nil
|
||||
}
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
|
||||
declaration.DeclarationUUID = uuid.NewString()
|
||||
return declaration, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ func TestApplyTeamSpecs(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
|
||||
declaration.DeclarationUUID = uuid.NewString()
|
||||
return declaration, nil
|
||||
}
|
||||
|
|
@ -755,7 +755,7 @@ func TestApplyAppConfig(t *testing.T) {
|
|||
return map[string]uint{fleet.BuiltinLabelMacOS14Plus: 1}, nil
|
||||
}
|
||||
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
|
||||
declaration.DeclarationUUID = uuid.NewString()
|
||||
return declaration, nil
|
||||
}
|
||||
|
|
@ -1486,7 +1486,7 @@ func TestApplyAsGitOps(t *testing.T) {
|
|||
ds.SetAsideLabelsFunc = func(ctx context.Context, notOnTeamID *uint, names []string, user fleet.User) error {
|
||||
return nil
|
||||
}
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
|
||||
declaration.DeclarationUUID = uuid.NewString()
|
||||
return declaration, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2610,7 +2610,7 @@ func TestGetTeamsYAMLAndApply(t *testing.T) {
|
|||
require.ElementsMatch(t, names, []string{fleet.BuiltinLabelMacOS14Plus})
|
||||
return map[string]uint{fleet.BuiltinLabelMacOS14Plus: 1}, nil
|
||||
}
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
|
||||
declaration.DeclarationUUID = uuid.NewString()
|
||||
return declaration, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1637,13 +1637,13 @@ func TestGitOpsFullTeam(t *testing.T) {
|
|||
ds.NewMDMAppleConfigProfileFunc = func(ctx context.Context, profile fleet.MDMAppleConfigProfile, vars []fleet.FleetVarName) (*fleet.MDMAppleConfigProfile, error) {
|
||||
return &profile, nil
|
||||
}
|
||||
ds.NewMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
|
||||
ds.NewMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
|
||||
return declaration, nil
|
||||
}
|
||||
ds.LabelIDsByNameFunc = func(ctx context.Context, names []string, filter fleet.TeamFilter) (map[string]uint, error) {
|
||||
return map[string]uint{fleet.BuiltinLabelMacOS14Plus: 1}, nil
|
||||
}
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
|
||||
declaration.DeclarationUUID = uuid.NewString()
|
||||
return declaration, nil
|
||||
}
|
||||
|
|
@ -5869,7 +5869,7 @@ func TestGitOpsAppleOSUpdates(t *testing.T) {
|
|||
defaultTeamConfig = config
|
||||
return nil
|
||||
}
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
|
||||
return &fleet.MDMAppleDeclaration{DeclarationUUID: "test-uuid"}, nil
|
||||
}
|
||||
ds.LabelIDsByNameFunc = func(ctx context.Context, names []string, filter fleet.TeamFilter) (map[string]uint, error) {
|
||||
|
|
@ -6154,7 +6154,7 @@ func TestGitOpsWindowsOSUpdates(t *testing.T) {
|
|||
defaultTeamConfig = config
|
||||
return nil
|
||||
}
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
|
||||
return &fleet.MDMAppleDeclaration{DeclarationUUID: "test-uuid"}, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ func setupEmptyGitOpsMocks(ds *mock.Store) {
|
|||
) (fleet.MDMProfilesUpdates, error) {
|
||||
return fleet.MDMProfilesUpdates{}, nil
|
||||
}
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
|
||||
return &fleet.MDMAppleDeclaration{}, nil
|
||||
}
|
||||
ds.DeleteMDMAppleDeclarationByNameFunc = func(ctx context.Context, teamID *uint, name string) error {
|
||||
|
|
|
|||
|
|
@ -450,7 +450,7 @@ func SetupFullGitOpsPremiumServer(t *testing.T) (*mock.Store, **fleet.AppConfig,
|
|||
savedTeams[team.Name] = &team
|
||||
return team, nil
|
||||
}
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (
|
||||
*fleet.MDMAppleDeclaration, error,
|
||||
) {
|
||||
declaration.DeclarationUUID = uuid.NewString()
|
||||
|
|
|
|||
|
|
@ -4222,7 +4222,7 @@ labels:
|
|||
- name: Test Fleet Label
|
||||
label_membership_type: dynamic
|
||||
query: SELECT 1
|
||||
|
||||
|
||||
`, fleetName)
|
||||
|
||||
fullFleetFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
|
|
@ -4518,3 +4518,44 @@ settings:
|
|||
require.Empty(t, teamMeta.LabelsExcludeAny)
|
||||
require.Empty(t, teamMeta.LabelsIncludeAll)
|
||||
}
|
||||
|
||||
func (s *enterpriseIntegrationGitopsTestSuite) TestFleetGitopsDDMUnsupportedFleetVariable() {
|
||||
t := s.T()
|
||||
user := s.createGitOpsUser(t)
|
||||
fleetctlConfig := s.createFleetctlConfig(t, user)
|
||||
|
||||
// Create a DDM declaration with an unsupported Fleet variable
|
||||
declDir := t.TempDir()
|
||||
declFile := path.Join(declDir, "decl-unsupported-var.json")
|
||||
err := os.WriteFile(declFile, []byte(`{
|
||||
"Type": "com.apple.configuration.management.test",
|
||||
"Identifier": "com.example.unsupported-var",
|
||||
"Payload": {"Value": "$FLEET_VAR_BOZO"}
|
||||
}`), 0o644)
|
||||
require.NoError(t, err)
|
||||
|
||||
globalFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
require.NoError(t, err)
|
||||
_, err = globalFile.WriteString(fmt.Sprintf(`
|
||||
agent_options:
|
||||
controls:
|
||||
macos_settings:
|
||||
custom_settings:
|
||||
- path: %s
|
||||
org_settings:
|
||||
server_settings:
|
||||
server_url: $FLEET_URL
|
||||
org_info:
|
||||
org_name: Fleet
|
||||
secrets:
|
||||
policies:
|
||||
queries:
|
||||
`, declFile))
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Setenv("FLEET_URL", s.Server.URL)
|
||||
|
||||
// Applying a DDM declaration with an unsupported Fleet variable should fail
|
||||
_, err = fleetctl.RunAppNoChecks([]string{"gitops", "--config", fleetctlConfig.Name(), "-f", globalFile.Name()})
|
||||
require.ErrorContains(t, err, "Fleet variable $FLEET_VAR_BOZO is not supported in DDM profiles")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,3 +222,43 @@ func (s *integrationGitopsTestSuite) TestFleetGitopsWithFleetSecrets() {
|
|||
require.NoError(t, err)
|
||||
assert.Contains(t, string(winProfile.SyncML), "${FLEET_SECRET_"+secretName2+"}")
|
||||
}
|
||||
|
||||
func (s *integrationGitopsTestSuite) TestFleetGitopsDDMFleetVarsRequiresPremium() {
|
||||
t := s.T()
|
||||
fleetctlConfig := s.createFleetctlConfig()
|
||||
|
||||
// Create a DDM declaration with a Fleet variable
|
||||
declDir := t.TempDir()
|
||||
declFile := path.Join(declDir, "decl-fleetvar.json")
|
||||
err := os.WriteFile(declFile, []byte(`{
|
||||
"Type": "com.apple.configuration.management.test",
|
||||
"Identifier": "com.example.fleetvar-test",
|
||||
"Payload": {"Value": "$FLEET_VAR_HOST_HARDWARE_SERIAL"}
|
||||
}`), 0o644)
|
||||
require.NoError(t, err)
|
||||
|
||||
globalFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
require.NoError(t, err)
|
||||
_, err = globalFile.WriteString(fmt.Sprintf(`
|
||||
agent_options:
|
||||
controls:
|
||||
macos_settings:
|
||||
custom_settings:
|
||||
- path: %s
|
||||
org_settings:
|
||||
server_settings:
|
||||
server_url: $FLEET_URL
|
||||
org_info:
|
||||
org_name: Fleet
|
||||
secrets:
|
||||
policies:
|
||||
queries:
|
||||
`, declFile))
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Setenv("FLEET_URL", s.Server.URL)
|
||||
|
||||
// Applying a DDM declaration with Fleet variables should fail without a premium license
|
||||
_, err = fleetctl.RunAppNoChecks([]string{"gitops", "--config", fleetctlConfig.Name(), "-f", globalFile.Name()})
|
||||
require.ErrorContains(t, err, "missing or invalid license")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ set -euo pipefail
|
|||
REPO_URL="https://github.com/canonical/ubuntu-security-notices.git"
|
||||
REPO_DIR="ubuntu-security-notices"
|
||||
DAYS_TO_KEEP=3 # how much git history to get for initial clone
|
||||
# Fallback depth used when --shallow-since returns no commits (upstream was quiet).
|
||||
# The sync only needs the tip commit to populate the working tree.
|
||||
# We grab a few extra commits so the warning log shows recent upstream activity for debugging.
|
||||
FALLBACK_DEPTH=3
|
||||
|
||||
echo "=== OSV Repository Sync ==="
|
||||
echo ""
|
||||
|
|
@ -57,7 +61,17 @@ else
|
|||
git config core.sparseCheckout true
|
||||
echo "osv/" > .git/info/sparse-checkout
|
||||
|
||||
git fetch --shallow-since="${DAYS_TO_KEEP} days ago" origin main
|
||||
if ! git fetch --shallow-since="${DAYS_TO_KEEP} days ago" origin main; then
|
||||
echo ""
|
||||
echo "WARNING: --shallow-since=${DAYS_TO_KEEP}d returned no commits."
|
||||
echo "Upstream has been quiet for >${DAYS_TO_KEEP} days. Falling back to --depth=${FALLBACK_DEPTH}."
|
||||
echo ""
|
||||
git fetch --depth="${FALLBACK_DEPTH}" origin main
|
||||
echo "Recent history:"
|
||||
git log --pretty=format:'%h %ci %s' origin/main
|
||||
echo ""
|
||||
echo ""
|
||||
fi
|
||||
git checkout -b main --track origin/main
|
||||
|
||||
COMMIT_SHA=$(git rev-parse HEAD)
|
||||
|
|
|
|||
|
|
@ -33,12 +33,25 @@ package_path: package_name.yml
|
|||
package_path: ../software/package_name.yml
|
||||
```
|
||||
|
||||
### `path:` vs `paths:` (glob patterns)
|
||||
|
||||
Several sections support both `path:` (singular) and `paths:` (plural), including `scripts`, `configuration_profiles`, `labels`, `policies`, and `reports`:
|
||||
|
||||
- **`path:`** references a single, literal file path. Must not contain the characters `*`, `?`, `[`, or `{`.
|
||||
- **`paths:`** accepts a glob pattern to match multiple files at once (e.g. `../lib/windows/profiles/*.xml`).
|
||||
|
||||
You cannot specify both `path:` and `paths:` on the same entry.
|
||||
|
||||
> **Important:** Filenames containing `*`, `?`, `[`, or `{` cannot be referenced using `path:`. If your filenames contain these characters (e.g. Windows profiles named `[AllowSpotlightCollection].xml`), either rename the files to remove them, or use `paths:` with a wildcard pattern like `*.xml`.
|
||||
|
||||
For the GitOps API token, create a dedicated API-only user with `fleetctl user create --api-only`. These users can modify configurations via GitOps but can’t access the Fleet UI. Assign the GitOps role and set the appropriate global or fleet scope in the UI.
|
||||
|
||||
## labels
|
||||
|
||||
Labels can be specified in your `default.yml` and `fleets/fleet-name.yml` files using inline configuration or references to separate files in your `lib/` folder. Labels cannot be specified in `fleets/unassigned.yml`.
|
||||
|
||||
Labels support `path:` (single file) and `paths:` (glob pattern) references. See [`path:` vs `paths:`](#path-vs-paths-glob-patterns) for details. Filenames must not contain `*`, `?`, `[`, or `{` when using `path:`.
|
||||
|
||||
- `name` specifies the label's name. Must be unique across all global and fleet labels.
|
||||
+ Changing a label's `name` in GitOps will delete and re-create the label, temporarily clearing its membership. To avoid this, update the label name in the UI before making the change in YAML.
|
||||
- `description` specifies the label's description.
|
||||
|
|
@ -111,6 +124,7 @@ labels:
|
|||
```yaml
|
||||
labels:
|
||||
- path: ./lib/labels-name.labels.yml
|
||||
- paths: ./lib/labels/*.yml
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -118,6 +132,8 @@ labels:
|
|||
|
||||
Policies can be specified inline in your `default.yml`, `fleets/fleet-name.yml`, or `fleets/unassigned.yml` files. They can also be specified in separate files in your `lib/` folder.
|
||||
|
||||
Policies support `path:` (single file) and `paths:` (glob pattern) references. See [`path:` vs `paths:`](#path-vs-paths-glob-patterns) for details. Filenames must not contain `*`, `?`, `[`, or `{` when using `path:`.
|
||||
|
||||
### Options
|
||||
|
||||
For available options, see the parameters for the [Create policy](https://fleetdm.com/docs/rest-api/rest-api#create-policy) and [Create team policy](https://fleetdm.com/docs/rest-api/rest-api#create-team-policy) API endpoints.
|
||||
|
|
@ -223,6 +239,7 @@ policies:
|
|||
```yaml
|
||||
policies:
|
||||
- path: ../lib/policies-name.policies.yml
|
||||
- paths: ../lib/*.policies.yml
|
||||
```
|
||||
|
||||
> Currently, the `run_script` and `install_software` policy automations can only be configured for a fleet (`fleets/fleet-name.yml`) or "Unassigned" (`fleets/unassigned.yml`). The automations can only be added to policies in which the script (or software) is defined in the same fleet (or "Unassigned"). `calendar_events_enabled` can only be configured for policies on a fleet.
|
||||
|
|
@ -234,6 +251,8 @@ policies:
|
|||
|
||||
Reports can be specified inline in your `default.yml` file or `fleets/fleet-name.yml` files. They can also be specified in separate files in your `lib/` folder.
|
||||
|
||||
Reports support `path:` (single file) and `paths:` (glob pattern) references. See [`path:` vs `paths:`](#path-vs-paths-glob-patterns) for details. Filenames must not contain `*`, `?`, `[`, or `{` when using `path:`.
|
||||
|
||||
### Options
|
||||
|
||||
For possible options, see the parameters for the [Create report API endpoint](https://fleetdm.com/docs/rest-api/rest-api#create-report).
|
||||
|
|
@ -287,6 +306,7 @@ reports:
|
|||
labels_include_any:
|
||||
- Engineering
|
||||
- Customer Support
|
||||
- paths: ../lib/*.reports.yml
|
||||
```
|
||||
|
||||
## agent_options
|
||||
|
|
@ -351,7 +371,7 @@ agent_options:
|
|||
|
||||
The `controls` section allows you to configure scripts and device management (MDM) features in Fleet.
|
||||
|
||||
- `scripts` is a list of paths to macOS, Windows, or Linux scripts.
|
||||
- `scripts` is a list of paths to macOS, Windows, or Linux scripts. Supports `path:` (single file) and `paths:` (glob pattern, filtered to `.sh` and `.ps1` files only). Filenames must not contain `*`, `?`, `[`, or `{` when using `path:`. See [`path:` vs `paths:`](#path-vs-paths-glob-patterns) for details.
|
||||
- `windows_enabled_and_configured` specifies whether or not to turn on Windows MDM features (default: `false`). Can only be configured for "All fleets" (`default.yml`).
|
||||
- `windows_entra_tenant_ids` is a list of Microsoft Entra tenant IDs to enable automatic (Autopilot) and manual enrollment by end users (**Settings** > **Accounts** > **Access work or school** on Windows). Can only be configured for "All fleets" (`default.yml`). Find your **Tenant ID**, on [**Microsoft Entra ID** > **Home**](https://entra.microsoft.com/#home).
|
||||
- `enable_turn_on_windows_mdm_manually` specifies whether or not to require end users to manually turn on MDM in **Settings > Access work or school** (default: `false`). If `false`, MDM is automatically turned on for all Windows hosts that aren't connected to any MDM solution. Can only be configured for "All fleets" (`default.yml`).
|
||||
|
|
@ -368,6 +388,7 @@ controls:
|
|||
- path: ../lib/macos-script.sh
|
||||
- path: ../lib/windows-script.ps1
|
||||
- path: ../lib/linux-script.sh
|
||||
- paths: ../lib/scripts/*.sh # Glob pattern (filtered to .sh and .ps1 only)
|
||||
windows_enabled_and_configured: true
|
||||
windows_entra_tenant_ids:
|
||||
- 4e342a0d-ec1a-4353-bdeb-785542e0a8fb
|
||||
|
|
@ -393,16 +414,24 @@ controls:
|
|||
- path: ../lib/macos-profile1.mobileconfig
|
||||
labels_exclude_any: # Available in Fleet Premium
|
||||
- Macs on Sequoia
|
||||
<<<<<<< AdamBaali-Gitops-YAML-globs-update
|
||||
- path: ../lib/macos-profile2.json
|
||||
labels_include_all: # Available in Fleet Premium
|
||||
- Macs on Sonoma
|
||||
- paths: ../lib/macos/profiles/*.mobileconfig # Glob pattern to include all .mobileconfig files
|
||||
=======
|
||||
- path: ../lib/macos-profile3.mobileconfig
|
||||
>>>>>>> main
|
||||
labels_include_any: # Available in Fleet Premium
|
||||
- Engineering
|
||||
- Product
|
||||
- paths: ../lib/configuration-profiles/*.json
|
||||
windows_settings:
|
||||
configuration_profiles:
|
||||
- path: ../lib/windows-profile.xml
|
||||
- paths: ../lib/windows/profiles/*.xml # Glob pattern to include all .xml files in directory
|
||||
labels_include_any:
|
||||
- Engineering
|
||||
android_settings:
|
||||
configuration_profiles:
|
||||
- path: ../lib/android-profile.json
|
||||
|
|
@ -445,14 +474,21 @@ controls:
|
|||
|
||||
### apple_settings and windows_settings
|
||||
|
||||
- `apple_settings.configuration_profiles` is a list of paths to macOS, iOS, and iPadOS configuration profiles (.mobileconfig) or declaration profiles (.json).
|
||||
- `windows_settings.configuration_profiles` is a list of paths to Windows configuration profiles (.xml).
|
||||
- `apple_settings.configuration_profiles` is a list of macOS, iOS, and iPadOS configuration profiles (.mobileconfig) or declaration profiles (.json).
|
||||
- `windows_settings.configuration_profiles` is a list of Windows configuration profiles (.xml).
|
||||
|
||||
Each entry can use either `path:` or `paths:`:
|
||||
|
||||
- **`path:`** references a single file. Filenames must not contain `*`, `?`, `[`, or `{`.
|
||||
- **`paths:`** accepts a [glob pattern](#path-vs-paths-glob-patterns) to match multiple files (e.g. `../lib/windows/profiles/*.xml`). Labels and other options specified on a `paths:` entry apply to all matched files.
|
||||
|
||||
Use `labels_include_all` to target hosts that have all labels, `labels_include_any` to target hosts that have any label, or `labels_exclude_any` to target hosts that don't have any of the labels. Only one of `labels_include_all`, `labels_include_any`, or `labels_exclude_any` can be specified. If none are specified, all hosts are targeted.
|
||||
|
||||
### android_settings
|
||||
|
||||
- `android_settings.configuration_profiles` is a list of paths to Android configuration profiles (.json).
|
||||
- `android_settings.configuration_profiles` is a list of Android configuration profiles (.json).
|
||||
|
||||
Each entry can use either `path:` or `paths:`. Filenames must not contain `*`, `?`, `[`, or `{` when using `path:`. See [`path:` vs `paths:`](#path-vs-paths-glob-patterns) for glob pattern support.
|
||||
|
||||
Use `labels_include_all` to target hosts that have all labels, `labels_include_any` to target hosts that have any label, or `labels_exclude_any` to target hosts that don't have any of the labels. Only one of `labels_include_all`, `labels_include_any`, or `labels_exclude_any` can be specified. If none are specified, all hosts are targeted.
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ Enables exporting logs to an OpenTelemetry collector in addition to stderr outpu
|
|||
|
||||
### mdm.allow_all_declarations
|
||||
|
||||
Documentation for setting has moved to the [Fleet server configuration](https://fleetdm.com/docs/configuration/fleet-server-configuration#mdm-allow_all_declarations) reference.
|
||||
Documentation for setting has moved to the [Fleet server configuration](https://fleetdm.com/docs/configuration/fleet-server-configuration#mdm-allow-all-declarations) reference.
|
||||
|
||||
### FLEET_ENABLE_POST_CLIENT_DEBUG_ERRORS
|
||||
|
||||
|
|
|
|||
|
|
@ -3973,6 +3973,8 @@ If `hostname` is specified when there is more than one host with the same hostna
|
|||
|
||||
### Get host by Fleet Desktop token
|
||||
|
||||
> If you're hitting this endpoint often (e.g. every hour) for a large number of hosts (e.g. 1k+) the best practice is to set the `exclude_software` to `true` to prevent overloading the Fleet server.
|
||||
|
||||
Returns a subset of information about the host specified by `token`. To get all information about a host, use the ["Get host"](#get-host) endpoint.
|
||||
|
||||
This is the API route used by the **My device** page in Fleet Desktop to display information about the host to the end user.
|
||||
|
|
@ -3986,6 +3988,7 @@ This endpoint doesn't require API token authentication. Authentication on macOS,
|
|||
| Name | Type | In | Description |
|
||||
| ----- | ------ | ---- | ---------------------------------- |
|
||||
| token | string | path | The host's [Fleet Desktop token](https://fleetdm.com/guides/fleet-desktop#secure-fleet-desktop). For macOS, Windows, and Linux, this is a random UUID that rotates hourly. For iOS and iPadOS, this is the host's hardware UUID. |
|
||||
| exclude_software | boolean | query | If `true`, the response will not include a list of installed software for the host. |
|
||||
|
||||
#### Request headers
|
||||
|
||||
|
|
|
|||
11
ee/maintained-apps/inputs/winget/druva-insync.json
Normal file
11
ee/maintained-apps/inputs/winget/druva-insync.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"name": "Druva inSync",
|
||||
"slug": "druva-insync/windows",
|
||||
"package_identifier": "Druva.inSync",
|
||||
"unique_identifier": "Druva inSync",
|
||||
"fuzzy_match_name": true,
|
||||
"installer_arch": "x64",
|
||||
"installer_type": "msi",
|
||||
"installer_scope": "machine",
|
||||
"default_categories": ["Productivity"]
|
||||
}
|
||||
|
|
@ -631,6 +631,13 @@
|
|||
"unique_identifier": "com.getdropbox.dropbox",
|
||||
"description": "Dropbox is a client for the Dropbox cloud storage service."
|
||||
},
|
||||
{
|
||||
"name": "Druva inSync",
|
||||
"slug": "druva-insync/windows",
|
||||
"platform": "windows",
|
||||
"unique_identifier": "Druva inSync",
|
||||
"description": "Druva inSync is a cloud-based product that protects endpoint data."
|
||||
},
|
||||
{
|
||||
"name": "Eclipse IDE",
|
||||
"slug": "eclipse-ide/darwin",
|
||||
|
|
@ -650,14 +657,14 @@
|
|||
"slug": "elgato-control-center/darwin",
|
||||
"platform": "darwin",
|
||||
"unique_identifier": "com.corsair.ControlCenter",
|
||||
"description": "Elgate Control Center is an app to control your Elgato key lights."
|
||||
"description": "Elgato Control Center is an app to control your Elgato key lights."
|
||||
},
|
||||
{
|
||||
"name": "Elgato Stream Deck",
|
||||
"slug": "elgato-stream-deck/darwin",
|
||||
"platform": "darwin",
|
||||
"unique_identifier": "com.elgato.StreamDeck",
|
||||
"description": "Elgateo Stream Deck is an app to assign keys, and then decorate and label them, on a Stream Deck."
|
||||
"description": "Elgato Stream Deck is an app to assign keys, and then decorate and label them, on a Stream Deck."
|
||||
},
|
||||
{
|
||||
"name": "Evernote",
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.142.1",
|
||||
"version": "1.143.2",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'company.thebrowser.Browser';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'company.thebrowser.Browser' AND version_compare(bundle_short_version, '1.142.1') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'company.thebrowser.Browser' AND version_compare(bundle_short_version, '1.143.2') < 0);"
|
||||
},
|
||||
"installer_url": "https://releases.arc.net/release/Arc-1.142.1-78710.zip",
|
||||
"installer_url": "https://releases.arc.net/release/Arc-1.143.2-79250.zip",
|
||||
"install_script_ref": "0c68f8e0",
|
||||
"uninstall_script_ref": "d6b0eb40",
|
||||
"sha256": "b473533e163be0fc04798e41ba4b6ce30c6a71368331c31799b604e5244e7769",
|
||||
"sha256": "d06d70a050f40651b761aa733f2c7096eaa396d57e5879f3bc20bbe8cdf90882",
|
||||
"default_categories": [
|
||||
"Browsers"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "147.1.89.132",
|
||||
"version": "147.1.89.137",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.brave.Browser';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.brave.Browser' AND version_compare(bundle_short_version, '147.1.89.132') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.brave.Browser' AND version_compare(bundle_short_version, '147.1.89.137') < 0);"
|
||||
},
|
||||
"installer_url": "https://updates-cdn.bravesoftware.com/sparkle/Brave-Browser/stable-arm64/189.132/Brave-Browser-arm64.dmg",
|
||||
"installer_url": "https://updates-cdn.bravesoftware.com/sparkle/Brave-Browser/stable-arm64/189.137/Brave-Browser-arm64.dmg",
|
||||
"install_script_ref": "14ab8c47",
|
||||
"uninstall_script_ref": "e860eed9",
|
||||
"sha256": "28c566312b6bc4bbbab8af0a1ffdf409645dfcd596a514273baa4641ec57c27a",
|
||||
"sha256": "e99cee5c36402f1d2afe324d546158578bc29f54b087dada4743087886088931",
|
||||
"default_categories": [
|
||||
"Browsers"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "147.1.89.132",
|
||||
"version": "147.1.89.137",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name = 'Brave' AND publisher = 'Brave Software Inc';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Brave' AND publisher = 'Brave Software Inc' AND version_compare(version, '147.1.89.132') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Brave' AND publisher = 'Brave Software Inc' AND version_compare(version, '147.1.89.137') < 0);"
|
||||
},
|
||||
"installer_url": "https://github.com/brave/brave-browser/releases/download/v1.89.132/BraveBrowserStandaloneSilentSetup.exe",
|
||||
"installer_url": "https://github.com/brave/brave-browser/releases/download/v1.89.137/BraveBrowserStandaloneSilentSetup.exe",
|
||||
"install_script_ref": "9a0c2b15",
|
||||
"uninstall_script_ref": "30c77f69",
|
||||
"sha256": "43e4177a53a5ca12633f607a6b623147be55493645ff6233dc65f1a9fcb70583",
|
||||
"sha256": "6df590d6e0630609036b504af7a56e8c18e9dfc93539f3c17568586f973a7804",
|
||||
"default_categories": [
|
||||
"Browsers"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.2026.84.2",
|
||||
"version": "1.2026.98.2",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.openai.atlas';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.openai.atlas' AND version_compare(bundle_short_version, '1.2026.84.2') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.openai.atlas' AND version_compare(bundle_short_version, '1.2026.98.2') < 0);"
|
||||
},
|
||||
"installer_url": "https://persistent.oaistatic.com/atlas/public/ChatGPT_Atlas_Desktop_public_1.2026.84.2_20260408151909000.dmg",
|
||||
"installer_url": "https://persistent.oaistatic.com/atlas/public/ChatGPT_Atlas_Desktop_public_1.2026.98.2_20260416164957000.dmg",
|
||||
"install_script_ref": "b8f2e355",
|
||||
"uninstall_script_ref": "06984429",
|
||||
"sha256": "2a75ebcfe662d792455309d2b1366ff95fb783e86ed3ab667f4a691beb34f1ab",
|
||||
"sha256": "7f4c2a6807b45a6fe84a3477a7dc9c8ff1d7c4f02873fc299e91eda33c218427",
|
||||
"default_categories": [
|
||||
"Browsers"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.2026.051",
|
||||
"version": "1.2026.099",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.openai.chat';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.openai.chat' AND version_compare(bundle_short_version, '1.2026.051') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.openai.chat' AND version_compare(bundle_short_version, '1.2026.099') < 0);"
|
||||
},
|
||||
"installer_url": "https://persistent.oaistatic.com/sidekick/public/ChatGPT_Desktop_public_1.2026.051_1775834670.dmg",
|
||||
"installer_url": "https://persistent.oaistatic.com/sidekick/public/ChatGPT_Desktop_public_1.2026.099_1776706502.dmg",
|
||||
"install_script_ref": "105f16ab",
|
||||
"uninstall_script_ref": "dbaa4d2e",
|
||||
"sha256": "4d5db720e5625514b34d53e52de9360413f0fb32de9d932eb88fcca66f99f7a7",
|
||||
"sha256": "f3a6d63494ff9ef8af8abf6dd3be5297db7f904ea01040b790251e6846b4ac88",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.2773.0",
|
||||
"version": "1.3561.0",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.anthropic.claudefordesktop';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.anthropic.claudefordesktop' AND version_compare(bundle_short_version, '1.2773.0') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.anthropic.claudefordesktop' AND version_compare(bundle_short_version, '1.3561.0') < 0);"
|
||||
},
|
||||
"installer_url": "https://downloads.claude.ai/releases/darwin/universal/1.2773.0/Claude-884b3735b1ce5042a0c286824c6f9bd2d341f7c8.zip",
|
||||
"installer_url": "https://downloads.claude.ai/releases/darwin/universal/1.3561.0/Claude-fbc74be3fdc714a2c46ef1fb84f71d4e4c062930.zip",
|
||||
"install_script_ref": "d05235fc",
|
||||
"uninstall_script_ref": "4cfbec7d",
|
||||
"sha256": "74b8226817ca96199accbae6f1410ad23c1d4d024c900276b8faf946f42c8a37",
|
||||
"sha256": "b037ee8ebe3d11e7eba959179dfdc534951ae8e387e96cacda1dceeecd035b52",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.2773.0",
|
||||
"version": "1.3561.0",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name = 'Claude' AND publisher = 'Anthropic, PBC';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Claude' AND publisher = 'Anthropic, PBC' AND version_compare(version, '1.2773.0') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Claude' AND publisher = 'Anthropic, PBC' AND version_compare(version, '1.3561.0') < 0);"
|
||||
},
|
||||
"installer_url": "https://downloads.claude.ai/releases/win32/x64/1.2773.0/Claude-884b3735b1ce5042a0c286824c6f9bd2d341f7c8.msix",
|
||||
"installer_url": "https://downloads.claude.ai/releases/win32/x64/1.3561.0/Claude-fbc74be3fdc714a2c46ef1fb84f71d4e4c062930.msix",
|
||||
"install_script_ref": "31a0b698",
|
||||
"uninstall_script_ref": "03f72055",
|
||||
"sha256": "17c8d3784cd1877d792bfd3a9457d628ca8797562eaf73b581704f7fad83daac",
|
||||
"sha256": "726cf8552406f0a6260c5ddce9d5a6f560fb0f9098137447e636adfe752174cc",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "6.2.6",
|
||||
"version": "7.0.0",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.coteditor.CotEditor';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.coteditor.CotEditor' AND version_compare(bundle_short_version, '6.2.6') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.coteditor.CotEditor' AND version_compare(bundle_short_version, '7.0.0') < 0);"
|
||||
},
|
||||
"installer_url": "https://github.com/coteditor/CotEditor/releases/download/6.2.6/CotEditor_6.2.6.dmg",
|
||||
"installer_url": "https://github.com/coteditor/CotEditor/releases/download/7.0.0/CotEditor_7.0.0.dmg",
|
||||
"install_script_ref": "e5de4a42",
|
||||
"uninstall_script_ref": "37cee933",
|
||||
"sha256": "6ccc029ede9da8eb497f31a8423cfea91bf34e7a08c67b66be0e331a922e8fc2",
|
||||
"sha256": "9eb8c709fe29046673d56e9e62c0176d4eb5869166860825cc005267f26da68d",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "3.1.15",
|
||||
"version": "3.1.17",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.todesktop.230313mzl4w4u92';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.todesktop.230313mzl4w4u92' AND version_compare(bundle_short_version, '3.1.15') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.todesktop.230313mzl4w4u92' AND version_compare(bundle_short_version, '3.1.17') < 0);"
|
||||
},
|
||||
"installer_url": "https://downloads.cursor.com/production/3a67af7b780e0bfc8d32aefa96b8ff1cb8817f88/darwin/arm64/Cursor-darwin-arm64.zip",
|
||||
"installer_url": "https://downloads.cursor.com/production/fce1e9ab7844f9ea35793da01e634aa7e50bce90/darwin/arm64/Cursor-darwin-arm64.zip",
|
||||
"install_script_ref": "5a1b1299",
|
||||
"uninstall_script_ref": "f7561d44",
|
||||
"sha256": "e0b65b57d30d94eb668151c9b44d474f7fbb9c78a2bc4ec1bdff1a537bbc21a2",
|
||||
"sha256": "2c308456eb5b834da262fe4f3cca744e179e68eb25591d0b4f83c3b742956290",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "3.1.15",
|
||||
"version": "3.1.17",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name = 'Cursor' AND publisher = 'Anysphere';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Cursor' AND publisher = 'Anysphere' AND version_compare(version, '3.1.15') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Cursor' AND publisher = 'Anysphere' AND version_compare(version, '3.1.17') < 0);"
|
||||
},
|
||||
"installer_url": "https://downloads.cursor.com/production/3a67af7b780e0bfc8d32aefa96b8ff1cb8817f88/win32/x64/system-setup/CursorSetup-x64-3.1.15.exe",
|
||||
"installer_url": "https://downloads.cursor.com/production/fce1e9ab7844f9ea35793da01e634aa7e50bce90/win32/x64/system-setup/CursorSetup-x64-3.1.17.exe",
|
||||
"install_script_ref": "03589b5e",
|
||||
"uninstall_script_ref": "6c8096c5",
|
||||
"sha256": "d667e13c7e538e11b23569071f2a47b271494038f9ae0be6c424a30c318bc73b",
|
||||
"sha256": "14f6e7c8244175496bf8be1af05a7004d7013b6928576a0cdc350705baa8808d",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "26.0.2",
|
||||
"version": "26.0.3",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'org.jkiss.dbeaver.core.product';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'org.jkiss.dbeaver.core.product' AND version_compare(bundle_short_version, '26.0.2') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'org.jkiss.dbeaver.core.product' AND version_compare(bundle_short_version, '26.0.3') < 0);"
|
||||
},
|
||||
"installer_url": "https://dbeaver.io/files/26.0.2/dbeaver-ce-26.0.2-macos-aarch64.dmg",
|
||||
"installer_url": "https://dbeaver.io/files/26.0.3/dbeaver-ce-26.0.3-macos-aarch64.dmg",
|
||||
"install_script_ref": "6f101bb8",
|
||||
"uninstall_script_ref": "d5f7201c",
|
||||
"sha256": "6000d9eedb444dfb3edc70b4e397879ed2e3d71f06444c34dbb1860d2188783c",
|
||||
"sha256": "bfc0902d04403b32d8d4fab120417368aa374622dbfe2f508713d06474ae82e2",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "0.0.385",
|
||||
"version": "0.0.386",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.hnc.Discord';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.hnc.Discord' AND version_compare(bundle_short_version, '0.0.385') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.hnc.Discord' AND version_compare(bundle_short_version, '0.0.386') < 0);"
|
||||
},
|
||||
"installer_url": "https://dl.discordapp.net/apps/osx/0.0.385/Discord.dmg",
|
||||
"installer_url": "https://dl.discordapp.net/apps/osx/0.0.386/Discord.dmg",
|
||||
"install_script_ref": "dac37ced",
|
||||
"uninstall_script_ref": "8ed76f08",
|
||||
"sha256": "c5b69b1d27abd56d610cdb6173b4575ec84971aa1bbf91875e992c85bad3cff7",
|
||||
"sha256": "a01cf51f325bb95f4f9dd2ca96f9c1a03f547ac00c4e2034164835508cd8a04d",
|
||||
"default_categories": [
|
||||
"Communication"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.0.9233",
|
||||
"version": "1.0.9234",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name = 'Discord' AND publisher = 'Discord Inc.';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Discord' AND publisher = 'Discord Inc.' AND version_compare(version, '1.0.9233') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Discord' AND publisher = 'Discord Inc.' AND version_compare(version, '1.0.9234') < 0);"
|
||||
},
|
||||
"installer_url": "https://stable.dl2.discordapp.net/distro/app/stable/win/x64/1.0.9233/DiscordSetup.exe",
|
||||
"installer_url": "https://stable.dl2.discordapp.net/distro/app/stable/win/x64/1.0.9234/DiscordSetup.exe",
|
||||
"install_script_ref": "fd04e860",
|
||||
"uninstall_script_ref": "73fc6eff",
|
||||
"sha256": "eaba7863d5a7ed017a865f991267583e0768914aba99590874da0980832e45a3",
|
||||
"sha256": "3f0306caceaa9594c608b39dbee8ceaba4422abc51052ee21deda7280eee9173",
|
||||
"default_categories": [
|
||||
"Communication"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "4.69.0",
|
||||
"version": "4.70.0",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.electron.dockerdesktop';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.electron.dockerdesktop' AND version_compare(bundle_short_version, '4.69.0') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.electron.dockerdesktop' AND version_compare(bundle_short_version, '4.70.0') < 0);"
|
||||
},
|
||||
"installer_url": "https://desktop.docker.com/mac/main/arm64/224084/Docker.dmg",
|
||||
"installer_url": "https://desktop.docker.com/mac/main/arm64/224270/Docker.dmg",
|
||||
"install_script_ref": "091b8a34",
|
||||
"uninstall_script_ref": "c31a36e7",
|
||||
"sha256": "8e4638f2d427a4fb9d0f86f21d0975a344a164228d20fc22a620750b7943d644",
|
||||
"sha256": "38a19ac039dee38e0e445118da34962039ef1601b0656dc4d138592efda2caba",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "29.6.6",
|
||||
"version": "29.7.8",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.jgraph.drawio.desktop';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.jgraph.drawio.desktop' AND version_compare(bundle_short_version, '29.6.6') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.jgraph.drawio.desktop' AND version_compare(bundle_short_version, '29.7.8') < 0);"
|
||||
},
|
||||
"installer_url": "https://github.com/jgraph/drawio-desktop/releases/download/v29.6.6/draw.io-arm64-29.6.6.dmg",
|
||||
"installer_url": "https://github.com/jgraph/drawio-desktop/releases/download/v29.7.8/draw.io-arm64-29.7.8.dmg",
|
||||
"install_script_ref": "60c841d6",
|
||||
"uninstall_script_ref": "58c5bcdc",
|
||||
"sha256": "d725b6333977adf73ecbfa3dcc60dd4f2d745706e6758526611b737561a5c61e",
|
||||
"sha256": "4ed41dcea4b40f7c534974f3b6c90aaf098e1cc747b4d0bc0b2967ee2f75fa18",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
23
ee/maintained-apps/outputs/druva-insync/windows.json
Normal file
23
ee/maintained-apps/outputs/druva-insync/windows.json
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "7.5.7",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name LIKE 'Druva inSync %' AND publisher = 'Druva Technologies Pte. Ltd.';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Druva inSync %' AND publisher = 'Druva Technologies Pte. Ltd.' AND version_compare(version, '7.5.7') < 0);"
|
||||
},
|
||||
"installer_url": "https://downloads.druva.com/downloads/inSync/Windows/7.5.7/inSync7.5.7r110923.msi",
|
||||
"install_script_ref": "8959087b",
|
||||
"uninstall_script_ref": "b98f2558",
|
||||
"sha256": "44e7295a0efba9e386e5dc24fa1e024e84b14d5e70f290ddd4389da5c5e5c96e",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
],
|
||||
"upgrade_code": "{99ADCB07-6ABD-4A1D-AFF6-03649753BAFF}"
|
||||
}
|
||||
],
|
||||
"refs": {
|
||||
"8959087b": "$logFile = \"${env:TEMP}/fleet-install-software.log\"\n\ntry {\n\n$installProcess = Start-Process msiexec.exe `\n -ArgumentList \"/quiet /norestart /lv ${logFile} /i `\"${env:INSTALLER_PATH}`\"\" `\n -PassThru -Verb RunAs -Wait\n\nGet-Content $logFile -Tail 500\n\nExit $installProcess.ExitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n",
|
||||
"b98f2558": "# Fleet uninstalls app by finding all related product codes for the specified upgrade code\n$inst = New-Object -ComObject \"WindowsInstaller.Installer\"\n$timeoutSeconds = 300 # 5 minute timeout per product\n\nforeach ($product_code in $inst.RelatedProducts('{99ADCB07-6ABD-4A1D-AFF6-03649753BAFF}')) {\n $process = Start-Process msiexec -ArgumentList @(\"/quiet\", \"/x\", $product_code, \"/norestart\") -PassThru\n \n # Wait for process with timeout\n $completed = $process.WaitForExit($timeoutSeconds * 1000)\n \n if (-not $completed) {\n Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue\n Exit 1603 # ERROR_UNINSTALL_FAILURE\n }\n \n # If the uninstall failed, bail\n if ($process.ExitCode -ne 0) {\n Write-Output \"Uninstall for $($product_code) exited $($process.ExitCode)\"\n Exit $process.ExitCode\n }\n}\n\n# All uninstalls succeeded; exit success\nExit 0\n"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "126.2.10",
|
||||
"version": "126.3.12",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name = 'Figma' AND publisher = 'Figma, Inc.';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Figma' AND publisher = 'Figma, Inc.' AND version_compare(version, '126.2.10') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Figma' AND publisher = 'Figma, Inc.' AND version_compare(version, '126.3.12') < 0);"
|
||||
},
|
||||
"installer_url": "https://desktop.figma.com/win/build/Figma-126.2.10.exe",
|
||||
"installer_url": "https://desktop.figma.com/win/build/Figma-126.3.12.exe",
|
||||
"install_script_ref": "442d71b3",
|
||||
"uninstall_script_ref": "e33afd6b",
|
||||
"sha256": "1642d5c0747a8c91ab11f4bbe921d0b3fff30f66e730135142018c7ec9feddd8",
|
||||
"sha256": "171f090862ce8cc97316fa8341850df1a3ef05e0145f3364ec7af98447533f97",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "3.2.2",
|
||||
"version": "3.2.4",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'org.gimp.gimp-3.0';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'org.gimp.gimp-3.0' AND version_compare(bundle_short_version, '3.2.2') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'org.gimp.gimp-3.0' AND version_compare(bundle_short_version, '3.2.4') < 0);"
|
||||
},
|
||||
"installer_url": "https://download.gimp.org/gimp/v3.2/macos/gimp-3.2.2-arm64.dmg",
|
||||
"installer_url": "https://download.gimp.org/gimp/v3.2/macos/gimp-3.2.4-arm64.dmg",
|
||||
"install_script_ref": "9d89c548",
|
||||
"uninstall_script_ref": "c6d835f1",
|
||||
"sha256": "899706072aca7db958a6f2f8ed25123f5bd4c0dd0228c880c50d4e7064da4dc3",
|
||||
"sha256": "294c016dca7795999129a38b462f80fac3c13cb963e6de9d04eeb5d6e519392b",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "3.2.2.0",
|
||||
"version": "3.2.4.0",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name LIKE 'GIMP %' AND publisher = 'The GIMP Team';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'GIMP %' AND publisher = 'The GIMP Team' AND version_compare(version, '3.2.2.0') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'GIMP %' AND publisher = 'The GIMP Team' AND version_compare(version, '3.2.4.0') < 0);"
|
||||
},
|
||||
"installer_url": "https://download.gimp.org/gimp/v3.2/windows/gimp-3.2.2-setup.exe",
|
||||
"installer_url": "https://download.gimp.org/gimp/v3.2/windows/gimp-3.2.4-setup.exe",
|
||||
"install_script_ref": "7e5269bc",
|
||||
"uninstall_script_ref": "79fb181d",
|
||||
"sha256": "cbdcdb49c144d5ef26693f03939fff22770bed22b83da7c420cdfe78a18b383e",
|
||||
"sha256": "ec31d757dd82831d201ffcf47ffeac4175df739e0c02d5122e89aeeadfb988cc",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "12.0.0",
|
||||
"version": "12.0.1",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.axosoft.gitkraken';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.axosoft.gitkraken' AND version_compare(bundle_short_version, '12.0.0') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.axosoft.gitkraken' AND version_compare(bundle_short_version, '12.0.1') < 0);"
|
||||
},
|
||||
"installer_url": "https://api.gitkraken.dev/releases/production/darwin/arm64/12.0.0/GitKraken-v12.0.0.zip",
|
||||
"installer_url": "https://api.gitkraken.dev/releases/production/darwin/arm64/12.0.1/GitKraken-v12.0.1.zip",
|
||||
"install_script_ref": "0ff0c24b",
|
||||
"uninstall_script_ref": "24856f6f",
|
||||
"sha256": "b38d1f6551a4250a29967f1442f659e0db82bef8c9abbac9afaeb658a0ed23fb",
|
||||
"sha256": "2c3f694fe3de2ffdca5d3bdbb5f8f2634725850f5eeccfafdb3204bc09be1edf",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "7.128.0",
|
||||
"version": "7.140.1",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.granola.app';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.granola.app' AND version_compare(bundle_short_version, '7.128.0') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.granola.app' AND version_compare(bundle_short_version, '7.140.1') < 0);"
|
||||
},
|
||||
"installer_url": "https://dr2v7l5emb758.cloudfront.net/7.128.0/Granola-7.128.0-mac-universal.dmg",
|
||||
"installer_url": "https://dr2v7l5emb758.cloudfront.net/7.140.1/Granola-7.140.1-mac-universal.dmg",
|
||||
"install_script_ref": "4a04ff4b",
|
||||
"uninstall_script_ref": "9f1ed248",
|
||||
"sha256": "378ce94f09f574a57bfb32531e2f03c2a241c24a24a009350b1d04efe8ef602a",
|
||||
"sha256": "4d9a9c461c6efb1262f2980771e7979643084d12b6f95e977006cc379d5d1135",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "7.128.0",
|
||||
"version": "7.140.1",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name LIKE 'Granola %' AND publisher = 'Granola';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Granola %' AND publisher = 'Granola' AND version_compare(version, '7.128.0') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Granola %' AND publisher = 'Granola' AND version_compare(version, '7.140.1') < 0);"
|
||||
},
|
||||
"installer_url": "https://api.granola.ai/v1/check-for-update/Granola-7.128.0-win-x64.exe",
|
||||
"installer_url": "https://api.granola.ai/v1/check-for-update/Granola-7.140.1-win-x64.exe",
|
||||
"install_script_ref": "3f66ac53",
|
||||
"uninstall_script_ref": "a4fab3f5",
|
||||
"sha256": "4ff0a9cec505f1e892f5b0ab90164c062d3aa17f1bbe4040c536c1672e32ca2c",
|
||||
"sha256": "9dfced2d0f94f8f9ef32c58cae3272f10cee1595f8b381f70bc92a3dc7941af9",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.4.1",
|
||||
"version": "1.4.2",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.colliderli.iina';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.colliderli.iina' AND version_compare(bundle_short_version, '1.4.1') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.colliderli.iina' AND version_compare(bundle_short_version, '1.4.2') < 0);"
|
||||
},
|
||||
"installer_url": "https://dl-portal.iina.io/IINA.v1.4.1.dmg",
|
||||
"installer_url": "https://dl-portal.iina.io/IINA.v1.4.2-build164.dmg",
|
||||
"install_script_ref": "18ab90f9",
|
||||
"uninstall_script_ref": "20f465cb",
|
||||
"sha256": "177ad469ea129bed95a82ac59b5fb58d0a06c35342fca7a37dba214a8821f848",
|
||||
"sha256": "804e3368518f19039ebfbc3d698e1fabc9cd20f15fc4e42de635456cdf6a7f58",
|
||||
"default_categories": [
|
||||
"Utilities"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "0.344.0",
|
||||
"version": "0.345.1",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.loom.desktop';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.loom.desktop' AND version_compare(bundle_short_version, '0.344.0') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.loom.desktop' AND version_compare(bundle_short_version, '0.345.1') < 0);"
|
||||
},
|
||||
"installer_url": "https://packages.loom.com/desktop-packages/Loom-0.344.0-arm64.dmg",
|
||||
"installer_url": "https://packages.loom.com/desktop-packages/Loom-0.345.1-arm64.dmg",
|
||||
"install_script_ref": "8185f7a5",
|
||||
"uninstall_script_ref": "393b959f",
|
||||
"sha256": "c5c561c45ce97d6bfaf344b0f12417165345e69a78dee3cfd02705e3c56b929d",
|
||||
"sha256": "dc837812b1e3255575e44e72b0a84f34b0f6500e91af32b234eb65f8fcd115ad",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "147.0.3912.60",
|
||||
"version": "147.0.3912.72",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.microsoft.edgemac';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.microsoft.edgemac' AND version_compare(bundle_short_version, '147.0.3912.60') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.microsoft.edgemac' AND version_compare(bundle_short_version, '147.0.3912.72') < 0);"
|
||||
},
|
||||
"installer_url": "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/b3b6a577-fc74-4bfe-b7a9-ee3a54e24a9a/MicrosoftEdge-147.0.3912.60.dmg",
|
||||
"installer_url": "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/897aa370-de25-41e0-9664-a7944796d7ee/MicrosoftEdge-147.0.3912.72.dmg",
|
||||
"install_script_ref": "b9ba259a",
|
||||
"uninstall_script_ref": "6ee9d9a4",
|
||||
"sha256": "89826009dce74190b59f40f64ebcee50243728d7206ca4bbe44c6e78d2e97462",
|
||||
"sha256": "6c1aaff7682af11d192e1fb9cadfdbccb2b2b68b58255a81d877a22a80b1eab8",
|
||||
"default_categories": [
|
||||
"Browsers"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "147.0.3912.60",
|
||||
"version": "147.0.3912.72",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name = 'Microsoft Edge' AND publisher = 'Microsoft Corporation';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Microsoft Edge' AND publisher = 'Microsoft Corporation' AND version_compare(version, '147.0.3912.60') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Microsoft Edge' AND publisher = 'Microsoft Corporation' AND version_compare(version, '147.0.3912.72') < 0);"
|
||||
},
|
||||
"installer_url": "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/5428dd4e-4363-469a-a2f5-e7d44afa501f/MicrosoftEdgeEnterpriseX64.msi",
|
||||
"installer_url": "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/a7793e3c-0595-419c-bfc9-a891c92c6e53/MicrosoftEdgeEnterpriseX64.msi",
|
||||
"install_script_ref": "8959087b",
|
||||
"uninstall_script_ref": "a173cfc1",
|
||||
"sha256": "b0c8fe30357b666beff27433b81d001df50af53b16a598e2c0e65dd66d1c1b35",
|
||||
"sha256": "f38cde736a1b9a538d85832ebba099e67f76c8c3ef781c559967c6ab95e1b130",
|
||||
"default_categories": [
|
||||
"Browsers"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "10.0.3",
|
||||
"version": "10.0.4",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.nordvpn.macos';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.nordvpn.macos' AND version_compare(bundle_short_version, '10.0.3') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.nordvpn.macos' AND version_compare(bundle_short_version, '10.0.4') < 0);"
|
||||
},
|
||||
"installer_url": "https://downloads.nordcdn.com/apps/macos/generic/NordVPN-OpenVPN/10.0.3/NordVPN.pkg",
|
||||
"installer_url": "https://downloads.nordcdn.com/apps/macos/generic/NordVPN-OpenVPN/10.0.4/NordVPN.pkg",
|
||||
"install_script_ref": "1fd3c81d",
|
||||
"uninstall_script_ref": "ebca7748",
|
||||
"sha256": "feb1eee445598ce3fd1b1440e345ed6ac484d351a3f8bf8b5be10b0d14e56fc4",
|
||||
"sha256": "dce634baebc9d9f78f4c2048ecb1345fb71426f8438d82b8e7c6a27ade012ec4",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.132.0",
|
||||
"version": "1.133.0",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.cron.electron';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.cron.electron' AND version_compare(bundle_short_version, '1.132.0') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.cron.electron' AND version_compare(bundle_short_version, '1.133.0') < 0);"
|
||||
},
|
||||
"installer_url": "https://calendar-desktop-release.notion-static.com/Notion%20Calendar-darwin-arm64-1.132.0.zip",
|
||||
"installer_url": "https://calendar-desktop-release.notion-static.com/Notion%20Calendar-darwin-arm64-1.133.0.zip",
|
||||
"install_script_ref": "85d6bd1a",
|
||||
"uninstall_script_ref": "0e018931",
|
||||
"sha256": "2c336bde3e3ab22a9ac2d2cbbe942947200db874a65a3837bf85c25ddb806371",
|
||||
"sha256": "3d8b73a890fa1b389535a580e13b7cb73cf8fbd32366ada0d56624b28b7cf1fb",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "0.20.7",
|
||||
"version": "0.21.0",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.electron.ollama';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.electron.ollama' AND version_compare(bundle_short_version, '0.20.7') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.electron.ollama' AND version_compare(bundle_short_version, '0.21.0') < 0);"
|
||||
},
|
||||
"installer_url": "https://github.com/ollama/ollama/releases/download/v0.20.7/Ollama-darwin.zip",
|
||||
"installer_url": "https://github.com/ollama/ollama/releases/download/v0.21.0/Ollama-darwin.zip",
|
||||
"install_script_ref": "306a3ea4",
|
||||
"uninstall_script_ref": "f60ddfee",
|
||||
"sha256": "74670dafa053a48aef8c7666100cf91f2a3c84fe88cee1a8293e7a7cb3442eea",
|
||||
"sha256": "700face7ac186443b627895863f5984cd760374dc12ad1dcb6279ae2d6ced7eb",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "0.20.7",
|
||||
"version": "0.21.0",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name = 'Ollama' AND publisher = 'Ollama';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Ollama' AND publisher = 'Ollama' AND version_compare(version, '0.20.7') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Ollama' AND publisher = 'Ollama' AND version_compare(version, '0.21.0') < 0);"
|
||||
},
|
||||
"installer_url": "https://github.com/ollama/ollama/releases/download/v0.20.7/OllamaSetup.exe",
|
||||
"installer_url": "https://github.com/ollama/ollama/releases/download/v0.21.0/OllamaSetup.exe",
|
||||
"install_script_ref": "e14c71ee",
|
||||
"uninstall_script_ref": "3f049b5d",
|
||||
"sha256": "eb67a3a654034cccd27bfb90639890a1071b857876a8393128f72e6edb671b0f",
|
||||
"sha256": "3ab56c0e0a4b2b61e172a1b938fc50b98b0f7ceb4064e9ea81cf3cccb07b0546",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "2.0.5",
|
||||
"version": "2.1.1",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'dev.kdrag0n.MacVirt';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.kdrag0n.MacVirt' AND version_compare(bundle_short_version, '2.0.5') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.kdrag0n.MacVirt' AND version_compare(bundle_short_version, '2.1.1') < 0);"
|
||||
},
|
||||
"installer_url": "https://cdn-updates.orbstack.dev/arm64/OrbStack_v2.0.5_19905_arm64.dmg",
|
||||
"installer_url": "https://cdn-updates.orbstack.dev/arm64/OrbStack_v2.1.1_20026_arm64.dmg",
|
||||
"install_script_ref": "3d018c85",
|
||||
"uninstall_script_ref": "401d288b",
|
||||
"sha256": "601889551cdfdc7feee148b7fdb0480fa0ba5c0db0be8f1c047fc840886a7571",
|
||||
"sha256": "18a41f759958e1fa0951696b820b5478d3ed7353f8ca486fe9d026a1a7d97207",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "26.3.0",
|
||||
"version": "26.3.1",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.parallels.desktop.console';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.parallels.desktop.console' AND version_compare(bundle_short_version, '26.3.0') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.parallels.desktop.console' AND version_compare(bundle_short_version, '26.3.1') < 0);"
|
||||
},
|
||||
"installer_url": "https://download.parallels.com/desktop/v26/26.3.0-57392/ParallelsDesktop-26.3.0-57392.dmg",
|
||||
"installer_url": "https://download.parallels.com/desktop/v26/26.3.1-57396/ParallelsDesktop-26.3.1-57396.dmg",
|
||||
"install_script_ref": "db96404a",
|
||||
"uninstall_script_ref": "117c49a4",
|
||||
"sha256": "a554e51976556ff43febf8bb074eca59bdca83ee4b9b4ebebf8111c548e85bba",
|
||||
"sha256": "ec0207f524578c53350fb017d702f855900900c67738ffdb225f188ad912c503",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "12.6.3",
|
||||
"version": "12.7.0",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.postmanlabs.mac';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.postmanlabs.mac' AND version_compare(bundle_short_version, '12.6.3') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.postmanlabs.mac' AND version_compare(bundle_short_version, '12.7.0') < 0);"
|
||||
},
|
||||
"installer_url": "https://dl.pstmn.io/download/version/12.6.3/osx_arm64",
|
||||
"installer_url": "https://dl.pstmn.io/download/version/12.7.0/osx_arm64",
|
||||
"install_script_ref": "b89b1fb9",
|
||||
"uninstall_script_ref": "15e9f11c",
|
||||
"sha256": "e03d51e679e895959ee40ef4f827aa227f91634c79ee2d3a3bdfd369b5a6de7b",
|
||||
"sha256": "c6dc1084cb40cc01edb65d2fb2bcf5e8ceea4fb129a65c0235c25eeed81b7770",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "12.6.3",
|
||||
"version": "12.7.0",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name LIKE 'Postman x64 %' AND publisher = 'Postman';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Postman x64 %' AND publisher = 'Postman' AND version_compare(version, '12.6.3') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Postman x64 %' AND publisher = 'Postman' AND version_compare(version, '12.7.0') < 0);"
|
||||
},
|
||||
"installer_url": "https://dl.pstmn.io/download/version/12.6.3/windows_64",
|
||||
"installer_url": "https://dl.pstmn.io/download/version/12.7.0/windows_64",
|
||||
"install_script_ref": "538f63bf",
|
||||
"uninstall_script_ref": "cd01b68f",
|
||||
"sha256": "ef677cc7ead3bef96174207d9bb202ec68bf9a66103d355ab40ded3ee81098d3",
|
||||
"sha256": "077849da6aa3adc674870e2d46209c5fa7e456535f3536af9529027a74cf69a4",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "4.5.4",
|
||||
"version": "4.5.5",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.luckymarmot.Paw';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.luckymarmot.Paw' AND version_compare(bundle_short_version, '4.5.4') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.luckymarmot.Paw' AND version_compare(bundle_short_version, '4.5.5') < 0);"
|
||||
},
|
||||
"installer_url": "https://cdn-builds.paw.cloud/paw/RapidAPI-4.5.4.zip",
|
||||
"installer_url": "https://cdn-builds.paw.cloud/paw/RapidAPI-4.5.5.zip",
|
||||
"install_script_ref": "1c8ec07f",
|
||||
"uninstall_script_ref": "eb82b992",
|
||||
"sha256": "cc8953efdde6eb142c294001d4dec30b49d1389513a7cecd7ad87eaf7c1f7991",
|
||||
"sha256": "d5447b2e3ff87dd870608be55a3b28f2d1833bed2c1fc5e48b2b173768baffbf",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "5.2.0",
|
||||
"version": "5.2.1",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.sequelace.SequelAce';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.sequelace.SequelAce' AND version_compare(bundle_short_version, '5.2.0') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.sequelace.SequelAce' AND version_compare(bundle_short_version, '5.2.1') < 0);"
|
||||
},
|
||||
"installer_url": "https://github.com/Sequel-Ace/Sequel-Ace/releases/download/production/5.2.0-20099/Sequel-Ace-5.2.0.zip",
|
||||
"installer_url": "https://github.com/Sequel-Ace/Sequel-Ace/releases/download/production/5.2.1-20100/Sequel-Ace-5.2.1.zip",
|
||||
"install_script_ref": "a24ed130",
|
||||
"uninstall_script_ref": "36152630",
|
||||
"sha256": "17d3866a7d973b13d11792eb2c17141fb1885ab5f6f801e0462961d3faa5d598",
|
||||
"sha256": "f041ddab14b995b83f0746f6473fa833ecc525a5c08045dc2614217e0258453f",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.2.87.414",
|
||||
"version": "1.2.87.415",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.spotify.client';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.spotify.client' AND version_compare(bundle_short_version, '1.2.87.414') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.spotify.client' AND version_compare(bundle_short_version, '1.2.87.415') < 0);"
|
||||
},
|
||||
"installer_url": "https://download.scdn.co/SpotifyARM64.dmg",
|
||||
"install_script_ref": "d4b8bdad",
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.2.87.414.g4e7a1155",
|
||||
"version": "1.2.87.415.g88652836",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM programs WHERE name = 'Spotify' AND publisher = 'Spotify AB';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Spotify' AND publisher = 'Spotify AB' AND version_compare(version, '1.2.87.414.g4e7a1155') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Spotify' AND publisher = 'Spotify AB' AND version_compare(version, '1.2.87.415.g88652836') < 0);"
|
||||
},
|
||||
"installer_url": "https://download.scdn.co/SpotifyFullSetupX64.exe",
|
||||
"install_script_ref": "7e4727ac",
|
||||
"uninstall_script_ref": "48d55e3d",
|
||||
"sha256": "c2e640ed2dbeefcf2f6266659a6a1a03f4110f05e4499b91951755febc9929d6",
|
||||
"sha256": "c82b19e0f74df1f274e104cb1c8f6c241319ca7e43c78ff789029fcd0fc4db33",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "2.12.9",
|
||||
"version": "2.12.11",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'eu.exelban.Stats';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'eu.exelban.Stats' AND version_compare(bundle_short_version, '2.12.9') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'eu.exelban.Stats' AND version_compare(bundle_short_version, '2.12.11') < 0);"
|
||||
},
|
||||
"installer_url": "https://github.com/exelban/stats/releases/download/v2.12.9/Stats.dmg",
|
||||
"installer_url": "https://github.com/exelban/stats/releases/download/v2.12.11/Stats.dmg",
|
||||
"install_script_ref": "3de99bb8",
|
||||
"uninstall_script_ref": "4222ba77",
|
||||
"sha256": "0d6d6dde8956a72c597e4e41af07063d07ced2df9a395adcff2a8bc171d89a4e",
|
||||
"sha256": "41edc5bc9c6a4503f9b48826ea1040ea3b94f76221f0801788c8714d18924093",
|
||||
"default_categories": [
|
||||
"Productivity"
|
||||
]
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -6,7 +6,7 @@
|
|||
"exists": "SELECT 1 FROM programs WHERE name = 'Telegram Desktop' AND publisher = 'Telegram FZ-LLC';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Telegram Desktop' AND publisher = 'Telegram FZ-LLC' AND version_compare(version, '6.7.6') < 0);"
|
||||
},
|
||||
"installer_url": "https://td.telegram.org/tx64/tsetup-x64.6.7.6.exe",
|
||||
"installer_url": "https://github.com/telegramdesktop/tdesktop/releases/download/v6.7.6/tsetup-x64.6.7.6.exe",
|
||||
"install_script_ref": "0b88a95e",
|
||||
"uninstall_script_ref": "42311f1b",
|
||||
"sha256": "8b77909856093627788a8dca744e48a30fa3f28db2cec80dc1c72cebf83f40b5",
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "0.2026.04.08.08.36.05",
|
||||
"version": "0.2026.04.15.08.45.02",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'dev.warp.Warp-Stable';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.warp.Warp-Stable' AND version_compare(bundle_short_version, '0.2026.04.08.08.36.05') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.warp.Warp-Stable' AND version_compare(bundle_short_version, '0.2026.04.15.08.45.02') < 0);"
|
||||
},
|
||||
"installer_url": "https://releases.warp.dev/stable/v0.2026.04.08.08.36.stable_05/Warp.dmg",
|
||||
"installer_url": "https://releases.warp.dev/stable/v0.2026.04.15.08.45.stable_02/Warp.dmg",
|
||||
"install_script_ref": "01373831",
|
||||
"uninstall_script_ref": "54d05203",
|
||||
"sha256": "no_check",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "26.15.20",
|
||||
"version": "26.16.15",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'net.whatsapp.WhatsApp';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'net.whatsapp.WhatsApp' AND version_compare(bundle_short_version, '26.15.20') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'net.whatsapp.WhatsApp' AND version_compare(bundle_short_version, '26.16.15') < 0);"
|
||||
},
|
||||
"installer_url": "https://web.whatsapp.com/desktop/mac_native/release/?configuration=Release&src=whatsapp_downloads_page",
|
||||
"install_script_ref": "f2b910d2",
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "2.0.50",
|
||||
"version": "2.0.61",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.exafunction.windsurf';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.exafunction.windsurf' AND version_compare(bundle_short_version, '2.0.50') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.exafunction.windsurf' AND version_compare(bundle_short_version, '2.0.61') < 0);"
|
||||
},
|
||||
"installer_url": "https://windsurf-stable.codeiumdata.com/darwin-arm64-dmg/stable/c973f91b37b89375b5b009109c2fe84d185fab48/Windsurf-darwin-arm64-2.0.50.dmg",
|
||||
"installer_url": "https://windsurf-stable.codeiumdata.com/darwin-arm64-dmg/stable/abcd9c8664da5af505557f3b327b5537400635f2/Windsurf-darwin-arm64-2.0.61.dmg",
|
||||
"install_script_ref": "c8855980",
|
||||
"uninstall_script_ref": "461afb53",
|
||||
"sha256": "4ef3563a37133a12a97cfa26a4febb5ba7877da9abbbfd0897deb2b267c028b0",
|
||||
"sha256": "53010c8710535ee78f2f28c7afbe94fd8ff2738b0b1b2587c684c42e721dc086",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "0.232.2",
|
||||
"version": "0.232.3",
|
||||
"queries": {
|
||||
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'dev.zed.Zed';",
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.zed.Zed' AND version_compare(bundle_short_version, '0.232.2') < 0);"
|
||||
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.zed.Zed' AND version_compare(bundle_short_version, '0.232.3') < 0);"
|
||||
},
|
||||
"installer_url": "https://zed.dev/api/releases/stable/0.232.2/Zed-aarch64.dmg",
|
||||
"installer_url": "https://zed.dev/api/releases/stable/0.232.3/Zed-aarch64.dmg",
|
||||
"install_script_ref": "b0e5ef67",
|
||||
"uninstall_script_ref": "a96df5e9",
|
||||
"sha256": "82717ddea4c03ad033a9c99d1440d1b71d6f6141b02eedd1aa1cb8eb3dcb938f",
|
||||
"sha256": "2f6ca2b175772e57c1d5b2893f8c8556e16581341f9568ee0ce4f84f5128b488",
|
||||
"default_categories": [
|
||||
"Developer tools"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1338,7 +1338,7 @@ func (svc *Service) mdmAppleEditedAppleOSUpdates(ctx context.Context, teamID *ui
|
|||
{LabelName: labelName, LabelID: lblIDs[labelName]},
|
||||
}
|
||||
|
||||
decl, err := svc.ds.SetOrUpdateMDMAppleDeclaration(ctx, d)
|
||||
decl, err := svc.ds.SetOrUpdateMDMAppleDeclaration(ctx, d, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ func TestGetOrCreatePreassignTeam(t *testing.T) {
|
|||
require.ElementsMatch(t, names, []string{fleet.BuiltinLabelMacOS14Plus})
|
||||
return map[string]uint{names[0]: 1}, nil
|
||||
}
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
|
||||
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
|
||||
declaration.DeclarationUUID = uuid.NewString()
|
||||
return declaration, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ interface IActionsDropdownProps {
|
|||
menuAlign?: "right" | "left" | "default";
|
||||
menuPlacement?: "top" | "bottom" | "auto";
|
||||
variant?: "button" | "brand-button" | "small-button";
|
||||
buttonLabel?: string;
|
||||
}
|
||||
|
||||
const getOptionBackgroundColor = (state: { isFocused: boolean }) => {
|
||||
|
|
@ -122,6 +123,7 @@ const ActionsDropdown = ({
|
|||
menuAlign = "default",
|
||||
menuPlacement = "bottom",
|
||||
variant,
|
||||
buttonLabel,
|
||||
}: IActionsDropdownProps): JSX.Element => {
|
||||
const dropdownClassnames = classnames(baseClass, className);
|
||||
|
||||
|
|
@ -161,7 +163,7 @@ const ActionsDropdown = ({
|
|||
aria-haspopup="listbox"
|
||||
aria-expanded={menuIsOpen}
|
||||
>
|
||||
<span>Actions</span>
|
||||
<span>{buttonLabel || "Actions"}</span>
|
||||
<Icon
|
||||
name="chevron-down"
|
||||
color="core-fleet-white"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,16 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $pad-medium;
|
||||
|
||||
// Hardcoded to fit all 3 custom target options (Exclude any, Include all,
|
||||
// Include any) without scrolling
|
||||
.Select-menu-outer {
|
||||
max-height: 260px;
|
||||
}
|
||||
|
||||
.Select-menu {
|
||||
max-height: 244px;
|
||||
}
|
||||
}
|
||||
|
||||
&__checkboxes {
|
||||
|
|
|
|||
12
frontend/interfaces/api_endpoint.ts
Normal file
12
frontend/interfaces/api_endpoint.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
export interface IApiEndpointRef {
|
||||
method: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
export interface IApiEndpoint extends IApiEndpointRef {
|
||||
display_name: string;
|
||||
deprecated: boolean;
|
||||
}
|
||||
|
||||
/** Unique key for an endpoint since there's no `id` field */
|
||||
export const endpointKey = (ep: IApiEndpointRef) => `${ep.method} ${ep.path}`;
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import PropTypes from "prop-types";
|
||||
import teamInterface, { ITeam } from "./team";
|
||||
import { IUserSettings } from "./config";
|
||||
import { IApiEndpointRef } from "./api_endpoint";
|
||||
|
||||
export default PropTypes.shape({
|
||||
created_at: PropTypes.string,
|
||||
|
|
@ -59,6 +60,7 @@ export interface IUser {
|
|||
api_only: boolean;
|
||||
teams: ITeam[];
|
||||
fleets: ITeam[]; // This will eventually replace `teams`, but for now we need both to avoid breaking changes.
|
||||
api_endpoints?: IApiEndpointRef[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -80,6 +82,8 @@ export interface IUserFormErrors {
|
|||
name?: string | null;
|
||||
password?: string | null;
|
||||
sso_enabled?: boolean | null;
|
||||
api_endpoints?: string | null;
|
||||
teams?: string | null;
|
||||
}
|
||||
export interface IResetPasswordFormErrors {
|
||||
new_password?: string | null;
|
||||
|
|
@ -97,7 +101,7 @@ export interface ILoginUserData {
|
|||
}
|
||||
|
||||
export interface ICreateUserFormData {
|
||||
email: string;
|
||||
email?: string;
|
||||
global_role: UserRole | null;
|
||||
name: string;
|
||||
password?: string | null;
|
||||
|
|
|
|||
14
frontend/pages/SoftwarePage/components/icons/DruvaInSync.tsx
Normal file
14
frontend/pages/SoftwarePage/components/icons/DruvaInSync.tsx
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -10,6 +10,7 @@ import BetterDisplay from "./BetterDisplay";
|
|||
import Charles from "./Charles";
|
||||
import ConnectFonts from "./ConnectFonts";
|
||||
import CrashPlan from "./CrashPlan";
|
||||
import DruvaInSync from "./DruvaInSync";
|
||||
import GoogleCredentialProviderForWindows from "./GoogleCredentialProviderForWindows";
|
||||
import Iina from "./Iina";
|
||||
import Kitty from "./Kitty";
|
||||
|
|
@ -316,6 +317,7 @@ export const SOFTWARE_NAME_TO_ICON_MAP = {
|
|||
crashplan: CrashPlan,
|
||||
"google credential provider for windows": GoogleCredentialProviderForWindows,
|
||||
iina: Iina,
|
||||
insyncclient: DruvaInSync,
|
||||
kitty: Kitty,
|
||||
krita: Krita,
|
||||
lastpass: LastPass,
|
||||
|
|
|
|||
|
|
@ -188,19 +188,34 @@ export const CUSTOM_TARGET_OPTIONS: IDropdownOption[] = [
|
|||
{
|
||||
value: "labelsIncludeAny",
|
||||
label: "Include any",
|
||||
helpText: "Hosts that have any of the selected labels.",
|
||||
helpText: (
|
||||
<>
|
||||
Software will only be available for install on hosts that{" "}
|
||||
<strong>have any</strong> of these labels.
|
||||
</>
|
||||
),
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
value: "labelsIncludeAll",
|
||||
label: "Include all",
|
||||
helpText: "Hosts that have all of the selected labels.",
|
||||
helpText: (
|
||||
<>
|
||||
Software will only be available for install on hosts that{" "}
|
||||
<strong>have all</strong> of these labels.
|
||||
</>
|
||||
),
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
value: "labelsExcludeAny",
|
||||
label: "Exclude any",
|
||||
helpText: "Hosts that don't have any of the selected labels.",
|
||||
helpText: (
|
||||
<>
|
||||
Software will only be available for install on hosts that{" "}
|
||||
<strong>don't have any</strong> of these labels.
|
||||
</>
|
||||
),
|
||||
disabled: false,
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -301,64 +301,68 @@ const Calendars = ({ appConfig }: IAppConfigFormProps): JSX.Element => {
|
|||
work calendar.)
|
||||
</li>
|
||||
<li>
|
||||
Save your changes.
|
||||
<Card>
|
||||
<form onSubmit={onFormSubmit} autoComplete="off">
|
||||
<InputField
|
||||
label="API key JSON"
|
||||
onChange={onInputChange}
|
||||
name="apiKeyJson"
|
||||
value={apiKeyJson}
|
||||
parseTarget
|
||||
type="textarea"
|
||||
placeholder={API_KEY_JSON_PLACEHOLDER}
|
||||
ignore1password
|
||||
inputClassName={`${baseClass}__api-key-json`}
|
||||
error={formErrors.apiKeyJson}
|
||||
disabled={gomEnabled}
|
||||
helpText={
|
||||
apiKeyJson === UNCHANGED_PASSWORD_API_RESPONSE
|
||||
? "API key is configured. Replace with a new key to update."
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
<InputField
|
||||
label="Primary domain"
|
||||
onChange={onInputChange}
|
||||
name="domain"
|
||||
value={domain}
|
||||
parseTarget
|
||||
placeholder="example.com"
|
||||
helpText={
|
||||
<>
|
||||
You can find your primary domain in Google Workspace{" "}
|
||||
<CustomLink
|
||||
url={GOOGLE_WORKSPACE_DOMAINS}
|
||||
text="here"
|
||||
newTab
|
||||
/>
|
||||
</>
|
||||
}
|
||||
error={formErrors.domain}
|
||||
disabled={gomEnabled}
|
||||
/>
|
||||
<div className="button-wrap">
|
||||
<GitOpsModeTooltipWrapper
|
||||
tipOffset={8}
|
||||
renderChildren={(dC) => (
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={Object.keys(formErrors).length > 0 || dC}
|
||||
className="save-loading"
|
||||
isLoading={isUpdatingSettings}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
)}
|
||||
<div className={`${baseClass}__save-changes`}>
|
||||
Save your changes.
|
||||
<Card>
|
||||
<form onSubmit={onFormSubmit} autoComplete="off">
|
||||
<InputField
|
||||
label="API key JSON"
|
||||
onChange={onInputChange}
|
||||
name="apiKeyJson"
|
||||
value={apiKeyJson}
|
||||
parseTarget
|
||||
type="textarea"
|
||||
placeholder={API_KEY_JSON_PLACEHOLDER}
|
||||
ignore1password
|
||||
inputClassName={`${baseClass}__api-key-json`}
|
||||
error={formErrors.apiKeyJson}
|
||||
disabled={gomEnabled}
|
||||
helpText={
|
||||
apiKeyJson === UNCHANGED_PASSWORD_API_RESPONSE
|
||||
? "API key is configured. Replace with a new key to update."
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</Card>
|
||||
<InputField
|
||||
label="Primary domain"
|
||||
onChange={onInputChange}
|
||||
name="domain"
|
||||
value={domain}
|
||||
parseTarget
|
||||
placeholder="example.com"
|
||||
helpText={
|
||||
<>
|
||||
You can find your primary domain in Google Workspace{" "}
|
||||
<CustomLink
|
||||
url={GOOGLE_WORKSPACE_DOMAINS}
|
||||
text="here"
|
||||
newTab
|
||||
/>
|
||||
</>
|
||||
}
|
||||
error={formErrors.domain}
|
||||
disabled={gomEnabled}
|
||||
/>
|
||||
<div className="button-wrap">
|
||||
<GitOpsModeTooltipWrapper
|
||||
tipOffset={8}
|
||||
renderChildren={(dC) => (
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={
|
||||
Object.keys(formErrors).length > 0 || dC
|
||||
}
|
||||
className="save-loading"
|
||||
isLoading={isUpdatingSettings}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</Card>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
|
@ -389,15 +393,16 @@ const Calendars = ({ appConfig }: IAppConfigFormProps): JSX.Element => {
|
|||
account.
|
||||
</li>
|
||||
<li>
|
||||
For the OAuth scopes, paste the following value:
|
||||
<InputField
|
||||
readOnly
|
||||
inputWrapperClass={`${baseClass}__oauth-scopes`}
|
||||
name="oauth-scopes"
|
||||
enableCopy
|
||||
type="textarea"
|
||||
value={OAUTH_SCOPES}
|
||||
/>
|
||||
<div className={`${baseClass}__oauth-scopes`}>
|
||||
For the OAuth scopes, paste the following value:
|
||||
<InputField
|
||||
readOnly
|
||||
name="oauth-scopes"
|
||||
enableCopy
|
||||
type="textarea"
|
||||
value={OAUTH_SCOPES}
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
Click <b>Authorize</b>.
|
||||
|
|
|
|||
|
|
@ -19,10 +19,6 @@
|
|||
margin: $pad-small 0;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin-top: $pad-small;
|
||||
}
|
||||
|
||||
&__configuration {
|
||||
button {
|
||||
align-self: flex-end;
|
||||
|
|
@ -36,12 +32,18 @@
|
|||
font-size: $x-small;
|
||||
}
|
||||
|
||||
&__save-changes,
|
||||
&__oauth-scopes {
|
||||
@include vertical-form-layout;
|
||||
padding-bottom: $pad-large;
|
||||
}
|
||||
|
||||
#oauth-scopes {
|
||||
font-family: "SourceCodePro", $monospace;
|
||||
color: $core-fleet-black;
|
||||
min-height: 82px;
|
||||
min-width: 100%;
|
||||
padding: $pad-medium;
|
||||
padding-right: $pad-xxlarge;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
&__learn-more-link {
|
||||
// used to keep the "Learn more" text content on a single line.
|
||||
min-width: 88px;
|
||||
min-width: max-content;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -233,7 +233,6 @@ const AppleBusinessManagerPage = ({ router }: { router: InjectedRouter }) => {
|
|||
{showRenewModal && selectedToken.current && (
|
||||
<RenewAbmModal
|
||||
tokenId={selectedToken.current.id}
|
||||
orgName={selectedToken.current.org_name}
|
||||
onCancel={onCancelRenewToken}
|
||||
onRenewedToken={onRenewed}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -52,73 +52,15 @@ const AddAbmModal = ({ onCancel, onAdded }: IAddAbmModalProps) => {
|
|||
|
||||
return (
|
||||
<Modal className={baseClass} title="Add AB" onExit={onCancel} width="large">
|
||||
<ol className={`${baseClass}__setup-list`}>
|
||||
<li>
|
||||
<span>1.</span>
|
||||
<p>
|
||||
Download your public key. <DownloadABMKey baseClass={baseClass} />
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<span>2.</span>
|
||||
<span>
|
||||
<span>
|
||||
Sign in to{" "}
|
||||
<CustomLink
|
||||
newTab
|
||||
text="Apple Business"
|
||||
url="https://business.apple.com"
|
||||
/>
|
||||
<br />
|
||||
If your organization doesn't have an account, select{" "}
|
||||
<b>Enroll now</b>.
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>3.</span>
|
||||
<span>
|
||||
Select your <b>account name</b> at the bottom left of the screen,
|
||||
then select <b>Preferences</b>.
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>4.</span>
|
||||
<span>
|
||||
In the <b>Your MDM Servers</b> section, select <b>Add</b>.
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>5.</span>
|
||||
<span>Enter a name for the server such as "Fleet".</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>6.</span>
|
||||
<span>
|
||||
Under <b>MDM Server Settings</b>, upload the public key downloaded
|
||||
in the first step and select <b>Save</b>.
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>7.</span>
|
||||
<span>
|
||||
In the <b>Default Device Assignment</b> section, select{" "}
|
||||
<b>Change</b>, then assign the newly created server as the default
|
||||
for your Macs, iPhones, and iPads. Then select <b>Done</b>.
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>8.</span>
|
||||
<span>
|
||||
Select newly created server in the sidebar, then select{" "}
|
||||
<b>Download MDM Server Token</b> on the top.
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>9.</span>
|
||||
<span>Upload the downloaded token (.p7m file).</span>
|
||||
</li>
|
||||
</ol>
|
||||
<p>
|
||||
Follow the step-by-step guide to connect Fleet to Apple Business
|
||||
Manager.{" "}
|
||||
<CustomLink
|
||||
url="https://fleetdm.com/learn-more-about/setup-abm"
|
||||
text="Learn how"
|
||||
newTab
|
||||
/>
|
||||
</p>
|
||||
<FileUploader
|
||||
className={`${baseClass}__file-uploader ${
|
||||
isUploading ? `${baseClass}__file-uploader--loading` : ""
|
||||
|
|
@ -139,6 +81,7 @@ const AddAbmModal = ({ onCancel, onAdded }: IAddAbmModalProps) => {
|
|||
>
|
||||
Add AB
|
||||
</Button>
|
||||
<DownloadABMKey baseClass={baseClass} />
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
.add-abm-modal {
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__request-button {
|
||||
display: flex;
|
||||
gap: $pad-small;
|
||||
align-items: center;
|
||||
margin-top: $pad-small;
|
||||
|
||||
label {
|
||||
display: flex;
|
||||
|
|
@ -13,33 +16,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
&__setup-list {
|
||||
font-size: $x-small;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $pad-large;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
max-width: 660px;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: $pad-small;
|
||||
|
||||
p {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__file-uploader {
|
||||
margin-top: $pad-medium;
|
||||
margin-left: $pad-medium;
|
||||
|
||||
.file-uploader__message {
|
||||
color: $ui-fleet-black-75;
|
||||
|
|
|
|||
|
|
@ -14,14 +14,12 @@ const baseClass = "renew-abm-modal";
|
|||
|
||||
interface IRenewAbmModalProps {
|
||||
tokenId: number;
|
||||
orgName: string;
|
||||
onCancel: () => void;
|
||||
onRenewedToken: () => void;
|
||||
}
|
||||
|
||||
const RenewAbmModal = ({
|
||||
tokenId,
|
||||
orgName,
|
||||
onCancel,
|
||||
onRenewedToken,
|
||||
}: IRenewAbmModalProps) => {
|
||||
|
|
@ -65,31 +63,24 @@ const RenewAbmModal = ({
|
|||
width="large"
|
||||
>
|
||||
<div className={`${baseClass}__page-content ${baseClass}__setup-content`}>
|
||||
<p className={`${baseClass}__description`}>
|
||||
Renew Apple Business for <b>{orgName}</b> by uploading your AB token.{" "}
|
||||
<p>
|
||||
Follow the step-by-step guide to renew.{" "}
|
||||
<CustomLink
|
||||
url="https://fleetdm.com/learn-more-about/renew-abm"
|
||||
text="Learn how"
|
||||
newTab
|
||||
text="Learn more"
|
||||
url="https://fleetdm.com/guides/apple-mdm-setup#to-renew-an-abm-token"
|
||||
/>
|
||||
</p>
|
||||
<ul className={`${baseClass}__setup-instructions-list`}>
|
||||
<li>
|
||||
<p>
|
||||
Upload the downloaded token (.p7m file) below.
|
||||
<FileUploader
|
||||
className={`${baseClass}__file-uploader`}
|
||||
accept=".p7m"
|
||||
buttonMessage="Choose file"
|
||||
buttonType="brand-inverse-icon"
|
||||
graphicName="file-p7m"
|
||||
message="AB token (.p7m)"
|
||||
onFileUpload={onSelectFile}
|
||||
fileDetails={tokenFile ? { name: tokenFile.name } : undefined}
|
||||
/>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
<FileUploader
|
||||
className={`${baseClass}__file-uploader`}
|
||||
accept=".p7m"
|
||||
buttonMessage="Choose file"
|
||||
buttonType="brand-inverse-icon"
|
||||
graphicName="file-p7m"
|
||||
message="AB token (.p7m)"
|
||||
onFileUpload={onSelectFile}
|
||||
fileDetails={tokenFile ? { name: tokenFile.name } : undefined}
|
||||
/>
|
||||
<div className="modal-cta-wrap">
|
||||
<Button
|
||||
className={`${baseClass}__submit-button ${
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
&__setup-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $pad-large;
|
||||
gap: $pad-medium;
|
||||
color: $core-fleet-black;
|
||||
|
||||
p {
|
||||
|
|
@ -11,25 +11,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
&__setup-instructions-list {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $pad-large;
|
||||
|
||||
li > p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&__file-uploader {
|
||||
margin-top: $pad-medium;
|
||||
margin-left: $pad-medium;
|
||||
}
|
||||
|
||||
&__button-wrap {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
|
|
|||
|
|
@ -210,7 +210,6 @@ const VppPage = ({ router }: IVppPageProps) => {
|
|||
{showRenewModal && selectedToken.current && (
|
||||
<RenewVppModal
|
||||
tokenId={selectedToken.current.id}
|
||||
orgName={selectedToken.current.org_name}
|
||||
onCancel={onCancelRenewToken}
|
||||
onRenewedToken={onRenewed}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ import mdmAppleAPI from "services/entities/mdm_apple";
|
|||
|
||||
import Modal from "components/Modal";
|
||||
import Button from "components/buttons/Button";
|
||||
import CustomLink from "components/CustomLink";
|
||||
import FileUploader from "components/FileUploader";
|
||||
|
||||
import VppSetupSteps from "../VppSetupSteps";
|
||||
import { getErrorMessage } from "./helpers";
|
||||
|
||||
const baseClass = "add-vpp-modal";
|
||||
|
|
@ -57,7 +57,14 @@ const AddVppModal = ({ onCancel, onAdded }: IAddVppModalProps) => {
|
|||
onExit={onCancel}
|
||||
width="large"
|
||||
>
|
||||
<VppSetupSteps extendendSteps />
|
||||
<p className={`${baseClass}__description`}>
|
||||
Follow the step-by-step guide to add VPP.{" "}
|
||||
<CustomLink
|
||||
url="https://fleetdm.com/learn-more-about/add-vpp"
|
||||
text="Learn how"
|
||||
newTab
|
||||
/>
|
||||
</p>
|
||||
<FileUploader
|
||||
className={`${baseClass}__file-uploader ${
|
||||
isUploading ? `${baseClass}__file-uploader--loading` : ""
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
.add-vpp-modal {
|
||||
|
||||
&__description {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__request-button {
|
||||
display: flex;
|
||||
gap: $pad-small;
|
||||
|
|
@ -39,7 +43,6 @@
|
|||
|
||||
&__file-uploader {
|
||||
margin-top: $pad-medium;
|
||||
margin-left: $pad-medium;
|
||||
|
||||
.file-uploader__message {
|
||||
color: $ui-fleet-black-75;
|
||||
|
|
|
|||
|
|
@ -5,23 +5,21 @@ import { NotificationContext } from "context/notification";
|
|||
import mdmAppleAPI from "services/entities/mdm_apple";
|
||||
|
||||
import Button from "components/buttons/Button";
|
||||
import CustomLink from "components/CustomLink";
|
||||
import { FileUploader } from "components/FileUploader/FileUploader";
|
||||
import Modal from "components/Modal";
|
||||
import VppSetupSteps from "../VppSetupSteps";
|
||||
import { getErrorMessage } from "./helpers";
|
||||
|
||||
const baseClass = "modal renew-vpp-modal";
|
||||
|
||||
interface IRenewVppModalProps {
|
||||
tokenId: number;
|
||||
orgName: string;
|
||||
onCancel: () => void;
|
||||
onRenewedToken: () => void;
|
||||
}
|
||||
|
||||
const RenewVppModal = ({
|
||||
tokenId,
|
||||
orgName,
|
||||
onCancel,
|
||||
onRenewedToken,
|
||||
}: IRenewVppModalProps) => {
|
||||
|
|
@ -68,9 +66,13 @@ const RenewVppModal = ({
|
|||
width="large"
|
||||
>
|
||||
<p className={`${baseClass}__description`}>
|
||||
Renew Volume Purchasing Program for <b>{orgName}</b> location.
|
||||
Follow the step-by-step guide to renew.{" "}
|
||||
<CustomLink
|
||||
url="https://fleetdm.com/learn-more-about/renew-vpp"
|
||||
text="Learn how"
|
||||
newTab
|
||||
/>
|
||||
</p>
|
||||
<VppSetupSteps />
|
||||
<FileUploader
|
||||
className={`${baseClass}__file-uploader`}
|
||||
accept=".vpptoken"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
.renew-vpp-modal {
|
||||
|
||||
&__description {
|
||||
margin: 0 0 $pad-large;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__file-uploader {
|
||||
margin-top: $pad-medium;
|
||||
margin-left: $pad-medium;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
import CustomLink from "components/CustomLink";
|
||||
import React from "react";
|
||||
|
||||
const baseClass = "vpp-setup-steps";
|
||||
|
||||
interface IVppSetupStepsProps {
|
||||
/** This prop is used to display additional setup steps content. We have this
|
||||
* because some places that use this component show additional content.
|
||||
*/
|
||||
extendendSteps?: boolean;
|
||||
}
|
||||
|
||||
const VppSetupSteps = ({ extendendSteps = false }: IVppSetupStepsProps) => {
|
||||
return (
|
||||
<ol className={baseClass}>
|
||||
<li>
|
||||
<span>1.</span>
|
||||
<p>
|
||||
Sign in to{" "}
|
||||
<CustomLink
|
||||
newTab
|
||||
url="https://business.apple.com"
|
||||
text="Apple Business"
|
||||
/>
|
||||
{extendendSteps && (
|
||||
<>
|
||||
<br />
|
||||
If your organization doesn't have an account, select{" "}
|
||||
<b>Sign up now</b>.
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<span>2.</span>
|
||||
<p>
|
||||
Select your <b>account name</b> at the bottom left of the screen, then
|
||||
select <b>Preferences</b>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<span>3.</span>
|
||||
<p>
|
||||
Select <b>Payments and Billing</b> in the menu.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<span>4.</span>
|
||||
<p>
|
||||
Under the <b>Content Tokens</b>, download the token for the location
|
||||
you want to use.
|
||||
{extendendSteps && (
|
||||
<>
|
||||
<br /> Each token is based on a location in Apple Business.
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<span>5.</span>
|
||||
<p>Upload content token (.vpptoken file) below.</p>
|
||||
</li>
|
||||
</ol>
|
||||
);
|
||||
};
|
||||
|
||||
export default VppSetupSteps;
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue