winget-cli

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

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 }