protected internal Poll PollByPollId(Guid pollId, IVotingContext context)
        {
            Expression <Func <Poll, bool> > predicate = (p => p.UUID == pollId);
            string errorMessage = string.Format("Poll {0} not found", pollId);

            return(PollByPredicate(predicate, errorMessage, context));
        }
        private void RemoveOptions(IVotingContext context, Poll poll, IEnumerable <int> optionsToRemove)
        {
            foreach (int pollOptionNumber in optionsToRemove)
            {
                Choice option = poll
                                .Choices
                                .Single(o => o.PollChoiceNumber == pollOptionNumber);

                _metricHandler.HandleChoiceDeletedEvent(option, poll.UUID);
                poll.Choices.Remove(option);
                context.Choices.Remove(option);

                List <Vote> votes = context
                                    .Votes
                                    .Include(v => v.Choice)
                                    .Where(v => v.Choice.PollChoiceNumber == pollOptionNumber)
                                    .ToList();

                foreach (Vote vote in votes)
                {
                    Ballot ballot = context
                                    .Ballots
                                    .Include(b => b.Votes)
                                    .Single(b => b.Votes.Any(v => v.Id == vote.Id));

                    _metricHandler.HandleVoteDeletedEvent(vote, poll.UUID);
                    ballot.Votes.Remove(vote);
                    context.Votes.Remove(vote);
                }
            }
        }
示例#3
0
 private void StoreEvent(Metric eventToStore)
 {
     using (IVotingContext context = _contextFactory.CreateContext())
     {
         context.Metrics.Add(eventToStore);
         context.SaveChanges();
     }
 }
示例#4
0
        public ManagePollTypeRequestResponse Get(Guid manageId)
        {
            using (IVotingContext context = _contextFactory.CreateContext())
            {
                Poll poll = PollByManageId(manageId, context);

                return(pollToModel(poll));
            }
        }
        public List <ManageChoiceResponseModel> Get(Guid manageId)
        {
            using (IVotingContext context = _contextFactory.CreateContext())
            {
                Poll poll = PollByManageId(manageId, context);

                return(poll
                       .Choices
                       .Select(CreateOptionResponseModel)
                       .ToList());
            }
        }
        private Poll GetPoll(Guid manageId, IVotingContext context)
        {
            Poll poll = context
                        .Polls
                        .Include(p => p.Choices)
                        .SingleOrDefault(p => p.ManageId == manageId);

            if (poll == null)
            {
                ThrowError(HttpStatusCode.NotFound, string.Format("Poll for manage id {0} not found", manageId));
            }
            return(poll);
        }
        public CopyPollResponseModel Copy(CopyPollRequestModel pollCopyRequest)
        {
            if (pollCopyRequest == null)
            {
                ThrowError(HttpStatusCode.BadRequest);
            }

            if (!ModelState.IsValid)
            {
                ThrowError(HttpStatusCode.BadRequest, ModelState);
            }

            using (IVotingContext context = _contextFactory.CreateContext())
            {
                string userId = User.Identity.GetUserId();

                Poll pollToCopy = context
                                  .Polls
                                  .Include(p => p.Choices)
                                  .SingleOrDefault(p => p.UUID == pollCopyRequest.UUIDToCopy);

                if (pollToCopy == null)
                {
                    ThrowError(HttpStatusCode.BadRequest);
                }


                if (pollToCopy.CreatorIdentity != userId)
                {
                    ThrowError(HttpStatusCode.Forbidden);
                }

                Poll newPoll = CopyPoll(pollToCopy);

                _metricHandler.HandlePollClonedEvent(newPoll);

                Ballot creatorBallot = CreateBallotForCreator();
                newPoll.Ballots.Add(creatorBallot);

                context.Polls.Add(newPoll);
                context.SaveChanges();

                return(new CopyPollResponseModel()
                {
                    NewPollId = newPoll.UUID,
                    NewManageId = newPoll.ManageId,
                    CreatorBallotToken = creatorBallot.TokenGuid
                });
            }
        }
示例#8
0
        public PollRequestResponseModel Get(Guid id)
        {
            using (IVotingContext context = _contextFactory.CreateContext())
            {
                Poll poll = PollByPollId(id, context);

                Guid?tokenGuid = GetTokenGuidFromHeaders();

                if (poll.InviteOnly)
                {
                    if (!tokenGuid.HasValue)
                    {
                        ThrowError(HttpStatusCode.Unauthorized);
                    }

                    if (poll.Ballots.All(b => b.TokenGuid != tokenGuid.Value))
                    {
                        ThrowError(HttpStatusCode.Unauthorized);
                    }
                }

                Ballot ballot;
                if (tokenGuid.HasValue)
                {
                    ballot = poll.Ballots.SingleOrDefault(b => b.TokenGuid == tokenGuid.Value);

                    if (ballot == null)
                    {
                        ThrowError(HttpStatusCode.NotFound);
                    }
                }
                else
                {
                    tokenGuid = Guid.NewGuid();

                    ballot = new Ballot()
                    {
                        TokenGuid = tokenGuid.Value
                    };

                    poll.Ballots.Add(ballot);
                    context.Ballots.Add(ballot);

                    context.SaveChanges();
                }

                return(CreateResponse(poll, tokenGuid.Value, ballot));
            }
        }
        public void Put(Guid manageId, ManageChoiceUpdateRequest request)
        {
            ValidateRequest(request);

            if (!ModelState.IsValid)
            {
                ThrowError(HttpStatusCode.BadRequest, ModelState);
            }

            using (IVotingContext context = _contextFactory.CreateContext())
            {
                Poll poll = GetPoll(manageId, context);

                List <int> existingPollOptionNumbers = GetExistingPollOptionNumbers(poll);
                List <int> requestPollOptionNumbers  = GetRequestPollOptionNumbers(request);

                if (requestPollOptionNumbers.Except(existingPollOptionNumbers).Any())
                {
                    ThrowError(HttpStatusCode.NotFound, String.Format("Options do not all belong to poll {0}", manageId));
                }


                List <int> optionsToRemove = existingPollOptionNumbers
                                             .Except(requestPollOptionNumbers)
                                             .ToList();

                RemoveOptions(context, poll, optionsToRemove);


                List <int> optionsToUpdate = existingPollOptionNumbers
                                             .Intersect(requestPollOptionNumbers)
                                             .ToList();

                UpdateOptions(request, poll, optionsToUpdate);


                List <ChoiceUpdate> optionUpdatesToAdd = request
                                                         .Choices
                                                         .Where(o => o.ChoiceNumber.HasValue == false)
                                                         .ToList();

                AddNewOptions(context, poll, optionUpdatesToAdd);


                poll.LastUpdatedUtc = DateTime.UtcNow;
                context.SaveChanges();
            }
        }
        public List <DashboardPollResponseModel> Polls()
        {
            using (IVotingContext context = _contextFactory.CreateContext())
            {
                string userId = User.Identity.GetUserId();

                IEnumerable <DashboardPollResponseModel> userPolls = context
                                                                     .Polls
                                                                     .Where(p => p.CreatorIdentity == userId)
                                                                     .OrderByDescending(p => p.CreatedDateUtc)
                                                                     .Include(p => p.Choices)
                                                                     .Select(CreateDashboardResponseFromModel);

                return(userPolls.ToList());
            }
        }
        protected internal Poll PollByManageId(Guid manageId, IVotingContext context)
        {
            Expression <Func <Poll, bool> > predicate = (p => p.ManageId == manageId);
            string errorMessage = string.Format("Poll for manage id {0} not found", manageId);

            Poll poll = PollByPredicate(predicate, errorMessage, context);

            if (String.IsNullOrEmpty(poll.CreatorIdentity) && !String.IsNullOrEmpty(User.Identity.GetUserId()))
            {
                poll.CreatorIdentity = User.Identity.GetUserId();
                poll.Creator         = User.Identity.GetUserName();
                context.SaveChanges();
            }

            return(poll);
        }
        private void AddNewOptions(IVotingContext context, Poll poll, IEnumerable <ChoiceUpdate> optionUpdatesToAdd)
        {
            foreach (ChoiceUpdate optionRequest in optionUpdatesToAdd)
            {
                var option = new Choice
                {
                    Name        = optionRequest.Name,
                    Description = optionRequest.Description
                };

                _metricHandler.HandleChoiceAddedEvent(option, poll.UUID);

                poll.Choices.Add(option);
                context.Choices.Add(option);
            }
        }
示例#13
0
        public void Put(Guid manageId, ManagePollTypeRequest updateRequest)
        {
            using (IVotingContext context = _contextFactory.CreateContext())
            {
                Poll poll = PollByManageId(manageId, context);

                PollType pollType;
                if (!Enum.TryParse <PollType>(updateRequest.PollType, true, out pollType))
                {
                    ModelState.AddModelError("PollType", "Invalid PollType");
                }

                if (!ModelState.IsValid)
                {
                    ThrowError(HttpStatusCode.BadRequest, ModelState);
                }

                if (poll.PollType == pollType)
                {
                    if (pollType != PollType.Points || (poll.MaxPoints == updateRequest.MaxPoints && poll.MaxPerVote == updateRequest.MaxPerVote))
                    {
                        return;
                    }
                }

                List <Vote> removedVotes = context.Votes.Include(v => v.Poll)
                                           .Where(v => v.Poll.UUID == poll.UUID)
                                           .ToList();
                foreach (Vote oldVote in removedVotes)
                {
                    _metricHandler.HandleVoteDeletedEvent(oldVote, poll.UUID);
                    context.Votes.Remove(oldVote);
                }

                _metricHandler.HandlePollTypeChangedEvent(pollType, updateRequest.MaxPerVote ?? 0, updateRequest.MaxPoints ?? 0, poll.UUID);

                poll.PollType   = pollType;
                poll.MaxPerVote = updateRequest.MaxPerVote;

                poll.MaxPoints = updateRequest.MaxPoints;

                poll.LastUpdatedUtc = DateTime.UtcNow;

                context.SaveChanges();
            }
        }
示例#14
0
        public void Setup()
        {
            _dummyPolls = new InMemoryDbSet <Poll>(true);

            var mockContextFactory = new Mock <IContextFactory>();
            var mockContext        = new Mock <IVotingContext>();

            _mockContext = mockContext.Object;
            mockContextFactory.Setup(a => a.CreateContext()).Returns(_mockContext);
            mockContext.Setup(a => a.Polls).Returns(_dummyPolls);

            var mockMetricHandler = new Mock <IMetricHandler>();

            _controller               = new WebApiController(mockContextFactory.Object, mockMetricHandler.Object);
            _controller.Request       = new HttpRequestMessage();
            _controller.Configuration = new HttpConfiguration();
        }
示例#15
0
        private void DeleteBallot(IVotingContext context, Ballot ballot, Poll poll)
        {
            List <Vote> redundantVotes = ballot.Votes.ToList();

            foreach (Vote redundantVote in redundantVotes)
            {
                _metricHandler.HandleVoteDeletedEvent(redundantVote, poll.UUID);
                context.Votes.Remove(redundantVote);
            }

            if (ballot.TokenGuid != Guid.Empty)
            {
                _metricHandler.HandleBallotDeletedEvent(ballot, poll.UUID);
            }

            poll.Ballots.Remove(ballot);
            context.Ballots.Remove(ballot);
        }
        public void Post(Guid pollId, ChoiceCreationRequestModel choiceCreationRequest)
        {
            using (IVotingContext context = _contextFactory.CreateContext())
            {
                if (choiceCreationRequest == null)
                {
                    ThrowError(HttpStatusCode.BadRequest);
                }

                Poll poll = context
                            .Polls
                            .Include(p => p.Choices)
                            .SingleOrDefault(p => p.UUID == pollId);

                if (poll == null)
                {
                    ThrowError(HttpStatusCode.NotFound, string.Format("Poll {0} does not exist", pollId));
                }

                if (!poll.ChoiceAdding)
                {
                    ThrowError(HttpStatusCode.MethodNotAllowed, string.Format("Option adding not allowed for poll {0}", pollId));
                }

                if (!ModelState.IsValid)
                {
                    ThrowError(HttpStatusCode.BadRequest, ModelState);
                }

                Choice newOption = CreateChoiceFromRequest(choiceCreationRequest);

                _metricHandler.HandleChoiceAddedEvent(newOption, pollId);

                poll.Choices.Add(newOption);
                context.Choices.Add(newOption);

                poll.LastUpdatedUtc = DateTime.UtcNow;

                context.SaveChanges();

                ClientSignaller.SignalUpdate(poll.UUID.ToString());
            }
        }
示例#17
0
        // Make sure we are using the PollId, not the corresponding ManageId, if available
        private Guid GetExistingPollId(Guid guid)
        {
            if (guid == Guid.Empty)
            {
                return(Guid.Empty);
            }

            // Find corresponding pollId for manageId
            using (IVotingContext context = _contextFactory.CreateContext())
            {
                Poll matchingPoll = context.Polls.SingleOrDefault(p => p.UUID == guid || p.ManageId == guid);

                if (matchingPoll == null)
                {
                    return(Guid.Empty);
                }

                return(matchingPoll.UUID);
            }
        }
        public ResultsRequestResponseModel Get(Guid pollId)
        {
            using (IVotingContext context = _contextFactory.CreateContext())
            {
                Poll poll = PollByPollId(pollId, context);

                Guid?tokenGuid = GetTokenGuidFromHeaders();

                if (poll.InviteOnly)
                {
                    if (!tokenGuid.HasValue)
                    {
                        ThrowError(HttpStatusCode.Unauthorized);
                    }

                    if (poll.Ballots.All(b => b.TokenGuid != tokenGuid.Value))
                    {
                        ThrowError(HttpStatusCode.Unauthorized);
                    }
                }

                List <Vote> votes = context
                                    .Votes
                                    .Include(v => v.Choice)
                                    .Include(v => v.Ballot)
                                    .Where(v => v.Poll.UUID == pollId)
                                    .ToList();

                _metricHandler.HandleResultsUpdateEvent(HttpStatusCode.OK, pollId);

                ResultsRequestResponseModel response = GenerateResults(votes, poll.Choices, poll.NamedVoting);
                response.PollName      = poll.Name;
                response.NamedVoting   = poll.NamedVoting;
                response.ExpiryDateUtc = poll.ExpiryDateUtc;
                response.PollType      = poll.PollType.ToString();
                return(response);
            }
        }
        public void Put(Guid pollId, Guid tokenGuid, BallotRequestModel ballotRequest)
        {
            using (IVotingContext context = _contextFactory.CreateContext())
            {
                if (ballotRequest == null)
                {
                    ThrowError(HttpStatusCode.BadRequest);
                }

                if (!ModelState.IsValid)
                {
                    ThrowError(HttpStatusCode.BadRequest, ModelState);
                }

                Poll poll = context
                            .Polls
                            .Where(p => p.UUID == pollId)
                            .Include(p => p.Ballots)
                            .Include(p => p.Choices)
                            .SingleOrDefault();

                if (poll == null)
                {
                    ThrowError(HttpStatusCode.NotFound, String.Format("Poll {0} not found", pollId));
                }

                if (poll.ExpiryDateUtc.HasValue && poll.ExpiryDateUtc < DateTime.UtcNow)
                {
                    ThrowError(HttpStatusCode.Forbidden, String.Format("Poll {0} has expired", pollId));
                }


                foreach (VoteRequestModel voteRequest in ballotRequest.Votes)
                {
                    if (poll.Choices.All(o => o.Id != voteRequest.ChoiceId))
                    {
                        ModelState.AddModelError("OptionId", "Option choice not valid for this poll");
                    }
                }

                Ballot ballot = poll
                                .Ballots
                                .SingleOrDefault(t => t.TokenGuid == tokenGuid);

                if (ballot == null)
                {
                    if (poll.InviteOnly)
                    {
                        ThrowError(HttpStatusCode.Forbidden, String.Format("Token {0} not valid for this poll", tokenGuid));
                    }
                    else
                    {
                        ballot = new Ballot()
                        {
                            TokenGuid = tokenGuid
                        };
                        poll.Ballots.Add(ballot);
                    }
                }

                // Poll specific validation
                IVoteValidator voteValidator = _voteValidatorFactory.CreateValidator(poll.PollType);
                voteValidator.Validate(ballotRequest.Votes, poll, ModelState);

                if (!ModelState.IsValid)
                {
                    ThrowError(HttpStatusCode.BadRequest, ModelState);
                }

                List <Vote> existingVotes = context
                                            .Votes
                                            .Include(v => v.Poll)
                                            .Where(v => v.Ballot.TokenGuid == tokenGuid && v.Poll.UUID == pollId)
                                            .ToList();

                foreach (Vote contextVote in existingVotes)
                {
                    _metricHandler.HandleVoteDeletedEvent(contextVote, pollId);
                    context.Votes.Remove(contextVote);
                }

                // For some reason, we don't have an addrange function on Entity Framework
                foreach (VoteRequestModel voteRequest in ballotRequest.Votes)
                {
                    Choice option = context
                                    .Choices
                                    .Single(o => o.Id == voteRequest.ChoiceId);

                    Vote modelToVote = ModelToVote(voteRequest, ballot, option, poll);
                    context.Votes.Add(modelToVote);

                    _metricHandler.HandleVoteAddedEvent(modelToVote, pollId);
                }

                if (!String.IsNullOrEmpty(ballotRequest.VoterName))
                {
                    ballot.VoterName = Regex.Replace(ballotRequest.VoterName, ValidVoterNameRegex, "");
                }

                ballot.HasVoted = true;

                poll.LastUpdatedUtc = DateTime.UtcNow;

                context.SaveChanges();

                ClientSignaller.SignalUpdate(poll.UUID.ToString());
            }
        }
        private Poll PollByPredicate(Expression <Func <Poll, bool> > predicate, string notFoundMessage, IVotingContext context)
        {
            Poll poll = context.Polls
                        .Include(p => p.Choices)
                        .Include(p => p.Ballots)
                        .Include(p => p.Ballots.Select(b => b.Votes))
                        .Include(p => p.Ballots.Select(b => b.Votes.Select(v => v.Choice)))
                        .SingleOrDefault(predicate);

            if (poll == null)
            {
                ThrowError(HttpStatusCode.NotFound, notFoundMessage);
            }

            return(poll);
        }
示例#21
0
        public void Delete(Guid manageId, DeleteVotersRequestModel request)
        {
            if (request == null)
            {
                ThrowError(HttpStatusCode.BadRequest);
            }

            if (!request.BallotDeleteRequests.Any())
            {
                ThrowError(HttpStatusCode.BadRequest);
            }

            if (request.BallotDeleteRequests.Any(b => !b.VoteDeleteRequests.Any()))
            {
                ThrowError(HttpStatusCode.BadRequest);
            }

            using (IVotingContext context = _contextFactory.CreateContext())
            {
                Poll poll = PollByManageId(manageId, context);

                List <Guid> requestBallotGuids = request
                                                 .BallotDeleteRequests
                                                 .Select(b => b.BallotManageGuid)
                                                 .ToList();

                List <Guid> pollBallotGuids = poll
                                              .Ballots
                                              .Select(b => b.ManageGuid)
                                              .ToList();

                if (requestBallotGuids.Except(pollBallotGuids).Any())
                {
                    ThrowError(HttpStatusCode.NotFound, String.Format("Ballots requested for delete do not all belong to poll {0}", manageId));
                }

                List <Ballot> ballots = poll.Ballots.ToList();

                foreach (DeleteBallotRequestModel ballotRequest in request.BallotDeleteRequests)
                {
                    Ballot ballot = ballots.Single(b => b.ManageGuid == ballotRequest.BallotManageGuid);

                    foreach (DeleteVoteRequestModel voteRequest in ballotRequest.VoteDeleteRequests)
                    {
                        Vote vote = ballot.Votes.ToList().SingleOrDefault(v => v.Choice.PollChoiceNumber == voteRequest.ChoiceNumber);

                        if (vote == null)
                        {
                            ThrowError(HttpStatusCode.NotFound, String.Format("Ballot {0} does not contain an option {1}", ballotRequest.BallotManageGuid, voteRequest.ChoiceNumber));
                        }

                        _metricHandler.HandleVoteDeletedEvent(vote, poll.UUID);
                        ballot.Votes.Remove(vote);
                        context.Votes.Remove(vote);
                    }

                    if (!ballot.Votes.Any())
                    {
                        poll.Ballots.Remove(ballot);
                        context.Ballots.Remove(ballot);
                    }
                }

                poll.LastUpdatedUtc = DateTime.UtcNow;

                context.SaveChanges();
            }
        }