People Sync: Creating a Custom Data Source - akumina/AkuminaTraining GitHub Wiki

Applies to

Akumina Foundation 3.4.0.0 and later

Download

You can download the code referenced in this article here

Overview

The Akumina Framework allows easy integration of Users from a variety of data sources into a Akumina Foundation Site. The AppManager has the powerful People Directory Sync app, a management app which enables an administrator to determine the set of users that are accessible to widgets on the site. Out of the box, the People Directory Sync App can pull users from Azure Active Directory or SharePoint User Profiles. image 0

Defining Users in XML

Users can also be defined within xml and synchronized to a Digital Workplace Site. Below is a sample user xml definition.

<Users xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<User ID="23497" DisplayName="Doe, John S" GivenName="John" MiddleInitial="S" Surname="Doe" Mail="[email protected]" JobTitle="Developer" Organization="Sample Organization 1" Section="Sample Organization Product" Division="North America" Department="Engineering" OfficeLocation="Nashua, NH"/>
</Users>

Retrieving Users from a Custom Data Source

We can easily create a custom data source by creating a class that extends the IPeopleDirectoryUserFetcher interface.

using Akumina.Common.Utilities;
using Akumina.Interchange.Core;
using Akumina.Interchange.Core.Entities.Connector;
using Akumina.Interchange.Core.Interfaces;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Web;
using System.Web.Hosting;

namespace CustomPeopleFetcher
{
    public class CustomPeopleFetcher : IPeopleDirectoryUserFetcher
    {
        IConnectorService ConnectorServiceInstance;
        IPeopleDirectoryUserStorageHandler Storage;
        private Dictionary<string, string> _options;

        public CustomPeopleFetcher(IConnectorService _connectorService, IPeopleDirectoryUserStorageHandler _storageHandler)
        {
            ConnectorServiceInstance = _connectorService;
            Storage = _storageHandler;
        }

        public PeopleDirectoryFetchResult FetchUsers()
        {
            PeopleDirectoryFetchResult result = new PeopleDirectoryFetchResult() { IsComplete = false, IsError = true, Message = "Unknown Error" };

            #region Get all Users
            System.IO.StreamReader reader = null;

            try
            {
                Storage.Delete();

                //Storing an xml file within our hosted files. Alternative approach would be to retrieve from a web url
                var requestUrl = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, "SiteDefinitions", "export.xml");

                System.Net.WebRequest request = System.Net.WebRequest.Create(requestUrl);

                var responseStream = request.GetResponse().GetResponseStream();

                reader = new System.IO.StreamReader(responseStream);

                string usersXml = reader.ReadToEnd();

                System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
                xmlDoc.LoadXml(usersXml);

                List<PeopleDirectoryUser> aadUserList = Read(xmlDoc);

                result.Users = aadUserList;
                result.UserCount = aadUserList.Count;
                result.IsComplete = true;
                result.IsError = false;
                result.Message = string.Empty;
            }
            catch (Exception e)
            {

                result.IsError = true;
                result.Message = string.Format("\nError getting Users. {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");

            }
            finally
            {
                if (reader != null)
                {
                    reader.Dispose();
                    reader = null;
                }
            }

            #endregion
            return result;
        }

        public void Initialize(Dictionary<string, string> fetcherOptions)
        {
            _options = fetcherOptions;
        }

        private List<PeopleDirectoryUser> Read(System.Xml.XmlDocument xmlDoc)
        {
            List<PeopleDirectoryUser> aadusers = new List<PeopleDirectoryUser>();

            try
            {
                List<KeyValuePair<string, string>> properties = null;

                foreach (System.Xml.XmlElement userNode in xmlDoc.SelectNodes("//User"))
                {
                    properties = new List<KeyValuePair<string, string>>();

                    foreach (System.Xml.XmlAttribute userPropAttribute in userNode.Attributes)
                    {
                        properties.Add(new KeyValuePair<string, string>(userPropAttribute.Name, userPropAttribute.Value));
                    }

                    aadusers.Add(new PeopleDirectoryUser(properties.ToArray()));
                }
            }
            catch (Exception ex)
            {
                aadusers.Clear();
                //TraceEvents.Log.Error(string.Format("Error detail: {0}", ex.InnerException.Message));
            }

            return aadusers;
        }
    }
}

IPeopleDirectoryUserFetcher

Extending the IPeopleDirectoryUserFetcher interface is required for the custom data source to interact with the People Directory Sync. It requires the following methods

        void Initialize(Dictionary<string, string> fetcherOptions);
        PeopleDirectoryFetchResult FetchUsers();

FetchUsers()

Here we fetch users from our custom data source and add them to a List list object.

Initialize(Dictionary<string, string> fetcherOptions)

Any additional options for the User Synchronization are set here.

Read(System.Xml.XmlDocument xmlDoc)

As this current example is retrieving user data from an xml file, we've created the Read helper method to parse the xml information and return it within a List list object.

Walkthrough

We will use the code snippets reviewed above to sync the John Doe user to our Akumina Foundation People Directory control. The following example will be done with a locally hosted instance of Interchange. The same steps can be followed for Azure Hosted Interchange by accessing your files through an FTP manager.

Creating your Users XML file

Copy and paste the xml snippet from the section above into an xml document. Save it as export.xml. Open your Hosted Interchange files. Copy your export.xml file and paste it inside of the SiteDefinitions folder within your Hosted Interchange files. image 2

Creating your Custom People Fetcher dll

Create a new blank solution called CustomPeopleFetcher within Visual Studio. Within your new solution, add a new C# Class Library project called CustomPeopleFetcher. Within the project add a new C# class called CustomPeopleFetcher.cs and paste the c# code snippet from the section above. Ensure your project has the references highlighted below.

image 3

Save and build your solution. Open your solution in File Explorer and Navigate to your Debug folder at ...\CustomPeopleFetcher\CustomPeopleFetcher\bin\Debug. You will see your CustomPeopleFetcher.dll file.

Open your Hosted AppManager files, either in File Explorer if you are locally hosting or in an FTP manager if you are hosting on Azure. Within your Hosted Interchange files, navigate to the bin folder. Paste your CustomPeopleFetcher.dll within. image 4

Creating a temp folder

Within the root of your Hosted AppManager files create a folder called temp image 5

Altering your interchange.settings.config

Locate your interchange.settings.config file within the root of your Hosted AppManager files. Edit it within a text editor. Insert the following key between the <appSettings></appSettings> tags.

<add key="akumina:tempuploadpath" value="C:\akumina\3.4.1703.1423-InterChange\temp" />

Change the value attribute to point to the temp file you just created.

Synchronizing your Custom User Definition

Within AppManager, go to the People Directory Sync app inside the Management App tab. Under Select Data Source, select CustomPeopleFetcher. Click Synchronize. image 6 image 7

Result

Once the People Directory Sync has finished syncing users navigate to the Directory.aspx page on your Akumina Foundation Site. Refresh the Cache and the page. You should see the profile for your custom user John Doe. image 8

Download

You can download the code referenced in this article here

Additional Articles

⚠️ **GitHub.com Fallback** ⚠️