예제 #1
0
        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 }));
        }
예제 #2
0
        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"));
                }
            }
        }
예제 #3
0
        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)));
        }