Skip to content

Commit

Permalink
Added PopulateCredentialsTask. Also removed Identifier column for now
Browse files Browse the repository at this point in the history
  • Loading branch information
analogrelay committed Oct 2, 2013
1 parent d92a97c commit d048af7
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 32 deletions.
3 changes: 0 additions & 3 deletions src/NuGetGallery.Core/Entities/Credential.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ public Credential(string type, string value)
[StringLength(maximumLength: 64)]
public string Type { get; set; }

[StringLength(maximumLength: 256)]
public string Identifier { get; set; }

[Required]
[StringLength(maximumLength: 256)]
public string Value { get; set; }
Expand Down
37 changes: 37 additions & 0 deletions src/NuGetGallery.Operations/Infrastructure/TableValuedParameter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using Dapper;
using Microsoft.SqlServer.Server;

namespace NuGetGallery.Operations.Infrastructure
{
public class TableValuedParameter : SqlMapper.IDynamicParameters
{
public string Name { get; private set; }
public string TableType { get; private set; }
public DataTable TableValue { get; private set; }

public TableValuedParameter(string name, string tableType, DataTable tableValue)
{
Name = name;
TableType = tableType;
TableValue = tableValue;
}

public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
{
var sqlCommand = (SqlCommand)command;
var param = new SqlParameter(Name, TableValue)
{
TypeName = TableType,
SqlDbType = SqlDbType.Structured,
Direction = ParameterDirection.Input
};
sqlCommand.Parameters.Add(param);
}
}
}
5 changes: 5 additions & 0 deletions src/NuGetGallery.Operations/NuGetGallery.Operations.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\AnglicanGeek.DbExecutor.0.1.2\lib\net40\AnglicanGeek.DbExecutor.dll</HintPath>
</Reference>
<Reference Include="Dapper">
<HintPath>..\..\packages\Dapper.1.13\lib\net45\Dapper.dll</HintPath>
</Reference>
<Reference Include="EntityFramework">
<HintPath>..\..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
</Reference>
Expand Down Expand Up @@ -151,6 +154,7 @@
<Compile Include="Infrastructure\LogLevelConverter.cs" />
<Compile Include="Infrastructure\SnazzyConsoleTarget.cs" />
<Compile Include="Infrastructure\SqlDbExecutorFactory.cs" />
<Compile Include="Infrastructure\TableValuedParameter.cs" />
<Compile Include="LoggerExtensions.cs" />
<Compile Include="Model\AuditEnvironment.cs" />
<Compile Include="Model\AuditRecord.cs" />
Expand Down Expand Up @@ -212,6 +216,7 @@
<Compile Include="Tasks\DataManagement\DeleteDuplicatePackageVersionsTask.cs" />
<Compile Include="Tasks\DataManagement\NormalizePackageFilesTask.cs" />
<Compile Include="Tasks\DataManagement\NormalizePackageVersionsTask.cs" />
<Compile Include="Tasks\DataManagement\PopulateCredentialsTask.cs" />
<Compile Include="Tasks\ExecuteAggregateStatisticsTask.cs" />
<Compile Include="Tasks\CopyExternalPackagesTask.cs" />
<Compile Include="Tasks\CreateWarehouseReportsTask.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,8 @@ FROM Packages p

DataTable output;
int count = 0;
try
WithTableType(c, "Temp_NormalizePackageVersionsInputType", "PackageKey int, NormalizedVersion nvarchar(64)", () =>
{
// Create a table-type for the query
db.Execute(@"
IF EXISTS (
SELECT *
FROM sys.types
WHERE is_table_type = 1
AND name = 'Temp_NormalizePackageVersionsInputType'
)
BEGIN
DROP TYPE Temp_NormalizePackageVersionsInputType
END
CREATE TYPE Temp_NormalizePackageVersionsInputType AS TABLE(PackageKey int, NormalizedVersion nvarchar(64))");

// Build a table to hold the new data
var updateTable = new DataTable();
updateTable.Columns.Add(new DataColumn("PackageKey", typeof(int)));
Expand All @@ -83,7 +70,7 @@ DROP TYPE Temp_NormalizePackageVersionsInputType
Log.Trace("Updating Database...");
var reader = cmd.ExecuteReader();
Log.Trace("Database Update Complete");

// Load the results into a datatable and render them
output = new DataTable();
output.Load(reader);
Expand All @@ -98,18 +85,7 @@ DROP TYPE Temp_NormalizePackageVersionsInputType
}
}
Log.Info("Updated {0} packages", count);
}
finally
{
// Clean up the type
db.Execute(@"
IF EXISTS (
SELECT *
FROM sys.types
WHERE is_table_type = 1
AND name = 'Temp_NormalizePackageVersionsInputType'
) DROP TYPE Temp_NormalizePackageVersionsInputType");
}
});
});
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using NuGetGallery.Operations.Infrastructure;

namespace NuGetGallery.Operations.Tasks.DataManagement
{
[Command("populatecredentials", "Populates the Credentials table for users who are missing data", AltName = "pc")]
public class PopulateCredentialsTask : DatabaseTask
{
private const string WhatIfQuery = "BEGIN TRAN\r\n" + Query + "\r\nROLLBACK TRAN";
private const string CommitQuery = "BEGIN TRAN\r\n" + Query + "\r\nCOMMIT TRAN";

private const string Query = @"
DECLARE @results TABLE(
Action nchar(10),
UserKey int,
Type nvarchar(64),
Value nvarchar(256)
)
MERGE INTO Credentials dest
USING @creds src
ON src.UserKey = dest.UserKey AND src.Type = dest.Type
WHEN NOT MATCHED THEN
INSERT(UserKey, Type, Value)
VALUES(src.UserKey, src.Type, src.Value)
OUTPUT
$action AS 'Action',
inserted.UserKey,
inserted.Type,
inserted.Value
INTO @results;
SELECT COUNT(*) FROM @results
";

private Dictionary<string, string> _hashAlgorithmToCredType = new Dictionary<string, string>() {
{Constants.PBKDF2HashAlgorithmId, CredentialTypes.Password.Pbkdf2},
{Constants.Sha1HashAlgorithmId, CredentialTypes.Password.Sha1}
};

public override void ExecuteCommand()
{
WithConnection(c =>
{
// Get user credentials
var users = c.Query("SELECT [Key], HashedPassword, PasswordHashAlgorithm, ApiKey FROM Users");

// Build a table
var dt = new DataTable();
dt.Columns.Add("UserKey", typeof(int));
dt.Columns.Add("Type", typeof(string));
dt.Columns.Add("Value", typeof(string));
foreach (var user in users)
{
var row = dt.NewRow();
row.SetField("UserKey", (int)user.Key);
row.SetField("Type", CredentialTypes.ApiKeyV1);
row.SetField("Value", ((Guid)user.ApiKey).ToString().ToLowerInvariant());
dt.Rows.Add(row);


string passwordCredType;
if (!_hashAlgorithmToCredType.TryGetValue(user.PasswordHashAlgorithm, out passwordCredType))
{
Log.Error("Unknown Hash Algorithm: {0}", user.PasswordHashAlgorithm);
}
else
{
row = dt.NewRow();
row.SetField("UserKey", (int)user.Key);
row.SetField("Type", passwordCredType);
row.SetField("Value", (string)user.HashedPassword);
dt.Rows.Add(row);
}
}

WithTableType(c, "Temp_PopulateCredentialsInputType", "UserKey int, Type nvarchar(64), Value nvarchar(256)", () =>
{
// Update the DB
var updatedRowCount = c.Execute(
WhatIf ? WhatIfQuery : CommitQuery,
new TableValuedParameter("@creds", "Temp_PopulateCredentialsInputType", dt));

Log.Info("Inserted {0} credential records", updatedRowCount);
});
});
}
}
}
37 changes: 37 additions & 0 deletions src/NuGetGallery.Operations/Tasks/TaskBases.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.WindowsAzure.Storage.Blob;
using NuGetGallery.Operations.Common;
using NuGetGallery.Infrastructure;
using Dapper;

namespace NuGetGallery.Operations
{
Expand Down Expand Up @@ -135,6 +136,42 @@ protected bool WithMasterConnection(Func<SqlConnection, SqlExecutor, bool> act)
}
}

protected void WithTableType(SqlConnection connection, string name, string definition, Action act)
{
try
{
// Create the table-valued parameter type
connection.Execute(String.Format(@"
IF EXISTS (
SELECT *
FROM sys.types
WHERE is_table_type = 1
AND name = '{0}'
)
BEGIN
DROP TYPE {0}
END
CREATE TYPE {0} AS TABLE ({1})", name, definition));

act();
}
finally
{
// Clean up the table-valued parameter type
connection.Execute(String.Format(@"
IF EXISTS (
SELECT *
FROM sys.types
WHERE is_table_type = 1
AND name = '{0}'
)
BEGIN
DROP TYPE {0}
END", name));
}

}

protected SqlConnection OpenConnection()
{
var c = new SqlConnection(ConnectionString.ConnectionString);
Expand Down
1 change: 1 addition & 0 deletions src/NuGetGallery.Operations/packages.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AnglicanGeek.DbExecutor" version="0.1.2" targetFramework="net45" />
<package id="Dapper" version="1.13" targetFramework="net45" />
<package id="EntityFramework" version="5.0.0" targetFramework="net45" />
<package id="Microsoft.AspNet.Razor" version="2.0.20715.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="2.0.20710.0" targetFramework="net45" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ public override void Up()
Key = c.Int(nullable: false, identity: true),
UserKey = c.Int(nullable: false),
Type = c.String(nullable: false, maxLength: 64),
Identifier = c.String(maxLength: 256),
Value = c.String(nullable: false, maxLength: 256),
})
.PrimaryKey(t => t.Key)
Expand All @@ -26,6 +25,11 @@ public override void Up()
new[] { "Type", "Value" },
unique: true,
name: "IX_Credentials_Type_Value");

Sql(@"CREATE VIEW UsersAndCredentials AS
SELECT u.Username, u.ApiKey, u.HashedPassword, c.[Type], c.Value
FROM Users u
LEFT OUTER JOIN [Credentials] c ON c.UserKey = u.[Key]");
}

public override void Down()
Expand All @@ -34,6 +38,9 @@ public override void Down()
DropIndex("dbo.Credentials", "IX_Credentials_Type_Value");
DropForeignKey("dbo.Credentials", "UserKey", "dbo.Users");
DropTable("dbo.Credentials");

Sql(@"IF EXISTS(SELECT * FROM sys.views WHERE name = 'UsersAndCredentials')
DROP VIEW UsersAndCredentials");
}
}
}
Loading

0 comments on commit d048af7

Please sign in to comment.