RestSourceFactory.cpp (5880B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "RestSourceFactory.h" 5 #include "RestClient.h" 6 #include "RestSource.h" 7 8 using namespace std::string_literals; 9 using namespace std::string_view_literals; 10 11 namespace AppInstaller::Repository::Rest 12 { 13 namespace 14 { 15 struct RestSourceReference : public ISourceReference 16 { 17 RestSourceReference(const SourceDetails& details) : m_details(details) {} 18 19 SourceDetails& GetDetails() override { return m_details; }; 20 21 std::string GetIdentifier() override 22 { 23 Initialize(); 24 return m_details.Identifier; 25 } 26 27 SourceInformation GetInformation() override 28 { 29 Initialize(); 30 return m_information; 31 } 32 33 // Set custom header. Returns false if custom header is not supported. 34 bool SetCustomHeader(std::optional<std::string> header) override 35 { 36 m_customHeader = header; 37 return true; 38 } 39 40 void SetCaller(std::string caller) override 41 { 42 m_caller = std::move(caller); 43 } 44 45 void SetAuthenticationArguments(Authentication::AuthenticationArguments authArgs) override 46 { 47 m_authArgs = std::move(authArgs); 48 } 49 50 std::shared_ptr<ISource> Open(IProgressCallback&) override 51 { 52 Initialize(); 53 RestClient restClient = RestClient::Create(m_details.Arg, m_customHeader, m_caller, m_httpClientHelper, m_restClientInformation, m_authArgs); 54 return std::make_shared<RestSource>(m_details, m_information, std::move(restClient)); 55 } 56 57 private: 58 void Initialize() 59 { 60 std::call_once(m_initializeFlag, 61 [&]() 62 { 63 m_httpClientHelper.SetPinningConfiguration(m_details.CertificatePinningConfiguration); 64 m_restClientInformation = RestClient::GetInformation(m_details.Arg, m_customHeader, m_caller, m_httpClientHelper); 65 66 m_details.Identifier = m_restClientInformation.SourceIdentifier; 67 68 m_information.UnsupportedPackageMatchFields = m_restClientInformation.UnsupportedPackageMatchFields; 69 m_information.RequiredPackageMatchFields = m_restClientInformation.RequiredPackageMatchFields; 70 m_information.UnsupportedQueryParameters = m_restClientInformation.UnsupportedQueryParameters; 71 m_information.RequiredQueryParameters = m_restClientInformation.RequiredQueryParameters; 72 73 m_information.SourceAgreementsIdentifier = m_restClientInformation.SourceAgreementsIdentifier; 74 for (auto const& agreement : m_restClientInformation.SourceAgreements) 75 { 76 m_information.SourceAgreements.emplace_back(agreement.Label, agreement.Text, agreement.Url); 77 } 78 79 m_information.Authentication = m_restClientInformation.Authentication; 80 }); 81 } 82 83 SourceDetails m_details; 84 Http::HttpClientHelper m_httpClientHelper; 85 SourceInformation m_information; 86 Schema::IRestClient::Information m_restClientInformation; 87 std::optional<std::string> m_customHeader; 88 std::string m_caller; 89 Authentication::AuthenticationArguments m_authArgs; 90 std::once_flag m_initializeFlag; 91 }; 92 93 // The base class for data that comes from a rest based source. 94 struct RestSourceFactoryImpl : public ISourceFactory 95 { 96 std::string_view TypeName() const override final 97 { 98 return RestSourceFactory::Type(); 99 } 100 101 std::shared_ptr<ISourceReference> Create(const SourceDetails& details) override final 102 { 103 THROW_HR_IF(E_INVALIDARG, !Utility::CaseInsensitiveEquals(details.Type, RestSourceFactory::Type())); 104 105 return std::make_shared<RestSourceReference>(details); 106 } 107 108 bool Add(SourceDetails& details, IProgressCallback&) override final 109 { 110 if (details.Type.empty()) 111 { 112 details.Type = RestSourceFactory::Type(); 113 } 114 else 115 { 116 THROW_HR_IF(E_INVALIDARG, !Utility::CaseInsensitiveEquals(details.Type, RestSourceFactory::Type())); 117 } 118 119 // Check if URL is remote and secure 120 THROW_HR_IF(APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE, !Utility::IsUrlRemote(details.Arg)); 121 THROW_HR_IF(APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE, !Utility::IsUrlSecure(details.Arg)); 122 123 return true; 124 } 125 126 bool Update(const SourceDetails& details, IProgressCallback&) override final 127 { 128 THROW_HR_IF(E_INVALIDARG, !Utility::CaseInsensitiveEquals(details.Type, RestSourceFactory::Type())); 129 return true; 130 } 131 132 bool Remove(const SourceDetails& details, IProgressCallback&) override final 133 { 134 THROW_HR_IF(E_INVALIDARG, !Utility::CaseInsensitiveEquals(details.Type, RestSourceFactory::Type())); 135 return true; 136 } 137 }; 138 } 139 140 std::unique_ptr<ISourceFactory> RestSourceFactory::Create() 141 { 142 return std::make_unique<RestSourceFactoryImpl>(); 143 } 144 }