diff --git a/.gitignore b/.gitignore index 07370c31..c83e3a48 100644 --- a/.gitignore +++ b/.gitignore @@ -333,3 +333,6 @@ ASALocalRun/ # MacOS .DS_Store + +# Fake database +*fakedatabase.db diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Account/AccountController.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Account/AccountController.cs index 789d167f..992134c4 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Account/AccountController.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Account/AccountController.cs @@ -9,7 +9,6 @@ using IdentityServer4.Models; using IdentityServer4.Services; using IdentityServer4.Stores; -using IdentityServer4.Test; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -82,36 +81,33 @@ public async Task Login(LoginInputModel model, string button) // the user clicked the "cancel" button if (button != "login") { - if (context != null) - { - // if the user cancels, send a result back into IdentityServer as if they - // denied the consent (even if this client does not require consent). - // this will send back an access denied OIDC error response to the client. - await _interaction.GrantConsentAsync(context, ConsentResponse.Denied); + if (context == null) + return Redirect("~/"); - // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null - if (await _clientStore.IsPkceClientAsync(context.ClientId)) - { - // if the client is PKCE then we assume it's native, so this change in how to - // return the response is for better UX for the end user. - return View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl }); - } + // if the user cancels, send a result back into IdentityServer as if they + // denied the consent (even if this client does not require consent). + // this will send back an access denied OIDC error response to the client. + await _interaction.GrantConsentAsync(context, ConsentResponse.Denied); - return Redirect(model.ReturnUrl); - } - else + // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null + if (await _clientStore.IsPkceClientAsync(context.ClientId)) { - // since we don't have a valid context, then we just go back to the home page - return Redirect("~/"); + // if the client is PKCE then we assume it's native, so this change in how to + // return the response is for better UX for the end user. + return View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl }); } + + return Redirect(model.ReturnUrl); + + // since we don't have a valid context, then we just go back to the home page } if (ModelState.IsValid) { // validate username/password against in-memory store - if (_users.ValidateCredentials(model.Username, model.Password)) + if (await _users.ValidateCredentials(model.Username, model.Password)) { - var user = _users.FindByUsername(model.Username); + var user = await _users.FindByUsername(model.Username); await _events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.SubjectId, user.Username, clientId: context?.ClientId)); // only set explicit expiration here if user chooses "remember me". @@ -124,7 +120,7 @@ public async Task Login(LoginInputModel model, string button) IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) }; - }; + } // issue authentication cookie with subject ID and username await HttpContext.SignInAsync(user.SubjectId, user.Username, props); @@ -144,18 +140,13 @@ public async Task Login(LoginInputModel model, string button) // request for a local page if (Url.IsLocalUrl(model.ReturnUrl)) - { return Redirect(model.ReturnUrl); - } - else if (string.IsNullOrEmpty(model.ReturnUrl)) - { + + if (string.IsNullOrEmpty(model.ReturnUrl)) return Redirect("~/"); - } - else - { - // user might have clicked on a malicious link - should be logged - throw new Exception("invalid return URL"); - } + + // user might have clicked on a malicious link - should be logged + throw new Exception("invalid return URL"); } await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId:context?.ClientId)); @@ -166,7 +157,6 @@ public async Task Login(LoginInputModel model, string button) var vm = await BuildLoginViewModelAsync(model); return View(vm); } - /// /// Show logout page @@ -227,7 +217,6 @@ public IActionResult AccessDenied() return View(); } - /*****************************************/ /* helper APIs for the AccountController */ /*****************************************/ @@ -243,7 +232,7 @@ private async Task BuildLoginViewModelAsync(string returnUrl) { EnableLocalLogin = local, ReturnUrl = returnUrl, - Username = context?.LoginHint + Username = context.LoginHint }; if (!local) @@ -332,7 +321,7 @@ private async Task BuildLoggedOutViewModelAsync(string logou { AutomaticRedirectAfterSignOut = AccountOptions.AutomaticRedirectAfterSignOut, PostLogoutRedirectUri = logout?.PostLogoutRedirectUri, - ClientName = string.IsNullOrEmpty(logout?.ClientName) ? logout?.ClientId : logout?.ClientName, + ClientName = string.IsNullOrEmpty(logout?.ClientName) ? logout?.ClientId : logout.ClientName, SignOutIframeUrl = logout?.SignOutIFrameUrl, LogoutId = logoutId }; diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Client/ClientRegistrationController.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Client/ClientRegistrationController.cs index b974de5f..fe45432d 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Client/ClientRegistrationController.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Client/ClientRegistrationController.cs @@ -1,18 +1,11 @@ using IdentityModel; -using IdentityServer4.Events; -using IdentityServer4.Extensions; using IdentityServer4.Models; using IdentityServer4.Stores; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Primitives; using OpenActive.FakeDatabase.NET; using System; -using System.Collections.Generic; using System.Linq; -using System.Numerics; -using System.Security.Cryptography; -using System.Text; using System.Text.Json.Serialization; using System.Threading.Tasks; @@ -23,11 +16,11 @@ namespace IdentityServer // [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] [Consumes("application/json")] [Produces("application/json")] - public class ClientResistrationController : ControllerBase + public class ClientRegistrationController : ControllerBase { private readonly IClientStore _clients; - public ClientResistrationController(IClientStore clients) + public ClientRegistrationController(IClientStore clients) { _clients = clients; } @@ -38,44 +31,33 @@ public ClientResistrationController(IClientStore clients) [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task PostAsync([FromBody] ClientRegistrationModel model) { - if (model.GrantTypes == null) - { - model.GrantTypes = new[] { OidcConstants.GrantTypes.AuthorizationCode, OidcConstants.GrantTypes.RefreshToken }; - } + model.GrantTypes ??= new[] {OidcConstants.GrantTypes.AuthorizationCode, OidcConstants.GrantTypes.RefreshToken}; if (model.GrantTypes.Any(x => x == OidcConstants.GrantTypes.Implicit) || model.GrantTypes.Any(x => x == OidcConstants.GrantTypes.AuthorizationCode)) { if (!model.RedirectUris.Any()) - { return BadRequest("A redirect URI is required for the supplied grant type."); - } if (model.RedirectUris.Any(redirectUri => !Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute))) - { return BadRequest("One or more of the redirect URIs are invalid."); - } } // generate a secret for the client var key = KeyGenerator.GenerateSecret(); - - StringValues headerValues; var registrationKey = string.Empty; - if (Request.Headers.TryGetValue("Authorization", out headerValues)) - { + if (Request.Headers.TryGetValue("Authorization", out var headerValues)) registrationKey = headerValues.FirstOrDefault().Substring("Bearer ".Length); - } // update the booking system - var bookingPartner = FakeBookingSystem.Database.GetBookingPartnerByInitialAccessToken(registrationKey); + var bookingPartner = await FakeBookingSystem.Database.GetBookingPartnerByInitialAccessToken(registrationKey); if (bookingPartner == null) return Unauthorized("Initial Access Token is not valid, or is expired"); bookingPartner.Registered = true; bookingPartner.ClientSecret = key.Sha256(); bookingPartner.Name = model.ClientName; - bookingPartner.ClientProperties = new OpenActive.FakeDatabase.NET.ClientModel + bookingPartner.ClientProperties = new ClientModel { ClientUri = model.ClientUri, LogoUri = model.LogoUri, @@ -83,14 +65,14 @@ public async Task PostAsync([FromBody] ClientRegistrationModel mo RedirectUris = model.RedirectUris, Scope = model.Scope, }; - FakeBookingSystem.Database.SaveBookingPartner(bookingPartner); + + await FakeBookingSystem.Database.SaveBookingPartner(bookingPartner); // Read the updated client from the database and reflect back in the request var client = await _clients.FindClientByIdAsync(bookingPartner.ClientId); if (bookingPartner.ClientSecret != client.ClientSecrets?.FirstOrDefault()?.Value) - { return Problem(title: "New client secret not updated in cache", statusCode: 500); - } + var response = new ClientRegistrationResponse { ClientId = client.ClientId, @@ -103,7 +85,8 @@ public async Task PostAsync([FromBody] ClientRegistrationModel mo Scope = string.Join(' ', client.AllowedScopes) }; - return CreatedAtAction("ClientRegistration", response); + var baseUrl = $"{Request.Scheme}://{Request.Host.Value}/connect/register"; + return Created($"{baseUrl}/{client.ClientId}", response); } } @@ -122,7 +105,7 @@ public class ClientRegistrationModel public string[] GrantTypes { get; set; } [JsonPropertyName(OidcConstants.ClientMetadata.RedirectUris)] - public string[] RedirectUris { get; set; } = new string[] {}; + public string[] RedirectUris { get; set; } = {}; public string Scope { get; set; } = "openid profile email"; } diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Client/ClientStore.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Client/ClientStore.cs index 720b7990..b89d7b18 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Client/ClientStore.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Client/ClientStore.cs @@ -1,8 +1,6 @@ using IdentityServer4.Models; using IdentityServer4.Stores; -using Microsoft.Extensions.Logging; using OpenActive.FakeDatabase.NET; -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -11,16 +9,18 @@ namespace IdentityServer { public class ClientStore : IClientStore { - public Task FindClientByIdAsync(string clientId) + public async Task FindClientByIdAsync(string clientId) { - var bookingPartner = FakeBookingSystem.Database.GetBookingPartner(clientId); - return Task.FromResult(this.ConvertToIS4Client(bookingPartner)); + var bookingPartner = await FakeBookingSystem.Database.GetBookingPartner(clientId); + return ConvertToIS4Client(bookingPartner); } private Client ConvertToIS4Client(BookingPartnerTable bookingPartner) { - if (bookingPartner == null) return null; - return new Client() + if (bookingPartner == null) + return null; + + return new Client { Enabled = bookingPartner.Registered, ClientId = bookingPartner.ClientId, diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Grants/BookingPartnerViewModel.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Grants/BookingPartnerViewModel.cs index 26cb3e2e..9150fc24 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Grants/BookingPartnerViewModel.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Grants/BookingPartnerViewModel.cs @@ -1,7 +1,6 @@ // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - using OpenActive.FakeDatabase.NET; using System; using System.Collections.Generic; @@ -25,5 +24,4 @@ public class BookingPartnerModel public IEnumerable ApiGrantNames { get; set; } public BookingPartnerTable BookingPartner { get; set; } } - } \ No newline at end of file diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Grants/BookingPartnersController.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Grants/BookingPartnersController.cs index 1915f813..29bdc820 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Grants/BookingPartnersController.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Grants/BookingPartnersController.cs @@ -1,21 +1,16 @@ // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - using IdentityServer4.Services; using IdentityServer4.Stores; using Microsoft.AspNetCore.Mvc; -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using IdentityServer4.Events; using IdentityServer4.Extensions; using OpenActive.FakeDatabase.NET; -using System.Security.Cryptography; using System; -using IdentityServer4.Models; -using System.Text.RegularExpressions; +using System.Linq; using IdentityServer; namespace src @@ -29,17 +24,12 @@ public class BookingPartnersController : Controller { private readonly IIdentityServerInteractionService _interaction; private readonly IClientStore _clients; - private readonly IResourceStore _resources; private readonly IEventService _events; - public BookingPartnersController(IIdentityServerInteractionService interaction, - IClientStore clients, - IResourceStore resources, - IEventService events) + public BookingPartnersController(IIdentityServerInteractionService interaction, IClientStore clients, IEventService events) { _interaction = interaction; _clients = clients; - _resources = resources; _events = events; } @@ -49,17 +39,19 @@ public BookingPartnersController(IIdentityServerInteractionService interaction, [HttpGet] public async Task Index() { - return View("Index", await BuildViewModelAsync()); + return View("Index", await BuildViewModel()); } /// /// Show list of grants /// [HttpGet] - public async Task Edit(string Id) + public async Task Edit(string id) { - var content = await BuildBookingPartnerViewModelAsync(Id); - if (content == null) return NotFound(); + var content = await BuildBookingPartnerViewModel(id); + if (content == null) + return NotFound(); + return View("BookingPartnerEdit", content); } @@ -79,7 +71,7 @@ public async Task Create() [ValidateAntiForgeryToken] public async Task CreateBookingPartner(string email, string bookingPartnerName) { - var newBookingPartner = new BookingPartnerTable() + var newBookingPartner = new BookingPartnerTable { ClientId = Guid.NewGuid().ToString(), Name = bookingPartnerName, @@ -92,9 +84,28 @@ public async Task CreateBookingPartner(string email, string booki BookingsSuspended = false }; - FakeBookingSystem.Database.AddBookingPartner(newBookingPartner); + await FakeBookingSystem.Database.AddBookingPartner(newBookingPartner); + return View("BookingPartnerEdit", await BuildBookingPartnerViewModel(newBookingPartner.ClientId)); + } + + /// + /// Handle postback to revoke a client + /// + [HttpPost] + [ValidateAntiForgeryToken] + public IActionResult ManageKeys(string clientId) + { + return RedirectToAction("Index"); + } - return View("BookingPartnerEdit", await BuildBookingPartnerViewModelAsync(newBookingPartner.ClientId)); + /// + /// Handle postback to revoke a client + /// + [HttpPost] + [ValidateAntiForgeryToken] + public IActionResult Restore(string clientId) + { + return RedirectToAction("Index"); } /// @@ -121,12 +132,7 @@ public async Task Suspend(string clientId) client.AllowedScopes.Remove("openactive-openbooking"); await _events.RaiseAsync(new GrantsRevokedEvent(User.GetSubjectId(), clientId)); - FakeBookingSystem.Database.UpdateBookingPartnerScope( - clientId, - "openid profile openactive-ordersfeed", - true - ); - + await FakeBookingSystem.Database.UpdateBookingPartnerScope(clientId, "openid profile openactive-ordersfeed", true); return RedirectToAction("Index"); } @@ -137,10 +143,10 @@ public async Task Suspend(string clientId) [ValidateAntiForgeryToken] public async Task RegenerateKey(string clientId) { - var bookingPartner = FakeBookingSystem.Database.GetBookingPartner(clientId); - FakeBookingSystem.Database.SetBookingPartnerKey(clientId, KeyGenerator.GenerateInitialAccessToken(bookingPartner.Name)); + var bookingPartner = await FakeBookingSystem.Database.GetBookingPartner(clientId); + await FakeBookingSystem.Database.SetBookingPartnerKey(clientId, KeyGenerator.GenerateInitialAccessToken(bookingPartner.Name)); - return View("BookingPartnerEdit", await BuildBookingPartnerViewModelAsync(clientId)); + return View("BookingPartnerEdit", await BuildBookingPartnerViewModel(clientId)); } /// @@ -150,24 +156,24 @@ public async Task RegenerateKey(string clientId) [ValidateAntiForgeryToken] public async Task RegenerateAllKeys(string clientId) { - var bookingPartner = FakeBookingSystem.Database.GetBookingPartner(clientId); - FakeBookingSystem.Database.ResetBookingPartnerKey(clientId, KeyGenerator.GenerateInitialAccessToken(bookingPartner.Name)); + var bookingPartner = await FakeBookingSystem.Database.GetBookingPartner(clientId); + await FakeBookingSystem.Database.ResetBookingPartnerKey(clientId, KeyGenerator.GenerateInitialAccessToken(bookingPartner.Name)); // TODO: Is this cached in memory, does it need updating?? //var client = await _clients.FindClientByIdAsync(clientId); //client.ClientSecrets = new List() { new Secret(clientSecret.Sha256()) }; - return View("BookingPartnerEdit", await BuildBookingPartnerViewModelAsync(clientId)); + return View("BookingPartnerEdit", await BuildBookingPartnerViewModel(clientId)); } - private async Task BuildBookingPartnerViewModelAsync(string clientId) + private static async Task BuildBookingPartnerViewModel(string clientId) { // var client = await _clients.FindClientByIdAsync(clientId); - var bookingPartner = FakeBookingSystem.Database.GetBookingPartner(clientId); + var bookingPartner = await FakeBookingSystem.Database.GetBookingPartner(clientId); + if (bookingPartner == null) + return null; - if (bookingPartner == null) return null; - - return new BookingPartnerModel() + return new BookingPartnerModel { ClientId = bookingPartner.ClientId, ClientName = bookingPartner.Name, @@ -176,28 +182,20 @@ private async Task BuildBookingPartnerViewModelAsync(string BookingPartner = bookingPartner }; } - private async Task BuildViewModelAsync() + + private static async Task BuildViewModel() { - var bookingPartners = FakeBookingSystem.Database.GetBookingPartners(); - var list = new List(); - foreach (var bookingPartner in bookingPartners) + var bookingPartners = await FakeBookingSystem.Database.GetBookingPartners(); + var list = bookingPartners.Select(bookingPartner => new BookingPartnerModel { - var item = new BookingPartnerModel() - { - ClientId = bookingPartner.ClientId, - ClientName = bookingPartner.Name, - ClientLogoUrl = bookingPartner.ClientProperties?.LogoUri, - ClientUrl = bookingPartner.ClientProperties?.ClientUri, - BookingPartner = bookingPartner - }; - - list.Add(item); - } - - return new BookingPartnerViewModel - { - BookingPartners = list - }; + ClientId = bookingPartner.ClientId, + ClientName = bookingPartner.Name, + ClientLogoUrl = bookingPartner.ClientProperties?.LogoUri, + ClientUrl = bookingPartner.ClientProperties?.ClientUri, + BookingPartner = bookingPartner + }).ToList(); + + return new BookingPartnerViewModel { BookingPartners = list }; } } } \ No newline at end of file diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Grants/PersistedGrantStore.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Grants/PersistedGrantStore.cs index 9408faa6..4ef01c1a 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Grants/PersistedGrantStore.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Grants/PersistedGrantStore.cs @@ -1,7 +1,6 @@ using IdentityServer4.Models; using IdentityServer4.Stores; using OpenActive.FakeDatabase.NET; -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -10,32 +9,28 @@ namespace IdentityServer { public class AcmePersistedGrantStore : IPersistedGrantStore { - public Task> GetAllAsync(string subjectId) + public async Task> GetAllAsync(string subjectId) { - var grants = FakeBookingSystem.Database.GetAllGrants(subjectId); - - List persistedGrants = new List(); - foreach(var grant in grants) + var grants = await FakeBookingSystem.Database.GetAllGrants(subjectId); + var persistedGrants = grants.Select(grant => new PersistedGrant { - persistedGrants.Add(new PersistedGrant() - { - Key = grant.Key, - Type = grant.Type, - SubjectId = grant.SubjectId, - ClientId = grant.ClientId, - CreationTime = grant.CreationTime, - Expiration = grant.Expiration, - Data = grant.Data - }); - } - return Task.FromResult>(persistedGrants); + Key = grant.Key, + Type = grant.Type, + SubjectId = grant.SubjectId, + ClientId = grant.ClientId, + CreationTime = grant.CreationTime, + Expiration = grant.Expiration, + Data = grant.Data + }).ToList(); + + return persistedGrants; } - public Task GetAsync(string key) + public async Task GetAsync(string key) { - var grant = FakeBookingSystem.Database.GetGrant(key); + var grant = await FakeBookingSystem.Database.GetGrant(key); - return Task.FromResult(grant != null ? new PersistedGrant() + return grant != null ? new PersistedGrant() { Key = grant.Key, Type = grant.Type, @@ -44,27 +39,31 @@ public Task GetAsync(string key) CreationTime = grant.CreationTime, Expiration = grant.Expiration, Data = grant.Data - } : null); + } : null; } - public async Task RemoveAllAsync(string subjectId, string clientId) + public Task RemoveAllAsync(string subjectId, string clientId) { FakeBookingSystem.Database.RemoveGrant(subjectId, clientId); + return Task.CompletedTask; } - public async Task RemoveAllAsync(string subjectId, string clientId, string type) + public Task RemoveAllAsync(string subjectId, string clientId, string type) { FakeBookingSystem.Database.RemoveGrant(subjectId, clientId, type); + return Task.CompletedTask; } - public async Task RemoveAsync(string key) + public Task RemoveAsync(string key) { FakeBookingSystem.Database.RemoveGrant(key); + return Task.CompletedTask; } - public async Task StoreAsync(PersistedGrant grant) + public Task StoreAsync(PersistedGrant grant) { FakeBookingSystem.Database.AddGrant(grant.Key, grant.Type, grant.SubjectId, grant.ClientId, grant.CreationTime, grant.Expiration, grant.Data); + return Task.CompletedTask; } } } diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Profile/ProfileService.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Profile/ProfileService.cs index 510b6a4e..08756234 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Profile/ProfileService.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Profile/ProfileService.cs @@ -1,13 +1,8 @@ using IdentityServer4.Extensions; using IdentityServer4.Models; using IdentityServer4.Services; -using IdentityServer4.Test; -using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; using System.Linq; -using System.Security.Claims; using System.Threading.Tasks; namespace IdentityServer @@ -40,14 +35,14 @@ public ProfileService(IUserRepository users, ILogger logger) /// /// The context. /// - public virtual Task GetProfileDataAsync(ProfileDataRequestContext context) + public virtual async Task GetProfileDataAsync(ProfileDataRequestContext context) { context.LogProfileRequest(Logger); // Claims added here are defined be the API and RESOURCE configurations in Config.cs, only the requested claims will be added to the IssuedClaims collection if (context.RequestedClaimTypes.Any()) { - var user = Users.FindBySubjectId(context.Subject.GetSubjectId()); + var user = await Users.FindBySubjectId(context.Subject.GetSubjectId()); if (user != null) { context.AddRequestedClaims(user.Claims); @@ -57,13 +52,10 @@ public virtual Task GetProfileDataAsync(ProfileDataRequestContext context) { context.IssuedClaims.Add(sellerIdClaim); } - } } context.LogIssuedClaims(Logger); - - return Task.CompletedTask; } /// @@ -72,15 +64,12 @@ public virtual Task GetProfileDataAsync(ProfileDataRequestContext context) /// /// The context. /// - public virtual Task IsActiveAsync(IsActiveContext context) + public virtual async Task IsActiveAsync(IsActiveContext context) { - Logger.LogDebug("IsActive called from: {caller}", context.Caller); + Logger.LogDebug("IsActive called from: {Caller}", context.Caller); - var user = Users.FindBySubjectId(context.Subject.GetSubjectId()); + var user = await Users.FindBySubjectId(context.Subject.GetSubjectId()); context.IsActive = user?.IsActive == true; - - return Task.CompletedTask; } - } } diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Resources/Config.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Resources/Config.cs index 0b7b2bac..0e949d76 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Resources/Config.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Resources/Config.cs @@ -3,7 +3,6 @@ using IdentityModel; -using IdentityServer4; using IdentityServer4.Models; using System.Collections.Generic; diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Resources/CustomIdentityResource.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Resources/CustomIdentityResource.cs index b4f87edb..d5ae5b43 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Resources/CustomIdentityResource.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Resources/CustomIdentityResource.cs @@ -1,8 +1,5 @@ using IdentityServer4.Models; -using System; using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace IdentityServer { diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/Extensions.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/Extensions.cs index 8ebf91c5..358a7df1 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/Extensions.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/Extensions.cs @@ -1,8 +1,4 @@ using Microsoft.Extensions.DependencyInjection; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace IdentityServer { diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/Interfaces.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/Interfaces.cs index d81a4d1f..2900161a 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/Interfaces.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/Interfaces.cs @@ -1,15 +1,11 @@ -using OpenActive.FakeDatabase.NET; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace IdentityServer { public interface IUserRepository { - bool ValidateCredentials(string username, string password); - UserWithClaims FindBySubjectId(string subjectId); - User FindByUsername(string username); + Task ValidateCredentials(string username, string password); + Task FindBySubjectId(string subjectId); + Task FindByUsername(string username); } } diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/ResourceOwnerPasswordValidator.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/ResourceOwnerPasswordValidator.cs index 95224345..07025669 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/ResourceOwnerPasswordValidator.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/ResourceOwnerPasswordValidator.cs @@ -1,8 +1,5 @@ using IdentityModel; using IdentityServer4.Validation; -using System; -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; namespace IdentityServer @@ -16,16 +13,14 @@ public ResourceOwnerPasswordValidator(IUserRepository userRepository) _userRepository = userRepository; } - public Task ValidateAsync(ResourceOwnerPasswordValidationContext context) + public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context) { // context.Username refers to the cardId; context.Password refers to Lastname - if (_userRepository.ValidateCredentials(context.UserName, context.Password)) + if (await _userRepository.ValidateCredentials(context.UserName, context.Password)) { - var user = _userRepository.FindByUsername(context.UserName); + var user = await _userRepository.FindByUsername(context.UserName); context.Result = new GrantValidationResult(user.SubjectId, OidcConstants.AuthenticationMethods.Password); } - - return Task.FromResult(0); } } } diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/UserRepository.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/UserRepository.cs index 09a9bcc8..ae3b5089 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/UserRepository.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Custom/Users/UserRepository.cs @@ -1,8 +1,5 @@ -using IdentityModel; -using OpenActive.FakeDatabase.NET; -using System; +using OpenActive.FakeDatabase.NET; using System.Collections.Generic; -using System.Linq; using System.Security.Claims; using System.Threading.Tasks; @@ -10,33 +7,28 @@ namespace IdentityServer { public class UserRepository : IUserRepository { - private string jsonLdIdBaseUrl; + private readonly string _jsonLdIdBaseUrl; public UserRepository(string jsonLdIdBaseUrl) { - this.jsonLdIdBaseUrl = jsonLdIdBaseUrl; + this._jsonLdIdBaseUrl = jsonLdIdBaseUrl; } - public bool ValidateCredentials(string username, string password) + public Task ValidateCredentials(string username, string password) { return FakeBookingSystem.Database.ValidateSellerUserCredentials(username, password); } - public UserWithClaims FindBySubjectId(string subjectId) + public async Task FindBySubjectId(string subjectId) { - if (long.TryParse(subjectId, out long longSubjectId)) - { - return GetUserFromSellerUserWithClaims(FakeBookingSystem.Database.GetSellerUserById(longSubjectId)); - } - else - { - return null; - } + return long.TryParse(subjectId, out var longSubjectId) + ? GetUserFromSellerUserWithClaims(await FakeBookingSystem.Database.GetSellerUserById(longSubjectId)) + : null; } - public User FindByUsername(string username) + public async Task FindByUsername(string username) { - return GetUserFromSellerUser(FakeBookingSystem.Database.GetSellerUser(username)); + return GetUserFromSellerUser(await FakeBookingSystem.Database.GetSellerUser(username)); } // TODO: Make this an extension method @@ -58,16 +50,19 @@ private UserWithClaims GetUserFromSellerUserWithClaims(SellerUserTable sellerUse IsActive = true, Claims = new List() }; + AddClaimIfNotNull(user.Claims, "https://openactive.io/sellerName", sellerUser.SellerTable.Name); - AddClaimIfNotNull(user.Claims, "https://openactive.io/sellerId", jsonLdIdBaseUrl + "/api/identifiers/sellers/" + sellerUser.SellerTable.Id); + AddClaimIfNotNull(user.Claims, "https://openactive.io/sellerId", _jsonLdIdBaseUrl + "/api/identifiers/sellers/" + sellerUser.SellerTable.Id); AddClaimIfNotNull(user.Claims, "https://openactive.io/sellerUrl", sellerUser.SellerTable.Url); AddClaimIfNotNull(user.Claims, "https://openactive.io/sellerLogo", sellerUser.SellerTable.LogoUrl); return user; } - private User GetUserFromSellerUser(SellerUserTable sellerUser) + private static User GetUserFromSellerUser(SellerUserTable sellerUser) { - if (sellerUser == null) return null; + if (sellerUser == null) + return null; + return new User { Username = sellerUser.Username, diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Program.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Program.cs index 8c6d9a5d..e5fb8053 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Program.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Program.cs @@ -43,7 +43,7 @@ public static int Main(string[] args) } catch (Exception ex) { - Log.Fatal(ex, "Host terminated unexpectedly."); + Log.Fatal(ex, "Host terminated unexpectedly"); return 1; } finally diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Startup.cs b/Examples/BookingSystem.AspNetCore.IdentityServer/Startup.cs index b759c40f..aaf3bebf 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Startup.cs +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Startup.cs @@ -1,15 +1,12 @@ // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - -using IdentityServer4.Services; using IdentityServer4.Stores; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Configuration; -using src; namespace IdentityServer { diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/Views/BookingPartners/BookingPartnerCreate.cshtml b/Examples/BookingSystem.AspNetCore.IdentityServer/Views/BookingPartners/BookingPartnerCreate.cshtml index b010dae8..e94a7db3 100644 --- a/Examples/BookingSystem.AspNetCore.IdentityServer/Views/BookingPartners/BookingPartnerCreate.cshtml +++ b/Examples/BookingSystem.AspNetCore.IdentityServer/Views/BookingPartners/BookingPartnerCreate.cshtml @@ -1,7 +1,6 @@ @model BookingPartnerModel -@using System; -
+
- public static FakeDatabase Database { get; } = FakeDatabase.GetPrepopulatedFakeDatabase(); + public static FakeDatabase Database { get; } = FakeDatabase.GetPrepopulatedFakeDatabase().Result; public static void Initialise() { @@ -31,13 +32,19 @@ public static void Initialise() // This SQLite database file is shared between the Booking System and Identity Server, and // Initialise() must be called on startup of each to ensure they do not wipe the database // on the first call to it +#pragma warning disable 4014 Database.GetBookingPartners(); +#pragma warning restore 4014 } public static DateTime Truncate(this DateTime dateTime, TimeSpan timeSpan) { - if (timeSpan == TimeSpan.Zero) return dateTime; // Or could throw an ArgumentException - if (dateTime == DateTime.MinValue || dateTime == DateTime.MaxValue) return dateTime; // do not modify "guard" values + if (timeSpan == TimeSpan.Zero) + return dateTime; // Or could throw an ArgumentException + + if (dateTime == DateTime.MinValue || dateTime == DateTime.MaxValue) + return dateTime; // do not modify "guard" values + return dateTime.AddTicks(-(dateTime.Ticks % timeSpan.Ticks)); } } @@ -54,7 +61,8 @@ internal static class HashExtensions /// A hash public static string Sha256(this string input) { - if (string.IsNullOrWhiteSpace(input)) return string.Empty; + if (string.IsNullOrWhiteSpace(input)) + return string.Empty; using (var sha = SHA256.Create()) { @@ -75,7 +83,7 @@ public InMemorySQLite() { // ServiceStack registers a memory cache client by default https://docs.servicestack.net/caching // There are issues with transactions when using full in-memory SQLite. To workaround this, we create a temporary file and use this to hold the SQLite database. - string connectionString = Path.GetTempPath() + "openactive-fakedatabase.db"; + var connectionString = Path.GetTempPath() + "openactive-fakedatabase.db"; Database = new OrmLiteConnectionFactory(connectionString, SqliteDialect.Provider); using (var connection = Database.Open()) @@ -172,35 +180,35 @@ static FakeDatabase() /// /// TODO: Call this on a schedule from both .NET Core and .NET Framework reference implementations /// - public void CleanupExpiredLeases() + public async Task CleanupExpiredLeases() { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { var occurrenceIds = new List(); var slotIds = new List(); - foreach (var order in db.Select(x => x.LeaseExpires < DateTimeOffset.Now)) + foreach (var order in await db.SelectAsync(x => x.LeaseExpires < DateTimeOffset.Now)) { // ReSharper disable twice PossibleInvalidOperationException - occurrenceIds.AddRange(db.Select(x => x.OrderId == order.OrderId && x.OccurrenceId.HasValue).Select(x => x.OccurrenceId.Value)); - slotIds.AddRange(db.Select(x => x.OrderId == order.OrderId && x.SlotId.HasValue).Select(x => x.SlotId.Value)); - db.Delete(x => x.OrderId == order.OrderId); - db.Delete(x => x.OrderId == order.OrderId); + occurrenceIds.AddRange((await db.SelectAsync(x => x.OrderId == order.OrderId && x.OccurrenceId.HasValue)).Select(x => x.OccurrenceId.Value)); + slotIds.AddRange((await db.SelectAsync(x => x.OrderId == order.OrderId && x.SlotId.HasValue)).Select(x => x.SlotId.Value)); + await db.DeleteAsync(x => x.OrderId == order.OrderId); + await db.DeleteAsync(x => x.OrderId == order.OrderId); } - RecalculateSpaces(db, occurrenceIds.Distinct()); - RecalculateSlotUses(db, slotIds.Distinct()); + await RecalculateSpaces(db, occurrenceIds.Distinct()); + await RecalculateSlotUses(db, slotIds.Distinct()); } } - public static bool AddLease(string clientId, Guid uuid, BrokerRole brokerRole, string brokerName, Uri brokerUrl, string brokerTelephone, long? sellerId, string customerEmail, DateTimeOffset leaseExpires, FakeDatabaseTransaction transaction) + public static async Task AddLease(string clientId, Guid uuid, BrokerRole brokerRole, string brokerName, Uri brokerUrl, string brokerTelephone, long? sellerId, string customerEmail, DateTimeOffset leaseExpires, FakeDatabaseTransaction transaction) { var db = transaction.DatabaseConnection; - var existingOrder = db.Single(x => x.ClientId == clientId && x.OrderId == uuid.ToString()); + var existingOrder = await db.SingleAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString()); if (existingOrder == null) { - db.Insert(new OrderTable + await db.InsertAsync(new OrderTable { ClientId = clientId, OrderId = uuid.ToString(), @@ -215,32 +223,29 @@ public static bool AddLease(string clientId, Guid uuid, BrokerRole brokerRole, s LeaseExpires = leaseExpires.DateTime, VisibleInOrdersFeed = FeedVisibility.None }); + return true; } + // Return false if there's a clash with an existing Order or OrderProposal - else if (existingOrder.OrderMode != OrderMode.Lease || existingOrder.Deleted) - { + if (existingOrder.OrderMode != OrderMode.Lease || existingOrder.Deleted) return false; - } - // Reuse existing lease if it exists - else - { - existingOrder.BrokerRole = brokerRole; - existingOrder.BrokerName = brokerName; - existingOrder.BrokerUrl = brokerUrl; - existingOrder.BrokerTelephone = brokerTelephone; - existingOrder.SellerId = sellerId ?? 1; - existingOrder.CustomerEmail = customerEmail; - existingOrder.OrderMode = OrderMode.Lease; - existingOrder.LeaseExpires = leaseExpires.DateTime; - db.Update(existingOrder); - - // TODO: Remove this and improve leasing logic to add/update rather than delete/replace - // Remove previous lease - db.Delete(x => x.OrderId == existingOrder.OrderId); - return true; - } + // Reuse existing lease if it exists + existingOrder.BrokerRole = brokerRole; + existingOrder.BrokerName = brokerName; + existingOrder.BrokerUrl = brokerUrl; + existingOrder.BrokerTelephone = brokerTelephone; + existingOrder.SellerId = sellerId ?? 1; + existingOrder.CustomerEmail = customerEmail; + existingOrder.OrderMode = OrderMode.Lease; + existingOrder.LeaseExpires = leaseExpires.DateTime; + await db.UpdateAsync(existingOrder); + + // TODO: Remove this and improve leasing logic to add/update rather than delete/replace + // Remove previous lease + await db.DeleteAsync(x => x.OrderId == existingOrder.OrderId); + return true; } /// @@ -249,23 +254,21 @@ public static bool AddLease(string clientId, Guid uuid, BrokerRole brokerRole, s /// /// /// - public bool UpdateFacilityUseName(long slotId, string newName) + public async Task UpdateFacilityUseName(long slotId, string newName) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { var query = db.From() - .LeftJoin() - .Where(x => x.Id == slotId) - .And(y => !y.Deleted); - var facilityUse = db.Select(query).Single(); + .LeftJoin() + .Where(x => x.Id == slotId) + .And(y => !y.Deleted); + var facilityUse = (await db.SelectAsync(query)).Single(); if (facilityUse == null) - { return false; - } facilityUse.Name = newName; facilityUse.Modified = DateTimeOffset.Now.UtcTicks; - db.Update(facilityUse); + await db.UpdateAsync(facilityUse); return true; } } @@ -276,20 +279,18 @@ public bool UpdateFacilityUseName(long slotId, string newName) /// /// /// - public bool UpdateFacilitySlotStartAndEndTimeByPeriodInMins(long slotId, int numberOfMins) + public async Task UpdateFacilitySlotStartAndEndTimeByPeriodInMins(long slotId, int numberOfMins) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - var slot = db.Single(x => x.Id == slotId && !x.Deleted); + var slot = await db.SingleAsync(x => x.Id == slotId && !x.Deleted); if (slot == null) - { return false; - } - slot.Start.AddMinutes(numberOfMins); - slot.End.AddMinutes(numberOfMins); + slot.Start = slot.Start.AddMinutes(numberOfMins); + slot.End = slot.End.AddMinutes(numberOfMins); slot.Modified = DateTimeOffset.Now.UtcTicks; - db.Update(slot); + await db.UpdateAsync(slot); return true; } } @@ -301,24 +302,22 @@ public bool UpdateFacilitySlotStartAndEndTimeByPeriodInMins(long slotId, int num /// /// /// - public bool UpdateFacilityUseLocationLatLng(long slotId, decimal newLat, decimal newLng) + public async Task UpdateFacilityUseLocationLatLng(long slotId, decimal newLat, decimal newLng) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { var query = db.From() - .LeftJoin() - .Where(x => x.Id == slotId) - .And(y => !y.Deleted); - var facilityUse = db.Select(query).Single(); + .LeftJoin() + .Where(x => x.Id == slotId) + .And(y => !y.Deleted); + var facilityUse = (await db.SelectAsync(query)).Single(); if (facilityUse == null) - { return false; - } facilityUse.LocationLat = newLat; facilityUse.LocationLng = newLng; facilityUse.Modified = DateTimeOffset.Now.UtcTicks; - db.Update(facilityUse); + await db.UpdateAsync(facilityUse); return true; } } @@ -329,23 +328,21 @@ public bool UpdateFacilityUseLocationLatLng(long slotId, decimal newLat, decimal /// /// /// - public bool UpdateClassTitle(long occurrenceId, string newTitle) + public async Task UpdateClassTitle(long occurrenceId, string newTitle) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { var query = db.From() .LeftJoin() .Where(x => x.Id == occurrenceId) .And(y => !y.Deleted); - var classInstance = db.Select(query).Single(); + var classInstance = await db.SingleAsync(query); if (classInstance == null) - { return false; - } classInstance.Title = newTitle; classInstance.Modified = DateTimeOffset.Now.UtcTicks; - db.Update(classInstance); + await db.UpdateAsync(classInstance); return true; } } @@ -356,20 +353,18 @@ public bool UpdateClassTitle(long occurrenceId, string newTitle) /// /// /// - public bool UpdateScheduledSessionStartAndEndTimeByPeriodInMins(long occurrenceId, int numberOfMins) + public async Task UpdateScheduledSessionStartAndEndTimeByPeriodInMins(long occurrenceId, int numberOfMins) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - var occurrence = db.Single(x => x.Id == occurrenceId && !x.Deleted); + var occurrence = await db.SingleAsync(x => x.Id == occurrenceId && !x.Deleted); if (occurrence == null) - { return false; - } - occurrence.Start.AddMinutes(numberOfMins); - occurrence.End.AddMinutes(numberOfMins); + occurrence.Start = occurrence.Start.AddMinutes(numberOfMins); + occurrence.End = occurrence.End.AddMinutes(numberOfMins); occurrence.Modified = DateTimeOffset.Now.UtcTicks; - db.Update(occurrence); + await db.UpdateAsync(occurrence); return true; } } @@ -381,42 +376,38 @@ public bool UpdateScheduledSessionStartAndEndTimeByPeriodInMins(long occurrenceI /// /// /// - public bool UpdateSessionSeriesLocationLatLng(long occurrenceId, decimal newLat, decimal newLng) + public async Task UpdateSessionSeriesLocationLatLng(long occurrenceId, decimal newLat, decimal newLng) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { var query = db.From() .LeftJoin() .Where(x => x.Id == occurrenceId) .And(y => !y.Deleted); - var classInstance = db.Select(query).Single(); + var classInstance = await db.SingleAsync(query); if (classInstance == null) - { return false; - } classInstance.LocationLat = newLat; classInstance.LocationLng = newLng; classInstance.Modified = DateTimeOffset.Now.UtcTicks; - db.Update(classInstance); + await db.UpdateAsync(classInstance); return true; } } - public bool UpdateAccess(Guid uuid, bool updateAccessPass = false, bool updateAccessCode = false, bool updateAccessChannel = false) + public async Task UpdateAccess(Guid uuid, bool updateAccessPass = false, bool updateAccessCode = false, bool updateAccessChannel = false) { if (!updateAccessPass && !updateAccessCode && !updateAccessChannel) - { return false; - } - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - OrderTable order = db.Single(x => x.OrderId == uuid.ToString() && !x.Deleted); + OrderTable order = await db.SingleAsync(x => x.OrderId == uuid.ToString() && !x.Deleted); if (order != null) { - List orderItems = db.Select(x => x.OrderId == order.OrderId); + List orderItems = await db.SelectAsync(x => x.OrderId == order.OrderId); foreach (OrderItemsTable orderItem in orderItems) { @@ -441,32 +432,30 @@ public bool UpdateAccess(Guid uuid, bool updateAccessPass = false, bool updateAc } orderItem.Modified = DateTimeOffset.Now.UtcTicks; - db.Save(orderItem); + await db.SaveAsync(orderItem); } } order.OrderModified = DateTimeOffset.Now.UtcTicks; order.VisibleInOrdersFeed = FeedVisibility.Visible; - db.Update(order); + await db.UpdateAsync(order); return true; } - else - { - return false; - } + + return false; } } - public bool UpdateOpportunityAttendance(Guid uuid, bool attended) + public async Task UpdateOpportunityAttendance(Guid uuid, bool attended) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - OrderTable order = db.Single(x => x.OrderId == uuid.ToString() && !x.Deleted); + OrderTable order = await db.SingleAsync(x => x.OrderId == uuid.ToString() && !x.Deleted); if (order != null) { - List orderItems = db.Select(x => x.OrderId == order.OrderId); + List orderItems = await db.SelectAsync(x => x.OrderId == order.OrderId); foreach (OrderItemsTable orderItem in orderItems) { @@ -474,75 +463,71 @@ public bool UpdateOpportunityAttendance(Guid uuid, bool attended) { orderItem.Status = attended ? BookingStatus.Attended : BookingStatus.Absent; orderItem.Modified = DateTimeOffset.Now.UtcTicks; - db.Update(orderItem); + await db.UpdateAsync(orderItem); } } order.OrderModified = DateTimeOffset.Now.UtcTicks; order.VisibleInOrdersFeed = FeedVisibility.Visible; - db.Update(order); + await db.UpdateAsync(order); return true; } - else - { - return false; - } + + return false; } } - public bool AddCustomerNotice(Guid uuid) + public async Task AddCustomerNotice(Guid uuid) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - OrderTable order = db.Single(x => x.OrderId == uuid.ToString() && !x.Deleted); + OrderTable order = await db.SingleAsync(x => x.OrderId == uuid.ToString() && !x.Deleted); if (order != null) { - List orderItems = db.Select(x => x.OrderId == order.OrderId); + List orderItems = await db.SelectAsync(x => x.OrderId == order.OrderId); foreach (OrderItemsTable orderItem in orderItems) { if (orderItem.Status == BookingStatus.Confirmed || orderItem.Status == BookingStatus.None) { orderItem.CustomerNotice = $"customer notice message: {Faker.Random.String(10, minChar: 'a', maxChar: 'z')}"; orderItem.Modified = DateTimeOffset.Now.UtcTicks; - db.Update(orderItem); + await db.UpdateAsync(orderItem); } } order.OrderModified = DateTimeOffset.Now.UtcTicks; order.VisibleInOrdersFeed = FeedVisibility.Visible; - db.Update(order); + await db.UpdateAsync(order); return true; } - else - { - return false; - } + + return false; } } - public void DeleteLease(string clientId, Guid uuid, long? sellerId) + public async Task DeleteLease(string clientId, Guid uuid, long? sellerId) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { // TODO: Note this should throw an error if the Seller ID does not match, same as DeleteOrder - if (db.Exists(x => x.ClientId == clientId && x.OrderMode == OrderMode.Lease && x.OrderId == uuid.ToString() && (!sellerId.HasValue || x.SellerId == sellerId))) + if (await db.ExistsAsync(x => x.ClientId == clientId && x.OrderMode == OrderMode.Lease && x.OrderId == uuid.ToString() && (!sellerId.HasValue || x.SellerId == sellerId))) { // ReSharper disable twice PossibleInvalidOperationException - var occurrenceIds = db.Select(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.OccurrenceId.HasValue).Select(x => x.OccurrenceId.Value).Distinct(); - var slotIds = db.Select(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.SlotId.HasValue).Select(x => x.SlotId.Value).Distinct(); + var occurrenceIds = (await db.SelectAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.OccurrenceId.HasValue)).Select(x => x.OccurrenceId.Value).Distinct(); + var slotIds = (await db.SelectAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.SlotId.HasValue)).Select(x => x.SlotId.Value).Distinct(); - db.Delete(x => x.ClientId == clientId && x.OrderId == uuid.ToString()); - db.Delete(x => x.ClientId == clientId && x.OrderId == uuid.ToString()); + await db.DeleteAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString()); + await db.DeleteAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString()); - RecalculateSpaces(db, occurrenceIds); - RecalculateSlotUses(db, slotIds); + await RecalculateSpaces(db, occurrenceIds); + await RecalculateSlotUses(db, slotIds); } } } - public static bool AddOrder( + public static async Task AddOrder( string clientId, Guid uuid, BrokerRole brokerRole, string brokerName, Uri brokerUrl, string brokerTelephone, long? sellerId, string customerEmail, CustomerType customerType, string customerOrganizationName, string customerIdentifier, string customerGivenName, string customerFamilyName, string customerTelephone, @@ -551,10 +536,10 @@ public static bool AddOrder( { var db = transaction.DatabaseConnection; - var existingOrder = db.Single(x => x.ClientId == clientId && x.OrderId == uuid.ToString()); + var existingOrder = await db.SingleAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString()); if (existingOrder == null) { - db.Insert(new OrderTable + await db.InsertAsync(new OrderTable { ClientId = clientId, OrderId = uuid.ToString(), @@ -584,69 +569,65 @@ public static bool AddOrder( return true; } // Return false if there's a clash with an existing Order or OrderProposal - else if (existingOrder.OrderMode != OrderMode.Lease || existingOrder.Deleted) + + if (existingOrder.OrderMode != OrderMode.Lease || existingOrder.Deleted) { return false; } // Reuse existing lease if it exists - else - { - existingOrder.BrokerRole = brokerRole; - existingOrder.BrokerName = brokerName; - existingOrder.BrokerUrl = brokerUrl; - existingOrder.BrokerTelephone = brokerTelephone; - existingOrder.SellerId = sellerId ?? 1; - existingOrder.CustomerEmail = customerEmail; - existingOrder.CustomerType = customerType; - existingOrder.CustomerOrganizationName = customerOrganizationName; - existingOrder.CustomerIdentifier = customerIdentifier; - existingOrder.CustomerGivenName = customerGivenName; - existingOrder.CustomerFamilyName = customerFamilyName; - existingOrder.CustomerTelephone = customerTelephone; - existingOrder.PaymentIdentifier = paymentIdentifier; - existingOrder.PaymentName = paymentName; - existingOrder.PaymentProviderId = paymentProviderId; - existingOrder.PaymentAccountId = paymentAccountId; - existingOrder.TotalOrderPrice = totalOrderPrice; - existingOrder.OrderMode = proposalVersionUuid != null ? OrderMode.Proposal : OrderMode.Booking; - existingOrder.ProposalVersionId = proposalVersionUuid; - existingOrder.ProposalStatus = proposalStatus; - db.Update(existingOrder); - - return true; - } - } - - public (FakeDatabaseGetOrderResult, OrderTable, List) GetOrderAndOrderItems(string clientId, long? sellerId, Guid uuid) - { - using (var db = Mem.Database.Open()) - { - var order = db.Single(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && !x.Deleted && (!sellerId.HasValue || x.SellerId == sellerId)); + existingOrder.BrokerRole = brokerRole; + existingOrder.BrokerName = brokerName; + existingOrder.BrokerUrl = brokerUrl; + existingOrder.BrokerTelephone = brokerTelephone; + existingOrder.SellerId = sellerId ?? 1; + existingOrder.CustomerEmail = customerEmail; + existingOrder.CustomerType = customerType; + existingOrder.CustomerOrganizationName = customerOrganizationName; + existingOrder.CustomerIdentifier = customerIdentifier; + existingOrder.CustomerGivenName = customerGivenName; + existingOrder.CustomerFamilyName = customerFamilyName; + existingOrder.CustomerTelephone = customerTelephone; + existingOrder.PaymentIdentifier = paymentIdentifier; + existingOrder.PaymentName = paymentName; + existingOrder.PaymentProviderId = paymentProviderId; + existingOrder.PaymentAccountId = paymentAccountId; + existingOrder.TotalOrderPrice = totalOrderPrice; + existingOrder.OrderMode = proposalVersionUuid != null ? OrderMode.Proposal : OrderMode.Booking; + existingOrder.ProposalVersionId = proposalVersionUuid; + existingOrder.ProposalStatus = proposalStatus; + await db.UpdateAsync(existingOrder); + + return true; + } + + public async Task<(FakeDatabaseGetOrderResult, OrderTable, List)> GetOrderAndOrderItems(string clientId, long? sellerId, Guid uuid) + { + using (var db = await Mem.Database.OpenAsync()) + { + var order = await db.SingleAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && !x.Deleted && (!sellerId.HasValue || x.SellerId == sellerId)); if (order == null) return (FakeDatabaseGetOrderResult.OrderWasNotFound, null, null); - var orderItems = db.Select(x => x.ClientId == clientId && x.OrderId == uuid.ToString()); + var orderItems = await db.SelectAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString()); if (orderItems.Count == 0) return (FakeDatabaseGetOrderResult.OrderWasNotFound, null, null); return (FakeDatabaseGetOrderResult.OrderSuccessfullyGot, order, orderItems); } } - public (bool, ClassTable, OccurrenceTable, BookedOrderItemInfo) GetOccurrenceAndBookedOrderItemInfoByOccurrenceId(Guid uuid, long? occurrenceId) + public async Task<(bool, ClassTable, OccurrenceTable, BookedOrderItemInfo)> GetOccurrenceAndBookedOrderItemInfoByOccurrenceId(Guid uuid, long? occurrenceId) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { var query = db.From() .LeftJoin() - .Where((x) => x.Id == occurrenceId); + .Where(x => x.Id == occurrenceId); var rows = db.SelectMulti(query); - var hasFoundOccurrence = false; if (!rows.Any()) - { - return (hasFoundOccurrence, null, null, null); - } + return (true, null, null, null); + var (occurrence, thisClass) = rows.FirstOrDefault(); - var orderItem = db.Single(x => x.OrderId == uuid.ToString() && x.OccurrenceId == occurrenceId); - var bookedOrderItemInfo = (orderItem != null && orderItem.Status == BookingStatus.Confirmed) ? + var orderItem = await db.SingleAsync(x => x.OrderId == uuid.ToString() && x.OccurrenceId == occurrenceId); + var bookedOrderItemInfo = orderItem != null && orderItem.Status == BookingStatus.Confirmed ? new BookedOrderItemInfo { OrderItemId = orderItem.Id, @@ -659,9 +640,8 @@ public static bool AddOrder( } : null; - hasFoundOccurrence = true; return ( - hasFoundOccurrence, + true, thisClass, occurrence, bookedOrderItemInfo @@ -669,21 +649,19 @@ public static bool AddOrder( } } - public (bool, FacilityUseTable, SlotTable, BookedOrderItemInfo) GetSlotAndBookedOrderItemInfoBySlotId(Guid uuid, long? slotId) + public async Task<(bool, FacilityUseTable, SlotTable, BookedOrderItemInfo)> GetSlotAndBookedOrderItemInfoBySlotId(Guid uuid, long? slotId) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { var query = db.From() .LeftJoin() - .Where((x) => x.Id == slotId); + .Where(x => x.Id == slotId); var rows = db.SelectMulti(query); - var hasFoundOccurrence = false; if (!rows.Any()) - { - return (hasFoundOccurrence, null, null, null); - } + return (false, null, null, null); + var (slot, facilityUse) = rows.FirstOrDefault(); - var orderItem = db.Single(x => x.OrderId == uuid.ToString() && x.SlotId == slotId); + var orderItem = await db.SingleAsync(x => x.OrderId == uuid.ToString() && x.SlotId == slotId); var bookedOrderItemInfo = (orderItem != null && orderItem.Status == BookingStatus.Confirmed) ? new BookedOrderItemInfo { @@ -694,9 +672,8 @@ public static bool AddOrder( } : null; - hasFoundOccurrence = true; return ( - hasFoundOccurrence, + true, facilityUse, slot, bookedOrderItemInfo @@ -704,12 +681,12 @@ public static bool AddOrder( } } - public FakeDatabaseDeleteOrderResult DeleteOrder(string clientId, Guid uuid, long? sellerId) + public async Task DeleteOrder(string clientId, Guid uuid, long? sellerId) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { // Set the Order to deleted in the feed, and erase all associated personal data - var order = db.Single(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.OrderMode != OrderMode.Lease); + var order = await db.SingleAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.OrderMode != OrderMode.Lease); if (order == null) { return FakeDatabaseDeleteOrderResult.OrderWasNotFound; @@ -725,24 +702,24 @@ public FakeDatabaseDeleteOrderResult DeleteOrder(string clientId, Guid uuid, lon order.Deleted = true; order.CustomerEmail = null; order.OrderModified = DateTimeOffset.Now.UtcTicks; - db.Update(order); + await db.UpdateAsync(order); - var occurrenceIds = db.Select(x => x.ClientId == clientId && x.OrderId == order.OrderId && x.OccurrenceId.HasValue).Select(x => x.OccurrenceId.Value).Distinct(); - var slotIds = db.Select(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.SlotId.HasValue).Select(x => x.SlotId.Value).Distinct(); - db.Delete(x => x.ClientId == clientId && x.OrderId == order.OrderId); + var occurrenceIds = (await db.SelectAsync(x => x.ClientId == clientId && x.OrderId == order.OrderId && x.OccurrenceId.HasValue)).Select(x => x.OccurrenceId.Value).Distinct(); + var slotIds = (await db.SelectAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.SlotId.HasValue)).Select(x => x.SlotId.Value).Distinct(); + await db.DeleteAsync(x => x.ClientId == clientId && x.OrderId == order.OrderId); - RecalculateSpaces(db, occurrenceIds); - RecalculateSlotUses(db, slotIds); + await RecalculateSpaces(db, occurrenceIds); + await RecalculateSlotUses(db, slotIds); return FakeDatabaseDeleteOrderResult.OrderSuccessfullyDeleted; } } - public static (ReserveOrderItemsResult, long?, long?) LeaseOrderItemsForClassOccurrence(FakeDatabaseTransaction transaction, string clientId, long? sellerId, Guid uuid, long occurrenceId, long spacesRequested) + public static async Task<(ReserveOrderItemsResult, long?, long?)> LeaseOrderItemsForClassOccurrence(FakeDatabaseTransaction transaction, string clientId, long? sellerId, Guid uuid, long occurrenceId, long spacesRequested) { var db = transaction.DatabaseConnection; - var thisOccurrence = db.Single(x => x.Id == occurrenceId && !x.Deleted); - var thisClass = db.Single(x => x.Id == thisOccurrence.ClassId && !x.Deleted); + var thisOccurrence = await db.SingleAsync(x => x.Id == occurrenceId && !x.Deleted); + var thisClass = await db.SingleAsync(x => x.Id == thisOccurrence.ClassId && !x.Deleted); if (thisOccurrence == null || thisClass == null) return (ReserveOrderItemsResult.OpportunityNotFound, null, null); @@ -755,8 +732,8 @@ public static (ReserveOrderItemsResult, long?, long?) LeaseOrderItemsForClassOcc // Remove existing leases // Note a real implementation would likely maintain existing leases instead of removing and recreating them - db.Delete(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.OccurrenceId == occurrenceId); - RecalculateSpaces(db, thisOccurrence); + await db.DeleteAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.OccurrenceId == occurrenceId); + await RecalculateSpaces(db, thisOccurrence); // Only lease if all spaces requested are available if (thisOccurrence.RemainingSpaces - thisOccurrence.LeasedSpaces < spacesRequested) @@ -769,7 +746,7 @@ public static (ReserveOrderItemsResult, long?, long?) LeaseOrderItemsForClassOcc for (var i = 0; i < spacesRequested; i++) { - db.Insert(new OrderItemsTable + await db.InsertAsync(new OrderItemsTable { ClientId = clientId, Deleted = false, @@ -780,15 +757,15 @@ public static (ReserveOrderItemsResult, long?, long?) LeaseOrderItemsForClassOcc } // Update number of spaces remaining for the opportunity - RecalculateSpaces(db, thisOccurrence); + await RecalculateSpaces(db, thisOccurrence); return (ReserveOrderItemsResult.Success, null, null); } - public static (ReserveOrderItemsResult, long?, long?) LeaseOrderItemsForFacilitySlot(FakeDatabaseTransaction transaction, string clientId, long? sellerId, Guid uuid, long slotId, long spacesRequested) + public static async Task<(ReserveOrderItemsResult, long?, long?)> LeaseOrderItemsForFacilitySlot(FakeDatabaseTransaction transaction, string clientId, long? sellerId, Guid uuid, long slotId, long spacesRequested) { var db = transaction.DatabaseConnection; - var thisSlot = db.Single(x => x.Id == slotId && !x.Deleted); - var thisFacility = db.Single(x => x.Id == thisSlot.FacilityUseId && !x.Deleted); + var thisSlot = await db.SingleAsync(x => x.Id == slotId && !x.Deleted); + var thisFacility = await db.SingleAsync(x => x.Id == thisSlot.FacilityUseId && !x.Deleted); if (thisSlot == null || thisFacility == null) return (ReserveOrderItemsResult.OpportunityNotFound, null, null); @@ -801,8 +778,8 @@ public static (ReserveOrderItemsResult, long?, long?) LeaseOrderItemsForFacility // Remove existing leases // Note a real implementation would likely maintain existing leases instead of removing and recreating them - db.Delete(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.SlotId == slotId); - RecalculateSlotUses(db, thisSlot); + await db.DeleteAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.SlotId == slotId); + await RecalculateSlotUses(db, thisSlot); // Only lease if all spaces requested are available if (thisSlot.RemainingUses - thisSlot.LeasedUses < spacesRequested) @@ -815,7 +792,7 @@ public static (ReserveOrderItemsResult, long?, long?) LeaseOrderItemsForFacility for (var i = 0; i < spacesRequested; i++) { - db.Insert(new OrderItemsTable + await db.InsertAsync(new OrderItemsTable { ClientId = clientId, Deleted = false, @@ -826,7 +803,7 @@ public static (ReserveOrderItemsResult, long?, long?) LeaseOrderItemsForFacility } // Update number of spaces remaining for the opportunity - RecalculateSlotUses(db, thisSlot); + await RecalculateSlotUses(db, thisSlot); return (ReserveOrderItemsResult.Success, null, null); } @@ -843,7 +820,7 @@ public class BookedOrderItemInfo } // TODO this should reuse code of LeaseOrderItemsForClassOccurrence - public static (ReserveOrderItemsResult, List) BookOrderItemsForClassOccurrence( + public static async Task<(ReserveOrderItemsResult, List)> BookOrderItemsForClassOccurrence( FakeDatabaseTransaction transaction, string clientId, long? sellerId, @@ -856,8 +833,8 @@ bool proposal ) { var db = transaction.DatabaseConnection; - var thisOccurrence = db.Single(x => x.Id == occurrenceId && !x.Deleted); - var thisClass = db.Single(x => x.Id == thisOccurrence.ClassId && !x.Deleted); + var thisOccurrence = await db.SingleAsync(x => x.Id == occurrenceId && !x.Deleted); + var thisClass = await db.SingleAsync(x => x.Id == thisOccurrence.ClassId && !x.Deleted); if (thisOccurrence == null || thisClass == null) return (ReserveOrderItemsResult.OpportunityNotFound, null); @@ -870,8 +847,8 @@ bool proposal // Remove existing leases // Note a real implementation would likely maintain existing leases instead of removing and recreating them - db.Delete(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.OccurrenceId == occurrenceId); - RecalculateSpaces(db, thisOccurrence); + await db.DeleteAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.OccurrenceId == occurrenceId); + await RecalculateSpaces(db, thisOccurrence); // Only lease if all spaces requested are available if (thisOccurrence.RemainingSpaces - thisOccurrence.LeasedSpaces < numberOfSpaces) @@ -898,7 +875,7 @@ bool proposal MeetingId = thisClass.AttendanceMode != AttendanceMode.Offline ? Faker.Random.String(length: 10, minChar: '0', maxChar: '9') : null, MeetingPassword = thisClass.AttendanceMode != AttendanceMode.Offline ? Faker.Random.String(length: 10, minChar: '0', maxChar: '9') : null }; - db.Save(orderItem); + await db.SaveAsync(orderItem); bookedOrderItemInfos.Add(new BookedOrderItemInfo { OrderItemId = orderItem.Id, @@ -911,12 +888,12 @@ bool proposal }); } - RecalculateSpaces(db, thisOccurrence); + await RecalculateSpaces(db, thisOccurrence); return (ReserveOrderItemsResult.Success, bookedOrderItemInfos); } // TODO this should reuse code of LeaseOrderItemsForFacilityOccurrence - public static (ReserveOrderItemsResult, List) BookOrderItemsForFacilitySlot( + public static async Task<(ReserveOrderItemsResult, List)> BookOrderItemsForFacilitySlot( FakeDatabaseTransaction transaction, string clientId, long? sellerId, @@ -929,8 +906,8 @@ bool proposal ) { var db = transaction.DatabaseConnection; - var thisSlot = db.Single(x => x.Id == slotId && !x.Deleted); - var thisFacility = db.Single(x => x.Id == thisSlot.FacilityUseId && !x.Deleted); + var thisSlot = await db.SingleAsync(x => x.Id == slotId && !x.Deleted); + var thisFacility = await db.SingleAsync(x => x.Id == thisSlot.FacilityUseId && !x.Deleted); if (thisSlot == null || thisFacility == null) return (ReserveOrderItemsResult.OpportunityNotFound, null); @@ -943,8 +920,8 @@ bool proposal // Remove existing leases // Note a real implementation would likely maintain existing leases instead of removing and recreating them - db.Delete(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.SlotId == slotId); - RecalculateSlotUses(db, thisSlot); + await db.DeleteAsync(x => x.ClientId == clientId && x.OrderId == uuid.ToString() && x.SlotId == slotId); + await RecalculateSlotUses(db, thisSlot); // Only lease if all spaces requested are available if (thisSlot.RemainingUses - thisSlot.LeasedUses < numberOfSpaces) @@ -969,7 +946,7 @@ bool proposal BarCodeText = Faker.Random.String(length: 10, minChar: '0', maxChar: '9') }; - db.Save(orderItem); + await db.SaveAsync(orderItem); bookedOrderItemInfos.Add(new BookedOrderItemInfo { @@ -980,18 +957,18 @@ bool proposal }); } - RecalculateSlotUses(db, thisSlot); + await RecalculateSlotUses(db, thisSlot); return (ReserveOrderItemsResult.Success, bookedOrderItemInfos); } - public bool CancelOrderItems(string clientId, long? sellerId, Guid uuid, List orderItemIds, bool customerCancelled, bool includeCancellationMessage = false) + public async Task CancelOrderItems(string clientId, long? sellerId, Guid uuid, List orderItemIds, bool customerCancelled, bool includeCancellationMessage = false) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) using (var transaction = db.OpenTransaction(IsolationLevel.Serializable)) { var order = customerCancelled - ? db.Single(x => x.ClientId == clientId && x.OrderMode == OrderMode.Booking && x.OrderId == uuid.ToString() && !x.Deleted) - : db.Single(x => x.OrderId == uuid.ToString() && !x.Deleted); + ? await db.SingleAsync(x => x.ClientId == clientId && x.OrderMode == OrderMode.Booking && x.OrderId == uuid.ToString() && !x.Deleted) + : await db.SingleAsync(x => x.OrderId == uuid.ToString() && !x.Deleted); if (order == null) return false; @@ -1053,11 +1030,9 @@ public bool CancelOrderItems(string clientId, long? sellerId, Guid uuid, List 0) { - var totalPrice = db.Select(x => + var totalPrice = (await db.SelectAsync(x => x.ClientId == clientId && x.OrderId == order.OrderId && - (x.Status == BookingStatus.Confirmed || x.Status == BookingStatus.Attended || x.Status == BookingStatus.Absent)).Sum(x => x.Price); + (x.Status == BookingStatus.Confirmed || x.Status == BookingStatus.Attended || x.Status == BookingStatus.Absent))).Sum(x => x.Price); order.TotalOrderPrice = totalPrice; order.VisibleInOrdersFeed = FeedVisibility.Visible; order.OrderModified = DateTimeOffset.Now.UtcTicks; - db.Update(order); + await db.UpdateAsync(order); // Note an actual implementation would need to handle different opportunity types here // Update the number of spaces available as a result of cancellation - RecalculateSpaces(db, updatedOrderItems.Where(x => x.OccurrenceId.HasValue).Select(x => x.OccurrenceId.Value).Distinct()); - RecalculateSlotUses(db, updatedOrderItems.Where(x => x.SlotId.HasValue).Select(x => x.SlotId.Value).Distinct()); + await RecalculateSpaces(db, updatedOrderItems.Where(x => x.OccurrenceId.HasValue).Select(x => x.OccurrenceId.Value).Distinct()); + await RecalculateSlotUses(db, updatedOrderItems.Where(x => x.SlotId.HasValue).Select(x => x.SlotId.Value).Distinct()); } transaction.Commit(); @@ -1096,9 +1071,9 @@ public bool CancelOrderItems(string clientId, long? sellerId, Guid uuid, List ReplaceOrderOpportunity(Guid uuid) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { var query = db.From() .Join() @@ -1108,7 +1083,7 @@ public bool ReplaceOrderOpportunity(Guid uuid) if (!orderItemsAndOrder.Any()) return false; var order = orderItemsAndOrder.First().Item2; - var orderItems = orderItemsAndOrder.Select(x => x.Item1); + var orderItems = orderItemsAndOrder.Select(x => x.Item1).AsList(); var index = Faker.Random.Int(0, orderItemsAndOrder.Count - 1); var orderItem = orderItemsAndOrder[index].Item1; @@ -1158,26 +1133,26 @@ public bool ReplaceOrderOpportunity(Guid uuid) return false; } - db.Update(orderItem); + await db.UpdateAsync(orderItem); - order.TotalOrderPrice = orderItems.Sum(x => x.Price); ; + order.TotalOrderPrice = orderItems.Sum(x => x.Price); order.VisibleInOrdersFeed = FeedVisibility.Visible; order.OrderModified = DateTimeOffset.Now.UtcTicks; - db.Update(order); + await db.UpdateAsync(order); // Note an actual implementation would need to handle different opportunity types here // Update the number of spaces available as a result of cancellation - RecalculateSpaces(db, orderItems.Where(x => x.OccurrenceId.HasValue).Select(x => x.OccurrenceId.Value).Distinct()); - RecalculateSlotUses(db, orderItems.Where(x => x.SlotId.HasValue).Select(x => x.SlotId.Value).Distinct()); + await RecalculateSpaces(db, orderItems.Where(x => x.OccurrenceId.HasValue).Select(x => x.OccurrenceId.Value).Distinct()); + await RecalculateSlotUses(db, orderItems.Where(x => x.SlotId.HasValue).Select(x => x.SlotId.Value).Distinct()); return true; } } - public bool AcceptOrderProposal(Guid uuid) + public async Task AcceptOrderProposal(Guid uuid) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - var order = db.Single(x => x.OrderMode == OrderMode.Proposal && x.OrderId == uuid.ToString() && !x.Deleted); + var order = await db.SingleAsync(x => x.OrderMode == OrderMode.Proposal && x.OrderId == uuid.ToString() && !x.Deleted); if (order != null) { // This makes the call idempotent @@ -1187,21 +1162,19 @@ public bool AcceptOrderProposal(Guid uuid) order.ProposalStatus = ProposalStatus.SellerAccepted; order.VisibleInOrderProposalsFeed = FeedVisibility.Visible; order.OrderProposalModified = DateTimeOffset.Now.UtcTicks; - db.Update(order); + await db.UpdateAsync(order); } return true; } - else - { - return false; - } + + return false; } } - public bool AmendOrderProposal(Guid uuid, Guid version) + public async Task AmendOrderProposal(Guid uuid, Guid version) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - var order = db.Single(x => x.OrderMode == OrderMode.Proposal && x.OrderId == uuid.ToString() && !x.Deleted); + var order = await db.SingleAsync(x => x.OrderMode == OrderMode.Proposal && x.OrderId == uuid.ToString() && !x.Deleted); if (order != null) { // This makes the call idempotent @@ -1211,23 +1184,21 @@ public bool AmendOrderProposal(Guid uuid, Guid version) order.ProposalVersionId = version; order.VisibleInOrderProposalsFeed = FeedVisibility.Visible; order.OrderProposalModified = DateTimeOffset.Now.UtcTicks; - db.Update(order); + await db.UpdateAsync(order); } return true; } - else - { - return false; - } + + return false; } } - public FakeDatabaseBookOrderProposalResult BookOrderProposal(string clientId, long? sellerId, Guid uuid, Guid? proposalVersionUuid) + public async Task BookOrderProposal(string clientId, long? sellerId, Guid uuid, Guid? proposalVersionUuid) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { // Note call is idempotent, so it might already be in the booked state - var order = db.Single(x => x.ClientId == clientId && (x.OrderMode == OrderMode.Proposal || x.OrderMode == OrderMode.Booking) && x.OrderId == uuid.ToString() && !x.Deleted); + var order = await db.SingleAsync(x => x.ClientId == clientId && (x.OrderMode == OrderMode.Proposal || x.OrderMode == OrderMode.Booking) && x.OrderId == uuid.ToString() && !x.Deleted); if (order != null) { if (sellerId.HasValue && order.SellerId != sellerId) @@ -1243,13 +1214,13 @@ public FakeDatabaseBookOrderProposalResult BookOrderProposal(string clientId, lo return FakeDatabaseBookOrderProposalResult.OrderProposalNotAccepted; } List updatedOrderItems = new List(); - foreach (OrderItemsTable orderItem in db.Select(x => x.ClientId == clientId && x.OrderId == order.OrderId)) + foreach (OrderItemsTable orderItem in await db.SelectAsync(x => x.ClientId == clientId && x.OrderId == order.OrderId)) { if (orderItem.Status != BookingStatus.Confirmed) { updatedOrderItems.Add(orderItem); orderItem.Status = BookingStatus.Confirmed; - db.Save(orderItem); + await db.SaveAsync(orderItem); } } // Update the status and modified date of the OrderProposal to update the feed, if something has changed @@ -1259,24 +1230,22 @@ public FakeDatabaseBookOrderProposalResult BookOrderProposal(string clientId, lo order.OrderMode = OrderMode.Booking; order.VisibleInOrderProposalsFeed = FeedVisibility.Archived; order.OrderProposalModified = DateTimeOffset.Now.UtcTicks; - db.Update(order); + await db.UpdateAsync(order); // Note an actual implementation would need to handle different opportunity types here // Update the number of spaces available as a result of cancellation - RecalculateSpaces(db, updatedOrderItems.Where(x => x.OccurrenceId.HasValue).Select(x => x.OccurrenceId.Value).Distinct()); - RecalculateSlotUses(db, updatedOrderItems.Where(x => x.SlotId.HasValue).Select(x => x.SlotId.Value).Distinct()); + await RecalculateSpaces(db, updatedOrderItems.Where(x => x.OccurrenceId.HasValue).Select(x => x.OccurrenceId.Value).Distinct()); + await RecalculateSlotUses(db, updatedOrderItems.Where(x => x.SlotId.HasValue).Select(x => x.SlotId.Value).Distinct()); } return FakeDatabaseBookOrderProposalResult.OrderSuccessfullyBooked; } - else - { - return FakeDatabaseBookOrderProposalResult.OrderWasNotFound; - } + + return FakeDatabaseBookOrderProposalResult.OrderWasNotFound; } } - public long GetNumberOfOtherLeaseForOccurrence(Guid uuid, long? occurrenceId) + public async Task GetNumberOfOtherLeaseForOccurrence(Guid uuid, long? occurrenceId) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { return db.Count(x => x.OrderTable.OrderMode != OrderMode.Booking && x.OrderTable.ProposalStatus != ProposalStatus.CustomerRejected && @@ -1286,9 +1255,9 @@ public long GetNumberOfOtherLeaseForOccurrence(Guid uuid, long? occurrenceId) } } - public long GetNumberOfOtherLeasesForSlot(Guid uuid, long? slotId) + public async Task GetNumberOfOtherLeasesForSlot(Guid uuid, long? slotId) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { return db.Count(x => x.OrderTable.OrderMode != OrderMode.Booking && x.OrderTable.ProposalStatus != ProposalStatus.CustomerRejected && @@ -1298,11 +1267,11 @@ public long GetNumberOfOtherLeasesForSlot(Guid uuid, long? slotId) } } - public bool RejectOrderProposal(string clientId, long? sellerId, Guid uuid, bool customerRejected) + public async Task RejectOrderProposal(string clientId, long? sellerId, Guid uuid, bool customerRejected) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - var order = db.Single(x => (clientId == null || x.ClientId == clientId) && x.OrderMode == OrderMode.Proposal && x.OrderId == uuid.ToString() && !x.Deleted); + var order = await db.SingleAsync(x => (clientId == null || x.ClientId == clientId) && x.OrderMode == OrderMode.Proposal && x.OrderId == uuid.ToString() && !x.Deleted); if (order != null) { if (sellerId.HasValue && order.SellerId != sellerId) @@ -1315,95 +1284,94 @@ public bool RejectOrderProposal(string clientId, long? sellerId, Guid uuid, bool order.ProposalStatus = customerRejected ? ProposalStatus.CustomerRejected : ProposalStatus.SellerRejected; order.VisibleInOrderProposalsFeed = FeedVisibility.Visible; order.OrderProposalModified = DateTimeOffset.Now.UtcTicks; - db.Update(order); + await db.UpdateAsync(order); // Note an actual implementation would need to handle different opportunity types here // Update the number of spaces available as a result of cancellation - List updatedOrderItems = db.Select(x => (clientId == null || x.ClientId == clientId) && x.OrderId == order.OrderId).ToList(); - RecalculateSpaces(db, updatedOrderItems.Where(x => x.OccurrenceId.HasValue).Select(x => x.OccurrenceId.Value).Distinct()); - RecalculateSlotUses(db, updatedOrderItems.Where(x => x.SlotId.HasValue).Select(x => x.SlotId.Value).Distinct()); + List updatedOrderItems = (await db.SelectAsync(x => (clientId == null || x.ClientId == clientId) && x.OrderId == order.OrderId)).AsList(); + await RecalculateSpaces(db, updatedOrderItems.Where(x => x.OccurrenceId.HasValue).Select(x => x.OccurrenceId.Value).Distinct()); + await RecalculateSlotUses(db, updatedOrderItems.Where(x => x.SlotId.HasValue).Select(x => x.SlotId.Value).Distinct()); } return true; } - else - { - return false; - } + + return false; } } - public static void RecalculateSlotUses(IDbConnection db, SlotTable slot) + public static async Task RecalculateSlotUses(IDbConnection db, SlotTable slot) { if (slot == null) return; // Update number of leased spaces remaining for the opportunity - var leasedUses = db.LoadSelect(x => x.OrderTable.OrderMode != OrderMode.Booking && x.OrderTable.ProposalStatus != ProposalStatus.CustomerRejected && x.OrderTable.ProposalStatus != ProposalStatus.SellerRejected && x.SlotId == slot.Id).Count(); + var leasedUses = (await db.LoadSelectAsync(x => x.OrderTable.OrderMode != OrderMode.Booking && x.OrderTable.ProposalStatus != ProposalStatus.CustomerRejected && x.OrderTable.ProposalStatus != ProposalStatus.SellerRejected && x.SlotId == slot.Id)).Count; slot.LeasedUses = leasedUses; // Update number of actual spaces remaining for the opportunity - var totalUsesTaken = db.LoadSelect(x => x.OrderTable.OrderMode == OrderMode.Booking && x.OccurrenceId == slot.Id && (x.Status == BookingStatus.Confirmed || x.Status == BookingStatus.Attended || x.Status == BookingStatus.Absent)).Count(); + var totalUsesTaken = (await db.LoadSelectAsync(x => x.OrderTable.OrderMode == OrderMode.Booking && x.OccurrenceId == slot.Id && (x.Status == BookingStatus.Confirmed || x.Status == BookingStatus.Attended || x.Status == BookingStatus.Absent))).Count; slot.RemainingUses = slot.MaximumUses - totalUsesTaken; // Push the change into the future to avoid it getting lost in the feed (see race condition transaction challenges https://developer.openactive.io/publishing-data/data-feeds/implementing-rpde-feeds#preventing-the-race-condition) // TODO: Document this! slot.Modified = DateTimeOffset.Now.UtcTicks; - db.Update(slot); + await db.UpdateAsync(slot); } - public static void RecalculateSlotUses(IDbConnection db, IEnumerable slotIds) + public static async Task RecalculateSlotUses(IDbConnection db, IEnumerable slotIds) { foreach (var slotId in slotIds) { - var thisSlot = db.Single(x => x.Id == slotId && !x.Deleted); - RecalculateSlotUses(db, thisSlot); + var thisSlot = await db.SingleAsync(x => x.Id == slotId && !x.Deleted); + await RecalculateSlotUses(db, thisSlot); } } - public static void RecalculateSpaces(IDbConnection db, OccurrenceTable occurrence) + public static async Task RecalculateSpaces(IDbConnection db, OccurrenceTable occurrence) { if (occurrence == null) return; // Update number of leased spaces remaining for the opportunity - var leasedSpaces = db.LoadSelect(x => x.OrderTable.OrderMode != OrderMode.Booking && x.OrderTable.ProposalStatus != ProposalStatus.CustomerRejected && x.OrderTable.ProposalStatus != ProposalStatus.SellerRejected && x.OccurrenceId == occurrence.Id).Count(); + var leasedSpaces = (await db.LoadSelectAsync(x => x.OrderTable.OrderMode != OrderMode.Booking && x.OrderTable.ProposalStatus != ProposalStatus.CustomerRejected && x.OrderTable.ProposalStatus != ProposalStatus.SellerRejected && x.OccurrenceId == occurrence.Id)).Count; occurrence.LeasedSpaces = leasedSpaces; // Update number of actual spaces remaining for the opportunity - var totalSpacesTaken = db.LoadSelect(x => x.OrderTable.OrderMode == OrderMode.Booking && x.OccurrenceId == occurrence.Id && (x.Status == BookingStatus.Confirmed || x.Status == BookingStatus.Attended || x.Status == BookingStatus.Absent)).Count(); + var totalSpacesTaken = (await db.LoadSelectAsync(x => x.OrderTable.OrderMode == OrderMode.Booking && x.OccurrenceId == occurrence.Id && (x.Status == BookingStatus.Confirmed || x.Status == BookingStatus.Attended || x.Status == BookingStatus.Absent))).Count(); occurrence.RemainingSpaces = occurrence.TotalSpaces - totalSpacesTaken; // Push the change into the future to avoid it getting lost in the feed (see race condition transaction challenges https://developer.openactive.io/publishing-data/data-feeds/implementing-rpde-feeds#preventing-the-race-condition) // TODO: Document this! occurrence.Modified = DateTimeOffset.Now.UtcTicks; - db.Update(occurrence); + await db.UpdateAsync(occurrence); } - public static void RecalculateSpaces(IDbConnection db, IEnumerable occurrenceIds) + public static async Task RecalculateSpaces(IDbConnection db, IEnumerable occurrenceIds) { foreach (var occurrenceId in occurrenceIds) { - var thisOccurrence = db.Single(x => x.Id == occurrenceId && !x.Deleted); - RecalculateSpaces(db, thisOccurrence); + var thisOccurrence = await db.SingleAsync(x => x.Id == occurrenceId && !x.Deleted); + await RecalculateSpaces(db, thisOccurrence); } } - public static FakeDatabase GetPrepopulatedFakeDatabase() + public static async Task GetPrepopulatedFakeDatabase() { var database = new FakeDatabase(); - using (var db = database.Mem.Database.Open()) + using (var db = await database.Mem.Database.OpenAsync()) using (var transaction = db.OpenTransaction(IsolationLevel.Serializable)) { - CreateSellers(db); - CreateSellerUsers(db); - CreateFakeClasses(db); - CreateFakeFacilitiesAndSlots(db); - CreateBookingPartners(db); + await CreateSellers(db); + await CreateSellerUsers(db); + await CreateFakeClasses(db); + await CreateFakeFacilitiesAndSlots(db); + await CreateBookingPartners(db); transaction.Commit(); } + return database; } - private static void CreateFakeFacilitiesAndSlots(IDbConnection db) + private static async Task CreateFakeFacilitiesAndSlots(IDbConnection db) { var opportunitySeeds = GenerateOpportunitySeedDistribution(OpportunityCount); @@ -1415,9 +1383,9 @@ private static void CreateFakeFacilitiesAndSlots(IDbConnection db) Name = $"{Faker.Commerce.ProductMaterial()} {Faker.PickRandomParam("Sports Hall", "Swimming Pool Hall", "Running Hall", "Jumping Hall")}", SellerId = Faker.Random.Bool(0.8f) ? Faker.Random.Long(1, 2) : Faker.Random.Long(3, 5), // distribution: 80% 1-2, 20% 3-5 }) - .ToList(); + .AsList(); - int slotId = 0; + var slotId = 0; var slots = opportunitySeeds.Select(seed => Enumerable.Range(0, 10) .Select(_ => new @@ -1426,7 +1394,7 @@ private static void CreateFakeFacilitiesAndSlots(IDbConnection db) TotalUses = Faker.Random.Int(0, 8), Price = decimal.Parse(Faker.Random.Bool() ? "0.00" : Faker.Commerce.Price(0, 20)), }) - .Select((slot) => + .Select(slot => { var requiresAdditionalDetails = Faker.Random.Bool(ProportionWithRequiresAdditionalDetails); return new SlotTable @@ -1446,7 +1414,7 @@ private static void CreateFakeFacilitiesAndSlots(IDbConnection db) RequiresAdditionalDetails = requiresAdditionalDetails, RequiredAdditionalDetails = requiresAdditionalDetails ? PickRandomAdditionalDetails() : null, RequiresApproval = seed.RequiresApproval, - AllowsProposalAmendment = seed.RequiresApproval ? Faker.Random.Bool() : false, + AllowsProposalAmendment = seed.RequiresApproval && Faker.Random.Bool(), ValidFromBeforeStartDate = seed.RandomValidFromBeforeStartDate(), LatestCancellationBeforeStartDate = RandomLatestCancellationBeforeStartDate(), AllowCustomerCancellationFullRefund = Faker.Random.Bool() @@ -1454,11 +1422,11 @@ private static void CreateFakeFacilitiesAndSlots(IDbConnection db) } )).SelectMany(os => os); - db.InsertAll(facilities); - db.InsertAll(slots); + await db.InsertAllAsync(facilities); + await db.InsertAllAsync(slots); } - public static void CreateFakeClasses(IDbConnection db) + public static async Task CreateFakeClasses(IDbConnection db) { var opportunitySeeds = GenerateOpportunitySeedDistribution(OpportunityCount); @@ -1470,7 +1438,7 @@ public static void CreateFakeClasses(IDbConnection db) ValidFromBeforeStartDate = seed.RandomValidFromBeforeStartDate(), seed.RequiresApproval }) - .Select((@class) => + .Select(@class => { var requiresAdditionalDetails = Faker.Random.Bool(ProportionWithRequiresAdditionalDetails); return new ClassTable @@ -1486,7 +1454,7 @@ public static void CreateFakeClasses(IDbConnection db) RequiresAdditionalDetails = requiresAdditionalDetails, RequiredAdditionalDetails = requiresAdditionalDetails ? PickRandomAdditionalDetails() : null, RequiresApproval = @class.RequiresApproval, - AllowsProposalAmendment = @class.RequiresApproval ? Faker.Random.Bool() : false, + AllowsProposalAmendment = @class.RequiresApproval && Faker.Random.Bool(), LatestCancellationBeforeStartDate = RandomLatestCancellationBeforeStartDate(), SellerId = Faker.Random.Bool(0.8f) ? Faker.Random.Long(1, 2) : Faker.Random.Long(3, 5), // distribution: 80% 1-2, 20% 3-5 ValidFromBeforeStartDate = @class.ValidFromBeforeStartDate, @@ -1494,9 +1462,9 @@ public static void CreateFakeClasses(IDbConnection db) AllowCustomerCancellationFullRefund = Faker.Random.Bool() }; }) - .ToList(); + .AsList(); - int occurrenceId = 0; + var occurrenceId = 0; var occurrences = opportunitySeeds.Select(seed => Enumerable.Range(0, 10) .Select(_ => new @@ -1515,11 +1483,11 @@ public static void CreateFakeClasses(IDbConnection db) RemainingSpaces = occurrence.TotalSpaces })).SelectMany(os => os); - db.InsertAll(classes); - db.InsertAll(occurrences); + await db.InsertAllAsync(classes); + await db.InsertAllAsync(occurrences); } - public static void CreateSellers(IDbConnection db) + public static async Task CreateSellers(IDbConnection db) { var sellers = new List { @@ -1530,10 +1498,10 @@ public static void CreateSellers(IDbConnection db) new SellerTable { Id = 5, Name = "Jane Smith", IsIndividual = true, LogoUrl = "https://placekitten.com/640/360", Url = "https://www.example.com", IsTaxGross = true } }; - db.InsertAll(sellers); + await db.InsertAllAsync(sellers); } - public static void CreateSellerUsers(IDbConnection db) + public static async Task CreateSellerUsers(IDbConnection db) { var sellerUsers = new List { @@ -1545,31 +1513,31 @@ public static void CreateSellerUsers(IDbConnection db) new SellerUserTable { Id = 105, Username = "test5", PasswordHash = "test5".Sha256(), SellerId = 5 }, }; - db.InsertAll(sellerUsers); + await db.InsertAllAsync(sellerUsers); } - public bool ValidateSellerUserCredentials(string Username, string Password) + public async Task ValidateSellerUserCredentials(string username, string password) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - var matchingUser = db.Single(x => x.Username == Username && x.PasswordHash == Password.Sha256()); - return (matchingUser != null); + var matchingUser = await db.SingleAsync(x => x.Username == username && x.PasswordHash == password.Sha256()); + return matchingUser != null; } } - public SellerUserTable GetSellerUser(string Username) + public async Task GetSellerUser(string username) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - return db.Single(x => x.Username == Username); + return await db.SingleAsync(x => x.Username == username); } } - public SellerUserTable GetSellerUserById(long sellerUserId) + public async Task GetSellerUserById(long sellerUserId) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - return db.LoadSingleById(sellerUserId); + return await db.LoadSingleByIdAsync(sellerUserId); } } @@ -1596,8 +1564,7 @@ public List GetBookingPartnerAdministrators() } */ - - public static void CreateBookingPartners(IDbConnection db) + public static async Task CreateBookingPartners(IDbConnection db) { var bookingPartners = new List { @@ -1608,7 +1575,7 @@ public static void CreateBookingPartners(IDbConnection db) GrantTypes = new[] { "client_credentials", "refresh_token", "authorization_code" }, ClientUri = "http://example.com", LogoUri = "https://via.placeholder.com/512x256.png?text=Logo", - RedirectUris = new string[] { "http://localhost:3000/cb" } + RedirectUris = new[] { "http://localhost:3000/cb" } } }, new BookingPartnerTable { Name = "Example app", ClientId = "clientid_801", ClientSecret = "secret".Sha256(), Email="garden@health.com", Registered = true, InitialAccessToken = "98768", InitialAccessTokenKeyValidUntil = DateTime.Now.AddDays(1), CreatedDate = DateTime.Now, BookingsSuspended = false, @@ -1617,183 +1584,182 @@ public static void CreateBookingPartners(IDbConnection db) GrantTypes = new[] { "client_credentials", "refresh_token", "authorization_code" }, ClientUri = "http://example.com", LogoUri = "https://via.placeholder.com/512x256.png?text=Logo", - RedirectUris = new string[] { "http://localhost:3000/cb" } + RedirectUris = new[] { "http://localhost:3000/cb" } } }, new BookingPartnerTable { Name = "Test Suite 2", ClientId = Guid.NewGuid().ToString(), InitialAccessToken = "dynamic-primary-745ddf2d13019ce8b69c", Registered = false, InitialAccessTokenKeyValidUntil = DateTime.Now.AddDays(1), CreatedDate = DateTime.Now }, new BookingPartnerTable { Name = "Test Suite 3", ClientId = Guid.NewGuid().ToString(), InitialAccessToken = "dynamic-secondary-a21518cb57af7b6052df", Registered = false, InitialAccessTokenKeyValidUntil = DateTime.Now.AddDays(1), CreatedDate = DateTime.Now } }; - var grants = new List() - { - new GrantTable() - { - Key = "8vJ5rH7eSj7HL4TD5Tlaeyfa+U6WkFc/ofBdkVuM/RY=", - Type = "user_consent", - SubjectId = "TestSubjectId", - ClientId = "clientid_123", - CreationTime = DateTime.Now, - Data = "{\"SubjectId\":\"818727\",\"ClientId\":\"clientid_123\",\"Scopes\":[\"openid\",\"profile\",\"openactive-identity\",\"openactive-openbooking\",\"oauth-dymamic-client-update\",\"offline_access\"],\"CreationTime\":\"2020-03-01T13:17:57Z\",\"Expiration\":null}" - }, - new GrantTable() - { - Key = "7vJ5rH7eSj7HL4TD5Tlaeyfa+U6WkFc/ofBdkVuM/RY=", - Type = "user_consent", - SubjectId = "TestSubjectId", - ClientId = "clientid_456", - CreationTime = DateTime.Now, - Data = "{\"SubjectId\":\"818727\",\"ClientId\":\"clientid_456\",\"Scopes\":[\"openid\",\"profile\",\"openactive-identity\",\"openactive-openbooking\",\"oauth-dymamic-client-update\",\"offline_access\"],\"CreationTime\":\"2020-03-01T13:17:57Z\",\"Expiration\":null}" - }, - new GrantTable() - { - Key = "9vJ5rH7eSj7HL4TD5Tlaeyfa+U6WkFc/ofBdkVuM/RY=", - Type = "user_consent", - SubjectId = "TestSubjectId", - ClientId = "clientid_789", - CreationTime = DateTime.Now, - Data = "{\"SubjectId\":\"818727\",\"ClientId\":\"clientid_789\",\"Scopes\":[\"openid\",\"profile\",\"openactive-identity\",\"openactive-openbooking\",\"oauth-dymamic-client-update\",\"offline_access\"],\"CreationTime\":\"2020-03-01T13:17:57Z\",\"Expiration\":null}" - }, - }; - - db.InsertAll(bookingPartners); - //db.InsertAll(grants); - } - - public List GetBookingPartners() - { - using (var db = Mem.Database.Open()) - { - return db.Select().ToList(); + // var grants = new List() + // { + // new GrantTable + // { + // Key = "8vJ5rH7eSj7HL4TD5Tlaeyfa+U6WkFc/ofBdkVuM/RY=", + // Type = "user_consent", + // SubjectId = "TestSubjectId", + // ClientId = "clientid_123", + // CreationTime = DateTime.Now, + // Data = "{\"SubjectId\":\"818727\",\"ClientId\":\"clientid_123\",\"Scopes\":[\"openid\",\"profile\",\"openactive-identity\",\"openactive-openbooking\",\"oauth-dymamic-client-update\",\"offline_access\"],\"CreationTime\":\"2020-03-01T13:17:57Z\",\"Expiration\":null}" + // }, + // new GrantTable + // { + // Key = "7vJ5rH7eSj7HL4TD5Tlaeyfa+U6WkFc/ofBdkVuM/RY=", + // Type = "user_consent", + // SubjectId = "TestSubjectId", + // ClientId = "clientid_456", + // CreationTime = DateTime.Now, + // Data = "{\"SubjectId\":\"818727\",\"ClientId\":\"clientid_456\",\"Scopes\":[\"openid\",\"profile\",\"openactive-identity\",\"openactive-openbooking\",\"oauth-dymamic-client-update\",\"offline_access\"],\"CreationTime\":\"2020-03-01T13:17:57Z\",\"Expiration\":null}" + // }, + // new GrantTable + // { + // Key = "9vJ5rH7eSj7HL4TD5Tlaeyfa+U6WkFc/ofBdkVuM/RY=", + // Type = "user_consent", + // SubjectId = "TestSubjectId", + // ClientId = "clientid_789", + // CreationTime = DateTime.Now, + // Data = "{\"SubjectId\":\"818727\",\"ClientId\":\"clientid_789\",\"Scopes\":[\"openid\",\"profile\",\"openactive-identity\",\"openactive-openbooking\",\"oauth-dymamic-client-update\",\"offline_access\"],\"CreationTime\":\"2020-03-01T13:17:57Z\",\"Expiration\":null}" + // }, + // }; + + await db.InsertAllAsync(bookingPartners); + //await db.InsertAllAsync(grants); + } + + public async Task> GetBookingPartners() + { + using (var db = await Mem.Database.OpenAsync()) + { + return (await db.SelectAsync()).AsList(); } } - public BookingPartnerTable GetBookingPartnerByInitialAccessToken(string registrationKey) + public async Task GetBookingPartnerByInitialAccessToken(string registrationKey) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - var bookingPartner = db.Single(x => x.InitialAccessToken == registrationKey); + var bookingPartner = await db.SingleAsync(x => x.InitialAccessToken == registrationKey); return bookingPartner?.InitialAccessTokenKeyValidUntil > DateTime.Now ? bookingPartner : null; } } - public BookingPartnerTable GetBookingPartner(string clientId) + public async Task GetBookingPartner(string clientId) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - return db.Single(x => x.ClientId == clientId); + return await db.SingleAsync(x => x.ClientId == clientId); } } - public void SaveBookingPartner(BookingPartnerTable bookingPartnerTable) + public async Task SaveBookingPartner(BookingPartnerTable bookingPartnerTable) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - db.Save(bookingPartnerTable); + await db.SaveAsync(bookingPartnerTable); } } - public void ResetBookingPartnerKey(string clientId, string key) + public async Task ResetBookingPartnerKey(string clientId, string key) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - var bookingPartner = db.Single(x => x.ClientId == clientId); + var bookingPartner = await db.SingleAsync(x => x.ClientId == clientId); bookingPartner.Registered = false; bookingPartner.InitialAccessToken = key; bookingPartner.InitialAccessTokenKeyValidUntil = DateTime.Now.AddDays(2); bookingPartner.ClientSecret = null; - db.Save(bookingPartner); + await db.SaveAsync(bookingPartner); } } - public void SetBookingPartnerKey(string clientId, string key) + public async Task SetBookingPartnerKey(string clientId, string key) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - var bookingPartner = db.Single(x => x.ClientId == clientId); + var bookingPartner = await db.SingleAsync(x => x.ClientId == clientId); bookingPartner.InitialAccessToken = key; bookingPartner.InitialAccessTokenKeyValidUntil = DateTime.Now.AddDays(2); - db.Save(bookingPartner); + await db.SaveAsync(bookingPartner); } } - public void UpdateBookingPartnerScope(string clientId, string scope, bool bookingsSuspended) + public async Task UpdateBookingPartnerScope(string clientId, string scope, bool bookingsSuspended) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - var bookingPartner = db.Single(x => x.ClientId == clientId); + var bookingPartner = await db.SingleAsync(x => x.ClientId == clientId); bookingPartner.ClientProperties.Scope = scope; bookingPartner.BookingsSuspended = true; - db.Save(bookingPartner); + await db.SaveAsync(bookingPartner); } } - - public void AddBookingPartner(BookingPartnerTable newBookingPartner) + public async Task AddBookingPartner(BookingPartnerTable newBookingPartner) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - db.Save(newBookingPartner); + await db.SaveAsync(newBookingPartner); } } - public GrantTable GetGrant(string key) + public async Task GetGrant(string key) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - return db.Single(x => x.Key == key); + return await db.SingleAsync(x => x.Key == key); } } - public IEnumerable GetAllGrants(string subjectId) + public async Task> GetAllGrants(string subjectId) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - return db.Select(x => x.SubjectId == subjectId).ToList(); + return (await db.SelectAsync(x => x.SubjectId == subjectId)).AsList(); } } - public void AddGrant(string key, string type, string subjectId, string clientId, DateTime CreationTime, DateTime? Expiration, string data) + public async Task AddGrant(string key, string type, string subjectId, string clientId, DateTime creationTime, DateTime? expiration, string data) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - var grant = new GrantTable() + var grant = new GrantTable { Key = key, Type = type, SubjectId = subjectId, ClientId = clientId, - CreationTime = CreationTime, - Expiration = Expiration, + CreationTime = creationTime, + Expiration = expiration, Data = data }; - db.Save(grant); + await db.SaveAsync(grant); } } - public void RemoveGrant(string key) + public async Task RemoveGrant(string key) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - db.Delete(x => x.Key == key); + await db.DeleteAsync(x => x.Key == key); } } - public void RemoveGrant(string subjectId, string clientId) + public async Task RemoveGrant(string subjectId, string clientId) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - db.Delete(x => x.SubjectId == subjectId && x.ClientId == clientId); + await db.DeleteAsync(x => x.SubjectId == subjectId && x.ClientId == clientId); } } - public void RemoveGrant(string subjectId, string clientId, string type) + public async Task RemoveGrant(string subjectId, string clientId, string type) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - db.Delete(x => x.SubjectId == subjectId && x.ClientId == clientId && x.Type == type); + await db.DeleteAsync(x => x.SubjectId == subjectId && x.ClientId == clientId && x.Type == type); } } - public (int, int) AddClass( + public async Task<(int, int)> AddClass( string testDatasetIdentifier, long? sellerId, string title, @@ -1816,7 +1782,7 @@ public void RemoveGrant(string subjectId, string clientId, string type) var startTime = DateTime.Now.AddDays(inPast ? -1 : 1); var endTime = DateTime.Now.AddDays(inPast ? -1 : 1).AddHours(1); - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) using (var transaction = db.OpenTransaction(IsolationLevel.Serializable)) { var @class = new ClassTable @@ -1844,7 +1810,7 @@ public void RemoveGrant(string subjectId, string clientId, string type) AllowCustomerCancellationFullRefund = allowCustomerCancellationFullRefund, Modified = DateTimeOffset.Now.UtcTicks }; - db.Save(@class); + await db.SaveAsync(@class); var occurrence = new OccurrenceTable { @@ -1857,7 +1823,7 @@ public void RemoveGrant(string subjectId, string clientId, string type) RemainingSpaces = totalSpaces, Modified = DateTimeOffset.Now.UtcTicks }; - db.Save(occurrence); + await db.SaveAsync(occurrence); transaction.Commit(); @@ -1865,7 +1831,7 @@ public void RemoveGrant(string subjectId, string clientId, string type) } } - public (int, int) AddFacility( + public async Task<(int, int)> AddFacility( string testDatasetIdentifier, long? sellerId, string title, @@ -1886,7 +1852,7 @@ public void RemoveGrant(string subjectId, string clientId, string type) var startTime = DateTime.Now.AddDays(inPast ? -1 : 1); var endTime = DateTime.Now.AddDays(inPast ? -1 : 1).AddHours(1); - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) using (var transaction = db.OpenTransaction(IsolationLevel.Serializable)) { var facility = new FacilityUseTable @@ -1899,7 +1865,7 @@ public void RemoveGrant(string subjectId, string clientId, string type) LocationLng = locationLng, Modified = DateTimeOffset.Now.UtcTicks }; - db.Save(facility); + await db.SaveAsync(facility); var slot = new SlotTable { @@ -1926,7 +1892,7 @@ public void RemoveGrant(string subjectId, string clientId, string type) AllowCustomerCancellationFullRefund = allowCustomerCancellationFullRefund, Modified = DateTimeOffset.Now.UtcTicks }; - db.Save(slot); + await db.SaveAsync(slot); transaction.Commit(); @@ -1934,26 +1900,26 @@ public void RemoveGrant(string subjectId, string clientId, string type) } } - public void DeleteTestClassesFromDataset(string testDatasetIdentifier) + public async Task DeleteTestClassesFromDataset(string testDatasetIdentifier) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - db.UpdateOnly(() => new ClassTable { Modified = DateTimeOffset.Now.UtcTicks, Deleted = true }, + await db.UpdateOnlyAsync(() => new ClassTable { Modified = DateTimeOffset.Now.UtcTicks, Deleted = true }, where: x => x.TestDatasetIdentifier == testDatasetIdentifier && !x.Deleted); - db.UpdateOnly(() => new OccurrenceTable { Modified = DateTimeOffset.Now.UtcTicks, Deleted = true }, + await db.UpdateOnlyAsync(() => new OccurrenceTable { Modified = DateTimeOffset.Now.UtcTicks, Deleted = true }, where: x => x.TestDatasetIdentifier == testDatasetIdentifier && !x.Deleted); } } - public void DeleteTestFacilitiesFromDataset(string testDatasetIdentifier) + public async Task DeleteTestFacilitiesFromDataset(string testDatasetIdentifier) { - using (var db = Mem.Database.Open()) + using (var db = await Mem.Database.OpenAsync()) { - db.UpdateOnly(() => new FacilityUseTable { Modified = DateTimeOffset.Now.UtcTicks, Deleted = true }, + await db.UpdateOnlyAsync(() => new FacilityUseTable { Modified = DateTimeOffset.Now.UtcTicks, Deleted = true }, where: x => x.TestDatasetIdentifier == testDatasetIdentifier && !x.Deleted); - db.UpdateOnly(() => new SlotTable { Modified = DateTimeOffset.Now.UtcTicks, Deleted = true }, + await db.UpdateOnlyAsync(() => new SlotTable { Modified = DateTimeOffset.Now.UtcTicks, Deleted = true }, where: x => x.TestDatasetIdentifier == testDatasetIdentifier && !x.Deleted); } } @@ -1988,7 +1954,7 @@ private static OpportunitySeed GenerateRandomOpportunityData(Faker faker, int in { return new OpportunitySeed { - Faker = faker, + SeedFaker = faker, Id = index + 1, StartDateBounds = BoundsDaysToMinutes(input.startDateRange).Value, ValidFromBeforeStartDateBounds = !input.validFromBeforeStartDateRange.HasValue ? (Bounds?)null : BoundsDaysToMinutes(input.validFromBeforeStartDateRange).Value, @@ -1998,8 +1964,8 @@ private static OpportunitySeed GenerateRandomOpportunityData(Faker faker, int in private static Bounds? BoundsDaysToMinutes(Bounds? bounds) { - const int MINUTES_IN_DAY = 60 * 24; - return !bounds.HasValue ? (Bounds?)null : new Bounds(bounds.Value.Lower * MINUTES_IN_DAY, bounds.Value.Upper * MINUTES_IN_DAY); + const int minutesInDay = 60 * 24; + return !bounds.HasValue ? (Bounds?)null : new Bounds(bounds.Value.Lower * minutesInDay, bounds.Value.Upper * minutesInDay); } /// @@ -2007,20 +1973,20 @@ private static OpportunitySeed GenerateRandomOpportunityData(Faker faker, int in /// private static List GenerateOpportunitySeedDistribution(int count) { - return Faker.GenerateIntegerDistribution(count, BucketDefinitions, GenerateRandomOpportunityData).ToList(); + return Faker.GenerateIntegerDistribution(count, BucketDefinitions, GenerateRandomOpportunityData).AsList(); } private struct OpportunitySeed { - public Faker Faker { get; set; } + public Faker SeedFaker { get; set; } public int Id { get; set; } public Bounds StartDateBounds { get; set; } public Bounds? ValidFromBeforeStartDateBounds { get; set; } - public DateTime RandomStartDate() => DateTime.Now.AddMinutes(this.Faker.Random.Int(StartDateBounds)); + public DateTime RandomStartDate() => DateTime.Now.AddMinutes(SeedFaker.Random.Int(StartDateBounds)); public TimeSpan? RandomValidFromBeforeStartDate() => ValidFromBeforeStartDateBounds.HasValue - ? TimeSpan.FromMinutes(this.Faker.Random.Int(ValidFromBeforeStartDateBounds.Value)) + ? TimeSpan.FromMinutes(SeedFaker.Random.Int(ValidFromBeforeStartDateBounds.Value)) : (TimeSpan?)null; public bool RequiresApproval { get; set; } } @@ -2035,7 +2001,7 @@ private struct OpportunitySeed private static List PickRandomAdditionalDetails() { - return new HashSet { Faker.PickRandom(), Faker.PickRandom() }.ToList(); + return new HashSet { Faker.PickRandom(), Faker.PickRandom() }.AsList(); } } } diff --git a/Fakes/OpenActive.FakeDatabase.NET/FakeDatabaseTransaction.cs b/Fakes/OpenActive.FakeDatabase.NET/FakeDatabaseTransaction.cs index fa4b6c02..fff6c808 100644 --- a/Fakes/OpenActive.FakeDatabase.NET/FakeDatabaseTransaction.cs +++ b/Fakes/OpenActive.FakeDatabase.NET/FakeDatabaseTransaction.cs @@ -1,10 +1,6 @@ using ServiceStack.OrmLite; using System; -using System.Collections.Generic; using System.Data; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace OpenActive.FakeDatabase.NET { diff --git a/OpenActive.Server.NET.Tests/IdTemplate.cs b/OpenActive.Server.NET.Tests/IdTemplate.cs index 3f40bd39..26f615c8 100644 --- a/OpenActive.Server.NET.Tests/IdTemplate.cs +++ b/OpenActive.Server.NET.Tests/IdTemplate.cs @@ -1,6 +1,5 @@ using System; using Xunit; -using OpenActive.Server.NET; using OpenActive.DatasetSite.NET; using OpenActive.Server.NET.OpenBookingHelper; diff --git a/OpenActive.Server.NET.Tests/SellerIdComponentsTest.cs b/OpenActive.Server.NET.Tests/SellerIdComponentsTest.cs index 2fa4c7e1..717d4b04 100644 --- a/OpenActive.Server.NET.Tests/SellerIdComponentsTest.cs +++ b/OpenActive.Server.NET.Tests/SellerIdComponentsTest.cs @@ -1,7 +1,4 @@ -using System; -using Xunit; -using OpenActive.Server.NET; -using OpenActive.DatasetSite.NET; +using Xunit; using OpenActive.Server.NET.OpenBookingHelper; namespace OpenActive.Server.NET.Tests diff --git a/OpenActive.Server.NET.Tests/StoreBookingEngineTest.cs b/OpenActive.Server.NET.Tests/StoreBookingEngineTest.cs index f7d6edbf..d105fcad 100644 --- a/OpenActive.Server.NET.Tests/StoreBookingEngineTest.cs +++ b/OpenActive.Server.NET.Tests/StoreBookingEngineTest.cs @@ -1,7 +1,4 @@ -using System; -using Xunit; -using OpenActive.Server.NET; -using OpenActive.NET; +using Xunit; namespace OpenActive.Server.NET.Tests { diff --git a/OpenActive.Server.NET/Entrypoint/IBookingEngine.cs b/OpenActive.Server.NET/Entrypoint/IBookingEngine.cs index 1f8a0eb0..a48efdb3 100644 --- a/OpenActive.Server.NET/Entrypoint/IBookingEngine.cs +++ b/OpenActive.Server.NET/Entrypoint/IBookingEngine.cs @@ -1,8 +1,5 @@ using System; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; -using OpenActive.NET; -using OpenActive.NET.Rpde.Version1; using OpenActive.Server.NET.OpenBookingHelper; namespace OpenActive.Server.NET diff --git a/OpenActive.Server.NET/OpenBookingHelper/Authentication/AuthenticationExtensions.cs b/OpenActive.Server.NET/OpenBookingHelper/Authentication/AuthenticationExtensions.cs index 1b06cfb1..3a523dd8 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Authentication/AuthenticationExtensions.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Authentication/AuthenticationExtensions.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Security.Claims; -using System.Text; using OpenActive.NET; namespace OpenActive.Server.NET.OpenBookingHelper diff --git a/OpenActive.Server.NET/OpenBookingHelper/Authentication/AuthenticationTestHeaders.cs b/OpenActive.Server.NET/OpenBookingHelper/Authentication/AuthenticationTestHeaders.cs index d0526321..dc672927 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Authentication/AuthenticationTestHeaders.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Authentication/AuthenticationTestHeaders.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace OpenActive.Server.NET.OpenBookingHelper +namespace OpenActive.Server.NET.OpenBookingHelper { public static class AuthenticationTestHeaders { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Authentication/OpenActiveCustomClaimNames.cs b/OpenActive.Server.NET/OpenBookingHelper/Authentication/OpenActiveCustomClaimNames.cs index d4985cfd..f148a8c0 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Authentication/OpenActiveCustomClaimNames.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Authentication/OpenActiveCustomClaimNames.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace OpenActive.Server.NET.OpenBookingHelper +namespace OpenActive.Server.NET.OpenBookingHelper { public static class OpenActiveCustomClaimNames { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Authentication/OpenActiveScopes.cs b/OpenActive.Server.NET/OpenBookingHelper/Authentication/OpenActiveScopes.cs index e839f7e7..eff392cb 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Authentication/OpenActiveScopes.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Authentication/OpenActiveScopes.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace OpenActive.Server.NET.OpenBookingHelper +namespace OpenActive.Server.NET.OpenBookingHelper { public static class OpenActiveScopes { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Beta/AuthenticatedPerson.cs b/OpenActive.Server.NET/OpenBookingHelper/Beta/AuthenticatedPerson.cs index 59cd1de3..a2e6e66a 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Beta/AuthenticatedPerson.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Beta/AuthenticatedPerson.cs @@ -1,7 +1,4 @@ using OpenActive.NET; -using System; -using System.Collections.Generic; -using System.Text; namespace OpenActive.Server.NET.OpenBookingHelper.Beta { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Content/ResponseContent.cs b/OpenActive.Server.NET/OpenBookingHelper/Content/ResponseContent.cs index f132d3ba..7a372724 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Content/ResponseContent.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Content/ResponseContent.cs @@ -1,9 +1,5 @@ using OpenActive.NET; -using System; -using System.Collections.Generic; using System.Net; -using System.Net.Http; -using System.Text; namespace OpenActive.Server.NET.OpenBookingHelper { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Context/BookingFlowContext.cs b/OpenActive.Server.NET/OpenBookingHelper/Context/BookingFlowContext.cs index 919c810d..b9ebdbe7 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Context/BookingFlowContext.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Context/BookingFlowContext.cs @@ -1,8 +1,4 @@ using OpenActive.NET; -using OpenActive.Server.NET.OpenBookingHelper; -using System; -using System.Collections.Generic; -using System.Text; namespace OpenActive.Server.NET.OpenBookingHelper { diff --git a/OpenActive.Server.NET/OpenBookingHelper/DynamicClientRegistration/ClientRegistrationModel.cs b/OpenActive.Server.NET/OpenBookingHelper/DynamicClientRegistration/ClientRegistrationModel.cs index 46e8472c..6ee41b6f 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/DynamicClientRegistration/ClientRegistrationModel.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/DynamicClientRegistration/ClientRegistrationModel.cs @@ -1,8 +1,6 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; -using System; using System.Collections.Generic; -using System.Text; namespace OpenActive.Server.NET.OpenBookingHelper { diff --git a/OpenActive.Server.NET/OpenBookingHelper/DynamicClientRegistration/OidcConstants.cs b/OpenActive.Server.NET/OpenBookingHelper/DynamicClientRegistration/OidcConstants.cs index 571ca8ae..34223d1d 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/DynamicClientRegistration/OidcConstants.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/DynamicClientRegistration/OidcConstants.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace OpenActive.Server.NET.OpenBookingHelper +namespace OpenActive.Server.NET.OpenBookingHelper { public static class OidcConstants { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Enums/FlowStage.cs b/OpenActive.Server.NET/OpenBookingHelper/Enums/FlowStage.cs index 6ea4bced..f68232ff 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Enums/FlowStage.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Enums/FlowStage.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace OpenActive.Server.NET.OpenBookingHelper +namespace OpenActive.Server.NET.OpenBookingHelper { public enum FlowStage { C1, C2, P, B, OrderStatus } } diff --git a/OpenActive.Server.NET/OpenBookingHelper/Enums/TaxPayeeRelationship.cs b/OpenActive.Server.NET/OpenBookingHelper/Enums/TaxPayeeRelationship.cs index 2a3639da..c70e43e2 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Enums/TaxPayeeRelationship.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Enums/TaxPayeeRelationship.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace OpenActive.Server.NET.OpenBookingHelper +namespace OpenActive.Server.NET.OpenBookingHelper { public enum TaxPayeeRelationship { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Exceptions/OpenBookingException.cs b/OpenActive.Server.NET/OpenBookingHelper/Exceptions/OpenBookingException.cs index f66726d3..2aeb0d1a 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Exceptions/OpenBookingException.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Exceptions/OpenBookingException.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Runtime.Serialization; using OpenActive.NET; using System.Net; diff --git a/OpenActive.Server.NET/OpenBookingHelper/IdTransforms/DefaultComponents.cs b/OpenActive.Server.NET/OpenBookingHelper/IdTransforms/DefaultComponents.cs index 28988776..a13a0f21 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/IdTransforms/DefaultComponents.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/IdTransforms/DefaultComponents.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; using System.Runtime.Serialization; -using System.Text; -using OpenActive.NET; namespace OpenActive.Server.NET.OpenBookingHelper { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Model/ModelSupport.cs b/OpenActive.Server.NET/OpenBookingHelper/Model/ModelSupport.cs index 4a5ea4c1..149af1c2 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Model/ModelSupport.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Model/ModelSupport.cs @@ -1,8 +1,5 @@ using OpenActive.DatasetSite.NET; -using OpenActive.NET; using System; -using System.Collections.Generic; -using System.Text; namespace OpenActive.Server.NET.OpenBookingHelper { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Model/OrderModelSupport.cs b/OpenActive.Server.NET/OpenBookingHelper/Model/OrderModelSupport.cs index dd8208e3..cdf686d2 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Model/OrderModelSupport.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Model/OrderModelSupport.cs @@ -1,8 +1,4 @@ -using OpenActive.DatasetSite.NET; -using OpenActive.NET; -using System; -using System.Collections.Generic; -using System.Text; +using System; namespace OpenActive.Server.NET.OpenBookingHelper { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Rpde/OrdersRpdeBase.cs b/OpenActive.Server.NET/OpenBookingHelper/Rpde/OrdersRpdeBase.cs index 8b3657a4..165f76bf 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Rpde/OrdersRpdeBase.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Rpde/OrdersRpdeBase.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using OpenActive.DatasetSite.NET; -using OpenActive.NET; using OpenActive.NET.Rpde.Version1; // TODO: Consolidate this logic with RpdeBase.cs to remove duplication (using generics?) diff --git a/OpenActive.Server.NET/OpenBookingHelper/Rpde/RpdeOrderingStrategyRouter.cs b/OpenActive.Server.NET/OpenBookingHelper/Rpde/RpdeOrderingStrategyRouter.cs index af3adc88..d1882e17 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Rpde/RpdeOrderingStrategyRouter.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Rpde/RpdeOrderingStrategyRouter.cs @@ -45,7 +45,7 @@ public static class RpdeOrderingStrategyRouter /// /// /// - public async static Task GetRpdePage(this IRpdeFeedGenerator generator, string feedidentifier, long? afterTimestamp, string afterId, long? afterChangeNumber) + public static async Task GetRpdePage(this IRpdeFeedGenerator generator, string feedidentifier, long? afterTimestamp, string afterId, long? afterChangeNumber) { switch (generator) { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Settings/BookingEngineSettings.cs b/OpenActive.Server.NET/OpenBookingHelper/Settings/BookingEngineSettings.cs index 1206fb1f..551b2c54 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Settings/BookingEngineSettings.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Settings/BookingEngineSettings.cs @@ -1,9 +1,6 @@ using System; using System.Collections.Generic; -using System.Text; using OpenActive.DatasetSite.NET; -using OpenActive.NET; -using OpenActive.NET.Rpde.Version1; namespace OpenActive.Server.NET.OpenBookingHelper { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Stores/SellerStore.cs b/OpenActive.Server.NET/OpenBookingHelper/Stores/SellerStore.cs index 40e8f897..d0601b94 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Stores/SellerStore.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Stores/SellerStore.cs @@ -1,8 +1,5 @@ using OpenActive.NET; -using OpenActive.Server.NET.OpenBookingHelper; using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; diff --git a/OpenActive.Server.NET/StoreBookingEngine/Context/StoreBookingFlowContext.cs b/OpenActive.Server.NET/StoreBookingEngine/Context/StoreBookingFlowContext.cs index a577a213..47c8f257 100644 --- a/OpenActive.Server.NET/StoreBookingEngine/Context/StoreBookingFlowContext.cs +++ b/OpenActive.Server.NET/StoreBookingEngine/Context/StoreBookingFlowContext.cs @@ -1,9 +1,7 @@ using OpenActive.NET; -using OpenActive.Server.NET.CustomBooking; using OpenActive.Server.NET.OpenBookingHelper; using System; using System.Collections.Generic; -using System.Text; namespace OpenActive.Server.NET.StoreBooking { diff --git a/OpenActive.Server.NET/StoreBookingEngine/StoreBookingEngine.cs b/OpenActive.Server.NET/StoreBookingEngine/StoreBookingEngine.cs index 1e35a801..7fca642c 100644 --- a/OpenActive.Server.NET/StoreBookingEngine/StoreBookingEngine.cs +++ b/OpenActive.Server.NET/StoreBookingEngine/StoreBookingEngine.cs @@ -296,7 +296,7 @@ public StoreBookingEngine(BookingEngineSettings settings, DatasetSiteGeneratorSe private readonly Dictionary storeRouting; private readonly StoreBookingEngineSettings storeBookingEngineSettings; - protected async override Task InsertTestOpportunity(string testDatasetIdentifier, OpportunityType opportunityType, TestOpportunityCriteriaEnumeration criteria, TestOpenBookingFlowEnumeration openBookingFlow, SellerIdComponents seller) + protected override async Task InsertTestOpportunity(string testDatasetIdentifier, OpportunityType opportunityType, TestOpportunityCriteriaEnumeration criteria, TestOpenBookingFlowEnumeration openBookingFlow, SellerIdComponents seller) { if (!storeRouting.ContainsKey(opportunityType)) throw new InternalOpenBookingException(new InternalLibraryConfigurationError(), "Specified opportunity type is not configured as bookable in the StoreBookingEngine constructor."); @@ -304,7 +304,7 @@ protected async override Task InsertTestOpportunity(string testDatasetIde return await storeRouting[opportunityType].CreateOpportunityWithinTestDataset(testDatasetIdentifier, opportunityType, criteria, openBookingFlow, seller); } - protected async override Task DeleteTestDataset(string testDatasetIdentifier) + protected override async Task DeleteTestDataset(string testDatasetIdentifier) { foreach (var store in storeRouting.Values) { @@ -312,7 +312,7 @@ protected async override Task DeleteTestDataset(string testDatasetIdentifier) } } - protected async override Task TriggerTestAction(OpenBookingSimulateAction simulateAction, OrderIdTemplate orderIdTemplate) + protected override async Task TriggerTestAction(OpenBookingSimulateAction simulateAction, OrderIdTemplate orderIdTemplate) { switch (simulateAction.Object.Value) { @@ -355,7 +355,7 @@ protected async override Task TriggerTestAction(OpenBookingSimulateAction simula } - public async override Task ProcessCustomerCancellation(OrderIdComponents orderId, SellerIdComponents sellerId, OrderIdTemplate orderIdTemplate, List orderItemIds) + public override async Task ProcessCustomerCancellation(OrderIdComponents orderId, SellerIdComponents sellerId, OrderIdTemplate orderIdTemplate, List orderItemIds) { if (!await storeBookingEngineSettings.OrderStore.CustomerCancelOrderItems(orderId, sellerId, orderItemIds)) { @@ -363,7 +363,7 @@ public async override Task ProcessCustomerCancellation(OrderIdComponents orderId } } - public async override Task ProcessOrderProposalCustomerRejection(OrderIdComponents orderId, SellerIdComponents sellerId, OrderIdTemplate orderIdTemplate) + public override async Task ProcessOrderProposalCustomerRejection(OrderIdComponents orderId, SellerIdComponents sellerId, OrderIdTemplate orderIdTemplate) { if (!await storeBookingEngineSettings.OrderStore.CustomerRejectOrderProposal(orderId, sellerId)) { @@ -371,12 +371,12 @@ public async override Task ProcessOrderProposalCustomerRejection(OrderIdComponen } } - protected async override Task ProcessOrderDeletion(OrderIdComponents orderId, SellerIdComponents sellerId) + protected override async Task ProcessOrderDeletion(OrderIdComponents orderId, SellerIdComponents sellerId) { return await storeBookingEngineSettings.OrderStore.DeleteOrder(orderId, sellerId); } - protected async override Task ProcessOrderQuoteDeletion(OrderIdComponents orderId, SellerIdComponents sellerId) + protected override async Task ProcessOrderQuoteDeletion(OrderIdComponents orderId, SellerIdComponents sellerId) { await storeBookingEngineSettings.OrderStore.DeleteLease(orderId, sellerId); } @@ -433,7 +433,7 @@ private static void CheckOrderIntegrity(Order requestOrder, Order responseOrder) } } - protected async override Task ProcessGetOrderStatus(OrderIdComponents orderId, SellerIdComponents sellerIdComponents, ILegalEntity seller) + protected override async Task ProcessGetOrderStatus(OrderIdComponents orderId, SellerIdComponents sellerIdComponents, ILegalEntity seller) { // Get Order without OrderItems expanded var order = await storeBookingEngineSettings.OrderStore.GetOrderStatus(orderId, sellerIdComponents, seller); @@ -468,7 +468,7 @@ protected async override Task ProcessGetOrderStatus(OrderIdComponents ord return order; } - public async override Task ProcessOrderCreationFromOrderProposal(OrderIdComponents orderId, OrderIdTemplate orderIdTemplate, ILegalEntity seller, SellerIdComponents sellerId, Order order) + public override async Task ProcessOrderCreationFromOrderProposal(OrderIdComponents orderId, OrderIdTemplate orderIdTemplate, ILegalEntity seller, SellerIdComponents sellerId, Order order) { if (!await storeBookingEngineSettings.OrderStore.CreateOrderFromOrderProposal(orderId, sellerId, order.OrderProposalVersion, order)) { @@ -650,7 +650,7 @@ public void AugmentWithOpenBookingPrepaymentConflictErrors(List ProcessFlowRequest(BookingFlowContext request, TOrder order) + public override async Task ProcessFlowRequest(BookingFlowContext request, TOrder order) { var flowContext = AugmentContextFromOrder(request, order); diff --git a/OpenActive.Server.NET/StoreBookingEngine/Stores/OpportunityStore.cs b/OpenActive.Server.NET/StoreBookingEngine/Stores/OpportunityStore.cs index 2efec0c0..eb741b78 100644 --- a/OpenActive.Server.NET/StoreBookingEngine/Stores/OpportunityStore.cs +++ b/OpenActive.Server.NET/StoreBookingEngine/Stores/OpportunityStore.cs @@ -1,7 +1,6 @@ using OpenActive.DatasetSite.NET; using OpenActive.NET; using OpenActive.Server.NET.OpenBookingHelper; -using OpenActive.Server.NET.StoreBooking; using System; using System.Collections.Generic; using System.Linq; diff --git a/OpenActive.Server.NET/StoreBookingEngine/Stores/OrderStore.cs b/OpenActive.Server.NET/StoreBookingEngine/Stores/OrderStore.cs index 296481a9..220ff538 100644 --- a/OpenActive.Server.NET/StoreBookingEngine/Stores/OrderStore.cs +++ b/OpenActive.Server.NET/StoreBookingEngine/Stores/OrderStore.cs @@ -2,7 +2,6 @@ using OpenActive.Server.NET.OpenBookingHelper; using System; using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; namespace OpenActive.Server.NET.StoreBooking