Beispiel #1
0
        public string SwedishCircuitMapOrgStrengthLookupReplacer(Match match)
        {
            // Five groups: "color" and "id" are the keys, "start", "middle" and "end" are what to paste in between.

            Dictionary <string, int> lookup = new Dictionary <string, int>();

            lookup["2N"] = 2;
            lookup["2S"] = 38;
            lookup["1"]  = 40;

            Organization org = Organization.FromIdentity(1); // Replace later for more generic

            string resultColorString = "#000000";
            string id    = match.Groups["id"].Value;
            int    geoId = 0;

            try
            {
                if (lookup.ContainsKey(id))
                {
                    geoId = lookup[id];
                }
                else
                {
                    geoId = Int32.Parse(id);
                }

                Geography geo = Geography.FromIdentity(geoId);

                RoleLookup officers = RoleLookup.FromGeographyAndOrganization(geo.Identity, org.Identity);

                bool hasLead   = officers[RoleType.LocalLead].Count > 0;
                bool hasSecond = officers[RoleType.LocalDeputy].Count > 0;

                Geographies geoTree = geo.GetTree();

                int cities         = 0;
                int citiesWithLead = 0;

                foreach (Geography localGeo in geoTree)
                {
                    if (localGeo.Identity == geo.Identity)
                    {
                        continue;
                    }

                    if (localGeo.Name.EndsWith("kommun"))
                    {
                        cities++;

                        officers = RoleLookup.FromGeographyAndOrganization(localGeo.Identity, org.Identity);

                        if (officers[RoleType.LocalLead].Count > 0)
                        {
                            citiesWithLead++;
                        }
                    }
                }

                int cityLeadPercent = 100;

                if (cities > 0)
                {
                    cityLeadPercent = citiesWithLead * 100 / cities;
                }

                // Determine color

                Color color = Color.Red;

                if (!hasLead)
                {
                    color = Color.Red;
                }
                else if (cityLeadPercent > 80 && hasSecond)
                {
                    color = Color.Green;
                }
                else
                {
                    // Find a hue between Orange and Light Green. Say, between 30 and 120.

                    cityLeadPercent += 30;
                    if (cityLeadPercent > 120)
                    {
                        cityLeadPercent = 120;
                    }

                    color = ColorFromAhsb(100, cityLeadPercent, 1.0f, 0.5f);
                }

                resultColorString = String.Format("#{0:x2}{1:x2}{2:x2}", color.R, color.G, color.B);
            }
            catch (Exception)
            {
                // Ignore - color will be black
            }

            return(match.Groups["start"].Value + resultColorString + match.Groups["middle"].Value + id +
                   match.Groups["end"].Value);
        }
Beispiel #2
0
    protected void ButtonSearch_Click(object sender, EventArgs e)
    {
        // If a member number is present, use only that as search criteria.

        People searchResults = null;

        string searchMemberNumber = this.TextMemberNumber.Text.Trim();

        if (searchMemberNumber.Length > 0)
        {
            // Lots of things here that will throw on invalid arguments
            Regex    re      = new Regex(@"[\s,;]+");
            string[] numbers = re.Replace(searchMemberNumber, ";").Split(';');
            searchResults = new People();
            foreach (string pers in numbers)
            {
                try
                {
                    string persID = pers;
                    if (searchMemberNumber.Trim().ToUpper().StartsWith("PP"))
                    {
                        //Hexcoded number
                        char[] mnr = persID.Substring(2).ToCharArray();
                        Array.Reverse(mnr);
                        persID = new string(mnr);
                        int num = (System.Int32.Parse(searchMemberNumber, System.Globalization.NumberStyles.AllowHexSpecifier));
                        persID = num.ToString();
                    }
                    int    personId = Convert.ToInt32(persID);
                    Person person   = Person.FromIdentity(personId);
                    searchResults.Add(person);
                }
                catch (Exception)
                { }
            }

            if (numbers.Length > 1)
            {
                PersonList.GridView.PageSize = numbers.Length;
                PersonList.ShowStreet        = true;
            }
        }
        else
        {
            searchResults = null;
            try
            {
                if (DropOrganizations.SelectedValue == "-1")
                {
                    if (DropGeographies.SelectedValue != "-1")
                    {
                        searchResults = People.FromGeography(Convert.ToInt32(DropGeographies.SelectedValue));
                    }
                    else
                    {
                        searchResults = null;
                    }
                }
                else
                {
                    searchResults = People.FromOrganizationAndGeography(Convert.ToInt32(DropOrganizations.SelectedValue),
                                                                        Convert.ToInt32(DropGeographies.SelectedValue));
                }
            }
            catch { }

            People nameResult  = People.FromNamePattern(TextNamePattern.Text);
            People emailResult = People.FromEmailPattern(TextEmailPattern.Text);
            People cityResult  = People.FromCityPattern(TextCityPattern.Text);
            People pcResult    = People.FromPostalCodePattern(TextPostalCodePattern.Text);

            if (nameResult != null)
            {
                searchResults = People.LogicalAnd(searchResults, nameResult);
            }
            if (searchResults != null || emailResult != null)
            {
                searchResults = People.LogicalAnd(searchResults, emailResult);
            }
            if (searchResults != null || cityResult != null)
            {
                searchResults = People.LogicalAnd(searchResults, cityResult);
            }
            if (searchResults != null || pcResult != null)
            {
                searchResults = People.LogicalAnd(searchResults, pcResult);
            }

            string inputDateText = textPersonalNumber.Text.Trim();
            if (inputDateText != "")
            {
                int inpLen = inputDateText.Length;
                int yLen   = 2;

                string[] formats2 = new string[] { "yy", "yyMM", "yyMMdd", "yyyy", "yyyyMM", "yyyyMMdd", "yyyy", "yyyy-MM", "yyyy-MM-dd", "yy", "yy-MM", "yy-MM-dd" };
                string[] formats4 = new string[] { "yyyy", "yyyyMM", "yyyyMMdd", "yy", "yyMM", "yyMMdd", "yyyy", "yyyy-MM", "yyyy-MM-dd", "yy", "yy-MM", "yy-MM-dd" };
                string[] formats;

                DateTime parsedDate = DateTime.MinValue;
                DateTime endDate    = DateTime.MaxValue;

                if (inputDateText.StartsWith("19") ||
                    inputDateText.StartsWith("20"))
                {
                    formats = formats4;
                    yLen    = 4;
                }
                else
                {
                    formats = formats2;
                }
                string[] datesSplit = (textPersonalNumber.Text + "--").Split(new string[] { "--" }, StringSplitOptions.None);

                DateTime.TryParseExact(datesSplit[0].Trim(), formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out parsedDate);
                if (parsedDate != DateTime.MinValue)
                {
                    if (datesSplit[1] != "")
                    {
                        DateTime.TryParseExact(datesSplit[1].Trim(), formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out endDate);
                        inpLen = datesSplit[1].Trim().Length;
                        bool dash = textPersonalNumber.Text.Contains("-");
                        if (inpLen == yLen)
                        {
                            endDate = endDate.AddYears(1);
                        }
                        else if (inpLen == yLen + 2 || (dash && inpLen == yLen + 3))
                        {
                            endDate = endDate.AddMonths(1);
                        }
                        else
                        {
                            endDate = endDate.AddDays(1);
                        }
                    }
                    else
                    {
                        inpLen = datesSplit[0].Trim().Length;
                        bool dash = textPersonalNumber.Text.Contains("-");
                        if (inpLen == yLen)
                        {
                            endDate = parsedDate.AddYears(1);
                        }
                        else if (inpLen == yLen + 2 || (dash && inpLen == yLen + 3))
                        {
                            endDate = parsedDate.AddMonths(1);
                        }
                        else
                        {
                            endDate = parsedDate.AddDays(1);
                        }
                    }

                    People dateResults = People.FromBirtDatePattern(parsedDate, endDate);
                    if (searchResults != null || dateResults != null)
                    {
                        searchResults = People.LogicalAnd(searchResults, dateResults);
                    }
                }
            }
        }

        if (searchResults != null && CheckBoxActivist.Checked)
        {
            Geography geoTree = Geography.FromIdentity(Convert.ToInt32(DropGeographies.SelectedValue));

            //Activism can't be searched for in itself. Too heavy on the DB.
            Activists activists   = Activists.FromGeography(Geography.FromIdentity(Convert.ToInt32(DropGeographies.SelectedValue)));
            int[]     activistIds = activists.Identities;
            Dictionary <int, bool> activistsHashed = new Dictionary <int, bool>();
            foreach (int id in activistIds)
            {
                activistsHashed[id] = true;
            }

            searchResults = searchResults.Filter(
                delegate(Person p)
            {
                if (activistsHashed.ContainsKey(p.Identity))
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            });
        }


        if (searchResults != null)
        {
            PersonList.ShowStatus = false;

            Authority auth = _authority;

            //TODO: All this supposes that these permissions can be applied to mon swedish people as well, ie Organization.PPSEid is supposed
            if (!auth.HasPermission(Permission.CanSeeNonMembers, Organization.PPSEid, -1, Authorization.Flag.AnyGeographyExactOrganization))
            {
                PersonList.ShowStatus = true;
            }

            if (!auth.HasPermission(Permission.CanValidateActivistEmail, Organization.PPSEid, -1, Authorization.Flag.AnyGeographyExactOrganization) ||
                searchResults.Count > 5)
            {
                // SERIOUS SECURITY BREACH here: All chairmen for all organizations could see ALL members.
                // "CanValidateActivistEmail" was set for "OrganizationChairman".

                searchResults = searchResults.GetVisiblePeopleByAuthority(auth);
            }
            else
            {
                PersonList.ShowStatus = true;
            }


            if (!auth.HasPermission(Permission.CanValidateActivistEmail, Organization.PPSEid, -1, Authorization.Flag.AnyGeographyExactOrganization) ||
                searchResults.Count > 1)
            {
                // SERIOUS SECURITY BREACH here: All chairmen for all organizations could see ALL members.
                // "CanValidateActivistEmail" was set for "OrganizationChairman".

                searchResults = searchResults.RemoveUnlisted();
            }
            PersonList.PersonList = searchResults;
        }
    }
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.ContentType = "application/json";

            string pattern = HttpUtility.UrlDecode(Request.QueryString["Pattern"]);

            string    geographyString = Request.QueryString["GeographyId"];
            int       geographyId     = int.Parse(geographyString);
            Geography geography       = Geography.FromIdentity(geographyId);

            if (
                !CurrentAuthority.HasAccess(new Access(CurrentOrganization, geography, AccessAspect.PersonalData,
                                                       AccessType.Read)))
            {
                throw new UnauthorizedAccessException("nope");
            }

            People matches = People.FromOrganizationAndGeographyWithPattern(CurrentOrganization, geography, pattern);

            matches = CurrentAuthority.FilterPeople(matches);

            if (matches == null)
            {
                matches = new People();
            }

            if (matches.Count > 1000)
            {
                matches.RemoveRange(1000, matches.Count - 1000);
            }

            List <string> jsonPeople = new List <string>();

            string editPersonTemplate =
                "\"actions\":\"<a href='javascript:masterBeginEditPerson({0})'><img src='/Images/Icons/iconshock-wrench-128x96px-centered.png' height='16' width='24' /></a>\"";

            Dictionary <int, Applicant> applicantLookup = new Dictionary <int, Applicant>();

            if (CurrentOrganization.Parameters.ParticipationEntry == "ApplicationApproval")
            {
                // There are applications possible for this org; find them and put the Score in the Notes field

                Applicants applicants = Applicants.FromPeopleInOrganization(matches, CurrentOrganization);

                foreach (Applicant applicant in applicants)
                {
                    applicantLookup[applicant.PersonId] = applicant;
                }
            }

            foreach (Person person in matches)
            {
                string notes = Participant.Localized(CurrentOrganization.RegularLabel, person.Gender);

                if (applicantLookup.ContainsKey(person.Identity))
                {
                    // If this is an applicant, use the "Notes" field for score
                    notes = "<span class='align-for-numbers'>" + applicantLookup[person.Identity].ScoreTotal.ToString("N0") + "</span>";
                }

                string onePerson = '{' +
                                   String.Format(
                    "\"id\":\"{0}\",\"name\":\"<span class='spanUser{0}Name'>{1}</span>\",\"avatar16Url\":\"{2}\",\"geographyName\":\"{3}\",\"mail\":\"<span class='spanUser{0}Mail'>{4}</span>\",\"notes\":\"{6}\",\"phone\":\"<span class='spanUser{0}Phone'>{5}</span>\"",
                    person.Identity,
                    JsonSanitize(person.Canonical),
                    person.GetSecureAvatarLink(16),
                    JsonSanitize(person.Geography.Localized),
                    JsonSanitize(person.Mail),
                    JsonSanitize(person.Phone),
                    JsonSanitize(notes)) + "," +
                                   String.Format(
                    editPersonTemplate, person.Identity)
                                   + '}';
                jsonPeople.Add(onePerson);
            }

            string result = '[' + String.Join(",", jsonPeople.ToArray()) + ']';

            Response.Output.WriteLine(result);

            Response.End();
        }
Beispiel #4
0
        private static void ProcessUploadThread(object guidObject)
        {
            string    guid        = (string)guidObject;
            Documents documents   = Documents.RecentFromDescription(guid);
            Document  uploadedDoc = documents[0];
            string    data        = string.Empty;
            int       count       = 0;

            using (StreamReader reader = uploadedDoc.GetReader(1252))
            {
                data = reader.ReadToEnd();
            }

            string[] lines = data.Split('\n');

            Random random = new Random();

            Dictionary <string, int> geoNameLookup = new Dictionary <string, int>();

            foreach (string lineRaw in lines)
            {
                count++;
                string   line      = lineRaw.Trim();
                string[] lineParts = line.Split('\t');

                if (lineParts.Length < 2)
                {
                    continue;  // at least country and one geo required
                }

                // set progress

                int percent = (count * 99) / lines.Length;
                if (percent == 0)
                {
                    percent = 1;
                }
                GuidCache.Set(guid + "-Progress", percent);

                // process

                string countryCode = lineParts[0].Trim().ToUpperInvariant();

                int countryGeoId = Geography.RootIdentity;
                if (geoNameLookup.ContainsKey(countryCode))
                {
                    countryGeoId = geoNameLookup[countryCode];
                }
                else
                {
                    Country country = Country.FromCode(countryCode);
                    if (countryGeoId == Geography.RootIdentity) // country not initialized as node
                    {
                        countryGeoId =
                            SwarmDb.GetDatabaseForWriting().CreateGeography(country.Name + " (" + country.Name + ")",
                                                                            Geography.RootIdentity); // TODO: Locate country
                        SwarmDb.GetDatabaseForWriting().SetCountryGeographyId(country.Identity, countryGeoId);
                        geoNameLookup[countryCode] = countryGeoId;
                    }

                    Geographies countryGeographies = Geography.FromIdentity(countryGeoId).GetTree();

                    foreach (Geography geography in countryGeographies)
                    {
                        geoNameLookup[countryCode + geography.Name] = geography.Identity;
                    }
                }

                int lastGeoId = countryGeoId;
                for (int partIndex = 1; partIndex < lineParts.Length; partIndex++)
                {
                    if (geoNameLookup.ContainsKey(countryCode + lineParts[partIndex]))
                    {
                        // geography exists
                        lastGeoId = geoNameLookup[countryCode + lineParts[partIndex]];
                    }
                    else
                    {
                        // geography does not exist yet: create

                        int newGeoId = SwarmDb.GetDatabaseForWriting().CreateGeography(lineParts[partIndex], lastGeoId);
                        geoNameLookup[countryCode + lineParts[partIndex]] = newGeoId;
                        lastGeoId = newGeoId;
                    }
                }
            }

            GuidCache.Set(guid + "-Progress", 100);
        }
    SeriesCollection GetVotingDayRankingData()
    {
        GeographyBallotCoverageLookup lookup;

        lookup = GetLookupFromCache();

        Geographies geos = null;

        string circuitString = Request.QueryString["CircuitId"];
        int    circuitId     = 0;

        if (String.IsNullOrEmpty(Request.QueryString["CircuitId"]))
        {
            geos = Geographies.FromLevel(Country.FromCode("SE"), GeographyLevel.ElectoralCircuit);
        }
        else
        {
            circuitId = Int32.Parse(circuitString);
            Geographies candidateGeos = Geography.FromIdentity(circuitId).GetTree();
            geos = new Geographies();

            foreach (Geography geo in candidateGeos)
            {
                if (lookup.ContainsKey(geo.Identity) && geo.Identity != circuitId)
                {
                    geos.Add(geo);
                }
            }
        }

        GeographyBallotCoverageData data = new GeographyBallotCoverageData();

        foreach (Geography geo in geos)
        {
            if (lookup.ContainsKey(geo.Identity))
            {
                data.Add(lookup[geo.Identity]);
            }
        }

        data.Sort(
            delegate(GeographyBallotCoverageDataPoint p1, GeographyBallotCoverageDataPoint p2)
        {
            int i1 = (absoluteMode?p1.VotingStationsTotal: p1.WVotingStationsTotal)
                     - (absoluteMode?p1.VotingStationsDistroSingle: p1.WVotingStationsDistroSingle);
            int i2 = (absoluteMode?p2.VotingStationsTotal: p2.WVotingStationsTotal)
                     - (absoluteMode?p2.VotingStationsDistroSingle: p2.WVotingStationsDistroSingle);
            return(i1.CompareTo(i2));
        });

        SeriesCollection collection = new SeriesCollection();

        Series seriesPositiveSingle = new Series();

        seriesPositiveSingle.Name = "Positive, single distro";

        Label2.Text = "(I hela Sverige saknar " + (lookup[Geography.SwedenId].VotingStationsTotal - lookup[Geography.SwedenId].VotingStationsDistroSingle).ToString("#,##0") + " väljare Piratpartiets valsedlar.)";

        if (circuitId != 0)
        {
            AddSingleVotingDayDataPoint(lookup[circuitId], seriesPositiveSingle);
        }

        seriesPositiveSingle.Elements.Add(new Element());

        foreach (GeographyBallotCoverageDataPoint dataPoint in data)
        {
            AddSingleVotingDayDataPoint(dataPoint, seriesPositiveSingle);
        }

        seriesPositiveSingle.DefaultElement.Color     = System.Drawing.Color.Red;
        seriesPositiveSingle.DefaultElement.ShowValue = true;

        SeriesCollection result = new SeriesCollection();

        result.Add(seriesPositiveSingle);

        return(result);
    }
Beispiel #6
0
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.ContentType = "text/xml";
        try
        {
            string cacheDataKey = "allGeographies";

            string[] local  = (Request.ServerVariables["LOCAL_ADDR"]).Split(new char[] { '.' });
            string[] remote = (Request.ServerVariables["REMOTE_ADDR"]).Split(new char[] { '.' });
            if (local[0] == remote[0] && local[1] == remote[1])
            {
                localCall = true;
            }

            Geography geography = null;
            string    geoString = Request.QueryString["GeographyId"] != null ? Request.QueryString["GeographyId"].ToString() : "-1";
            string    geoName   = Request.QueryString["GeographyName"] != null ? Request.QueryString["GeographyName"].ToString() : "-1";
            if (geoName != "")
            {
                Geographies allGeographies = (Geographies)Cache.Get(cacheDataKey);

                if (allGeographies == null || geoName == "reload")
                {
                    allGeographies = Geography.Root.GetTree();
                    Cache.Insert(cacheDataKey, allGeographies, null, DateTime.Today.AddHours(1).ToUniversalTime(), System.Web.Caching.Cache.NoSlidingExpiration);
                }

                foreach (Geography g in allGeographies)
                {
                    if (g.Name.ToLower().Trim().Replace("s ", "").Replace(" ", "") == geoName.ToLower().Trim().Replace("s ", "").Replace(" ", "") ||
                        g.Name.ToLower().Trim().Replace(" ", "") == geoName.ToLower().Trim().Replace(" ", ""))
                    {
                        geography = g;
                        break;
                    }
                }
                if (geography == null)
                {
                    Response.Write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n<EPICFAIL>No geography with name:'" + geoName + "'.</EPICFAIL>\r\n");
                    Session.Abandon();
                    Response.End();
                }
            }
            else
            {
                int geoRootId = Int32.Parse(geoString.Trim());
                if (geoRootId < 0)
                {
                    Response.Write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n<EPICFAIL>No geographyId given.</EPICFAIL>\r\n");
                    Session.Abandon();
                    Response.End();
                }
                geography = Geography.FromIdentity(geoRootId);
            }


            XmlElement root = xDoc.CreateElement("ROOT");
            xDoc.AppendChild(root);


            int totOfficers = PrintGeography(root, geography, 1);

            root.SetAttribute("totcount", totOfficers.ToString());
            Response.Write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n" + xDoc.OuterXml);
            Response.Write("\r\n");
            Session.Abandon();
        }
        catch (Exception e1)
        {
            Response.Write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n<EPICFAIL>Exception was thrown. '" + Server.HtmlEncode(e1.Message) + "'</EPICFAIL>\r\n");
            Session.Abandon();
            Response.End();
        }
    }
        public static string GetRecipientCount(int recipientTypeId, int geographyId)
        {
            int personCount = 0;

            AuthenticationData authData  = GetAuthenticationDataAndCulture();
            Geography          geography = Geography.FromIdentity(geographyId);
            Geographies        geoTree   = geography.ThisAndBelow();
            Organizations      orgTree   = authData.CurrentOrganization.ThisAndBelow();

            switch (recipientTypeId)
            {
            case 0:     // "Select one"
                personCount = 0;
                break;

            case 1:              // Applicants
                personCount = 1; // todo
                break;

            case 2:     // Regulars
                personCount = orgTree.GetMemberCountForGeographies(geoTree);
                break;

            case 3:     // Agents
                personCount = Activists.GetCountForGeography(geography);
                break;

            // TODO: Dynamic membership types

            case 101:     // Officers
                personCount = orgTree.GetRoleHolderCountForGeographies(geoTree);
                break;

            case 102:            // Volunteers
                personCount = 0; // TODO
                break;

            default:
                throw new NotImplementedException();
            }

            string result;

            string[] resources = Resources.Pages.Comms.SendMassMessage_RecipientCount.Split('|');

            switch (personCount)
            {
            case 0:
                result = resources[0];
                break;

            case 1:
                result = resources[1];
                break;

            default:
                result = String.Format(resources[2], personCount);
                break;
            }

            return(result);
        }
        public static AjaxCallResult ExecuteSend(int recipientTypeId, int geographyId, string mode, string subject,
                                                 string body, string dummyMail, bool live)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();

            if (PilotInstallationIds.IsPilot(PilotInstallationIds.DevelopmentSandbox) && authData.CurrentUser.Identity == 1 && !live)
            {
                OutboundComm.CreateSandboxMail(subject, body, dummyMail);
                return(new AjaxCallResult {
                    Success = true
                });
            }
            else if (!live)
            {
                // Test mail

                OutboundComm.CreateParticipantMail(subject, body,
                                                   authData.CurrentUser.ParticipationOf(authData.CurrentOrganization), authData.CurrentUser);

                return(new AjaxCallResult {
                    Success = true
                });
            }
            else // Send live
            {
                // TODO: change resolver to match selected group

                OutboundComm.CreateParticipantMail(subject, body, authData.CurrentUser, authData.CurrentUser, authData.CurrentOrganization, Geography.FromIdentity(geographyId));
                return(new AjaxCallResult {
                    Success = true
                });
            }
        }
Beispiel #9
0
        public static AjaxCallResult AssignPosition(int personId, int positionId, int durationMonths, int geographyId)
        {
            AuthenticationData authData  = GetAuthenticationDataAndCulture();
            Position           position  = Position.FromIdentity(positionId);
            Person             person    = Person.FromIdentity(personId);
            Geography          geography = (geographyId == 0 ? null : Geography.FromIdentity(geographyId));

            if (position.PositionLevel == PositionLevel.Geography ||
                position.PositionLevel == PositionLevel.GeographyDefault)
            {
                position.AssignGeography(geography);
            }

            if ((position.OrganizationId > 0 && authData.CurrentOrganization.Identity != position.OrganizationId) || person.Identity < 0)
            {
                throw new UnauthorizedAccessException();
            }
            if (position.PositionLevel == PositionLevel.SystemWide && !authData.Authority.HasAccess(new Access(AccessAspect.Administration)))
            {
                // Authority check for systemwide
                throw new UnauthorizedAccessException();
            }
            if ((position.GeographyId == Geography.RootIdentity || position.GeographyId == 0) &&
                !authData.Authority.HasAccess(new Access(authData.CurrentOrganization, AccessAspect.Administration)))
            {
                // Authority check for org-global
                throw new UnauthorizedAccessException();
            }
            if (
                !authData.Authority.HasAccess(new Access(authData.CurrentOrganization, geography,
                                                         AccessAspect.Administration)))
            {
                // Authority check for org/geo combo
                throw new UnauthorizedAccessException();
            }

            if (position.MaxCount > 0 && position.Assignments.Count >= position.MaxCount)
            {
                return(new AjaxCallResult
                {
                    Success = false,
                    DisplayMessage = Resources.Controls.Swarm.Positions_NoMorePeopleOnPosition
                });
            }

            // Deliberate: no requirement for membership (or equivalent) in order to be assigned to position.
            // Find the current user position used to assign.

            PositionAssignments currentUserAssignments = authData.CurrentUser.PositionAssignments;

            // Get the one this user is currently using to assign - it's either a system level position,
            // one with a parent organization (TODO), or one with this organization

            Position activePosition = null;

            foreach (PositionAssignment currentUserAssignment in currentUserAssignments)
            {
                if (currentUserAssignment.OrganizationId == 0 && currentUserAssignment.Active)
                {
                    activePosition = currentUserAssignment.Position;
                    break; // a system-level active position has priority over org-level
                }
                if (currentUserAssignment.OrganizationId == authData.CurrentOrganization.Identity &&
                    currentUserAssignment.Active)
                {
                    activePosition = currentUserAssignment.Position;
                }
            }

            if (activePosition == null)
            {
                return(new AjaxCallResult
                {
                    Success = false,
                    DisplayMessage = "Error: No authority to assign a position"
                });
            }

            DateTime?expiresUtc = null;

            if (durationMonths > 0)
            {
                expiresUtc = DateTime.UtcNow.AddMonths(durationMonths);
            }

            try
            {
                PositionAssignment.Create(position, geography, person, authData.CurrentUser, activePosition,
                                          expiresUtc, string.Empty);
            }
            catch (DatabaseConcurrencyException)
            {
                return(new AjaxCallResult {
                    Success = false, DisplayMessage = Resources.Global.Error_DatabaseConcurrency
                });
            }

            return(new AjaxCallResult {
                Success = true
            });
        }