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());
        }
示例#4
0
        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);
        }
示例#7
0
        /// <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;
                }
            }
        }
示例#8
0
        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));
        }
示例#12
0
        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));
        }
示例#15
0
        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);
        }
示例#16
0
        /// <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));
                }
            }
        }
示例#17
0
        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
            });
        }
示例#19
0
        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);
        }
示例#20
0
        /// <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);
        }
示例#21
0
        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));
        }
示例#22
0
 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);
 }
示例#24
0
        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);
            }
        }
示例#25
0
        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);
            }
        }