From 2f4391ba4dea36ec2e94690b813721e076baa295 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Wed, 14 Feb 2024 19:26:45 -0800 Subject: [PATCH 01/32] Add admin setting for enabling proxy --- .../Shared/Strings/en-us/winget.resw | 4 +++ src/AppInstallerCLITests/AdminSettings.cpp | 26 +++++++++++++++++++ src/AppInstallerCommonCore/AdminSettings.cpp | 17 ++++++++++++ .../Public/winget/AdminSettings.h | 10 +++++++ src/AppInstallerSharedLib/GroupPolicy.cpp | 2 ++ .../Public/winget/GroupPolicy.h | 1 + .../Public/winget/Resources.h | 1 + 7 files changed, 61 insertions(+) diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index cf45ed4b42..24dd4f14a5 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -2757,4 +2757,8 @@ Please specify one of them using the --source option to proceed. The {0} source requires authentication. Authentication prompt may appear when necessary. Authenticated information will be shared with the source for access authorization. {Locked="{0}"} + + Enable Windows Package Manager proxy command line options + Describres a Group Policy that can enable the use of the --proxy option to set a proxy + \ No newline at end of file diff --git a/src/AppInstallerCLITests/AdminSettings.cpp b/src/AppInstallerCLITests/AdminSettings.cpp index be05f13e71..3495cb677a 100644 --- a/src/AppInstallerCLITests/AdminSettings.cpp +++ b/src/AppInstallerCLITests/AdminSettings.cpp @@ -61,3 +61,29 @@ TEST_CASE("AdminSetting_Disable", "[adminSettings]") } } } + +TEST_CASE("AdminSetting_AllSettingsAreImplemented", "[adminSettings]") +{ + using AdminSetting_t = std::underlying_type_t; + + // Skip Unknown. + for (AdminSetting_t i = 1 + static_cast(AdminSetting::Unknown); i < static_cast(AdminSetting::Max); ++i) + { + auto adminSetting = static_cast(i); + + // If we forget to add it to the conversion, it returns Unknown/None + REQUIRE(AdminSettingToString(adminSetting) != AdminSettingToString(AdminSetting::Unknown)); + REQUIRE(StringToAdminSetting(AdminSettingToString(adminSetting)) != AdminSetting::Unknown); + REQUIRE(GetAdminSettingPolicy(adminSetting) != TogglePolicy::Policy::None); + + GroupPolicyTestOverride policies; + policies.SetState(GetAdminSettingPolicy(adminSetting), PolicyState::NotConfigured); + + // We should be able to configure the state. + // If we forget to add it, it won't persist. + REQUIRE(EnableAdminSetting(adminSetting)); + REQUIRE(IsAdminSettingEnabled(adminSetting)); + REQUIRE(DisableAdminSetting(adminSetting)); + REQUIRE_FALSE(IsAdminSettingEnabled(adminSetting)); + } +} \ No newline at end of file diff --git a/src/AppInstallerCommonCore/AdminSettings.cpp b/src/AppInstallerCommonCore/AdminSettings.cpp index 71d0f7ba3b..b0d979a272 100644 --- a/src/AppInstallerCommonCore/AdminSettings.cpp +++ b/src/AppInstallerCommonCore/AdminSettings.cpp @@ -19,6 +19,7 @@ namespace AppInstaller::Settings constexpr Utility::LocIndView s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore = "BypassCertificatePinningForMicrosoftStore"_liv; constexpr Utility::LocIndView s_AdminSettingsYaml_InstallerHashOverride = "InstallerHashOverride"_liv; constexpr Utility::LocIndView s_AdminSettingsYaml_LocalArchiveMalwareScanOverride = "LocalArchiveMalwareScanOverride"_liv; + constexpr Utility::LocIndView s_AdminSettingsYaml_ProxyCommandLineOptions = "ProxyCommandLineOptions"_liv; // Attempts to read a single scalar value from the node. template @@ -42,6 +43,7 @@ namespace AppInstaller::Settings bool BypassCertificatePinningForMicrosoftStore = false; bool InstallerHashOverride = false; bool LocalArchiveMalwareScanOverride = false; + bool ProxyCommandLineOptions = false; }; struct AdminSettingsInternal @@ -83,6 +85,9 @@ namespace AppInstaller::Settings case AdminSetting::LocalArchiveMalwareScanOverride: m_settingValues.LocalArchiveMalwareScanOverride = enabled; break; + case AdminSetting::ProxyCommandLineOptions: + m_settingValues.ProxyCommandLineOptions = enabled; + break; default: return; } @@ -111,6 +116,8 @@ namespace AppInstaller::Settings return m_settingValues.InstallerHashOverride; case AdminSetting::LocalArchiveMalwareScanOverride: return m_settingValues.LocalArchiveMalwareScanOverride; + case AdminSetting::ProxyCommandLineOptions: + return m_settingValues.ProxyCommandLineOptions; default: return false; } @@ -154,6 +161,7 @@ namespace AppInstaller::Settings TryReadScalar(document, s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore, m_settingValues.BypassCertificatePinningForMicrosoftStore); TryReadScalar(document, s_AdminSettingsYaml_InstallerHashOverride, m_settingValues.InstallerHashOverride); TryReadScalar(document, s_AdminSettingsYaml_LocalArchiveMalwareScanOverride, m_settingValues.LocalArchiveMalwareScanOverride); + TryReadScalar(document, s_AdminSettingsYaml_ProxyCommandLineOptions, m_settingValues.ProxyCommandLineOptions); } bool AdminSettingsInternal::SaveAdminSettings() @@ -164,6 +172,7 @@ namespace AppInstaller::Settings out << YAML::Key << s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore << YAML::Value << m_settingValues.BypassCertificatePinningForMicrosoftStore; out << YAML::Key << s_AdminSettingsYaml_InstallerHashOverride << YAML::Value << m_settingValues.InstallerHashOverride; out << YAML::Key << s_AdminSettingsYaml_LocalArchiveMalwareScanOverride << YAML::Value << m_settingValues.LocalArchiveMalwareScanOverride; + out << YAML::Key << s_AdminSettingsYaml_ProxyCommandLineOptions << YAML::Value << m_settingValues.ProxyCommandLineOptions; out << YAML::EndMap; return m_settingStream.Set(out.str()); @@ -190,6 +199,10 @@ namespace AppInstaller::Settings { result = AdminSetting::LocalArchiveMalwareScanOverride; } + else if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_ProxyCommandLineOptions, in)) + { + result = AdminSetting::ProxyCommandLineOptions; + } return result; } @@ -206,6 +219,8 @@ namespace AppInstaller::Settings return s_AdminSettingsYaml_InstallerHashOverride; case AdminSetting::LocalArchiveMalwareScanOverride: return s_AdminSettingsYaml_LocalArchiveMalwareScanOverride; + case AdminSetting::ProxyCommandLineOptions: + return s_AdminSettingsYaml_ProxyCommandLineOptions; default: return "Unknown"_liv; } @@ -223,6 +238,8 @@ namespace AppInstaller::Settings return TogglePolicy::Policy::HashOverride; case AdminSetting::LocalArchiveMalwareScanOverride: return TogglePolicy::Policy::LocalArchiveMalwareScanOverride; + case AdminSetting::ProxyCommandLineOptions: + return TogglePolicy::Policy::ProxyCommandLineOptions; default: return TogglePolicy::Policy::None; } diff --git a/src/AppInstallerCommonCore/Public/winget/AdminSettings.h b/src/AppInstallerCommonCore/Public/winget/AdminSettings.h index 4641d84225..4c6e9a1f9f 100644 --- a/src/AppInstallerCommonCore/Public/winget/AdminSettings.h +++ b/src/AppInstallerCommonCore/Public/winget/AdminSettings.h @@ -4,6 +4,10 @@ #include +#ifndef AICLI_DISABLE_TEST_HOOKS +#include "winget/GroupPolicy.h" +#endif + namespace AppInstaller::Settings { // Enum of admin settings. @@ -14,6 +18,7 @@ namespace AppInstaller::Settings BypassCertificatePinningForMicrosoftStore, InstallerHashOverride, LocalArchiveMalwareScanOverride, + ProxyCommandLineOptions, Max, }; @@ -28,4 +33,9 @@ namespace AppInstaller::Settings bool IsAdminSettingEnabled(AdminSetting setting); std::vector GetAllAdminSettings(); + +#ifndef AICLI_DISABLE_TEST_HOOKS + // Only used in tests to validate that all admin settings have a corresponding policy + TogglePolicy::Policy GetAdminSettingPolicy(AdminSetting setting); +#endif } diff --git a/src/AppInstallerSharedLib/GroupPolicy.cpp b/src/AppInstallerSharedLib/GroupPolicy.cpp index 6777d000b0..37c9c3f96c 100644 --- a/src/AppInstallerSharedLib/GroupPolicy.cpp +++ b/src/AppInstallerSharedLib/GroupPolicy.cpp @@ -298,6 +298,8 @@ namespace AppInstaller::Settings return TogglePolicy(policy, "EnableWindowsPackageManagerCommandLineInterfaces"sv, String::PolicyEnableWindowsPackageManagerCommandLineInterfaces); case TogglePolicy::Policy::Configuration: return TogglePolicy(policy, "EnableWindowsPackageManagerConfiguration"sv, String::PolicyEnableWinGetConfiguration); + case TogglePolicy::Policy::ProxyCommandLineOptions: + return TogglePolicy(policy, "EnableWindowsPackageManagerProxyCommandLineOptions"sv, String::PolicyEnableProxyCommandLineOptions); default: THROW_HR(E_UNEXPECTED); } diff --git a/src/AppInstallerSharedLib/Public/winget/GroupPolicy.h b/src/AppInstallerSharedLib/Public/winget/GroupPolicy.h index 96ca9396d4..52c0b936b9 100644 --- a/src/AppInstallerSharedLib/Public/winget/GroupPolicy.h +++ b/src/AppInstallerSharedLib/Public/winget/GroupPolicy.h @@ -45,6 +45,7 @@ namespace AppInstaller::Settings BypassCertificatePinningForMicrosoftStore, WinGetCommandLineInterfaces, Configuration, + ProxyCommandLineOptions, Max, }; diff --git a/src/AppInstallerSharedLib/Public/winget/Resources.h b/src/AppInstallerSharedLib/Public/winget/Resources.h index ced47b8e5c..dc6591abd0 100644 --- a/src/AppInstallerSharedLib/Public/winget/Resources.h +++ b/src/AppInstallerSharedLib/Public/winget/Resources.h @@ -59,6 +59,7 @@ namespace AppInstaller WINGET_DEFINE_RESOURCE_STRINGID(PolicyEnableBypassCertificatePinningForMicrosoftStore); WINGET_DEFINE_RESOURCE_STRINGID(PolicyEnableWindowsPackageManagerCommandLineInterfaces); WINGET_DEFINE_RESOURCE_STRINGID(PolicyEnableWinGetConfiguration); + WINGET_DEFINE_RESOURCE_STRINGID(PolicyEnableProxyCommandLineOptions); WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningInvalidFieldFormat); WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningInvalidFieldValue); From b7f8153c597ea8e1ddb248866472398611a85914 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Fri, 16 Feb 2024 15:34:09 -0800 Subject: [PATCH 02/32] Add proxy argument --- src/AppInstallerCLICore/Argument.cpp | 9 +++++++++ src/AppInstallerCLICore/Argument.h | 1 + src/AppInstallerCLICore/Commands/DownloadCommand.cpp | 6 ++++-- src/AppInstallerCLICore/Commands/ImportCommand.cpp | 2 ++ src/AppInstallerCLICore/Commands/InstallCommand.cpp | 2 ++ src/AppInstallerCLICore/Commands/ListCommand.cpp | 2 ++ src/AppInstallerCLICore/Commands/SearchCommand.cpp | 2 ++ src/AppInstallerCLICore/Commands/ShowCommand.cpp | 2 ++ src/AppInstallerCLICore/Commands/SourceCommand.cpp | 4 ++++ src/AppInstallerCLICore/Commands/UninstallCommand.cpp | 2 ++ src/AppInstallerCLICore/Commands/UpgradeCommand.cpp | 2 ++ src/AppInstallerCLICore/ExecutionArgs.h | 3 +++ src/AppInstallerCLICore/Resources.h | 2 ++ .../Shared/Strings/en-us/winget.resw | 6 ++++++ 14 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/AppInstallerCLICore/Argument.cpp b/src/AppInstallerCLICore/Argument.cpp index 7497468840..80f74c5311 100644 --- a/src/AppInstallerCLICore/Argument.cpp +++ b/src/AppInstallerCLICore/Argument.cpp @@ -233,6 +233,11 @@ namespace AppInstaller::CLI case Execution::Args::Type::AcceptSourceAgreements: return { type, "accept-source-agreements"_liv, ArgTypeCategory::ExtendedSource }; + case Execution::Args::Type::Proxy: + return { type, "proxy"_liv, ArgTypeCategory::CopyValueToSubContext, ArgTypeExclusiveSet::Proxy }; + case Execution::Args::Type::NoProxy: + return { type, "no-proxy"_liv, ArgTypeCategory::CopyFlagToSubContext, ArgTypeExclusiveSet::Proxy }; + case Execution::Args::Type::ToolVersion: return { type, "version"_liv, 'v' }; @@ -379,6 +384,10 @@ namespace AppInstaller::CLI return Argument{ type, Resource::String::AllowRebootArgumentDescription, ArgumentType::Flag }; case Args::Type::IgnoreResumeLimit: return Argument{ type, Resource::String::IgnoreResumeLimitArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Resume }; + case Args::Type::Proxy: + return Argument{ type, Resource::String::ProxyArgumentDescription, ArgumentType::Standard, false }; + case Args::Type::NoProxy: + return Argument{ type, Resource::String::NoProxyArgumentDescription, ArgumentType::Flag }; default: THROW_HR(E_UNEXPECTED); } diff --git a/src/AppInstallerCLICore/Argument.h b/src/AppInstallerCLICore/Argument.h index d33741eaf1..4350a0f8fd 100644 --- a/src/AppInstallerCLICore/Argument.h +++ b/src/AppInstallerCLICore/Argument.h @@ -85,6 +85,7 @@ namespace AppInstaller::CLI PurgePreserve = 0x4, PinType = 0x8, StubType = 0x10, + Proxy = 0x20, // This must always be at the end Max diff --git a/src/AppInstallerCLICore/Commands/DownloadCommand.cpp b/src/AppInstallerCLICore/Commands/DownloadCommand.cpp index 39739feeaf..bce785f6f9 100644 --- a/src/AppInstallerCLICore/Commands/DownloadCommand.cpp +++ b/src/AppInstallerCLICore/Commands/DownloadCommand.cpp @@ -36,8 +36,10 @@ namespace AppInstaller::CLI Argument::ForType(Args::Type::CustomHeader), Argument::ForType(Args::Type::AuthenticationMode), Argument::ForType(Args::Type::AuthenticationAccount), - Argument::ForType(Execution::Args::Type::AcceptPackageAgreements), - Argument::ForType(Execution::Args::Type::AcceptSourceAgreements), + Argument::ForType(Args::Type::Proxy), + Argument::ForType(Args::Type::NoProxy), + Argument::ForType(Args::Type::AcceptPackageAgreements), + Argument::ForType(Args::Type::AcceptSourceAgreements), }; } diff --git a/src/AppInstallerCLICore/Commands/ImportCommand.cpp b/src/AppInstallerCLICore/Commands/ImportCommand.cpp index 744599c1d5..7c024e666b 100644 --- a/src/AppInstallerCLICore/Commands/ImportCommand.cpp +++ b/src/AppInstallerCLICore/Commands/ImportCommand.cpp @@ -19,6 +19,8 @@ namespace AppInstaller::CLI Argument{ Execution::Args::Type::IgnoreUnavailable, Resource::String::ImportIgnoreUnavailableArgumentDescription, ArgumentType::Flag }, Argument{ Execution::Args::Type::IgnoreVersions, Resource::String::ImportIgnorePackageVersionsArgumentDescription, ArgumentType::Flag }, Argument::ForType(Execution::Args::Type::NoUpgrade), + Argument::ForType(Execution::Args::Type::Proxy), + Argument::ForType(Execution::Args::Type::NoProxy), Argument::ForType(Execution::Args::Type::AcceptPackageAgreements), Argument::ForType(Execution::Args::Type::AcceptSourceAgreements), }; diff --git a/src/AppInstallerCLICore/Commands/InstallCommand.cpp b/src/AppInstallerCLICore/Commands/InstallCommand.cpp index 097719e70c..a7bf51dbb7 100644 --- a/src/AppInstallerCLICore/Commands/InstallCommand.cpp +++ b/src/AppInstallerCLICore/Commands/InstallCommand.cpp @@ -55,6 +55,8 @@ namespace AppInstaller::CLI Argument::ForType(Args::Type::Rename), Argument::ForType(Args::Type::UninstallPrevious), Argument::ForType(Args::Type::Force), + Argument::ForType(Args::Type::Proxy), + Argument::ForType(Args::Type::NoProxy), Argument{ Args::Type::IncludeUnknown, Resource::String::IncludeUnknownArgumentDescription, ArgumentType::Flag, Argument::Visibility::Hidden}, }; } diff --git a/src/AppInstallerCLICore/Commands/ListCommand.cpp b/src/AppInstallerCLICore/Commands/ListCommand.cpp index 93c5798498..6423d6767e 100644 --- a/src/AppInstallerCLICore/Commands/ListCommand.cpp +++ b/src/AppInstallerCLICore/Commands/ListCommand.cpp @@ -27,6 +27,8 @@ namespace AppInstaller::CLI Argument::ForType(Execution::Args::Type::CustomHeader), Argument::ForType(Execution::Args::Type::AuthenticationMode), Argument::ForType(Execution::Args::Type::AuthenticationAccount), + Argument::ForType(Execution::Args::Type::Proxy), + Argument::ForType(Execution::Args::Type::NoProxy), Argument::ForType(Execution::Args::Type::AcceptSourceAgreements), Argument{ Execution::Args::Type::Upgrade, Resource::String::UpgradeArgumentDescription, ArgumentType::Flag, Argument::Visibility::Help }, Argument{ Execution::Args::Type::IncludeUnknown, Resource::String::IncludeUnknownInListArgumentDescription, ArgumentType::Flag }, diff --git a/src/AppInstallerCLICore/Commands/SearchCommand.cpp b/src/AppInstallerCLICore/Commands/SearchCommand.cpp index 0ae547d302..ed509f4011 100644 --- a/src/AppInstallerCLICore/Commands/SearchCommand.cpp +++ b/src/AppInstallerCLICore/Commands/SearchCommand.cpp @@ -27,6 +27,8 @@ namespace AppInstaller::CLI Argument::ForType(Execution::Args::Type::CustomHeader), Argument::ForType(Execution::Args::Type::AuthenticationMode), Argument::ForType(Execution::Args::Type::AuthenticationAccount), + Argument::ForType(Execution::Args::Type::Proxy), + Argument::ForType(Execution::Args::Type::NoProxy), Argument::ForType(Execution::Args::Type::AcceptSourceAgreements), Argument::ForType(Execution::Args::Type::ListVersions), }; diff --git a/src/AppInstallerCLICore/Commands/ShowCommand.cpp b/src/AppInstallerCLICore/Commands/ShowCommand.cpp index 76198a9699..aeef920b16 100644 --- a/src/AppInstallerCLICore/Commands/ShowCommand.cpp +++ b/src/AppInstallerCLICore/Commands/ShowCommand.cpp @@ -33,6 +33,8 @@ namespace AppInstaller::CLI Argument::ForType(Execution::Args::Type::CustomHeader), Argument::ForType(Execution::Args::Type::AuthenticationMode), Argument::ForType(Execution::Args::Type::AuthenticationAccount), + Argument::ForType(Execution::Args::Type::Proxy), + Argument::ForType(Execution::Args::Type::NoProxy), Argument::ForType(Execution::Args::Type::AcceptSourceAgreements), }; } diff --git a/src/AppInstallerCLICore/Commands/SourceCommand.cpp b/src/AppInstallerCLICore/Commands/SourceCommand.cpp index cd44ffaef5..f15b6f035e 100644 --- a/src/AppInstallerCLICore/Commands/SourceCommand.cpp +++ b/src/AppInstallerCLICore/Commands/SourceCommand.cpp @@ -53,6 +53,8 @@ namespace AppInstaller::CLI Argument::ForType(Args::Type::SourceArg), Argument::ForType(Args::Type::SourceType), Argument::ForType(Args::Type::CustomHeader), + Argument::ForType(Args::Type::Proxy), + Argument::ForType(Args::Type::NoProxy), Argument::ForType(Args::Type::AcceptSourceAgreements), }; } @@ -126,6 +128,8 @@ namespace AppInstaller::CLI { return { Argument::ForType(Args::Type::SourceName), + Argument::ForType(Execution::Args::Type::Proxy), + Argument::ForType(Execution::Args::Type::NoProxy), }; } diff --git a/src/AppInstallerCLICore/Commands/UninstallCommand.cpp b/src/AppInstallerCLICore/Commands/UninstallCommand.cpp index a0b0ae91a8..870f84895a 100644 --- a/src/AppInstallerCLICore/Commands/UninstallCommand.cpp +++ b/src/AppInstallerCLICore/Commands/UninstallCommand.cpp @@ -37,6 +37,8 @@ namespace AppInstaller::CLI Argument::ForType(Args::Type::CustomHeader), Argument::ForType(Args::Type::AuthenticationMode), Argument::ForType(Args::Type::AuthenticationAccount), + Argument::ForType(Args::Type::Proxy), + Argument::ForType(Args::Type::NoProxy), Argument::ForType(Args::Type::AcceptSourceAgreements), }; } diff --git a/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp b/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp index a5c2701ae2..104057b249 100644 --- a/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp +++ b/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp @@ -73,6 +73,8 @@ namespace AppInstaller::CLI Argument{ Args::Type::IncludePinned, Resource::String::IncludePinnedArgumentDescription, ArgumentType::Flag}, Argument::ForType(Args::Type::UninstallPrevious), Argument::ForType(Args::Type::Force), + Argument::ForType(Args::Type::Proxy), + Argument::ForType(Args::Type::NoProxy), }; } diff --git a/src/AppInstallerCLICore/ExecutionArgs.h b/src/AppInstallerCLICore/ExecutionArgs.h index ad1b70496a..ca6d711949 100644 --- a/src/AppInstallerCLICore/ExecutionArgs.h +++ b/src/AppInstallerCLICore/ExecutionArgs.h @@ -140,6 +140,9 @@ namespace AppInstaller::CLI::Execution AuthenticationMode, // Authentication mode (silent, silentPreferred or interactive) AuthenticationAccount, // Authentication account to be used + Proxy, // Set a proxy to use in this execution + NoProxy, // Do not use the default proxy + ToolVersion, // Used for demonstration purposes diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h index cfd3bb5d7b..7f314428d9 100644 --- a/src/AppInstallerCLICore/Resources.h +++ b/src/AppInstallerCLICore/Resources.h @@ -344,6 +344,7 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(NoPackageFound); WINGET_DEFINE_RESOURCE_STRINGID(NoPackageSelectionArgumentProvided); WINGET_DEFINE_RESOURCE_STRINGID(NoPackagesFoundInImportFile); + WINGET_DEFINE_RESOURCE_STRINGID(NoProxyArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(Notes); WINGET_DEFINE_RESOURCE_STRINGID(NoUninstallInfoFound); WINGET_DEFINE_RESOURCE_STRINGID(NoUpgradeArgumentDescription); @@ -411,6 +412,7 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(PromptOptionNo); WINGET_DEFINE_RESOURCE_STRINGID(PromptOptionYes); WINGET_DEFINE_RESOURCE_STRINGID(PromptToProceed); + WINGET_DEFINE_RESOURCE_STRINGID(ProxyArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(PurgeArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(PurgeInstallDirectory); WINGET_DEFINE_RESOURCE_STRINGID(QueryArgumentDescription); diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index 24dd4f14a5..c1a1d87aa1 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -2761,4 +2761,10 @@ Please specify one of them using the --source option to proceed. Enable Windows Package Manager proxy command line options Describres a Group Policy that can enable the use of the --proxy option to set a proxy + + Set a proxy to use for this execution + + + Disable the use of proxy for this execution + \ No newline at end of file From b2d9f311c1f7f52044f636d19ebbf134d8c2bd79 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Fri, 16 Feb 2024 16:46:27 -0800 Subject: [PATCH 03/32] Add group policy --- doc/admx/DesktopAppInstaller.admx | 10 ++++++++++ doc/admx/en-US/DesktopAppInstaller.adml | 9 ++++++++- src/AppInstallerCLIE2ETests/GroupPolicyHelper.cs | 6 ++++++ .../Shared/Strings/en-us/winget.resw | 2 +- src/AppInstallerCLITests/GroupPolicy.cpp | 1 + src/AppInstallerCLITests/TestSettings.h | 1 + .../Resources/GroupPolicyResource.Designer.cs | 9 +++++++++ .../Resources/GroupPolicyResource.resx | 3 +++ 8 files changed, 39 insertions(+), 2 deletions(-) diff --git a/doc/admx/DesktopAppInstaller.admx b/doc/admx/DesktopAppInstaller.admx index 64b911e1f2..7257e1ed28 100644 --- a/doc/admx/DesktopAppInstaller.admx +++ b/doc/admx/DesktopAppInstaller.admx @@ -166,5 +166,15 @@ + + + + + + + + + + diff --git a/doc/admx/en-US/DesktopAppInstaller.adml b/doc/admx/en-US/DesktopAppInstaller.adml index 4e80a38093..632016577b 100644 --- a/doc/admx/en-US/DesktopAppInstaller.adml +++ b/doc/admx/en-US/DesktopAppInstaller.adml @@ -100,7 +100,7 @@ If you disable or do not configure this setting, users will not be able to insta If you disable this policy, users will not be able execute the Windows Package Manager CLI, and PowerShell cmdlets. - If you enable, or do not configuring this policy, users will be able to execute the Windows Package Manager CLI commands, and PowerShell cmdlets. (Provided “Enable App Installer” policy is not disabled). + If you enable, or do not configure this policy, users will be able to execute the Windows Package Manager CLI commands, and PowerShell cmdlets. (Provided “Enable App Installer” policy is not disabled). This policy does not override the “Enable App Installer” policy. Enable Windows Package Manager Configuration @@ -109,6 +109,13 @@ If you disable or do not configure this setting, users will not be able to insta If you enable or do not configure this setting, users will be able to use the Windows Package Manager configuration feature. If you disable this setting, users will not be able to use the Windows Package Manager configuration feature. + Enable Windows Package Manager Proxy command line options + + This policy controls whether the Windows Package Manager usage of proxy can be configured by users through the command line. + + If you enable this setting, users will be able to configure the Windows Package Manager's use of proxy through the command line. + + If you disable or do not configure this setting, users will not be able to to configure the Windows Package Manager's use of proxy through the command line. diff --git a/src/AppInstallerCLIE2ETests/GroupPolicyHelper.cs b/src/AppInstallerCLIE2ETests/GroupPolicyHelper.cs index 2eb2fe0db6..8179934fa6 100644 --- a/src/AppInstallerCLIE2ETests/GroupPolicyHelper.cs +++ b/src/AppInstallerCLIE2ETests/GroupPolicyHelper.cs @@ -118,6 +118,11 @@ private GroupPolicyHelper(string name, string elementId) /// public static GroupPolicyHelper EnableConfiguration { get; private set; } = new GroupPolicyHelper("EnableWindowsPackageManagerConfiguration"); + /// + /// Gets the Enable Windows Package Manager proxy command line options policy. + /// + public static GroupPolicyHelper EnableProxyCommandLineOptions { get; private set; } = new GroupPolicyHelper("EnableWindowsPackageManagerProxyCommandLineOptions"); + /// /// Gets the Enable auto update interval policy. /// @@ -138,6 +143,7 @@ private GroupPolicyHelper(string name, string elementId) SourceAutoUpdateInterval, EnableWinGetCommandLineInterfaces, EnableConfiguration, + EnableProxyCommandLineOptions, }; /// diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index c1a1d87aa1..33c93addc2 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -2764,7 +2764,7 @@ Please specify one of them using the --source option to proceed. Set a proxy to use for this execution - + Disable the use of proxy for this execution \ No newline at end of file diff --git a/src/AppInstallerCLITests/GroupPolicy.cpp b/src/AppInstallerCLITests/GroupPolicy.cpp index f57442c28f..4c8c2356ac 100644 --- a/src/AppInstallerCLITests/GroupPolicy.cpp +++ b/src/AppInstallerCLITests/GroupPolicy.cpp @@ -376,6 +376,7 @@ TEST_CASE("GroupPolicy_AllEnabled", "[groupPolicy]") SetRegistryValue(policiesKey.get(), BypassCertificatePinningForMicrosoftStoreValueName, 1); SetRegistryValue(policiesKey.get(), EnableWindowsPackageManagerCommandLineInterfaces, 1); SetRegistryValue(policiesKey.get(), ConfigurationPolicyValueName, 1); + SetRegistryValue(policiesKey.get(), ProxyCommandLineOptionsPolicyValueName, 1); GroupPolicy groupPolicy{ policiesKey.get() }; for (const auto& policy : TogglePolicy::GetAllPolicies()) diff --git a/src/AppInstallerCLITests/TestSettings.h b/src/AppInstallerCLITests/TestSettings.h index 878264a8c1..7da1a728ef 100644 --- a/src/AppInstallerCLITests/TestSettings.h +++ b/src/AppInstallerCLITests/TestSettings.h @@ -22,6 +22,7 @@ namespace TestCommon const std::wstring BypassCertificatePinningForMicrosoftStoreValueName = L"EnableBypassCertificatePinningForMicrosoftStore"; const std::wstring EnableWindowsPackageManagerCommandLineInterfaces = L"EnableWindowsPackageManagerCommandLineInterfaces"; const std::wstring ConfigurationPolicyValueName = L"EnableWindowsPackageManagerConfiguration"; + const std::wstring ProxyCommandLineOptionsPolicyValueName = L"EnableWindowsPackageManagerProxyCommandLineOptions"; const std::wstring SourceUpdateIntervalPolicyValueName = L"SourceAutoUpdateInterval"; const std::wstring SourceUpdateIntervalPolicyOldValueName = L"SourceAutoUpdateIntervalInMinutes"; diff --git a/src/PowerShell/Microsoft.WinGet.SharedLib/Resources/GroupPolicyResource.Designer.cs b/src/PowerShell/Microsoft.WinGet.SharedLib/Resources/GroupPolicyResource.Designer.cs index c737994bc6..13d57659f4 100644 --- a/src/PowerShell/Microsoft.WinGet.SharedLib/Resources/GroupPolicyResource.Designer.cs +++ b/src/PowerShell/Microsoft.WinGet.SharedLib/Resources/GroupPolicyResource.Designer.cs @@ -150,6 +150,15 @@ internal class GroupPolicyResource { } } + /// + /// Looks up a localized string similar to Enable Windows Package Manager proxy command line options. + /// + internal static string PolicyEnableProxyCommandLineOptions { + get { + return ResourceManager.GetString("PolicyEnableProxyCommandLineOptions", resourceCulture); + } + } + /// /// Looks up a localized string similar to Enable Windows Package Manager command line interfaces. /// diff --git a/src/PowerShell/Microsoft.WinGet.SharedLib/Resources/GroupPolicyResource.resx b/src/PowerShell/Microsoft.WinGet.SharedLib/Resources/GroupPolicyResource.resx index f49d201ea4..60d79c6e0f 100644 --- a/src/PowerShell/Microsoft.WinGet.SharedLib/Resources/GroupPolicyResource.resx +++ b/src/PowerShell/Microsoft.WinGet.SharedLib/Resources/GroupPolicyResource.resx @@ -147,6 +147,9 @@ Enable Windows App Installer Microsoft Store Source + + Enable Windows Package Manager proxy command line options + Enable Windows Package Manager command line interfaces From d729041099167898e13c712095c110b09e3d503d Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Fri, 16 Feb 2024 16:49:47 -0800 Subject: [PATCH 04/32] Fix bad name copy --- src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index 33c93addc2..a3bd2ee224 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -2757,7 +2757,7 @@ Please specify one of them using the --source option to proceed. The {0} source requires authentication. Authentication prompt may appear when necessary. Authenticated information will be shared with the source for access authorization. {Locked="{0}"} - + Enable Windows Package Manager proxy command line options Describres a Group Policy that can enable the use of the --proxy option to set a proxy From 426a5f33b9774e5d82d51bc73879e779a713ec34 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Wed, 21 Feb 2024 11:31:58 -0800 Subject: [PATCH 05/32] Add policy for default proxy --- doc/admx/DesktopAppInstaller.admx | 7 +++++++ doc/admx/en-US/DesktopAppInstaller.adml | 11 +++++++++++ src/AppInstallerSharedLib/GroupPolicy.cpp | 8 ++++++++ src/AppInstallerSharedLib/Public/winget/GroupPolicy.h | 2 ++ 4 files changed, 28 insertions(+) diff --git a/doc/admx/DesktopAppInstaller.admx b/doc/admx/DesktopAppInstaller.admx index 7257e1ed28..9cad850345 100644 --- a/doc/admx/DesktopAppInstaller.admx +++ b/doc/admx/DesktopAppInstaller.admx @@ -176,5 +176,12 @@ + + + + + + + diff --git a/doc/admx/en-US/DesktopAppInstaller.adml b/doc/admx/en-US/DesktopAppInstaller.adml index 632016577b..79f3e08f44 100644 --- a/doc/admx/en-US/DesktopAppInstaller.adml +++ b/doc/admx/en-US/DesktopAppInstaller.adml @@ -116,6 +116,12 @@ If you disable this setting, users will not be able to use the Windows Package M If you enable this setting, users will be able to configure the Windows Package Manager's use of proxy through the command line. If you disable or do not configure this setting, users will not be able to to configure the Windows Package Manager's use of proxy through the command line. + Set Windows Package Manager Default Proxy + This policy controls the default proxy used by the Windows Package Manager. + +If you disable or do not configure this setting, no proxy will be used by default. + +If you enable this setting, the specified proxy will be used by default. @@ -127,6 +133,11 @@ If you disable this setting, users will not be able to use the Windows Package M Allowed Sources: + + + + + diff --git a/src/AppInstallerSharedLib/GroupPolicy.cpp b/src/AppInstallerSharedLib/GroupPolicy.cpp index 37c9c3f96c..7325203238 100644 --- a/src/AppInstallerSharedLib/GroupPolicy.cpp +++ b/src/AppInstallerSharedLib/GroupPolicy.cpp @@ -224,6 +224,13 @@ namespace AppInstaller::Settings namespace details { +#define POLICY_MAPPING_DEFAULT_READ(_policy_) \ + std::optional::value_t> ValuePolicyMapping<_policy_>::ReadAndValidate(const Registry::Key& policiesKey) \ + { \ + using Mapping = ValuePolicyMapping<_policy_>; \ + return GetRegistryValueData(policiesKey, Mapping::ValueName); \ + } + #define POLICY_MAPPING_DEFAULT_LIST_READ(_policy_) \ std::optional::value_t> ValuePolicyMapping<_policy_>::ReadAndValidate(const Registry::Key& policiesKey) \ { \ @@ -232,6 +239,7 @@ namespace AppInstaller::Settings POLICY_MAPPING_DEFAULT_LIST_READ(ValuePolicy::AdditionalSources); POLICY_MAPPING_DEFAULT_LIST_READ(ValuePolicy::AllowedSources); + POLICY_MAPPING_DEFAULT_READ(ValuePolicy::DefaultProxy); std::nullopt_t ValuePolicyMapping::ReadAndValidate(const Registry::Key&) { diff --git a/src/AppInstallerSharedLib/Public/winget/GroupPolicy.h b/src/AppInstallerSharedLib/Public/winget/GroupPolicy.h index 52c0b936b9..114ef6703a 100644 --- a/src/AppInstallerSharedLib/Public/winget/GroupPolicy.h +++ b/src/AppInstallerSharedLib/Public/winget/GroupPolicy.h @@ -22,6 +22,7 @@ namespace AppInstaller::Settings SourceAutoUpdateIntervalInMinutes, AdditionalSources, AllowedSources, + DefaultProxy, Max, }; @@ -147,6 +148,7 @@ namespace AppInstaller::Settings ) POLICY_MAPPING_VALUE_SPECIALIZATION(ValuePolicy::SourceAutoUpdateIntervalInMinutes, uint32_t, "SourceAutoUpdateInterval"sv, Registry::Value::Type::DWord); + POLICY_MAPPING_VALUE_SPECIALIZATION(ValuePolicy::DefaultProxy, std::string, "DefaultProxy"sv, Registry::Value::Type::String); POLICY_MAPPING_LIST_SPECIALIZATION(ValuePolicy::AdditionalSources, SourceFromPolicy, "AdditionalSources"sv); POLICY_MAPPING_LIST_SPECIALIZATION(ValuePolicy::AllowedSources, SourceFromPolicy, "AllowedSources"sv); From f795ce2a31200bf0af80016d45288dc99e7ba200 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Wed, 21 Feb 2024 13:08:49 -0800 Subject: [PATCH 06/32] Add proxy to context --- src/AppInstallerCLICore/Argument.cpp | 4 +-- .../ExecutionContextData.h | 7 ++++ .../Workflows/WorkflowBase.cpp | 32 +++++++++++++++++++ .../Workflows/WorkflowBase.h | 6 ++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/AppInstallerCLICore/Argument.cpp b/src/AppInstallerCLICore/Argument.cpp index 80f74c5311..fcaa72af62 100644 --- a/src/AppInstallerCLICore/Argument.cpp +++ b/src/AppInstallerCLICore/Argument.cpp @@ -385,9 +385,9 @@ namespace AppInstaller::CLI case Args::Type::IgnoreResumeLimit: return Argument{ type, Resource::String::IgnoreResumeLimitArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Resume }; case Args::Type::Proxy: - return Argument{ type, Resource::String::ProxyArgumentDescription, ArgumentType::Standard, false }; + return Argument{ type, Resource::String::ProxyArgumentDescription, ArgumentType::Standard, Settings::TogglePolicy::Policy::ProxyCommandLineOptions, Settings::AdminSetting::ProxyCommandLineOptions }; case Args::Type::NoProxy: - return Argument{ type, Resource::String::NoProxyArgumentDescription, ArgumentType::Flag }; + return Argument{ type, Resource::String::NoProxyArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::ProxyCommandLineOptions, Settings::AdminSetting::ProxyCommandLineOptions }; default: THROW_HR(E_UNEXPECTED); } diff --git a/src/AppInstallerCLICore/ExecutionContextData.h b/src/AppInstallerCLICore/ExecutionContextData.h index 96c2d250ee..08952d4091 100644 --- a/src/AppInstallerCLICore/ExecutionContextData.h +++ b/src/AppInstallerCLICore/ExecutionContextData.h @@ -63,6 +63,7 @@ namespace AppInstaller::CLI::Execution Pins, ConfigurationContext, DownloadDirectory, + ProxyUri, Max }; @@ -267,5 +268,11 @@ namespace AppInstaller::CLI::Execution { using value_t = std::filesystem::path; }; + + template <> + struct DataMapping + { + using value_t = std::optional; + }; } } diff --git a/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp b/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp index 1be12e80cc..2951ed2c7b 100644 --- a/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp +++ b/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp @@ -11,6 +11,7 @@ #include #include #include +#include using namespace std::string_literals; using namespace AppInstaller::Utility::literals; @@ -1355,6 +1356,37 @@ namespace AppInstaller::CLI::Workflow } table.Complete(); } + + void GetProxy(Execution::Context& context) + { + if (context.Contains(Execution::Data::ProxyUri)) + { + // Already determined proxy to use + return; + } + + // First check command line arguments. These override any default if present. + if (context.Args.Contains(Execution::Args::Type::NoProxy)) + { + AICLI_LOG(CLI, Info, << "Proxy disabled by command line argument"); + context.Add(std::nullopt); + return; + } + + if (context.Args.Contains(Execution::Args::Type::Proxy)) + { + auto proxyFromArg = context.Args.GetArg(Execution::Args::Type::Proxy); + AICLI_LOG(CLI, Info, << "Setting proxy from command line argument: " << proxyFromArg); + context.Add(std::string{ proxyFromArg }); + return; + } + + // Get the default proxy + std::optional defaultProxy = GroupPolicies().GetValueRef(); + AICLI_LOG(CLI, Info, << "Default proxy: " << (defaultProxy ? defaultProxy.value() : "Not configured")); + + context.Add(defaultProxy); + } } AppInstaller::CLI::Execution::Context& operator<<(AppInstaller::CLI::Execution::Context& context, AppInstaller::CLI::Workflow::WorkflowTask::Func f) diff --git a/src/AppInstallerCLICore/Workflows/WorkflowBase.h b/src/AppInstallerCLICore/Workflows/WorkflowBase.h index 98df349531..c913df7718 100644 --- a/src/AppInstallerCLICore/Workflows/WorkflowBase.h +++ b/src/AppInstallerCLICore/Workflows/WorkflowBase.h @@ -434,6 +434,12 @@ namespace AppInstaller::CLI::Workflow private: ExecutionStage m_stage; }; + + // Gets the proxy to use according to the CLI arg, settings and policies. + // Required Args: None + // Inputs: None + // Outputs: ProxyUri + void GetProxy(Execution::Context& context); } // Passes the context to the function if it has not been terminated; returns the context. From 4d73e74d4e60b2325079086afb63d62075bfcec2 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Thu, 22 Feb 2024 13:17:36 -0800 Subject: [PATCH 07/32] Add experimental feature --- src/AppInstallerCLICore/Argument.cpp | 4 ++-- src/AppInstallerCLICore/Argument.h | 3 +++ src/AppInstallerCLICore/ExecutionArgs.h | 1 + src/AppInstallerCommonCore/ExperimentalFeature.cpp | 4 ++++ .../Public/winget/ExperimentalFeature.h | 1 + src/AppInstallerCommonCore/Public/winget/UserSettings.h | 2 ++ 6 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/AppInstallerCLICore/Argument.cpp b/src/AppInstallerCLICore/Argument.cpp index fcaa72af62..e9f8b97714 100644 --- a/src/AppInstallerCLICore/Argument.cpp +++ b/src/AppInstallerCLICore/Argument.cpp @@ -385,9 +385,9 @@ namespace AppInstaller::CLI case Args::Type::IgnoreResumeLimit: return Argument{ type, Resource::String::IgnoreResumeLimitArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Resume }; case Args::Type::Proxy: - return Argument{ type, Resource::String::ProxyArgumentDescription, ArgumentType::Standard, Settings::TogglePolicy::Policy::ProxyCommandLineOptions, Settings::AdminSetting::ProxyCommandLineOptions }; + return Argument{ type, Resource::String::ProxyArgumentDescription, ArgumentType::Standard, ExperimentalFeature::Feature::Proxy, TogglePolicy::Policy::ProxyCommandLineOptions, AdminSetting::ProxyCommandLineOptions }; case Args::Type::NoProxy: - return Argument{ type, Resource::String::NoProxyArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::ProxyCommandLineOptions, Settings::AdminSetting::ProxyCommandLineOptions }; + return Argument{ type, Resource::String::NoProxyArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Proxy, TogglePolicy::Policy::ProxyCommandLineOptions, AdminSetting::ProxyCommandLineOptions }; default: THROW_HR(E_UNEXPECTED); } diff --git a/src/AppInstallerCLICore/Argument.h b/src/AppInstallerCLICore/Argument.h index 4350a0f8fd..2016880480 100644 --- a/src/AppInstallerCLICore/Argument.h +++ b/src/AppInstallerCLICore/Argument.h @@ -244,6 +244,9 @@ namespace AppInstaller::CLI Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) : m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {} + Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::ExperimentalFeature::Feature feature, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) : + m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_feature(feature), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {} + ArgumentCommon m_argCommon; Resource::StringId m_desc; bool m_required = false; diff --git a/src/AppInstallerCLICore/ExecutionArgs.h b/src/AppInstallerCLICore/ExecutionArgs.h index ca6d711949..32f5e58535 100644 --- a/src/AppInstallerCLICore/ExecutionArgs.h +++ b/src/AppInstallerCLICore/ExecutionArgs.h @@ -140,6 +140,7 @@ namespace AppInstaller::CLI::Execution AuthenticationMode, // Authentication mode (silent, silentPreferred or interactive) AuthenticationAccount, // Authentication account to be used + // Network Behavior Proxy, // Set a proxy to use in this execution NoProxy, // Do not use the default proxy diff --git a/src/AppInstallerCommonCore/ExperimentalFeature.cpp b/src/AppInstallerCommonCore/ExperimentalFeature.cpp index 98dd70ce88..d531a36fe8 100644 --- a/src/AppInstallerCommonCore/ExperimentalFeature.cpp +++ b/src/AppInstallerCommonCore/ExperimentalFeature.cpp @@ -44,6 +44,8 @@ namespace AppInstaller::Settings return userSettings.Get(); case ExperimentalFeature::Feature::Configuration03: return userSettings.Get(); + case ExperimentalFeature::Feature::Proxy: + return userSettings.Get(); default: THROW_HR(E_UNEXPECTED); } @@ -77,6 +79,8 @@ namespace AppInstaller::Settings return ExperimentalFeature{ "Resume", "resume", "https://aka.ms/winget-settings", Feature::Resume }; case Feature::Configuration03: return ExperimentalFeature{ "Configuration Schema 0.3", "configuration03", "https://aka.ms/winget-settings", Feature::Configuration03 }; + case Feature::Proxy: + return ExperimentalFeature{ "Proxy", "proxy", "https://aka.ms/winget-settings", Feature::Proxy }; default: THROW_HR(E_UNEXPECTED); } diff --git a/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h b/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h index 72cad2a480..e2847cd0a4 100644 --- a/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h +++ b/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h @@ -25,6 +25,7 @@ namespace AppInstaller::Settings DirectMSI = 0x1, Resume = 0x2, Configuration03 = 0x4, + Proxy = 0x8, Max, // This MUST always be after all experimental features // Features listed after Max will not be shown with the features command diff --git a/src/AppInstallerCommonCore/Public/winget/UserSettings.h b/src/AppInstallerCommonCore/Public/winget/UserSettings.h index ad63b65c44..ba156f8cf8 100644 --- a/src/AppInstallerCommonCore/Public/winget/UserSettings.h +++ b/src/AppInstallerCommonCore/Public/winget/UserSettings.h @@ -72,6 +72,7 @@ namespace AppInstaller::Settings EFDirectMSI, EFResume, EFConfiguration03, + EFProxy, // Telemetry TelemetryDisable, // Install behavior @@ -151,6 +152,7 @@ namespace AppInstaller::Settings SETTINGMAPPING_SPECIALIZATION(Setting::EFDirectMSI, bool, bool, false, ".experimentalFeatures.directMSI"sv); SETTINGMAPPING_SPECIALIZATION(Setting::EFResume, bool, bool, false, ".experimentalFeatures.resume"sv); SETTINGMAPPING_SPECIALIZATION(Setting::EFConfiguration03, bool, bool, false, ".experimentalFeatures.configuration03"sv); + SETTINGMAPPING_SPECIALIZATION(Setting::EFProxy, bool, bool, false, ".experimentalFeatures.proxy"sv); // Telemetry SETTINGMAPPING_SPECIALIZATION(Setting::TelemetryDisable, bool, bool, false, ".telemetry.disable"sv); // Install behavior From 59b0a5f4f33430a10241ed0897e19c705d065600 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Thu, 22 Feb 2024 16:26:49 -0800 Subject: [PATCH 08/32] Pass proxy info to some places it is needed --- .../ExecutionContextData.h | 7 ++-- .../Workflows/ConfigurationFlow.cpp | 2 +- .../Workflows/DownloadFlow.cpp | 35 ++++++++++++++++- .../Workflows/DownloadFlow.h | 6 +++ .../Workflows/WorkflowBase.cpp | 39 ++++--------------- .../Workflows/WorkflowBase.h | 6 --- src/AppInstallerCLITests/Downloader.cpp | 8 ++-- src/AppInstallerCLITests/MsixInfo.cpp | 2 +- src/AppInstallerCLITests/TestCommon.cpp | 2 +- src/AppInstallerCLITests/pch.h | 2 + src/AppInstallerCommonCore/Downloader.cpp | 30 ++++++++++---- .../Manifest/MsixManifestValidation.cpp | 4 +- .../Public/AppInstallerDownloader.h | 29 ++++++++------ src/AppInstallerCommonCore/UserSettings.cpp | 1 + .../InstallerMetadataCollectionContext.cpp | 2 +- src/AppInstallerRepositoryCore/pch.h | 35 +++++++++-------- src/Microsoft.Management.Deployment/pch.h | 1 + src/WinGetUtil/Exports.cpp | 2 +- src/WinGetUtil/pch.h | 1 + 19 files changed, 126 insertions(+), 88 deletions(-) diff --git a/src/AppInstallerCLICore/ExecutionContextData.h b/src/AppInstallerCLICore/ExecutionContextData.h index 08952d4091..a3278f46cf 100644 --- a/src/AppInstallerCLICore/ExecutionContextData.h +++ b/src/AppInstallerCLICore/ExecutionContextData.h @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. #pragma once +#include #include #include #include @@ -63,7 +64,7 @@ namespace AppInstaller::CLI::Execution Pins, ConfigurationContext, DownloadDirectory, - ProxyUri, + NetworkProxyInfo, Max }; @@ -270,9 +271,9 @@ namespace AppInstaller::CLI::Execution }; template <> - struct DataMapping + struct DataMapping { - using value_t = std::optional; + using value_t = Utility::ProxyInfo; }; } } diff --git a/src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp b/src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp index 77c1fbd9d1..5aadb38261 100644 --- a/src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp @@ -866,7 +866,7 @@ namespace AppInstaller::CLI::Workflow { std::ostringstream stringStream; ProgressCallback emptyCallback; - Utility::DownloadToStream(argPath, stringStream, Utility::DownloadType::ConfigurationFile, emptyCallback); + Utility::DownloadToStream(argPath, stringStream, Utility::DownloadType::ConfigurationFile, emptyCallback, Utility::ProxyInfo::NoProxy); auto strContent = stringStream.str(); std::vector byteContent{ strContent.begin(), strContent.end() }; diff --git a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp index 1bd4cd462a..d1223ce5b5 100644 --- a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include namespace AppInstaller::CLI::Workflow @@ -14,6 +15,7 @@ namespace AppInstaller::CLI::Workflow using namespace AppInstaller::Manifest; using namespace AppInstaller::Repository; using namespace AppInstaller::Utility; + using namespace AppInstaller::Settings; using namespace std::string_view_literals; namespace @@ -178,6 +180,35 @@ namespace AppInstaller::CLI::Workflow } } + void GetProxyInfo(Execution::Context& context) + { + if (context.Contains(Execution::Data::NetworkProxyInfo)) + { + // Already determined proxy to use + return; + } + + Utility::ProxyInfo proxyInfo; + + // Get the default proxy + proxyInfo.ProxyUri = GroupPolicies().GetValueRef(); + AICLI_LOG(CLI, Info, << "Default proxy: " << (proxyInfo.ProxyUri ? proxyInfo.ProxyUri.value() : "Not configured")); + + // Check command line arguments. These override any default if present. + if (context.Args.Contains(Execution::Args::Type::NoProxy)) + { + AICLI_LOG(CLI, Info, << "Proxy disabled by command line argument"); + proxyInfo = Utility::ProxyInfo::NoProxy; + } + else if (context.Args.Contains(Execution::Args::Type::Proxy)) + { + proxyInfo.ProxyUri = context.Args.GetArg(Execution::Args::Type::Proxy); + AICLI_LOG(CLI, Info, << "Setting proxy from command line argument: " << proxyInfo.ProxyUri.value()); + } + + context.Add(proxyInfo); + } + void DownloadInstaller(Execution::Context& context) { // Check if file was already downloaded. @@ -289,7 +320,7 @@ namespace AppInstaller::CLI::Workflow void DownloadInstallerFile(Execution::Context& context) { - context << GetInstallerDownloadPath; + context << GetInstallerDownloadPath << GetProxyInfo; if (context.IsTerminated()) { return; @@ -297,6 +328,7 @@ namespace AppInstaller::CLI::Workflow const auto& installer = context.Get().value(); const auto& installerPath = context.Get(); + const auto& proxyInfo = context.Get(); Utility::DownloadInfo downloadInfo{}; downloadInfo.DisplayName = Resource::GetFixedString(Resource::FixedString::ProductName); @@ -319,6 +351,7 @@ namespace AppInstaller::CLI::Workflow installerPath, Utility::DownloadType::Installer, std::placeholders::_1, + proxyInfo, true, downloadInfo)); diff --git a/src/AppInstallerCLICore/Workflows/DownloadFlow.h b/src/AppInstallerCLICore/Workflows/DownloadFlow.h index 2ff6e15210..57b96ab5a0 100644 --- a/src/AppInstallerCLICore/Workflows/DownloadFlow.h +++ b/src/AppInstallerCLICore/Workflows/DownloadFlow.h @@ -5,6 +5,12 @@ namespace AppInstaller::CLI::Workflow { + // Gets the proxy settings according to the CLI arg, settings and group policies. + // Required Args: None + // Inputs: None + // Outputs: ProxyInfo + void GetProxyInfo(Execution::Context& context); + // Composite flow that chooses what to do based on the installer type. // Required Args: None // Inputs: Manifest, Installer diff --git a/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp b/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp index 2951ed2c7b..fde4159348 100644 --- a/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp +++ b/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp @@ -4,6 +4,7 @@ #include "WorkflowBase.h" #include "ExecutionContext.h" #include "ManifestComparator.h" +#include "DownloadFlow.h" #include "PromptFlow.h" #include "TableOutput.h" #include @@ -66,6 +67,13 @@ namespace AppInstaller::CLI::Workflow Repository::Source OpenNamedSource(Execution::Context& context, Utility::LocIndView sourceName) { + // Opening a source may require updating it. + context << GetProxyInfo; + if (context.IsTerminated()) + { + return {}; + } + Repository::Source source; try @@ -1356,37 +1364,6 @@ namespace AppInstaller::CLI::Workflow } table.Complete(); } - - void GetProxy(Execution::Context& context) - { - if (context.Contains(Execution::Data::ProxyUri)) - { - // Already determined proxy to use - return; - } - - // First check command line arguments. These override any default if present. - if (context.Args.Contains(Execution::Args::Type::NoProxy)) - { - AICLI_LOG(CLI, Info, << "Proxy disabled by command line argument"); - context.Add(std::nullopt); - return; - } - - if (context.Args.Contains(Execution::Args::Type::Proxy)) - { - auto proxyFromArg = context.Args.GetArg(Execution::Args::Type::Proxy); - AICLI_LOG(CLI, Info, << "Setting proxy from command line argument: " << proxyFromArg); - context.Add(std::string{ proxyFromArg }); - return; - } - - // Get the default proxy - std::optional defaultProxy = GroupPolicies().GetValueRef(); - AICLI_LOG(CLI, Info, << "Default proxy: " << (defaultProxy ? defaultProxy.value() : "Not configured")); - - context.Add(defaultProxy); - } } AppInstaller::CLI::Execution::Context& operator<<(AppInstaller::CLI::Execution::Context& context, AppInstaller::CLI::Workflow::WorkflowTask::Func f) diff --git a/src/AppInstallerCLICore/Workflows/WorkflowBase.h b/src/AppInstallerCLICore/Workflows/WorkflowBase.h index c913df7718..98df349531 100644 --- a/src/AppInstallerCLICore/Workflows/WorkflowBase.h +++ b/src/AppInstallerCLICore/Workflows/WorkflowBase.h @@ -434,12 +434,6 @@ namespace AppInstaller::CLI::Workflow private: ExecutionStage m_stage; }; - - // Gets the proxy to use according to the CLI arg, settings and policies. - // Required Args: None - // Inputs: None - // Outputs: ProxyUri - void GetProxy(Execution::Context& context); } // Passes the context to the function if it has not been terminated; returns the context. diff --git a/src/AppInstallerCLITests/Downloader.cpp b/src/AppInstallerCLITests/Downloader.cpp index 95f8337818..e9b49f1989 100644 --- a/src/AppInstallerCLITests/Downloader.cpp +++ b/src/AppInstallerCLITests/Downloader.cpp @@ -17,7 +17,7 @@ TEST_CASE("DownloadValidFileAndVerifyHash", "[Downloader]") // Todo: point to files from our repo when the repo goes public ProgressCallback callback; - auto result = Download("https://raw.githubusercontent.com/microsoft/msix-packaging/master/LICENSE", tempFile.GetPath(), DownloadType::Manifest, callback, true); + auto result = Download("https://raw.githubusercontent.com/microsoft/msix-packaging/master/LICENSE", tempFile.GetPath(), DownloadType::Manifest, callback, ProxyInfo::NoProxy, true); REQUIRE(result.has_value()); auto resultHash = result.value(); @@ -50,7 +50,7 @@ TEST_CASE("DownloadValidFileAndCancel", "[Downloader]") std::optional> waitResult; std::thread waitThread([&] { - waitResult = Download("https://aka.ms/win32-x64-user-stable", tempFile.GetPath(), DownloadType::Installer, callback, true); + waitResult = Download("https://aka.ms/win32-x64-user-stable", tempFile.GetPath(), DownloadType::Installer, callback, ProxyInfo::NoProxy, true); }); callback.Cancel(); @@ -67,7 +67,7 @@ TEST_CASE("DownloadInvalidUrl", "[Downloader]") ProgressCallback callback; - REQUIRE_THROWS(Download("blargle-flargle-fluff", tempFile.GetPath(), DownloadType::Installer, callback, true)); + REQUIRE_THROWS(Download("blargle-flargle-fluff", tempFile.GetPath(), DownloadType::Installer, callback, ProxyInfo::NoProxy, true)); } TEST_CASE("HttpStream_ReadLastFullPage", "[HttpStream]") @@ -77,7 +77,7 @@ TEST_CASE("HttpStream_ReadLastFullPage", "[HttpStream]") for (size_t i = 0; i < 10; ++i) { - stream = GetReadOnlyStreamFromURI("https://cdn.winget.microsoft.com/cache/source.msix"); + stream = GetReadOnlyStreamFromURI("https://cdn.winget.microsoft.com/cache/source.msix", ProxyInfo::NoProxy); stat = { 0 }; REQUIRE(stream->Stat(&stat, STATFLAG_NONAME) == S_OK); diff --git a/src/AppInstallerCLITests/MsixInfo.cpp b/src/AppInstallerCLITests/MsixInfo.cpp index 59a33f6f36..ad8c506120 100644 --- a/src/AppInstallerCLITests/MsixInfo.cpp +++ b/src/AppInstallerCLITests/MsixInfo.cpp @@ -84,7 +84,7 @@ TEST_CASE("MsixInfo_ValidateMsixTrustInfo", "[msixinfo]") TestCommon::TempFile microsoftSigned{ "testIndex"s, ".msix"s }; ProgressCallback callback; - Utility::Download("https://cdn.winget.microsoft.com/cache/source.msix", microsoftSigned.GetPath(), Utility::DownloadType::Index, callback); + Utility::Download("https://cdn.winget.microsoft.com/cache/source.msix", microsoftSigned.GetPath(), Utility::DownloadType::Index, callback, ProxyInfo::NoProxy); Msix::WriteLockedMsixFile microsoftSignedWriteLocked{ microsoftSigned }; REQUIRE(microsoftSignedWriteLocked.ValidateTrustInfo(true)); diff --git a/src/AppInstallerCLITests/TestCommon.cpp b/src/AppInstallerCLITests/TestCommon.cpp index fea68d8639..2993dd9171 100644 --- a/src/AppInstallerCLITests/TestCommon.cpp +++ b/src/AppInstallerCLITests/TestCommon.cpp @@ -325,7 +325,7 @@ namespace TestCommon auto path = testFile.GetPath().u8string(); // Get the stream for the test file - auto stream = AppInstaller::Utility::GetReadOnlyStreamFromURI(path); + auto stream = AppInstaller::Utility::GetReadOnlyStreamFromURI(path, {}); // Get manifest from package reader Microsoft::WRL::ComPtr packageReader; diff --git a/src/AppInstallerCLITests/pch.h b/src/AppInstallerCLITests/pch.h index fdceff3fea..12cd316374 100644 --- a/src/AppInstallerCLITests/pch.h +++ b/src/AppInstallerCLITests/pch.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include diff --git a/src/AppInstallerCommonCore/Downloader.cpp b/src/AppInstallerCommonCore/Downloader.cpp index 748cce6de9..4a1a98bc6d 100644 --- a/src/AppInstallerCommonCore/Downloader.cpp +++ b/src/AppInstallerCommonCore/Downloader.cpp @@ -90,11 +90,14 @@ namespace AppInstaller::Utility } } + const ProxyInfo ProxyInfo::NoProxy = {}; + std::optional> WinINetDownloadToStream( const std::string& url, std::ostream& dest, IProgressCallback& progress, - bool computeHash) + bool computeHash, + const ProxyInfo& proxyInfo) { // For AICLI_LOG usages with string literals. #pragma warning(push) @@ -105,8 +108,8 @@ namespace AppInstaller::Utility auto agentWide = Utility::ConvertToUTF16(Runtime::GetDefaultUserAgent().get()); wil::unique_hinternet session(InternetOpen( agentWide.c_str(), - INTERNET_OPEN_TYPE_PRECONFIG, - NULL, + proxyInfo.ProxyUri ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_PRECONFIG, + proxyInfo.ProxyUri ? Utility::ConvertToUTF16(proxyInfo.ProxyUri.value()).c_str() : NULL, NULL, 0)); THROW_LAST_ERROR_IF_NULL_MSG(session, "InternetOpen() failed."); @@ -268,11 +271,12 @@ namespace AppInstaller::Utility std::ostream& dest, DownloadType, IProgressCallback& progress, + const ProxyInfo& proxyInfo, bool computeHash, std::optional) { THROW_HR_IF(E_INVALIDARG, url.empty()); - return WinINetDownloadToStream(url, dest, progress, computeHash); + return WinINetDownloadToStream(url, dest, progress, computeHash, proxyInfo); } std::optional> Download( @@ -280,6 +284,7 @@ namespace AppInstaller::Utility const std::filesystem::path& dest, DownloadType type, IProgressCallback& progress, + const ProxyInfo& proxyInfo, bool computeHash, std::optional info) { @@ -298,9 +303,18 @@ namespace AppInstaller::Utility { // Determine whether to try DO first or not, as this is the only choice currently supported. InstallerDownloader setting = User().Get(); + bool useDeliveryOptimization = setting == InstallerDownloader::Default || + setting == InstallerDownloader::DeliveryOptimization; + + // DO does not support specifying a custom proxy. + // When proxy is requested, we switch to wininet + if (useDeliveryOptimization && proxyInfo.ProxyUri) + { + AICLI_LOG(Core, Info, << "Forcing use of wininet for download as DO does not support proxy"); + useDeliveryOptimization = false; + } - if (setting == InstallerDownloader::Default || - setting == InstallerDownloader::DeliveryOptimization) + if (useDeliveryOptimization) { try { @@ -346,7 +360,7 @@ namespace AppInstaller::Utility // Use std::ofstream::app to append to previous empty file so that it will not // create a new file and clear motw. std::ofstream outfile(dest, std::ofstream::binary | std::ofstream::app); - return WinINetDownloadToStream(url, outfile, progress, computeHash); + return WinINetDownloadToStream(url, outfile, progress, computeHash, proxyInfo); } using namespace std::string_view_literals; @@ -491,7 +505,7 @@ namespace AppInstaller::Utility return aesSaveResult; } - Microsoft::WRL::ComPtr GetReadOnlyStreamFromURI(std::string_view uriStr) + Microsoft::WRL::ComPtr GetReadOnlyStreamFromURI(std::string_view uriStr, const ProxyInfo&) { Microsoft::WRL::ComPtr inputStream; if (Utility::IsUrlRemote(uriStr)) diff --git a/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp b/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp index c838d2e8d8..dd12f05601 100644 --- a/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp +++ b/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp @@ -59,8 +59,8 @@ namespace AppInstaller::Manifest { AICLI_LOG(Core, Info, << "Start downloading installer"); auto tempFile = Runtime::GetNewTempFilePath(); - ProgressCallback callback; - Utility::Download(installerUrl, tempFile, Utility::DownloadType::Installer, callback); + ProgressCallback emptyCallback; + Utility::Download(installerUrl, tempFile, Utility::DownloadType::Installer, emptyCallback, Utility::ProxyInfo::NoProxy); m_downloadedInstallers.push_back(tempFile); return tempFile; } diff --git a/src/AppInstallerCommonCore/Public/AppInstallerDownloader.h b/src/AppInstallerCommonCore/Public/AppInstallerDownloader.h index c99e10767c..5f5fdee954 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerDownloader.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerDownloader.h @@ -4,11 +4,6 @@ #include #include -#include - -#include -#include - #include #include #include @@ -41,6 +36,16 @@ namespace AppInstaller::Utility std::string ContentId; }; + // Details on the proxy to use for the download + struct ProxyInfo + { + std::optional ProxyUri; + + // Represents configuration to not use a proxy. + // Used to track all the places where we do not support proxy yet. + static const ProxyInfo NoProxy; + }; + // An exception that indicates that a remote service is too busy/unavailable and may contain data on when to try again. struct ServiceUnavailableException : public wil::ResultException { @@ -56,30 +61,32 @@ namespace AppInstaller::Utility // url: The url to be downloaded from. http->https redirection is allowed. // dest: The stream to be downloaded to. // computeHash: Optional. Indicates if SHA256 hash should be calculated when downloading. - // downloadIdentifier: Optional. Currently only used by DO to identify the download. + // downloadInfo: Optional. Currently only used by DO to identify the download. std::optional> DownloadToStream( const std::string& url, std::ostream& dest, DownloadType type, IProgressCallback& progress, + const ProxyInfo& proxyInfo, bool computeHash = false, - std::optional info = {}); + std::optional downloadInfo = {}); // Downloads a file from the given URL and places it in the given location. // url: The url to be downloaded from. http->https redirection is allowed. // dest: The path to local file to be downloaded to. // computeHash: Optional. Indicates if SHA256 hash should be calculated when downloading. - // downloadIdentifier: Optional. Currently only used by DO to identify the download. + // downloadInfo: Optional. Currently only used by DO to identify the download. std::optional> Download( const std::string& url, const std::filesystem::path& dest, DownloadType type, IProgressCallback& progress, + const ProxyInfo& proxyInfo, bool computeHash = false, - std::optional info = {}); + std::optional downloadInfo = {}); // Gets the headers for the given URL. - std::map GetHeaders(std::string_view url); + std::map GetHeaders(std::string_view url, const ProxyInfo& proxyInfo); // Determines if the given url is a remote location. bool IsUrlRemote(std::string_view url); @@ -100,7 +107,7 @@ namespace AppInstaller::Utility HRESULT ApplyMotwUsingIAttachmentExecuteIfApplicable(const std::filesystem::path& filePath, const std::string& source, URLZONE zoneIfScanFailure); // Function to read-only create a stream from a uri string (url address or file system path) - Microsoft::WRL::ComPtr GetReadOnlyStreamFromURI(std::string_view uriStr); + ::Microsoft::WRL::ComPtr GetReadOnlyStreamFromURI(std::string_view uriStr, const ProxyInfo& proxyInfo); // Gets the retry after value in terms of a delay in seconds. std::chrono::seconds GetRetryAfter(const std::wstring& retryAfter); diff --git a/src/AppInstallerCommonCore/UserSettings.cpp b/src/AppInstallerCommonCore/UserSettings.cpp index bc02392383..12d4d378aa 100644 --- a/src/AppInstallerCommonCore/UserSettings.cpp +++ b/src/AppInstallerCommonCore/UserSettings.cpp @@ -261,6 +261,7 @@ namespace AppInstaller::Settings WINGET_VALIDATE_PASS_THROUGH(EFDirectMSI) WINGET_VALIDATE_PASS_THROUGH(EFResume) WINGET_VALIDATE_PASS_THROUGH(EFConfiguration03) + WINGET_VALIDATE_PASS_THROUGH(EFProxy) WINGET_VALIDATE_PASS_THROUGH(AnonymizePathForDisplay) WINGET_VALIDATE_PASS_THROUGH(TelemetryDisable) WINGET_VALIDATE_PASS_THROUGH(InteractivityDisable) diff --git a/src/AppInstallerRepositoryCore/InstallerMetadataCollectionContext.cpp b/src/AppInstallerRepositoryCore/InstallerMetadataCollectionContext.cpp index 0a343648ba..055c5df19d 100644 --- a/src/AppInstallerRepositoryCore/InstallerMetadataCollectionContext.cpp +++ b/src/AppInstallerRepositoryCore/InstallerMetadataCollectionContext.cpp @@ -831,7 +831,7 @@ namespace AppInstaller::Repository::Metadata { try { - auto downloadHash = DownloadToStream(utf8Uri, jsonStream, DownloadType::InstallerMetadataCollectionInput, emptyCallback); + auto downloadHash = DownloadToStream(utf8Uri, jsonStream, DownloadType::InstallerMetadataCollectionInput, emptyCallback, Utility::ProxyInfo::NoProxy); break; } catch (...) diff --git a/src/AppInstallerRepositoryCore/pch.h b/src/AppInstallerRepositoryCore/pch.h index 512990f9bd..fb24299526 100644 --- a/src/AppInstallerRepositoryCore/pch.h +++ b/src/AppInstallerRepositoryCore/pch.h @@ -20,23 +20,6 @@ #include #pragma warning( pop ) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include #include @@ -44,6 +27,7 @@ #include #include #include +#include #include #include @@ -77,3 +61,20 @@ #include #include #pragma warning( pop ) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/src/Microsoft.Management.Deployment/pch.h b/src/Microsoft.Management.Deployment/pch.h index b50e4d854b..47a1ae5ceb 100644 --- a/src/Microsoft.Management.Deployment/pch.h +++ b/src/Microsoft.Management.Deployment/pch.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include diff --git a/src/WinGetUtil/Exports.cpp b/src/WinGetUtil/Exports.cpp index a01c592547..5b2a09c79f 100644 --- a/src/WinGetUtil/Exports.cpp +++ b/src/WinGetUtil/Exports.cpp @@ -490,7 +490,7 @@ extern "C" THROW_HR_IF(E_INVALIDARG, computeHash && sha256HashLength != 32); AppInstaller::ProgressCallback callback; - auto hashValue = Download(ConvertToUTF8(url), filePath, DownloadType::WinGetUtil, callback, computeHash); + auto hashValue = Download(ConvertToUTF8(url), filePath, DownloadType::WinGetUtil, callback, ProxyInfo::NoProxy, computeHash); // At this point, if computeHash is set we have verified that the buffer is valid and 32 bytes. if (computeHash) diff --git a/src/WinGetUtil/pch.h b/src/WinGetUtil/pch.h index 99d149eb3a..9136b0b146 100644 --- a/src/WinGetUtil/pch.h +++ b/src/WinGetUtil/pch.h @@ -19,3 +19,4 @@ #include #include +#include From d002528cc8ca48f31310d0ca89f76f0af04f877f Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Fri, 23 Feb 2024 14:22:02 -0800 Subject: [PATCH 09/32] Add proxy info to sources --- .../Commands/HashCommand.cpp | 2 +- .../Workflows/DownloadFlow.cpp | 16 ++++++++++----- .../Workflows/WorkflowBase.cpp | 1 + src/AppInstallerCLITests/MsixInfo.cpp | 2 +- src/AppInstallerCommonCore/Deployment.cpp | 7 +++++-- src/AppInstallerCommonCore/Downloader.cpp | 7 ++++--- .../HttpStream/HttpClientWrapper.cpp | 3 ++- .../HttpStream/HttpClientWrapper.h | 7 ++++++- .../HttpStream/HttpRandomAccessStream.cpp | 4 ++-- .../HttpStream/HttpRandomAccessStream.h | 8 +++++++- .../Manifest/MsixManifestValidation.cpp | 2 +- src/AppInstallerCommonCore/MsixInfo.cpp | 4 ++-- .../Public/AppInstallerMsixInfo.h | 9 +++++++-- src/AppInstallerRepositoryCore/ISource.h | 5 +++++ .../PreIndexedPackageSourceFactory.cpp | 20 ++++++++++--------- .../Microsoft/SQLiteIndexSource.cpp | 8 ++++---- .../Public/winget/RepositorySource.h | 7 +++++++ .../RepositorySource.cpp | 8 ++++++++ .../Rest/RestSourceFactory.cpp | 5 +++++ .../Rest/Schema/HttpClientHelper.cpp | 5 +++++ .../Rest/Schema/HttpClientHelper.h | 3 +++ 21 files changed, 98 insertions(+), 35 deletions(-) diff --git a/src/AppInstallerCLICore/Commands/HashCommand.cpp b/src/AppInstallerCLICore/Commands/HashCommand.cpp index 0d6e01589e..f6838056a1 100644 --- a/src/AppInstallerCLICore/Commands/HashCommand.cpp +++ b/src/AppInstallerCLICore/Commands/HashCommand.cpp @@ -50,7 +50,7 @@ namespace AppInstaller::CLI { try { - Msix::MsixInfo msixInfo{ inputFile }; + Msix::MsixInfo msixInfo{ inputFile, Utility::ProxyInfo::NoProxy }; auto signatureHash = msixInfo.GetSignatureHash(); context.Reporter.Info() << "SignatureSha256: "_liv << Utility::LocIndString{ Utility::SHA256::ConvertToString(signatureHash) } << std::endl; diff --git a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp index d1223ce5b5..9b0701140d 100644 --- a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp @@ -216,7 +216,8 @@ namespace AppInstaller::CLI::Workflow // separately before, e.g. on COM scenarios. context << ReportExecutionStage(ExecutionStage::Download) << - CheckForExistingInstaller; + CheckForExistingInstaller << + GetProxyInfo; if (context.IsTerminated()) { @@ -242,14 +243,18 @@ namespace AppInstaller::CLI::Workflow context << DownloadInstallerFile; break; case InstallerTypeEnum::Msix: - if (installer.SignatureSha256.empty() || installerDownloadOnly) + // If the signature hash is provided in the manifest and we are doing an install, + // we can just verify signature hash without a full download and do a streaming install. + // Even if we have the signature hash, we still do a full download if InstallerDownloadOnly + // flag is set, or if we need to use a proxy (as deployment APIs won't use proxy for us). + if (installer.SignatureSha256.empty() + || installerDownloadOnly + || context.Get().ProxyUri) { - // If InstallerDownloadOnly flag is set, always download the installer file. context << DownloadInstallerFile; } else { - // Signature hash provided. No download needed. Just verify signature hash. context << GetMsixSignatureHash; } break; @@ -419,7 +424,8 @@ namespace AppInstaller::CLI::Workflow { const auto& installer = context.Get().value(); - Msix::MsixInfo msixInfo(installer.Url); + // Signature hash is only used for streaming installs, which don't use proxy + Msix::MsixInfo msixInfo(installer.Url, Utility::ProxyInfo::NoProxy); auto signatureHash = msixInfo.GetSignatureHash(); context.Add(std::make_pair(installer.SignatureSha256, signatureHash)); diff --git a/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp b/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp index fde4159348..9e1f65a481 100644 --- a/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp +++ b/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp @@ -117,6 +117,7 @@ namespace AppInstaller::CLI::Workflow { source.SetCaller("winget-cli"); source.SetAuthenticationArguments(GetAuthenticationArguments(context)); + source.SetProxyInfo(context.Get()); return source.Open(progress); }; auto updateFailures = context.Reporter.ExecuteWithProgress(openFunction, true); diff --git a/src/AppInstallerCLITests/MsixInfo.cpp b/src/AppInstallerCLITests/MsixInfo.cpp index ad8c506120..8f0b43ce52 100644 --- a/src/AppInstallerCLITests/MsixInfo.cpp +++ b/src/AppInstallerCLITests/MsixInfo.cpp @@ -84,7 +84,7 @@ TEST_CASE("MsixInfo_ValidateMsixTrustInfo", "[msixinfo]") TestCommon::TempFile microsoftSigned{ "testIndex"s, ".msix"s }; ProgressCallback callback; - Utility::Download("https://cdn.winget.microsoft.com/cache/source.msix", microsoftSigned.GetPath(), Utility::DownloadType::Index, callback, ProxyInfo::NoProxy); + Utility::Download("https://cdn.winget.microsoft.com/cache/source.msix", microsoftSigned.GetPath(), Utility::DownloadType::Index, callback, Utility::ProxyInfo::NoProxy); Msix::WriteLockedMsixFile microsoftSignedWriteLocked{ microsoftSigned }; REQUIRE(microsoftSignedWriteLocked.ValidateTrustInfo(true)); diff --git a/src/AppInstallerCommonCore/Deployment.cpp b/src/AppInstallerCommonCore/Deployment.cpp index 10add79822..dd2d983d90 100644 --- a/src/AppInstallerCommonCore/Deployment.cpp +++ b/src/AppInstallerCommonCore/Deployment.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT License. #include "pch.h" #include "Public/AppInstallerDeployment.h" +#include "Public/AppInstallerDownloader.h" #include "Public/AppInstallerLogging.h" #include "Public/AppInstallerMsixInfo.h" #include "Public/AppInstallerRuntime.h" @@ -114,7 +115,8 @@ namespace AppInstaller::Deployment PackageManager packageManager; // In the event of a failure we want to ensure that the package is not left on the system. - Msix::MsixInfo packageInfo{ uri }; + // No need for proxy as Deployment won't use it anyways. + Msix::MsixInfo packageInfo{ uri, Utility::ProxyInfo::NoProxy }; std::wstring packageFullNameWide = packageInfo.GetPackageFullNameWide(); std::string packageFullName = Utility::ConvertToUTF8(packageFullNameWide); auto removePackage = wil::scope_exit([&]() { @@ -218,7 +220,8 @@ namespace AppInstaller::Deployment PackageManager packageManager; // In the event of a failure we want to ensure that the package is not left on the system. - Msix::MsixInfo packageInfo{ uri }; + // No need for proxy as Deployment won't use it anyways. + Msix::MsixInfo packageInfo{ uri, Utility::ProxyInfo::NoProxy }; std::wstring packageFullNameWide = packageInfo.GetPackageFullNameWide(); std::string packageFullName = Utility::ConvertToUTF8(packageFullNameWide); std::string packageFamilyName = Msix::GetPackageFamilyNameFromFullName(packageFullName); diff --git a/src/AppInstallerCommonCore/Downloader.cpp b/src/AppInstallerCommonCore/Downloader.cpp index 4a1a98bc6d..0bac5d70a6 100644 --- a/src/AppInstallerCommonCore/Downloader.cpp +++ b/src/AppInstallerCommonCore/Downloader.cpp @@ -225,8 +225,9 @@ namespace AppInstaller::Utility return result; } - std::map GetHeaders(std::string_view url) + std::map GetHeaders(std::string_view url, const ProxyInfo&) { + // TODO: Use proxy info. HttpClient does not support using a custom proxy, only using the system-wide one. AICLI_LOG(Core, Verbose, << "Retrieving headers from url: " << url); HttpBaseProtocolFilter filter; @@ -505,7 +506,7 @@ namespace AppInstaller::Utility return aesSaveResult; } - Microsoft::WRL::ComPtr GetReadOnlyStreamFromURI(std::string_view uriStr, const ProxyInfo&) + Microsoft::WRL::ComPtr GetReadOnlyStreamFromURI(std::string_view uriStr, const ProxyInfo& proxyInfo) { Microsoft::WRL::ComPtr inputStream; if (Utility::IsUrlRemote(uriStr)) @@ -517,7 +518,7 @@ namespace AppInstaller::Utility try { - auto randomAccessStream = httpRandomAccessStream->InitializeAsync(uri).get(); + auto randomAccessStream = httpRandomAccessStream->InitializeAsync(uri, proxyInfo).get(); ::IUnknown* rasAsIUnknown = (::IUnknown*)winrt::get_abi(randomAccessStream); THROW_IF_FAILED(CreateStreamOverRandomAccessStream( diff --git a/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp b/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp index a9aedbb279..94e92c6f59 100644 --- a/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp +++ b/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp @@ -20,8 +20,9 @@ using namespace winrt::Windows::Web::Http::Filters; // The HRESULTs will be mapped to UI error code by the appropriate component namespace AppInstaller::Utility::HttpStream { - std::future> HttpClientWrapper::CreateAsync(const Uri& uri) + std::future> HttpClientWrapper::CreateAsync(const Uri& uri, const ProxyInfo&) { + // TODO: Use proxy info. HttpClient does not support using a custom proxy, only using the system-wide one. std::shared_ptr instance = std::make_shared(); // Use an HTTP filter to disable the default caching behavior and use the Most Recent caching behavior instead diff --git a/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.h b/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.h index 599c171224..e599947a5f 100644 --- a/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.h +++ b/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.h @@ -4,6 +4,11 @@ #include #include +namespace AppInstaller::Utility +{ + struct ProxyInfo; +} + namespace AppInstaller::Utility::HttpStream { // Wrapper around HTTP client. When created, an object of this class will send a HTTP @@ -11,7 +16,7 @@ namespace AppInstaller::Utility::HttpStream class HttpClientWrapper { public: - static std::future> CreateAsync(const winrt::Windows::Foundation::Uri& uri); + static std::future> CreateAsync(const winrt::Windows::Foundation::Uri& uri, const ProxyInfo& proxyInfo); std::future DownloadRangeAsync( const ULONG64 startPosition, diff --git a/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.cpp b/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.cpp index a2ab0a7821..d503e0cb31 100644 --- a/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.cpp +++ b/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.cpp @@ -13,13 +13,13 @@ using namespace winrt::Windows::Storage::Streams; // The HRESULTs will be mapped to UI error code by the appropriate component namespace AppInstaller::Utility::HttpStream { - IAsyncOperation HttpRandomAccessStream::InitializeAsync(const Uri& uri) + IAsyncOperation HttpRandomAccessStream::InitializeAsync(const Uri& uri, const Utility::ProxyInfo& proxyInfo) { auto strong_this{ get_strong() }; try { - strong_this->m_httpHelper = co_await HttpClientWrapper::CreateAsync(uri); + strong_this->m_httpHelper = co_await HttpClientWrapper::CreateAsync(uri, proxyInfo); strong_this->m_size = strong_this->m_httpHelper->GetFullFileSize(); strong_this->m_httpLocalCache = std::make_unique(); } diff --git a/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.h b/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.h index 6947be6578..ae0ea07ce3 100644 --- a/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.h +++ b/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.h @@ -7,6 +7,11 @@ using namespace std::chrono_literals; +namespace AppInstaller::Utility +{ + struct ProxyInfo; +} + namespace AppInstaller::Utility::HttpStream { // Provides an implementation of a random access stream over HTTP that supports @@ -20,7 +25,8 @@ namespace AppInstaller::Utility::HttpStream { public: winrt::Windows::Foundation::IAsyncOperation InitializeAsync( - const winrt::Windows::Foundation::Uri& uri); + const winrt::Windows::Foundation::Uri& uri, + const ProxyInfo& proxyInfo); uint64_t Size() const; void Size(uint64_t value); uint64_t Position() const; diff --git a/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp b/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp index dd12f05601..87d4ec2598 100644 --- a/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp +++ b/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp @@ -78,7 +78,7 @@ namespace AppInstaller::Manifest try { AICLI_LOG(Core, Info, << "Fetching Msix info from installer url"); - return std::make_shared(installerUrl); + return std::make_shared(installerUrl, Utility::ProxyInfo::NoProxy); } catch (...) { diff --git a/src/AppInstallerCommonCore/MsixInfo.cpp b/src/AppInstallerCommonCore/MsixInfo.cpp index c27d606136..c744d5e1b1 100644 --- a/src/AppInstallerCommonCore/MsixInfo.cpp +++ b/src/AppInstallerCommonCore/MsixInfo.cpp @@ -528,9 +528,9 @@ namespace AppInstaller::Msix return { std::move(certContext), std::move(certStore) }; } - MsixInfo::MsixInfo(std::string_view uriStr) + MsixInfo::MsixInfo(std::string_view uriStr, const Utility::ProxyInfo& proxyInfo) { - m_stream = Utility::GetReadOnlyStreamFromURI(uriStr); + m_stream = Utility::GetReadOnlyStreamFromURI(uriStr, proxyInfo); if (GetBundleReader(m_stream.Get(), &m_bundleReader)) { diff --git a/src/AppInstallerCommonCore/Public/AppInstallerMsixInfo.h b/src/AppInstallerCommonCore/Public/AppInstallerMsixInfo.h index 8d52581b75..00263ef308 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerMsixInfo.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerMsixInfo.h @@ -17,6 +17,11 @@ #include #include +namespace AppInstaller::Utility +{ + struct ProxyInfo; +} + namespace AppInstaller::Msix { // Function to create an AppxBundle package reader given the input file name. @@ -49,10 +54,10 @@ namespace AppInstaller::Msix // MsixInfo class handles all appx/msix related query. struct MsixInfo { - MsixInfo(std::string_view uriStr); + MsixInfo(std::string_view uriStr, const Utility::ProxyInfo& proxyInfo); template, int> = 0> - MsixInfo(const T& path) : MsixInfo(path.u8string()) {} + MsixInfo(const T& path) : MsixInfo(path.u8string(), Utility::ProxyInfo::NoProxy) {} MsixInfo(const MsixInfo&) = default; MsixInfo& operator=(const MsixInfo&) = default; diff --git a/src/AppInstallerRepositoryCore/ISource.h b/src/AppInstallerRepositoryCore/ISource.h index 5dc609ee1d..2d070b01a6 100644 --- a/src/AppInstallerRepositoryCore/ISource.h +++ b/src/AppInstallerRepositoryCore/ISource.h @@ -4,6 +4,11 @@ #include "Public/winget/RepositorySource.h" #include +namespace AppInstaller::Utility +{ + struct ProxyInfo; +} + namespace AppInstaller::Repository { // To allow for runtime casting from ISource to the specific types, this enum contains all of the ISource implementations. diff --git a/src/AppInstallerRepositoryCore/Microsoft/PreIndexedPackageSourceFactory.cpp b/src/AppInstallerRepositoryCore/Microsoft/PreIndexedPackageSourceFactory.cpp index c1dd214a62..0b0c919aae 100644 --- a/src/AppInstallerRepositoryCore/Microsoft/PreIndexedPackageSourceFactory.cpp +++ b/src/AppInstallerRepositoryCore/Microsoft/PreIndexedPackageSourceFactory.cpp @@ -72,7 +72,7 @@ namespace AppInstaller::Repository::Microsoft try { - m_msixInfo = std::make_unique(m_packageLocation); + m_msixInfo = std::make_unique(m_packageLocation, details.ProxyInfo); return; } catch (...) @@ -89,7 +89,7 @@ namespace AppInstaller::Repository::Microsoft try { - m_msixInfo = std::make_unique(m_packageLocation); + m_msixInfo = std::make_unique(m_packageLocation, details.ProxyInfo); return; } CATCH_LOG_MSG("PreIndexedPackageInfo failed on alternate location"); @@ -118,7 +118,7 @@ namespace AppInstaller::Repository::Microsoft try { - m_availableVersion = GetAvailableVersionFrom(m_packageLocation); + m_availableVersion = GetAvailableVersionFrom(m_packageLocation, details.ProxyInfo); return; } catch (...) @@ -136,7 +136,7 @@ namespace AppInstaller::Repository::Microsoft try { - m_availableVersion = GetAvailableVersionFrom(m_packageLocation); + m_availableVersion = GetAvailableVersionFrom(m_packageLocation, details.ProxyInfo); return; } CATCH_LOG_MSG("PreIndexedPackageUpdateCheck failed on alternate location"); @@ -151,11 +151,11 @@ namespace AppInstaller::Repository::Microsoft std::string m_packageLocation; Msix::PackageVersion m_availableVersion; - Msix::PackageVersion GetAvailableVersionFrom(const std::string& packageLocation) + Msix::PackageVersion GetAvailableVersionFrom(const std::string& packageLocation, const Utility::ProxyInfo& proxyInfo) { if (Utility::IsUrlRemote(packageLocation)) { - std::map headers = Utility::GetHeaders(packageLocation); + std::map headers = Utility::GetHeaders(packageLocation, proxyInfo); auto itr = headers.find(std::string{ s_PreIndexedPackageSourceFactory_PackageVersionHeader }); if (itr != headers.end()) { @@ -176,7 +176,7 @@ namespace AppInstaller::Repository::Microsoft } AICLI_LOG(Repo, Verbose, << "Reading package data to determine version"); - Msix::MsixInfo info{ packageLocation }; + Msix::MsixInfo info{ packageLocation, proxyInfo }; auto manifest = info.GetAppPackageManifests(); THROW_HR_IF(APPINSTALLER_CLI_ERROR_PACKAGE_IS_BUNDLE, manifest.size() > 1); @@ -476,6 +476,7 @@ namespace AppInstaller::Repository::Microsoft private: SourceDetails m_details; + Utility::ProxyInfo m_proxyInfo; }; // Source factory for running within a packaged context @@ -503,7 +504,7 @@ namespace AppInstaller::Repository::Microsoft localFile = Runtime::GetPathTo(Runtime::PathName::Temp); localFile /= GetPackageFamilyNameFromDetails(details) + ".msix"; - Utility::Download(packageLocation, localFile, Utility::DownloadType::Index, progress); + Utility::Download(packageLocation, localFile, Utility::DownloadType::Index, progress, details.ProxyInfo); } else { @@ -631,6 +632,7 @@ namespace AppInstaller::Repository::Microsoft private: SourceDetails m_details; + Utility::ProxyInfo m_proxyInfo; }; // Source factory for running outside of a package. @@ -669,7 +671,7 @@ namespace AppInstaller::Repository::Microsoft if (Utility::IsUrlRemote(packageLocation)) { - AppInstaller::Utility::Download(packageLocation, tempPackagePath, AppInstaller::Utility::DownloadType::Index, progress); + AppInstaller::Utility::Download(packageLocation, tempPackagePath, AppInstaller::Utility::DownloadType::Index, progress, details.ProxyInfo); } else { diff --git a/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.cpp b/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.cpp index 908d0fc4fc..d38dad4a88 100644 --- a/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.cpp +++ b/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.cpp @@ -86,7 +86,7 @@ namespace AppInstaller::Repository::Microsoft HRESULT primaryHR = S_OK; try { - return GetManifestFromArgAndRelativePath(source->GetDetails().Arg, relativePathOpt.value(), manifestSHA256); + return GetManifestFromArgAndRelativePath(source->GetDetails().Arg, relativePathOpt.value(), manifestSHA256, source->GetDetails().ProxyInfo); } catch (...) { @@ -100,7 +100,7 @@ namespace AppInstaller::Repository::Microsoft // Try alternate location try { - return GetManifestFromArgAndRelativePath(source->GetDetails().AlternateArg, relativePathOpt.value(), manifestSHA256); + return GetManifestFromArgAndRelativePath(source->GetDetails().AlternateArg, relativePathOpt.value(), manifestSHA256, source->GetDetails().ProxyInfo); } CATCH_LOG_MSG("GetManifest failed on alternate location"); @@ -126,7 +126,7 @@ namespace AppInstaller::Repository::Microsoft } private: - static Manifest::Manifest GetManifestFromArgAndRelativePath(const std::string& arg, const std::string& relativePath, const SHA256::HashBuffer& expectedHash) + static Manifest::Manifest GetManifestFromArgAndRelativePath(const std::string& arg, const std::string& relativePath, const SHA256::HashBuffer& expectedHash, const Utility::ProxyInfo& proxyInfo) { std::string fullPath = arg; if (fullPath.back() != '/') @@ -148,7 +148,7 @@ namespace AppInstaller::Repository::Microsoft { try { - auto downloadHash = Utility::DownloadToStream(fullPath, manifestStream, Utility::DownloadType::Manifest, emptyCallback, !expectedHash.empty()); + auto downloadHash = Utility::DownloadToStream(fullPath, manifestStream, Utility::DownloadType::Manifest, emptyCallback, proxyInfo, !expectedHash.empty()); if (!expectedHash.empty() && (!downloadHash || downloadHash->size() != expectedHash.size() || !std::equal(expectedHash.begin(), expectedHash.end(), downloadHash->begin()))) diff --git a/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h b/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h index 486e69d524..0f2932364f 100644 --- a/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h +++ b/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h @@ -3,6 +3,7 @@ #pragma once #include #include +#include #include #include #include @@ -132,6 +133,9 @@ namespace AppInstaller::Repository // The configuration of how the server certificate will be validated. Certificates::PinningConfiguration CertificatePinningConfiguration; + // Proxy to use when talking to the source + Utility::ProxyInfo ProxyInfo = {}; + // This value is used as an alternative to the `Arg` value if it is failing to function properly. // The alternate location must point to identical data or inconsistencies may arise. std::string AlternateArg; @@ -248,6 +252,9 @@ namespace AppInstaller::Repository // Set authentication arguments. Must be set before Open to have effect. void SetAuthenticationArguments(Authentication::AuthenticationArguments args); + // Set proxy info. Must be set before Open to have effect. + void SetProxyInfo(const Utility::ProxyInfo& proxyInfo); + // Set background update check interval. void SetBackgroundUpdateInterval(TimeSpan interval); diff --git a/src/AppInstallerRepositoryCore/RepositorySource.cpp b/src/AppInstallerRepositoryCore/RepositorySource.cpp index bee2f4a4dc..9760aee579 100644 --- a/src/AppInstallerRepositoryCore/RepositorySource.cpp +++ b/src/AppInstallerRepositoryCore/RepositorySource.cpp @@ -555,6 +555,14 @@ namespace AppInstaller::Repository } } + void Source::SetProxyInfo(const Utility::ProxyInfo& proxyInfo) + { + for (auto& sourceReference : m_sourceReferences) + { + sourceReference->GetDetails().ProxyInfo = proxyInfo; + } + } + void Source::SetBackgroundUpdateInterval(TimeSpan interval) { m_backgroundUpdateInterval = interval; diff --git a/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp b/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp index 29367d9724..7f6c5d84f7 100644 --- a/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp +++ b/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp @@ -61,6 +61,11 @@ namespace AppInstaller::Repository::Rest [&]() { m_httpClientHelper.SetPinningConfiguration(m_details.CertificatePinningConfiguration); + if (m_details.ProxyInfo.ProxyUri) + { + m_httpClientHelper.SetProxy(Utility::ConvertToUTF16(m_details.ProxyInfo.ProxyUri.value())); + } + auto sourceInformation = RestClient::GetInformation(m_details.Arg, m_customHeader, m_caller, m_httpClientHelper); m_details.Identifier = sourceInformation.SourceIdentifier; diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.cpp index 51276c1d7b..403f233537 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.cpp +++ b/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.cpp @@ -139,6 +139,11 @@ namespace AppInstaller::Repository::Rest::Schema }); } + void HttpClientHelper::SetProxy(const utility::string_t& uri) + { + m_clientConfig.set_proxy(web::web_proxy{ uri }); + } + web::http::client::http_client HttpClientHelper::GetClient(const utility::string_t& uri) const { web::http::client::http_client client{ uri, m_clientConfig }; diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.h b/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.h index c7938c3329..0f0dcaf6e6 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.h +++ b/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.h @@ -26,6 +26,9 @@ namespace AppInstaller::Repository::Rest::Schema std::optional HandleGet(const utility::string_t& uri, const HttpRequestHeaders& headers = {}, const HttpRequestHeaders& authHeaders = {}) const; void SetPinningConfiguration(const Certificates::PinningConfiguration& configuration); + + void SetProxy(const utility::string_t& proxyUri); + protected: std::optional ValidateAndExtractResponse(const web::http::http_response& response) const; From 7caaa8608aed986392e7e71c7ddd61f6a53377f5 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Fri, 23 Feb 2024 17:36:04 -0800 Subject: [PATCH 10/32] Add admin setting for default proxy --- src/AppInstallerCLICore/Argument.cpp | 10 +- src/AppInstallerCLICore/Argument.h | 2 +- src/AppInstallerCLICore/Command.cpp | 2 +- .../Commands/SettingsCommand.cpp | 10 +- .../Workflows/ArchiveFlow.cpp | 2 +- .../Workflows/DownloadFlow.cpp | 2 +- src/AppInstallerCLITests/AdminSettings.cpp | 23 +- src/AppInstallerCLITests/InstallFlow.cpp | 4 +- src/AppInstallerCommonCore/AdminSettings.cpp | 267 ++++++++++++++---- .../Public/winget/AdminSettings.h | 32 ++- src/AppInstallerRepositoryCore/SourceList.cpp | 2 +- .../Public/AppInstallerLanguageUtilities.h | 29 ++ 12 files changed, 283 insertions(+), 102 deletions(-) diff --git a/src/AppInstallerCLICore/Argument.cpp b/src/AppInstallerCLICore/Argument.cpp index e9f8b97714..b2bde9919c 100644 --- a/src/AppInstallerCLICore/Argument.cpp +++ b/src/AppInstallerCLICore/Argument.cpp @@ -273,7 +273,7 @@ namespace AppInstaller::CLI case Args::Type::MultiQuery: return Argument{ type, Resource::String::MultiQueryArgumentDescription, ArgumentType::Positional }.SetCountLimit(128); case Args::Type::Manifest: - return Argument{ type, Resource::String::ManifestArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help, Settings::TogglePolicy::Policy::LocalManifestFiles, Settings::AdminSetting::LocalManifestFiles }; + return Argument{ type, Resource::String::ManifestArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help, Settings::TogglePolicy::Policy::LocalManifestFiles, Settings::BoolAdminSetting::LocalManifestFiles }; case Args::Type::Id: return Argument{ type, Resource::String::IdArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help }; case Args::Type::Name: @@ -313,7 +313,7 @@ namespace AppInstaller::CLI case Args::Type::InstallLocation: return Argument{ type, Resource::String::LocationArgumentDescription, ArgumentType::Standard }; case Args::Type::HashOverride: - return Argument{ type, Resource::String::HashOverrideArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::HashOverride, Settings::AdminSetting::InstallerHashOverride }; + return Argument{ type, Resource::String::HashOverrideArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::HashOverride, Settings::BoolAdminSetting::InstallerHashOverride }; case Args::Type::AcceptPackageAgreements: return Argument{ type, Resource::String::AcceptPackageAgreementsArgumentDescription, ArgumentType::Flag }; case Args::Type::NoUpgrade: @@ -329,7 +329,7 @@ namespace AppInstaller::CLI case Args::Type::SkipDependencies: return Argument{ type, Resource::String::SkipDependenciesArgumentDescription, ArgumentType::Flag, false }; case Args::Type::IgnoreLocalArchiveMalwareScan: - return Argument{ type, Resource::String::IgnoreLocalArchiveMalwareScanArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::LocalArchiveMalwareScanOverride, Settings::AdminSetting::LocalArchiveMalwareScanOverride }; + return Argument{ type, Resource::String::IgnoreLocalArchiveMalwareScanArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::LocalArchiveMalwareScanOverride, Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride }; case Args::Type::SourceName: return Argument{ type, Resource::String::SourceNameArgumentDescription, ArgumentType::Positional, false }; case Args::Type::SourceArg: @@ -385,9 +385,9 @@ namespace AppInstaller::CLI case Args::Type::IgnoreResumeLimit: return Argument{ type, Resource::String::IgnoreResumeLimitArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Resume }; case Args::Type::Proxy: - return Argument{ type, Resource::String::ProxyArgumentDescription, ArgumentType::Standard, ExperimentalFeature::Feature::Proxy, TogglePolicy::Policy::ProxyCommandLineOptions, AdminSetting::ProxyCommandLineOptions }; + return Argument{ type, Resource::String::ProxyArgumentDescription, ArgumentType::Standard, ExperimentalFeature::Feature::Proxy, TogglePolicy::Policy::ProxyCommandLineOptions, BoolAdminSetting::ProxyCommandLineOptions }; case Args::Type::NoProxy: - return Argument{ type, Resource::String::NoProxyArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Proxy, TogglePolicy::Policy::ProxyCommandLineOptions, AdminSetting::ProxyCommandLineOptions }; + return Argument{ type, Resource::String::NoProxyArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Proxy, TogglePolicy::Policy::ProxyCommandLineOptions, BoolAdminSetting::ProxyCommandLineOptions }; default: THROW_HR(E_UNEXPECTED); } diff --git a/src/AppInstallerCLICore/Argument.h b/src/AppInstallerCLICore/Argument.h index 2016880480..d82374c30a 100644 --- a/src/AppInstallerCLICore/Argument.h +++ b/src/AppInstallerCLICore/Argument.h @@ -255,6 +255,6 @@ namespace AppInstaller::CLI size_t m_countLimit = 1; Settings::ExperimentalFeature::Feature m_feature = Settings::ExperimentalFeature::Feature::None; Settings::TogglePolicy::Policy m_groupPolicy = Settings::TogglePolicy::Policy::None; - Settings::AdminSetting m_adminSetting = Settings::AdminSetting::Unknown; + Settings::AdminSetting m_adminSetting = Settings::BoolAdminSetting::Unknown; }; } diff --git a/src/AppInstallerCLICore/Command.cpp b/src/AppInstallerCLICore/Command.cpp index dec1945adf..408b7adfe7 100644 --- a/src/AppInstallerCLICore/Command.cpp +++ b/src/AppInstallerCLICore/Command.cpp @@ -637,7 +637,7 @@ namespace AppInstaller::CLI throw GroupPolicyException(arg.GroupPolicy()); } - if (arg.AdminSetting() != AdminSetting::Unknown && !Settings::IsAdminSettingEnabled(arg.AdminSetting()) && execArgs.Contains(arg.ExecArgType())) + if (arg.AdminSetting() != BoolAdminSetting::Unknown && !Settings::IsAdminSettingEnabled(arg.AdminSetting()) && execArgs.Contains(arg.ExecArgType())) { auto setting = Settings::AdminSettingToString(arg.AdminSetting()); AICLI_LOG(CLI, Error, << "Trying to use argument: " << arg.Name() << " disabled by admin setting " << setting); diff --git a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp index 55c436e631..4050c37ef7 100644 --- a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp +++ b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp @@ -49,21 +49,19 @@ namespace AppInstaller::CLI void SettingsCommand::ValidateArgumentsInternal(Execution::Args& execArgs) const { // Get admin setting string for all available options except Unknown - using AdminSetting_t = std::underlying_type_t; - std::vector adminSettingList; - for (AdminSetting_t i = 1 + static_cast(AdminSetting::Unknown); i < static_cast(AdminSetting::Max); ++i) + for (auto setting : GetAllSequentialEnumValues(BoolAdminSetting::Unknown)) { - adminSettingList.emplace_back(AdminSettingToString(static_cast(i))); + adminSettingList.emplace_back(AdminSettingToString(setting)); } Utility::LocIndString validOptions = Join(", "_liv, adminSettingList); - if (execArgs.Contains(Execution::Args::Type::AdminSettingEnable) && AdminSetting::Unknown == StringToAdminSetting(execArgs.GetArg(Execution::Args::Type::AdminSettingEnable))) + if (execArgs.Contains(Execution::Args::Type::AdminSettingEnable) && BoolAdminSetting::Unknown == StringToAdminSetting(execArgs.GetArg(Execution::Args::Type::AdminSettingEnable))) { throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::AdminSettingEnable).Name, validOptions)); } - if (execArgs.Contains(Execution::Args::Type::AdminSettingDisable) && AdminSetting::Unknown == StringToAdminSetting(execArgs.GetArg(Execution::Args::Type::AdminSettingDisable))) + if (execArgs.Contains(Execution::Args::Type::AdminSettingDisable) && BoolAdminSetting::Unknown == StringToAdminSetting(execArgs.GetArg(Execution::Args::Type::AdminSettingDisable))) { throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::AdminSettingDisable).Name, validOptions)); } diff --git a/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp b/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp index c273fd827a..069598e45b 100644 --- a/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp @@ -29,7 +29,7 @@ namespace AppInstaller::CLI::Workflow else { if (context.Args.Contains(Execution::Args::Type::IgnoreLocalArchiveMalwareScan) && - Settings::IsAdminSettingEnabled(Settings::AdminSetting::LocalArchiveMalwareScanOverride)) + Settings::IsAdminSettingEnabled(Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride)) { AICLI_LOG(CLI, Warning, << "Archive scan detected malware. Proceeding due to --ignore-local-archive-malware-scan"); context.Reporter.Warn() << Resource::String::ArchiveFailedMalwareScanOverridden << std::endl; diff --git a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp index 9b0701140d..0ebe6e2245 100644 --- a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp @@ -461,7 +461,7 @@ namespace AppInstaller::CLI::Workflow { context.Reporter.Error() << Resource::String::InstallerHashMismatchAdminBlock << std::endl; } - else if (!Settings::IsAdminSettingEnabled(Settings::AdminSetting::InstallerHashOverride)) + else if (!Settings::IsAdminSettingEnabled(Settings::BoolAdminSetting::InstallerHashOverride)) { context.Reporter.Error() << Resource::String::InstallerHashMismatchError << std::endl; } diff --git a/src/AppInstallerCLITests/AdminSettings.cpp b/src/AppInstallerCLITests/AdminSettings.cpp index 3495cb677a..a7fa9d2a15 100644 --- a/src/AppInstallerCLITests/AdminSettings.cpp +++ b/src/AppInstallerCLITests/AdminSettings.cpp @@ -16,21 +16,21 @@ TEST_CASE("AdminSetting_Enable", "[adminSettings]") { GroupPolicyTestOverride policies; policies.SetState(TogglePolicy::Policy::LocalManifestFiles, PolicyState::NotConfigured); - REQUIRE(EnableAdminSetting(AdminSetting::LocalManifestFiles)); + REQUIRE(EnableAdminSetting(BoolAdminSetting::LocalManifestFiles)); } SECTION("Enabled") { GroupPolicyTestOverride policies; policies.SetState(TogglePolicy::Policy::LocalManifestFiles, PolicyState::Enabled); - REQUIRE(EnableAdminSetting(AdminSetting::LocalManifestFiles)); + REQUIRE(EnableAdminSetting(BoolAdminSetting::LocalManifestFiles)); } SECTION("Disabled") { GroupPolicyTestOverride policies; policies.SetState(TogglePolicy::Policy::LocalManifestFiles, PolicyState::Disabled); - REQUIRE_FALSE(EnableAdminSetting(AdminSetting::LocalManifestFiles)); + REQUIRE_FALSE(EnableAdminSetting(BoolAdminSetting::LocalManifestFiles)); } } } @@ -43,37 +43,32 @@ TEST_CASE("AdminSetting_Disable", "[adminSettings]") { GroupPolicyTestOverride policies; policies.SetState(TogglePolicy::Policy::LocalManifestFiles, PolicyState::NotConfigured); - REQUIRE(DisableAdminSetting(AdminSetting::LocalManifestFiles)); + REQUIRE(DisableAdminSetting(BoolAdminSetting::LocalManifestFiles)); } SECTION("Enabled") { GroupPolicyTestOverride policies; policies.SetState(TogglePolicy::Policy::LocalManifestFiles, PolicyState::Enabled); - REQUIRE_FALSE(DisableAdminSetting(AdminSetting::LocalManifestFiles)); + REQUIRE_FALSE(DisableAdminSetting(BoolAdminSetting::LocalManifestFiles)); } SECTION("Disabled") { GroupPolicyTestOverride policies; policies.SetState(TogglePolicy::Policy::LocalManifestFiles, PolicyState::Disabled); - REQUIRE(DisableAdminSetting(AdminSetting::LocalManifestFiles)); + REQUIRE(DisableAdminSetting(BoolAdminSetting::LocalManifestFiles)); } } } TEST_CASE("AdminSetting_AllSettingsAreImplemented", "[adminSettings]") { - using AdminSetting_t = std::underlying_type_t; - - // Skip Unknown. - for (AdminSetting_t i = 1 + static_cast(AdminSetting::Unknown); i < static_cast(AdminSetting::Max); ++i) + for (auto adminSetting : GetAllBoolAdminSettings()) { - auto adminSetting = static_cast(i); - // If we forget to add it to the conversion, it returns Unknown/None - REQUIRE(AdminSettingToString(adminSetting) != AdminSettingToString(AdminSetting::Unknown)); - REQUIRE(StringToAdminSetting(AdminSettingToString(adminSetting)) != AdminSetting::Unknown); + REQUIRE(AdminSettingToString(adminSetting) != AdminSettingToString(BoolAdminSetting::Unknown)); + REQUIRE(StringToBoolAdminSetting(AdminSettingToString(adminSetting)) != BoolAdminSetting::Unknown); REQUIRE(GetAdminSettingPolicy(adminSetting) != TogglePolicy::Policy::None); GroupPolicyTestOverride policies; diff --git a/src/AppInstallerCLITests/InstallFlow.cpp b/src/AppInstallerCLITests/InstallFlow.cpp index 56f117bceb..a52dd702a1 100644 --- a/src/AppInstallerCLITests/InstallFlow.cpp +++ b/src/AppInstallerCLITests/InstallFlow.cpp @@ -450,7 +450,7 @@ TEST_CASE("InstallFlow_Zip_ArchiveScanOverride_AdminSettingDisabled", "[InstallF context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_Zip_Exe.yaml").GetPath().u8string()); context.Args.AddArg(Execution::Args::Type::IgnoreLocalArchiveMalwareScan); - DisableAdminSetting(AppInstaller::Settings::AdminSetting::LocalArchiveMalwareScanOverride); + DisableAdminSetting(AppInstaller::Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride); TestHook::SetScanArchiveResult_Override scanArchiveResultOverride(false); @@ -478,7 +478,7 @@ TEST_CASE("InstallFlow_Zip_ArchiveScanOverride_AdminSettingEnabled", "[InstallFl context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_Zip_Exe.yaml").GetPath().u8string()); context.Args.AddArg(Execution::Args::Type::IgnoreLocalArchiveMalwareScan); - EnableAdminSetting(AppInstaller::Settings::AdminSetting::LocalArchiveMalwareScanOverride); + EnableAdminSetting(AppInstaller::Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride); TestHook::SetScanArchiveResult_Override scanArchiveResultOverride(false); diff --git a/src/AppInstallerCommonCore/AdminSettings.cpp b/src/AppInstallerCommonCore/AdminSettings.cpp index b0d979a272..4053e3c258 100644 --- a/src/AppInstallerCommonCore/AdminSettings.cpp +++ b/src/AppInstallerCommonCore/AdminSettings.cpp @@ -21,6 +21,8 @@ namespace AppInstaller::Settings constexpr Utility::LocIndView s_AdminSettingsYaml_LocalArchiveMalwareScanOverride = "LocalArchiveMalwareScanOverride"_liv; constexpr Utility::LocIndView s_AdminSettingsYaml_ProxyCommandLineOptions = "ProxyCommandLineOptions"_liv; + constexpr Utility::LocIndView s_AdminSettingsYaml_DefaultProxy = "DefaultProxy"_liv; + // Attempts to read a single scalar value from the node. template bool TryReadScalar(const YAML::Node& rootNode, std::string_view name, Value& value) @@ -44,20 +46,29 @@ namespace AppInstaller::Settings bool InstallerHashOverride = false; bool LocalArchiveMalwareScanOverride = false; bool ProxyCommandLineOptions = false; + + std::optional DefaultProxy; }; struct AdminSettingsInternal { AdminSettingsInternal(); - void SetAdminSetting(AdminSetting setting, bool enabled); + void SetAdminSetting(BoolAdminSetting setting, bool enabled); + void SetAdminSetting(StringAdminSetting setting, const std::optional& value); - bool GetAdminSettingBoolValue(AdminSetting setting) const; + bool GetAdminSettingValue(BoolAdminSetting setting) const; + std::optional GetAdminSettingValue(StringAdminSetting setting) const; private: void LoadAdminSettings(); [[nodiscard]] bool SaveAdminSettings(); + // Sets the value of an admin setting using the given function and then saves the changes. + // Encapsulates the retry and reload logic. + // Stops if the value cannot be set, as indicated by the return value of setValue() + void SetAdminSettingAndSave(std::function setValue); + Stream m_settingStream; AdminSettingValues m_settingValues; }; @@ -67,28 +78,12 @@ namespace AppInstaller::Settings LoadAdminSettings(); } - void AdminSettingsInternal::SetAdminSetting(AdminSetting setting, bool enabled) + void AdminSettingsInternal::SetAdminSettingAndSave(std::function setValue) { for (size_t i = 0; i < 10; ++i) { - switch (setting) + if (!setValue()) { - case AdminSetting::LocalManifestFiles: - m_settingValues.LocalManifestFiles = enabled; - break; - case AdminSetting::BypassCertificatePinningForMicrosoftStore: - m_settingValues.BypassCertificatePinningForMicrosoftStore = enabled; - break; - case AdminSetting::InstallerHashOverride: - m_settingValues.InstallerHashOverride = enabled; - break; - case AdminSetting::LocalArchiveMalwareScanOverride: - m_settingValues.LocalArchiveMalwareScanOverride = enabled; - break; - case AdminSetting::ProxyCommandLineOptions: - m_settingValues.ProxyCommandLineOptions = enabled; - break; - default: return; } @@ -104,25 +99,78 @@ namespace AppInstaller::Settings THROW_HR_MSG(E_UNEXPECTED, "Too many attempts at SaveAdminSettings"); } - bool AdminSettingsInternal::GetAdminSettingBoolValue(AdminSetting setting) const + void AdminSettingsInternal::SetAdminSetting(BoolAdminSetting setting, bool enabled) + { + SetAdminSettingAndSave([&]() + { + switch (setting) + { + case BoolAdminSetting::LocalManifestFiles: + m_settingValues.LocalManifestFiles = enabled; + return true; + case BoolAdminSetting::BypassCertificatePinningForMicrosoftStore: + m_settingValues.BypassCertificatePinningForMicrosoftStore = enabled; + return true; + case BoolAdminSetting::InstallerHashOverride: + m_settingValues.InstallerHashOverride = enabled; + return true; + case BoolAdminSetting::LocalArchiveMalwareScanOverride: + m_settingValues.LocalArchiveMalwareScanOverride = enabled; + return true; + case BoolAdminSetting::ProxyCommandLineOptions: + m_settingValues.ProxyCommandLineOptions = enabled; + return true; + default: + return false; + } + }); + } + + void AdminSettingsInternal::SetAdminSetting(StringAdminSetting setting, const std::optional& value) + { + SetAdminSettingAndSave([&]() + { + switch (setting) + { + case StringAdminSetting::DefaultProxy: + m_settingValues.DefaultProxy = value; + return true; + default: + return false; + } + }); + } + + bool AdminSettingsInternal::GetAdminSettingValue(BoolAdminSetting setting) const { switch (setting) { - case AdminSetting::LocalManifestFiles: + case BoolAdminSetting::LocalManifestFiles: return m_settingValues.LocalManifestFiles; - case AdminSetting::BypassCertificatePinningForMicrosoftStore: + case BoolAdminSetting::BypassCertificatePinningForMicrosoftStore: return m_settingValues.BypassCertificatePinningForMicrosoftStore; - case AdminSetting::InstallerHashOverride: + case BoolAdminSetting::InstallerHashOverride: return m_settingValues.InstallerHashOverride; - case AdminSetting::LocalArchiveMalwareScanOverride: + case BoolAdminSetting::LocalArchiveMalwareScanOverride: return m_settingValues.LocalArchiveMalwareScanOverride; - case AdminSetting::ProxyCommandLineOptions: + case BoolAdminSetting::ProxyCommandLineOptions: return m_settingValues.ProxyCommandLineOptions; default: return false; } } + std::optional AdminSettingsInternal::GetAdminSettingValue(StringAdminSetting setting) const + { + switch (setting) + { + case StringAdminSetting::DefaultProxy: + return m_settingValues.DefaultProxy; + default: + return std::nullopt; + } + } + void AdminSettingsInternal::LoadAdminSettings() { auto stream = m_settingStream.Get(); @@ -162,6 +210,12 @@ namespace AppInstaller::Settings TryReadScalar(document, s_AdminSettingsYaml_InstallerHashOverride, m_settingValues.InstallerHashOverride); TryReadScalar(document, s_AdminSettingsYaml_LocalArchiveMalwareScanOverride, m_settingValues.LocalArchiveMalwareScanOverride); TryReadScalar(document, s_AdminSettingsYaml_ProxyCommandLineOptions, m_settingValues.ProxyCommandLineOptions); + + std::string defaultProxy; + if (TryReadScalar(document, s_AdminSettingsYaml_DefaultProxy, defaultProxy)) + { + m_settingValues.DefaultProxy.emplace(std::move(defaultProxy)); + } } bool AdminSettingsInternal::SaveAdminSettings() @@ -173,82 +227,127 @@ namespace AppInstaller::Settings out << YAML::Key << s_AdminSettingsYaml_InstallerHashOverride << YAML::Value << m_settingValues.InstallerHashOverride; out << YAML::Key << s_AdminSettingsYaml_LocalArchiveMalwareScanOverride << YAML::Value << m_settingValues.LocalArchiveMalwareScanOverride; out << YAML::Key << s_AdminSettingsYaml_ProxyCommandLineOptions << YAML::Value << m_settingValues.ProxyCommandLineOptions; + + if (m_settingValues.DefaultProxy) + { + out << YAML::Key << s_AdminSettingsYaml_DefaultProxy << YAML::Value << m_settingValues.DefaultProxy.value(); + } + out << YAML::EndMap; return m_settingStream.Set(out.str()); } + + auto GetPolicyStateForSetting(BoolAdminSetting setting) + { + auto policy = GetAdminSettingPolicy(setting); + return GroupPolicies().GetState(policy); + } + + std::optional> GetPolicyStateForSetting(StringAdminSetting setting) + { + switch (setting) + { + case AppInstaller::Settings::StringAdminSetting::DefaultProxy: + return GroupPolicies().GetValueRef(); + default: + return std::nullopt; + } + } } - AdminSetting StringToAdminSetting(std::string_view in) + BoolAdminSetting StringToBoolAdminSetting(std::string_view in) { - AdminSetting result = AdminSetting::Unknown; + BoolAdminSetting result = BoolAdminSetting::Unknown; if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_LocalManifestFiles, in)) { - result = AdminSetting::LocalManifestFiles; + result = BoolAdminSetting::LocalManifestFiles; } else if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore, in)) { - result = AdminSetting::BypassCertificatePinningForMicrosoftStore; + result = BoolAdminSetting::BypassCertificatePinningForMicrosoftStore; } else if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_InstallerHashOverride, in)) { - result = AdminSetting::InstallerHashOverride; + result = BoolAdminSetting::InstallerHashOverride; } else if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_LocalArchiveMalwareScanOverride, in)) { - result = AdminSetting::LocalArchiveMalwareScanOverride; + result = BoolAdminSetting::LocalArchiveMalwareScanOverride; } else if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_ProxyCommandLineOptions, in)) { - result = AdminSetting::ProxyCommandLineOptions; + result = BoolAdminSetting::ProxyCommandLineOptions; + } + + return result; + } + + StringAdminSetting StringToStringAdminSetting(std::string_view in) + { + StringAdminSetting result = StringAdminSetting::Unknown; + + if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_DefaultProxy, in)) + { + result = StringAdminSetting::DefaultProxy; } return result; } - Utility::LocIndView AdminSettingToString(AdminSetting setting) + Utility::LocIndView AdminSettingToString(BoolAdminSetting setting) { switch (setting) { - case AdminSetting::LocalManifestFiles: + case BoolAdminSetting::LocalManifestFiles: return s_AdminSettingsYaml_LocalManifestFiles; - case AdminSetting::BypassCertificatePinningForMicrosoftStore: + case BoolAdminSetting::BypassCertificatePinningForMicrosoftStore: return s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore; - case AdminSetting::InstallerHashOverride: + case BoolAdminSetting::InstallerHashOverride: return s_AdminSettingsYaml_InstallerHashOverride; - case AdminSetting::LocalArchiveMalwareScanOverride: + case BoolAdminSetting::LocalArchiveMalwareScanOverride: return s_AdminSettingsYaml_LocalArchiveMalwareScanOverride; - case AdminSetting::ProxyCommandLineOptions: + case BoolAdminSetting::ProxyCommandLineOptions: return s_AdminSettingsYaml_ProxyCommandLineOptions; default: return "Unknown"_liv; } } - TogglePolicy::Policy GetAdminSettingPolicy(AdminSetting setting) + Utility::LocIndView AdminSettingToString(StringAdminSetting setting) { switch (setting) { - case AdminSetting::LocalManifestFiles: + case StringAdminSetting::DefaultProxy: + return s_AdminSettingsYaml_DefaultProxy; + default: + return "Unknown"_liv; + } + } + + TogglePolicy::Policy GetAdminSettingPolicy(BoolAdminSetting setting) + { + switch (setting) + { + case BoolAdminSetting::LocalManifestFiles: return TogglePolicy::Policy::LocalManifestFiles; - case AdminSetting::BypassCertificatePinningForMicrosoftStore: + case BoolAdminSetting::BypassCertificatePinningForMicrosoftStore: return TogglePolicy::Policy::BypassCertificatePinningForMicrosoftStore; - case AdminSetting::InstallerHashOverride: + case BoolAdminSetting::InstallerHashOverride: return TogglePolicy::Policy::HashOverride; - case AdminSetting::LocalArchiveMalwareScanOverride: + case BoolAdminSetting::LocalArchiveMalwareScanOverride: return TogglePolicy::Policy::LocalArchiveMalwareScanOverride; - case AdminSetting::ProxyCommandLineOptions: + case BoolAdminSetting::ProxyCommandLineOptions: return TogglePolicy::Policy::ProxyCommandLineOptions; default: return TogglePolicy::Policy::None; } } - bool EnableAdminSetting(AdminSetting setting) + bool EnableAdminSetting(BoolAdminSetting setting) { - auto policy = GetAdminSettingPolicy(setting); - if (GroupPolicies().GetState(policy) == PolicyState::Disabled) + if (GetPolicyStateForSetting(setting) == PolicyState::Disabled) { return false; } @@ -258,10 +357,9 @@ namespace AppInstaller::Settings return true; } - bool DisableAdminSetting(AdminSetting setting) + bool DisableAdminSetting(BoolAdminSetting setting) { - auto policy = GetAdminSettingPolicy(setting); - if (GroupPolicies().GetState(policy) == PolicyState::Enabled) + if (GetPolicyStateForSetting(setting) == PolicyState::Enabled) { return false; } @@ -271,31 +369,78 @@ namespace AppInstaller::Settings return true; } - bool IsAdminSettingEnabled(AdminSetting setting) + bool IsAdminSettingEnabled(BoolAdminSetting setting) { // Check for a policy that overrides this setting. - auto policy = GetAdminSettingPolicy(setting); - auto policyState = GroupPolicies().GetState(policy); + auto policyState = GetPolicyStateForSetting(setting); if (policyState != PolicyState::NotConfigured) { return policyState == PolicyState::Enabled; } AdminSettingsInternal adminSettingsInternal; - return adminSettingsInternal.GetAdminSettingBoolValue(setting); + return adminSettingsInternal.GetAdminSettingValue(setting); + } + + bool SetAdminSetting(StringAdminSetting setting, std::string_view value) + { + if (GetPolicyStateForSetting(setting)) + { + return false; + } + + AdminSettingsInternal adminSettingsInternal; + adminSettingsInternal.SetAdminSetting(setting, std::string{ value }); + return true; + } + + bool ResetAdminSetting(StringAdminSetting setting) + { + if (GetPolicyStateForSetting(setting)) + { + return false; + } + + AdminSettingsInternal adminSettingsInternal; + adminSettingsInternal.SetAdminSetting(setting, std::nullopt); + return true; } - std::vector GetAllAdminSettings() + std::optional GetAdminSetting(StringAdminSetting setting) { - std::vector result; - using AdminSetting_t = std::underlying_type_t; + // Check for a policy that overrides this setting. + auto policyState = GetPolicyStateForSetting(setting); + if (policyState) + { + return policyState.value(); + } - // Skip Unknown. - for (AdminSetting_t i = 1 + static_cast(AdminSetting::Unknown); i < static_cast(AdminSetting::Max); ++i) + AdminSettingsInternal adminSettingsInternal; + return adminSettingsInternal.GetAdminSettingValue(setting); + } + + template + std::vector GetAllSequentialEnumValues(E initialToSkip) + { + std::vector result; + using underlying_t = std::underlying_type_t; + + for (E i = 1 + static_cast(initialToSkip); i < static_cast(E::Max); ++i) { - result.emplace_back(static_cast(i));; + result.emplace_back(static_cast(i)); } return result; } + + std::vector GetAllBoolAdminSettings() + { + return GetAllSequentialEnumValues(BoolAdminSetting::Unknown); + } + + std::vector GetAllStringAdminSettings() + { + return GetAllSequentialEnumValues(StringAdminSetting::Unknown); + } + } diff --git a/src/AppInstallerCommonCore/Public/winget/AdminSettings.h b/src/AppInstallerCommonCore/Public/winget/AdminSettings.h index 4c6e9a1f9f..d322da1e3c 100644 --- a/src/AppInstallerCommonCore/Public/winget/AdminSettings.h +++ b/src/AppInstallerCommonCore/Public/winget/AdminSettings.h @@ -11,7 +11,7 @@ namespace AppInstaller::Settings { // Enum of admin settings. - enum class AdminSetting + enum class BoolAdminSetting : size_t { Unknown = 0, LocalManifestFiles, @@ -22,20 +22,34 @@ namespace AppInstaller::Settings Max, }; - AdminSetting StringToAdminSetting(std::string_view in); + enum class StringAdminSetting : size_t + { + Unknown = 0, + DefaultProxy, + Max, + }; - Utility::LocIndView AdminSettingToString(AdminSetting setting); + BoolAdminSetting StringToBoolAdminSetting(std::string_view in); + StringAdminSetting StringToStringAdminSetting(std::string_view in); - bool EnableAdminSetting(AdminSetting setting); + Utility::LocIndView AdminSettingToString(BoolAdminSetting setting); + Utility::LocIndView AdminSettingToString(StringAdminSetting setting); - bool DisableAdminSetting(AdminSetting setting); + // Returns true if the value is set. + // Group policy overriding the setting can prevent the value from being set + bool EnableAdminSetting(BoolAdminSetting setting); + bool DisableAdminSetting(BoolAdminSetting setting); + bool SetAdminSetting(StringAdminSetting setting, std::string_view value); + bool ResetAdminSetting(StringAdminSetting setting, std::string_view value); - bool IsAdminSettingEnabled(AdminSetting setting); + bool IsAdminSettingEnabled(BoolAdminSetting setting); + std::optional GetAdminSetting(StringAdminSetting setting); - std::vector GetAllAdminSettings(); + std::vector GetAllBoolAdminSettings(); + std::vector GetAllStringAdminSettings(); #ifndef AICLI_DISABLE_TEST_HOOKS - // Only used in tests to validate that all admin settings have a corresponding policy - TogglePolicy::Policy GetAdminSettingPolicy(AdminSetting setting); + // Only exposed for tests to validate that all admin settings have a corresponding policy + TogglePolicy::Policy GetAdminSettingPolicy(BoolAdminSetting setting); #endif } diff --git a/src/AppInstallerRepositoryCore/SourceList.cpp b/src/AppInstallerRepositoryCore/SourceList.cpp index c934e75847..197a19f4f1 100644 --- a/src/AppInstallerRepositoryCore/SourceList.cpp +++ b/src/AppInstallerRepositoryCore/SourceList.cpp @@ -316,7 +316,7 @@ namespace AppInstaller::Repository details.TrustLevel = SourceTrustLevel::Trusted; details.SupportInstalledSearchCorrelation = false; - if (!Settings::IsAdminSettingEnabled(Settings::AdminSetting::BypassCertificatePinningForMicrosoftStore)) + if (!Settings::IsAdminSettingEnabled(Settings::BoolAdminSetting::BypassCertificatePinningForMicrosoftStore)) { using namespace AppInstaller::Certificates; diff --git a/src/AppInstallerSharedLib/Public/AppInstallerLanguageUtilities.h b/src/AppInstallerSharedLib/Public/AppInstallerLanguageUtilities.h index 2a8f2c92fb..3ada65ba7c 100644 --- a/src/AppInstallerSharedLib/Public/AppInstallerLanguageUtilities.h +++ b/src/AppInstallerSharedLib/Public/AppInstallerLanguageUtilities.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace AppInstaller { @@ -144,6 +145,34 @@ namespace AppInstaller std::map m_data; }; + + template + std::vector GetAllSequentialEnumValues(E initialToSkip) + { + std::vector result; + using underlying_t = std::underlying_type_t; + + for (E i = 1 + static_cast(initialToSkip); i < static_cast(E::Max); ++i) + { + result.emplace_back(static_cast(i)); + } + + return result; + } + + template + std::vector GetAllExponentialEnumValues(E initialToSkip) + { + std::vector result; + using underlying_t = std::underlying_type_t; + + for (E i = 1 + static_cast(initialToSkip); i < static_cast(E::Max); i <<= 1) + { + result.emplace_back(static_cast(i)); + } + + return result; + } } // Enable enums to be output generically (as their integral value). From 1a588b0161659a003a86dc9c4bfd1ab8fbb6ffd8 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Fri, 23 Feb 2024 17:38:35 -0800 Subject: [PATCH 11/32] Use admin setting for proxy --- src/AppInstallerCLICore/Argument.h | 10 +++++----- src/AppInstallerCLICore/Workflows/DownloadFlow.cpp | 2 +- src/AppInstallerCommonCore/AdminSettings.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/AppInstallerCLICore/Argument.h b/src/AppInstallerCLICore/Argument.h index d82374c30a..741c2de068 100644 --- a/src/AppInstallerCLICore/Argument.h +++ b/src/AppInstallerCLICore/Argument.h @@ -212,7 +212,7 @@ namespace AppInstaller::CLI Argument::Visibility GetVisibility() const; Settings::ExperimentalFeature::Feature Feature() const { return m_feature; } Settings::TogglePolicy::Policy GroupPolicy() const { return m_groupPolicy; } - Settings::AdminSetting AdminSetting() const { return m_adminSetting; } + Settings::BoolAdminSetting AdminSetting() const { return m_adminSetting; } Argument& SetRequired(bool required) { m_required = required; return *this; } Argument& SetCountLimit(size_t countLimit) { m_countLimit = countLimit; return *this; } @@ -238,13 +238,13 @@ namespace AppInstaller::CLI Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, bool required, Settings::ExperimentalFeature::Feature feature) : m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_required(required), m_feature(feature) {} - Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) : + Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::TogglePolicy::Policy groupPolicy, Settings::BoolAdminSetting adminSetting) : m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {} - Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) : + Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, Settings::TogglePolicy::Policy groupPolicy, Settings::BoolAdminSetting adminSetting) : m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {} - Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::ExperimentalFeature::Feature feature, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) : + Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::ExperimentalFeature::Feature feature, Settings::TogglePolicy::Policy groupPolicy, Settings::BoolAdminSetting adminSetting) : m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_feature(feature), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {} ArgumentCommon m_argCommon; @@ -255,6 +255,6 @@ namespace AppInstaller::CLI size_t m_countLimit = 1; Settings::ExperimentalFeature::Feature m_feature = Settings::ExperimentalFeature::Feature::None; Settings::TogglePolicy::Policy m_groupPolicy = Settings::TogglePolicy::Policy::None; - Settings::AdminSetting m_adminSetting = Settings::BoolAdminSetting::Unknown; + Settings::BoolAdminSetting m_adminSetting = Settings::BoolAdminSetting::Unknown; }; } diff --git a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp index 0ebe6e2245..7aa0a285fa 100644 --- a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp @@ -191,7 +191,7 @@ namespace AppInstaller::CLI::Workflow Utility::ProxyInfo proxyInfo; // Get the default proxy - proxyInfo.ProxyUri = GroupPolicies().GetValueRef(); + proxyInfo.ProxyUri = GetAdminSetting(StringAdminSetting::DefaultProxy); AICLI_LOG(CLI, Info, << "Default proxy: " << (proxyInfo.ProxyUri ? proxyInfo.ProxyUri.value() : "Not configured")); // Check command line arguments. These override any default if present. diff --git a/src/AppInstallerCommonCore/AdminSettings.cpp b/src/AppInstallerCommonCore/AdminSettings.cpp index 4053e3c258..fa12dc8a61 100644 --- a/src/AppInstallerCommonCore/AdminSettings.cpp +++ b/src/AppInstallerCommonCore/AdminSettings.cpp @@ -425,7 +425,7 @@ namespace AppInstaller::Settings std::vector result; using underlying_t = std::underlying_type_t; - for (E i = 1 + static_cast(initialToSkip); i < static_cast(E::Max); ++i) + for (underlying_t i = 1 + static_cast(initialToSkip); i < static_cast(E::Max); ++i) { result.emplace_back(static_cast(i)); } From 682e07e6e20d53a5ae128faef1eee6f67ea76ee0 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Sat, 24 Feb 2024 01:37:27 -0800 Subject: [PATCH 12/32] Add to info, export --- .../settings/settings.export.schema.0.1.json | 20 +++++++++++++++- .../Commands/RootCommand.cpp | 10 +++++++- .../Commands/SettingsCommand.cpp | 5 ++-- .../Workflows/SettingsFlow.cpp | 23 +++++++++++++++---- src/AppInstallerCommonCore/AdminSettings.cpp | 14 ----------- .../Public/AppInstallerLanguageUtilities.h | 4 ++-- src/WinGetSchemas/WinGetSchemas.vcxitems | 1 + .../WinGetSchemas.vcxitems.filters | 3 +++ 8 files changed, 56 insertions(+), 24 deletions(-) diff --git a/schemas/JSON/settings/settings.export.schema.0.1.json b/schemas/JSON/settings/settings.export.schema.0.1.json index 17d0e8d5e4..f8809255f5 100644 --- a/schemas/JSON/settings/settings.export.schema.0.1.json +++ b/schemas/JSON/settings/settings.export.schema.0.1.json @@ -16,8 +16,26 @@ "description": "Enable installing local manifests.", "type": "boolean", "default": false + }, + "InstallerHashOverride": { + "description": "Enable overriding installer hash validation.", + "type": "boolean", + "default": false + }, + "LocalArchiveMalwareScanOverride": { + "description": "Enable overriding malware scan for local archives.", + "type": "boolean", + "default": false + }, + "ProxyCommandLineOptions": { + "description": "Enable using command line options for proxy.", + "type": "boolean", + "default": false + }, + "DefaultProxy": { + "description": "Default proxy.", + "type": "string" } - } }, "UserSettingsFile": { "description": "Path for the winget's user settings file.", diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp index 3cbe1950fc..b43f10768b 100644 --- a/src/AppInstallerCLICore/Commands/RootCommand.cpp +++ b/src/AppInstallerCLICore/Commands/RootCommand.cpp @@ -123,13 +123,21 @@ namespace AppInstaller::CLI Execution::TableOutput<2> adminSettingsTable{ context.Reporter, { Resource::String::AdminSettingHeader, Resource::String::StateHeader } }; // Output the admin settings. - for (const auto& setting : Settings::GetAllAdminSettings()) + for (const auto& setting : Settings::GetAllBoolAdminSettings()) { adminSettingsTable.OutputLine({ std::string{ AdminSettingToString(setting)}, Resource::LocString{ IsAdminSettingEnabled(setting) ? Resource::String::StateEnabled : Resource::String::StateDisabled } }); } + for (const auto& setting : Settings::GetAllStringAdminSettings()) + { + auto settingValue = GetAdminSetting(setting); + adminSettingsTable.OutputLine({ + std::string{ AdminSettingToString(setting)}, + settingValue ? Utility::LocIndString{ settingValue.value() } : Resource::LocString{ Resource::String::StateDisabled } + }); + } adminSettingsTable.Complete(); } diff --git a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp index 4050c37ef7..2713f0a18b 100644 --- a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp +++ b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp @@ -49,6 +49,7 @@ namespace AppInstaller::CLI void SettingsCommand::ValidateArgumentsInternal(Execution::Args& execArgs) const { // Get admin setting string for all available options except Unknown + std::vector adminSettingList; for (auto setting : GetAllSequentialEnumValues(BoolAdminSetting::Unknown)) { adminSettingList.emplace_back(AdminSettingToString(setting)); @@ -56,12 +57,12 @@ namespace AppInstaller::CLI Utility::LocIndString validOptions = Join(", "_liv, adminSettingList); - if (execArgs.Contains(Execution::Args::Type::AdminSettingEnable) && BoolAdminSetting::Unknown == StringToAdminSetting(execArgs.GetArg(Execution::Args::Type::AdminSettingEnable))) + if (execArgs.Contains(Execution::Args::Type::AdminSettingEnable) && BoolAdminSetting::Unknown == StringToBoolAdminSetting(execArgs.GetArg(Execution::Args::Type::AdminSettingEnable))) { throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::AdminSettingEnable).Name, validOptions)); } - if (execArgs.Contains(Execution::Args::Type::AdminSettingDisable) && BoolAdminSetting::Unknown == StringToAdminSetting(execArgs.GetArg(Execution::Args::Type::AdminSettingDisable))) + if (execArgs.Contains(Execution::Args::Type::AdminSettingDisable) && BoolAdminSetting::Unknown == StringToBoolAdminSetting(execArgs.GetArg(Execution::Args::Type::AdminSettingDisable))) { throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::AdminSettingDisable).Name, validOptions)); } diff --git a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp index da2d5c8198..5e5d11f876 100644 --- a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp @@ -23,12 +23,22 @@ namespace AppInstaller::CLI::Workflow root["userSettingsFile"] = UserSettings::SettingsFilePath().u8string(); } - void AddAdminSetting(AdminSetting setting) + void AddAdminSetting(BoolAdminSetting setting) { auto str = std::string{ Settings::AdminSettingToString(setting) }; root["adminSettings"][str] = Settings::IsAdminSettingEnabled(setting); } + void AddAdminSetting(StringAdminSetting setting) + { + auto name = std::string{ Settings::AdminSettingToString(setting) }; + auto value = Settings::GetAdminSetting(setting); + if (value) + { + root["adminSettings"][name] = value.value(); + } + } + std::string ToJsonString() const { Json::StreamWriterBuilder writerBuilder; @@ -44,7 +54,7 @@ namespace AppInstaller::CLI::Workflow void EnableAdminSetting(Execution::Context& context) { auto adminSettingString = context.Args.GetArg(Execution::Args::Type::AdminSettingEnable); - AdminSetting adminSetting = Settings::StringToAdminSetting(adminSettingString); + BoolAdminSetting adminSetting = Settings::StringToBoolAdminSetting(adminSettingString); if (Settings::EnableAdminSetting(adminSetting)) { context.Reporter.Info() << Resource::String::AdminSettingEnabled(AdminSettingToString(adminSetting)) << std::endl; @@ -58,7 +68,7 @@ namespace AppInstaller::CLI::Workflow void DisableAdminSetting(Execution::Context& context) { auto adminSettingString = context.Args.GetArg(Execution::Args::Type::AdminSettingDisable); - AdminSetting adminSetting = Settings::StringToAdminSetting(adminSettingString); + BoolAdminSetting adminSetting = Settings::StringToBoolAdminSetting(adminSettingString); if (Settings::DisableAdminSetting(adminSetting)) { context.Reporter.Info() << Resource::String::AdminSettingDisabled(AdminSettingToString(adminSetting)) << std::endl; @@ -129,7 +139,12 @@ namespace AppInstaller::CLI::Workflow { ExportSettingsJson exportSettingsJson; - for (const auto& setting : GetAllAdminSettings()) + for (const auto& setting : GetAllBoolAdminSettings()) + { + exportSettingsJson.AddAdminSetting(setting); + } + + for (const auto& setting : GetAllStringAdminSettings()) { exportSettingsJson.AddAdminSetting(setting); } diff --git a/src/AppInstallerCommonCore/AdminSettings.cpp b/src/AppInstallerCommonCore/AdminSettings.cpp index fa12dc8a61..89a23d64ea 100644 --- a/src/AppInstallerCommonCore/AdminSettings.cpp +++ b/src/AppInstallerCommonCore/AdminSettings.cpp @@ -419,20 +419,6 @@ namespace AppInstaller::Settings return adminSettingsInternal.GetAdminSettingValue(setting); } - template - std::vector GetAllSequentialEnumValues(E initialToSkip) - { - std::vector result; - using underlying_t = std::underlying_type_t; - - for (underlying_t i = 1 + static_cast(initialToSkip); i < static_cast(E::Max); ++i) - { - result.emplace_back(static_cast(i)); - } - - return result; - } - std::vector GetAllBoolAdminSettings() { return GetAllSequentialEnumValues(BoolAdminSetting::Unknown); diff --git a/src/AppInstallerSharedLib/Public/AppInstallerLanguageUtilities.h b/src/AppInstallerSharedLib/Public/AppInstallerLanguageUtilities.h index 3ada65ba7c..11cfefbab0 100644 --- a/src/AppInstallerSharedLib/Public/AppInstallerLanguageUtilities.h +++ b/src/AppInstallerSharedLib/Public/AppInstallerLanguageUtilities.h @@ -152,7 +152,7 @@ namespace AppInstaller std::vector result; using underlying_t = std::underlying_type_t; - for (E i = 1 + static_cast(initialToSkip); i < static_cast(E::Max); ++i) + for (underlying_t i = 1 + static_cast(initialToSkip); i < static_cast(E::Max); ++i) { result.emplace_back(static_cast(i)); } @@ -166,7 +166,7 @@ namespace AppInstaller std::vector result; using underlying_t = std::underlying_type_t; - for (E i = 1 + static_cast(initialToSkip); i < static_cast(E::Max); i <<= 1) + for (underlying_t i = 1 + static_cast(initialToSkip); i < static_cast(E::Max); i <<= 1) { result.emplace_back(static_cast(i)); } diff --git a/src/WinGetSchemas/WinGetSchemas.vcxitems b/src/WinGetSchemas/WinGetSchemas.vcxitems index c7e31821e5..36517bf71c 100644 --- a/src/WinGetSchemas/WinGetSchemas.vcxitems +++ b/src/WinGetSchemas/WinGetSchemas.vcxitems @@ -16,6 +16,7 @@ + diff --git a/src/WinGetSchemas/WinGetSchemas.vcxitems.filters b/src/WinGetSchemas/WinGetSchemas.vcxitems.filters index d81bd02d1e..de1a2218cc 100644 --- a/src/WinGetSchemas/WinGetSchemas.vcxitems.filters +++ b/src/WinGetSchemas/WinGetSchemas.vcxitems.filters @@ -18,6 +18,9 @@ packages + + settings + From 2f843c0d15da5ef559d2246df7c259dfbf083858 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Sun, 25 Feb 2024 21:14:11 -0800 Subject: [PATCH 13/32] Add proxy to settings schema experimental features --- schemas/JSON/settings/settings.schema.0.2.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/schemas/JSON/settings/settings.schema.0.2.json b/schemas/JSON/settings/settings.schema.0.2.json index f2df98f147..65153e486a 100644 --- a/schemas/JSON/settings/settings.schema.0.2.json +++ b/schemas/JSON/settings/settings.schema.0.2.json @@ -270,6 +270,11 @@ "description": "Enable support for configuration", "type": "boolean", "default": false + }, + "proxy": { + "description": "Enable support for proxies", + "type": "boolean", + "default": false } } } From e984f7f5efbe1ad9fb6edb1633dc5c6b26a86375 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Mon, 26 Feb 2024 11:11:45 -0800 Subject: [PATCH 14/32] Typo --- .../Shared/Strings/en-us/winget.resw | 2 +- src/AppInstallerCommonCore/Downloader.cpp | 27 ++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index a3bd2ee224..c841b8289a 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -2759,7 +2759,7 @@ Please specify one of them using the --source option to proceed. Enable Windows Package Manager proxy command line options - Describres a Group Policy that can enable the use of the --proxy option to set a proxy + Describes a Group Policy that can enable the use of the --proxy option to set a proxy Set a proxy to use for this execution diff --git a/src/AppInstallerCommonCore/Downloader.cpp b/src/AppInstallerCommonCore/Downloader.cpp index 0bac5d70a6..91a0d80780 100644 --- a/src/AppInstallerCommonCore/Downloader.cpp +++ b/src/AppInstallerCommonCore/Downloader.cpp @@ -106,12 +106,27 @@ namespace AppInstaller::Utility AICLI_LOG(Core, Info, << "WinINet downloading from url: " << url); auto agentWide = Utility::ConvertToUTF16(Runtime::GetDefaultUserAgent().get()); - wil::unique_hinternet session(InternetOpen( - agentWide.c_str(), - proxyInfo.ProxyUri ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_PRECONFIG, - proxyInfo.ProxyUri ? Utility::ConvertToUTF16(proxyInfo.ProxyUri.value()).c_str() : NULL, - NULL, - 0)); + wil::unique_hinternet session; + if (proxyInfo.ProxyUri) + { + AICLI_LOG(Core, Info, << "Using proxy " << proxyInfo.ProxyUri.value()); + session.reset(InternetOpen( + agentWide.c_str(), + INTERNET_OPEN_TYPE_PROXY, + Utility::ConvertToUTF16(proxyInfo.ProxyUri.value()).c_str(), + NULL, + 0)); + } + else + { + session.reset(InternetOpen( + agentWide.c_str(), + INTERNET_OPEN_TYPE_PRECONFIG, + NULL, + NULL, + 0)); + } + THROW_LAST_ERROR_IF_NULL_MSG(session, "InternetOpen() failed."); auto urlWide = Utility::ConvertToUTF16(url); From 284a1cea405ca79e6d65e9c945ed0d3034160970 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Mon, 26 Feb 2024 11:22:54 -0800 Subject: [PATCH 15/32] Fix id --- doc/admx/en-US/DesktopAppInstaller.adml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/admx/en-US/DesktopAppInstaller.adml b/doc/admx/en-US/DesktopAppInstaller.adml index 79f3e08f44..55e028222e 100644 --- a/doc/admx/en-US/DesktopAppInstaller.adml +++ b/doc/admx/en-US/DesktopAppInstaller.adml @@ -117,7 +117,7 @@ If you disable this setting, users will not be able to use the Windows Package M If you disable or do not configure this setting, users will not be able to to configure the Windows Package Manager's use of proxy through the command line. Set Windows Package Manager Default Proxy - This policy controls the default proxy used by the Windows Package Manager. + This policy controls the default proxy used by the Windows Package Manager. If you disable or do not configure this setting, no proxy will be used by default. From 17264b7af85c3af36545c4a545827fe349978efd Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Mon, 26 Feb 2024 12:18:30 -0800 Subject: [PATCH 16/32] missing ; --- src/AppInstallerCLICore/ExecutionContextData.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/AppInstallerCLICore/ExecutionContextData.h b/src/AppInstallerCLICore/ExecutionContextData.h index 9a1fcda996..4862f808e3 100644 --- a/src/AppInstallerCLICore/ExecutionContextData.h +++ b/src/AppInstallerCLICore/ExecutionContextData.h @@ -278,6 +278,7 @@ namespace AppInstaller::CLI::Execution using value_t = std::string; }; + template<> struct DataMapping { @@ -288,6 +289,6 @@ namespace AppInstaller::CLI::Execution struct DataMapping { using value_t = Utility::ProxyInfo; - } + }; } } From 8a11d7cbabf813c5b5bd3d6722f9f4fe19488118 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Tue, 27 Feb 2024 10:56:30 -0800 Subject: [PATCH 17/32] Use existing httpclienthelper --- src/AppInstallerCLITests/CustomHeader.cpp | 14 ++++++------- src/AppInstallerCLITests/RestClient.cpp | 20 +++++++++---------- .../RestInterface_1_1.cpp | 20 +++++++++---------- .../RestInterface_1_4.cpp | 4 ++-- .../RestInterface_1_5.cpp | 2 +- .../RestInterface_1_6.cpp | 2 +- .../RestInterface_1_7.cpp | 14 ++++++------- .../Rest/RestClient.cpp | 19 +++++++++--------- .../Rest/RestClient.h | 12 ++++++++--- .../Rest/RestSourceFactory.cpp | 7 ++++++- .../Rest/Schema/1_0/Interface.h | 2 +- .../Rest/Schema/1_1/Interface.h | 2 +- .../Rest/Schema/1_1/RestInterface_1_1.cpp | 4 ++-- .../Rest/Schema/1_4/Interface.h | 2 +- .../Rest/Schema/1_4/RestInterface_1_4.cpp | 4 ++-- .../Rest/Schema/1_5/Interface.h | 2 +- .../Rest/Schema/1_5/RestInterface_1_5.cpp | 4 ++-- .../Rest/Schema/1_6/Interface.h | 2 +- .../Rest/Schema/1_6/RestInterface_1_6.cpp | 4 ++-- .../Rest/Schema/1_7/Interface.h | 2 +- .../Rest/Schema/1_7/RestInterface_1_7.cpp | 4 ++-- 21 files changed, 79 insertions(+), 67 deletions(-) diff --git a/src/AppInstallerCLITests/CustomHeader.cpp b/src/AppInstallerCLITests/CustomHeader.cpp index a8f3a2bf7a..1501d4cd95 100644 --- a/src/AppInstallerCLITests/CustomHeader.cpp +++ b/src/AppInstallerCLITests/CustomHeader.cpp @@ -54,7 +54,7 @@ TEST_CASE("RestClient_CustomHeader", "[RestSource][CustomHeader]") std::optional customHeader = "Testing custom header"; auto header = std::make_pair<>(CustomHeaderName, JSON::GetUtilityString(customHeader.value())); HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, sample, header) }; - RestClient client = RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), customHeader, {}, {}, std::move(helper)); + RestClient client = RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), customHeader, {}, std::move(helper), {}); REQUIRE(client.GetSourceIdentifier() == "Source123"); } @@ -66,7 +66,7 @@ TEST_CASE("RestSourceSearch_CustomHeader", "[RestSource][CustomHeader]") std::unordered_map headers; headers.emplace(CustomHeaderName, customHeader); - V1_1::Interface v1_1{ "https://restsource.com/api", {}, headers, std::move(helper) }; + V1_1::Interface v1_1{ "https://restsource.com/api", std::move(helper) , {}, headers}; Schema::IRestClient::SearchResult searchResponse = v1_1.Search({}); REQUIRE(searchResponse.Matches.size() == 1); Schema::IRestClient::Package package = searchResponse.Matches.at(0); @@ -80,7 +80,7 @@ TEST_CASE("RestSourceSearch_WhitespaceCustomHeader", "[RestSource][CustomHeader] std::unordered_map headers; headers.emplace(CustomHeaderName, customHeader); - V1_1::Interface v1_1{ "https://restsource.com/api", {}, headers, std::move(helper) }; + V1_1::Interface v1_1{ "https://restsource.com/api", std::move(helper), {}, headers }; Schema::IRestClient::SearchResult searchResponse = v1_1.Search({}); REQUIRE(searchResponse.Matches.size() == 1); } @@ -93,7 +93,7 @@ TEST_CASE("RestSourceSearch_NoCustomHeader", "[RestSource][CustomHeader]") std::unordered_map headers; headers.emplace(CustomHeaderName, customHeader); - V1_1::Interface v1_1{ "https://restsource.com/api", {}, {}, std::move(helper) }; + V1_1::Interface v1_1{ "https://restsource.com/api", std::move(helper), {}, {} }; REQUIRE_THROWS_HR(v1_1.Search({}), APPINSTALLER_CLI_ERROR_RESTSOURCE_INTERNAL_ERROR); } @@ -103,7 +103,7 @@ TEST_CASE("RestSourceSearch_CustomHeaderExceedingSize", "[RestSource][CustomHead auto header = std::make_pair<>(CustomHeaderName, JSON::GetUtilityString(customHeader)); HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, sampleSearchResponse, header) }; - REQUIRE_THROWS_HR(RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), customHeader, {}, {}, std::move(helper)), + REQUIRE_THROWS_HR(RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), customHeader, {}, std::move(helper), {}), APPINSTALLER_CLI_ERROR_CUSTOMHEADER_EXCEEDS_MAXLENGTH); } @@ -121,7 +121,7 @@ TEST_CASE("RestClient_CustomUserAgentHeader", "[RestSource][CustomHeader]") std::string testCaller = "TestCaller"; auto header = std::make_pair<>(web::http::header_names::user_agent, JSON::GetUtilityString(Runtime::GetUserAgent(testCaller))); HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, sample, header) }; - RestClient client = RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), {}, testCaller, {}, std::move(helper)); + RestClient client = RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), {}, testCaller, std::move(helper), {}); REQUIRE(client.GetSourceIdentifier() == "Source123"); } @@ -138,6 +138,6 @@ TEST_CASE("RestClient_DefaultUserAgentHeader", "[RestSource][CustomHeader]") auto header = std::make_pair<>(web::http::header_names::user_agent, JSON::GetUtilityString(Runtime::GetDefaultUserAgent())); HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, sample, header) }; - RestClient client = RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), {}, {}, {}, std::move(helper)); + RestClient client = RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), {}, {}, std::move(helper), {}); REQUIRE(client.GetSourceIdentifier() == "Source123"); } \ No newline at end of file diff --git a/src/AppInstallerCLITests/RestClient.cpp b/src/AppInstallerCLITests/RestClient.cpp index 00af2e2a27..d7ad277a73 100644 --- a/src/AppInstallerCLITests/RestClient.cpp +++ b/src/AppInstallerCLITests/RestClient.cpp @@ -47,11 +47,11 @@ TEST_CASE("GetSupportedInterface", "[RestSource]") IRestClient::Information info{ "TestId", { "1.0.0" } }; Version version{ "1.0.0" }; - REQUIRE(RestClient::GetSupportedInterface(TestRestUri, {}, info, {}, version)->GetVersion() == version); + REQUIRE(RestClient::GetSupportedInterface(TestRestUri, {}, info, {}, version, {})->GetVersion() == version); // Update this test to next version so that we don't forget to add to supported versions before rest e2e tests are available. Version invalid{ "1.8.0" }; - REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, info, {}, invalid), APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION); + REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, info, {}, invalid, {}), APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION); Authentication::AuthenticationArguments authArgs; authArgs.Mode = Authentication::AuthenticationMode::Silent; @@ -60,12 +60,12 @@ TEST_CASE("GetSupportedInterface", "[RestSource]") // GetSupportedInterface throws on unknown authentication type. IRestClient::Information infoWithUnknownAuthenticationType{ "TestId", { "1.7.0" } }; infoWithUnknownAuthenticationType.Authentication.Type = Authentication::AuthenticationType::Unknown; - REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, infoWithUnknownAuthenticationType, authArgs, version_1_7), APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED); + REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, infoWithUnknownAuthenticationType, authArgs, version_1_7, {}), APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED); // GetSupportedInterface throws on invalid authentication info. IRestClient::Information infoWithInvalidAuthenticationInfo{ "TestId", { "1.7.0" } }; infoWithInvalidAuthenticationInfo.Authentication.Type = Authentication::AuthenticationType::MicrosoftEntraId; - REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, infoWithInvalidAuthenticationInfo, authArgs, version_1_7), APPINSTALLER_CLI_ERROR_INVALID_AUTHENTICATION_INFO); + REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, infoWithInvalidAuthenticationInfo, authArgs, version_1_7, {}), APPINSTALLER_CLI_ERROR_INVALID_AUTHENTICATION_INFO); } TEST_CASE("GetInformation_Success", "[RestSource]") @@ -277,7 +277,7 @@ TEST_CASE("RestClientCreate_UnsupportedVersion", "[RestSource]") }})delimiter"); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, sample) }; - REQUIRE_THROWS_HR(RestClient::Create("https://restsource.com/api", {}, {}, {}, std::move(helper)), APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE); + REQUIRE_THROWS_HR(RestClient::Create("https://restsource.com/api", {}, {}, std::move(helper)), APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE); } TEST_CASE("RestClientCreate_UnsupportedAuthenticationMethod", "[RestSource]") @@ -297,7 +297,7 @@ TEST_CASE("RestClientCreate_UnsupportedAuthenticationMethod", "[RestSource]") HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, sample) }; Authentication::AuthenticationArguments authArgs; authArgs.Mode = Authentication::AuthenticationMode::Silent; - REQUIRE_THROWS_HR(RestClient::Create("https://restsource.com/api", {}, {}, std::move(authArgs), std::move(helper)), APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED); + REQUIRE_THROWS_HR(RestClient::Create("https://restsource.com/api", {}, {}, std::move(helper), std::move(authArgs)), APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED); } TEST_CASE("RestClientCreate_InvalidAuthenticationArguments", "[RestSource]") @@ -320,7 +320,7 @@ TEST_CASE("RestClientCreate_InvalidAuthenticationArguments", "[RestSource]") HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, sample) }; Authentication::AuthenticationArguments authArgs; authArgs.Mode = Authentication::AuthenticationMode::Unknown; - REQUIRE_THROWS_HR(RestClient::Create("https://restsource.com/api", {}, {}, std::move(authArgs), std::move(helper)), E_UNEXPECTED); + REQUIRE_THROWS_HR(RestClient::Create("https://restsource.com/api", {}, {}, std::move(helper), std::move(authArgs)), E_UNEXPECTED); } TEST_CASE("RestClientCreate_1.0_Success", "[RestSource]") @@ -335,7 +335,7 @@ TEST_CASE("RestClientCreate_1.0_Success", "[RestSource]") }})delimiter"); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, sample) }; - RestClient client = RestClient::Create(TestRestUri, {}, {}, {}, std::move(helper)); + RestClient client = RestClient::Create(TestRestUri, {}, {}, std::move(helper), {}); REQUIRE(client.GetSourceIdentifier() == "Source123"); } @@ -372,7 +372,7 @@ TEST_CASE("RestClientCreate_1.1_Success", "[RestSource]") }})delimiter"); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, sample) }; - RestClient client = RestClient::Create(TestRestUri, {}, {}, {}, std::move(helper)); + RestClient client = RestClient::Create(TestRestUri, {}, {}, std::move(helper)); REQUIRE(client.GetSourceIdentifier() == "Source123"); auto information = client.GetSourceInformation(); REQUIRE(information.SourceAgreementsIdentifier == "agreementV1"); @@ -438,7 +438,7 @@ TEST_CASE("RestClientCreate_1.7_Success", "[RestSource]") Authentication::AuthenticationArguments authArgs; authArgs.Mode = Authentication::AuthenticationMode::Silent; HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, sample) }; - RestClient client = RestClient::Create(TestRestUri, {}, {}, std::move(authArgs), std::move(helper)); + RestClient client = RestClient::Create(TestRestUri, {}, {}, std::move(helper), std::move(authArgs)); REQUIRE(client.GetSourceIdentifier() == "Source123"); auto information = client.GetSourceInformation(); REQUIRE(information.SourceAgreementsIdentifier == "agreementV1"); diff --git a/src/AppInstallerCLITests/RestInterface_1_1.cpp b/src/AppInstallerCLITests/RestInterface_1_1.cpp index a167c03427..3334388146 100644 --- a/src/AppInstallerCLITests/RestInterface_1_1.cpp +++ b/src/AppInstallerCLITests/RestInterface_1_1.cpp @@ -310,7 +310,7 @@ TEST_CASE("Search_BadResponse_UnsupportedPackageMatchFields", "[RestSource][Inte })delimiter"); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) }; + Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; AppInstaller::Repository::SearchRequest request; PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "Foo" }; request.Filters.emplace_back(std::move(filter)); @@ -326,7 +326,7 @@ TEST_CASE("Search_BadResponse_RequiredPackageMatchFields", "[RestSource][Interfa })delimiter"); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) }; + Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; AppInstaller::Repository::SearchRequest request; PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "Foo" }; request.Filters.emplace_back(std::move(filter)); @@ -342,7 +342,7 @@ TEST_CASE("GetManifests_BadResponse_UnsupportedQueryParameters", "[RestSource][I })delimiter"); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) }; + Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; REQUIRE_THROWS_HR(v1_1.GetManifests("Foo"), APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST); } @@ -355,7 +355,7 @@ TEST_CASE("GetManifests_BadResponse_RequiredQueryParameters", "[RestSource][Inte })delimiter"); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) }; + Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; REQUIRE_THROWS_HR(v1_1.GetManifests("Foo"), APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST); } @@ -375,7 +375,7 @@ TEST_CASE("Search_BadRequest_UnsupportedPackageMatchFields", "[RestSource][Inter })delimiter"); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) }; + Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; AppInstaller::Repository::SearchRequest request; PackageMatchFilter filter{ PackageMatchField::Moniker, MatchType::Exact, "Foo" }; request.Filters.emplace_back(std::move(filter)); @@ -398,7 +398,7 @@ TEST_CASE("Search_GoodRequest_OnlyMarketRequired", "[RestSource][Interface_1_1]" })delimiter"); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) }; + Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; AppInstaller::Repository::SearchRequest request; PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "Foo" }; request.Filters.emplace_back(std::move(filter)); @@ -443,7 +443,7 @@ TEST_CASE("GetManifests_BadRequest_UnsupportedQueryParameters", "[RestSource][In })delimiter"); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) }; + Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; REQUIRE_THROWS_HR(v1_1.GetManifestByVersion("Foo", "1.0", "beta"), APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST); } @@ -479,7 +479,7 @@ TEST_CASE("GetManifests_GoodRequest_OnlyMarketRequired", "[RestSource][Interface IRestClient::Information info = GetTestSourceInformation(); info.UnsupportedQueryParameters.clear(); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_1{ TestRestUriString, info, {}, std::move(helper) }; + Interface v1_1{ TestRestUriString, std::move(helper), info, {} }; auto manifestResult = v1_1.GetManifestByVersion("Foo", "5.0.0", ""); REQUIRE(manifestResult.has_value()); const Manifest& manifest = manifestResult.value(); @@ -526,7 +526,7 @@ TEST_CASE("GetManifests_GoodResponse_MSStoreType", "[RestSource][Interface_1_1]" })delimiter"); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(msstoreInstallerResponse)) }; - Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) }; + Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} }; std::vector manifests = v1_1.GetManifests("Foo.Bar"); REQUIRE(manifests.size() == 1); @@ -542,7 +542,7 @@ TEST_CASE("GetManifests_GoodResponse_V1_1", "[RestSource][Interface_1_1]") GoodManifest_AllFields sampleManifest; utility::string_t sample = sampleManifest.GetSampleManifest_AllFields(); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_1{ TestRestUriString, {}, {}, std::move(helper) }; + Interface v1_1{ TestRestUriString, std::move(helper), {} }; std::vector manifests = v1_1.GetManifests("Foo.Bar"); REQUIRE(manifests.size() == 1); diff --git a/src/AppInstallerCLITests/RestInterface_1_4.cpp b/src/AppInstallerCLITests/RestInterface_1_4.cpp index a1c3bb7add..e136070c42 100644 --- a/src/AppInstallerCLITests/RestInterface_1_4.cpp +++ b/src/AppInstallerCLITests/RestInterface_1_4.cpp @@ -361,7 +361,7 @@ TEST_CASE("GetManifests_GoodResponse_V1_4", "[RestSource][Interface_1_4]") GoodManifest_AllFields sampleManifest; utility::string_t sample = sampleManifest.GetSampleManifest_AllFields(); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_4{ TestRestUriString, {}, {}, std::move(helper) }; + Interface v1_4{ TestRestUriString, std::move(helper), {} }; std::vector manifests = v1_4.GetManifests("Foo.Bar"); REQUIRE(manifests.size() == 1); @@ -404,7 +404,7 @@ TEST_CASE("Search_GoodResponse_V1_4", "[RestSource][Interface_1_4]") })delimiter"); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_4{ TestRestUriString, {}, {}, std::move(helper) }; + Interface v1_4{ TestRestUriString, std::move(helper), {} }; Schema::IRestClient::SearchResult searchResponse = v1_4.Search({}); REQUIRE(searchResponse.Matches.size() == 1); Schema::IRestClient::Package package = searchResponse.Matches.at(0); diff --git a/src/AppInstallerCLITests/RestInterface_1_5.cpp b/src/AppInstallerCLITests/RestInterface_1_5.cpp index 69416b2c2e..c1a04dc60d 100644 --- a/src/AppInstallerCLITests/RestInterface_1_5.cpp +++ b/src/AppInstallerCLITests/RestInterface_1_5.cpp @@ -387,7 +387,7 @@ TEST_CASE("GetManifests_GoodResponse_V1_5", "[RestSource][Interface_1_5]") GoodManifest_AllFields sampleManifest; utility::string_t sample = sampleManifest.GetSampleManifest_AllFields(); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_5{ TestRestUriString, {}, {}, std::move(helper) }; + Interface v1_5{ TestRestUriString, std::move(helper), {} }; std::vector manifests = v1_5.GetManifests("Foo.Bar"); REQUIRE(manifests.size() == 1); diff --git a/src/AppInstallerCLITests/RestInterface_1_6.cpp b/src/AppInstallerCLITests/RestInterface_1_6.cpp index 0cddd5970c..da1582b69c 100644 --- a/src/AppInstallerCLITests/RestInterface_1_6.cpp +++ b/src/AppInstallerCLITests/RestInterface_1_6.cpp @@ -389,7 +389,7 @@ TEST_CASE("GetManifests_GoodResponse_V1_6", "[RestSource][Interface_1_6]") GoodManifest_AllFields sampleManifest; utility::string_t sample = sampleManifest.GetSampleManifest_AllFields(); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_6{ TestRestUriString, {}, {}, std::move(helper) }; + Interface v1_6{ TestRestUriString, std::move(helper), {} }; std::vector manifests = v1_6.GetManifests("Foo.Bar"); REQUIRE(manifests.size() == 1); diff --git a/src/AppInstallerCLITests/RestInterface_1_7.cpp b/src/AppInstallerCLITests/RestInterface_1_7.cpp index e2ca66d9e9..bde849b644 100644 --- a/src/AppInstallerCLITests/RestInterface_1_7.cpp +++ b/src/AppInstallerCLITests/RestInterface_1_7.cpp @@ -457,7 +457,7 @@ TEST_CASE("GetManifests_GoodRequest_Authentication", "[RestSource][Interface_1_7 // GetManifest should succeed with expected value. HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleGetManifestResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) }; - Interface v1_7{ TestRestUriString, GetTestSourceInformation(), {}, GetTestAuthenticationArguments(), std::move(helper) }; + Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() }; auto manifestResult = v1_7.GetManifestByVersion("Foo.Bar", "5.0.0", ""); REQUIRE(manifestResult.has_value()); const auto& manifest = manifestResult.value(); @@ -482,7 +482,7 @@ TEST_CASE("GetManifests_BadRequest_AuthenticationFailed", "[RestSource][Interfac // GetManifest should fail with authentication failure HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleGetManifestResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) }; - Interface v1_7{ TestRestUriString, GetTestSourceInformation(), {}, GetTestAuthenticationArguments(), std::move(helper) }; + Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() }; REQUIRE_THROWS_HR(v1_7.GetManifestByVersion("Foo.Bar", "5.0.0", ""), APPINSTALLER_CLI_ERROR_AUTHENTICATION_FAILED); } @@ -504,7 +504,7 @@ TEST_CASE("GetManifests_BadRequest_InvalidAuthenticationToken", "[RestSource][In // GetManifest should fail with access denied HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleGetManifestResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) }; - Interface v1_7{ TestRestUriString, GetTestSourceInformation(), {}, GetTestAuthenticationArguments(), std::move(helper) }; + Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() }; REQUIRE_THROWS_HR(v1_7.GetManifestByVersion("Foo.Bar", "5.0.0", ""), HTTP_E_STATUS_DENIED); } @@ -526,7 +526,7 @@ TEST_CASE("Search_GoodRequest_Authentication", "[RestSource][Interface_1_7]") // Search should succeed with expected value. HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleSearchResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) }; - Interface v1_7{ TestRestUriString, GetTestSourceInformation(), {}, GetTestAuthenticationArguments(), std::move(helper) }; + Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() }; SearchRequest request; PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "package" }; request.Filters.emplace_back(std::move(filter)); @@ -553,7 +553,7 @@ TEST_CASE("Search_BadRequest_AuthenticationFailed", "[RestSource][Interface_1_7] // Search should fail with authentication failure HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleSearchResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) }; - Interface v1_7{ TestRestUriString, GetTestSourceInformation(), {}, GetTestAuthenticationArguments(), std::move(helper) }; + Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() }; SearchRequest request; PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "package" }; request.Filters.emplace_back(std::move(filter)); @@ -578,7 +578,7 @@ TEST_CASE("Search_BadRequest_InvalidAuthenticationToken", "[RestSource][Interfac // Search should fail with access denied HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleSearchResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) }; - Interface v1_7{ TestRestUriString, GetTestSourceInformation(), {}, GetTestAuthenticationArguments(), std::move(helper) }; + Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() }; SearchRequest request; PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "package" }; request.Filters.emplace_back(std::move(filter)); @@ -590,7 +590,7 @@ TEST_CASE("GetManifests_GoodResponse_V1_7", "[RestSource][Interface_1_7]") GoodManifest_AllFields sampleManifest; utility::string_t sample = sampleManifest.GetSampleManifest_AllFields(); HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) }; - Interface v1_7{ TestRestUriString, {}, {}, {}, std::move(helper) }; + Interface v1_7{ TestRestUriString, std::move(helper), {} }; std::vector manifests = v1_7.GetManifests("Foo.Bar"); REQUIRE(manifests.size() == 1); diff --git a/src/AppInstallerRepositoryCore/Rest/RestClient.cpp b/src/AppInstallerRepositoryCore/Rest/RestClient.cpp index d085757c92..900a4a895e 100644 --- a/src/AppInstallerRepositoryCore/Rest/RestClient.cpp +++ b/src/AppInstallerRepositoryCore/Rest/RestClient.cpp @@ -148,37 +148,38 @@ namespace AppInstaller::Repository::Rest const HttpClientHelper::HttpRequestHeaders& additionalHeaders, const IRestClient::Information& information, const Authentication::AuthenticationArguments& authArgs, - const Version& version) + const Version& version, + const HttpClientHelper& helper) { if (version == Version_1_0_0) { - return std::make_unique(api); + return std::make_unique(api, helper); } else if (version == Version_1_1_0) { - return std::make_unique(api, information, additionalHeaders); + return std::make_unique(api, helper, information, additionalHeaders); } else if (version == Version_1_4_0) { - return std::make_unique(api, information, additionalHeaders); + return std::make_unique(api, helper, information, additionalHeaders); } else if (version == Version_1_5_0) { - return std::make_unique(api, information, additionalHeaders); + return std::make_unique(api, helper, information, additionalHeaders); } else if (version == Version_1_6_0) { - return std::make_unique(api, information, additionalHeaders); + return std::make_unique(api, helper, information, additionalHeaders); } else if (version == Version_1_7_0) { - return std::make_unique(api, information, additionalHeaders, authArgs); + return std::make_unique(api, helper, information, additionalHeaders, authArgs); } THROW_HR(APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION); } - RestClient RestClient::Create(const std::string& restApi, std::optional customHeader, std::string_view caller, const Authentication::AuthenticationArguments& authArgs, const HttpClientHelper& helper) + RestClient RestClient::Create(const std::string& restApi, std::optional customHeader, std::string_view caller, const HttpClientHelper& helper, const Authentication::AuthenticationArguments& authArgs) { utility::string_t restEndpoint = RestHelper::GetRestAPIBaseUri(restApi); THROW_HR_IF(APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_URL, !RestHelper::IsValidUri(restEndpoint)); @@ -189,7 +190,7 @@ namespace AppInstaller::Repository::Rest std::optional latestCommonVersion = GetLatestCommonVersion(information.ServerSupportedVersions, WingetSupportedContracts); THROW_HR_IF(APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE, !latestCommonVersion); - std::unique_ptr supportedInterface = GetSupportedInterface(utility::conversions::to_utf8string(restEndpoint), headers, information, authArgs, latestCommonVersion.value()); + std::unique_ptr supportedInterface = GetSupportedInterface(utility::conversions::to_utf8string(restEndpoint), headers, information, authArgs, latestCommonVersion.value(), helper); return RestClient{ std::move(supportedInterface), information.SourceIdentifier }; } } diff --git a/src/AppInstallerRepositoryCore/Rest/RestClient.h b/src/AppInstallerRepositoryCore/Rest/RestClient.h index 64bb1f5989..e7ee2c7313 100644 --- a/src/AppInstallerRepositoryCore/Rest/RestClient.h +++ b/src/AppInstallerRepositoryCore/Rest/RestClient.h @@ -30,12 +30,18 @@ namespace AppInstaller::Repository::Rest static std::optional GetLatestCommonVersion(const std::vector& serverSupportedVersions, const std::set& wingetSupportedVersions); // Responsible for getting the source information contracts with minimal validation. Does not try to create a rest interface out of it. - static Schema::IRestClient::Information GetInformation(const std::string& restApi, std::optional customHeader, std::string_view caller, const Schema::HttpClientHelper& helper = {}); + static Schema::IRestClient::Information GetInformation(const std::string& restApi, std::optional customHeader, std::string_view caller, const Schema::HttpClientHelper& helper); - static std::unique_ptr GetSupportedInterface(const std::string& restApi, const Schema::HttpClientHelper::HttpRequestHeaders& additionalHeaders, const Schema::IRestClient::Information& information, const Authentication::AuthenticationArguments& authArgs, const AppInstaller::Utility::Version& version); + static std::unique_ptr GetSupportedInterface( + const std::string& restApi, + const Schema::HttpClientHelper::HttpRequestHeaders& additionalHeaders, + const Schema::IRestClient::Information& information, + const Authentication::AuthenticationArguments& authArgs, + const AppInstaller::Utility::Version& version, + const Schema::HttpClientHelper& helper); // Creates the rest client. Full validation performed (just as opening the source) - static RestClient Create(const std::string& restApi, std::optional customHeader, std::string_view caller, const Authentication::AuthenticationArguments& authArgs = {}, const Schema::HttpClientHelper& helper = {}); + static RestClient Create(const std::string& restApi, std::optional customHeader, std::string_view caller, const Schema::HttpClientHelper& helper, const Authentication::AuthenticationArguments& authArgs = {}); private: RestClient(std::unique_ptr supportedInterface, std::string sourceIdentifier); diff --git a/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp b/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp index 7f6c5d84f7..d523e0caa1 100644 --- a/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp +++ b/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp @@ -50,7 +50,7 @@ namespace AppInstaller::Repository::Rest std::shared_ptr Open(IProgressCallback&) override { Initialize(); - RestClient restClient = RestClient::Create(m_details.Arg, m_customHeader, m_caller, m_authArgs, m_httpClientHelper); + RestClient restClient = RestClient::Create(m_details.Arg, m_customHeader, m_caller, m_httpClientHelper, m_authArgs); return std::make_shared(m_details, m_information, std::move(restClient)); } @@ -63,8 +63,13 @@ namespace AppInstaller::Repository::Rest m_httpClientHelper.SetPinningConfiguration(m_details.CertificatePinningConfiguration); if (m_details.ProxyInfo.ProxyUri) { + AICLI_LOG(Repo, Info, << "Setting proxy for REST source to " << m_details.ProxyInfo.ProxyUri.value()); m_httpClientHelper.SetProxy(Utility::ConvertToUTF16(m_details.ProxyInfo.ProxyUri.value())); } + else + { + AICLI_LOG(Repo, Info, << "REST source does not use proxy"); + } auto sourceInformation = RestClient::GetInformation(m_details.Arg, m_customHeader, m_caller, m_httpClientHelper); diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_0/Interface.h b/src/AppInstallerRepositoryCore/Rest/Schema/1_0/Interface.h index 0ea59b2dfc..a304a9bae7 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/1_0/Interface.h +++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_0/Interface.h @@ -10,7 +10,7 @@ namespace AppInstaller::Repository::Rest::Schema::V1_0 // Interface to this schema version exposed through IRestClient. struct Interface : public IRestClient { - Interface(const std::string& restApi, const HttpClientHelper& httpClientHelper = {}); + Interface(const std::string& restApi, const Schema::HttpClientHelper& helper); Interface(const Interface&) = delete; Interface& operator=(const Interface&) = delete; diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_1/Interface.h b/src/AppInstallerRepositoryCore/Rest/Schema/1_1/Interface.h index 31575a7c51..8bf3629b69 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/1_1/Interface.h +++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_1/Interface.h @@ -8,7 +8,7 @@ namespace AppInstaller::Repository::Rest::Schema::V1_1 // Interface to this schema version exposed through IRestClient. struct Interface : public V1_0::Interface { - Interface(const std::string& restApi, IRestClient::Information information, const HttpClientHelper::HttpRequestHeaders& additionalHeaders = {}, const HttpClientHelper& httpClientHelper = {}); + Interface(const std::string& restApi, const Schema::HttpClientHelper& helper, IRestClient::Information information, const HttpClientHelper::HttpRequestHeaders& additionalHeaders = {}); Interface(const Interface&) = delete; Interface& operator=(const Interface&) = delete; diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_1/RestInterface_1_1.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/1_1/RestInterface_1_1.cpp index 7fdaa5f2b1..23589e67a4 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/1_1/RestInterface_1_1.cpp +++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_1/RestInterface_1_1.cpp @@ -26,9 +26,9 @@ namespace AppInstaller::Repository::Rest::Schema::V1_1 Interface::Interface( const std::string& restApi, + const HttpClientHelper& httpClientHelper, IRestClient::Information information, - const HttpClientHelper::HttpRequestHeaders& additionalHeaders, - const HttpClientHelper& httpClientHelper) : V1_0::Interface(restApi, httpClientHelper), m_information(std::move(information)) + const HttpClientHelper::HttpRequestHeaders& additionalHeaders) : V1_0::Interface(restApi, httpClientHelper), m_information(std::move(information)) { m_requiredRestApiHeaders[JSON::GetUtilityString(ContractVersion)] = JSON::GetUtilityString(Version_1_1_0.ToString()); diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_4/Interface.h b/src/AppInstallerRepositoryCore/Rest/Schema/1_4/Interface.h index cd8b2d63a7..c08ab1b875 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/1_4/Interface.h +++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_4/Interface.h @@ -8,7 +8,7 @@ namespace AppInstaller::Repository::Rest::Schema::V1_4 // Interface to this schema version exposed through IRestClient. struct Interface : public V1_1::Interface { - Interface(const std::string& restApi, IRestClient::Information information, const HttpClientHelper::HttpRequestHeaders& additionalHeaders = {}, const HttpClientHelper& httpClientHelper = {}); + Interface(const std::string& restApi, const Schema::HttpClientHelper& helper, IRestClient::Information information, const HttpClientHelper::HttpRequestHeaders& additionalHeaders = {}); Interface(const Interface&) = delete; Interface& operator=(const Interface&) = delete; diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_4/RestInterface_1_4.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/1_4/RestInterface_1_4.cpp index 9ade746c48..fc7a0b8656 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/1_4/RestInterface_1_4.cpp +++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_4/RestInterface_1_4.cpp @@ -11,9 +11,9 @@ namespace AppInstaller::Repository::Rest::Schema::V1_4 { Interface::Interface( const std::string& restApi, + const HttpClientHelper& httpClientHelper, IRestClient::Information information, - const HttpClientHelper::HttpRequestHeaders& additionalHeaders, - const HttpClientHelper& httpClientHelper) : V1_1::Interface(restApi, std::move(information), additionalHeaders, httpClientHelper) + const HttpClientHelper::HttpRequestHeaders& additionalHeaders) : V1_1::Interface(restApi, httpClientHelper, std::move(information), additionalHeaders) { m_requiredRestApiHeaders[JSON::GetUtilityString(ContractVersion)] = JSON::GetUtilityString(Version_1_4_0.ToString()); } diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_5/Interface.h b/src/AppInstallerRepositoryCore/Rest/Schema/1_5/Interface.h index aa47758c9c..51b8ddd4fb 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/1_5/Interface.h +++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_5/Interface.h @@ -8,7 +8,7 @@ namespace AppInstaller::Repository::Rest::Schema::V1_5 // Interface to this schema version exposed through IRestClient. struct Interface : public V1_4::Interface { - Interface(const std::string& restApi, IRestClient::Information information, const HttpClientHelper::HttpRequestHeaders& additionalHeaders = {}, const HttpClientHelper& httpClientHelper = {}); + Interface(const std::string& restApi, const Schema::HttpClientHelper& helper, IRestClient::Information information, const HttpClientHelper::HttpRequestHeaders& additionalHeaders = {}); Interface(const Interface&) = delete; Interface& operator=(const Interface&) = delete; diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_5/RestInterface_1_5.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/1_5/RestInterface_1_5.cpp index 92da210126..82aa257bb5 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/1_5/RestInterface_1_5.cpp +++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_5/RestInterface_1_5.cpp @@ -11,9 +11,9 @@ namespace AppInstaller::Repository::Rest::Schema::V1_5 { Interface::Interface( const std::string& restApi, + const HttpClientHelper& httpClientHelper, IRestClient::Information information, - const HttpClientHelper::HttpRequestHeaders& additionalHeaders, - const HttpClientHelper& httpClientHelper) : V1_4::Interface(restApi, std::move(information), additionalHeaders, httpClientHelper) + const HttpClientHelper::HttpRequestHeaders& additionalHeaders) : V1_4::Interface(restApi, httpClientHelper, std::move(information), additionalHeaders) { m_requiredRestApiHeaders[JSON::GetUtilityString(ContractVersion)] = JSON::GetUtilityString(Version_1_5_0.ToString()); } diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_6/Interface.h b/src/AppInstallerRepositoryCore/Rest/Schema/1_6/Interface.h index 49bc919d24..527017931e 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/1_6/Interface.h +++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_6/Interface.h @@ -8,7 +8,7 @@ namespace AppInstaller::Repository::Rest::Schema::V1_6 // Interface to this schema version exposed through IRestClient. struct Interface : public V1_5::Interface { - Interface(const std::string& restApi, IRestClient::Information information, const HttpClientHelper::HttpRequestHeaders& additionalHeaders = {}, const HttpClientHelper& httpClientHelper = {}); + Interface(const std::string& restApi, const Schema::HttpClientHelper& helper, IRestClient::Information information, const HttpClientHelper::HttpRequestHeaders& additionalHeaders = {}); Interface(const Interface&) = delete; Interface& operator=(const Interface&) = delete; diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_6/RestInterface_1_6.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/1_6/RestInterface_1_6.cpp index 454476bce8..4277b683ac 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/1_6/RestInterface_1_6.cpp +++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_6/RestInterface_1_6.cpp @@ -11,9 +11,9 @@ namespace AppInstaller::Repository::Rest::Schema::V1_6 { Interface::Interface( const std::string& restApi, + const HttpClientHelper& httpClientHelper, IRestClient::Information information, - const HttpClientHelper::HttpRequestHeaders& additionalHeaders, - const HttpClientHelper& httpClientHelper) : V1_5::Interface(restApi, std::move(information), additionalHeaders, httpClientHelper) + const HttpClientHelper::HttpRequestHeaders& additionalHeaders) : V1_5::Interface(restApi, httpClientHelper, std::move(information), additionalHeaders) { m_requiredRestApiHeaders[JSON::GetUtilityString(ContractVersion)] = JSON::GetUtilityString(Version_1_6_0.ToString()); } diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_7/Interface.h b/src/AppInstallerRepositoryCore/Rest/Schema/1_7/Interface.h index 5c51327998..911cc1a37d 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/1_7/Interface.h +++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_7/Interface.h @@ -8,7 +8,7 @@ namespace AppInstaller::Repository::Rest::Schema::V1_7 // Interface to this schema version exposed through IRestClient. struct Interface : public V1_6::Interface { - Interface(const std::string& restApi, IRestClient::Information information, const HttpClientHelper::HttpRequestHeaders& additionalHeaders = {}, Authentication::AuthenticationArguments authArgs = {}, const HttpClientHelper& httpClientHelper = {}); + Interface(const std::string& restApi, const Schema::HttpClientHelper& helper, IRestClient::Information information, const HttpClientHelper::HttpRequestHeaders& additionalHeaders = {}, Authentication::AuthenticationArguments authArgs = {}); Interface(const Interface&) = delete; Interface& operator=(const Interface&) = delete; diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/1_7/RestInterface_1_7.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/1_7/RestInterface_1_7.cpp index 0ed0e370a9..96108aa0f6 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/1_7/RestInterface_1_7.cpp +++ b/src/AppInstallerRepositoryCore/Rest/Schema/1_7/RestInterface_1_7.cpp @@ -11,10 +11,10 @@ namespace AppInstaller::Repository::Rest::Schema::V1_7 { Interface::Interface( const std::string& restApi, + const HttpClientHelper& httpClientHelper, IRestClient::Information information, const HttpClientHelper::HttpRequestHeaders& additionalHeaders, - Authentication::AuthenticationArguments authArgs, - const HttpClientHelper& httpClientHelper) : V1_6::Interface(restApi, std::move(information), additionalHeaders, httpClientHelper), m_authArgs(std::move(authArgs)) + Authentication::AuthenticationArguments authArgs) : V1_6::Interface(restApi, httpClientHelper, std::move(information), additionalHeaders), m_authArgs(std::move(authArgs)) { m_requiredRestApiHeaders[JSON::GetUtilityString(ContractVersion)] = JSON::GetUtilityString(Version_1_7_0.ToString()); From 317223862bdfcccf3166db96c387c719083f787f Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Tue, 27 Feb 2024 11:06:18 -0800 Subject: [PATCH 18/32] Fix string id --- src/AppInstallerCLICore/Argument.cpp | 4 + .../Commands/SettingsCommand.cpp | 95 +++++++++++++++++++ .../Commands/SettingsCommand.h | 32 +++++++ src/AppInstallerCLICore/ExecutionArgs.h | 2 + src/AppInstallerCLICore/Resources.h | 16 +++- .../Workflows/SettingsFlow.cpp | 29 ++++++ .../Workflows/SettingsFlow.h | 12 +++ .../Shared/Strings/en-us/winget.resw | 36 ++++++- .../Public/winget/AdminSettings.h | 2 +- 9 files changed, 223 insertions(+), 5 deletions(-) diff --git a/src/AppInstallerCLICore/Argument.cpp b/src/AppInstallerCLICore/Argument.cpp index b2bde9919c..2f47eb1013 100644 --- a/src/AppInstallerCLICore/Argument.cpp +++ b/src/AppInstallerCLICore/Argument.cpp @@ -151,6 +151,10 @@ namespace AppInstaller::CLI return { type, "enable"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::EnableDisable }; case Execution::Args::Type::AdminSettingDisable: return { type, "disable"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::EnableDisable }; + case Execution::Args::Type::SettingName: + return { type, "setting"_liv }; + case Execution::Args::Type::SettingValue: + return { type, "value"_liv }; // Upgrade command case Execution::Args::Type::All: diff --git a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp index 2713f0a18b..a03a2c69d6 100644 --- a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp +++ b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp @@ -20,6 +20,8 @@ namespace AppInstaller::CLI { return InitializeFromMoveOnly>>({ std::make_unique(FullName()), + std::make_unique(FullName()), + std::make_unique(FullName()), }); } @@ -109,4 +111,97 @@ namespace AppInstaller::CLI context << Workflow::ExportSettings; } + + std::vector SettingsSetCommand::GetArguments() const + { + return { + Argument { Execution::Args::Type::SettingName, Resource::String::SettingNameArgumentDescription, ArgumentType::Positional, true }, + Argument { Execution::Args::Type::SettingValue, Resource::String::SettingValueArgumentDescription, ArgumentType::Positional, true }, + }; + } + + Resource::LocString SettingsSetCommand::ShortDescription() const + { + return { Resource::String::SettingsSetCommandShortDescription }; + } + + Resource::LocString SettingsSetCommand::LongDescription() const + { + return { Resource::String::SettingsSetCommandLongDescription }; + } + + Utility::LocIndView SettingsSetCommand::HelpLink() const + { + return s_SettingsCommand_HelpLink; + } + + void SettingsSetCommand::ValidateArgumentsInternal(Execution::Args& execArgs) const + { + // Get admin setting string for all available options except Unknown + std::vector adminSettingList; + for (auto setting : GetAllSequentialEnumValues(StringAdminSetting::Unknown)) + { + adminSettingList.emplace_back(AdminSettingToString(setting)); + } + + Utility::LocIndString validOptions = Join(", "_liv, adminSettingList); + + if (execArgs.Contains(Execution::Args::Type::AdminSettingEnable) && StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName))) + { + throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::SettingName).Name, validOptions)); + } + } + + void SettingsSetCommand::ExecuteInternal(Execution::Context& context) const + { + context << + Workflow::EnsureRunningAsAdmin << + Workflow::SetAdminSetting; + } + + std::vector SettingsResetCommand::GetArguments() const + { + return { + Argument { Execution::Args::Type::SettingName, Resource::String::SettingNameArgumentDescription, ArgumentType::Positional, true }, + }; + } + + Resource::LocString SettingsResetCommand::ShortDescription() const + { + return { Resource::String::SettingsResetCommandShortDescription }; + } + + Resource::LocString SettingsResetCommand::LongDescription() const + { + return { Resource::String::SettingsResetCommandLongDescription }; + } + + Utility::LocIndView SettingsResetCommand::HelpLink() const + { + return s_SettingsCommand_HelpLink; + } + + void SettingsResetCommand::ValidateArgumentsInternal(Execution::Args& execArgs) const + { + // Get admin setting string for all available options except Unknown + std::vector adminSettingList; + for (auto setting : GetAllSequentialEnumValues(StringAdminSetting::Unknown)) + { + adminSettingList.emplace_back(AdminSettingToString(setting)); + } + + Utility::LocIndString validOptions = Join(", "_liv, adminSettingList); + + if (execArgs.Contains(Execution::Args::Type::AdminSettingEnable) && StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName))) + { + throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::SettingName).Name, validOptions)); + } + } + + void SettingsResetCommand::ExecuteInternal(Execution::Context& context) const + { + context << + Workflow::EnsureRunningAsAdmin << + Workflow::ResetAdminSetting; + } } diff --git a/src/AppInstallerCLICore/Commands/SettingsCommand.h b/src/AppInstallerCLICore/Commands/SettingsCommand.h index aee6cffbfd..78cb164da2 100644 --- a/src/AppInstallerCLICore/Commands/SettingsCommand.h +++ b/src/AppInstallerCLICore/Commands/SettingsCommand.h @@ -34,4 +34,36 @@ namespace AppInstaller::CLI protected: void ExecuteInternal(Execution::Context& context) const override; }; + + struct SettingsSetCommand final : public Command + { + SettingsSetCommand(std::string_view parent) : Command("set", {}, parent, Settings::TogglePolicy::Policy::Settings) {} + + std::vector GetArguments() const override; + + virtual Resource::LocString ShortDescription() const override; + virtual Resource::LocString LongDescription() const override; + + Utility::LocIndView HelpLink() const override; + + protected: + void ValidateArgumentsInternal(Execution::Args& execArgs) const override; + void ExecuteInternal(Execution::Context& context) const override; + }; + + struct SettingsResetCommand final : public Command + { + SettingsResetCommand(std::string_view parent) : Command("reset", {}, parent, Settings::TogglePolicy::Policy::Settings) {} + + std::vector GetArguments() const override; + + virtual Resource::LocString ShortDescription() const override; + virtual Resource::LocString LongDescription() const override; + + Utility::LocIndView HelpLink() const override; + + protected: + void ValidateArgumentsInternal(Execution::Args& execArgs) const override; + void ExecuteInternal(Execution::Context& context) const override; + }; } diff --git a/src/AppInstallerCLICore/ExecutionArgs.h b/src/AppInstallerCLICore/ExecutionArgs.h index 32f5e58535..8ea1e0754d 100644 --- a/src/AppInstallerCLICore/ExecutionArgs.h +++ b/src/AppInstallerCLICore/ExecutionArgs.h @@ -89,6 +89,8 @@ namespace AppInstaller::CLI::Execution // Setting Command AdminSettingEnable, AdminSettingDisable, + SettingName, + SettingValue, // Upgrade command All, // Used in Update command to update all installed packages to latest diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h index b1f48342ce..a05c3c691a 100644 --- a/src/AppInstallerCLICore/Resources.h +++ b/src/AppInstallerCLICore/Resources.h @@ -339,16 +339,16 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(NestedInstallerNotFound); WINGET_DEFINE_RESOURCE_STRINGID(NestedInstallerNotSpecified); WINGET_DEFINE_RESOURCE_STRINGID(NestedInstallerNotSupported); - WINGET_DEFINE_RESOURCE_STRINGID(NoApplicableInstallers); WINGET_DEFINE_RESOURCE_STRINGID(NoAdminRepairForUserScopePackage); + WINGET_DEFINE_RESOURCE_STRINGID(NoApplicableInstallers); WINGET_DEFINE_RESOURCE_STRINGID(NoExperimentalFeaturesMessage); WINGET_DEFINE_RESOURCE_STRINGID(NoInstalledPackageFound); WINGET_DEFINE_RESOURCE_STRINGID(NoPackageFound); WINGET_DEFINE_RESOURCE_STRINGID(NoPackageSelectionArgumentProvided); WINGET_DEFINE_RESOURCE_STRINGID(NoPackagesFoundInImportFile); WINGET_DEFINE_RESOURCE_STRINGID(NoProxyArgumentDescription); - WINGET_DEFINE_RESOURCE_STRINGID(Notes); WINGET_DEFINE_RESOURCE_STRINGID(NoRepairInfoFound); + WINGET_DEFINE_RESOURCE_STRINGID(Notes); WINGET_DEFINE_RESOURCE_STRINGID(NoUninstallInfoFound); WINGET_DEFINE_RESOURCE_STRINGID(NoUpgradeArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(NoVTArgumentDescription); @@ -439,6 +439,8 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(ReportIdentityFound); WINGET_DEFINE_RESOURCE_STRINGID(RequiredArgError); WINGET_DEFINE_RESOURCE_STRINGID(ReservedFilenameError); + WINGET_DEFINE_RESOURCE_STRINGID(ResetAdminSettingFailed); + WINGET_DEFINE_RESOURCE_STRINGID(ResetAdminSettingSucceeded); WINGET_DEFINE_RESOURCE_STRINGID(ResumeCommandLongDescription); WINGET_DEFINE_RESOURCE_STRINGID(ResumeCommandShortDescription); WINGET_DEFINE_RESOURCE_STRINGID(ResumeIdArgumentDescription); @@ -459,14 +461,22 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(SearchTruncated); WINGET_DEFINE_RESOURCE_STRINGID(SearchVersion); WINGET_DEFINE_RESOURCE_STRINGID(SeeLineAndColumn); + WINGET_DEFINE_RESOURCE_STRINGID(SetAdminSettingFailed); + WINGET_DEFINE_RESOURCE_STRINGID(SetAdminSettingSucceeded); WINGET_DEFINE_RESOURCE_STRINGID(SettingLoadFailure); + WINGET_DEFINE_RESOURCE_STRINGID(SettingNameArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(SettingsCommandLongDescription); WINGET_DEFINE_RESOURCE_STRINGID(SettingsCommandShortDescription); WINGET_DEFINE_RESOURCE_STRINGID(SettingsExportCommandLongDescription); WINGET_DEFINE_RESOURCE_STRINGID(SettingsExportCommandShortDescription); + WINGET_DEFINE_RESOURCE_STRINGID(SettingsResetCommandLongDescription); + WINGET_DEFINE_RESOURCE_STRINGID(SettingsResetCommandShortDescription); + WINGET_DEFINE_RESOURCE_STRINGID(SettingsSetCommandLongDescription); + WINGET_DEFINE_RESOURCE_STRINGID(SettingsSetCommandShortDescription); WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningField); WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarnings); WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningValue); + WINGET_DEFINE_RESOURCE_STRINGID(SettingValueArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(ShowChannel); WINGET_DEFINE_RESOURCE_STRINGID(ShowCommandLongDescription); WINGET_DEFINE_RESOURCE_STRINGID(ShowCommandShortDescription); @@ -591,8 +601,8 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(UpdateNotApplicableReason); WINGET_DEFINE_RESOURCE_STRINGID(UpgradeArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(UpgradeAvailableForPinned); - WINGET_DEFINE_RESOURCE_STRINGID(UpgradeBlockedByPinCount); WINGET_DEFINE_RESOURCE_STRINGID(UpgradeBlockedByManifest); + WINGET_DEFINE_RESOURCE_STRINGID(UpgradeBlockedByPinCount); WINGET_DEFINE_RESOURCE_STRINGID(UpgradeCommandLongDescription); WINGET_DEFINE_RESOURCE_STRINGID(UpgradeCommandShortDescription); WINGET_DEFINE_RESOURCE_STRINGID(UpgradeDifferentInstallTechnology); diff --git a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp index 5e5d11f876..99159e72b2 100644 --- a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp @@ -79,6 +79,35 @@ namespace AppInstaller::CLI::Workflow } } + void SetAdminSetting(Execution::Context& context) + { + auto adminSettingName = context.Args.GetArg(Execution::Args::Type::SettingName); + auto adminSettingValue = context.Args.GetArg(Execution::Args::Type::SettingValue); + StringAdminSetting adminSetting = Settings::StringToStringAdminSetting(adminSettingName); + if (Settings::SetAdminSetting(adminSetting, adminSettingValue)) + { + context.Reporter.Info() << Resource::String::SetAdminSettingSucceeded(AdminSettingToString(adminSetting), LocIndString{ adminSettingValue }) << std::endl; + } + else + { + context.Reporter.Error() << Resource::String::SetAdminSettingFailed(AdminSettingToString(adminSetting)) << std::endl; + } + } + + void ResetAdminSetting(Execution::Context& context) + { + auto adminSettingName = context.Args.GetArg(Execution::Args::Type::SettingName); + StringAdminSetting adminSetting = Settings::StringToStringAdminSetting(adminSettingName); + if (Settings::ResetAdminSetting(adminSetting)) + { + context.Reporter.Info() << Resource::String::ResetAdminSettingSucceeded(AdminSettingToString(adminSetting)) << std::endl; + } + else + { + context.Reporter.Error() << Resource::String::ResetAdminSettingFailed(AdminSettingToString(adminSetting)) << std::endl; + } + } + void OpenUserSetting(Execution::Context& context) { // Show warnings only when the setting command is executed. diff --git a/src/AppInstallerCLICore/Workflows/SettingsFlow.h b/src/AppInstallerCLICore/Workflows/SettingsFlow.h index e40a0051c9..50998295a5 100644 --- a/src/AppInstallerCLICore/Workflows/SettingsFlow.h +++ b/src/AppInstallerCLICore/Workflows/SettingsFlow.h @@ -17,6 +17,18 @@ namespace AppInstaller::CLI::Workflow // Outputs: None void DisableAdminSetting(Execution::Context& context); + // Sets the value of an admin setting. + // Required Args: SettingName, SettingValue + // Inputs: None + // Outputs: None + void SetAdminSetting(Execution::Context& context); + + // Resets an admin setting to the default. + // Required Args: SettingName + // Inputs: None + // Outputs: None + void ResetAdminSetting(Execution::Context& context); + // Opens the user settings. // Required Args: None // Inputs: None diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index 8ef4f71a0e..7f5838c20e 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -2817,7 +2817,7 @@ Please specify one of them using the --source option to proceed. The SQLite connection was terminated to prevent corruption. - + Enable Windows Package Manager proxy command line options Describes a Group Policy that can enable the use of the --proxy option to set a proxy @@ -2827,4 +2827,38 @@ Please specify one of them using the --source option to proceed. Disable the use of proxy for this execution + + Cannot reset {0}. This setting is controlled by policy. For more information contact your system administrator. + {Locked="{0}"} The value will be replaced with the feature name + + + Reset admin setting '{0}'. + {Locked="{0}"} Message displayed after the user resets an admin setting to its default value. Reset is used as verb in past tense. {0} is a placeholder replaced by the setting name. + + + Cannot set {0}. This setting is controlled by policy. For more information contact your system administrator. + {Locked="{0}"} The value will be replaced with the feature name + + + Set admin setting '{0}' to '{1}'. + {Locked="{0}"} Message displayed after the user sets the value of an admin setting. Set is used as a verb in past tense. {0} is a placeholder replaced by the setting name. {1} is a placeholder replaced + + + Name of the setting to modify + + + Value to set for the setting. + + + Resets an admin setting to its default value. + + + Resets an admin setting to its default value. + + + Sets the value of an admin setting. + + + Sets the value of an admin setting. + \ No newline at end of file diff --git a/src/AppInstallerCommonCore/Public/winget/AdminSettings.h b/src/AppInstallerCommonCore/Public/winget/AdminSettings.h index d322da1e3c..09d77fff6f 100644 --- a/src/AppInstallerCommonCore/Public/winget/AdminSettings.h +++ b/src/AppInstallerCommonCore/Public/winget/AdminSettings.h @@ -40,7 +40,7 @@ namespace AppInstaller::Settings bool EnableAdminSetting(BoolAdminSetting setting); bool DisableAdminSetting(BoolAdminSetting setting); bool SetAdminSetting(StringAdminSetting setting, std::string_view value); - bool ResetAdminSetting(StringAdminSetting setting, std::string_view value); + bool ResetAdminSetting(StringAdminSetting setting); bool IsAdminSettingEnabled(BoolAdminSetting setting); std::optional GetAdminSetting(StringAdminSetting setting); From 2e065e67951b5157b6ea07ba637b2ec88db9d1aa Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Thu, 29 Feb 2024 11:58:42 -0800 Subject: [PATCH 19/32] Make proxy settings global --- .../Commands/HashCommand.cpp | 2 +- src/AppInstallerCLICore/Core.cpp | 7 --- src/AppInstallerCLICore/ExecutionContext.cpp | 18 ++++++ .../ExecutionContextData.h | 7 --- .../Workflows/ConfigurationFlow.cpp | 2 +- .../Workflows/DownloadFlow.cpp | 41 ++---------- .../Workflows/DownloadFlow.h | 6 -- .../Workflows/WorkflowBase.cpp | 8 --- src/AppInstallerCLITests/Downloader.cpp | 8 +-- src/AppInstallerCLITests/MsixInfo.cpp | 2 +- src/AppInstallerCLITests/TestCommon.cpp | 2 +- .../AppInstallerCommonCore.vcxproj | 2 + .../AppInstallerCommonCore.vcxproj.filters | 6 ++ src/AppInstallerCommonCore/Deployment.cpp | 4 +- src/AppInstallerCommonCore/Downloader.cpp | 41 ++++-------- .../HttpStream/HttpClientWrapper.cpp | 2 +- .../HttpStream/HttpClientWrapper.h | 7 +-- .../HttpStream/HttpRandomAccessStream.cpp | 4 +- .../HttpStream/HttpRandomAccessStream.h | 9 +-- .../Manifest/MsixManifestValidation.cpp | 4 +- src/AppInstallerCommonCore/MsixInfo.cpp | 4 +- .../NetworkSettings.cpp | 62 +++++++++++++++++++ .../Public/AppInstallerDownloader.h | 16 +---- .../Public/AppInstallerMsixInfo.h | 9 +-- .../Public/winget/NetworkSettings.h | 31 ++++++++++ src/AppInstallerRepositoryCore/ISource.h | 5 -- .../InstallerMetadataCollectionContext.cpp | 2 +- .../PreIndexedPackageSourceFactory.cpp | 20 +++--- .../Microsoft/SQLiteIndexSource.cpp | 8 +-- .../Public/winget/RepositorySource.h | 6 -- .../RepositorySource.cpp | 8 --- .../Rest/RestSourceFactory.cpp | 8 ++- src/WinGetUtil/Exports.cpp | 2 +- 33 files changed, 180 insertions(+), 183 deletions(-) create mode 100644 src/AppInstallerCommonCore/NetworkSettings.cpp create mode 100644 src/AppInstallerCommonCore/Public/winget/NetworkSettings.h diff --git a/src/AppInstallerCLICore/Commands/HashCommand.cpp b/src/AppInstallerCLICore/Commands/HashCommand.cpp index f6838056a1..0d6e01589e 100644 --- a/src/AppInstallerCLICore/Commands/HashCommand.cpp +++ b/src/AppInstallerCLICore/Commands/HashCommand.cpp @@ -50,7 +50,7 @@ namespace AppInstaller::CLI { try { - Msix::MsixInfo msixInfo{ inputFile, Utility::ProxyInfo::NoProxy }; + Msix::MsixInfo msixInfo{ inputFile }; auto signatureHash = msixInfo.GetSignatureHash(); context.Reporter.Info() << "SignatureSha256: "_liv << Utility::LocIndString{ Utility::SHA256::ConvertToString(signatureHash) } << std::endl; diff --git a/src/AppInstallerCLICore/Core.cpp b/src/AppInstallerCLICore/Core.cpp index 89d5c892eb..fe19bb0aec 100644 --- a/src/AppInstallerCLICore/Core.cpp +++ b/src/AppInstallerCLICore/Core.cpp @@ -119,13 +119,6 @@ namespace AppInstaller::CLI Logging::Telemetry().LogCommand(command->FullName()); command->ParseArguments(invocation, context.Args); - - // Change logging level to Info if Verbose not requested - if (context.Args.Contains(Execution::Args::Type::VerboseLogs)) - { - Logging::Log().SetLevel(Logging::Level::Verbose); - } - context.UpdateForArgs(); context.SetExecutingCommand(command.get()); command->ValidateArguments(context.Args); diff --git a/src/AppInstallerCLICore/ExecutionContext.cpp b/src/AppInstallerCLICore/ExecutionContext.cpp index 48fd668ee6..d8ecb88b1c 100644 --- a/src/AppInstallerCLICore/ExecutionContext.cpp +++ b/src/AppInstallerCLICore/ExecutionContext.cpp @@ -9,6 +9,7 @@ #include #include #include +#include using namespace AppInstaller::Checkpoints; @@ -349,6 +350,23 @@ namespace AppInstaller::CLI::Execution void Context::UpdateForArgs() { + // Change logging level to Info if Verbose not requested + if (Args.Contains(Args::Type::VerboseLogs)) + { + Logging::Log().SetLevel(Logging::Level::Verbose); + } + + // Set proxy + if (Args.Contains(Args::Type::Proxy)) + { + Network().SetProxyUri(std::string{ Args.GetArg(Args::Type::Proxy) }); + } + else if (Args.Contains(Args::Type::NoProxy)) + { + Network().SetProxyUri(std::nullopt); + } + + // Set visual style if (Args.Contains(Args::Type::NoVT)) { Reporter.SetStyle(VisualStyle::NoVT); diff --git a/src/AppInstallerCLICore/ExecutionContextData.h b/src/AppInstallerCLICore/ExecutionContextData.h index 8f24dddc53..0e7ae79e00 100644 --- a/src/AppInstallerCLICore/ExecutionContextData.h +++ b/src/AppInstallerCLICore/ExecutionContextData.h @@ -66,7 +66,6 @@ namespace AppInstaller::CLI::Execution DownloadDirectory, ModifyPath, RepairString, - NetworkProxyInfo, Max }; @@ -284,11 +283,5 @@ namespace AppInstaller::CLI::Execution { using value_t = std::string; }; - - template <> - struct DataMapping - { - using value_t = Utility::ProxyInfo; - }; } } diff --git a/src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp b/src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp index 5aadb38261..77c1fbd9d1 100644 --- a/src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp @@ -866,7 +866,7 @@ namespace AppInstaller::CLI::Workflow { std::ostringstream stringStream; ProgressCallback emptyCallback; - Utility::DownloadToStream(argPath, stringStream, Utility::DownloadType::ConfigurationFile, emptyCallback, Utility::ProxyInfo::NoProxy); + Utility::DownloadToStream(argPath, stringStream, Utility::DownloadType::ConfigurationFile, emptyCallback); auto strContent = stringStream.str(); std::vector byteContent{ strContent.begin(), strContent.end() }; diff --git a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp index 7aa0a285fa..618db03789 100644 --- a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace AppInstaller::CLI::Workflow { @@ -180,35 +181,6 @@ namespace AppInstaller::CLI::Workflow } } - void GetProxyInfo(Execution::Context& context) - { - if (context.Contains(Execution::Data::NetworkProxyInfo)) - { - // Already determined proxy to use - return; - } - - Utility::ProxyInfo proxyInfo; - - // Get the default proxy - proxyInfo.ProxyUri = GetAdminSetting(StringAdminSetting::DefaultProxy); - AICLI_LOG(CLI, Info, << "Default proxy: " << (proxyInfo.ProxyUri ? proxyInfo.ProxyUri.value() : "Not configured")); - - // Check command line arguments. These override any default if present. - if (context.Args.Contains(Execution::Args::Type::NoProxy)) - { - AICLI_LOG(CLI, Info, << "Proxy disabled by command line argument"); - proxyInfo = Utility::ProxyInfo::NoProxy; - } - else if (context.Args.Contains(Execution::Args::Type::Proxy)) - { - proxyInfo.ProxyUri = context.Args.GetArg(Execution::Args::Type::Proxy); - AICLI_LOG(CLI, Info, << "Setting proxy from command line argument: " << proxyInfo.ProxyUri.value()); - } - - context.Add(proxyInfo); - } - void DownloadInstaller(Execution::Context& context) { // Check if file was already downloaded. @@ -216,8 +188,7 @@ namespace AppInstaller::CLI::Workflow // separately before, e.g. on COM scenarios. context << ReportExecutionStage(ExecutionStage::Download) << - CheckForExistingInstaller << - GetProxyInfo; + CheckForExistingInstaller; if (context.IsTerminated()) { @@ -249,7 +220,7 @@ namespace AppInstaller::CLI::Workflow // flag is set, or if we need to use a proxy (as deployment APIs won't use proxy for us). if (installer.SignatureSha256.empty() || installerDownloadOnly - || context.Get().ProxyUri) + || Network().GetProxyUri()) { context << DownloadInstallerFile; } @@ -325,7 +296,7 @@ namespace AppInstaller::CLI::Workflow void DownloadInstallerFile(Execution::Context& context) { - context << GetInstallerDownloadPath << GetProxyInfo; + context << GetInstallerDownloadPath; if (context.IsTerminated()) { return; @@ -333,7 +304,6 @@ namespace AppInstaller::CLI::Workflow const auto& installer = context.Get().value(); const auto& installerPath = context.Get(); - const auto& proxyInfo = context.Get(); Utility::DownloadInfo downloadInfo{}; downloadInfo.DisplayName = Resource::GetFixedString(Resource::FixedString::ProductName); @@ -356,7 +326,6 @@ namespace AppInstaller::CLI::Workflow installerPath, Utility::DownloadType::Installer, std::placeholders::_1, - proxyInfo, true, downloadInfo)); @@ -425,7 +394,7 @@ namespace AppInstaller::CLI::Workflow const auto& installer = context.Get().value(); // Signature hash is only used for streaming installs, which don't use proxy - Msix::MsixInfo msixInfo(installer.Url, Utility::ProxyInfo::NoProxy); + Msix::MsixInfo msixInfo(installer.Url); auto signatureHash = msixInfo.GetSignatureHash(); context.Add(std::make_pair(installer.SignatureSha256, signatureHash)); diff --git a/src/AppInstallerCLICore/Workflows/DownloadFlow.h b/src/AppInstallerCLICore/Workflows/DownloadFlow.h index 57b96ab5a0..2ff6e15210 100644 --- a/src/AppInstallerCLICore/Workflows/DownloadFlow.h +++ b/src/AppInstallerCLICore/Workflows/DownloadFlow.h @@ -5,12 +5,6 @@ namespace AppInstaller::CLI::Workflow { - // Gets the proxy settings according to the CLI arg, settings and group policies. - // Required Args: None - // Inputs: None - // Outputs: ProxyInfo - void GetProxyInfo(Execution::Context& context); - // Composite flow that chooses what to do based on the installer type. // Required Args: None // Inputs: Manifest, Installer diff --git a/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp b/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp index e98568e664..9d0ffe0396 100644 --- a/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp +++ b/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp @@ -68,13 +68,6 @@ namespace AppInstaller::CLI::Workflow Repository::Source OpenNamedSource(Execution::Context& context, Utility::LocIndView sourceName) { - // Opening a source may require updating it. - context << GetProxyInfo; - if (context.IsTerminated()) - { - return {}; - } - Repository::Source source; try @@ -118,7 +111,6 @@ namespace AppInstaller::CLI::Workflow { source.SetCaller("winget-cli"); source.SetAuthenticationArguments(GetAuthenticationArguments(context)); - source.SetProxyInfo(context.Get()); return source.Open(progress); }; auto updateFailures = context.Reporter.ExecuteWithProgress(openFunction, true); diff --git a/src/AppInstallerCLITests/Downloader.cpp b/src/AppInstallerCLITests/Downloader.cpp index e9b49f1989..95f8337818 100644 --- a/src/AppInstallerCLITests/Downloader.cpp +++ b/src/AppInstallerCLITests/Downloader.cpp @@ -17,7 +17,7 @@ TEST_CASE("DownloadValidFileAndVerifyHash", "[Downloader]") // Todo: point to files from our repo when the repo goes public ProgressCallback callback; - auto result = Download("https://raw.githubusercontent.com/microsoft/msix-packaging/master/LICENSE", tempFile.GetPath(), DownloadType::Manifest, callback, ProxyInfo::NoProxy, true); + auto result = Download("https://raw.githubusercontent.com/microsoft/msix-packaging/master/LICENSE", tempFile.GetPath(), DownloadType::Manifest, callback, true); REQUIRE(result.has_value()); auto resultHash = result.value(); @@ -50,7 +50,7 @@ TEST_CASE("DownloadValidFileAndCancel", "[Downloader]") std::optional> waitResult; std::thread waitThread([&] { - waitResult = Download("https://aka.ms/win32-x64-user-stable", tempFile.GetPath(), DownloadType::Installer, callback, ProxyInfo::NoProxy, true); + waitResult = Download("https://aka.ms/win32-x64-user-stable", tempFile.GetPath(), DownloadType::Installer, callback, true); }); callback.Cancel(); @@ -67,7 +67,7 @@ TEST_CASE("DownloadInvalidUrl", "[Downloader]") ProgressCallback callback; - REQUIRE_THROWS(Download("blargle-flargle-fluff", tempFile.GetPath(), DownloadType::Installer, callback, ProxyInfo::NoProxy, true)); + REQUIRE_THROWS(Download("blargle-flargle-fluff", tempFile.GetPath(), DownloadType::Installer, callback, true)); } TEST_CASE("HttpStream_ReadLastFullPage", "[HttpStream]") @@ -77,7 +77,7 @@ TEST_CASE("HttpStream_ReadLastFullPage", "[HttpStream]") for (size_t i = 0; i < 10; ++i) { - stream = GetReadOnlyStreamFromURI("https://cdn.winget.microsoft.com/cache/source.msix", ProxyInfo::NoProxy); + stream = GetReadOnlyStreamFromURI("https://cdn.winget.microsoft.com/cache/source.msix"); stat = { 0 }; REQUIRE(stream->Stat(&stat, STATFLAG_NONAME) == S_OK); diff --git a/src/AppInstallerCLITests/MsixInfo.cpp b/src/AppInstallerCLITests/MsixInfo.cpp index 8f0b43ce52..59a33f6f36 100644 --- a/src/AppInstallerCLITests/MsixInfo.cpp +++ b/src/AppInstallerCLITests/MsixInfo.cpp @@ -84,7 +84,7 @@ TEST_CASE("MsixInfo_ValidateMsixTrustInfo", "[msixinfo]") TestCommon::TempFile microsoftSigned{ "testIndex"s, ".msix"s }; ProgressCallback callback; - Utility::Download("https://cdn.winget.microsoft.com/cache/source.msix", microsoftSigned.GetPath(), Utility::DownloadType::Index, callback, Utility::ProxyInfo::NoProxy); + Utility::Download("https://cdn.winget.microsoft.com/cache/source.msix", microsoftSigned.GetPath(), Utility::DownloadType::Index, callback); Msix::WriteLockedMsixFile microsoftSignedWriteLocked{ microsoftSigned }; REQUIRE(microsoftSignedWriteLocked.ValidateTrustInfo(true)); diff --git a/src/AppInstallerCLITests/TestCommon.cpp b/src/AppInstallerCLITests/TestCommon.cpp index 11a0cab718..1364f49e4b 100644 --- a/src/AppInstallerCLITests/TestCommon.cpp +++ b/src/AppInstallerCLITests/TestCommon.cpp @@ -326,7 +326,7 @@ namespace TestCommon auto path = testFile.GetPath().u8string(); // Get the stream for the test file - auto stream = AppInstaller::Utility::GetReadOnlyStreamFromURI(path, {}); + auto stream = AppInstaller::Utility::GetReadOnlyStreamFromURI(path); // Get manifest from package reader Microsoft::WRL::ComPtr packageReader; diff --git a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj index 298d81f5e2..f9dbdc9361 100644 --- a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj +++ b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj @@ -435,6 +435,7 @@ + @@ -481,6 +482,7 @@ + diff --git a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters index 85789ca484..ab890bd70f 100644 --- a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters +++ b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters @@ -189,6 +189,9 @@ Public\winget + + Public\winget + @@ -338,6 +341,9 @@ Authentication + + Source Files + diff --git a/src/AppInstallerCommonCore/Deployment.cpp b/src/AppInstallerCommonCore/Deployment.cpp index 53dcaf89ef..f3588b9011 100644 --- a/src/AppInstallerCommonCore/Deployment.cpp +++ b/src/AppInstallerCommonCore/Deployment.cpp @@ -116,7 +116,7 @@ namespace AppInstaller::Deployment // In the event of a failure we want to ensure that the package is not left on the system. // No need for proxy as Deployment won't use it anyways. - Msix::MsixInfo packageInfo{ uri, Utility::ProxyInfo::NoProxy }; + Msix::MsixInfo packageInfo{ uri }; std::wstring packageFullNameWide = packageInfo.GetPackageFullNameWide(); std::string packageFullName = Utility::ConvertToUTF8(packageFullNameWide); auto removePackage = wil::scope_exit([&]() { @@ -221,7 +221,7 @@ namespace AppInstaller::Deployment // In the event of a failure we want to ensure that the package is not left on the system. // No need for proxy as Deployment won't use it anyways. - Msix::MsixInfo packageInfo{ uri, Utility::ProxyInfo::NoProxy }; + Msix::MsixInfo packageInfo{ uri }; std::wstring packageFullNameWide = packageInfo.GetPackageFullNameWide(); std::string packageFullName = Utility::ConvertToUTF8(packageFullNameWide); std::string packageFamilyName = Msix::GetPackageFamilyNameFromFullName(packageFullName); diff --git a/src/AppInstallerCommonCore/Downloader.cpp b/src/AppInstallerCommonCore/Downloader.cpp index 91a0d80780..4f6098533f 100644 --- a/src/AppInstallerCommonCore/Downloader.cpp +++ b/src/AppInstallerCommonCore/Downloader.cpp @@ -9,6 +9,7 @@ #include "Public/AppInstallerLogging.h" #include "Public/AppInstallerTelemetry.h" #include "Public/winget/UserSettings.h" +#include "Public/winget/NetworkSettings.h" #include "Public/winget/Filesystem.h" #include "DODownloader.h" #include "HttpStream/HttpRandomAccessStream.h" @@ -90,14 +91,11 @@ namespace AppInstaller::Utility } } - const ProxyInfo ProxyInfo::NoProxy = {}; - std::optional> WinINetDownloadToStream( const std::string& url, std::ostream& dest, IProgressCallback& progress, - bool computeHash, - const ProxyInfo& proxyInfo) + bool computeHash) { // For AICLI_LOG usages with string literals. #pragma warning(push) @@ -107,13 +105,15 @@ namespace AppInstaller::Utility auto agentWide = Utility::ConvertToUTF16(Runtime::GetDefaultUserAgent().get()); wil::unique_hinternet session; - if (proxyInfo.ProxyUri) + + const auto& proxyUri = Network().GetProxyUri(); + if (proxyUri) { - AICLI_LOG(Core, Info, << "Using proxy " << proxyInfo.ProxyUri.value()); + AICLI_LOG(Core, Info, << "Using proxy " << proxyUri.value()); session.reset(InternetOpen( agentWide.c_str(), INTERNET_OPEN_TYPE_PROXY, - Utility::ConvertToUTF16(proxyInfo.ProxyUri.value()).c_str(), + Utility::ConvertToUTF16(proxyUri.value()).c_str(), NULL, 0)); } @@ -240,7 +240,7 @@ namespace AppInstaller::Utility return result; } - std::map GetHeaders(std::string_view url, const ProxyInfo&) + std::map GetHeaders(std::string_view url) { // TODO: Use proxy info. HttpClient does not support using a custom proxy, only using the system-wide one. AICLI_LOG(Core, Verbose, << "Retrieving headers from url: " << url); @@ -287,12 +287,11 @@ namespace AppInstaller::Utility std::ostream& dest, DownloadType, IProgressCallback& progress, - const ProxyInfo& proxyInfo, bool computeHash, std::optional) { THROW_HR_IF(E_INVALIDARG, url.empty()); - return WinINetDownloadToStream(url, dest, progress, computeHash, proxyInfo); + return WinINetDownloadToStream(url, dest, progress, computeHash); } std::optional> Download( @@ -300,7 +299,6 @@ namespace AppInstaller::Utility const std::filesystem::path& dest, DownloadType type, IProgressCallback& progress, - const ProxyInfo& proxyInfo, bool computeHash, std::optional info) { @@ -317,20 +315,7 @@ namespace AppInstaller::Utility // - WinGetUtil :: Intentionally not using DO at this time if (type == DownloadType::Installer) { - // Determine whether to try DO first or not, as this is the only choice currently supported. - InstallerDownloader setting = User().Get(); - bool useDeliveryOptimization = setting == InstallerDownloader::Default || - setting == InstallerDownloader::DeliveryOptimization; - - // DO does not support specifying a custom proxy. - // When proxy is requested, we switch to wininet - if (useDeliveryOptimization && proxyInfo.ProxyUri) - { - AICLI_LOG(Core, Info, << "Forcing use of wininet for download as DO does not support proxy"); - useDeliveryOptimization = false; - } - - if (useDeliveryOptimization) + if (Network().GetInstallerDownloader() == InstallerDownloader::DeliveryOptimization) { try { @@ -376,7 +361,7 @@ namespace AppInstaller::Utility // Use std::ofstream::app to append to previous empty file so that it will not // create a new file and clear motw. std::ofstream outfile(dest, std::ofstream::binary | std::ofstream::app); - return WinINetDownloadToStream(url, outfile, progress, computeHash, proxyInfo); + return WinINetDownloadToStream(url, outfile, progress, computeHash); } using namespace std::string_view_literals; @@ -521,7 +506,7 @@ namespace AppInstaller::Utility return aesSaveResult; } - Microsoft::WRL::ComPtr GetReadOnlyStreamFromURI(std::string_view uriStr, const ProxyInfo& proxyInfo) + Microsoft::WRL::ComPtr GetReadOnlyStreamFromURI(std::string_view uriStr) { Microsoft::WRL::ComPtr inputStream; if (Utility::IsUrlRemote(uriStr)) @@ -533,7 +518,7 @@ namespace AppInstaller::Utility try { - auto randomAccessStream = httpRandomAccessStream->InitializeAsync(uri, proxyInfo).get(); + auto randomAccessStream = httpRandomAccessStream->InitializeAsync(uri).get(); ::IUnknown* rasAsIUnknown = (::IUnknown*)winrt::get_abi(randomAccessStream); THROW_IF_FAILED(CreateStreamOverRandomAccessStream( diff --git a/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp b/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp index 94e92c6f59..d5e1401965 100644 --- a/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp +++ b/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp @@ -20,7 +20,7 @@ using namespace winrt::Windows::Web::Http::Filters; // The HRESULTs will be mapped to UI error code by the appropriate component namespace AppInstaller::Utility::HttpStream { - std::future> HttpClientWrapper::CreateAsync(const Uri& uri, const ProxyInfo&) + std::future> HttpClientWrapper::CreateAsync(const Uri& uri) { // TODO: Use proxy info. HttpClient does not support using a custom proxy, only using the system-wide one. std::shared_ptr instance = std::make_shared(); diff --git a/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.h b/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.h index e599947a5f..599c171224 100644 --- a/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.h +++ b/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.h @@ -4,11 +4,6 @@ #include #include -namespace AppInstaller::Utility -{ - struct ProxyInfo; -} - namespace AppInstaller::Utility::HttpStream { // Wrapper around HTTP client. When created, an object of this class will send a HTTP @@ -16,7 +11,7 @@ namespace AppInstaller::Utility::HttpStream class HttpClientWrapper { public: - static std::future> CreateAsync(const winrt::Windows::Foundation::Uri& uri, const ProxyInfo& proxyInfo); + static std::future> CreateAsync(const winrt::Windows::Foundation::Uri& uri); std::future DownloadRangeAsync( const ULONG64 startPosition, diff --git a/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.cpp b/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.cpp index d503e0cb31..a2ab0a7821 100644 --- a/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.cpp +++ b/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.cpp @@ -13,13 +13,13 @@ using namespace winrt::Windows::Storage::Streams; // The HRESULTs will be mapped to UI error code by the appropriate component namespace AppInstaller::Utility::HttpStream { - IAsyncOperation HttpRandomAccessStream::InitializeAsync(const Uri& uri, const Utility::ProxyInfo& proxyInfo) + IAsyncOperation HttpRandomAccessStream::InitializeAsync(const Uri& uri) { auto strong_this{ get_strong() }; try { - strong_this->m_httpHelper = co_await HttpClientWrapper::CreateAsync(uri, proxyInfo); + strong_this->m_httpHelper = co_await HttpClientWrapper::CreateAsync(uri); strong_this->m_size = strong_this->m_httpHelper->GetFullFileSize(); strong_this->m_httpLocalCache = std::make_unique(); } diff --git a/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.h b/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.h index ae0ea07ce3..0ed2d0c108 100644 --- a/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.h +++ b/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.h @@ -7,11 +7,6 @@ using namespace std::chrono_literals; -namespace AppInstaller::Utility -{ - struct ProxyInfo; -} - namespace AppInstaller::Utility::HttpStream { // Provides an implementation of a random access stream over HTTP that supports @@ -24,9 +19,7 @@ namespace AppInstaller::Utility::HttpStream winrt::Windows::Storage::Streams::IInputStream> { public: - winrt::Windows::Foundation::IAsyncOperation InitializeAsync( - const winrt::Windows::Foundation::Uri& uri, - const ProxyInfo& proxyInfo); + winrt::Windows::Foundation::IAsyncOperation InitializeAsync(const winrt::Windows::Foundation::Uri& uri); uint64_t Size() const; void Size(uint64_t value); uint64_t Position() const; diff --git a/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp b/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp index 87d4ec2598..bd769a4d33 100644 --- a/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp +++ b/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp @@ -60,7 +60,7 @@ namespace AppInstaller::Manifest AICLI_LOG(Core, Info, << "Start downloading installer"); auto tempFile = Runtime::GetNewTempFilePath(); ProgressCallback emptyCallback; - Utility::Download(installerUrl, tempFile, Utility::DownloadType::Installer, emptyCallback, Utility::ProxyInfo::NoProxy); + Utility::Download(installerUrl, tempFile, Utility::DownloadType::Installer, emptyCallback); m_downloadedInstallers.push_back(tempFile); return tempFile; } @@ -78,7 +78,7 @@ namespace AppInstaller::Manifest try { AICLI_LOG(Core, Info, << "Fetching Msix info from installer url"); - return std::make_shared(installerUrl, Utility::ProxyInfo::NoProxy); + return std::make_shared(installerUrl); } catch (...) { diff --git a/src/AppInstallerCommonCore/MsixInfo.cpp b/src/AppInstallerCommonCore/MsixInfo.cpp index c744d5e1b1..c27d606136 100644 --- a/src/AppInstallerCommonCore/MsixInfo.cpp +++ b/src/AppInstallerCommonCore/MsixInfo.cpp @@ -528,9 +528,9 @@ namespace AppInstaller::Msix return { std::move(certContext), std::move(certStore) }; } - MsixInfo::MsixInfo(std::string_view uriStr, const Utility::ProxyInfo& proxyInfo) + MsixInfo::MsixInfo(std::string_view uriStr) { - m_stream = Utility::GetReadOnlyStreamFromURI(uriStr, proxyInfo); + m_stream = Utility::GetReadOnlyStreamFromURI(uriStr); if (GetBundleReader(m_stream.Get(), &m_bundleReader)) { diff --git a/src/AppInstallerCommonCore/NetworkSettings.cpp b/src/AppInstallerCommonCore/NetworkSettings.cpp new file mode 100644 index 0000000000..59a6dfe7ef --- /dev/null +++ b/src/AppInstallerCommonCore/NetworkSettings.cpp @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "winget/NetworkSettings.h" +#include "winget/AdminSettings.h" +#include "AppInstallerLogging.h" + +namespace AppInstaller::Settings +{ + void NetworkSettings::SetProxyUri(const std::optional& proxyUri) + { + AICLI_LOG(Core, Info, << "Setting proxy"); + + // Get the default proxy + m_proxyUri = GetAdminSetting(StringAdminSetting::DefaultProxy); + AICLI_LOG(Core, Info, << "Default proxy is " << (m_proxyUri ? m_proxyUri.value() : "not set")); + + if (proxyUri) + { + m_proxyUri = proxyUri.value(); + AICLI_LOG(Core, Info, << "New value for proxy is " << m_proxyUri.value()); + } + else + { + m_proxyUri.reset(); + AICLI_LOG(Core, Info, << "Proxy will not be used"); + } + } + + InstallerDownloader NetworkSettings::GetInstallerDownloader() const + { + // The default is DeliveryOptimization. + // We only use WinINet if specified by settings, or if we want to use proxy (as DO does not support that) + InstallerDownloader setting = User().Get(); + + if (setting != InstallerDownloader::WinInet && m_proxyUri) + { + AICLI_LOG(Core, Info, << "Forcing use of wininet for download as DO does not support proxy"); + return InstallerDownloader::WinInet; + } + else // Default or DO + { + return InstallerDownloader::DeliveryOptimization; + } + } + + NetworkSettings::NetworkSettings() + { + SetProxyUri(std::nullopt); + } + + NetworkSettings& NetworkSettings::Instance() + { + static NetworkSettings networkSettings; + return networkSettings; + } + + NetworkSettings& Network() + { + return NetworkSettings::Instance(); + } +} \ No newline at end of file diff --git a/src/AppInstallerCommonCore/Public/AppInstallerDownloader.h b/src/AppInstallerCommonCore/Public/AppInstallerDownloader.h index 5f5fdee954..1850a44be6 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerDownloader.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerDownloader.h @@ -36,16 +36,6 @@ namespace AppInstaller::Utility std::string ContentId; }; - // Details on the proxy to use for the download - struct ProxyInfo - { - std::optional ProxyUri; - - // Represents configuration to not use a proxy. - // Used to track all the places where we do not support proxy yet. - static const ProxyInfo NoProxy; - }; - // An exception that indicates that a remote service is too busy/unavailable and may contain data on when to try again. struct ServiceUnavailableException : public wil::ResultException { @@ -67,7 +57,6 @@ namespace AppInstaller::Utility std::ostream& dest, DownloadType type, IProgressCallback& progress, - const ProxyInfo& proxyInfo, bool computeHash = false, std::optional downloadInfo = {}); @@ -81,12 +70,11 @@ namespace AppInstaller::Utility const std::filesystem::path& dest, DownloadType type, IProgressCallback& progress, - const ProxyInfo& proxyInfo, bool computeHash = false, std::optional downloadInfo = {}); // Gets the headers for the given URL. - std::map GetHeaders(std::string_view url, const ProxyInfo& proxyInfo); + std::map GetHeaders(std::string_view url); // Determines if the given url is a remote location. bool IsUrlRemote(std::string_view url); @@ -107,7 +95,7 @@ namespace AppInstaller::Utility HRESULT ApplyMotwUsingIAttachmentExecuteIfApplicable(const std::filesystem::path& filePath, const std::string& source, URLZONE zoneIfScanFailure); // Function to read-only create a stream from a uri string (url address or file system path) - ::Microsoft::WRL::ComPtr GetReadOnlyStreamFromURI(std::string_view uriStr, const ProxyInfo& proxyInfo); + ::Microsoft::WRL::ComPtr GetReadOnlyStreamFromURI(std::string_view uriStr); // Gets the retry after value in terms of a delay in seconds. std::chrono::seconds GetRetryAfter(const std::wstring& retryAfter); diff --git a/src/AppInstallerCommonCore/Public/AppInstallerMsixInfo.h b/src/AppInstallerCommonCore/Public/AppInstallerMsixInfo.h index 00263ef308..8d52581b75 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerMsixInfo.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerMsixInfo.h @@ -17,11 +17,6 @@ #include #include -namespace AppInstaller::Utility -{ - struct ProxyInfo; -} - namespace AppInstaller::Msix { // Function to create an AppxBundle package reader given the input file name. @@ -54,10 +49,10 @@ namespace AppInstaller::Msix // MsixInfo class handles all appx/msix related query. struct MsixInfo { - MsixInfo(std::string_view uriStr, const Utility::ProxyInfo& proxyInfo); + MsixInfo(std::string_view uriStr); template, int> = 0> - MsixInfo(const T& path) : MsixInfo(path.u8string(), Utility::ProxyInfo::NoProxy) {} + MsixInfo(const T& path) : MsixInfo(path.u8string()) {} MsixInfo(const MsixInfo&) = default; MsixInfo& operator=(const MsixInfo&) = default; diff --git a/src/AppInstallerCommonCore/Public/winget/NetworkSettings.h b/src/AppInstallerCommonCore/Public/winget/NetworkSettings.h new file mode 100644 index 0000000000..496346d883 --- /dev/null +++ b/src/AppInstallerCommonCore/Public/winget/NetworkSettings.h @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once + +#include +#include +#include "winget/UserSettings.h" + +namespace AppInstaller::Settings +{ + // Network related settings. + // Merges information from user settings, admin settings, command line, and group policy. + struct NetworkSettings + { + static NetworkSettings& Instance(); + + const std::optional GetProxyUri() const { return m_proxyUri; } + // Sets the proxy URI; may do nothing depending on admin settings and group policy + void SetProxyUri(const std::optional& proxyUri); + + InstallerDownloader GetInstallerDownloader() const; + + protected: + NetworkSettings(); + ~NetworkSettings() = default; + + std::optional m_proxyUri; + }; + + NetworkSettings& Network(); +} \ No newline at end of file diff --git a/src/AppInstallerRepositoryCore/ISource.h b/src/AppInstallerRepositoryCore/ISource.h index 2d070b01a6..5dc609ee1d 100644 --- a/src/AppInstallerRepositoryCore/ISource.h +++ b/src/AppInstallerRepositoryCore/ISource.h @@ -4,11 +4,6 @@ #include "Public/winget/RepositorySource.h" #include -namespace AppInstaller::Utility -{ - struct ProxyInfo; -} - namespace AppInstaller::Repository { // To allow for runtime casting from ISource to the specific types, this enum contains all of the ISource implementations. diff --git a/src/AppInstallerRepositoryCore/InstallerMetadataCollectionContext.cpp b/src/AppInstallerRepositoryCore/InstallerMetadataCollectionContext.cpp index 055c5df19d..0a343648ba 100644 --- a/src/AppInstallerRepositoryCore/InstallerMetadataCollectionContext.cpp +++ b/src/AppInstallerRepositoryCore/InstallerMetadataCollectionContext.cpp @@ -831,7 +831,7 @@ namespace AppInstaller::Repository::Metadata { try { - auto downloadHash = DownloadToStream(utf8Uri, jsonStream, DownloadType::InstallerMetadataCollectionInput, emptyCallback, Utility::ProxyInfo::NoProxy); + auto downloadHash = DownloadToStream(utf8Uri, jsonStream, DownloadType::InstallerMetadataCollectionInput, emptyCallback); break; } catch (...) diff --git a/src/AppInstallerRepositoryCore/Microsoft/PreIndexedPackageSourceFactory.cpp b/src/AppInstallerRepositoryCore/Microsoft/PreIndexedPackageSourceFactory.cpp index 0b0c919aae..c1dd214a62 100644 --- a/src/AppInstallerRepositoryCore/Microsoft/PreIndexedPackageSourceFactory.cpp +++ b/src/AppInstallerRepositoryCore/Microsoft/PreIndexedPackageSourceFactory.cpp @@ -72,7 +72,7 @@ namespace AppInstaller::Repository::Microsoft try { - m_msixInfo = std::make_unique(m_packageLocation, details.ProxyInfo); + m_msixInfo = std::make_unique(m_packageLocation); return; } catch (...) @@ -89,7 +89,7 @@ namespace AppInstaller::Repository::Microsoft try { - m_msixInfo = std::make_unique(m_packageLocation, details.ProxyInfo); + m_msixInfo = std::make_unique(m_packageLocation); return; } CATCH_LOG_MSG("PreIndexedPackageInfo failed on alternate location"); @@ -118,7 +118,7 @@ namespace AppInstaller::Repository::Microsoft try { - m_availableVersion = GetAvailableVersionFrom(m_packageLocation, details.ProxyInfo); + m_availableVersion = GetAvailableVersionFrom(m_packageLocation); return; } catch (...) @@ -136,7 +136,7 @@ namespace AppInstaller::Repository::Microsoft try { - m_availableVersion = GetAvailableVersionFrom(m_packageLocation, details.ProxyInfo); + m_availableVersion = GetAvailableVersionFrom(m_packageLocation); return; } CATCH_LOG_MSG("PreIndexedPackageUpdateCheck failed on alternate location"); @@ -151,11 +151,11 @@ namespace AppInstaller::Repository::Microsoft std::string m_packageLocation; Msix::PackageVersion m_availableVersion; - Msix::PackageVersion GetAvailableVersionFrom(const std::string& packageLocation, const Utility::ProxyInfo& proxyInfo) + Msix::PackageVersion GetAvailableVersionFrom(const std::string& packageLocation) { if (Utility::IsUrlRemote(packageLocation)) { - std::map headers = Utility::GetHeaders(packageLocation, proxyInfo); + std::map headers = Utility::GetHeaders(packageLocation); auto itr = headers.find(std::string{ s_PreIndexedPackageSourceFactory_PackageVersionHeader }); if (itr != headers.end()) { @@ -176,7 +176,7 @@ namespace AppInstaller::Repository::Microsoft } AICLI_LOG(Repo, Verbose, << "Reading package data to determine version"); - Msix::MsixInfo info{ packageLocation, proxyInfo }; + Msix::MsixInfo info{ packageLocation }; auto manifest = info.GetAppPackageManifests(); THROW_HR_IF(APPINSTALLER_CLI_ERROR_PACKAGE_IS_BUNDLE, manifest.size() > 1); @@ -476,7 +476,6 @@ namespace AppInstaller::Repository::Microsoft private: SourceDetails m_details; - Utility::ProxyInfo m_proxyInfo; }; // Source factory for running within a packaged context @@ -504,7 +503,7 @@ namespace AppInstaller::Repository::Microsoft localFile = Runtime::GetPathTo(Runtime::PathName::Temp); localFile /= GetPackageFamilyNameFromDetails(details) + ".msix"; - Utility::Download(packageLocation, localFile, Utility::DownloadType::Index, progress, details.ProxyInfo); + Utility::Download(packageLocation, localFile, Utility::DownloadType::Index, progress); } else { @@ -632,7 +631,6 @@ namespace AppInstaller::Repository::Microsoft private: SourceDetails m_details; - Utility::ProxyInfo m_proxyInfo; }; // Source factory for running outside of a package. @@ -671,7 +669,7 @@ namespace AppInstaller::Repository::Microsoft if (Utility::IsUrlRemote(packageLocation)) { - AppInstaller::Utility::Download(packageLocation, tempPackagePath, AppInstaller::Utility::DownloadType::Index, progress, details.ProxyInfo); + AppInstaller::Utility::Download(packageLocation, tempPackagePath, AppInstaller::Utility::DownloadType::Index, progress); } else { diff --git a/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.cpp b/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.cpp index d21c17dd20..34f7d8bd7e 100644 --- a/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.cpp +++ b/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndexSource.cpp @@ -86,7 +86,7 @@ namespace AppInstaller::Repository::Microsoft HRESULT primaryHR = S_OK; try { - return GetManifestFromArgAndRelativePath(source->GetDetails().Arg, relativePathOpt.value(), manifestSHA256, source->GetDetails().ProxyInfo); + return GetManifestFromArgAndRelativePath(source->GetDetails().Arg, relativePathOpt.value(), manifestSHA256); } catch (...) { @@ -100,7 +100,7 @@ namespace AppInstaller::Repository::Microsoft // Try alternate location try { - return GetManifestFromArgAndRelativePath(source->GetDetails().AlternateArg, relativePathOpt.value(), manifestSHA256, source->GetDetails().ProxyInfo); + return GetManifestFromArgAndRelativePath(source->GetDetails().AlternateArg, relativePathOpt.value(), manifestSHA256); } CATCH_LOG_MSG("GetManifest failed on alternate location"); @@ -126,7 +126,7 @@ namespace AppInstaller::Repository::Microsoft } private: - static Manifest::Manifest GetManifestFromArgAndRelativePath(const std::string& arg, const std::string& relativePath, const SHA256::HashBuffer& expectedHash, const Utility::ProxyInfo& proxyInfo) + static Manifest::Manifest GetManifestFromArgAndRelativePath(const std::string& arg, const std::string& relativePath, const SHA256::HashBuffer& expectedHash) { std::string fullPath = arg; if (fullPath.back() != '/') @@ -148,7 +148,7 @@ namespace AppInstaller::Repository::Microsoft { try { - auto downloadHash = Utility::DownloadToStream(fullPath, manifestStream, Utility::DownloadType::Manifest, emptyCallback, proxyInfo, !expectedHash.empty()); + auto downloadHash = Utility::DownloadToStream(fullPath, manifestStream, Utility::DownloadType::Manifest, emptyCallback, !expectedHash.empty()); if (!expectedHash.empty() && (!downloadHash || downloadHash->size() != expectedHash.size() || !std::equal(expectedHash.begin(), expectedHash.end(), downloadHash->begin()))) diff --git a/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h b/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h index cf8e46d7e4..c48746a53d 100644 --- a/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h +++ b/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h @@ -133,9 +133,6 @@ namespace AppInstaller::Repository // The configuration of how the server certificate will be validated. Certificates::PinningConfiguration CertificatePinningConfiguration; - // Proxy to use when talking to the source - Utility::ProxyInfo ProxyInfo = {}; - // This value is used as an alternative to the `Arg` value if it is failing to function properly. // The alternate location must point to identical data or inconsistencies may arise. std::string AlternateArg; @@ -257,9 +254,6 @@ namespace AppInstaller::Repository // Set authentication arguments. Must be set before Open to have effect. void SetAuthenticationArguments(Authentication::AuthenticationArguments args); - // Set proxy info. Must be set before Open to have effect. - void SetProxyInfo(const Utility::ProxyInfo& proxyInfo); - // Set background update check interval. void SetBackgroundUpdateInterval(TimeSpan interval); diff --git a/src/AppInstallerRepositoryCore/RepositorySource.cpp b/src/AppInstallerRepositoryCore/RepositorySource.cpp index 0b962ccf08..f3899b104c 100644 --- a/src/AppInstallerRepositoryCore/RepositorySource.cpp +++ b/src/AppInstallerRepositoryCore/RepositorySource.cpp @@ -568,14 +568,6 @@ namespace AppInstaller::Repository } } - void Source::SetProxyInfo(const Utility::ProxyInfo& proxyInfo) - { - for (auto& sourceReference : m_sourceReferences) - { - sourceReference->GetDetails().ProxyInfo = proxyInfo; - } - } - void Source::SetBackgroundUpdateInterval(TimeSpan interval) { m_backgroundUpdateInterval = interval; diff --git a/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp b/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp index d523e0caa1..f4aa943c87 100644 --- a/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp +++ b/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp @@ -4,6 +4,7 @@ #include "RestSourceFactory.h" #include "RestClient.h" #include "RestSource.h" +#include using namespace std::string_literals; using namespace std::string_view_literals; @@ -61,10 +62,11 @@ namespace AppInstaller::Repository::Rest [&]() { m_httpClientHelper.SetPinningConfiguration(m_details.CertificatePinningConfiguration); - if (m_details.ProxyInfo.ProxyUri) + const auto& proxyUri = Settings::Network().GetProxyUri(); + if (proxyUri) { - AICLI_LOG(Repo, Info, << "Setting proxy for REST source to " << m_details.ProxyInfo.ProxyUri.value()); - m_httpClientHelper.SetProxy(Utility::ConvertToUTF16(m_details.ProxyInfo.ProxyUri.value())); + AICLI_LOG(Repo, Info, << "Setting proxy for REST source to " << proxyUri.value()); + m_httpClientHelper.SetProxy(Utility::ConvertToUTF16(proxyUri.value())); } else { diff --git a/src/WinGetUtil/Exports.cpp b/src/WinGetUtil/Exports.cpp index 5b2a09c79f..a01c592547 100644 --- a/src/WinGetUtil/Exports.cpp +++ b/src/WinGetUtil/Exports.cpp @@ -490,7 +490,7 @@ extern "C" THROW_HR_IF(E_INVALIDARG, computeHash && sha256HashLength != 32); AppInstaller::ProgressCallback callback; - auto hashValue = Download(ConvertToUTF8(url), filePath, DownloadType::WinGetUtil, callback, ProxyInfo::NoProxy, computeHash); + auto hashValue = Download(ConvertToUTF8(url), filePath, DownloadType::WinGetUtil, callback, computeHash); // At this point, if computeHash is set we have verified that the buffer is valid and 32 bytes. if (computeHash) From 48872d5424096c8eb3caad5104bd52ceee0f269b Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Thu, 29 Feb 2024 12:03:08 -0800 Subject: [PATCH 20/32] Make proxy arguments common --- src/AppInstallerCLICore/Argument.cpp | 2 ++ src/AppInstallerCLICore/Commands/DownloadCommand.cpp | 2 -- src/AppInstallerCLICore/Commands/ImportCommand.cpp | 2 -- src/AppInstallerCLICore/Commands/InstallCommand.cpp | 2 -- src/AppInstallerCLICore/Commands/ListCommand.cpp | 2 -- src/AppInstallerCLICore/Commands/SearchCommand.cpp | 2 -- src/AppInstallerCLICore/Commands/ShowCommand.cpp | 2 -- src/AppInstallerCLICore/Commands/SourceCommand.cpp | 4 ---- src/AppInstallerCLICore/Commands/UninstallCommand.cpp | 2 -- src/AppInstallerCLICore/Commands/UpgradeCommand.cpp | 2 -- 10 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/AppInstallerCLICore/Argument.cpp b/src/AppInstallerCLICore/Argument.cpp index 2f47eb1013..6299beb909 100644 --- a/src/AppInstallerCLICore/Argument.cpp +++ b/src/AppInstallerCLICore/Argument.cpp @@ -407,6 +407,8 @@ namespace AppInstaller::CLI args.push_back(ForType(Args::Type::RetroStyle)); args.push_back(ForType(Args::Type::VerboseLogs)); args.emplace_back(Args::Type::DisableInteractivity, Resource::String::DisableInteractivityArgumentDescription, ArgumentType::Flag, false); + args.push_back(ForType(Args::Type::Proxy)); + args.push_back(ForType(Args::Type::NoProxy)); } std::string Argument::GetUsageString() const diff --git a/src/AppInstallerCLICore/Commands/DownloadCommand.cpp b/src/AppInstallerCLICore/Commands/DownloadCommand.cpp index bce785f6f9..b2b7d3ec15 100644 --- a/src/AppInstallerCLICore/Commands/DownloadCommand.cpp +++ b/src/AppInstallerCLICore/Commands/DownloadCommand.cpp @@ -36,8 +36,6 @@ namespace AppInstaller::CLI Argument::ForType(Args::Type::CustomHeader), Argument::ForType(Args::Type::AuthenticationMode), Argument::ForType(Args::Type::AuthenticationAccount), - Argument::ForType(Args::Type::Proxy), - Argument::ForType(Args::Type::NoProxy), Argument::ForType(Args::Type::AcceptPackageAgreements), Argument::ForType(Args::Type::AcceptSourceAgreements), }; diff --git a/src/AppInstallerCLICore/Commands/ImportCommand.cpp b/src/AppInstallerCLICore/Commands/ImportCommand.cpp index 7c024e666b..744599c1d5 100644 --- a/src/AppInstallerCLICore/Commands/ImportCommand.cpp +++ b/src/AppInstallerCLICore/Commands/ImportCommand.cpp @@ -19,8 +19,6 @@ namespace AppInstaller::CLI Argument{ Execution::Args::Type::IgnoreUnavailable, Resource::String::ImportIgnoreUnavailableArgumentDescription, ArgumentType::Flag }, Argument{ Execution::Args::Type::IgnoreVersions, Resource::String::ImportIgnorePackageVersionsArgumentDescription, ArgumentType::Flag }, Argument::ForType(Execution::Args::Type::NoUpgrade), - Argument::ForType(Execution::Args::Type::Proxy), - Argument::ForType(Execution::Args::Type::NoProxy), Argument::ForType(Execution::Args::Type::AcceptPackageAgreements), Argument::ForType(Execution::Args::Type::AcceptSourceAgreements), }; diff --git a/src/AppInstallerCLICore/Commands/InstallCommand.cpp b/src/AppInstallerCLICore/Commands/InstallCommand.cpp index a7bf51dbb7..097719e70c 100644 --- a/src/AppInstallerCLICore/Commands/InstallCommand.cpp +++ b/src/AppInstallerCLICore/Commands/InstallCommand.cpp @@ -55,8 +55,6 @@ namespace AppInstaller::CLI Argument::ForType(Args::Type::Rename), Argument::ForType(Args::Type::UninstallPrevious), Argument::ForType(Args::Type::Force), - Argument::ForType(Args::Type::Proxy), - Argument::ForType(Args::Type::NoProxy), Argument{ Args::Type::IncludeUnknown, Resource::String::IncludeUnknownArgumentDescription, ArgumentType::Flag, Argument::Visibility::Hidden}, }; } diff --git a/src/AppInstallerCLICore/Commands/ListCommand.cpp b/src/AppInstallerCLICore/Commands/ListCommand.cpp index 6423d6767e..93c5798498 100644 --- a/src/AppInstallerCLICore/Commands/ListCommand.cpp +++ b/src/AppInstallerCLICore/Commands/ListCommand.cpp @@ -27,8 +27,6 @@ namespace AppInstaller::CLI Argument::ForType(Execution::Args::Type::CustomHeader), Argument::ForType(Execution::Args::Type::AuthenticationMode), Argument::ForType(Execution::Args::Type::AuthenticationAccount), - Argument::ForType(Execution::Args::Type::Proxy), - Argument::ForType(Execution::Args::Type::NoProxy), Argument::ForType(Execution::Args::Type::AcceptSourceAgreements), Argument{ Execution::Args::Type::Upgrade, Resource::String::UpgradeArgumentDescription, ArgumentType::Flag, Argument::Visibility::Help }, Argument{ Execution::Args::Type::IncludeUnknown, Resource::String::IncludeUnknownInListArgumentDescription, ArgumentType::Flag }, diff --git a/src/AppInstallerCLICore/Commands/SearchCommand.cpp b/src/AppInstallerCLICore/Commands/SearchCommand.cpp index ed509f4011..0ae547d302 100644 --- a/src/AppInstallerCLICore/Commands/SearchCommand.cpp +++ b/src/AppInstallerCLICore/Commands/SearchCommand.cpp @@ -27,8 +27,6 @@ namespace AppInstaller::CLI Argument::ForType(Execution::Args::Type::CustomHeader), Argument::ForType(Execution::Args::Type::AuthenticationMode), Argument::ForType(Execution::Args::Type::AuthenticationAccount), - Argument::ForType(Execution::Args::Type::Proxy), - Argument::ForType(Execution::Args::Type::NoProxy), Argument::ForType(Execution::Args::Type::AcceptSourceAgreements), Argument::ForType(Execution::Args::Type::ListVersions), }; diff --git a/src/AppInstallerCLICore/Commands/ShowCommand.cpp b/src/AppInstallerCLICore/Commands/ShowCommand.cpp index aeef920b16..76198a9699 100644 --- a/src/AppInstallerCLICore/Commands/ShowCommand.cpp +++ b/src/AppInstallerCLICore/Commands/ShowCommand.cpp @@ -33,8 +33,6 @@ namespace AppInstaller::CLI Argument::ForType(Execution::Args::Type::CustomHeader), Argument::ForType(Execution::Args::Type::AuthenticationMode), Argument::ForType(Execution::Args::Type::AuthenticationAccount), - Argument::ForType(Execution::Args::Type::Proxy), - Argument::ForType(Execution::Args::Type::NoProxy), Argument::ForType(Execution::Args::Type::AcceptSourceAgreements), }; } diff --git a/src/AppInstallerCLICore/Commands/SourceCommand.cpp b/src/AppInstallerCLICore/Commands/SourceCommand.cpp index f15b6f035e..cd44ffaef5 100644 --- a/src/AppInstallerCLICore/Commands/SourceCommand.cpp +++ b/src/AppInstallerCLICore/Commands/SourceCommand.cpp @@ -53,8 +53,6 @@ namespace AppInstaller::CLI Argument::ForType(Args::Type::SourceArg), Argument::ForType(Args::Type::SourceType), Argument::ForType(Args::Type::CustomHeader), - Argument::ForType(Args::Type::Proxy), - Argument::ForType(Args::Type::NoProxy), Argument::ForType(Args::Type::AcceptSourceAgreements), }; } @@ -128,8 +126,6 @@ namespace AppInstaller::CLI { return { Argument::ForType(Args::Type::SourceName), - Argument::ForType(Execution::Args::Type::Proxy), - Argument::ForType(Execution::Args::Type::NoProxy), }; } diff --git a/src/AppInstallerCLICore/Commands/UninstallCommand.cpp b/src/AppInstallerCLICore/Commands/UninstallCommand.cpp index 870f84895a..a0b0ae91a8 100644 --- a/src/AppInstallerCLICore/Commands/UninstallCommand.cpp +++ b/src/AppInstallerCLICore/Commands/UninstallCommand.cpp @@ -37,8 +37,6 @@ namespace AppInstaller::CLI Argument::ForType(Args::Type::CustomHeader), Argument::ForType(Args::Type::AuthenticationMode), Argument::ForType(Args::Type::AuthenticationAccount), - Argument::ForType(Args::Type::Proxy), - Argument::ForType(Args::Type::NoProxy), Argument::ForType(Args::Type::AcceptSourceAgreements), }; } diff --git a/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp b/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp index 104057b249..a5c2701ae2 100644 --- a/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp +++ b/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp @@ -73,8 +73,6 @@ namespace AppInstaller::CLI Argument{ Args::Type::IncludePinned, Resource::String::IncludePinnedArgumentDescription, ArgumentType::Flag}, Argument::ForType(Args::Type::UninstallPrevious), Argument::ForType(Args::Type::Force), - Argument::ForType(Args::Type::Proxy), - Argument::ForType(Args::Type::NoProxy), }; } From 87dba88e30923503e50e352081b7ea394092c699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Flor=20Chac=C3=B3n?= <14323496+florelis@users.noreply.github.com> Date: Mon, 11 Mar 2024 11:57:30 -0700 Subject: [PATCH 21/32] Update doc/admx/en-US/DesktopAppInstaller.adml Co-authored-by: yao-msft <50888816+yao-msft@users.noreply.github.com> --- doc/admx/en-US/DesktopAppInstaller.adml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/admx/en-US/DesktopAppInstaller.adml b/doc/admx/en-US/DesktopAppInstaller.adml index 55e028222e..848ba6be70 100644 --- a/doc/admx/en-US/DesktopAppInstaller.adml +++ b/doc/admx/en-US/DesktopAppInstaller.adml @@ -135,7 +135,8 @@ If you enable this setting, the specified proxy will be used by default. - + + From d20d685d438ed8631f19a9a9fa1784cdd0a8f581 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Mon, 11 Mar 2024 12:59:21 -0700 Subject: [PATCH 22/32] Fix set default proxy --- doc/admx/en-US/DesktopAppInstaller.adml | 1 - src/AppInstallerCLICore/ExecutionContextData.h | 1 - src/AppInstallerCommonCore/NetworkSettings.cpp | 8 +++----- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/doc/admx/en-US/DesktopAppInstaller.adml b/doc/admx/en-US/DesktopAppInstaller.adml index 848ba6be70..5c3142ab6b 100644 --- a/doc/admx/en-US/DesktopAppInstaller.adml +++ b/doc/admx/en-US/DesktopAppInstaller.adml @@ -136,7 +136,6 @@ If you enable this setting, the specified proxy will be used by default. - diff --git a/src/AppInstallerCLICore/ExecutionContextData.h b/src/AppInstallerCLICore/ExecutionContextData.h index 0e7ae79e00..b1f5e42110 100644 --- a/src/AppInstallerCLICore/ExecutionContextData.h +++ b/src/AppInstallerCLICore/ExecutionContextData.h @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. #pragma once -#include #include #include #include diff --git a/src/AppInstallerCommonCore/NetworkSettings.cpp b/src/AppInstallerCommonCore/NetworkSettings.cpp index 59a6dfe7ef..34ef02d5bf 100644 --- a/src/AppInstallerCommonCore/NetworkSettings.cpp +++ b/src/AppInstallerCommonCore/NetworkSettings.cpp @@ -11,10 +11,6 @@ namespace AppInstaller::Settings { AICLI_LOG(Core, Info, << "Setting proxy"); - // Get the default proxy - m_proxyUri = GetAdminSetting(StringAdminSetting::DefaultProxy); - AICLI_LOG(Core, Info, << "Default proxy is " << (m_proxyUri ? m_proxyUri.value() : "not set")); - if (proxyUri) { m_proxyUri = proxyUri.value(); @@ -46,7 +42,9 @@ namespace AppInstaller::Settings NetworkSettings::NetworkSettings() { - SetProxyUri(std::nullopt); + // Get the default proxy + m_proxyUri = GetAdminSetting(StringAdminSetting::DefaultProxy); + AICLI_LOG(Core, Info, << "Default proxy is " << (m_proxyUri ? m_proxyUri.value() : "not set")); } NetworkSettings& NetworkSettings::Instance() From 0d9284273cf2d9ca7804310ba4ecf2c08055dfd2 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Mon, 11 Mar 2024 13:06:14 -0700 Subject: [PATCH 23/32] Move setting proxy to HttpClientHelper constructor --- .../Rest/RestSourceFactory.cpp | 12 ----------- .../Rest/Schema/HttpClientHelper.cpp | 21 +++++++++++++------ .../Rest/Schema/HttpClientHelper.h | 2 -- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp b/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp index f4aa943c87..ff9be0ddbb 100644 --- a/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp +++ b/src/AppInstallerRepositoryCore/Rest/RestSourceFactory.cpp @@ -4,7 +4,6 @@ #include "RestSourceFactory.h" #include "RestClient.h" #include "RestSource.h" -#include using namespace std::string_literals; using namespace std::string_view_literals; @@ -62,17 +61,6 @@ namespace AppInstaller::Repository::Rest [&]() { m_httpClientHelper.SetPinningConfiguration(m_details.CertificatePinningConfiguration); - const auto& proxyUri = Settings::Network().GetProxyUri(); - if (proxyUri) - { - AICLI_LOG(Repo, Info, << "Setting proxy for REST source to " << proxyUri.value()); - m_httpClientHelper.SetProxy(Utility::ConvertToUTF16(proxyUri.value())); - } - else - { - AICLI_LOG(Repo, Info, << "REST source does not use proxy"); - } - auto sourceInformation = RestClient::GetInformation(m_details.Arg, m_customHeader, m_caller, m_httpClientHelper); m_details.Identifier = sourceInformation.SourceIdentifier; diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.cpp b/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.cpp index 403f233537..8d4c316171 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.cpp +++ b/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT License. #include "pch.h" #include "HttpClientHelper.h" +#include namespace AppInstaller::Repository::Rest::Schema { @@ -42,7 +43,20 @@ namespace AppInstaller::Repository::Rest::Schema } } - HttpClientHelper::HttpClientHelper(std::shared_ptr stage) : m_defaultRequestHandlerStage(std::move(stage)) {} + HttpClientHelper::HttpClientHelper(std::shared_ptr stage) + : m_defaultRequestHandlerStage(std::move(stage)) + { + const auto& proxyUri = Settings::Network().GetProxyUri(); + if (proxyUri) + { + AICLI_LOG(Repo, Info, << "Setting proxy for REST HTTP Client helper to " << proxyUri.value()); + m_clientConfig.set_proxy(web::web_proxy{ Utility::ConvertToUTF16(proxyUri.value()) }); + } + else + { + AICLI_LOG(Repo, Info, << "REST HTTP Client helper does not use proxy"); + } + } pplx::task HttpClientHelper::Post( const utility::string_t& uri, @@ -139,11 +153,6 @@ namespace AppInstaller::Repository::Rest::Schema }); } - void HttpClientHelper::SetProxy(const utility::string_t& uri) - { - m_clientConfig.set_proxy(web::web_proxy{ uri }); - } - web::http::client::http_client HttpClientHelper::GetClient(const utility::string_t& uri) const { web::http::client::http_client client{ uri, m_clientConfig }; diff --git a/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.h b/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.h index 0f0dcaf6e6..9164270713 100644 --- a/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.h +++ b/src/AppInstallerRepositoryCore/Rest/Schema/HttpClientHelper.h @@ -27,8 +27,6 @@ namespace AppInstaller::Repository::Rest::Schema void SetPinningConfiguration(const Certificates::PinningConfiguration& configuration); - void SetProxy(const utility::string_t& proxyUri); - protected: std::optional ValidateAndExtractResponse(const web::http::http_response& response) const; From 84fb0da0f5b85d845c2c34946bdf7d5efe8575f9 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Mon, 11 Mar 2024 13:09:48 -0700 Subject: [PATCH 24/32] Add to settings.md --- doc/Settings.md | 11 +++++++++++ .../Public/winget/NetworkSettings.h | 2 ++ .../Public/winget/RepositorySource.h | 1 - 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/Settings.md b/doc/Settings.md index fcd14080b0..628cabcb52 100644 --- a/doc/Settings.md +++ b/doc/Settings.md @@ -312,3 +312,14 @@ You can enable the feature as shown below. "configuration03": true }, ``` + +### proxy + +This feature enables the use of web proxies. +You can enable the feature as shown below. + +```json + "experimentalFeatures": { + "proxy": true + }, +``` diff --git a/src/AppInstallerCommonCore/Public/winget/NetworkSettings.h b/src/AppInstallerCommonCore/Public/winget/NetworkSettings.h index 496346d883..856055fcc8 100644 --- a/src/AppInstallerCommonCore/Public/winget/NetworkSettings.h +++ b/src/AppInstallerCommonCore/Public/winget/NetworkSettings.h @@ -10,6 +10,8 @@ namespace AppInstaller::Settings { // Network related settings. // Merges information from user settings, admin settings, command line, and group policy. + // TODO: This is currently a process global. It should be converted to a thread local + // (like telemetry) once we expose configuring a proxy through the COM API struct NetworkSettings { static NetworkSettings& Instance(); diff --git a/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h b/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h index c48746a53d..33a8acc5bf 100644 --- a/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h +++ b/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h @@ -3,7 +3,6 @@ #pragma once #include #include -#include #include #include #include From 193d2eba9f4cb25488542dcf2f54993c22fb6819 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Mon, 11 Mar 2024 13:10:54 -0700 Subject: [PATCH 25/32] Update settings schema --- schemas/JSON/settings/settings.schema.0.2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schemas/JSON/settings/settings.schema.0.2.json b/schemas/JSON/settings/settings.schema.0.2.json index 743851f379..80e224487b 100644 --- a/schemas/JSON/settings/settings.schema.0.2.json +++ b/schemas/JSON/settings/settings.schema.0.2.json @@ -266,8 +266,8 @@ "type": "boolean", "default": false }, - "configuration": { - "description": "Enable support for configuration", + "configuration03": { + "description": "Enable support for configuration schema 0.3", "type": "boolean", "default": false }, From 25facf15f182d89119c8f3cd7ed021477858bdd1 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Mon, 11 Mar 2024 13:12:10 -0700 Subject: [PATCH 26/32] Fix arg name --- src/AppInstallerCLICore/Commands/SettingsCommand.cpp | 4 ++-- src/AppInstallerCommonCore/Deployment.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp index a03a2c69d6..f428245643 100644 --- a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp +++ b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp @@ -146,7 +146,7 @@ namespace AppInstaller::CLI Utility::LocIndString validOptions = Join(", "_liv, adminSettingList); - if (execArgs.Contains(Execution::Args::Type::AdminSettingEnable) && StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName))) + if (execArgs.Contains(Execution::Args::Type::SettingName) && StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName))) { throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::SettingName).Name, validOptions)); } @@ -192,7 +192,7 @@ namespace AppInstaller::CLI Utility::LocIndString validOptions = Join(", "_liv, adminSettingList); - if (execArgs.Contains(Execution::Args::Type::AdminSettingEnable) && StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName))) + if (execArgs.Contains(Execution::Args::Type::SettingName) && StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName))) { throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::SettingName).Name, validOptions)); } diff --git a/src/AppInstallerCommonCore/Deployment.cpp b/src/AppInstallerCommonCore/Deployment.cpp index f3588b9011..08c5c84b26 100644 --- a/src/AppInstallerCommonCore/Deployment.cpp +++ b/src/AppInstallerCommonCore/Deployment.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT License. #include "pch.h" #include "Public/AppInstallerDeployment.h" -#include "Public/AppInstallerDownloader.h" #include "Public/AppInstallerLogging.h" #include "Public/AppInstallerMsixInfo.h" #include "Public/AppInstallerRuntime.h" From e0fdcf770d26c3289b2370e7ea0df796a7d6dffa Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Mon, 11 Mar 2024 13:26:26 -0700 Subject: [PATCH 27/32] Reset bool admin settings --- .../Commands/SettingsCommand.cpp | 11 +++++++++-- .../Workflows/SettingsFlow.cpp | 19 ++++++++++++------- .../Workflows/WorkflowBase.cpp | 2 -- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp index f428245643..ccc33c73a8 100644 --- a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp +++ b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp @@ -183,8 +183,13 @@ namespace AppInstaller::CLI void SettingsResetCommand::ValidateArgumentsInternal(Execution::Args& execArgs) const { - // Get admin setting string for all available options except Unknown + // Get admin setting string for all available options except Unknown. + // We accept both bool and string settings std::vector adminSettingList; + for (auto setting : GetAllSequentialEnumValues(BoolAdminSetting::Unknown)) + { + adminSettingList.emplace_back(AdminSettingToString(setting)); + } for (auto setting : GetAllSequentialEnumValues(StringAdminSetting::Unknown)) { adminSettingList.emplace_back(AdminSettingToString(setting)); @@ -192,7 +197,9 @@ namespace AppInstaller::CLI Utility::LocIndString validOptions = Join(", "_liv, adminSettingList); - if (execArgs.Contains(Execution::Args::Type::SettingName) && StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName))) + if (execArgs.Contains(Execution::Args::Type::SettingName) + && StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName)) + && BoolAdminSetting::Unknown == StringToBoolAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName))) { throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::SettingName).Name, validOptions)); } diff --git a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp index 99159e72b2..3a48647ffd 100644 --- a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp @@ -86,25 +86,30 @@ namespace AppInstaller::CLI::Workflow StringAdminSetting adminSetting = Settings::StringToStringAdminSetting(adminSettingName); if (Settings::SetAdminSetting(adminSetting, adminSettingValue)) { - context.Reporter.Info() << Resource::String::SetAdminSettingSucceeded(AdminSettingToString(adminSetting), LocIndString{ adminSettingValue }) << std::endl; + context.Reporter.Info() << Resource::String::SetAdminSettingSucceeded(adminSettingName, LocIndString{ adminSettingValue }) << std::endl; } else { - context.Reporter.Error() << Resource::String::SetAdminSettingFailed(AdminSettingToString(adminSetting)) << std::endl; + context.Reporter.Error() << Resource::String::SetAdminSettingFailed(adminSettingName) << std::endl; } } void ResetAdminSetting(Execution::Context& context) { auto adminSettingName = context.Args.GetArg(Execution::Args::Type::SettingName); - StringAdminSetting adminSetting = Settings::StringToStringAdminSetting(adminSettingName); - if (Settings::ResetAdminSetting(adminSetting)) + + // Try as both bool and string setting as we don't know the type + auto boolAdminSetting = Settings::StringToBoolAdminSetting(adminSettingName); + auto stringAdminSetting = Settings::StringToStringAdminSetting(adminSettingName); + + if ((boolAdminSetting != Settings::BoolAdminSetting::Unknown && Settings::DisableAdminSetting(boolAdminSetting)) + || (stringAdminSetting != Settings::StringAdminSetting::Unknown && Settings::ResetAdminSetting(stringAdminSetting))) { - context.Reporter.Info() << Resource::String::ResetAdminSettingSucceeded(AdminSettingToString(adminSetting)) << std::endl; + context.Reporter.Info() << Resource::String::ResetAdminSettingSucceeded(adminSettingName) << std::endl; } - else + else if (stringAdminSetting != Settings::StringAdminSetting::Unknown) { - context.Reporter.Error() << Resource::String::ResetAdminSettingFailed(AdminSettingToString(adminSetting)) << std::endl; + context.Reporter.Error() << Resource::String::ResetAdminSettingFailed(adminSettingName) << std::endl; } } diff --git a/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp b/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp index 9d0ffe0396..b0045126af 100644 --- a/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp +++ b/src/AppInstallerCLICore/Workflows/WorkflowBase.cpp @@ -4,7 +4,6 @@ #include "WorkflowBase.h" #include "ExecutionContext.h" #include "ManifestComparator.h" -#include "DownloadFlow.h" #include "PromptFlow.h" #include "TableOutput.h" #include @@ -13,7 +12,6 @@ #include #include #include -#include using namespace std::string_literals; using namespace AppInstaller::Utility::literals; From 3d8f87a7d27cb322837115e982dfd5b536edf58c Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Mon, 11 Mar 2024 13:37:14 -0700 Subject: [PATCH 28/32] LocIndString --- src/AppInstallerCLICore/Workflows/SettingsFlow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp index 3a48647ffd..5e73ba0b72 100644 --- a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp @@ -86,11 +86,11 @@ namespace AppInstaller::CLI::Workflow StringAdminSetting adminSetting = Settings::StringToStringAdminSetting(adminSettingName); if (Settings::SetAdminSetting(adminSetting, adminSettingValue)) { - context.Reporter.Info() << Resource::String::SetAdminSettingSucceeded(adminSettingName, LocIndString{ adminSettingValue }) << std::endl; + context.Reporter.Info() << Resource::String::SetAdminSettingSucceeded(LocIndString{ adminSettingName }, LocIndString{ adminSettingValue }) << std::endl; } else { - context.Reporter.Error() << Resource::String::SetAdminSettingFailed(adminSettingName) << std::endl; + context.Reporter.Error() << Resource::String::SetAdminSettingFailed(LocIndString{ adminSettingName }) << std::endl; } } @@ -105,11 +105,11 @@ namespace AppInstaller::CLI::Workflow if ((boolAdminSetting != Settings::BoolAdminSetting::Unknown && Settings::DisableAdminSetting(boolAdminSetting)) || (stringAdminSetting != Settings::StringAdminSetting::Unknown && Settings::ResetAdminSetting(stringAdminSetting))) { - context.Reporter.Info() << Resource::String::ResetAdminSettingSucceeded(adminSettingName) << std::endl; + context.Reporter.Info() << Resource::String::ResetAdminSettingSucceeded(LocIndString{ adminSettingName }) << std::endl; } else if (stringAdminSetting != Settings::StringAdminSetting::Unknown) { - context.Reporter.Error() << Resource::String::ResetAdminSettingFailed(adminSettingName) << std::endl; + context.Reporter.Error() << Resource::String::ResetAdminSettingFailed(LocIndString{ adminSettingName }) << std::endl; } } From 48d2ab52ec422f2c1ede18152ddc4e2562e7b69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Flor=20Chac=C3=B3n?= <14323496+florelis@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:32:47 -0700 Subject: [PATCH 29/32] Update src/AppInstallerCLICore/Commands/SettingsCommand.cpp Co-authored-by: yao-msft <50888816+yao-msft@users.noreply.github.com> --- src/AppInstallerCLICore/Commands/SettingsCommand.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp index ccc33c73a8..0cd2451ea2 100644 --- a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp +++ b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp @@ -146,7 +146,8 @@ namespace AppInstaller::CLI Utility::LocIndString validOptions = Join(", "_liv, adminSettingList); - if (execArgs.Contains(Execution::Args::Type::SettingName) && StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName))) + if (StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName)) + { throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::SettingName).Name, validOptions)); } From 97e9415ece4f978258b7da6094da5ac0bd80c12e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Flor=20Chac=C3=B3n?= <14323496+florelis@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:33:26 -0700 Subject: [PATCH 30/32] Update src/AppInstallerCLICore/Workflows/SettingsFlow.cpp Co-authored-by: yao-msft <50888816+yao-msft@users.noreply.github.com> --- src/AppInstallerCLICore/Workflows/SettingsFlow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp index 5e73ba0b72..32e7cc8e54 100644 --- a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp @@ -107,7 +107,8 @@ namespace AppInstaller::CLI::Workflow { context.Reporter.Info() << Resource::String::ResetAdminSettingSucceeded(LocIndString{ adminSettingName }) << std::endl; } - else if (stringAdminSetting != Settings::StringAdminSetting::Unknown) + else + { context.Reporter.Error() << Resource::String::ResetAdminSettingFailed(LocIndString{ adminSettingName }) << std::endl; } From ce47cf58660b53cf06ddce11492dacf62839e831 Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Thu, 14 Mar 2024 13:35:29 -0700 Subject: [PATCH 31/32] PR suggestion --- src/AppInstallerCLICore/Commands/SettingsCommand.cpp | 4 +--- src/AppInstallerCLICore/Workflows/SettingsFlow.cpp | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp index 0cd2451ea2..b0e5ef77a9 100644 --- a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp +++ b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp @@ -147,7 +147,6 @@ namespace AppInstaller::CLI Utility::LocIndString validOptions = Join(", "_liv, adminSettingList); if (StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName)) - { throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::SettingName).Name, validOptions)); } @@ -198,8 +197,7 @@ namespace AppInstaller::CLI Utility::LocIndString validOptions = Join(", "_liv, adminSettingList); - if (execArgs.Contains(Execution::Args::Type::SettingName) - && StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName)) + if (StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName)) && BoolAdminSetting::Unknown == StringToBoolAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName))) { throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::SettingName).Name, validOptions)); diff --git a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp index 32e7cc8e54..49eca405cd 100644 --- a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp @@ -108,7 +108,6 @@ namespace AppInstaller::CLI::Workflow context.Reporter.Info() << Resource::String::ResetAdminSettingSucceeded(LocIndString{ adminSettingName }) << std::endl; } else - { context.Reporter.Error() << Resource::String::ResetAdminSettingFailed(LocIndString{ adminSettingName }) << std::endl; } From fb18813addb19dfd5e9a514ef393c320518de30d Mon Sep 17 00:00:00 2001 From: Flor Elisa Chacon Ochoa Date: Thu, 14 Mar 2024 14:04:08 -0700 Subject: [PATCH 32/32] Missing ) --- src/AppInstallerCLICore/Commands/SettingsCommand.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp index b0e5ef77a9..70620f5bca 100644 --- a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp +++ b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp @@ -146,7 +146,7 @@ namespace AppInstaller::CLI Utility::LocIndString validOptions = Join(", "_liv, adminSettingList); - if (StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName)) + if (StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName))) { throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::SettingName).Name, validOptions)); }