public void SetFormChangeSet <TForm>([CanBeNull] FormChangeSet <TForm> changeSet) { if (changeSet == null) { FormChangeSetSerialized = null; return; } using (var memoryStream = new MemoryStream()) { new BinaryFormatter().Serialize(memoryStream, changeSet); FormChangeSetSerialized = memoryStream.ToArray(); } }
public ActionResult EventLog(int id) { Election election = db.Elections.Find(id); if (election == null) { return(HttpNotFound()); } List <EventLogEntry> entries = new List <EventLogEntry>(); entries.AddRange( db.AdminActionRecords .Where(record => record.ElectionId == election.Id) .AsEnumerable() .Select(record => { EventLogEntry entry = new EventLogEntry { User = record.UserId, OccuredAt = record.OccurredAt, }; switch (record.Type) { case AdminActionRecord.RecordType.ViewVotes: entry.Text = "Viewed votes"; break; case AdminActionRecord.RecordType.Edit: FormChangeSet <ElectionForm> changeSet = record.GetChangeSet <ElectionForm>(); Debug.Assert(changeSet != null, nameof(changeSet) + " != null"); entry.Text = "Edited election properties. Changed fields:" + FormChangeSetPrinter.GenerateHtmlList(changeSet.Delta); break; default: throw new ArgumentOutOfRangeException(); } return(entry); }) ); entries.AddRange( db.ElectionStateChanges .Where(change => change.ElectionId == election.Id && change.CompletedAt != null) .AsEnumerable() .Select(change => new EventLogEntry { // ReSharper disable once PossibleInvalidOperationException OccuredAt = (DateTime)change.CompletedAt, User = change.InstigatorUsername, Text = change.PreviousState.HasValue ? "State changed from " + change.PreviousState.ToString() + " to " + change.TargetState.ToString() : "Election created" }) ); IDictionary <string, TimetableUserEntry> users = GetTimetableUsers( entries.Select(data => data.User).Where(userid => !string.IsNullOrEmpty(userid)) ); foreach (EventLogEntry entry in entries) { if (entry.User != null && users.TryGetValue(entry.User, out TimetableUserEntry userEntry)) { entry.User = userEntry.Fullname; } } return(View(new EventLogData { Election = election, Entries = entries.OrderByDescending(entry => entry.OccuredAt).ToArray() })); }
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 })); }