Module: Data protection
9 of 13 Pages
Understand the Identity collectors
Data protection laws such as the European Union’s GDPR often specify that visitors to a site must be able to see their personal data that has been collected, and they can request that it be removed. Identity collection is a key part of this process.
Let’s create an identity collector for gathering Contacts. Data protection laws such as the European Union’s GDPR often specify that visitors to a site must be able to see their personal data that has been collected, and they can request that it be removed. Identity collection is a key part of this process.
Let’s create an identity collector for gathering Contacts.
You can read more about GDPR compliance in the Xperience by Kentico Documentation.
Understand the components
In the Configuration → Data Protection application in Xperience by Kentico, you’ll notice tabs for Data portability, Right to access, and Right to be forgotten.
These correspond to aspects of the GDPR but are applicable to other regulations as well, and each is used for dealing with visitors’ personal data.
The Data portability tab, once implemented, allows administrators to gather a visitor’s data in a machine-readable format. In contrast, the Right to access tab collects data in a human-readable format. Finally, the Right to be forgotten tab allows a visitor’s data to be wiped from the site.
However, the code that carries out these actions needs to be implemented, as there is no one-size-fits-all solution to the virtually limitless ways a site could collect and store personal information. The code samples from this series cover just one example site with its own specific requirements. However, the code that carries out these actions needs to be implemented, as there is no one-size-fits-all solution to the virtually limitless ways a site could collect and store personal information. The code samples from this series cover just one example site with its own specific requirements.
Identify the first step
Data collection and erasure require an Identity collector as the first step.
Identity collectors are used to gather a collection of Xperience objects representing the visitor, called Identities. For example, real-world people could be represented by a User object, one or more Contact objects, or any custom objects, such as Customer, Author, Contractor, etc.
Once the identity collector gathers these identities, it passes them to other components. These components can use these identities to find objects that reference them, e.g. activities performed by a contact.
We will cover the creation of an identity collector, the first step of this process. We will cover the creation of an identity collector, the first step of this process.
Note: The system uses identifiers, such as an email address, to find Identity objects. It is critical that any data you collect and store always contains one of the following, so that it can be found.
- a reference to one of the identity objects
- the identifier itself
Consider an example where you use an email address as the identifier and create a form that collects the first and last name of a visitor but no email address. In such a case, there would be no way to find that information using a supplied email address, and GDPR compliance would be impossible when a visitor exercises their right to be forgotten.
Implement the identity collector
This code sample will assume the site collects only contacts as identities — it does not account for visitors saved as users, members, or custom objects.
Create a Collectors folder in ~/Features/DataProtection of the TrainingGuides.Web project.
Add a ContactIdentityCollector.cs file to the folder, and add a namespace matching the folder structure (
TrainingGuides.Web.Features.DataProtection.Collectors
).Copy the example identity collector from the documentation, and add it to the same namespace.
Add a constant to replace the hard-coded
“email”
string, as it occurs more than once.Define additional logic that creates a new contact with the supplied email address if the query finds none.
It is possible for form data containing an email address to exist even if there is no contact in the database with that email. Creating this dummy contact allows the Data collector, which will be covered in the next part of this series, to find form data associated with the provided email address in such a case.
using CMS.ContactManagement;
using CMS.DataEngine;
using CMS.DataProtection;
namespace TrainingGuides.Web.Features.DataProtection.Collectors;
public class ContactIdentityCollector : IIdentityCollector
{
private const string EMAIL_KEY = "email";
private readonly IInfoProvider<ContactInfo> contactInfoProvider;
public ContactIdentityCollector(IInfoProvider<ContactInfo> contactInfoProvider)
{
this.contactInfoProvider = contactInfoProvider;
}
public void Collect(IDictionary<string, object> dataSubjectFilter, List<BaseInfo> identities)
{
string? email = dataSubjectFilter.ContainsKey(EMAIL_KEY)
? dataSubjectFilter[EMAIL_KEY] as string
: string.Empty;
if (string.IsNullOrWhiteSpace(email))
{
return;
}
var contacts = contactInfoProvider
.Get()
.WhereEquals(nameof(ContactInfo.ContactEmail), email)
.ToList();
if (contacts.Count() == 0)
{
contacts.Add(new ContactInfo() { ContactEmail = email });
}
identities.AddRange(contacts);
}
}
Register the Identity collector
Now that the Identity collector is in place, it can be registered.
- Create a new
DataProtectionRegistrationModule
class in ~/Features/DataProtection/Shared folder of the TrainingGuides.Web project. - Inherit from Xperience’s
Module
class, and overrideOnInit
to addContactIdentityCollector
to theIdentityCollectorRegister
. - Resolve an info provider for contacts, and pass it to the collector to fill the parameter we set earllier
- Register the module using assembly attribute.
using CMS;
using CMS.ContactManagement;
using CMS.Core;
using CMS.DataEngine;
using CMS.DataProtection;
using TrainingGuides.Web.Features.DataProtection.Collectors;
using TrainingGuides.Web.Features.DataProtection.Shared;
[assembly: RegisterModule(
type: typeof(DataProtectionRegistrationModule))]
namespace TrainingGuides.Web.Features.DataProtection.Shared;
public class DataProtectionRegistrationModule : Module
{
public DataProtectionRegistrationModule()
: base("DataProtectionRegistration")
{
}
// Contains initialization code that is executed when the application starts
protected override void OnInit(ModuleInitParameters parameters)
{
var contactInfoProvider = parameters.Services.GetRequiredService<IInfoProvider<ContactInfo>>();
base.OnInit(parameters);
// Adds the ContactIdentityCollector to the collection of registered identity collectors
IdentityCollectorRegister.Instance.Add(new ContactIdentityCollector(contactInfoProvider));
}
}
Now, Xperience will know how to utilize the ContactIdentityCollector
class for data portability, collection, and erasure requests. When you implement a Data collector, covered later on in this series, Xperience will use the identity collector class to gather a list of contacts and pass them to the data collector to retrieve personal data associated with them. Now, Xperience will know how to utilize the ContactIdentityCollector
class for data portability, collection, and erasure requests. When you implement a Data collector, covered later on in this series, Xperience will use the identity collector class to gather a list of contacts and pass them to the data collector to retrieve personal data associated with them.
The IdentityCollectorRegister
, like the other data protection registers, is a queue that can contain multiple collectors. If the same class is registered to this queue more than once, it will be called multiple times.
What’s next?
The following guide in this series will cover the process of creating a Data collector and some utility classes to help it run smoothly.