private void HandlePushNotificationRecords(GDPRContentContext context, MobileContactPart part)
 {
     foreach (var pnRecord in part.MobileRecord)
     {
         pnRecord.UUIdentifier = pnRecord.UUIdentifier.GenerateUniqueString();
         _pushNotificationRepository.Update(pnRecord);
     }
 }
Beispiel #2
0
 private void HandleSmsRecords(GDPRContentContext context, SmsContactPart part)
 {
     foreach (var smsRecord in part.SmsRecord)
     {
         // Clear the phone number
         smsRecord.Sms = smsRecord.Sms.GenerateUniqueString();
         _smsRecordRepository.Update(smsRecord);
     }
 }
Beispiel #3
0
        // We cannot replace neither the email address nor the mobile phone number with default
        // strings. This is because the drivers will verify that those are unique when editing
        // the contacts. Any update there would then fail.
        // Thus we will hash a combination of the personal information and the UTC DateTime of the
        // anonymization/erasure. This should ensure that the resulting strings are unique. Since
        // the DateTime of the process may be logged somewhere, to prevent bruteforce discovery of
        // the original string (which would be comparatively simple in the case of the phone number)
        // rather than using a contant key, we generate a new one each time.

        private void HandleEmailRecords(GDPRContentContext context, EmailContactPart part)
        {
            foreach (var emailRecord in part.EmailRecord)
            {
                // Clear the email address
                emailRecord.Email = emailRecord.Email.GenerateUniqueString();
                _emailRecordRepository.Update(emailRecord);
            }
        }
 public bool ProcessIsAllowed(GDPRContentContext context)
 {
     if (context.GDPRPart == null)
     {
         // do nothing if the item is not configured for GDPR processing
         return(false);
     }
     // do nothing for protected items
     return(!context.GDPRPart.IsProtected);
 }
        private void HandleMobilePushPart(GDPRContentContext context, MobilePushPart mpPart)
        {
            // clear the RecipientsList in all versions of the content.
            var partVersions = context.AllVersions // all the versions of the ContentItem being processed
                               .Select(civ => civ
                                       .Parts
                                       .FirstOrDefault(pa => pa is MobilePushPart))
                               .Where(pa => pa != null)
                               .Cast <MobilePushPart>();

            foreach (var part in partVersions)
            {
                part.RecipientList = string.Empty;
            }
        }
        private void HandlePart(GDPRContentContext context, SmsGatewayPart smsGatewayPart)
        {
            // clear the RecipientsList in all versions of the content.
            var partVersions = context.AllVersions // all the versions of the ContentItem
                               .Select(civ => civ
                                       .Parts
                                       .FirstOrDefault(pa => pa is SmsGatewayPart))
                               .Where(pa => pa != null)
                               .Cast <SmsGatewayPart>();

            foreach (var part in partVersions)
            {
                part.RecipientList = string.Empty;
            }
        }
Beispiel #7
0
        private void HandlerPart(GDPRContentContext context, UserPwdRecoveryPart part)
        {
            // clear the phone number from all versions
            var partVersions = context.AllVersions
                               .Select(civ => civ
                                       .Parts
                                       .FirstOrDefault(pa => pa is UserPwdRecoveryPart))
                               .Where(pa => pa != null)
                               .Cast <UserPwdRecoveryPart>();

            foreach (var pv in partVersions)
            {
                pv.PhoneNumber = string.Empty;
            }
        }
        private void HandleProviders(GDPRContentContext context, UserProvidersPart userProvidersPart)
        {
            // fetch the records directly, because the part does not contain them (rather, it contains
            // some "derived" objects)
            var providerRecords = _userProviderRepository
                                  .Fetch(x => x.UserId == context.ContentItem.Id);

            foreach (var record in providerRecords)
            {
                // ProviderUserId is the identifier for the user in the provider
                record.ProviderUserId = string.Empty;
                // ProviderUserData contains any additional information related to the user. This usually
                // is personal identifiable information.
                record.ProviderUserData = string.Empty;
            }
        }
        private void HandleLatestUUID(GDPRContentContext context, UserPart part)
        {
            // the record may not exist
            var userRecord = part.Record;

            if (userRecord != null)   // sanity check
            {
                var latestRecord = _latestUUIDForUserRepository
                                   .Fetch(luu => luu.UserPartRecord == userRecord)
                                   .FirstOrDefault();
                if (latestRecord != null)
                {
                    // we had recorded the UUID, so now we clear it
                    latestRecord.UUID = latestRecord.UUID.GenerateUniqueString();
                    _latestUUIDForUserRepository.Update(latestRecord);
                }
            }
        }
        private void HandleUser(GDPRContentContext context, UserPart userPart)
        {
            // Given the user, we should process every MobilePushPart ever, including
            // eventually deleted ones. We should check whether in its RecipientList there
            // is either the username or the email of the current user, and remove it if
            // that is the case.
            var comparisonArray = new string[] {
                userPart.UserName?.Trim(),
                userPart.Email?.Trim()
            }.Where(str => !string.IsNullOrWhiteSpace(str));

            if (comparisonArray.Any())   // sanity check
            {
                var mpParts = _contentManager.Query <MobilePushPart>(VersionOptions.AllVersions)
                              .Where <MobilePushPartRecord>(mppr => // this predicate replaces
                                                            mppr.RecipientList != null && // !string.IsNullOrWhiteSpace(str)
                                                            mppr.RecipientList != "")
                              .List()         // here the IContentQuery ends and the IEnumerable begins
                              .Where(mpp => { // only those that may contain either username or email
                    foreach (var compare in comparisonArray)
                    {
                        if (mpp.RecipientList
                            .Contains(compare, StringComparison.OrdinalIgnoreCase))
                        {
                            return(true);
                        }
                    }
                    return(false);
                });

                foreach (var mpPart in mpParts)
                {
                    // RecipientList is a string of usernames or email addresses separated by
                    // a new line.
                    var split = mpPart.RecipientList
                                .Split(new string[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
                    mpPart.RecipientList = string.Join(Environment.NewLine,
                                                       split.Select(str => str.Trim()) // get rid of spare whitespace
                                                       .Except(comparisonArray, StringComparer.OrdinalIgnoreCase));
                }
            }
        }
        private void HandleContact(GDPRContentContext context, SmsContactPart smsContactPart)
        {
            // Get all the phone numbers we'll have to process
            var numbers = smsContactPart.SmsRecord
                          .Select(csr => new PhoneNumber(csr))
                          .Where(pn => !string.IsNullOrWhiteSpace(pn.Number)); // sanity check

            if (numbers.Any())                                                 // sanity check
            {
                var sgParts = _contentManager.Query <SmsGatewayPart>(VersionOptions.AllVersions)
                              .Where <SmsGatewayPartRecord>(sgpr => // this predicate replaces
                                                            sgpr.RecipientList != null && //!string.IsNullOrWhitespace
                                                            sgpr.RecipientList != "")
                              .List() // here IContentQuery ends and IEnumerable begins
                              .Where(sgp => {
                    foreach (var pn in numbers)
                    {
                        if (sgp.RecipientList
                            .Contains(pn.Number, StringComparison.OrdinalIgnoreCase))
                        {
                            return(true);
                        }
                    }
                    return(false);
                });

                // Each phone number in the RecipientLists should be prefix+number, but we check
                // also for the case where it is just number
                var comparisonArray = numbers.Select(pn => pn.Number).ToList();
                comparisonArray.AddRange(numbers.Select(pn => pn.FullNumber));

                foreach (var sgPart in sgParts)
                {
                    // RecipientList is a string of phone numbers separated by newline.
                    var split = sgPart.RecipientList
                                .Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                    sgPart.RecipientList = string.Join(Environment.NewLine,
                                                       split.Select(str => str.Trim())
                                                       .Except(comparisonArray, StringComparer.OrdinalIgnoreCase));
                }
            }
        }
Beispiel #12
0
        /// <summary>
        /// These operations should all happen before the Anonymized/Erased event is raised. Otherwise
        /// we may end up deleting the item in a Workflow there, and preventing all other handlers
        /// to run as they should.
        /// </summary>
        /// <param name="context"></param>
        private void PostProcessing(GDPRContentContext context)
        {
            var updateCtx = new UpdateContentContext(context.ContentItem);

            ContentHandlers.Invoke(handler => handler.Updated(updateCtx), Logger);

            // Re-publish the published version of the ContentItem, if it exists.
            // This way, all its handlers are launched again, synchronizing information as needed.
            // For example, this is sufficient to propagate anonymization onto the Alias, when
            // AutoroutePart is subject to anonymization/erasure, and onto the FieldIndexRecords
            // for fields that we processed above.
            var publishedVersion = context.AllVersions
                                   .FirstOrDefault(v => v.VersionRecord.Published);

            if (publishedVersion != null)
            {
                var civr = publishedVersion.Record.Versions.FirstOrDefault(v => v.Published);
                civr.Published = false;
                _contentManager.Publish(publishedVersion);
            }
        }
        private void HandleDeviceRecords(GDPRContentContext context, UserPart part)
        {
            var userRecord = part.Record;

            if (userRecord != null)   // sanity check
            {
                var deviceRecords = _userDeviceRepository
                                    .Fetch(ud => ud.UserPartRecord == userRecord)
                                    .ToList();
                foreach (var deviceRecord in deviceRecords)
                {
                    // clear this UUID
                    deviceRecord.UUIdentifier = deviceRecord.UUIdentifier.GenerateUniqueString();
                    _userDeviceRepository.Update(deviceRecord);
                    // These records we are processing here will be deleted elsewhere if
                    // the user is deleted. However, here we cannot know if the user is going
                    // to be deleted, and we cannot assume it will be. For this reason we
                    // are putting the unique string there.
                }
            }
        }
Beispiel #14
0
 public void Anonymize(ContentItem contentItem, GDPRContentContext previousContext)
 {
     Anonymize(new AnonymizeContentContext(contentItem, previousContext));
 }
Beispiel #15
0
 public void Erase(ContentItem contentItem, GDPRContentContext previousContext)
 {
     Erase(new EraseContentContext(contentItem, previousContext));
 }
Beispiel #16
0
 public bool ProcessIsAllowed(GDPRContentContext context)
 {
     return(context != null &&
            ProcessIsAllowed(context.ContentItem));
 }