winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 128607f43088642d1c1f0b9160bea649011c03ca
parent d0039d013f9be8274055b8df2c539acf26e228d5
Author: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date:   Wed, 30 Aug 2023 11:37:52 -0700

Improve rest client manifest parsing for upgrade behavior deny (#3570)


Diffstat:
Msrc/AppInstallerCLICore/Workflows/InstallFlow.cpp | 3++-
Msrc/AppInstallerCLITests/RestInterface_1_6.cpp | 4++--
Msrc/AppInstallerCLITests/TestData/MultiFileManifestV1_6/ManifestV1_6-MultiFile-Installer.yaml | 1+
Msrc/AppInstallerCLITests/YamlManifest.cpp | 1+
Msrc/AppInstallerRepositoryCore/Rest/Schema/1_0/Json/ManifestDeserializer.h | 2++
Msrc/AppInstallerRepositoryCore/Rest/Schema/1_0/Json/ManifestDeserializer_1_0.cpp | 18+++++++++++++++++-
Msrc/AppInstallerRepositoryCore/Rest/Schema/1_1/Json/ManifestDeserializer_1_1.cpp | 2+-
Msrc/AppInstallerRepositoryCore/Rest/Schema/1_6/Json/ManifestDeserializer.h | 2++
Msrc/AppInstallerRepositoryCore/Rest/Schema/1_6/Json/ManifestDeserializer_1_6.cpp | 12++++++++++++
9 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/src/AppInstallerCLICore/Workflows/InstallFlow.cpp b/src/AppInstallerCLICore/Workflows/InstallFlow.cpp @@ -590,6 +590,7 @@ namespace AppInstaller::CLI::Workflow // Implementation of de-elevation is complex; simply block for now. if (installer->ElevationRequirement == ElevationRequirementEnum::ElevationProhibited && Runtime::IsRunningAsAdmin()) { + AICLI_LOG(CLI, Error, << "The installer cannot be run from an administrator context."); context.Reporter.Error() << Resource::String::InstallerProhibitsElevation << std::endl; AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_INSTALLER_PROHIBITS_ELEVATION); } @@ -600,7 +601,7 @@ namespace AppInstaller::CLI::Workflow UpdateBehaviorEnum updateBehavior = installer->UpdateBehavior; if (isUpdate && (updateBehavior == UpdateBehaviorEnum::Deny)) { - AICLI_LOG(CLI, Info, << "Manifest specifies update behavior is denied. The attempt will be cancelled."); + AICLI_LOG(CLI, Error, << "Manifest specifies update behavior is denied. The attempt will be cancelled."); context.Reporter.Error() << Resource::String::UpgradeBlockedByManifest << std::endl; AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED); } diff --git a/src/AppInstallerCLITests/RestInterface_1_6.cpp b/src/AppInstallerCLITests/RestInterface_1_6.cpp @@ -157,7 +157,7 @@ namespace "InstallerSuccessCodes": [ 0 ], - "UpgradeBehavior": "install", + "UpgradeBehavior": "deny", "Commands": [ "command1" ], @@ -337,7 +337,7 @@ namespace REQUIRE(actualInstaller.Switches.at(InstallerSwitchType::Custom) == "/custom"); REQUIRE(actualInstaller.InstallerSuccessCodes.size() == 1); REQUIRE(actualInstaller.InstallerSuccessCodes.at(0) == 0); - REQUIRE(actualInstaller.UpdateBehavior == UpdateBehaviorEnum::Install); + REQUIRE(actualInstaller.UpdateBehavior == UpdateBehaviorEnum::Deny); REQUIRE(actualInstaller.Commands.at(0) == "command1"); REQUIRE(actualInstaller.Protocols.at(0) == "protocol1"); REQUIRE(actualInstaller.FileExtensions.at(0) == ".file-extension"); diff --git a/src/AppInstallerCLITests/TestData/MultiFileManifestV1_6/ManifestV1_6-MultiFile-Installer.yaml b/src/AppInstallerCLITests/TestData/MultiFileManifestV1_6/ManifestV1_6-MultiFile-Installer.yaml @@ -161,6 +161,7 @@ Installers: InstallerUrl: https://www.microsoft.com/msixsdk/msixsdkx64.exe InstallerSha256: 69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8C82 ProductCode: "{Bar}" + UpgradeBehavior: deny - Architecture: x86 InstallerType: portable InstallerUrl: https://www.microsoft.com/msixsdk/msixsdkx86.exe diff --git a/src/AppInstallerCLITests/YamlManifest.cpp b/src/AppInstallerCLITests/YamlManifest.cpp @@ -706,6 +706,7 @@ void VerifyV1ManifestContent(const Manifest& manifest, bool isSingleton, Manifes if (manifestVer >= ManifestVer{ s_ManifestVersionV1_6 }) { REQUIRE(installer2.DownloadCommandProhibited); + REQUIRE(installer2.UpdateBehavior == UpdateBehaviorEnum::Deny); } } diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_0/Json/ManifestDeserializer.h b/src/AppInstallerRepositoryCore/Rest/Schema/1_0/Json/ManifestDeserializer.h @@ -44,6 +44,8 @@ namespace AppInstaller::Repository::Rest::Schema::V1_0::Json virtual Manifest::InstallerTypeEnum ConvertToInstallerType(std::string_view in) const; + virtual Manifest::UpdateBehaviorEnum ConvertToUpdateBehavior(std::string_view in) const; + std::vector<Manifest::string_t> ConvertToManifestStringArray(const std::vector<std::string>& values) const; virtual Manifest::ManifestVer GetManifestVersion() const; diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_0/Json/ManifestDeserializer_1_0.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/1_0/Json/ManifestDeserializer_1_0.cpp @@ -406,7 +406,7 @@ namespace AppInstaller::Repository::Rest::Schema::V1_0::Json std::optional<std::string> updateBehavior = JSON::GetRawStringValueFromJsonNode(installerJsonObject, JSON::GetUtilityString(UpgradeBehavior)); if (updateBehavior) { - installer.UpdateBehavior = Manifest::ConvertToUpdateBehaviorEnum(updateBehavior.value()); + installer.UpdateBehavior = ConvertToUpdateBehavior(updateBehavior.value()); } installer.Commands = ConvertToManifestStringArray(JSON::GetRawStringArrayFromJsonNode(installerJsonObject, JSON::GetUtilityString(Commands))); @@ -518,6 +518,22 @@ namespace AppInstaller::Repository::Rest::Schema::V1_0::Json return InstallerTypeEnum::Unknown; } + Manifest::UpdateBehaviorEnum ManifestDeserializer::ConvertToUpdateBehavior(std::string_view in) const + { + std::string inStrLower = Utility::ToLower(in); + + if (inStrLower == "install") + { + return UpdateBehaviorEnum::Install; + } + else if (inStrLower == "uninstallprevious") + { + return UpdateBehaviorEnum::UninstallPrevious; + } + + return UpdateBehaviorEnum::Unknown; + } + std::vector<Manifest::string_t> ManifestDeserializer::ConvertToManifestStringArray(const std::vector<std::string>& values) const { std::vector<Manifest::string_t> result; diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_1/Json/ManifestDeserializer_1_1.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/1_1/Json/ManifestDeserializer_1_1.cpp @@ -53,7 +53,7 @@ namespace AppInstaller::Repository::Rest::Schema::V1_1::Json arpEntry.DisplayVersion = JSON::GetRawStringValueFromJsonNode(arpEntryNode, JSON::GetUtilityString(DisplayVersion)).value_or(""); arpEntry.ProductCode = JSON::GetRawStringValueFromJsonNode(arpEntryNode, JSON::GetUtilityString(ProductCode)).value_or(""); arpEntry.UpgradeCode = JSON::GetRawStringValueFromJsonNode(arpEntryNode, JSON::GetUtilityString(UpgradeCode)).value_or(""); - arpEntry.InstallerType = Manifest::ConvertToInstallerTypeEnum(JSON::GetRawStringValueFromJsonNode(arpEntryNode, JSON::GetUtilityString(InstallerType)).value_or("")); + arpEntry.InstallerType = ConvertToInstallerType(JSON::GetRawStringValueFromJsonNode(arpEntryNode, JSON::GetUtilityString(InstallerType)).value_or("")); // Only add when at least one field is valid if (!arpEntry.DisplayName.empty() || !arpEntry.Publisher.empty() || !arpEntry.DisplayVersion.empty() || diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_6/Json/ManifestDeserializer.h b/src/AppInstallerRepositoryCore/Rest/Schema/1_6/Json/ManifestDeserializer.h @@ -12,6 +12,8 @@ namespace AppInstaller::Repository::Rest::Schema::V1_6::Json std::optional<Manifest::ManifestInstaller> DeserializeInstaller(const web::json::value& installerJsonObject) const override; + Manifest::UpdateBehaviorEnum ConvertToUpdateBehavior(std::string_view in) const override; + Manifest::ManifestVer GetManifestVersion() const override; }; } diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_6/Json/ManifestDeserializer_1_6.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/1_6/Json/ManifestDeserializer_1_6.cpp @@ -28,6 +28,18 @@ namespace AppInstaller::Repository::Rest::Schema::V1_6::Json return result; } + Manifest::UpdateBehaviorEnum ManifestDeserializer::ConvertToUpdateBehavior(std::string_view in) const + { + std::string inStrLower = Utility::ToLower(in); + + if (inStrLower == "deny") + { + return UpdateBehaviorEnum::Deny; + } + + return V1_5::Json::ManifestDeserializer::ConvertToUpdateBehavior(inStrLower); + } + Manifest::ManifestVer ManifestDeserializer::GetManifestVersion() const { return Manifest::s_ManifestVersionV1_6;