/// <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>
 /// Initializes a new instance of the <see cref="DirectoryExtensions"/> class.
 /// </summary>
 /// <param name="gq">initializes graph client</param>
 public DirectoryExtensions(GraphQuery gq)
 {
     this.graphCall = gq;
 }
 /// <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);
 }