Esempio n. 1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SFInstallableDblResource" /> class.
 /// </summary>
 /// <param name="userSecret">The user secret.</param>
 /// <param name="paratextOptions">The paratext options.</param>
 /// <param name="restClientFactory">The rest client factory.</param>
 /// <param name="fileSystemService">The file system service.</param>
 /// <param name="jwtTokenHelper">The JWT token helper.</param>
 /// <remarks>
 /// This is a convenience constructor for unit tests.
 /// </remarks>
 internal SFInstallableDblResource(UserSecret userSecret, ParatextOptions paratextOptions,
                                   ISFRestClientFactory restClientFactory, IFileSystemService fileSystemService,
                                   IJwtTokenHelper jwtTokenHelper)
     : this(userSecret, paratextOptions, restClientFactory, fileSystemService, jwtTokenHelper,
            new ParatextProjectDeleter(), new ParatextMigrationOperations(),
            new ParatextZippedResourcePasswordProvider(paratextOptions))
 {
 }
Esempio n. 2
0
        public ParatextService(IWebHostEnvironment env, IOptions <ParatextOptions> paratextOptions,
                               IRepository <UserSecret> userSecretRepository, IRealtimeService realtimeService,
                               IExceptionHandler exceptionHandler, IOptions <SiteOptions> siteOptions, IFileSystemService fileSystemService,
                               ILogger <ParatextService> logger, IJwtTokenHelper jwtTokenHelper, IParatextDataHelper paratextDataHelper,
                               IInternetSharedRepositorySourceProvider internetSharedRepositorySourceProvider,
                               ISFRestClientFactory restClientFactory)
        {
            _paratextOptions      = paratextOptions;
            _userSecretRepository = userSecretRepository;
            _realtimeService      = realtimeService;
            _exceptionHandler     = exceptionHandler;
            _siteOptions          = siteOptions;
            _fileSystemService    = fileSystemService;
            _logger             = logger;
            _jwtTokenHelper     = jwtTokenHelper;
            _paratextDataHelper = paratextDataHelper;
            _internetSharedRepositorySourceProvider = internetSharedRepositorySourceProvider;
            _restClientFactory = restClientFactory;

            _httpClientHandler = new HttpClientHandler();
            _registryClient    = new HttpClient(_httpClientHandler);
            if (env.IsDevelopment() || env.IsEnvironment("DevelopmentBeta") || env.IsEnvironment("Testing") || env.IsEnvironment("TestingBeta"))
            {
                _httpClientHandler.ServerCertificateCustomValidationCallback
                    = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
                // This should be paratext-qa.thedigitalbiblelibrary.org, but it's broken as of 2021-04 and
                // qa.thedigitalbiblelibrary.org should be just as good, at least for the time being.
                _dblServerUri               = "https://qa.thedigitalbiblelibrary.org/";
                _registryServerUri          = "https://registry-dev.paratext.org";
                _registryClient.BaseAddress = new Uri(_registryServerUri);
                _sendReceiveServerUri       = InternetAccess.uriDevelopment;
            }
            else
            {
                _registryClient.BaseAddress = new Uri(_registryServerUri);
            }
            _registryClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            ScrTextCollection = new LazyScrTextCollection();
            HgWrapper         = new HgWrapper();

            SharingLogicWrapper = new SharingLogicWrapper();
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
        }
Esempio n. 3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SFInstallableDblResource" /> class.
 /// </summary>
 /// <param name="userSecret">The user secret.</param>
 /// <param name="paratextOptions">The paratext options.</param>
 /// <param name="restClientFactory">The rest client factory.</param>
 /// <param name="fileSystemService">The file system service.</param>
 /// <param name="jwtTokenHelper">The JWT token helper.</param>
 /// <param name="projectDeleter">The project deleter.</param>
 /// <param name="migrationOperations">The migration operations.</param>
 /// <param name="passwordProvider">The password provider.</param>
 /// <exception cref="ArgumentNullException">restClientFactory</exception>
 private SFInstallableDblResource(UserSecret userSecret, ParatextOptions paratextOptions,
                                  ISFRestClientFactory restClientFactory, IFileSystemService fileSystemService,
                                  IJwtTokenHelper jwtTokenHelper, IProjectDeleter projectDeleter,
                                  IMigrationOperations migrationOperations, IZippedResourcePasswordProvider passwordProvider)
     : base(projectDeleter, migrationOperations, passwordProvider)
 {
     this._userSecret        = userSecret;
     this._paratextOptions   = paratextOptions;
     this._restClientFactory = restClientFactory;
     this._fileSystemService = fileSystemService;
     this._jwtTokenHelper    = jwtTokenHelper;
     if (this._restClientFactory == null)
     {
         throw new ArgumentNullException(nameof(restClientFactory));
     }
     else if (this._fileSystemService == null)
     {
         throw new ArgumentNullException(nameof(fileSystemService));
     }
 }
Esempio n. 4
0
        /// <summary>
        /// Converts the JSON response to a list of Installable DBL Resources.
        /// </summary>
        /// <param name="baseUri">The base URI.</param>
        /// <param name="response">The response.</param>
        /// <param name="restClientFactory">The rest client factory.</param>
        /// <param name="fileSystemService">The file system service.</param>
        /// <param name="jwtTokenHelper">The JWT token helper.</param>
        /// <param name="createdTimestamp">The created timestamp.</param>
        /// <param name="userSecret">The user secret.</param>
        /// <param name="paratextOptions">The paratext options.</param>
        /// <param name="projectDeleter">The project deleter.</param>
        /// <param name="migrationOperations">The migration operations.</param>
        /// <param name="passwordProvider">The password provider.</param>
        /// <returns>
        /// The Installable Resources.
        /// </returns>
        private static IEnumerable <SFInstallableDblResource> ConvertJsonResponseToInstallableDblResources(
            string baseUri, string response, ISFRestClientFactory restClientFactory,
            IFileSystemService fileSystemService, IJwtTokenHelper jwtTokenHelper, DateTime createdTimestamp,
            UserSecret userSecret, ParatextOptions paratextOptions, IProjectDeleter projectDeleter,
            IMigrationOperations migrationOperations, IZippedResourcePasswordProvider passwordProvider)
        {
            if (!string.IsNullOrWhiteSpace(response))
            {
                JObject jsonResources;
                try
                {
                    jsonResources = JObject.Parse(response);
                }
                catch (JsonReaderException)
                {
                    // Ignore the exception and just return empty result
                    // This is probably caused by partial result from poor connection to DBL
                    yield break;
                }
                foreach (JToken jsonResource in jsonResources["resources"] as JArray ?? new JArray())
                {
                    var name       = (string)jsonResource["name"];
                    var nameCommon = (string)jsonResource["nameCommon"];
                    var fullname   = (string)jsonResource["fullname"];
                    if (string.IsNullOrWhiteSpace(fullname))
                    {
                        fullname = nameCommon;
                    }

                    var        languageName        = (string)jsonResource["languageName"];
                    var        id                  = (string)jsonResource["id"];
                    var        revision            = (string)jsonResource["revision"];
                    var        permissionsChecksum = (string)jsonResource["permissions-checksum"];
                    var        manifestChecksum    = (string)jsonResource["p8z-manifest-checksum"];
                    var        languageIdLdml      = (string)jsonResource["languageLDMLId"];
                    var        languageIdCode      = (string)jsonResource["languageCode"];
                    LanguageId languageId          =
                        migrationOperations.DetermineBestLangIdToUseForResource(languageIdLdml, languageIdCode);
                    if (string.IsNullOrEmpty(languageId.Id))
                    {
                        languageId = LanguageIdHelper.FromCommonLanguageName(languageName);
                    }
                    else
                    {
                        languageId = LanguageId.FromEthnologueCode(languageId.Id);
                    }

                    string url      = BuildDblResourceEntriesUrl(baseUri, id);
                    var    resource = new SFInstallableDblResource(userSecret, paratextOptions, restClientFactory,
                                                                   fileSystemService, jwtTokenHelper, projectDeleter, migrationOperations, passwordProvider)
                    {
                        DisplayName         = name,
                        Name                = name,
                        FullName            = fullname,
                        LanguageID          = languageId,
                        DblSourceUrl        = url,
                        DBLEntryUid         = id,
                        DBLRevision         = int.Parse(revision),
                        PermissionsChecksum = permissionsChecksum,
                        ManifestChecksum    = manifestChecksum,
                        CreatedTimestamp    = createdTimestamp,
                    };

                    resource.LanguageName = MacroLanguageHelper.GetMacroLanguage(resource.LanguageID) ?? languageName;

                    yield return(resource);
                }
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Return a list of resources which this user is allowed to install from DBL.
        /// If we cannot contact DBL, return an empty list.
        /// </summary>
        /// <param name="userSecret">The user secret.</param>
        /// <param name="paratextOptions">The paratext options.</param>
        /// <param name="restClientFactory">The rest client factory.</param>
        /// <param name="fileSystemService">The file system service.</param>
        /// <param name="jwtTokenHelper">The JWT token helper.</param>
        /// <param name="baseUrl">The base URL.</param>
        /// <returns>The Installable Resources.</returns>
        /// <exception cref="ArgumentNullException">restClientFactory
        /// or
        /// userSecret</exception>
        /// <remarks>Tests on this method can be found in ParatextServiceTests.cs calling GetResources().</remarks>
        public static IEnumerable <SFInstallableDblResource> GetInstallableDblResources(UserSecret userSecret,
                                                                                        ParatextOptions paratextOptions, ISFRestClientFactory restClientFactory,
                                                                                        IFileSystemService fileSystemService, IJwtTokenHelper jwtTokenHelper, IExceptionHandler exceptionHandler,
                                                                                        string baseUrl = null)
        {
            // Parameter check (just like the constructor)
            if (restClientFactory == null)
            {
                throw new ArgumentNullException(nameof(restClientFactory));
            }
            else if (userSecret == null)
            {
                throw new ArgumentNullException(nameof(userSecret));
            }

            ISFRestClient client =
                restClientFactory.Create(string.Empty, ApplicationProduct.DefaultVersion, userSecret);

            baseUrl = string.IsNullOrWhiteSpace(baseUrl) ? InternetAccess.ParatextDBLServer : baseUrl;
            string response = null;

            try
            {
                response = client.Get(BuildDblResourceEntriesUrl(baseUrl));
            }
            catch (WebException e)
            {
                // If we get a temporary 401 Unauthorized response, return an empty list.
                string errorExplanation = "GetInstallableDblResources failed when attempting to inquire about"
                                          + $" resources and is ignoring error {e}";
                var report = new Exception(errorExplanation);
                // Report to bugsnag, but don't throw.
                exceptionHandler.ReportException(report);
                return(Enumerable.Empty <SFInstallableDblResource>());
            }
            IEnumerable <SFInstallableDblResource> resources = ConvertJsonResponseToInstallableDblResources(baseUrl,
                                                                                                            response, restClientFactory, fileSystemService, jwtTokenHelper, DateTime.Now, userSecret,
                                                                                                            paratextOptions, new ParatextProjectDeleter(), new ParatextMigrationOperations(),
                                                                                                            new ParatextZippedResourcePasswordProvider(paratextOptions));

            return(resources);
        }
Esempio n. 6
0
        /// <summary>
        /// Checks the resource permission.
        /// </summary>
        /// <param name="id">The identifier.</param>
        /// <param name="userSecret">The user secret.</param>
        /// <param name="paratextOptions">The paratext options.</param>
        /// <param name="restClientFactory">The rest client factory.</param>
        /// <param name="fileSystemService">The file system service.</param>
        /// <param name="jwtTokenHelper">The JWT token helper.</param>
        /// <param name="baseUrl">The base URL.</param>
        /// <returns>
        ///   <c>true</c> if the user has permission to access the resource; otherwise, <c>false</c>.
        /// </returns>
        /// <exception cref="ArgumentNullException">id
        /// or
        /// userSecret
        /// or
        /// restClientFactory</exception>
        public static bool CheckResourcePermission(string id, UserSecret userSecret,
                                                   ParatextOptions paratextOptions, ISFRestClientFactory restClientFactory,
                                                   IFileSystemService fileSystemService, IJwtTokenHelper jwtTokenHelper,
                                                   IExceptionHandler exceptionHandler, string baseUrl = null)
        {
            // Parameter check
            if (string.IsNullOrWhiteSpace(id))
            {
                throw new ArgumentNullException(nameof(id));
            }
            else if (userSecret == null)
            {
                throw new ArgumentNullException(nameof(userSecret));
            }
            else if (restClientFactory == null)
            {
                throw new ArgumentNullException(nameof(restClientFactory));
            }

            ISFRestClient client = restClientFactory.Create(string.Empty, ApplicationProduct.DefaultVersion, userSecret);

            baseUrl = string.IsNullOrWhiteSpace(baseUrl) ? InternetAccess.ParatextDBLServer : baseUrl;
            try
            {
                _ = client.Head(BuildDblResourceEntriesUrl(baseUrl, id));
                return(true);
            }
            catch (Exception ex)
            {
                // Normally we would catch the specific WebException,
                // but something in ParatextData is interfering with it.
                if (ex.InnerException?.Message.StartsWith("401: ", StringComparison.OrdinalIgnoreCase) ?? false)
                {
                    // A 401 error means unauthorized (probably a bad token)
                    return(false);
                }
                else if (ex.InnerException?.Message.StartsWith("403: ", StringComparison.OrdinalIgnoreCase) ?? false)
                {
                    // A 403 error means no access.
                    return(false);
                }
                else if (ex.InnerException?.Message.StartsWith("404: ", StringComparison.OrdinalIgnoreCase) ?? false)
                {
                    // A 404 error means that the resource is not on the server
                    return(false);
                }
                else if (ex.InnerException?.Message.StartsWith("405: ", StringComparison.OrdinalIgnoreCase) ?? false)
                {
                    // A 405 means that HEAD request does not work on the server, so we will use the resource list
                    // This is slower (although faster than a GET request on the resource), but more reliable
                    IEnumerable <SFInstallableDblResource> resources =
                        GetInstallableDblResources(
                            userSecret,
                            paratextOptions,
                            restClientFactory,
                            fileSystemService,
                            jwtTokenHelper,
                            exceptionHandler,
                            baseUrl);
                    return(resources.Any(r => r.DBLEntryUid == id));
                }
                else if (ex.Source == "NSubstitute")
                {
                    // This occurs during unit tests to test whether there is permission or not
                    return(false);
                }
                else
                {
                    // An unknown error
                    throw;
                }
            }
        }