Skip to content

Commit 7fefe5e

Browse files
Add auditing for package (un)deprecate actions (#7118)
* Add auditing for package (un)deprecate actions * Register DeprecatedByUser data * Fix unit tests * PR feedback + unit test
1 parent ea46070 commit 7fefe5e

13 files changed

Lines changed: 152 additions & 15 deletions
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using NuGet.Services.Entities;
5+
using NuGetGallery.Auditing.Obfuscation;
6+
using System;
7+
8+
namespace NuGetGallery.Auditing.AuditedEntities
9+
{
10+
public class AuditedPackageDeprecation
11+
{
12+
public int Key { get; private set; }
13+
public int PackageKey { get; private set; }
14+
public int Status { get; private set; }
15+
public int? AlternatePackageRegistrationKey { get; private set; }
16+
public int? AlternatePackageKey { get; private set; }
17+
[Obfuscate(ObfuscationType.UserKey)]
18+
public int? DeprecatedByUserKey { get; private set; }
19+
public DateTime DeprecatedOn { get; private set; }
20+
public string CustomMessage { get; private set; }
21+
22+
public static AuditedPackageDeprecation CreateFrom(PackageDeprecation packageDeprecation)
23+
{
24+
return new AuditedPackageDeprecation
25+
{
26+
Key = packageDeprecation.Key,
27+
PackageKey = packageDeprecation.PackageKey,
28+
Status = (int)packageDeprecation.Status,
29+
AlternatePackageRegistrationKey = packageDeprecation.AlternatePackageRegistrationKey,
30+
AlternatePackageKey = packageDeprecation.AlternatePackageKey,
31+
DeprecatedByUserKey = packageDeprecation.DeprecatedByUserKey,
32+
DeprecatedOn = packageDeprecation.DeprecatedOn,
33+
CustomMessage = packageDeprecation.CustomMessage
34+
};
35+
}
36+
}
37+
}

src/NuGetGallery.Core/Auditing/AuditedPackageAction.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public enum AuditedPackageAction
1717
UndoEdit,
1818
Verify,
1919
SymbolsCreate,
20-
SymbolsDelete
20+
SymbolsDelete,
21+
Deprecate,
22+
Undeprecate
2123
}
2224
}

src/NuGetGallery.Core/Auditing/PackageAuditReasons.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,20 @@ public static class PackageDeletedVia
2828
/// </summary>
2929
public const string Web = "Deleted via web.";
3030
}
31+
32+
public static class PackageDeprecatedVia
33+
{
34+
/// <summary>
35+
/// Package has been deprecated via NuGet web interface (browser)
36+
/// </summary>
37+
public const string Web = "Deprecated via web.";
38+
}
39+
40+
public static class PackageUndeprecatedVia
41+
{
42+
/// <summary>
43+
/// Package has been undeprecated via NuGet web interface (browser)
44+
/// </summary>
45+
public const string Web = "Undeprecated via web.";
46+
}
3147
}

src/NuGetGallery.Core/Auditing/PackageAuditRecord.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using NuGet.Services.Entities;
55
using NuGetGallery.Auditing.AuditedEntities;
6+
using System.Linq;
67

78
namespace NuGetGallery.Auditing
89
{
@@ -14,12 +15,15 @@ public class PackageAuditRecord : AuditRecord<AuditedPackageAction>
1415

1516
public AuditedPackage PackageRecord { get; }
1617
public AuditedPackageRegistration RegistrationRecord { get; }
18+
public AuditedPackageDeprecation DeprecationRecord { get; }
1719

1820
public string Reason { get; }
1921

2022
public PackageAuditRecord(
2123
string id, string version, string hash,
22-
AuditedPackage packageRecord, AuditedPackageRegistration registrationRecord,
24+
AuditedPackage packageRecord,
25+
AuditedPackageRegistration registrationRecord,
26+
AuditedPackageDeprecation deprecationRecord,
2327
AuditedPackageAction action, string reason)
2428
: base(action)
2529
{
@@ -28,6 +32,7 @@ public PackageAuditRecord(
2832
Hash = hash;
2933
PackageRecord = packageRecord;
3034
RegistrationRecord = registrationRecord;
35+
DeprecationRecord = deprecationRecord;
3136
Reason = reason;
3237
}
3338

@@ -37,6 +42,7 @@ public PackageAuditRecord(string id, string version, AuditedPackageAction action
3742
hash: "",
3843
packageRecord: null,
3944
registrationRecord: null,
45+
deprecationRecord: null,
4046
action: action,
4147
reason: reason)
4248
{ }
@@ -47,11 +53,15 @@ public PackageAuditRecord(Package package, AuditedPackageAction action, string r
4753
package.Hash,
4854
packageRecord: null,
4955
registrationRecord: null,
56+
deprecationRecord: null,
5057
action: action,
5158
reason: reason)
5259
{
5360
PackageRecord = AuditedPackage.CreateFrom(package);
5461
RegistrationRecord = AuditedPackageRegistration.CreateFrom(package.PackageRegistration);
62+
DeprecationRecord = package.Deprecations
63+
.Select(d => AuditedPackageDeprecation.CreateFrom(d))
64+
.SingleOrDefault();
5565
}
5666

5767
public PackageAuditRecord(Package package, AuditedPackageAction action)
@@ -60,11 +70,15 @@ public PackageAuditRecord(Package package, AuditedPackageAction action)
6070
package.Hash,
6171
packageRecord: null,
6272
registrationRecord: null,
73+
deprecationRecord: null,
6374
action: action,
6475
reason: null)
6576
{
6677
PackageRecord = AuditedPackage.CreateFrom(package);
6778
RegistrationRecord = AuditedPackageRegistration.CreateFrom(package.PackageRegistration);
79+
DeprecationRecord = package.Deprecations
80+
.Select(d => AuditedPackageDeprecation.CreateFrom(d))
81+
.SingleOrDefault();
6882
}
6983

7084
public override string GetPath()

src/NuGetGallery.Core/NuGetGallery.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
<Compile Include="Auditing\AggregateAuditingService.cs" />
6565
<Compile Include="Auditing\AuditedCertificateAction.cs" />
6666
<Compile Include="Auditing\AuditedDeleteAccountAction.cs" />
67+
<Compile Include="Auditing\AuditedEntities\AuditedPackageDeprecation.cs" />
6768
<Compile Include="Auditing\CertificateAuditRecord.cs" />
6869
<Compile Include="Auditing\Obfuscation\ObfuscateAttribute.cs" />
6970
<Compile Include="Auditing\Obfuscation\ObfuscationType.cs" />

src/NuGetGallery/Controllers/ManageDeprecationJsonApiController.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,26 @@
99
using System.Web.Mvc;
1010
using NuGet.Services.Entities;
1111
using NuGet.Versioning;
12+
using NuGetGallery.Auditing;
1213
using NuGetGallery.Filters;
1314

1415
namespace NuGetGallery
1516
{
1617
public partial class ManageDeprecationJsonApiController
1718
: AppController
1819
{
20+
private readonly IAuditingService _auditingService;
1921
private readonly IPackageService _packageService;
2022
private readonly IPackageDeprecationService _deprecationService;
2123
private readonly IFeatureFlagService _featureFlagService;
2224

2325
public ManageDeprecationJsonApiController(
26+
IAuditingService auditingService,
2427
IPackageService packageService,
2528
IPackageDeprecationService deprecationService,
2629
IFeatureFlagService featureFlagService)
2730
{
31+
_auditingService = auditingService ?? throw new ArgumentNullException(nameof(auditingService));
2832
_packageService = packageService ?? throw new ArgumentNullException(nameof(packageService));
2933
_deprecationService = deprecationService ?? throw new ArgumentNullException(nameof(deprecationService));
3034
_featureFlagService = featureFlagService ?? throw new ArgumentNullException(nameof(featureFlagService));
@@ -162,7 +166,18 @@ await _deprecationService.UpdateDeprecation(
162166
status,
163167
alternatePackageRegistration,
164168
alternatePackage,
165-
customMessage);
169+
customMessage,
170+
currentUser);
171+
172+
foreach (var packageToUpdate in packagesToUpdate)
173+
{
174+
await _auditingService.SaveAuditRecordAsync(
175+
new PackageAuditRecord(
176+
packageToUpdate,
177+
status == PackageDeprecationStatus.NotDeprecated ? AuditedPackageAction.Undeprecate : AuditedPackageAction.Deprecate,
178+
status == PackageDeprecationStatus.NotDeprecated ? PackageUndeprecatedVia.Web : PackageDeprecatedVia.Web));
179+
180+
}
166181

167182
return Json(HttpStatusCode.OK);
168183
}

src/NuGetGallery/Services/IPackageDeprecationService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ Task UpdateDeprecation(
2121
PackageDeprecationStatus status,
2222
PackageRegistration alternatePackageRegistration,
2323
Package alternatePackage,
24-
string customMessage);
24+
string customMessage,
25+
User user);
2526

2627
PackageDeprecation GetDeprecationByPackage(Package package);
2728
}

src/NuGetGallery/Services/PackageDeleteService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ public async Task ReflowHardDeletedPackageAsync(string id, string version)
414414
hash: string.Empty,
415415
packageRecord: null,
416416
registrationRecord: null,
417+
deprecationRecord: null,
417418
action: AuditedPackageAction.Delete,
418419
reason: "reflow hard-deleted package");
419420

src/NuGetGallery/Services/PackageDeprecationService.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,19 @@ public async Task UpdateDeprecation(
2525
PackageDeprecationStatus status,
2626
PackageRegistration alternatePackageRegistration,
2727
Package alternatePackage,
28-
string customMessage)
28+
string customMessage,
29+
User user)
2930
{
3031
if (packages == null || !packages.Any())
3132
{
3233
throw new ArgumentException(nameof(packages));
3334
}
3435

36+
if (user == null)
37+
{
38+
throw new ArgumentNullException(nameof(user));
39+
}
40+
3541
var shouldDelete = status == PackageDeprecationStatus.NotDeprecated;
3642
var deprecations = new List<PackageDeprecation>();
3743
foreach (var package in packages)
@@ -59,6 +65,7 @@ public async Task UpdateDeprecation(
5965
}
6066

6167
deprecation.Status = status;
68+
deprecation.DeprecatedByUser = user;
6269

6370
deprecation.AlternatePackageRegistration = alternatePackageRegistration;
6471
deprecation.AlternatePackage = alternatePackage;

tests/NuGetGallery.Core.Facts/Auditing/AuditedPackageActionTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ public void Definition_HasNotChanged()
2121
"UndoEdit",
2222
"Verify",
2323
"SymbolsCreate",
24-
"SymbolsDelete"
24+
"SymbolsDelete",
25+
"Deprecate",
26+
"Undeprecate"
2527
};
2628

2729
Verify(typeof(AuditedPackageAction), expectedNames);

0 commit comments

Comments
 (0)