2121using NuGetGallery . AsyncFileUpload ;
2222using NuGetGallery . Auditing ;
2323using NuGetGallery . Configuration ;
24+ using NuGetGallery . Diagnostics ;
2425using NuGetGallery . Filters ;
2526using NuGetGallery . Helpers ;
2627using NuGetGallery . Infrastructure . Lucene ;
@@ -88,6 +89,7 @@ public partial class PackagesController
8889 private readonly IPackageOwnershipManagementService _packageOwnershipManagementService ;
8990 private readonly IContentObjectService _contentObjectService ;
9091 private readonly ISymbolPackageUploadService _symbolPackageUploadService ;
92+ private readonly IDiagnosticsSource _trace ;
9193
9294 public PackagesController (
9395 IPackageService packageService ,
@@ -111,7 +113,8 @@ public PackagesController(
111113 IValidationService validationService ,
112114 IPackageOwnershipManagementService packageOwnershipManagementService ,
113115 IContentObjectService contentObjectService ,
114- ISymbolPackageUploadService symbolPackageUploadService )
116+ ISymbolPackageUploadService symbolPackageUploadService ,
117+ IDiagnosticsService diagnosticsService )
115118 {
116119 _packageService = packageService ;
117120 _uploadFileService = uploadFileService ;
@@ -135,6 +138,7 @@ public PackagesController(
135138 _packageOwnershipManagementService = packageOwnershipManagementService ;
136139 _contentObjectService = contentObjectService ;
137140 _symbolPackageUploadService = symbolPackageUploadService ;
141+ _trace = diagnosticsService ? . SafeGetSource ( nameof ( PackagesController ) ) ?? throw new ArgumentNullException ( nameof ( diagnosticsService ) ) ;
138142 }
139143
140144 [ HttpGet ]
@@ -220,7 +224,7 @@ private async Task<ActionResult> UploadSymbolsPackageInternal(SubmitPackageReque
220224 var existingPackageRegistration = packageForUploadingSymbols . PackageRegistration ;
221225
222226 IEnumerable < User > accountsAllowedOnBehalfOf = Enumerable . Empty < User > ( ) ;
223- bool isAllowed = ActionsRequiringPermissions . UploadNewPackageVersion . CheckPermissionsOnBehalfOfAnyAccount ( currentUser , existingPackageRegistration , out accountsAllowedOnBehalfOf ) == PermissionsCheckResult . Allowed ;
227+ bool isAllowed = ActionsRequiringPermissions . UploadSymbolPackage . CheckPermissionsOnBehalfOfAnyAccount ( currentUser , existingPackageRegistration , out accountsAllowedOnBehalfOf ) == PermissionsCheckResult . Allowed ;
224228 if ( ! isAllowed )
225229 {
226230 accountsAllowedOnBehalfOf = new [ ] { currentUser } ;
@@ -363,7 +367,7 @@ private async Task<JsonResult> UploadSymbolsPackageInternal(PackageArchiveReader
363367
364368 // Evaluate the permissions for user on behalf of any account possible, since the user
365369 // could change the ownership before submitting the package.
366- if ( ActionsRequiringPermissions . UploadNewPackageVersion . CheckPermissionsOnBehalfOfAnyAccount (
370+ if ( ActionsRequiringPermissions . UploadSymbolPackage . CheckPermissionsOnBehalfOfAnyAccount (
367371 currentUser , existingPackageRegistration , out accountsAllowedOnBehalfOf ) != PermissionsCheckResult . Allowed )
368372 {
369373 return Json ( HttpStatusCode . Conflict , new [ ] { string . Format ( CultureInfo . CurrentCulture , Strings . PackageIdNotAvailable , existingPackageRegistration . Id ) } ) ;
@@ -1161,6 +1165,40 @@ public virtual ActionResult Delete(string id, string version)
11611165 return View ( model ) ;
11621166 }
11631167
1168+ [ HttpGet ]
1169+ [ UIAuthorize ]
1170+ [ RequiresAccountConfirmation ( "delete a symbols package" ) ]
1171+ public virtual ActionResult DeleteSymbols ( string id , string version )
1172+ {
1173+ var package = _packageService . FindPackageByIdAndVersion ( id , version ) ;
1174+ if ( package == null )
1175+ {
1176+ return HttpNotFound ( ) ;
1177+ }
1178+
1179+ var currentUser = GetCurrentUser ( ) ;
1180+ if ( ActionsRequiringPermissions . DeleteSymbolPackage . CheckPermissionsOnBehalfOfAnyAccount ( currentUser , package ) != PermissionsCheckResult . Allowed )
1181+ {
1182+ return HttpForbidden ( ) ;
1183+ }
1184+
1185+ var model = new DeletePackageViewModel ( package , currentUser , DeleteReasons ) ;
1186+
1187+ model . VersionSelectList = new SelectList (
1188+ model
1189+ . PackageVersions
1190+ . Where ( p => ! p . Deleted
1191+ && p . LatestSymbolsPackage != null
1192+ && p . LatestSymbolsPackage . StatusKey == PackageStatus . Available )
1193+ . Select ( p => new
1194+ {
1195+ text = p . NuGetVersion . ToFullString ( ) + ( p . LatestVersionSemVer2 ? " (Latest)" : string . Empty ) ,
1196+ url = Url . DeleteSymbolsPackage ( p )
1197+ } ) , "url" , "text" , Url . DeleteSymbolsPackage ( model ) ) ;
1198+
1199+ return View ( model ) ;
1200+ }
1201+
11641202 [ UIAuthorize ( Roles = "Admins" ) ]
11651203 [ RequiresAccountConfirmation ( "reflow a package" ) ]
11661204 public virtual async Task < ActionResult > Reflow ( string id , string version )
@@ -1278,6 +1316,67 @@ await _packageDeleteService.HardDeletePackagesAsync(
12781316 return Delete ( firstPackage . PackageRegistration . Id , firstPackage . Version ) ;
12791317 }
12801318
1319+ [ UIAuthorize ]
1320+ [ HttpPost ]
1321+ [ RequiresAccountConfirmation ( "delete a symbols package" ) ]
1322+ [ ValidateAntiForgeryToken ]
1323+ public virtual async Task < ActionResult > DeleteSymbolsPackage ( string id , string version )
1324+ {
1325+ var package = _packageService . FindPackageByIdAndVersionStrict ( id , version ) ;
1326+ if ( package == null )
1327+ {
1328+ return new HttpStatusCodeResult ( HttpStatusCode . NotFound ,
1329+ string . Format ( Strings . PackageWithIdAndVersionNotFound , id , version ) ) ;
1330+ }
1331+
1332+ if ( ActionsRequiringPermissions . DeleteSymbolPackage . CheckPermissionsOnBehalfOfAnyAccount ( GetCurrentUser ( ) , package )
1333+ != PermissionsCheckResult . Allowed )
1334+ {
1335+ return new HttpStatusCodeResult ( HttpStatusCode . Forbidden , Strings . SymbolsPackage_UploadNotAllowed ) ;
1336+ }
1337+
1338+ if ( package . PackageRegistration . IsLocked )
1339+ {
1340+ return new HttpStatusCodeResult ( HttpStatusCode . Forbidden ,
1341+ string . Format ( CultureInfo . CurrentCulture , Strings . PackageIsLocked , package . PackageRegistration . Id ) ) ;
1342+ }
1343+
1344+ // Get all available symbol packages for a given package, ideally this should
1345+ // always return one symbol package. For thoroughness we can cleanup the data
1346+ // for any inconsistencies.
1347+ var availableSymbolPackages = package
1348+ . SymbolPackages
1349+ . Where ( sp => sp . StatusKey == PackageStatus . Available ) ;
1350+
1351+ if ( availableSymbolPackages . Count ( ) > 1 )
1352+ {
1353+ _trace . Warning ( $ "Multiple({ availableSymbolPackages . Count ( ) } ) available symbol packages found for { package . Id } , { package . Version } ") ;
1354+ }
1355+
1356+ if ( availableSymbolPackages . Any ( ) )
1357+ {
1358+ foreach ( var symbolPackage in availableSymbolPackages )
1359+ {
1360+ await _symbolPackageUploadService . DeleteSymbolsPackageAsync ( symbolPackage ) ;
1361+ }
1362+
1363+ TempData [ "Message" ] = Strings . SymbolsPackage_Deleted ;
1364+
1365+ await _auditingService . SaveAuditRecordAsync (
1366+ new PackageAuditRecord ( package , AuditedPackageAction . SymbolsDelete , PackageDeletedVia . Web ) ) ;
1367+
1368+ _telemetryService . TrackSymbolPackageDeleteEvent ( package . Id , package . Version ) ;
1369+
1370+ // Redirect to the package details page
1371+ return Redirect ( Url . Package ( package , relativeUrl : true ) ) ;
1372+ }
1373+ else
1374+ {
1375+ return new HttpStatusCodeResult ( HttpStatusCode . BadRequest ,
1376+ string . Format ( Strings . SymbolsPackage_PackageNotAvailable , id , version ) ) ;
1377+ }
1378+ }
1379+
12811380 [ UIAuthorize ]
12821381 [ HttpPost ]
12831382 [ RequiresAccountConfirmation ( "unlist a package" ) ]
@@ -1697,7 +1796,7 @@ public virtual async Task<JsonResult> VerifySymbolsPackageInternal(
16971796
16981797 // Evaluate the permissions for the owner, the permissions for uploading a symbols should be same as that of
16991798 // uploading a new version of a given package.
1700- var checkPermissionsOfUploadNewVersion = ActionsRequiringPermissions . UploadNewPackageVersion . CheckPermissions ( currentUser , owner , existingPackageRegistration ) ;
1799+ var checkPermissionsOfUploadNewVersion = ActionsRequiringPermissions . UploadSymbolPackage . CheckPermissions ( currentUser , owner , existingPackageRegistration ) ;
17011800 if ( checkPermissionsOfUploadNewVersion != PermissionsCheckResult . Allowed )
17021801 {
17031802 if ( checkPermissionsOfUploadNewVersion == PermissionsCheckResult . AccountFailure )
0 commit comments