public async Task <IActionResult> Identify(string id, string mobile, string remote, string rectype, string idnum, DateTime?idexp) { var pq = from p in _context.Person join u in _context.UserLogin on p.Id equals u.PersonFk where u.Provider == "AzureAD" && u.UserId == this.User.Identity.Name select p; if (await pq.CountAsync() != 1) { throw new Exception("Internal error! Too many persons associated with login " + this.User.Identity.Name); } var person = await pq.FirstAsync(); var voter = await _context.Person.FirstOrDefaultAsync(p => p.PublicId == id); if (voter == null) { return(NotFound("PublicId not found")); } var voteruseridq = from u in _context.UserLogin where u.PersonFk == voter.Id select u.UserId; var voteruid = await voteruseridq.FirstAsync(); List <Guid> electionKeys = null; Dictionary <Guid, Election> elections = null; int ae = 0; if (this.User.IsInRole(EligereRoles.RemoteIdentificationOfficer)) { var(per, relections, rae, psd) = await GetElectionDataForRemoteIdentificationOfficer(person); electionKeys = relections.Keys.ToList(); elections = relections; ae = rae; } else { var(per, celections, cae, psd) = await GetElectionData(person); electionKeys = celections.Keys.ToList(); elections = celections; ae = cae; } var availableVotes = await(from v in _context.Voter where electionKeys.Contains(v.ElectionFk) && v.PersonFk == voter.Id select v).Include(v => v.RecognitionFkNavigation).ToListAsync(); // To avoid international prefix check if (voter.GetPersonAttributes().Mobile != mobile) { var a = voter.GetPersonAttributes(); a.Mobile = mobile.Length < 5 ? null : mobile.Replace(" ", "").Replace("-", ""); voter.SetPersonAttributes(a); } var otp = OTPSender.GenerateOTP(); foreach (var v in availableVotes) { var recognition = v.RecognitionFkNavigation; if (recognition == null) { recognition = new Recognition() { Id = Guid.NewGuid(), }; v.RecognitionFk = recognition.Id; _context.Recognition.Add(recognition); } recognition.Idtype = rectype; recognition.UserId = User.Identity.Name; recognition.AccountProvider = "AzureAD"; recognition.Otp = otp; recognition.State = 0; recognition.Validity = DateTime.Now + TimeSpan.FromMinutes(30); if (User.IsInRole(EligereRoles.RemoteIdentificationOfficer)) { recognition.RemoteIdentification = true; } else { recognition.RemoteIdentification = remote == "on"; } if (rectype != "KnownPerson") { recognition.Idnum = idnum; recognition.Idexpiration = idexp; } } await _context.SaveChangesAsync(); if (mobile.Length > 5) { if (mobile.StartsWith("\\u002B")) { mobile = mobile.Replace("\\u002B", "+"); } OTPSender.SendSMS(Configuration, otp, mobile); } string otpresult = null; try { OTPSender.SendMail(Configuration, otp, voteruid); } catch { otpresult = $"Error sending to {voteruid}"; } return(RedirectToAction("Identify", new { id = id, otpresult = otpresult })); }
public async Task <IActionResult> IdentificationLink() { var pq = from p in _context.Person join u in _context.UserLogin on p.Id equals u.PersonFk where u.Provider == "AzureAD" && u.UserId == this.User.Identity.Name select p; if (await pq.CountAsync() != 1) { throw new Exception("Internal error! Too many persons associated with login " + this.User.Identity.Name); } var person = await pq.FirstAsync(); var comm = new List <Guid>(); var elections = new List <Guid>(); var samplingrate = 0.0; IdentificationType?idtype = default; foreach (var(voter, election, commissions, past, voted) in await GetElections(person)) { if (election.Active && !voted.HasValue) { if (!idtype.HasValue) { idtype = election.ElectionConfiguration.IdentificationType; if (idtype == IdentificationType.Sampling) { samplingrate = election.ElectionConfiguration.SamplingRate; } } else { if (idtype != election.ElectionConfiguration.IdentificationType) { throw new Exception("Identification type should be the same for all elections associated with a voter"); } if (idtype == IdentificationType.Sampling && samplingrate != election.ElectionConfiguration.SamplingRate) { throw new Exception("For sampled identification you should use the same rate"); } } elections.Add(election.Id); foreach (var c in commissions) { comm.Add(c.Id); } } } List <Guid> busycomm = new List <Guid>(); // FIXME: Introduce memoization of voter identification for a period of time (i.e. 30min) to avoid mischievous behavior _manager.CollectExpiredItems(); busycomm = _manager.GetBusyCommissioners(); // 30 out of 100 are sent to some commissioner. 70 if there is an affine commissioner will be preferred // Disabled for student general elections if (false && _manager.Rnd.Next(100) > 30) { var affineCommissioners = await(from ar in _context.IdentificationCommissionerAffinityRel where elections.Contains(ar.ElectionFk) select ar.PersonFk).Distinct().ToListAsync(); var affineIds = await(from psc in _context.PollingStationCommissioner where !busycomm.Contains(psc.PersonFk) && comm.Contains(psc.PollingStationCommissionFk) && affineCommissioners.Contains(psc.PersonFk) && psc.AvailableForRemoteRecognition select new { Id = psc.Id, PersonFk = psc.PersonFk, VirtualRoom = psc.VirtualRoom }).Distinct().ToListAsync(); var affineRids = await(from psc in _context.RemoteIdentificationCommissioner where !busycomm.Contains(psc.PersonFk) && comm.Contains(psc.PollingStationCommissionFk) && affineCommissioners.Contains(psc.PersonFk) && psc.AvailableForRemoteRecognition select new { Id = psc.Id, PersonFk = psc.PersonFk, VirtualRoom = psc.VirtualRoom }).Distinct().ToListAsync(); affineIds.AddRange(affineRids); if (affineIds.Count > 0) { var selecteda = affineIds[_manager.Rnd.Next(affineIds.Count)]; _manager.AddBusyCommissioner(selecteda.PersonFk); return(Redirect(selectVirtualRoom(selecteda.VirtualRoom))); } } var ids = await(from psc in _context.PollingStationCommissioner where !busycomm.Contains(psc.PersonFk) && comm.Contains(psc.PollingStationCommissionFk) && psc.AvailableForRemoteRecognition select new { Id = psc.Id, PersonFk = psc.PersonFk, VirtualRoom = psc.VirtualRoom }).Distinct().ToListAsync(); var rids = await(from psc in _context.RemoteIdentificationCommissioner where !busycomm.Contains(psc.PersonFk) && comm.Contains(psc.PollingStationCommissionFk) && psc.AvailableForRemoteRecognition select new { Id = psc.Id, PersonFk = psc.PersonFk, VirtualRoom = psc.VirtualRoom }).Distinct().ToListAsync(); ids.AddRange(rids); if (ids.Count > 0) { var selected = ids[_manager.Rnd.Next(ids.Count)]; _manager.AddBusyCommissioner(selected.PersonFk); return(Redirect(selectVirtualRoom(selected.VirtualRoom))); } else { if (idtype == IdentificationType.Sampling) { var otp = OTPSender.GenerateOTP(); var votes = await _context.Voter.Where(v => elections.Contains(v.ElectionFk) && v.PersonFk == person.Id).Include(v => v.RecognitionFkNavigation).ToListAsync(); foreach (var v in votes) { var recognition = v.RecognitionFkNavigation; if (recognition == null) { recognition = new Recognition() { Id = Guid.NewGuid(), }; v.RecognitionFk = recognition.Id; _context.Recognition.Add(recognition); } recognition.Idtype = "_SampledIdentification"; recognition.UserId = User.Identity.Name; recognition.AccountProvider = "AzureAD"; recognition.Otp = otp; recognition.State = 0; recognition.Validity = DateTime.Now + TimeSpan.FromMinutes(30); recognition.RemoteIdentification = true; } await _context.SaveChangesAsync(); try { OTPSender.SendMail(Configuration, otp, this.User.Identity.Name); ViewData["OTPResult"] = "Success"; } catch { ViewData["OTPResult"] = "Error"; } return(View("CheckForOTP")); } else { return(View("WaitForCommissioner")); } } }
public async Task <IActionResult> PublicIdentificationElection(string remote) { var pq = from p in _context.Person join u in _context.UserLogin on p.Id equals u.PersonFk where u.Provider == "AzureAD" && u.UserId == this.User.Identity.Name select p; if (await pq.CountAsync() != 1) { throw new Exception("Internal error! Too many persons associated with login " + this.User.Identity.Name); } var person = await pq.FirstAsync(); var(per, elections, count, commissions) = await GetElectionData(person); if (!elections.Where(e => e.Value.ElectionConfiguration.IdentificationType == Models.Extensions.IdentificationType.Public).Any()) { return(BadRequest("No election in the group is not configured to allow public identification")); } var pubElections = new List <Guid>(); pubElections.AddRange( elections .Where(el => el.Value.ElectionConfiguration.IdentificationType == Models.Extensions.IdentificationType.Public) .Select(el => el.Key).ToList() ); var otp = OTPSender.GenerateOTP(); var voters = await _context.Voter.Where(v => pubElections.Contains(v.ElectionFk)).Include(v => v.RecognitionFkNavigation).ToListAsync(); foreach (var v in voters) { var recognition = v.RecognitionFkNavigation; if (recognition == null) { recognition = new Recognition() { Id = Guid.NewGuid(), }; v.RecognitionFk = recognition.Id; _context.Recognition.Add(recognition); } recognition.Idtype = "_PublicIdentification"; recognition.UserId = User.Identity.Name; recognition.AccountProvider = "AzureAD"; recognition.Otp = otp; recognition.State = 0; recognition.Validity = DateTime.Now + TimeSpan.FromMinutes(30); if (User.IsInRole(EligereRoles.RemoteIdentificationOfficer)) { recognition.RemoteIdentification = true; } else { recognition.RemoteIdentification = remote == "off"; } } await _context.SaveChangesAsync(); var pubElList = elections.Where(el => pubElections.Contains(el.Key)).Select(el => el.Value).ToList(); return(View((pubElList, otp))); }