166 lines
6.2 KiB
C#
166 lines
6.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel.DataAnnotations;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Json;
|
|
using System.Threading.Tasks;
|
|
using contact.Services;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace contact.Pages
|
|
{
|
|
[BindProperties(SupportsGet = true)]
|
|
public class RequestFormModel
|
|
{
|
|
public RequestFormModel()
|
|
{
|
|
DataCenter = "SF";
|
|
}
|
|
[Required]
|
|
public string Name { get; set; }
|
|
[Required]
|
|
public string Company { get; set; }
|
|
[Required, EmailAddress]
|
|
public string Email { get; set; }
|
|
[Required]
|
|
public string DataCenter { get; set; }
|
|
}
|
|
|
|
public class RequestModel : PageModel
|
|
{
|
|
private const string EvaluateUrl = "https://ayanova.com/docs/ay-evaluate/";
|
|
|
|
[BindProperty(SupportsGet = true)]
|
|
public RequestFormModel SubRequest { get; set; }
|
|
|
|
//Set when neither Sockeye nor the email got the request, so the page can say so
|
|
public bool SendFailed { get; set; }
|
|
|
|
public List<SelectListItem> DataCenters { get; } = new List<SelectListItem>
|
|
{
|
|
new SelectListItem { Value = "SF", Text = "San Francisco" },
|
|
new SelectListItem { Value = "ATL", Text = "Atlanta" },
|
|
new SelectListItem { Value = "NY", Text = "New York" },
|
|
new SelectListItem { Value = "TOR", Text = "Toronto" },
|
|
new SelectListItem { Value = "AMS", Text = "Amsterdam" },
|
|
new SelectListItem { Value = "LON", Text = "London" },
|
|
new SelectListItem { Value = "FFT", Text = "Frankfurt" },
|
|
new SelectListItem { Value = "SNG", Text = "Singapore" },
|
|
new SelectListItem { Value = "BNG", Text = "Bangalore" },
|
|
new SelectListItem { Value = "SYD", Text = "Sydney Australia" }
|
|
};
|
|
|
|
private readonly IConfiguration _configuration;
|
|
private readonly IHttpClientFactory _httpClientFactory;
|
|
private readonly MailSender _mail;
|
|
private readonly ILogger<RequestModel> _logger;
|
|
|
|
public RequestModel(IConfiguration configuration, IHttpClientFactory httpClientFactory, MailSender mail, ILogger<RequestModel> logger)
|
|
{
|
|
_configuration = configuration;
|
|
_httpClientFactory = httpClientFactory;
|
|
_mail = mail;
|
|
_logger = logger;
|
|
}
|
|
|
|
public void OnGet()
|
|
{
|
|
}
|
|
|
|
public async Task<IActionResult> OnPostAsync()
|
|
{
|
|
//The select can be bypassed by a hand-crafted POST; only accept codes from the list
|
|
if (!DataCenters.Any(d => d.Value == SubRequest.DataCenter))
|
|
{
|
|
ModelState.AddModelError("SubRequest.DataCenter", "Please choose a data center from the list.");
|
|
}
|
|
|
|
if (!ModelState.IsValid)
|
|
{
|
|
return Page();
|
|
}
|
|
|
|
if (ContactModel.IsBlocked(SubRequest.Company))
|
|
{
|
|
return Redirect(EvaluateUrl);
|
|
}
|
|
|
|
//1. Record the request in Sockeye. A failure here is logged and reported in the email,
|
|
// so the trial can be set up by hand instead of the request disappearing.
|
|
string sockeyeResult;
|
|
bool sockeyeOk;
|
|
try
|
|
{
|
|
await PostRequestToSockeyeAsync();
|
|
sockeyeOk = true;
|
|
sockeyeResult = "Recorded in Sockeye.";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
sockeyeOk = false;
|
|
sockeyeResult = $"NOT RECORDED IN SOCKEYE ({ex.Message}). Set this trial up by hand.";
|
|
_logger.LogError(ex, "Trial request post to Sockeye failed. {Body}", Describe());
|
|
}
|
|
|
|
//2. Notify support. Email is in the body; From is the form account, so it was never there before either
|
|
var body = $"{Describe()}\r\n\r\nSockeye:\r\n{sockeyeResult}";
|
|
var subject = sockeyeOk
|
|
? $"Trial request from {SubRequest.Company}"
|
|
: $"Trial request NOT RECORDED from {SubRequest.Company}";
|
|
bool mailOk;
|
|
try
|
|
{
|
|
await _mail.SendToSupportAsync(subject, body, SubRequest.Name, SubRequest.Email);
|
|
mailOk = true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
mailOk = false;
|
|
_logger.LogError(ex, "Trial request email failed. Submission:\r\n{Body}", body);
|
|
}
|
|
|
|
//Either path reaching John means the request is not lost; only both failing is a failure for the visitor
|
|
if (!sockeyeOk && !mailOk)
|
|
{
|
|
SendFailed = true;
|
|
return Page();
|
|
}
|
|
|
|
return Redirect(EvaluateUrl);
|
|
}
|
|
|
|
private string Describe() =>
|
|
$"Name:\r\n{SubRequest.Name}\r\n\r\nCompany:\r\n{SubRequest.Company}\r\n\r\nEmail:\r\n{SubRequest.Email}\r\n\r\nDataCenter:\r\n{SubRequest.DataCenter}";
|
|
|
|
private async Task PostRequestToSockeyeAsync()
|
|
{
|
|
//Sockeye:TrialRequestUrl. On the server this is http://127.0.0.1:7575/subscription-server-trial-request,
|
|
//straight to Kestrel on the same host, so it depends on neither DNS nor the droplet reaching its own reserved IP.
|
|
var url = _configuration["Sockeye:TrialRequestUrl"];
|
|
if (string.IsNullOrWhiteSpace(url))
|
|
{
|
|
throw new InvalidOperationException("Sockeye:TrialRequestUrl is not configured");
|
|
}
|
|
|
|
var r = new
|
|
{
|
|
dataCenter = SubRequest.DataCenter,
|
|
email = SubRequest.Email,
|
|
company = SubRequest.Company,
|
|
name = SubRequest.Name,
|
|
rValue = "totallylegit"
|
|
};
|
|
|
|
var client = _httpClientFactory.CreateClient("sockeye");
|
|
var response = await client.PostAsJsonAsync(url, r);
|
|
//Previously the response was never checked, so a rejected request failed silently
|
|
response.EnsureSuccessStatusCode();
|
|
}
|
|
}
|
|
}
|