Skip to content

Commit c71e124

Browse files
authored
Merge pull request #8514 from NuGet/dev
[ReleasePrep][2021.04.08]RI dev into main
2 parents be38792 + 3fcfd71 commit c71e124

36 files changed

Lines changed: 707 additions & 259 deletions

src/Bootstrap/dist/css/bootstrap-theme.css

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
.page-add-organization {
2-
.owner-image {
3-
margin-top: 6px;
4-
margin-bottom: 6px;
5-
}
6-
}
2+
.owner-image {
3+
margin-top: 6px;
4+
margin-bottom: 6px;
5+
}
6+
7+
.required:after {
8+
color: red;
9+
content: " *";
10+
}
11+
}

src/Bootstrap/package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/DatabaseMigrationTools/DatabaseMigrationTools.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
<PrivateAssets>all</PrivateAssets>
6666
</PackageReference>
6767
<PackageReference Include="NuGet.Services.Validation">
68-
<Version>2.84.0</Version>
68+
<Version>2.86.0</Version>
6969
</PackageReference>
7070
</ItemGroup>
7171
<ItemGroup>

src/GitHubVulnerabilities2Db/GitHubVulnerabilities2Db.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
<Version>4.3.0-dev-3612825</Version>
9090
</PackageReference>
9191
<PackageReference Include="NuGet.Services.Cursor">
92-
<Version>2.84.0</Version>
92+
<Version>2.86.0</Version>
9393
</PackageReference>
9494
</ItemGroup>
9595
<ItemGroup>

src/NuGet.Services.Entities/Package.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace NuGet.Services.Entities
1212
public class Package
1313
: IPackageEntity
1414
{
15+
private string _id;
1516

1617
#pragma warning disable 618 // TODO: remove Package.Authors completely once production services definitely no longer need it
1718
public Package()
@@ -264,7 +265,17 @@ public bool HasEmbeddedReadme
264265

265266
public virtual ICollection<SymbolPackage> SymbolPackages { get; set; }
266267

267-
public string Id => PackageRegistration.Id;
268+
/// <summary>
269+
/// The package ID with casing specific to this version if available, otherwise it will fallback to the ID on
270+
/// the package registration. WARNING: this property should not be used for comparisons in LINQ to SQL because
271+
/// it may be null sometimes. Use <see cref="PackageRegistration.Id"/> instead.
272+
/// </summary>
273+
[StringLength(Constants.MaxPackageIdLength)]
274+
public string Id
275+
{
276+
get => _id ?? PackageRegistration?.Id;
277+
set => _id = value;
278+
}
268279

269280
public EmbeddedLicenseFileType EmbeddedLicenseType { get; set; }
270281

src/NuGetGallery.Core/Auditing/CloudAuditingService.cs

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,17 @@ public class CloudAuditingService : AuditingService, ICloudStorageStatusDependen
2121
{
2222
public static readonly string DefaultContainerName = "auditing";
2323

24-
private CloudBlobContainer _auditContainer;
24+
private Func<ICloudBlobContainer> _auditContainerFactory;
2525
private Func<Task<AuditActor>> _getOnBehalfOf;
2626

27-
public CloudAuditingService(string storageConnectionString, bool readAccessGeoRedundant, Func<Task<AuditActor>> getOnBehalfOf)
28-
: this(GetContainer(storageConnectionString, readAccessGeoRedundant), getOnBehalfOf)
27+
public CloudAuditingService(Func<ICloudBlobClient> cloudBlobClientFactory, Func<Task<AuditActor>> getOnBehalfOf)
28+
: this(() => GetContainer(cloudBlobClientFactory), getOnBehalfOf)
2929
{
3030
}
3131

32-
public CloudAuditingService(CloudBlobContainer auditContainer, Func<Task<AuditActor>> getOnBehalfOf)
32+
public CloudAuditingService(Func<ICloudBlobContainer> auditContainerFactory, Func<Task<AuditActor>> getOnBehalfOf)
3333
{
34-
_auditContainer = auditContainer;
34+
_auditContainerFactory = auditContainerFactory;
3535
_getOnBehalfOf = getOnBehalfOf;
3636
}
3737

@@ -52,7 +52,8 @@ protected override async Task SaveAuditRecordAsync(string auditData, string reso
5252
$"{filePath.Replace(Path.DirectorySeparatorChar, '/')}/" +
5353
$"{Guid.NewGuid().ToString("N")}-{action.ToLowerInvariant()}.audit.v1.json";
5454

55-
var blob = _auditContainer.GetBlockBlobReference(fullPath);
55+
var container = _auditContainerFactory();
56+
var blob = container.GetBlobReference(fullPath);
5657
bool retry = false;
5758
try
5859
{
@@ -74,37 +75,23 @@ protected override async Task SaveAuditRecordAsync(string auditData, string reso
7475
{
7576
// Create the container and try again,
7677
// this time we let exceptions bubble out
77-
await Task.Factory.FromAsync(
78-
(cb, s) => _auditContainer.BeginCreateIfNotExists(cb, s),
79-
ar => _auditContainer.EndCreateIfNotExists(ar),
80-
null);
78+
await container.CreateIfNotExistAsync(permissions: null);
8179
await WriteBlob(auditData, fullPath, blob);
8280
}
8381
}
8482

85-
private static CloudBlobContainer GetContainer(string storageConnectionString, bool readAccessGeoRedundant)
83+
private static ICloudBlobContainer GetContainer(Func<ICloudBlobClient> cloudBlobClientFactory)
8684
{
87-
var cloudBlobClient = CloudStorageAccount.Parse(storageConnectionString).CreateCloudBlobClient();
88-
if (readAccessGeoRedundant)
89-
{
90-
cloudBlobClient.DefaultRequestOptions.LocationMode = LocationMode.PrimaryThenSecondary;
91-
}
85+
var cloudBlobClient = cloudBlobClientFactory();
9286
return cloudBlobClient.GetContainerReference(DefaultContainerName);
9387
}
9488

95-
private static async Task WriteBlob(string auditData, string fullPath, CloudBlockBlob blob)
89+
private static async Task WriteBlob(string auditData, string fullPath, ISimpleCloudBlob blob)
9690
{
9791
try
9892
{
99-
var strm = await Task.Factory.FromAsync(
100-
(cb, s) => blob.BeginOpenWrite(
101-
AccessCondition.GenerateIfNoneMatchCondition("*"),
102-
new BlobRequestOptions(),
103-
new OperationContext(),
104-
cb, s),
105-
ar => blob.EndOpenWrite(ar),
106-
null);
107-
using (var writer = new StreamWriter(strm))
93+
using (var stream = await blob.OpenWriteAsync(AccessCondition.GenerateIfNoneMatchCondition("*")))
94+
using (var writer = new StreamWriter(stream))
10895
{
10996
await writer.WriteAsync(auditData);
11097
}
@@ -125,7 +112,7 @@ private static async Task WriteBlob(string auditData, string fullPath, CloudBloc
125112

126113
public Task<bool> IsAvailableAsync(BlobRequestOptions options, OperationContext operationContext)
127114
{
128-
return _auditContainer.ExistsAsync(options, operationContext);
115+
return _auditContainerFactory().ExistsAsync(options, operationContext);
129116
}
130117

131118
public override string RenderAuditEntry(AuditEntry entry)

src/NuGetGallery.Core/Infrastructure/AzureEntityList.cs

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,25 @@ namespace NuGetGallery.Infrastructure
2222
private const string IndexPartitionKey = "INDEX";
2323
private const string IndexRowKey = "0";
2424

25-
private CloudTable _tableRef;
25+
private readonly string _tableName;
26+
private readonly bool _readAccessGeoRedundant;
27+
private readonly Func<string> _connectionStringFactory;
2628

27-
public AzureEntityList(string connStr, string tableName, bool readAccessGeoRedundant)
29+
public AzureEntityList(Func<string> connectionStringFactory, string tableName, bool readAccessGeoRedundant)
2830
{
29-
var tableClient = CloudStorageAccount.Parse(connStr).CreateCloudTableClient();
30-
if (readAccessGeoRedundant)
31-
{
32-
tableClient.DefaultRequestOptions.LocationMode = LocationMode.PrimaryThenSecondary;
33-
}
34-
_tableRef = tableClient.GetTableReference(tableName);
31+
_tableName = tableName ?? throw new ArgumentNullException(nameof(tableName));
32+
_readAccessGeoRedundant = readAccessGeoRedundant;
33+
_connectionStringFactory = connectionStringFactory ?? throw new ArgumentNullException(nameof(connectionStringFactory));
3534

35+
var tableRef = GetTableReference();
3636
// Create the actual Azure Table, if it doesn't yet exist.
37-
bool newTable = _tableRef.CreateIfNotExists();
37+
bool newTable = tableRef.CreateIfNotExists();
3838

3939
// Create the Index if it doesn't yet exist.
4040
bool needsIndex = newTable;
4141
if (!newTable)
4242
{
43-
var indexResult = _tableRef.Execute(
43+
var indexResult = tableRef.Execute(
4444
TableOperation.Retrieve<Index>(IndexPartitionKey, IndexRowKey));
4545

4646
needsIndex = (indexResult.HttpStatusCode == 404);
@@ -49,7 +49,7 @@ public AzureEntityList(string connStr, string tableName, bool readAccessGeoRedun
4949
if (needsIndex)
5050
{
5151
// Create the index
52-
var result = _tableRef.Execute(
52+
var result = tableRef.Execute(
5353
TableOperation.Insert(new Index
5454
{
5555
Count = 0,
@@ -102,7 +102,8 @@ public T this[long index]
102102
string partitionKey = FormatPartitionKey(page);
103103
string rowKey = FormatRowKey(row);
104104

105-
var response = _tableRef.Execute(TableOperation.Retrieve<T>(partitionKey, rowKey));
105+
var tableRef = GetTableReference();
106+
var response = tableRef.Execute(TableOperation.Retrieve<T>(partitionKey, rowKey));
106107
if (response.HttpStatusCode == 404)
107108
{
108109
throw new ArgumentOutOfRangeException(nameof(index), index, CoreStrings.Http404NotFound);
@@ -129,8 +130,10 @@ public T this[long index]
129130
value.PartitionKey = FormatPartitionKey(page);
130131
value.RowKey = FormatRowKey(row);
131132

133+
var tableRef = GetTableReference();
134+
132135
// Just do an unconditional update - if you wanted any *real* benefit of atomic update then you would need a more complex method signature that calls you back when optimistic updates fail ETAG checks!
133-
_tableRef.Execute(TableOperation.Replace(value));
136+
tableRef.Execute(TableOperation.Replace(value));
134137
}
135138
}
136139

@@ -161,13 +164,14 @@ public long Add(T entity)
161164
/// </summary>
162165
public IEnumerator<T> GetEnumerator()
163166
{
167+
var tableRef = GetTableReference();
164168
for (long page = 0;; page++)
165169
{
166170
string partitionKey = FormatPartitionKey(page);
167171
var chunkQuery = new TableQuery<T>().Where(
168172
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey));
169173

170-
var chunk = _tableRef.ExecuteQuery(chunkQuery).ToArray();
174+
var chunk = tableRef.ExecuteQuery(chunkQuery).ToArray();
171175

172176
foreach (var item in chunk)
173177
{
@@ -191,6 +195,7 @@ public IEnumerable<T> GetRange(long pos, int n)
191195
int done = 0;
192196
long page = pos / 1000;
193197
long offset = pos % 1000;
198+
var tableRef = GetTableReference();
194199
while (done < n)
195200
{
196201
string partitionKey = FormatPartitionKey(page);
@@ -201,7 +206,7 @@ public IEnumerable<T> GetRange(long pos, int n)
201206
TableOperators.And,
202207
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThanOrEqual, rowKey)));
203208

204-
var chunk = _tableRef.ExecuteQuery(chunkQuery).ToArray();
209+
var chunk = tableRef.ExecuteQuery(chunkQuery).ToArray();
205210
if (chunk.Length == 0)
206211
{
207212
break; // Reached the end of the list
@@ -235,9 +240,10 @@ private long AtomicIncrementCount()
235240
// 2) use ETAG to do a conditional +1 update
236241
// 3) retry if that optimistic concurrency attempt failed
237242
long pos = -1; // To avoid compiler warnings, grr - should never be returned
243+
var tableRef = GetTableReference();
238244
DoReplaceWithRetry(() =>
239245
{
240-
var result1 = _tableRef.Execute(
246+
var result1 = tableRef.Execute(
241247
TableOperation.Retrieve<Index>(IndexPartitionKey, IndexRowKey));
242248

243249
ThrowIfErrorStatus(result1);
@@ -260,6 +266,7 @@ private long AtomicIncrementCount()
260266
private void InsertIfNotExistsWithRetry<T2>(Func<T2> valueGenerator) where T2 : ITableEntity
261267
{
262268
TableResult storeResult;
269+
var tableRef = GetTableReference();
263270
do
264271
{
265272
var entity = valueGenerator();
@@ -268,7 +275,7 @@ private void InsertIfNotExistsWithRetry<T2>(Func<T2> valueGenerator) where T2 :
268275
// - the dummy MERGES with existing data instead of overwriting it, so no data loss.
269276
// 2) Use its ETAG to conditionally replace the item
270277
// 3) return true if success, false to allow retry on failure
271-
var dummyResult = _tableRef.Execute(
278+
var dummyResult = tableRef.Execute(
272279
TableOperation.InsertOrMerge(new HazardEntry
273280
{
274281
PartitionKey = entity.PartitionKey,
@@ -281,7 +288,7 @@ private void InsertIfNotExistsWithRetry<T2>(Func<T2> valueGenerator) where T2 :
281288
}
282289

283290
entity.ETag = dummyResult.Etag;
284-
storeResult = _tableRef.Execute(TableOperation.Replace(entity));
291+
storeResult = tableRef.Execute(TableOperation.Replace(entity));
285292
}
286293
while (storeResult.HttpStatusCode == 412);
287294
ThrowIfErrorStatus(storeResult);
@@ -290,17 +297,19 @@ private void InsertIfNotExistsWithRetry<T2>(Func<T2> valueGenerator) where T2 :
290297
private void DoReplaceWithRetry<T2>(Func<T2> valueGenerator) where T2 : ITableEntity
291298
{
292299
TableResult storeResult;
300+
var tableRef = GetTableReference();
293301
do
294302
{
295-
storeResult = _tableRef.Execute(TableOperation.Replace(valueGenerator.Invoke()));
303+
storeResult = tableRef.Execute(TableOperation.Replace(valueGenerator.Invoke()));
296304
}
297305
while (storeResult.HttpStatusCode == 412);
298306
ThrowIfErrorStatus(storeResult);
299307
}
300308

301309
private Index ReadIndex()
302310
{
303-
var response = _tableRef.Execute(TableOperation.Retrieve<Index>(IndexPartitionKey, IndexRowKey));
311+
var tableRef = GetTableReference();
312+
var response = tableRef.Execute(TableOperation.Retrieve<Index>(IndexPartitionKey, IndexRowKey));
304313
return (Index)response.Result;
305314
}
306315

@@ -333,6 +342,16 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
333342
return GetEnumerator();
334343
}
335344

345+
private CloudTable GetTableReference()
346+
{
347+
var tableClient = CloudStorageAccount.Parse(_connectionStringFactory()).CreateCloudTableClient();
348+
if (_readAccessGeoRedundant)
349+
{
350+
tableClient.DefaultRequestOptions.LocationMode = LocationMode.PrimaryThenSecondary;
351+
}
352+
return tableClient.GetTableReference(_tableName);
353+
}
354+
336355
class HazardEntry : ITableEntity
337356
{
338357
private const string PlaceHolderPropertyName = "Place_Held";

src/NuGetGallery.Core/Infrastructure/TableErrorLog.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,11 @@ public class TableErrorLog : ErrorLog
141141
{
142142
public const string TableName = "ElmahErrors";
143143

144-
private readonly string _connectionString;
145144
private readonly AzureEntityList<ErrorEntity> _entityList;
146145

147-
public TableErrorLog(string connectionString, bool readAccessGeoRedundant)
146+
public TableErrorLog(Func<string> connectionStringFactory, bool readAccessGeoRedundant)
148147
{
149-
_connectionString = connectionString;
150-
_entityList = new AzureEntityList<ErrorEntity>(connectionString, TableName, readAccessGeoRedundant);
148+
_entityList = new AzureEntityList<ErrorEntity>(connectionStringFactory, TableName, readAccessGeoRedundant);
151149
}
152150

153151
public override ErrorLogEntry GetError(string id)

src/NuGetGallery.Core/NuGetGallery.Core.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
<Version>5.9.0</Version>
4848
</PackageReference>
4949
<PackageReference Include="NuGet.Services.FeatureFlags">
50-
<Version>2.84.0</Version>
50+
<Version>2.86.0</Version>
5151
</PackageReference>
5252
<PackageReference Include="WindowsAzure.Storage">
5353
<Version>9.3.3</Version>
@@ -56,13 +56,13 @@
5656

5757
<ItemGroup Condition="'$(TargetFramework)' == 'net472'">
5858
<PackageReference Include="NuGet.Services.Messaging.Email">
59-
<Version>2.84.0</Version>
59+
<Version>2.86.0</Version>
6060
</PackageReference>
6161
<PackageReference Include="NuGet.Services.Validation">
62-
<Version>2.84.0</Version>
62+
<Version>2.86.0</Version>
6363
</PackageReference>
6464
<PackageReference Include="NuGet.Services.Validation.Issues">
65-
<Version>2.84.0</Version>
65+
<Version>2.86.0</Version>
6666
</PackageReference>
6767
<PackageReference Include="NuGet.StrongName.elmah.corelibrary">
6868
<Version>1.2.2</Version>

0 commit comments

Comments
 (0)