public MatchLocation CreateAuditableCopy(MatchLocation matchLocation) { if (matchLocation == null) { return(null); } return(new MatchLocation { MatchLocationId = matchLocation.MatchLocationId, SecondaryAddressableObjectName = matchLocation.SecondaryAddressableObjectName, PrimaryAddressableObjectName = matchLocation.PrimaryAddressableObjectName, StreetDescription = matchLocation.StreetDescription, Locality = matchLocation.Locality, Town = matchLocation.Town, AdministrativeArea = matchLocation.AdministrativeArea, Postcode = matchLocation.Postcode.ToUpperInvariant(), GeoPrecision = matchLocation.GeoPrecision, Latitude = matchLocation.Latitude, Longitude = matchLocation.Longitude, MatchLocationNotes = matchLocation.MatchLocationNotes, MatchLocationRoute = matchLocation.MatchLocationRoute, MemberGroupKey = matchLocation.MemberGroupKey, MemberGroupName = matchLocation.MemberGroupName }); }
/// <summary> /// Gets a description of the match suitable for metadata or search results /// </summary> public string Description() { var description = new StringBuilder(PlayerType.Humanize(LetterCasing.Sentence)).Append(" stoolball "); description.Append(MatchType == null ? "tournament" : MatchType.Humanize(LetterCasing.LowerCase)); if (MatchLocation != null) { description.Append(" at ").Append(MatchLocation.NameAndLocalityOrTown()); } description.Append(". "); if (TournamentQualificationType == Matches.TournamentQualificationType.OpenTournament) { description.Append("Any team may enter this tournament. "); } else if (TournamentQualificationType == Matches.TournamentQualificationType.ClosedTournament) { description.Append("This tournament is for invited or qualifying teams only. "); } if (PlayersPerTeam.HasValue) { description.Append(PlayersPerTeam).Append(" players per team. "); } return(description.ToString().TrimEnd()); }
/// <summary> /// Gets a description of the match suitable for metadata or search results /// </summary> public string Description() { var description = new StringBuilder(); // Display match type/season/tournament if (Tournament != null) { // Check for 'the' to get the grammar right var the = (Tournament.TournamentName.StartsWith("THE ", StringComparison.OrdinalIgnoreCase)) ? string.Empty : "the "; description.Append("Match in ").Append(the).Append(Tournament.TournamentName); if (MatchLocation != null) { description.Append(" at ").Append(MatchLocation.NameAndLocalityOrTown()); } description.Append('.'); } else { description.Append("Stoolball ").Append(MatchType.Humanize(LetterCasing.LowerCase)); if (MatchLocation != null) { description.Append(" at ").Append(MatchLocation.NameAndLocalityOrTown()); } if (Season != null) { var the = Season.Competition.CompetitionName.ToUpperInvariant().Contains("THE "); description.Append(" in ").Append(the ? string.Empty : "the ").Append(Season.Competition.CompetitionName); } description.Append('.'); } return(description.ToString()); }
public async Task Update_location_does_not_redirect_unchanged_route() { var location = _databaseFixture.TestData.MatchLocations.First(); var auditable = new MatchLocation { MatchLocationId = location.MatchLocationId, MatchLocationRoute = location.MatchLocationRoute }; var routeGenerator = new Mock <IRouteGenerator>(); routeGenerator.Setup(x => x.GenerateUniqueRoute(location.MatchLocationRoute, "/locations", auditable.NameAndLocalityOrTownIfDifferent(), NoiseWords.MatchLocationRoute, It.IsAny <Func <string, Task <int> > >())).Returns(Task.FromResult(location.MatchLocationRoute)); var copier = new Mock <IStoolballEntityCopier>(); copier.Setup(x => x.CreateAuditableCopy(location)).Returns(auditable); var redirects = new Mock <IRedirectsRepository>(); var repo = new SqlServerMatchLocationRepository(_databaseFixture.ConnectionFactory, Mock.Of <IAuditRepository>(), Mock.Of <ILogger>(), routeGenerator.Object, redirects.Object, Mock.Of <IHtmlSanitizer>(), copier.Object); var updated = await repo.UpdateMatchLocation(location, Guid.NewGuid(), "Person 1").ConfigureAwait(false); redirects.Verify(x => x.InsertRedirect(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <IDbTransaction>()), Times.Never); }
public void Town_is_required() { var matchLocation = new MatchLocation(); Assert.Contains(ValidateModel(matchLocation), v => v.MemberNames.Contains(nameof(MatchLocation.Town)) && v.ErrorMessage.Contains("is required", StringComparison.OrdinalIgnoreCase)); }
public MatchLocation CreateRedactedCopy(MatchLocation matchLocation) { var redacted = CreateAuditableCopy(matchLocation); if (redacted != null) { redacted.MatchLocationNotes = _dataRedactor.RedactPersonalData(redacted.MatchLocationNotes); } return(redacted); }
/// <summary> /// Removes the current item from the matches list. /// </summary> protected void RemoveCurrentMatch() { if (_matches.Count == 0) { return; } var index = Index - 1; var matchLine = _matches[index].Line; _matches.RemoveAt(index); MatchCount--; // quickly set index to invalid so setting it back to the current index raises a property changed event Index = 0; if (_matches.Count > 0) { if (index == _matches.Count) { // move to the first match Index = 1; } else { // if any other matches are on current line, make sure their offsets are still correct if (_matches[index].Line == matchLine) { var searchText = SearchText.Text; var lineViewModel = Owner.Lines[matchLine - 1]; var lineText = lineViewModel.PendingText ?? lineViewModel.Text; var offset = lineText.IndexOf(searchText, StringComparison.OrdinalIgnoreCase); if (offset > 0) { offset = offset - _matches[index].Column + 1; if (offset != 0) { var index2 = index; do { _matches[index2] = new MatchLocation { Line = matchLine, Column = _matches[index2].Column + offset }; index2++; } while (index2 < _matches.Count && _matches[index2].Line == matchLine); } } } // move to the next match Index = index + 1; } } }
public async Task Create_location_audits_and_logs() { var location = new MatchLocation { PrimaryAddressableObjectName = "New location " + Guid.NewGuid(), MemberGroupKey = Guid.NewGuid(), MemberGroupName = "Test group" }; var auditable = new MatchLocation { PrimaryAddressableObjectName = location.PrimaryAddressableObjectName, MemberGroupKey = location.MemberGroupKey, MemberGroupName = location.MemberGroupName }; var redacted = new MatchLocation { PrimaryAddressableObjectName = location.PrimaryAddressableObjectName, MemberGroupKey = location.MemberGroupKey, MemberGroupName = location.MemberGroupName }; var route = "/locations/" + Guid.NewGuid(); var routeGenerator = new Mock <IRouteGenerator>(); routeGenerator.Setup(x => x.GenerateUniqueRoute("/locations", location.NameAndLocalityOrTownIfDifferent(), NoiseWords.MatchLocationRoute, It.IsAny <Func <string, Task <int> > >())).Returns(Task.FromResult(route)); var copier = new Mock <IStoolballEntityCopier>(); copier.Setup(x => x.CreateAuditableCopy(location)).Returns(auditable); copier.Setup(x => x.CreateRedactedCopy(auditable)).Returns(redacted); var auditRepository = new Mock <IAuditRepository>(); var logger = new Mock <ILogger>(); var repo = new SqlServerMatchLocationRepository(_databaseFixture.ConnectionFactory, auditRepository.Object, logger.Object, routeGenerator.Object, Mock.Of <IRedirectsRepository>(), Mock.Of <IHtmlSanitizer>(), copier.Object); var memberKey = Guid.NewGuid(); var memberName = "Person 1"; var created = await repo.CreateMatchLocation(location, memberKey, memberName).ConfigureAwait(false); copier.Verify(x => x.CreateRedactedCopy(auditable), Times.Once); auditRepository.Verify(x => x.CreateAudit(It.IsAny <AuditRecord>(), It.IsAny <IDbTransaction>()), Times.Once); logger.Verify(x => x.Info(typeof(SqlServerMatchLocationRepository), LoggingTemplates.Created, redacted, memberName, memberKey, typeof(SqlServerMatchLocationRepository), nameof(SqlServerMatchLocationRepository.CreateMatchLocation))); }
private List<KeyValuePair<string, Color>> GenerateStyleMap(IEnumerable<KeyValuePair<StyleClass<TextPattern>, MatchLocation>> targets, string input) { List<KeyValuePair<string, Color>> styleMap = new List<KeyValuePair<string, Color>>(); MatchLocation previousLocation = new MatchLocation(0, 0); int chocolateEnd = 0; foreach (KeyValuePair<StyleClass<TextPattern>, MatchLocation> styledLocation in targets) { MatchLocation currentLocation = styledLocation.Value; if (previousLocation.End > currentLocation.Beginning) { previousLocation = new MatchLocation(0, 0); } int vanillaStart = previousLocation.End; int vanillaEnd = currentLocation.Beginning; int chocolateStart = vanillaEnd; chocolateEnd = currentLocation.End; string vanilla = input.Substring(vanillaStart, vanillaEnd - vanillaStart); string chocolate = input.Substring(chocolateStart, chocolateEnd - chocolateStart); chocolate = matchFoundHandlers[styledLocation.Key].Invoke(input, styledLocation.Value, input.Substring(chocolateStart, chocolateEnd - chocolateStart)); if (vanilla != "") { styleMap.Add(new KeyValuePair<string, Color>(vanilla, styleSheet.UnstyledColor)); } if (chocolate != "") { styleMap.Add(new KeyValuePair<string, Color>(chocolate, styledLocation.Key.Color)); } previousLocation = currentLocation.Prototype(); } if (chocolateEnd < input.Length) { string vanilla = input.Substring(chocolateEnd, input.Length - chocolateEnd); styleMap.Add(new KeyValuePair<string, Color>(vanilla, styleSheet.UnstyledColor)); } return styleMap; }
public async Task <ActionResult> UpdateMatchLocation([Bind(Prefix = "MatchLocation", Include = "SecondaryAddressableObjectName,PrimaryAddressableObjectName,StreetDescription,Locality,Town,AdministrativeArea,Postcode,GeoPrecision,Latitude,Longitude")] MatchLocation location) { if (location is null) { throw new System.ArgumentNullException(nameof(location)); } var beforeUpdate = await _matchLocationDataSource.ReadMatchLocationByRoute(Request.RawUrl).ConfigureAwait(false); location.MatchLocationId = beforeUpdate.MatchLocationId; location.MatchLocationRoute = beforeUpdate.MatchLocationRoute; // get this from the unvalidated form instead of via modelbinding so that HTML can be allowed location.MatchLocationNotes = Request.Unvalidated.Form["MatchLocation.MatchLocationNotes"]; var isAuthorized = _authorizationPolicy.IsAuthorized(beforeUpdate); if (isAuthorized[AuthorizedAction.EditMatchLocation] && ModelState.IsValid) { var currentMember = Members.GetCurrentMember(); var updatedMatchLocation = await _matchLocationRepository.UpdateMatchLocation(location, currentMember.Key, currentMember.Name).ConfigureAwait(false); _cacheOverride.OverrideCacheForCurrentMember(CacheConstants.MatchLocationsCacheKeyPrefix); return(Redirect(updatedMatchLocation.MatchLocationRoute + "/edit")); } var viewModel = new MatchLocationViewModel(CurrentPage, Services.UserService) { MatchLocation = location, }; viewModel.IsAuthorized = isAuthorized; viewModel.Metadata.PageTitle = $"Edit {location.NameAndLocalityOrTown()}"; viewModel.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.MatchLocations, Url = new Uri(Constants.Pages.MatchLocationsUrl, UriKind.Relative) }); viewModel.Breadcrumbs.Add(new Breadcrumb { Name = viewModel.MatchLocation.NameAndLocalityOrTownIfDifferent(), Url = new Uri(viewModel.MatchLocation.MatchLocationRoute, UriKind.Relative) }); return(View("EditMatchLocation", viewModel)); }
public void AdministrativeArea_disallows_31_characters() { var x = "x"; var someValue = new StringBuilder(); for (var i = 1; i <= 31; i++) { someValue.Append(x); } var matchLocation = new MatchLocation { AdministrativeArea = someValue.ToString() }; Assert.Contains(ValidateModel(matchLocation), v => v.MemberNames.Contains(nameof(MatchLocation.AdministrativeArea)) && v.ErrorMessage.Contains("maximum length", StringComparison.OrdinalIgnoreCase)); }
public void MatchLocation_filter_adds_location_breadcrumb() { var builder = new StatisticsBreadcrumbBuilder(); var breadcrumbs = new List <Breadcrumb>(); var location = new MatchLocation { MatchLocationRoute = "/locations/example", PrimaryAddressableObjectName = "Example location", Town = "Test town" }; builder.BuildBreadcrumbs(breadcrumbs, new StatisticsFilter { MatchLocation = location }); Assert.Equal(2, breadcrumbs.Count); Assert.Equal(Constants.Pages.MatchLocations, breadcrumbs[0].Name); Assert.Equal(Constants.Pages.MatchLocationsUrl, breadcrumbs[0].Url.ToString()); Assert.Equal(location.NameAndLocalityOrTownIfDifferent(), breadcrumbs[1].Name); Assert.Equal(location.MatchLocationRoute, breadcrumbs[1].Url.ToString()); }
public void SecondaryAddressableObjectName_disallows_101_characters() { var x = "x"; var someValue = new StringBuilder(); for (var i = 1; i <= 101; i++) { someValue.Append(x); } var matchLocation = new MatchLocation { SecondaryAddressableObjectName = someValue.ToString() }; Assert.Contains(ValidateModel(matchLocation), v => v.MemberNames.Contains(nameof(MatchLocation.SecondaryAddressableObjectName)) && v.ErrorMessage.Contains("maximum length", StringComparison.OrdinalIgnoreCase)); }
public void Postcode_allows_9_characters() { var x = "x"; var someValue = new StringBuilder(); for (var i = 1; i <= 9; i++) { someValue.Append(x); } var matchLocation = new MatchLocation { Postcode = someValue.ToString() }; Assert.DoesNotContain(ValidateModel(matchLocation), v => v.MemberNames.Contains(nameof(MatchLocation.Postcode)) && v.ErrorMessage.Contains("maximum length", StringComparison.OrdinalIgnoreCase)); }
public async Task MatchLocation_route_populates_location_from_matchLocationDataSource() { var matchLocation = new MatchLocation { MatchLocationId = Guid.NewGuid(), MatchLocationRoute = "/locations/example" }; var routeParser = new Mock <IStoolballEntityRouteParser>(); routeParser.Setup(x => x.ParseRoute(matchLocation.MatchLocationRoute)).Returns(StoolballEntityType.MatchLocation); _routeNormaliser.Setup(x => x.NormaliseRouteToEntity(matchLocation.MatchLocationRoute, "locations")).Returns(matchLocation.MatchLocationRoute); _matchLocationDataSource.Setup(x => x.ReadMatchLocationByRoute(matchLocation.MatchLocationRoute, false)).Returns(Task.FromResult(matchLocation)); var filterFactory = new StatisticsFilterFactory(routeParser.Object, _playerDataSource.Object, _clubDataSource.Object, _teamDataSource.Object, _matchLocationDataSource.Object, _competitionDataSource.Object, _seasonDataSource.Object, _routeNormaliser.Object); var result = await filterFactory.FromRoute(matchLocation.MatchLocationRoute).ConfigureAwait(false); _matchLocationDataSource.Verify(x => x.ReadMatchLocationByRoute(matchLocation.MatchLocationRoute, false), Times.Once); Assert.Equal(matchLocation, result.MatchLocation); }
/// <summary> /// Deletes a stoolball match location /// </summary> public async Task DeleteMatchLocation(MatchLocation matchLocation, Guid memberKey, string memberName) { if (matchLocation is null) { throw new ArgumentNullException(nameof(matchLocation)); } using (var connection = _databaseConnectionFactory.CreateDatabaseConnection()) { connection.Open(); using (var transaction = connection.BeginTransaction()) { await connection.ExecuteAsync($@"UPDATE {Tables.PlayerInMatchStatistics} SET MatchLocationId = NULL WHERE MatchLocationId = @MatchLocationId", new { matchLocation.MatchLocationId }, transaction).ConfigureAwait(false); await connection.ExecuteAsync($@"UPDATE {Tables.Match} SET MatchLocationId = NULL WHERE MatchLocationId = @MatchLocationId", new { matchLocation.MatchLocationId }, transaction).ConfigureAwait(false); await connection.ExecuteAsync($@"DELETE FROM {Tables.TeamMatchLocation} WHERE MatchLocationId = @MatchLocationId", new { matchLocation.MatchLocationId }, transaction).ConfigureAwait(false); await connection.ExecuteAsync($@"DELETE FROM {Tables.MatchLocation} WHERE MatchLocationId = @MatchLocationId", new { matchLocation.MatchLocationId }, transaction).ConfigureAwait(false); var auditableMatchLocation = _copier.CreateAuditableCopy(matchLocation); var redacted = _copier.CreateRedactedCopy(auditableMatchLocation); await _auditRepository.CreateAudit(new AuditRecord { Action = AuditAction.Delete, MemberKey = memberKey, ActorName = memberName, EntityUri = matchLocation.EntityUri, State = JsonConvert.SerializeObject(auditableMatchLocation), RedactedState = JsonConvert.SerializeObject(redacted), AuditDate = DateTime.UtcNow }, transaction).ConfigureAwait(false); await _redirectsRepository.DeleteRedirectsByDestinationPrefix(auditableMatchLocation.MatchLocationRoute, transaction).ConfigureAwait(false); transaction.Commit(); _logger.Info(GetType(), LoggingTemplates.Deleted, redacted, memberName, memberKey, GetType(), nameof(DeleteMatchLocation)); } } }
public async Task Create_minimal_location_succeeds() { var location = new MatchLocation { MemberGroupKey = Guid.NewGuid(), MemberGroupName = "Test group" }; var route = "/locations/" + Guid.NewGuid(); var routeGenerator = new Mock <IRouteGenerator>(); routeGenerator.Setup(x => x.GenerateUniqueRoute("/locations", location.NameAndLocalityOrTownIfDifferent(), NoiseWords.MatchLocationRoute, It.IsAny <Func <string, Task <int> > >())).Returns(Task.FromResult(route)); var copier = new Mock <IStoolballEntityCopier>(); copier.Setup(x => x.CreateAuditableCopy(location)).Returns(location); var repo = new SqlServerMatchLocationRepository( _databaseFixture.ConnectionFactory, Mock.Of <IAuditRepository>(), Mock.Of <ILogger>(), routeGenerator.Object, Mock.Of <IRedirectsRepository>(), Mock.Of <IHtmlSanitizer>(), copier.Object); var created = await repo.CreateMatchLocation(location, Guid.NewGuid(), "Member name").ConfigureAwait(false); routeGenerator.Verify(x => x.GenerateUniqueRoute("/locations", location.NameAndLocalityOrTownIfDifferent(), NoiseWords.MatchLocationRoute, It.IsAny <Func <string, Task <int> > >()), Times.Once); using (var connection = _databaseFixture.ConnectionFactory.CreateDatabaseConnection()) { var locationResult = await connection.QuerySingleOrDefaultAsync <MatchLocation>($"SELECT MemberGroupKey, MemberGroupName, MatchLocationRoute FROM {Tables.MatchLocation} WHERE MatchLocationId = @MatchLocationId", new { created.MatchLocationId }).ConfigureAwait(false); Assert.NotNull(locationResult); Assert.Equal(location.MemberGroupKey, locationResult.MemberGroupKey); Assert.Equal(location.MemberGroupName, locationResult.MemberGroupName); Assert.Equal(location.MatchLocationRoute, locationResult.MatchLocationRoute); } }
public void AddTeamToMatchLocation(Team team, MatchLocation matchLocation) { var teamMatchLocationId = _connection.QuerySingleOrDefault <Guid?>($"SELECT TeamMatchLocationId FROM {Tables.TeamMatchLocation} WHERE TeamId = @TeamId AND MatchLocationId = @MatchLocationId", new { team.TeamId, matchLocation.MatchLocationId }); if (teamMatchLocationId.HasValue) { return; } _connection.Execute($@"INSERT INTO {Tables.TeamMatchLocation} (TeamMatchLocationId, MatchLocationId, TeamId, FromDate, UntilDate) VALUES (@TeamMatchLocationId, @MatchLocationId, @TeamId, @FromDate, @UntilDate)", new { TeamMatchLocationId = Guid.NewGuid(), matchLocation.MatchLocationId, team.TeamId, FromDate = new DateTimeOffset(2000, 1, 1, 0, 0, 0, TimeSpan.Zero), UntilDate = (DateTimeOffset?)null }); }
public async Task Update_location_returns_a_copy() { var location = new MatchLocation { MemberGroupKey = Guid.NewGuid(), MemberGroupName = "Test group" }; var copyLocation = new MatchLocation { MemberGroupKey = location.MemberGroupKey, MemberGroupName = location.MemberGroupName }; var routeGenerator = new Mock <IRouteGenerator>(); routeGenerator.Setup(x => x.GenerateUniqueRoute(location.MatchLocationRoute, "/locations", location.NameAndLocalityOrTownIfDifferent(), NoiseWords.MatchLocationRoute, It.IsAny <Func <string, Task <int> > >())).Returns(Task.FromResult("/locations/" + Guid.NewGuid())); var copier = new Mock <IStoolballEntityCopier>(); copier.Setup(x => x.CreateAuditableCopy(location)).Returns(copyLocation); var repo = new SqlServerMatchLocationRepository( _databaseFixture.ConnectionFactory, Mock.Of <IAuditRepository>(), Mock.Of <ILogger>(), routeGenerator.Object, Mock.Of <IRedirectsRepository>(), Mock.Of <IHtmlSanitizer>(), copier.Object); var updated = await repo.UpdateMatchLocation(location, Guid.NewGuid(), "Member name").ConfigureAwait(false); copier.Verify(x => x.CreateAuditableCopy(location), Times.Once); Assert.Equal(copyLocation, updated); }
/// <summary> /// Creates a match location and populates the <see cref="MatchLocation.MatchLocationId"/> /// </summary> /// <returns>The created match location</returns> public async Task <MatchLocation> CreateMatchLocation(MatchLocation matchLocation, Guid memberKey, string memberName) { if (matchLocation is null) { throw new ArgumentNullException(nameof(matchLocation)); } if (string.IsNullOrWhiteSpace(memberName)) { throw new ArgumentNullException(nameof(memberName)); } var auditableMatchLocation = _copier.CreateAuditableCopy(matchLocation); auditableMatchLocation.MatchLocationId = Guid.NewGuid(); auditableMatchLocation.MatchLocationNotes = _htmlSanitiser.Sanitize(auditableMatchLocation.MatchLocationNotes); using (var connection = _databaseConnectionFactory.CreateDatabaseConnection()) { connection.Open(); using (var transaction = connection.BeginTransaction()) { auditableMatchLocation.MatchLocationRoute = await _routeGenerator.GenerateUniqueRoute( "/locations", auditableMatchLocation.NameAndLocalityOrTownIfDifferent(), NoiseWords.MatchLocationRoute, async route => await connection.ExecuteScalarAsync <int>($"SELECT COUNT(*) FROM {Tables.MatchLocation} WHERE MatchLocationRoute = @MatchLocationRoute", new { auditableMatchLocation.MatchLocationRoute }, transaction).ConfigureAwait(false) ).ConfigureAwait(false); await connection.ExecuteAsync( $@"INSERT INTO {Tables.MatchLocation} (MatchLocationId, SecondaryAddressableObjectName, PrimaryAddressableObjectName, StreetDescription, Locality, Town, AdministrativeArea, Postcode, ComparableName, GeoPrecision, Latitude, Longitude, MatchLocationNotes, MatchLocationRoute, MemberGroupKey, MemberGroupName) VALUES (@MatchLocationId, @SecondaryAddressableObjectName, @PrimaryAddressableObjectName, @StreetDescription, @Locality, @Town, @AdministrativeArea, @Postcode, @ComparableName, @GeoPrecision, @Latitude, @Longitude, @MatchLocationNotes, @MatchLocationRoute, @MemberGroupKey, @MemberGroupName)", new { auditableMatchLocation.MatchLocationId, auditableMatchLocation.SecondaryAddressableObjectName, auditableMatchLocation.PrimaryAddressableObjectName, auditableMatchLocation.StreetDescription, auditableMatchLocation.Locality, auditableMatchLocation.Town, auditableMatchLocation.AdministrativeArea, auditableMatchLocation.Postcode, ComparableName = auditableMatchLocation.ComparableName(), GeoPrecision = auditableMatchLocation.GeoPrecision?.ToString(), auditableMatchLocation.Latitude, auditableMatchLocation.Longitude, auditableMatchLocation.MatchLocationNotes, auditableMatchLocation.MatchLocationRoute, auditableMatchLocation.MemberGroupKey, auditableMatchLocation.MemberGroupName }, transaction).ConfigureAwait(false); var redacted = _copier.CreateRedactedCopy(auditableMatchLocation); await _auditRepository.CreateAudit(new AuditRecord { Action = AuditAction.Create, MemberKey = memberKey, ActorName = memberName, EntityUri = matchLocation.EntityUri, State = JsonConvert.SerializeObject(auditableMatchLocation), RedactedState = JsonConvert.SerializeObject(redacted), AuditDate = DateTime.UtcNow }, transaction).ConfigureAwait(false); transaction.Commit(); _logger.Info(GetType(), LoggingTemplates.Created, redacted, memberName, memberKey, GetType(), nameof(CreateMatchLocation)); } } return(auditableMatchLocation); }
public async Task <ActionResult> CreateMatchLocation([Bind(Prefix = "MatchLocation", Include = "SecondaryAddressableObjectName,PrimaryAddressableObjectName,StreetDescription,Locality,Town,AdministrativeArea,Postcode,GeoPrecision,Latitude,Longitude")] MatchLocation location) { if (location is null) { throw new System.ArgumentNullException(nameof(location)); } // get this from the unvalidated form instead of via modelbinding so that HTML can be allowed location.MatchLocationNotes = Request.Unvalidated.Form["MatchLocation.MatchLocationNotes"]; var isAuthorized = _authorizationPolicy.IsAuthorized(location); if (isAuthorized[AuthorizedAction.CreateMatchLocation] && ModelState.IsValid) { // Create an owner group var groupName = _routeGenerator.GenerateRoute("location", location.NameAndLocalityOrTownIfDifferent(), NoiseWords.MatchLocationRoute); IMemberGroup group; do { group = Services.MemberGroupService.GetByName(groupName); if (group == null) { group = new MemberGroup { Name = groupName }; Services.MemberGroupService.Save(group); location.MemberGroupKey = group.Key; location.MemberGroupName = group.Name; break; } else { groupName = _routeGenerator.IncrementRoute(groupName); } }while (group != null); // Assign the current member to the group unless they're already admin var currentMember = Members.GetCurrentMember(); if (!Members.IsMemberAuthorized(null, new[] { Groups.Administrators }, null)) { Services.MemberService.AssignRole(currentMember.Id, group.Name); } // Create the location var createdMatchLocation = await _matchLocationRepository.CreateMatchLocation(location, currentMember.Key, currentMember.Name).ConfigureAwait(false); _cacheOverride.OverrideCacheForCurrentMember(CacheConstants.MatchLocationsCacheKeyPrefix); // Redirect to the location return(Redirect(createdMatchLocation.MatchLocationRoute)); } var viewModel = new MatchLocationViewModel(CurrentPage, Services.UserService) { MatchLocation = location, }; viewModel.IsAuthorized = isAuthorized; viewModel.Metadata.PageTitle = $"Add a ground or sports centre"; viewModel.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.MatchLocations, Url = new Uri(Constants.Pages.MatchLocationsUrl, UriKind.Relative) }); return(View("CreateMatchLocation", viewModel)); }
public IEnumerable <WalletRule> GetMatchedRules(int index, MatchLocation matchType) { return(MatchedRules.Where(r => r.Index == index && r.MatchType == matchType).Select(c => c.Rule)); }
public IEnumerable<WalletRule> GetMatchedRules(int index, MatchLocation matchType) { return MatchedRules.Where(r => r.Index == index && r.MatchType == matchType).Select(c => c.Rule); }
public async Task Update_location_succeeds() { var location = _databaseFixture.TestData.MatchLocations.First(); var auditable = new MatchLocation { MatchLocationId = location.MatchLocationId, SecondaryAddressableObjectName = Guid.NewGuid().ToString(), PrimaryAddressableObjectName = Guid.NewGuid().ToString(), StreetDescription = Guid.NewGuid().ToString(), Locality = Guid.NewGuid().ToString().Substring(0, 35), Town = Guid.NewGuid().ToString().Substring(0, 30), AdministrativeArea = Guid.NewGuid().ToString().Substring(0, 30), Postcode = new string(location.Postcode.Reverse().ToArray()), GeoPrecision = location.GeoPrecision == GeoPrecision.Exact ? GeoPrecision.Street : GeoPrecision.Exact, Latitude = location.Latitude.HasValue ? location.Latitude + 3.5 : 3.5, Longitude = location.Longitude.HasValue ? location.Longitude + 5.1 : 5.1, MatchLocationNotes = location.MatchLocationNotes ?? "Unsanitised notes" }; var updatedRoute = location.MatchLocationRoute + Guid.NewGuid(); var routeGenerator = new Mock <IRouteGenerator>(); routeGenerator.Setup(x => x.GenerateUniqueRoute(location.MatchLocationRoute, "/locations", auditable.NameAndLocalityOrTownIfDifferent(), NoiseWords.MatchLocationRoute, It.IsAny <Func <string, Task <int> > >())).Returns(Task.FromResult(updatedRoute)); var copier = new Mock <IStoolballEntityCopier>(); copier.Setup(x => x.CreateAuditableCopy(location)).Returns(auditable); var originalNotes = auditable.MatchLocationNotes; var sanitisedNotes = location.MatchLocationNotes + Guid.NewGuid(); var sanitizer = new Mock <IHtmlSanitizer>(); sanitizer.Setup(x => x.Sanitize(auditable.MatchLocationNotes)).Returns(sanitisedNotes); var repo = new SqlServerMatchLocationRepository(_databaseFixture.ConnectionFactory, Mock.Of <IAuditRepository>(), Mock.Of <ILogger>(), routeGenerator.Object, Mock.Of <IRedirectsRepository>(), sanitizer.Object, copier.Object); var updated = await repo.UpdateMatchLocation(location, Guid.NewGuid(), "Person 1").ConfigureAwait(false); using (var connection = _databaseFixture.ConnectionFactory.CreateDatabaseConnection()) { var comparableNameResult = await connection.ExecuteScalarAsync <string>( $@"SELECT ComparableName FROM {Tables.MatchLocation} WHERE MatchLocationId = @MatchLocationId", new { updated.MatchLocationId }).ConfigureAwait(false); var locationResult = await connection.QuerySingleOrDefaultAsync <MatchLocation>( $@"SELECT SecondaryAddressableObjectName, PrimaryAddressableObjectName, StreetDescription, Locality, Town, AdministrativeArea, Postcode, Latitude, Longitude, GeoPrecision, MatchLocationNotes, MemberGroupKey, MemberGroupName, MatchLocationRoute FROM {Tables.MatchLocation} WHERE MatchLocationId = @MatchLocationId", new { updated.MatchLocationId }).ConfigureAwait(false); Assert.NotNull(locationResult); Assert.Equal(auditable.ComparableName(), comparableNameResult); Assert.Equal(auditable.SecondaryAddressableObjectName, locationResult.SecondaryAddressableObjectName); Assert.Equal(auditable.PrimaryAddressableObjectName, locationResult.PrimaryAddressableObjectName); Assert.Equal(auditable.StreetDescription, locationResult.StreetDescription); Assert.Equal(auditable.Locality, locationResult.Locality); Assert.Equal(auditable.Town, locationResult.Town); Assert.Equal(auditable.AdministrativeArea, locationResult.AdministrativeArea); Assert.Equal(auditable.Postcode, locationResult.Postcode); Assert.Equal(auditable.Latitude, locationResult.Latitude); Assert.Equal(auditable.Longitude, locationResult.Longitude); Assert.Equal(auditable.GeoPrecision, locationResult.GeoPrecision); sanitizer.Verify(x => x.Sanitize(originalNotes)); Assert.Equal(sanitisedNotes, locationResult.MatchLocationNotes); Assert.Equal(updatedRoute, locationResult.MatchLocationRoute); } }
public async Task Create_complete_location_succeeds() { var originalNotes = "<p>These are unsanitised notes.</p>"; var sanitisedNotes = "<p>Sanitised notes</p>"; var location = new MatchLocation { SecondaryAddressableObjectName = "Pitch 1", PrimaryAddressableObjectName = "Test ground", StreetDescription = "1 Cricketfield Road", Locality = "Test area", Town = "Test town", AdministrativeArea = "Test county", Postcode = "AB1 1CD", GeoPrecision = GeoPrecision.Postcode, Latitude = 123.456, Longitude = 234.567, MatchLocationNotes = originalNotes, MemberGroupKey = Guid.NewGuid(), MemberGroupName = "Test group" }; var route = "/locations/" + Guid.NewGuid(); var routeGenerator = new Mock <IRouteGenerator>(); routeGenerator.Setup(x => x.GenerateUniqueRoute("/locations", location.NameAndLocalityOrTownIfDifferent(), NoiseWords.MatchLocationRoute, It.IsAny <Func <string, Task <int> > >())).Returns(Task.FromResult(route)); var copier = new Mock <IStoolballEntityCopier>(); copier.Setup(x => x.CreateAuditableCopy(location)).Returns(location); var sanitizer = new Mock <IHtmlSanitizer>(); sanitizer.Setup(x => x.Sanitize(location.MatchLocationNotes)).Returns(sanitisedNotes); var repo = new SqlServerMatchLocationRepository( _databaseFixture.ConnectionFactory, Mock.Of <IAuditRepository>(), Mock.Of <ILogger>(), routeGenerator.Object, Mock.Of <IRedirectsRepository>(), sanitizer.Object, copier.Object); var created = await repo.CreateMatchLocation(location, Guid.NewGuid(), "Member name").ConfigureAwait(false); using (var connection = _databaseFixture.ConnectionFactory.CreateDatabaseConnection()) { var comparableNameResult = await connection.ExecuteScalarAsync <string>( $@"SELECT ComparableName FROM {Tables.MatchLocation} WHERE MatchLocationId = @MatchLocationId", new { created.MatchLocationId }).ConfigureAwait(false); var locationResult = await connection.QuerySingleOrDefaultAsync <MatchLocation>( $@"SELECT SecondaryAddressableObjectName, PrimaryAddressableObjectName, StreetDescription, Locality, Town, AdministrativeArea, Postcode, Latitude, Longitude, GeoPrecision, MatchLocationNotes, MemberGroupKey, MemberGroupName, MatchLocationRoute FROM {Tables.MatchLocation} WHERE MatchLocationId = @MatchLocationId", new { created.MatchLocationId }).ConfigureAwait(false); Assert.NotNull(locationResult); Assert.Equal(location.ComparableName(), comparableNameResult); Assert.Equal(location.SecondaryAddressableObjectName, locationResult.SecondaryAddressableObjectName); Assert.Equal(location.PrimaryAddressableObjectName, locationResult.PrimaryAddressableObjectName); Assert.Equal(location.StreetDescription, locationResult.StreetDescription); Assert.Equal(location.Locality, locationResult.Locality); Assert.Equal(location.Town, locationResult.Town); Assert.Equal(location.AdministrativeArea, locationResult.AdministrativeArea); Assert.Equal(location.Postcode, locationResult.Postcode); Assert.Equal(location.Latitude, locationResult.Latitude); Assert.Equal(location.Longitude, locationResult.Longitude); Assert.Equal(location.GeoPrecision, locationResult.GeoPrecision); sanitizer.Verify(x => x.Sanitize(originalNotes)); Assert.Equal(sanitisedNotes, locationResult.MatchLocationNotes); Assert.Equal(location.MemberGroupKey, locationResult.MemberGroupKey); Assert.Equal(location.MemberGroupName, locationResult.MemberGroupName); Assert.Equal(route, locationResult.MatchLocationRoute); } }