Exemple #1
0
        public ActionResult PublishResults(int id)
        {
            Election election = db.Elections.Find(id);

            if (election == null)
            {
                return(HttpNotFound());
            }

            bool canDo = ElectionLifecycleInfo.CanPublishResults(election);

            ViewBag.CanConfirm = canDo;

            if (Request.HttpMethod.ToUpper() != "POST")
            {
                // Just show the template
                return(View(election));
            }

            if (!canDo)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
            }

            AntiForgery.Validate();

            ChangeStateByUserAndRecord(election, ElectionState.ResultsPublished);
            db.SaveChanges();

            BackgroundJob.Enqueue <ElectionStudentSimpleEmailsJobs>(
                jobs => jobs.SendResultsPublished(election.Id, JobCancellationToken.Null)
                );

            return(RedirectToAction("Details", new { id }));
        }
Exemple #2
0
        public ActionResult RegeneratePositions(int id)
        {
            Election election = db.Elections.Find(id);

            if (election == null)
            {
                return(HttpNotFound());
            }

            if (ElectionLifecycleInfo.CanForcePositionGeneration(election))
            {
                using (DbContextTransaction transaction = db.Database.BeginTransaction())
                {
                    election.PositionGenerationInProcess = true;
                    db.SaveChanges();

                    // Undo the PositionGenerationInProcess change if this fails - otherwise the election will be stuck in limbo forever
                    BackgroundJob.Enqueue(() => GeneratePositions.Execute(election.Id, JobCancellationToken.Null));

                    transaction.Commit();
                }
            }

            return(RedirectToAction("Details", new { id }));
        }
Exemple #3
0
        public ActionResult Deactivate(int id)
        {
            Election election = db.Elections.Find(id);

            if (election == null)
            {
                return(HttpNotFound());
            }

            if (!ElectionLifecycleInfo.CanDeactivate(election))
            {
                // No idea how we got here... History?
                return(RedirectToAction("Details", new { id }));
            }

            if (Request.HttpMethod.ToUpper() != "POST")
            {
                // Just show the template
                return(View(election));
            }

            AntiForgery.Validate();

            ChangeStateByUserAndRecord(election, ElectionState.Disabled);
            db.SaveChanges();

            BackgroundJob.Enqueue <SynchronizeDelayedJobsJob>(job => job.Execute(election.Id));

            return(RedirectToAction("Details", new { id }));
        }
Exemple #4
0
        public void TestIsInactive()
        {
            Assert.True(ElectionLifecycleInfo.IsInactive(new Election()));
            Assert.True(ElectionLifecycleInfo.IsInactive(new Election {
                State = ElectionState.Aborted
            }));

            Assert.False(ElectionLifecycleInfo.IsInactive(new Election {
                State = ElectionState.PreNominations
            }));
            Assert.False(ElectionLifecycleInfo.IsInactive(new Election {
                State = ElectionState.Nominations
            }));
            Assert.False(ElectionLifecycleInfo.IsInactive(new Election {
                State = ElectionState.PreVoting
            }));
            Assert.False(ElectionLifecycleInfo.IsInactive(new Election {
                State = ElectionState.Voting
            }));
            Assert.False(ElectionLifecycleInfo.IsInactive(new Election {
                State = ElectionState.Closed
            }));
            Assert.False(ElectionLifecycleInfo.IsInactive(new Election {
                State = ElectionState.ResultsPublished
            }));
        }
Exemple #5
0
        public void TestIsAfter()
        {
            Assert.True(ElectionLifecycleInfo.IsAfter(
                            new Election {
                State = ElectionState.PreVoting
            },
                            ElectionState.Nominations
                            ));

            Assert.False(ElectionLifecycleInfo.IsAfter(
                             new Election {
                State = ElectionState.PreNominations
            },
                             ElectionState.Nominations
                             ));

            Assert.False(ElectionLifecycleInfo.IsAfter(
                             new Election {
                State = ElectionState.Nominations
            },
                             ElectionState.Nominations
                             ));

            Assert.Throws <InactiveElectionNoLifecycleComparisonException>(() =>
            {
                ElectionLifecycleInfo.IsAfter(
                    new Election {
                    State = ElectionState.Disabled
                },
                    ElectionState.Nominations
                    );
            });
        }
Exemple #6
0
        public ActionResult Vote(int id /* Election */)
        {
            Election election = db.Elections.Find(id);

            if (election == null)
            {
                return(HttpNotFound());
            }

            string currentUsername = User.Identity.GetUserId();

            // ReSharper disable once SimplifyLinqExpression
            if (!election.EligibilityEntries.Any(entry => entry.Username == currentUsername))
            {
                // This student is not eligible for this election - pretend it doesn't exist
                return(HttpNotFound());
            }

            if (!ElectionLifecycleInfo.CanVote(election))
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
            }

            return(View(new VotingData(
                            election,
                            new VotingManager().PrepareVotingDataFor(currentUsername, election)
                            )));
        }
Exemple #7
0
        public void TestBefore()
        {
            Assert.Throws <ArgumentOutOfRangeException>(() => ElectionLifecycleInfo.Before(ElectionState.PreNominations));

            Assert.AreEqual(ElectionState.PreNominations, ElectionLifecycleInfo.Before(ElectionState.Nominations));
            Assert.AreEqual(ElectionState.Nominations, ElectionLifecycleInfo.Before(ElectionState.PreVoting));
            Assert.AreEqual(ElectionState.PreVoting, ElectionLifecycleInfo.Before(ElectionState.Voting));
            Assert.AreEqual(ElectionState.Voting, ElectionLifecycleInfo.Before(ElectionState.Closed));
            Assert.AreEqual(ElectionState.Closed, ElectionLifecycleInfo.Before(ElectionState.ResultsPublished));

            Assert.Throws <ArgumentOutOfRangeException>(() => ElectionLifecycleInfo.Before(ElectionState.Disabled));
            Assert.Throws <ArgumentOutOfRangeException>(() => ElectionLifecycleInfo.Before(ElectionState.Aborted));
        }
Exemple #8
0
        public ActionResult Delete(int id)
        {
            Election election = db.Elections.Find(id);

            if (election == null)
            {
                return(HttpNotFound());
            }

            bool canDo = ElectionLifecycleInfo.CanDelete(election);

            ViewBag.CanConfirm = canDo;

            if (Request.HttpMethod.ToUpper() != "POST")
            {
                // Just show the template
                return(View(election));
            }

            if (!canDo)
            {
                // Just reload the page
                return(RedirectToAction("Delete", new { id }));
            }

            AntiForgery.Validate();

            using (DbContextTransaction transaction = db.Database.BeginTransaction())
            {
                // Need to cleanup transitions that have explicit references
                // as otherwise we have cascade cycles and everything spazzes out
                election.RemoveAutomaticStateTransitions(db);
                db.SaveChanges();

                db.Elections.Remove(election);
                db.SaveChanges();

                transaction.Commit();
            }

            return(RedirectToAction("Current"));
        }
Exemple #9
0
        public ActionResult Nominations(int id)
        {
            Election election = db.Elections.Find(id);

            if (election == null)
            {
                return(HttpNotFound());
            }

            string currentUsername = User.Identity.GetUserId();

            // ReSharper disable once SimplifyLinqExpression
            if (!election.EligibilityEntries.Any(entry => entry.Username == currentUsername))
            {
                // This student is not eligible for this election - pretend it doesn't exist
                return(HttpNotFound());
            }

            List <PositionEligibilityEntry> positionEligibilityEntries = db.PositionEligibilityEntries
                                                                         .Where(entry => entry.Username == currentUsername)
                                                                         .Where(entry => entry.Position.ElectionId == election.Id)
                                                                         .ToList();

            NomineeFetcher  nomineeFetcher = new NomineeFetcher(new TimetableUserRepository());
            NominationsData data           = new NominationsData(
                election,
                ElectionLifecycleInfo.CanNominate(election),
                nomineeFetcher.Fetch(positionEligibilityEntries.Select(entry => entry.Position))
                );

            foreach (PositionEligibilityEntry entry in positionEligibilityEntries)
            {
                data.ElgibilePositions.Add(new NominationsData.PositionData(
                                               entry.Position,
                                               entry.CanNominate,
                                               entry.Position.NominationEntries.Any(nomination => nomination.Username == currentUsername)
                                               ));
            }

            return(View(data));
        }
        public override bool ShouldBeScheduled()
        {
            ElectionState intendedState = IsStart ? ElectionLifecycleInfo.Before(PhaseState) : PhaseState;

            return(Entity.State == intendedState);
        }
Exemple #11
0
        public ActionResult Edit(int id)
        {
            Election election = db.Elections.Find(id);

            if (election == null)
            {
                return(HttpNotFound());
            }

            CouncilElectionData councilData = null;
            CouncilElectionForm councilForm = null;
            ElectionForm        form;

            if (election.Type == ElectionType.StudentCouncil)
            {
                councilData = db.CouncilElectionData.First(data => data.ElectionId == election.Id);
                form        = councilForm = GenerateFormForCouncil(election, councilData);
            }
            else
            {
                form = GenerateFormForCourseRep(election);
            }

            ModelFieldsAccessibility fieldsInfo = ElectionLifecycleInfo.GetWhatCanBeEditedCouncil(election);

            ViewData[FormConstants.FieldsInfoKey] = fieldsInfo;
            ViewBag.Election = election;

            fieldsInfo.EnsureAllowedDefaultKind(
                ModelFieldsAccessibility.Kind.Editable,
                nameof(AdminElectionsController) + "." + nameof(Edit)
                );

            if (Request.HttpMethod.ToUpper() != "POST")
            {
                // Just show the template
                return(View("Edit", form));
            }

            AntiForgery.Validate();

            // Update the form based on data that we received
            // ReSharper disable once ConvertIfStatementToNullCoalescingExpression - we need the compiler to specify different generic arguments
            if (councilForm != null)
            {
                TryUpdateModel(councilForm);
            }
            else
            {
                TryUpdateModel(form);
            }

            // Get the original form so that we use old values for uneditable fields
            CouncilElectionForm councilOriginalForm = null;
            ElectionForm        originalForm;

            if (councilForm != null)
            {
                originalForm = councilOriginalForm = GenerateFormForCouncil(election, councilData);
            }
            else
            {
                originalForm = GenerateFormForCourseRep(election);
            }

            // Replace all uneditable values with old ones
            fieldsInfo.ReplaceUneditableWithOldValues(form, originalForm);

            // As the role IDs are sent from user, we need to make sure that they weren't changed
            if (councilForm != null && fieldsInfo.CanBeChangedByUser(nameof(CouncilElectionForm.Roles)))
            {
                IEnumerable <int?> initialRoleIds = councilOriginalForm.Roles.Select(role => role.Id);
                IEnumerable <int?> newRoleIds     = councilForm.Roles.Select(role => role.Id);

                if (!initialRoleIds.SequenceEqual(newRoleIds))
                {
                    throw new Exception("The IDs of roles were changed by user input");
                }
            }

            // Validate again (since some rules are relative to other fields and can be affected by operations above)
            TryValidateModel(form);

            // Ignore the failures from uneditable fields
            this.RemoveIgnoredErrors(fieldsInfo);

            if (!ModelState.IsValid)
            {
                // The validation failed so we just display the form again
                return(View("Edit", form));
            }

            // Record the admin action
            AdminActionRecord actionRecord = CreateActionRecord(election, AdminActionRecord.RecordType.Edit);

            actionRecord.SetFormChangeSet(FormChangeSet.Generate(form, originalForm));
            db.AdminActionRecords.Add(actionRecord);

            // Validation passed with the fields that are allowed to change. Persist the changes
            Mapper.Map(form, election);
            if (councilData != null)
            {
                Mapper.Map(form, councilData);
            }

            db.SaveChanges();

            BackgroundJob.Enqueue <SynchronizeDelayedJobsJob>(job => job.Execute(election.Id));
            AuditLogManager.RecordElectionEdit(User, election);

            return(RedirectToAction("Details", new { id }));
        }
Exemple #12
0
        public ActionResult Details(int id)
        {
            Election election = db.Elections.Find(id);

            if (election == null)
            {
                return(HttpNotFound());
            }

            DetailsData data = new DetailsData
            {
                Common         = election,
                NomineeEntries = new NomineeFetcher(new TimetableUserRepository()).Fetch(election.Positions)
            };

            if (election.Type == ElectionType.StudentCouncil)
            {
                data.CouncilElectionData = db.CouncilElectionData
                                           .First(councilData => councilData.ElectionId == id);
            }

            // ReSharper disable once SwitchStatementMissingSomeCases
            switch (election.State)
            {
            case ElectionState.Disabled:
            {
                DetailsData.Action action = new DetailsData.Action()
                {
                    Title   = "Activate",
                    Url     = Url.Action("Activate", new { id }),
                    CssType = "success"
                };

                SimpleValidationResult validationResult = ElectionLifecycleInfo.CanActivate(election);

                if (!validationResult.IsNoErrors())
                {
                    action.Enabled = false;
                    action.Tooltip = validationResult.Violations[0].HumanError;
                }
                else
                {
                    action.Enabled = true;
                }

                data.Actions.Add(action);
                break;
            }

            case ElectionState.PreNominations:
            {
                DetailsData.Action action = new DetailsData.Action()
                {
                    Title   = "Deactivate",
                    Url     = Url.Action("Deactivate", new { id }),
                    CssType = "warning",
                    Enabled = true,
                    Tooltip = "Go back to deactivated state"
                };

                data.Actions.Add(action);
                break;
            }

            case ElectionState.Closed:
            {
                DetailsData.Action action = new DetailsData.Action()
                {
                    Title   = "Publish results",
                    Url     = Url.Action("PublishResults", new { id }),
                    CssType = "success",
                    Enabled = true
                };

                data.Actions.Add(action);
                break;
            }
            }

            if (election.State == ElectionState.Aborted)
            {
                data.Actions.Add(new DetailsData.Action()
                {
                    Title   = "Remove from system",
                    Enabled = true,
                    Url     = Url.Action("Delete", new { id }),
                    CssType = "danger",
                });
            }
            else
            {
                if (ElectionLifecycleInfo.CanEdit(election))
                {
                    data.Actions.Add(new DetailsData.Action()
                    {
                        Title   = "Edit",
                        Enabled = true,
                        Url     = Url.Action("Edit", new { id }),
                        CssType = "primary"
                    });
                }

                // Should be last
                data.Actions.Add(new DetailsData.Action()
                {
                    Title   = "Abort",
                    Enabled = true,
                    Url     = Url.Action("Abort", new { id }),
                    CssType = "danger"
                });
            }

            return(View(data));
        }
Exemple #13
0
        public ActionResult UpdateNominationsStatus(int positionId, bool newStatus)
        {
            VotablePosition position = db.VotablePositions.Find(positionId);

            if (position == null)
            {
                return(HttpNotFound());
            }

            Election election        = position.Election;
            string   currentUsername = User.Identity.GetUserId();

            // ReSharper disable once SimplifyLinqExpression
            if (!election.EligibilityEntries.Any(entry => entry.Username == currentUsername))
            {
                // This student is not eligible for this election - pretend it doesn't exist
                return(HttpNotFound());
            }

            PositionEligibilityEntry positionEligibilityEntry = db.PositionEligibilityEntries
                                                                .FirstOrDefault(entry => entry.PositionId == positionId && entry.Username == currentUsername);

            if (positionEligibilityEntry == null)
            {
                // This student is not eligible for this position - pretend it doesn't exist
                return(HttpNotFound());
            }

            // At this point we are sure that the position is visible to this student
            // Now we need to check whether (s)he can change the status (at this time)

            if (!ElectionLifecycleInfo.CanNominate(election) || !positionEligibilityEntry.CanNominate)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
            }

            // At this point we are sure that the student can change the nomination status for this position
            // Now we just need to create or delete the record in database (or do nothing if it's already matching)

            NominationEntry exitingNomination = position.NominationEntries
                                                .FirstOrDefault(entry => entry.Username == currentUsername);

            if (exitingNomination != null)
            {
                if (newStatus)
                {
                    // Do nothing
                }
                else
                {
                    // There is an existing one, remove it
                    db.NominationEntries.Remove(exitingNomination);
                    db.SaveChanges();
                }
            }
            else
            {
                if (newStatus)
                {
                    // No nomination currently, create one
                    db.NominationEntries.Add(new NominationEntry()
                    {
                        Position = position, Username = currentUsername
                    });
                    db.SaveChanges();
                }
                else
                {
                    // Do nothing
                }
            }

            AuditLogManager.RecordNominationUpdate(User, position, newStatus);

            return(RedirectToAction("Nominations", new { id = election.Id }));
        }
 public override bool ShouldBeScheduled()
 {
     return
         (ElectionLifecycleInfo.AreAlmostOverEmailsEnabled(Entity) &&
          Entity.State == GetPhase().AssociatedState);
 }