/// <summary>
        /// Returns the document stream for the given file name in specified library.
        /// </summary>
        /// <param name="filename">The document to find and stream.</param>
        /// <param name="libraryName">The folder name of the document location.</param>
        /// <returns> A stream containing the contents of the document. </returns>
        public async Task <byte[]> GetDocument(string filename, string libraryName)
        {
            _logger.LogInformation($"[{nameof(GetDocument)}] - Attempting to connect to SharePoint location.");

            string fileRelativeUrl = $"{_spConfig.RelativeSiteURL}/{libraryName}/{filename}";

            try
            {
                var file = _clientContext.Web.GetFileByServerRelativeUrl(fileRelativeUrl);
                _clientContext.Load(file);
                if (file is null)
                {
                    _logger.LogError($"[{nameof(GetDocument)}] - File not found: {fileRelativeUrl}");
                    return(HandleFileNotFoundExceptionWithTestPdf(new DocumentNotFoundException($"[{nameof(GetDocument)}] - File not found: {fileRelativeUrl}")));
                }

                ClientResult <Stream> stream = file.OpenBinaryStream();
                await _clientContext.ExecuteQueryAsync();

                if (stream.Value is null)
                {
                    _logger.LogError($"[{nameof(GetDocument)}] - File not stream from location: {fileRelativeUrl}");
                    return(HandleFileNotFoundExceptionWithTestPdf(new DocumentNotFoundException($"[{nameof(GetDocument)}] - File not found: {fileRelativeUrl}")));
                }

                _logger.LogInformation($"[{nameof(GetDocument)}] - File stream location: {fileRelativeUrl} completed.");
                return(stream.Value.ToByteArray());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"[{nameof(GetDocument)}] - The contract pdf file is not accessible. File: {fileRelativeUrl}");
                return(HandleFileNotFoundExceptionWithTestPdf(new DocumentNotAccessibleException("The contract pdf file is not accessible.", ex)));
            }
        }
コード例 #2
0
        /// <inheritdoc/>
        public async Task <string> AcquireSPTokenAsync()
        {
            Uri site = new Uri($"{_spConfig.ApiBaseAddress}{_spConfig.RelativeSiteURL}");
            var cleanAccessRequestContent = "grant_type=client_credentials" +
                                            $"&resource={_spConfig.Resource}/{site.DnsSafeHost}@{_spConfig.TenantId}" +
                                            $"&client_id={_spConfig.ClientId}@{_spConfig.TenantId}";

            var body = cleanAccessRequestContent +
                       $"&client_secret={HttpUtility.UrlEncode(_spConfig.ClientSecret)}";

            using (var stringContent = new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded"))
            {
                var sharepointAadEndpoint = $"{_spConfig.Authority}{_spConfig.TenantId}/tokens/OAuth/2";
                _logger.LogInformation($"[{nameof(AcquireSPTokenAsync)}] - Attempting to get token from the SharePoint account access control [{sharepointAadEndpoint}] with access request [{cleanAccessRequestContent}]. For site: {site.AbsoluteUri}");

                var result = await _httpClient.PostAsync(sharepointAadEndpoint, stringContent);

                var resultContent = await result.Content.ReadAsStringAsync();

                if (!result.IsSuccessStatusCode)
                {
                    _logger.LogError($"[{nameof(AcquireSPTokenAsync)}] - Failed to get access token with status code [{result.StatusCode}] and reponse message [{resultContent}]");
                    throw new SPTokenAcquisitionFailureException($"Access token cannot be acquired for the SharePoint AAD Auth. Failed with error: [{resultContent}]");
                }

                var    tokenResult = JsonSerializer.Deserialize <JsonElement>(resultContent);
                string token       = string.Empty;

                try
                {
                    token = tokenResult.GetProperty("access_token").GetString();
                }
                catch (KeyNotFoundException ex)
                {
                    _logger.LogError(ex, $"[{nameof(AcquireSPTokenAsync)}] - Access token cannot be acquired for the SharePoint AAD Auth. Site: {site.AbsoluteUri}");
                    throw new SPTokenAcquisitionFailureException("Access token cannot be acquired for the SharePoint AAD Auth.", ex);
                }

                if (string.IsNullOrEmpty(token))
                {
                    throw new SPTokenAcquisitionFailureException($"Access token cannot be acquired from token result [{resultContent}] for the SharePoint AAD Auth.");
                }

                _logger.LogInformation($"[{nameof(AcquireSPTokenAsync)}] - Successfully acquired the SharePoint token from the SharePoint account access control. Site: {site.AbsoluteUri}");
                return(token);
            }
        }
コード例 #3
0
        /// <inheritdoc/>
        public async Task <SessionWorkflowState> ProcessSessionMessageAsync(IMessageSession session, Message message)
        {
            var state = await _stateManager.GetWorkflowStateAsync(session);

            if (message.UserProperties.TryGetValue("ResetWorkflowState", out var shouldReset) && Convert.ToBoolean(shouldReset))
            {
                _logger.LogInformation($"[{nameof(ContractEventSessionManager)}.{nameof(ProcessSessionMessageAsync)}] - Reset workflow state message [{message.MessageId}] received, resetting session [{session.SessionId}].");
                return(await _stateManager.ResetWorkflowStateAsync(session));
            }

            if (state.IsFaulted && state.FailedMessageId != message.MessageId)
            {
                _logger.LogWarning($"[{nameof(ContractEventSessionManager)}.{nameof(ProcessSessionMessageAsync)}] - Moving this message [{message.MessageId}] to DLQ, beacause previous message [{state.FailedMessageId}] failed, hence dropping all messages in session [{session.SessionId}].");
                state.PostponedMessages.Add(message.MessageId);
                await session.DeadLetterAsync(message.SystemProperties.LockToken, $"Previous message failed, hence dropping all messages in session", $"Previous message {state.FailedMessageId} failed, hence dropping all messages in session {session.SessionId}");

                await _stateManager.SetWorkflowStateAsync(session, state);
            }
            else
            {
                if (state.IsFaulted && state.FailedMessageId == message.MessageId)
                {
                    state = await _stateManager.ResetWorkflowStateAsync(session);
                }

                try
                {
                    var contractEvent = JsonConvert.DeserializeObject <ContractEvent>(Encoding.UTF8.GetString(message.Body));
                    _processLog.Initialise(message, contractEvent);

                    await _contractService.ProcessMessage(contractEvent);
                }
                catch (NotImplementedException notImplemented)
                {
                    await SaveFailedState(session, message, state, notImplemented, "Message contains not implemented input");

                    await session.DeadLetterAsync(message.SystemProperties.LockToken, $"Message contains not imeplemented input", $"Invalid message {state.FailedMessageId} in session {session.SessionId} reason - {notImplemented.Message}.");
                }
                catch (ContractEventExpectationFailedException badMessage)
                {
                    await SaveFailedState(session, message, state, badMessage, "Message contains invalid input");

                    await session.DeadLetterAsync(message.SystemProperties.LockToken, $"Message contains invalid input", $"Invalid message {state.FailedMessageId} in session {session.SessionId} reason - {badMessage.Message}.");
                }
                catch (Exception ex)
                {
                    if (message.SystemProperties.DeliveryCount >= _functionSettings.MaximumDeliveryCount)
                    {
                        await SaveFailedState(session, message, state, ex, "Message delivery count exceeded");
                    }

                    throw;
                }
            }

            return(state);
        }
コード例 #4
0
        /// <summary>
        /// Converts the byte array PDF to be in the PDF\2A_2B format.
        /// </summary>
        /// <param name="pdf">The original PDF.</param>
        /// <returns>The formatted PDF.</returns>
        public byte[] ConvertToPdfA(byte[] pdf)
        {
            _logger.LogInformation("Starting conversion of PDF to PDF_A_2B.");
            var sw = Stopwatch.StartNew();

            using (var inputStream = new MemoryStream(pdf))
            {
                using (var doc = new Document(inputStream))
                {
                    doc.ConvertToPdfA();

                    using (var outputStream = new MemoryStream())
                    {
                        EnsureLandscapePagesAreMarkedCorrectly(doc);
                        doc.Save(outputStream);
                        _logger.LogInformation($"PDF conversion took {sw.ElapsedMilliseconds}ms to complete.");
                        return(outputStream.ToArray());
                    }
                }
            }
        }
        /// <summary>
        /// It will create a new contract.
        /// </summary>
        /// <param name="contractEvent">New contract Data.</param>
        /// <returns>Returns true when a new contract created else false.</returns>
        public async Task <bool> CreateAsync(ContractEvent contractEvent)
        {
            _logger.LogInformation($"[{nameof(CreateAsync)}] - Processing message for contract creation. ContractNumber: {contractEvent.ContractNumber}, ContractVersion: {contractEvent.ContractVersion}");

            var createRequest     = _contractEventMapper.GetCreateRequest(contractEvent);
            var fileName          = _contractEventMapper.GetFileNameForContractDocument(contractEvent.UKPRN, contractEvent.ContractNumber, contractEvent.ContractVersion);
            var folderName        = _contractEventMapper.GetFolderNameForContractDocument(contractEvent.FundingType.GetEnumShortName(), contractEvent.ContractPeriodValue, _spConfig.PublicationFolderSuffix);
            var urlSafeFolderName = _contractEventMapper.GetUrlSafeFolderNameForContractDocument(folderName);
            var pdfDoc            = await _sharePointClientService.GetDocument(fileName, urlSafeFolderName);

            var pdfADoc = _documentManagementService.ConvertToPdfA(pdfDoc);

            createRequest.ContractContent = _contractEventMapper.GetContractContent(pdfADoc, fileName);
            await _contractsDataService.CreateContractAsync(createRequest);

            return(true);
        }
コード例 #6
0
        /// <inheritdoc/>
        public async Task ProcessMessage(ContractEvent contractEvent)
        {
            _logger.LogInformation($"[{nameof(ProcessMessage)}] Processing message for contract event : {contractEvent.BookmarkId}");

            var eventType = contractEvent.GetContractEventType();

            switch (eventType)
            {
            case ContractEventType.Create:
                var existingContract = await _contractsDataService.TryGetContractAsync(contractEvent.ContractNumber, contractEvent.ContractVersion);

                if (existingContract is null)
                {
                    await _contractCreationService.CreateAsync(contractEvent);
                }
                else
                {
                    _logger.LogWarning($"[{nameof(ContractEventProcessor)}] - Ignoring contract event with id [{contractEvent.BookmarkId}] because a contract with contract number [{contractEvent.ContractNumber}], version [{contractEvent.ContractVersion}] and Id [{existingContract.Id}] already exists.");
                }

                break;

            case ContractEventType.Approve:
                var approveContract = await _contractsDataService.TryGetContractAsync(contractEvent.ContractNumber, contractEvent.ContractVersion);

                if (approveContract is null)
                {
                    _logger.LogWarning($"[{nameof(ContractEventProcessor)}] - Ignoring contract event with id [{contractEvent.BookmarkId}] because unable to find a contract with contract number [{contractEvent.ContractNumber}], version [{contractEvent.ContractVersion}].");
                }
                else
                {
                    await _contractApprovalService.ApproveAsync(contractEvent, approveContract);
                }

                break;

            case ContractEventType.Withdraw:
                await _contractWithdrawService.WithdrawAsync(contractEvent);

                break;

            default:
                throw new NotImplementedException($"[{nameof(ContractService)}] - [{nameof(ProcessMessage)}] does not have an implementation for event type [{eventType}].");
            }
        }
        /// <inheritdoc/>
        public async Task <bool> ApproveAsync(ContractEvent contractEvent, Contract existingContract)
        {
            var approvalRequest = new ApprovalRequest()
            {
                ContractNumber  = existingContract.ContractNumber,
                ContractVersion = existingContract.ContractVersion,
                Id       = existingContract.Id,
                FileName = contractEvent.ContractEventXml
            };

            var eventType = contractEvent.GetContractEventType();

            if (eventType != Enums.ContractEventType.Approve)
            {
                throw new InvalidOperationException($"[{nameof(ContractApprovalService)}] - [{nameof(ApproveAsync)}] called for event type [{eventType}].");
            }

            switch (existingContract.Status)
            {
            case Data.Api.Client.Enumerations.ContractStatus.PublishedToProvider:
                await _contractsDataService.ManualApproveAsync(approvalRequest);

                break;

            case Data.Api.Client.Enumerations.ContractStatus.ApprovedWaitingConfirmation:
                await _contractsDataService.ConfirmApprovalAsync(approvalRequest);

                break;

            default:
                _logger.LogInformation($"[{nameof(ContractApprovalService)}] - [{nameof(ApproveAsync)}] - No further action taken on [{existingContract.ContractNumber}], version [{existingContract.ContractVersion}], Id [{existingContract.Id}], event parent status [{contractEvent.ParentStatus}], event status [{contractEvent.Status}], event amendment type [{contractEvent.AmendmentType}] and contract status [{existingContract.Status}].");
                break;
            }

            return(true);
        }