Sample blog post
January 1, 2022 by Mark
using System.Globalization;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Identity.Web;
using Microsoft.EntityFrameworkCore;
using Monopoly.UK.Crew.Data.Models;
using Monopoly.UK.Crew.Services;
using Monopoly.UK.Crew.Microsite.Extensions;
using Monopoly.UK.Crew.Microsite.Services;
using CodeString.Data.Models;
// Create configuration
IConfigurationBuilder configBuilder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false, true);
IConfigurationRoot config = configBuilder.Build();
var builder = WebApplication.CreateBuilder(args);
// Add database contexts
builder.Services.AddDbContextFactory<Context>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});
builder.Services.AddDbContext<Context>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
}, ServiceLifetime.Transient);
builder.Services.AddDbContextFactory<LoggingContext>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});
if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS")))
{
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", System.AppDomain.CurrentDomain.BaseDirectory + "mcdonalds-festiv-1684507707072-390149bda32e.json");
}
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
builder.Configuration.Bind("AzureAd", options);
options.Events.OnRedirectToIdentityProvider = context =>
{
if (!string.IsNullOrEmpty(context.Properties.RedirectUri))
{
context.ProtocolMessage.SetParameter("domain_hint", builder.Configuration.GetSection("AzureAd:DomainHint").Value);
}
return Task.CompletedTask;
};
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
builder.Services.AddControllersWithViews();
builder.Services.AddMicrositeServiceManager(config);
builder.Services.AddServiceManager(builder.Configuration);
builder.Services.AddAntiforgery(options =>
{
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
builder.Services.AddDistributedMemoryCache();
builder.Services.AddRazorPages();
// Add services to the container.
builder.Services.AddHttpClient();
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-GB");
var app = builder.Build();
app.UseSecureHeadersMiddleware(builder.Configuration.GetSection("CSP"));
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error/500");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/Error/{0}");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Globalization;
using Monopoly.UK.Crew.Data.Enums;
using Monopoly.UK.Crew.Data.Extensions;
using Monopoly.UK.Crew.Models.Claim;
using Monopoly.UK.Crew.Services.BankCheck;
using Monopoly.UK.Crew.Services.Claim;
using Monopoly.UK.Crew.Services.ReCaptcha;
using CodeString.Cryptography.Encryption;
using Monopoly.UK.Crew.Microsite.Attributes;
using Monopoly.UK.Crew.Microsite.ContentHelpers;
using Monopoly.UK.Crew.Microsite.Models;
namespace Monopoly.UK.Crew.Microsite.Controllers
{
public class ClaimController : Controller
{
private readonly IMapper mapper;
private readonly IClaimService claimService;
private readonly IBankCheckService bankCheckService;
private readonly IReCaptchaEnterpriseService reCaptchaEnterpriseService;
private readonly IEncryptionService encryptionService;
public ClaimController(IMapper mapper,
IClaimService claimService,
IBankCheckService bankCheckService,
IReCaptchaEnterpriseService reCaptchaEnterpriseService,
IEncryptionService encryptionService)
{
this.mapper = mapper;
this.claimService = claimService;
this.bankCheckService = bankCheckService;
this.reCaptchaEnterpriseService = reCaptchaEnterpriseService;
this.encryptionService = encryptionService;
}
[HttpGet]
[Authorize]
[ServiceFilter(typeof(CampaignStateFilterAttribute))]
[ServiceFilter(typeof(AccountAccessFilterAttribute))]
public IActionResult Cash(string id)
{
var claimRef = Guid.Empty;
if (!Guid.TryParse(id, out claimRef))
{
return RedirectToAction("Error", "Error", new { Id = 404 });
};
var claim = claimService.GetClaimToUpdate(claimRef, (int)ClaimStates.New, PrizeProcesses.Cash.GetStringValue());
if (!claim.Success)
{
return RedirectToAction("Error", "Error", new { Id = 500 });
}
var cashClaimViewModel = new CashClaimViewModel
{
ClaimRef = claim.ClaimRef.ToString(),
Email = claim.Email,
FirstName = claim.FirstName,
LastName = claim.LastName,
PrizeName = PrizeHelper.GetPrizeName(claim.PrizeId),
PrizeImageUrl = PrizeHelper.GetPrizeImageUrl(claim.PrizeId)
};
return View(cashClaimViewModel);
}
[HttpGet]
[Authorize]
[ServiceFilter(typeof(CampaignStateFilterAttribute))]
[ServiceFilter(typeof(AccountAccessFilterAttribute))]
public IActionResult Physical(string id)
{
var claimRef = Guid.Empty;
if (!Guid.TryParse(id, out claimRef))
{
return RedirectToAction("Error", "Error", new { Id = 404 });
};
var claim = claimService.GetClaimToUpdate(claimRef, (int)ClaimStates.New, PrizeProcesses.Physical.GetStringValue());
if (!claim.Success)
{
return RedirectToAction("Error", "Error", new { Id = 500 });
}
var physicalClaimViewModel = new PhysicalClaimViewModel
{
ClaimRef = claim.ClaimRef.ToString(),
Email = claim.Email,
FirstName = claim.FirstName,
LastName = claim.LastName,
PrizeName = claim.PrizeName,
PrizeImageUrl = claim.PrizeImageUrl
};
return View(physicalClaimViewModel);
}
[HttpGet]
[Authorize]
[ServiceFilter(typeof(CampaignStateFilterAttribute))]
[ServiceFilter(typeof(AccountAccessFilterAttribute))]
public IActionResult Digital(string id)
{
var claimRef = Guid.Empty;
if (!Guid.TryParse(id, out claimRef))
{
return RedirectToAction("Error", "Error", new { Id = 404 });
};
var claim = claimService.GetClaimToUpdate(claimRef, (int)ClaimStates.New, PrizeProcesses.Digital.GetStringValue());
if (!claim.Success)
{
return RedirectToAction("Error", "Error", new { Id = 500 });
}
var digitalClaimViewModel = new DigitalClaimViewModel
{
ClaimRef = claim.ClaimRef.ToString(),
ClaimId = claim.ClaimId,
Email = claim.Email,
AlternateEmail = claim.AlternateEmail,
FirstName = claim.FirstName,
LastName = claim.LastName,
PrizeName = claim.PrizeName,
PrizeImageUrl = claim.PrizeImageUrl
};
return View(digitalClaimViewModel);
}
[HttpGet]
[Authorize]
public IActionResult Incentive(string id)
{
var claimRef = Guid.Empty;
if (!Guid.TryParse(id, out claimRef))
{
return RedirectToAction("Error", "Error", new { Id = 404 });
};
var claim = claimService.GetClaimToUpdate(claimRef, (int)ClaimStates.New, PrizeProcesses.Incentive.GetStringValue());
if (!claim.Success)
{
return RedirectToAction("Error", "Error", new { Id = 500 });
}
var incentiveClaimViewModel = new IncentiveClaimViewModel
{
ClaimRef = claim.ClaimRef.ToString(),
Email = claim.Email,
FirstName = claim.FirstName,
LastName = claim.LastName,
PrizeName = PrizeHelper.GetPrizeName(claim.PrizeId),
PrizeImageUrl = PrizeHelper.GetPrizeImageUrl(claim.PrizeId)
};
return View(incentiveClaimViewModel);
}
[HttpPost]
[Authorize]
[ServiceFilter(typeof(CampaignStateFilterAttribute))]
[ServiceFilter(typeof(AccountAccessFilterAttribute))]
public IActionResult Cash(CashClaimViewModel cashClaimViewModel)
{
var dob = string.Format("{0}-{1}-{2}", cashClaimViewModel.DobYear, cashClaimViewModel.DobMonth, cashClaimViewModel.DobDay);
var minimumAge = 16;
if (!DateTime.TryParseExact(dob, "yyyy-M-d", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out DateTime outputDob))
{
ModelState.AddModelError("DateOfBirth", "Please enter a valid date of birth");
}
if (DateTime.Now.AddYears(-minimumAge) < outputDob)
{
ModelState.AddModelError("DateOfBirth", "You need to be 16 or over to claim this prize");
}
if (!ModelState.IsValid)
{
return View(cashClaimViewModel);
}
var reCaptchaResponse = reCaptchaEnterpriseService.PerformRecaptchaCheck(cashClaimViewModel.ReCaptchaToken, "CLAIM");
if (!reCaptchaResponse.Success)
{
ModelState.AddModelError("ReCaptchaToken", reCaptchaResponse.Message);
return View(cashClaimViewModel);
}
var bankCheck = bankCheckService.CheckBankDetails(cashClaimViewModel.SortCode, cashClaimViewModel.AccountNumber);
if (!bankCheck.Success)
{
ModelState.AddModelError("AccountNumber", "Please enter a valid account number");
ModelState.AddModelError("SortCode", "Please enter a valid sort code");
return View(cashClaimViewModel);
}
cashClaimViewModel.AccountName = encryptionService.Encrypt(cashClaimViewModel.AccountName);
cashClaimViewModel.AccountNumber = encryptionService.Encrypt(cashClaimViewModel.AccountNumber);
cashClaimViewModel.SortCode = encryptionService.Encrypt(cashClaimViewModel.SortCode);
cashClaimViewModel.DOB = DateOnly.FromDateTime(outputDob);
var claimRef = Guid.Parse(cashClaimViewModel.ClaimRef);
var claim = claimService.GetClaimToUpdate(claimRef, (int)ClaimStates.New, PrizeProcesses.Cash.GetStringValue());
var updatedClaimDetails = mapper.Map<UpdateClaimModel>(cashClaimViewModel);
updatedClaimDetails.ClaimId = claim.ClaimId;
var updatedClaim = claimService.UpdateClaim(updatedClaimDetails);
if (!updatedClaim.Success)
{
return RedirectToAction("Error", "Error", new { Id = 403 });
}
return RedirectToAction("Cash", "Confirmation", new { id = updatedClaim.ClaimRef.ToString() });
}
[HttpPost]
[Authorize]
[ServiceFilter(typeof(CampaignStateFilterAttribute))]
[ServiceFilter(typeof(AccountAccessFilterAttribute))]
public IActionResult Physical(PhysicalClaimViewModel physicalClaimViewModel)
{
var dob = string.Format("{0}-{1}-{2}", physicalClaimViewModel.DobYear, physicalClaimViewModel.DobMonth, physicalClaimViewModel.DobDay);
var minimumAge = 16;
if (!DateTime.TryParseExact(dob, "yyyy-M-d", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out DateTime outputDob))
{
ModelState.AddModelError("DateOfBirth", "Please enter a valid date of birth");
}
if (DateTime.Now.AddYears(-minimumAge) < outputDob)
{
ModelState.AddModelError("DateOfBirth", "You need to be 16 or over to claim this prize");
}
if (!ModelState.IsValid)
{
return View(physicalClaimViewModel);
}
var reCaptchaResponse = reCaptchaEnterpriseService.PerformRecaptchaCheck(physicalClaimViewModel.ReCaptchaToken, "CLAIM");
if (!reCaptchaResponse.Success)
{
ModelState.AddModelError("ReCaptchaToken", reCaptchaResponse.Message);
return View(physicalClaimViewModel);
}
physicalClaimViewModel.DOB = DateOnly.FromDateTime(outputDob);
var claimRef = Guid.Parse(physicalClaimViewModel.ClaimRef);
var claim = claimService.GetClaimToUpdate(claimRef, (int)ClaimStates.New, PrizeProcesses.Physical.GetStringValue());
var updatedClaimDetails = mapper.Map<UpdateClaimModel>(physicalClaimViewModel);
updatedClaimDetails.ClaimId = claim.ClaimId;
var updatedClaim = claimService.UpdateClaim(updatedClaimDetails);
if (!updatedClaim.Success)
{
return RedirectToAction("Error", "Error", new { Id = 403 });
}
return RedirectToAction("Physical", "Confirmation", new { id = updatedClaim.ClaimRef.ToString() });
}
[HttpPost]
[Authorize]
[ServiceFilter(typeof(CampaignStateFilterAttribute))]
[ServiceFilter(typeof(AccountAccessFilterAttribute))]
public IActionResult Digital(DigitalClaimViewModel digitalClaimViewModel)
{
var dob = string.Format("{0}-{1}-{2}", digitalClaimViewModel.DobYear, digitalClaimViewModel.DobMonth, digitalClaimViewModel.DobDay);
var minimumAge = 16;
if (!DateTime.TryParseExact(dob, "yyyy-M-d", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out DateTime outputDob))
{
ModelState.AddModelError("DateOfBirth", "Please enter a valid date of birth");
}
if (DateTime.Now.AddYears(-minimumAge) < outputDob)
{
ModelState.AddModelError("DateOfBirth", "You need to be 16 or over to claim this prize");
}
if (!ModelState.IsValid)
{
return View(digitalClaimViewModel);
}
var reCaptchaResponse = reCaptchaEnterpriseService.PerformRecaptchaCheck(digitalClaimViewModel.ReCaptchaToken, "CLAIM");
if (!reCaptchaResponse.Success)
{
ModelState.AddModelError("ReCaptchaToken", reCaptchaResponse.Message);
return View(digitalClaimViewModel);
}
digitalClaimViewModel.DOB = DateOnly.FromDateTime(outputDob);
var claimRef = Guid.Parse(digitalClaimViewModel.ClaimRef);
var claim = claimService.GetClaimToUpdate(claimRef, (int)ClaimStates.New, PrizeProcesses.Digital.GetStringValue());
var updatedClaimDetails = mapper.Map<UpdateClaimModel>(digitalClaimViewModel);
updatedClaimDetails.ClaimId = claim.ClaimId;
var updatedClaim = claimService.UpdateClaim(updatedClaimDetails);
if (!updatedClaim.Success)
{
return RedirectToAction("Error", "Error", new { Id = 403 });
}
return RedirectToAction("Digital", "Confirmation", new { id = updatedClaim.ClaimRef.ToString() });
}
[HttpPost]
[Authorize]
public IActionResult Incentive(IncentiveClaimViewModel incentiveClaimViewModel)
{
var dob = string.Format("{0}-{1}-{2}", incentiveClaimViewModel.DobYear, incentiveClaimViewModel.DobMonth, incentiveClaimViewModel.DobDay);
var minimumAge = 16;
if (!DateTime.TryParseExact(dob, "yyyy-M-d", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out DateTime outputDob))
{
ModelState.AddModelError("DateOfBirth", "Please enter a valid date of birth");
}
if (DateTime.Now.AddYears(-minimumAge) < outputDob)
{
ModelState.AddModelError("DateOfBirth", "You need to be 16 or over to claim this prize");
}
if (!ModelState.IsValid)
{
return View(incentiveClaimViewModel);
}
var reCaptchaResponse = reCaptchaEnterpriseService.PerformRecaptchaCheck(incentiveClaimViewModel.ReCaptchaToken, "CLAIM");
if (!reCaptchaResponse.Success)
{
ModelState.AddModelError("ReCaptchaToken", reCaptchaResponse.Message);
return View(incentiveClaimViewModel);
}
incentiveClaimViewModel.DOB = DateOnly.FromDateTime(outputDob);
var claimRef = Guid.Parse(incentiveClaimViewModel.ClaimRef);
var claim = claimService.GetClaimToUpdate(claimRef, (int)ClaimStates.New, PrizeProcesses.Incentive.GetStringValue());
var updatedClaimDetails = mapper.Map<UpdateClaimModel>(incentiveClaimViewModel);
updatedClaimDetails.ClaimId = claim.ClaimId;
var updatedClaim = claimService.UpdateClaim(updatedClaimDetails);
if (!updatedClaim.Success)
{
return RedirectToAction("Error", "Error", new { Id = 403 });
}
return RedirectToAction("Incentive", "Confirmation", new { id = updatedClaim.ClaimRef.ToString() });
}
}
}