/// <summary>
        /// The Index method is the main method called when the front page of the website is launched. This method:
        /// 1. authenticates the application
        /// 2. performs requested actions in response to form submissions
        /// 3. calls the model to retrieve user data
        /// 4. calls the view to display user data
        /// </summary>
        /// <returns>ActionResult (generally a View).</returns>
        public ActionResult Index()
        {
            string strErrors = string.Empty;

            // check if we have changed authentication parameters
            string strFormAction = this.Request["submitButton"];
            if (strFormAction == "applicationUpdate")
            {
                Org.WhichCred(this.Request["WhichCred"]);
                StringConstants.ClientId = this.Request["AppId"];
                StringConstants.ClientSecret = this.Request["AppSecret"];
                StringConstants.AppObjectId = this.Request["AppObjectId"];
                StringConstants.Tenant = this.Request["AppTenant"];
            }

            // use ADAL library to connect to AAD tenant using authentication parameters
            string baseGraphUri = StringConstants.BaseGraphUri + StringConstants.Tenant;
            GraphQuery graphCall = new GraphQuery();
            graphCall.ApiVersion = StringConstants.ApiVersion;
            graphCall.BaseGraphUri = baseGraphUri;

            // get token using OAuth Authorization Code
            AzureADAuthentication aadAuthentication = new AzureADAuthentication();
            AuthenticationResult authenticationResult = aadAuthentication.GetAuthenticationResult(
                StringConstants.Tenant,
                StringConstants.ClientId,
                StringConstants.ClientSecret,
                StringConstants.Resource,
                StringConstants.AuthenticationEndpoint,
                ref strErrors);
            if (authenticationResult != null)
            {
                ViewBag.Message = "Authentication succeeded!";

                // initialize view data based on default or query string UPN
                NameValueCollection queryValues = Request.QueryString;
                string strUpn = queryValues["upn"];

                // initialize graph
                graphCall.aadAuthentication = aadAuthentication;
                graphCall.aadAuthentication.AadAuthenticationResult = authenticationResult;

                // configure org and extensions model objects
                OrgChart.Models.Org org = new OrgChart.Models.Org(graphCall);
                OrgChart.Models.DirectoryExtensions extensions = new OrgChart.Models.DirectoryExtensions(graphCall);

                // retrieve template user containing all extensions and add manager UPN
                ViewBag.ExtensionRegistryUser = extensions.GetExtensionRegistryUser(ref strErrors);
                ViewBag.ExtensionRegistryUser["managerUserPrincipalName"] = org.GetUsersManager(DirectoryExtensions.GetExtensionRegistryUserUpn());

                // setup JObject for setuser by enumerating registry user
                JObject graphUser = new JObject();
                foreach (JProperty property in ViewBag.ExtensionRegistryUser.Properties())
                {
                    if (property.Name.StartsWith(DirectoryExtensions.ExtensionPropertyPrefix) || Org.StandardAttributes().Contains(property.Name))
                    {
                        string value = this.Request[property.Name];
                        graphUser[property.Name] = (value == string.Empty) ? null : value;
                    }
                }

                // strFormAction set at top of Index() to process auth parameter actions, process the rest of the actions here
                switch (strFormAction)
                {
                    case "userUpdate":
                        // set display name, manager, job title, trio, skype for given UPN
                        extensions.SetUser(graphUser, ref strErrors);

                        // show the user, unless trio is set, then show the manager
                        strUpn = this.Request["userPrincipalName"];
                        if ((string)graphUser[DirectoryExtensions.GetExtensionName("trio")] != string.Empty)
                        {
                            strUpn = this.Request["managerUserPrincipalName"];
                        }

                        break;
                    case "userCreate":
                        // create user with given display name, UPN, and manager, show the new user
                        extensions.CreateUser(graphUser, ref strErrors);
                        strUpn = (string)graphUser["userPrincipalName"];
                        break;
                    case "userDelete":
                        // delete user with given UPN
                        org.DeleteUser((string)graphUser["userPrincipalName"], ref strErrors);
                        break;
                    case "extensionCreate":
                        {
                            // register the passed extension
                            string strExtension = this.Request["Extension"];
                            if (extensions.RegisterExtension(strExtension, ref strErrors))
                            {
                                // set this extension value to "registered" on the "registry" object
                                ViewBag.ExtensionRegistryUser[DirectoryExtensions.GetExtensionName(strExtension)] = "reserved";
                                JObject returnedUser = extensions.SetUser(ViewBag.ExtensionRegistryUser, ref strErrors);
                            }
                        }

                        break;
                }

                // may have changed attributes, extension values, extension registration, or tenant credentials, re-retrieve extension registry user
                ViewBag.ExtensionRegistryUser = extensions.GetExtensionRegistryUser(ref strErrors);
                ViewBag.ExtensionRegistryUser["managerUserPrincipalName"] = org.GetUsersManager(DirectoryExtensions.GetExtensionRegistryUserUpn());

                // no UPN provided, get the UPN of the first user instead
                if (strUpn == null)
                {
                    strUpn = org.GetFirstUpn();
                }

                // initialize the ViewBag if we have a UPN
                if (strUpn != null)
                {
                    string strTrio = queryValues["trio"];
                    bool bTrio = strTrio != null && string.Equals(strTrio, "true", StringComparison.CurrentCultureIgnoreCase);
                    ViewBag.AncestorsAndMainPerson = org.GetAncestorsAndMain(strUpn, bTrio, ref strErrors);
                    ViewBag.DirectsOfDirects = org.GetDirectsOfDirects(strUpn, bTrio, ref strErrors);
                    ViewBag.strErrors = strErrors;
                }
            }
            else
            {
                ViewBag.Message = "Authentication Failed!";
            }

            return this.View();
        }
        /// <summary>
        /// The Index method is the main method called when the front page of the website is launched. This method:
        /// 1. authenticates the application
        /// 2. performs requested actions in response to form submissions
        /// 3. calls the model to retrieve user data
        /// 4. calls the view to display user data
        /// </summary>
        /// <returns>ActionResult (generally a View).</returns>
        public ActionResult Index()
        {
            string strErrors = string.Empty;

            // check if we have changed authentication parameters
            string strFormAction = this.Request["submitButton"];

            if (strFormAction == "applicationUpdate")
            {
                Org.WhichCred(this.Request["WhichCred"]);
                StringConstants.ClientId     = this.Request["AppId"];
                StringConstants.ClientSecret = this.Request["AppSecret"];
                StringConstants.AppObjectId  = this.Request["AppObjectId"];
                StringConstants.Tenant       = this.Request["AppTenant"];
            }

            // use ADAL library to connect to AAD tenant using authentication parameters
            string     baseGraphUri = StringConstants.BaseGraphUri + StringConstants.Tenant;
            GraphQuery graphCall    = new GraphQuery();

            graphCall.ApiVersion   = StringConstants.ApiVersion;
            graphCall.BaseGraphUri = baseGraphUri;

            // get token using OAuth Authorization Code
            AzureADAuthentication aadAuthentication    = new AzureADAuthentication();
            AuthenticationResult  authenticationResult = aadAuthentication.GetAuthenticationResult(
                StringConstants.Tenant,
                StringConstants.ClientId,
                StringConstants.ClientSecret,
                StringConstants.Resource,
                StringConstants.AuthenticationEndpoint,
                ref strErrors);

            if (authenticationResult != null)
            {
                ViewBag.Message = "Authentication succeeded!";

                // initialize view data based on default or query string UPN
                NameValueCollection queryValues = Request.QueryString;
                string strUpn = queryValues["upn"];

                // initialize graph
                graphCall.aadAuthentication = aadAuthentication;
                graphCall.aadAuthentication.AadAuthenticationResult = authenticationResult;

                // configure org and extensions model objects
                OrgChart.Models.Org org = new OrgChart.Models.Org(graphCall);
                OrgChart.Models.DirectoryExtensions extensions = new OrgChart.Models.DirectoryExtensions(graphCall);

                // retrieve template user containing all extensions and add manager UPN
                ViewBag.ExtensionRegistryUser = extensions.GetExtensionRegistryUser(ref strErrors);
                ViewBag.ExtensionRegistryUser["managerUserPrincipalName"] = org.GetUsersManager(DirectoryExtensions.GetExtensionRegistryUserUpn());

                // setup JObject for setuser by enumerating registry user
                JObject graphUser = new JObject();
                foreach (JProperty property in ViewBag.ExtensionRegistryUser.Properties())
                {
                    if (property.Name.StartsWith(DirectoryExtensions.ExtensionPropertyPrefix) || Org.StandardAttributes().Contains(property.Name))
                    {
                        string value = this.Request[property.Name];
                        graphUser[property.Name] = (value == string.Empty) ? null : value;
                    }
                }

                // strFormAction set at top of Index() to process auth parameter actions, process the rest of the actions here
                switch (strFormAction)
                {
                case "userUpdate":
                    // set display name, manager, job title, trio, skype for given UPN
                    extensions.SetUser(graphUser, ref strErrors);

                    // show the user, unless trio is set, then show the manager
                    strUpn = this.Request["userPrincipalName"];
                    if ((string)graphUser[DirectoryExtensions.GetExtensionName("trio")] != string.Empty)
                    {
                        strUpn = this.Request["managerUserPrincipalName"];
                    }

                    break;

                case "userCreate":
                    // create user with given display name, UPN, and manager, show the new user
                    extensions.CreateUser(graphUser, ref strErrors);
                    strUpn = (string)graphUser["userPrincipalName"];
                    break;

                case "userDelete":
                    // delete user with given UPN
                    org.DeleteUser((string)graphUser["userPrincipalName"], ref strErrors);
                    break;

                case "extensionCreate":
                {
                    // register the passed extension
                    string strExtension = this.Request["Extension"];
                    if (extensions.RegisterExtension(strExtension, ref strErrors))
                    {
                        // set this extension value to "registered" on the "registry" object
                        ViewBag.ExtensionRegistryUser[DirectoryExtensions.GetExtensionName(strExtension)] = "reserved";
                        JObject returnedUser = extensions.SetUser(ViewBag.ExtensionRegistryUser, ref strErrors);
                    }
                }

                break;
                }

                // may have changed attributes, extension values, extension registration, or tenant credentials, re-retrieve extension registry user
                ViewBag.ExtensionRegistryUser = extensions.GetExtensionRegistryUser(ref strErrors);
                ViewBag.ExtensionRegistryUser["managerUserPrincipalName"] = org.GetUsersManager(DirectoryExtensions.GetExtensionRegistryUserUpn());

                // no UPN provided, get the UPN of the first user instead
                if (strUpn == null)
                {
                    strUpn = org.GetFirstUpn();
                }

                // initialize the ViewBag if we have a UPN
                if (strUpn != null)
                {
                    string strTrio = queryValues["trio"];
                    bool   bTrio   = strTrio != null && string.Equals(strTrio, "true", StringComparison.CurrentCultureIgnoreCase);
                    ViewBag.AncestorsAndMainPerson = org.GetAncestorsAndMain(strUpn, bTrio, ref strErrors);
                    ViewBag.DirectsOfDirects       = org.GetDirectsOfDirects(strUpn, bTrio, ref strErrors);
                    ViewBag.strErrors = strErrors;
                }
            }
            else
            {
                ViewBag.Message = "Authentication Failed!";
            }

            return(this.View());
        }
Exemple #3
0
        /// <summary>
        /// get user JSON object (including extension attributes) for object storing extensions registered by this module
        /// </summary>
        /// <param name="strErrors">error return value</param>
        /// <returns>user object</returns>
        public JObject GetExtensionRegistryUser(ref string strErrors)
        {
            string strUpn = DirectoryExtensions.GetExtensionRegistryUserUpn();

            return(this.GetUser(strUpn, ref strErrors));
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="Org"/> class.
 /// </summary>
 /// <param name="gq">initialized graph client object</param>
 public Org(GraphQuery gq)
 {
     this.graphCall = gq;
     this.extensions = new DirectoryExtensions(gq);
 }
        /// <summary>
        /// Retrieves chain of command for entity represented by UPN.
        /// If bTrio is not set, this returns list of single item lists terminating with single item list containing CEO.
        /// If bTrio is set, this returns list of trio leader lists terminating with single item list containing CEO.
        /// </summary>
        /// <param name="strUPN">Main person we are displaying in the org chart.</param>
        /// <param name="bTrio">Whether we are displaying in trio mode.</param>
        /// <param name="strErrors">Error return value.</param>
        /// <returns>list of list of users</returns>
        public List <List <JObject> > GetAncestorsAndMain(string strUPN, bool bTrio, ref string strErrors)
        {
            List <List <JObject> > returnedListOfLists = new List <List <JObject> >();

            // preserve original error
            string strOriginalError = strErrors;

            // split comma delimited UPN list into UPNs
            string[] arrayUPN = strUPN.Split(',');
            for (int idxTrio = 0; idxTrio < arrayUPN.Length; idxTrio++)
            {
                // retrieve graph node for this person (or for each trio member) from graph
                string  strMainUPN = arrayUPN[idxTrio];
                JObject graphUser  = this.extensions.GetUser(strMainUPN, ref strErrors);

                // TODO: this logic is dependent on trios being properly filled in at each level of hierarchy

                // enumerate graph users from the main person (or from each trio member) to the root
                int idxAncestorOrMain = 0;
                while (graphUser != null)
                {
                    // create a new AncestorOrMain trio list if processing non-trio member or first member of trio
                    if (idxTrio == 0)
                    {
                        returnedListOfLists.Insert(0, new List <JObject>());
                    }

                    // get next graph user
                    JObject graphUserParent = this.extensions.GetUsersManager((string)graphUser["userPrincipalName"], ref strErrors);

                    // tag user with manager attribute
                    graphUser["managerUserPrincipalName"] = (graphUserParent != null) ? graphUserParent["userPrincipalName"] : "NO MANAGER";

                    // insert user at end of the correct AncestorOrMain trio list
                    JToken tokenTrio = null;
                    if (bTrio && graphUser.TryGetValue(DirectoryExtensions.GetExtensionName("trio"), out tokenTrio))
                    {
                        // trio mode and there is a trio set on this object, add to list each time through
                        returnedListOfLists.ElementAt(returnedListOfLists.Count - idxAncestorOrMain - 1).Add(graphUser);
                    }
                    else if (idxTrio == 0)
                    {
                        // otherwise, this user not part of a trio, just add the first time through
                        returnedListOfLists.ElementAt(returnedListOfLists.Count - idxAncestorOrMain - 1).Add(graphUser);
                    }

                    // detect infinite loop: user is own manager, skip, notify and allow user to fix
                    if ((graphUserParent != null) && ((string)graphUserParent["userPrincipalName"] == (string)graphUser["userPrincipalName"]))
                    {
                        strErrors += (string)graphUser["userPrincipalName"] + " has itself as manager. Please resolve.\n";
                        break;
                    }

                    // set next graph user
                    graphUser = graphUserParent;

                    // increment the ancestor level
                    idxAncestorOrMain++;
                }

                // we know that root doesn't have a manager, restore original error
                if (graphUser == null)
                {
                    strErrors = strOriginalError;
                }
            }

            return(returnedListOfLists);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="Org"/> class.
 /// </summary>
 /// <param name="gq">initialized graph client object</param>
 public Org(GraphQuery gq)
 {
     this.graphCall  = gq;
     this.extensions = new DirectoryExtensions(gq);
 }
        /// <summary>
        /// Retrieves subordinates for entity represented by UPN.
        /// Each direct subordinate is head of a list, with subordinates of that direct as elements of that list.
        /// </summary>
        /// <param name="strUPN">Main person we are displaying in the org chart.</param>
        /// <param name="bTrio">Whether we are displaying in trio mode.</param>
        /// <param name="strErrors">Error return value.</param>
        /// <returns>list of list of users</returns>
        public List <List <JObject> > GetDirectsOfDirects(string strUPN, bool bTrio, ref string strErrors)
        {
            List <List <JObject> > returnedListOfLists = new List <List <JObject> >();

            // split comma delimited UPN list into UPNs
            string[] arrayUPN = strUPN.Split(',');

            // TODO: if in trio mode and only one passed member, do filtered query for rest of trio
            // TODO: more efficient to do this filtered query for rest of trio in GetAncestorsAndMain

            // now retrieve direct reports for single person or trio
            for (int i = 0; i < arrayUPN.Length; i++)
            {
                string strMainUPN = arrayUPN[i];
                JUsers directs    = this.extensions.GetUsersDirectReports(strMainUPN, ref strErrors);
                if (directs != null && directs.users != null)
                {
                    foreach (JObject directReport in directs.users)
                    {
                        // add a new list at front of list of lists
                        returnedListOfLists.Insert(0, new List <JObject>());

                        // tag the direct report with manager attribute
                        directReport["managerUserPrincipalName"] = strMainUPN;

                        // insert the direct report at front of newly inserted list
                        returnedListOfLists.ElementAt(0).Insert(0, directReport);

                        // get direct reports of the direct report (and tag manager state to color code managers among directs)
                        JUsers directsOfDirect = this.extensions.GetUsersDirectReports((string)directReport["userPrincipalName"], ref strErrors);
                        directReport["isManager"] = directsOfDirect.users.Count > 0;
                        foreach (JObject directOfDirect in directsOfDirect.users)
                        {
                            // tag each direct of direct with manager attribute and assume they are not managers (for purposes of coloring)
                            directOfDirect["managerUserPrincipalName"] = (string)directReport["userPrincipalName"];
                            directOfDirect["isManager"] = false;
                            returnedListOfLists.ElementAt(0).Add(directOfDirect);
                        }
                    }
                }
            }

            // sort the list of lists by trio
            // http://stackoverflow.com/questions/3309188/c-net-how-to-sort-a-list-t-by-a-property-in-the-object
            returnedListOfLists.Sort(
                delegate(List <JObject> x, List <JObject> y)
            {
                JToken tokenTrioX = null;
                bool bxTrio       = x.ElementAt(0).TryGetValue(DirectoryExtensions.GetExtensionName("trio"), out tokenTrioX);
                JToken tokenTrioY = null;
                bool byTrio       = y.ElementAt(0).TryGetValue(DirectoryExtensions.GetExtensionName("trio"), out tokenTrioY);

                if (!bxTrio && !byTrio)
                {
                    // if neither has a trio, they are equal
                    return(0);
                }
                else if (bxTrio && !byTrio)
                {
                    // if only one has a trio, that one comes first
                    return(-1);
                }
                else if (!bxTrio && byTrio)
                {
                    // if only one has a trio, that one comes first
                    return(1);
                }
                else if (bxTrio && byTrio)
                {
                    // if both have trios, perform the comparison to determine which one comes first
                    return(((string)tokenTrioX).CompareTo((string)tokenTrioY));
                }
                else
                {
                    return(0);
                }
            });
            return(returnedListOfLists);
        }