From 20e06839ad5aaf849d2cef7a030df79d19481196 Mon Sep 17 00:00:00 2001 From: cmanu Date: Thu, 10 Jan 2019 15:07:57 -0800 Subject: [PATCH] Not null the createdby on delete account (#6808) A support issue for a deleted account will have createdby field not null bu obfuscated. With this the issue will still be in the support issues view. Also the issue is automatically resolved. --- .../Admin/Services/SupportRequestService.cs | 8 +- .../NuGetGallery.Facts.csproj | 1 + .../Services/SupportRequestServiceFacts.cs | 3 +- .../UsernameValidationRegex.cs | 113 ++++++++++++++++++ 4 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 tests/NuGetGallery.Facts/UsernameValidationRegex.cs diff --git a/src/NuGetGallery/Areas/Admin/Services/SupportRequestService.cs b/src/NuGetGallery/Areas/Admin/Services/SupportRequestService.cs index f09098a7f6..9729eb543e 100644 --- a/src/NuGetGallery/Areas/Admin/Services/SupportRequestService.cs +++ b/src/NuGetGallery/Areas/Admin/Services/SupportRequestService.cs @@ -20,6 +20,8 @@ public class SupportRequestService private IAuditingService _auditingService; private readonly string _siteRoot; private const string _unassignedAdmin = "unassigned"; + private const string _deletedAccount = "_deletedaccount"; + private const string _NuGetDSRAccount = "_NuGetDSR"; public SupportRequestService( ISupportRequestDbContext supportRequestDbContext, @@ -302,7 +304,11 @@ public async Task DeleteSupportRequestsAsync(User user) foreach (var accountDeletedIssue in userIssues.Where(i => string.Equals(i.IssueTitle, Strings.AccountDelete_SupportRequestTitle))) { accountDeletedIssue.OwnerEmail = "deletedaccount"; - accountDeletedIssue.CreatedBy = null; + if(!accountDeletedIssue.CreatedBy.Equals(_NuGetDSRAccount, StringComparison.OrdinalIgnoreCase)) + { + accountDeletedIssue.CreatedBy = _deletedAccount; + } + accountDeletedIssue.IssueStatusId = IssueStatusKeys.Resolved; accountDeletedIssue.Details = "This support request has been redacted as the customer's account has been deleted."; foreach (var historyEntry in accountDeletedIssue.HistoryEntries) { diff --git a/tests/NuGetGallery.Facts/NuGetGallery.Facts.csproj b/tests/NuGetGallery.Facts/NuGetGallery.Facts.csproj index e65f7dc3d5..62f4a14e63 100644 --- a/tests/NuGetGallery.Facts/NuGetGallery.Facts.csproj +++ b/tests/NuGetGallery.Facts/NuGetGallery.Facts.csproj @@ -81,6 +81,7 @@ + diff --git a/tests/NuGetGallery.Facts/Services/SupportRequestServiceFacts.cs b/tests/NuGetGallery.Facts/Services/SupportRequestServiceFacts.cs index 6bf8ed4f50..5f6f5611c0 100644 --- a/tests/NuGetGallery.Facts/Services/SupportRequestServiceFacts.cs +++ b/tests/NuGetGallery.Facts/Services/SupportRequestServiceFacts.cs @@ -102,7 +102,8 @@ public async Task DeleteRequestsNormalPath() Assert.False(supportRequestContext.Issues.Any(issue => string.Equals(issue.IssueTitle, "Joe's OldIssue"))); var deleteRequestIssue = supportRequestContext.Issues.Where(issue => issue.Key == 1).FirstOrDefault(); Assert.NotNull(deleteRequestIssue); - Assert.Null(deleteRequestIssue.CreatedBy); + Assert.Equal(deleteRequestIssue.CreatedBy, "_deletedaccount"); + Assert.Equal(deleteRequestIssue.IssueStatusId, IssueStatusKeys.Resolved); Assert.Null(deleteRequestIssue.HistoryEntries.ElementAt(0).EditedBy); } diff --git a/tests/NuGetGallery.Facts/UsernameValidationRegex.cs b/tests/NuGetGallery.Facts/UsernameValidationRegex.cs new file mode 100644 index 0000000000..b1229c7241 --- /dev/null +++ b/tests/NuGetGallery.Facts/UsernameValidationRegex.cs @@ -0,0 +1,113 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Xunit; + +namespace NuGetGallery +{ + public class UsernameValidationRegex + { + private const int TestCharSetSize = 256; + + [Theory] + [MemberData(nameof(GetAllowedShortUsername))] + public void AllowedUsernames(string username) + { + var match = new Regex(GalleryConstants.UsernameValidationRegex).IsMatch(username); + Assert.True(match); + } + + [Theory] + [MemberData(nameof(GetNotAllowedSuffixPrefixCharacters))] + public void NotAllowedUsernamesPrefix(char incorrectPrefixChar) + { + string username = new string(new char[] { incorrectPrefixChar, 'a' }); + var match = new Regex(GalleryConstants.UsernameValidationRegex).IsMatch(username); + Assert.False(match); + } + + [Theory] + [MemberData(nameof(GetNotAllowedSuffixPrefixCharacters))] + public void NotAllowedUsernamesSuffix(char incorrectSuffixChar) + { + string username = new string(new char[] { 'a', incorrectSuffixChar }); + var match = new Regex(GalleryConstants.UsernameValidationRegex).IsMatch(username); + Assert.False(match); + } + + [Theory] + [MemberData(nameof(GetNotAllowedMiddleCharacters))] + public void NotAllowedUsernamesMiddle(char incorrectMiddleChar) + { + string username = new string(new char[] { 'a', incorrectMiddleChar, 'b' }); + var match = new Regex(GalleryConstants.UsernameValidationRegex).IsMatch(username); + Assert.False(match); + } + + public static IEnumerable GetNotAllowedSuffixPrefixCharacters() + { + return Enumerable.Range(0, TestCharSetSize) + .Select(i => (char)i) + .Where(c => !GetAllowedSuffixPrefixCharacters().Contains(c)) + .Select(c => new object[] { c }); + } + + public static IEnumerable GetNotAllowedMiddleCharacters() + { + return Enumerable.Range(0, TestCharSetSize) + .Select(i => (char)i) + .Where(c => !GetAllowedMiddleCharacters().Contains(c)) + .Select(c => new object[] { c }); ; + } + + public static IEnumerable GetAllowedShortUsername() + { + char[] shortAllowedPrefixSuffixList = new char[] { 'a', 'Z', '1' }; + char[] shortAllowedMiddleCharList = new char[] { '.', '_', '-' }; + + foreach (var prefix in shortAllowedPrefixSuffixList) + { + foreach (var middle in shortAllowedMiddleCharList) + { + foreach (var suffix in shortAllowedPrefixSuffixList) + { + var v = new string(new char[] { prefix, middle, suffix }); + yield return new object[] { new string(new char[] { prefix, middle, suffix }) }; + } + } + } + } + + public static IEnumerable GetAllowedSuffixPrefixCharacters() + { + foreach (var index in Enumerable.Range('a', 'z' - 'a' + 1)) + { + yield return (char)index; + } + foreach (var index in Enumerable.Range('A', 'Z' - 'A' + 1)) + { + yield return (char)index; + } + foreach (var index in Enumerable.Range(0, 10)) + { + yield return (char)('0' + index); + } + } + + public static IEnumerable GetAllowedMiddleCharacters() + { + foreach (var allowedPrefixOrSuffix in GetAllowedSuffixPrefixCharacters()) + { + yield return allowedPrefixOrSuffix; + } + foreach (var otherAllowed in new char[] {'.', '_', '-'}) + { + yield return otherAllowed; + } + + } + } +}