Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Credential Tagging Implementation #170

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a05de31
Upgrade back-end dependencies
markashleybell Jun 14, 2024
4a2f218
Add ADS workspace
markashleybell Jun 14, 2024
6dc7984
DatabaseType is now an enum
markashleybell Jun 14, 2024
51024e1
Initial SQLite schema
markashleybell Jun 14, 2024
4709709
We no longer return UserID for every single credential in the summary…
markashleybell Jun 14, 2024
fe2ec21
WIP: Very basic initial implementation of tagging
markashleybell Jun 14, 2024
bfd5d93
Stop annoying UI jump when adding/removing tags
markashleybell Jun 14, 2024
a3b5300
Update mab-dom dependency, pull up Jest to latest minor
markashleybell Jun 17, 2024
3a20f26
Move tag index SQL into SqlStatements
markashleybell Jun 17, 2024
3d3399a
Formatting
markashleybell Jun 17, 2024
d7f0a92
Upgrade StyleCop, minor formatting tweaks
markashleybell Jun 17, 2024
5eed0fa
WIP: Basic tag association on insert/update working, no index refresh…
markashleybell Jun 17, 2024
74c0f2f
Remove unused parameter from loadTagIndex
markashleybell Jun 22, 2024
284907f
Remove console.log
markashleybell Jun 22, 2024
d4a9de1
Fix tag removal
markashleybell Jun 22, 2024
43e5c2b
Refresh the tag index after an addition/update
markashleybell Jun 22, 2024
c991ebb
Fix tag ordering
markashleybell Jun 22, 2024
9a25708
Display tags in credential detail modal
markashleybell Jun 22, 2024
1bd22f2
Tweak so tag input placeholder isn't lower-cased
markashleybell Jun 22, 2024
ad18438
Remove debug logging
markashleybell Jun 22, 2024
026a9ee
Remove unnecessary casts
markashleybell Jun 22, 2024
4cb2a7f
Move tag search logic to Vault.searchCredentials, update tests
markashleybell Jun 22, 2024
c1e12ba
Basic test for tag search
markashleybell Jun 22, 2024
e9783c1
Update database schemas
markashleybell Jun 22, 2024
b32efa9
Unignore release scripts
markashleybell Jun 22, 2024
c7d3694
Fix display bug (JS is weird)
markashleybell Jun 22, 2024
8b3d34d
Tool to manually generate tag INSERT statements
markashleybell Jun 22, 2024
51b0940
Rename SQL release script
markashleybell Jul 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -349,3 +349,6 @@ Vault/wwwroot/js/dist/

# Development settings
appsettings.Development.json

# Database releases
!db/releases
6 changes: 3 additions & 3 deletions Vault.ruleset
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Vault" ToolsVersion="16.0">
<Rules AnalyzerId="Microsoft.CodeAnalysis.NetAnalyzers" RuleNamespace="Microsoft.CodeAnalysis.NetAnalyzers">
<Rule Id="CA1014" Action="None" />
<RuleSet Name="Vault" ToolsVersion="17.0">
<Rules AnalyzerId="Microsoft.CodeAnalysis.CSharp.Features" RuleNamespace="Microsoft.CodeAnalysis.CSharp.Features">
<Rule Id="IDE0290" Action="None" />
</Rules>
<Rules AnalyzerId="Microsoft.CodeQuality.Analyzers" RuleNamespace="Microsoft.CodeQuality.Analyzers">
<Rule Id="CA2007" Action="None" />
Expand Down
46 changes: 43 additions & 3 deletions Vault/Controllers/CredentialsController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Dapper;
using Microsoft.AspNetCore.Mvc;
Expand All @@ -14,12 +16,45 @@ public class CredentialsController : Controller
public CredentialsController(IConnectionFactory cf) =>
_db = new SqlExecutor(cf);

public async Task<ActionResult> ReadTagIndex(string userId) =>
await _db.ResultAsJson(async conn => {
var reader = await conn.QueryMultipleAsync(SqlStatements.TagIndex, new { UserID = userId });

var tags = await reader.ReadAsync<(string TagID, string Label)>();
var index = await reader.ReadAsync<(string TagID, string CredentialID)>();

return new {
tags = tags.Select(t => new {
t.TagID,
t.Label,
}),
index = index
.GroupBy(i => i.TagID)
.ToDictionary(g => g.Key, g => g.Select(i => i.CredentialID))
};
});

[HttpPost]
public async Task<ActionResult> Create([FromBody] Credential model) =>
await _db.ResultAsJson(conn => conn.ExecuteAsync(SqlStatements.Insert, model.WithNewID()));
await _db.ResultAsJson(async conn => {
var c = model.WithNewID();
var a = await conn.ExecuteAsync(SqlStatements.Insert, c);
var b = await conn.ExecuteAsync(SqlStatements.TagsToCredential, c.TagArray);
return a + b;
});

public async Task<ActionResult> Read(string id) =>
await _db.ResultAsJson(conn => conn.QuerySingleOrDefaultAsync<Credential>(SqlStatements.SelectSingle, new { CredentialID = id }));
await _db.ResultAsJson(async conn => {
var reader = await conn.QueryMultipleAsync(SqlStatements.SelectSingle, new { CredentialID = id });

var credential = await reader.ReadSingleAsync<Credential>();
var tags = await reader.ReadAsync<(string TagID, string Label)>();

credential.Tags = string.Join('|', tags.Select(t => t.TagID));
credential.TagDisplay = string.Join('|', tags.Select(t => t.Label));

return credential;
});

public async Task<ActionResult> ReadAll(string userId) =>
await _db.ResultAsJson(conn => conn.QueryAsync<Credential>(SqlStatements.Select, new { UserID = userId }));
Expand All @@ -29,7 +64,12 @@ public async Task<ActionResult> ReadSummaries(string userId) =>

[HttpPost]
public async Task<ActionResult> Update([FromBody] Credential model) =>
await _db.ResultAsJson(conn => conn.ExecuteAsync(SqlStatements.Update, model));
await _db.ResultAsJson(async conn => {
var a = await conn.ExecuteAsync(SqlStatements.Update, model);
var b = await conn.ExecuteAsync(SqlStatements.DeleteTagsFromCredential, model);
var c = await conn.ExecuteAsync(SqlStatements.TagsToCredential, model.TagArray);
return a + b + c;
});

[HttpPost]
public async Task<ActionResult> Import([FromBody] ImportViewModel model) =>
Expand Down
11 changes: 11 additions & 0 deletions Vault/Models/Credential.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using System.Linq;

namespace Vault.Models
{
Expand All @@ -19,6 +20,7 @@ public Credential()
UserDefined2 = "{{UserDefined2}}";
Notes = "{{Notes}}";
PwdOptions = "{{PwdOptions}}";
Tags = "{{Tags}}";
}

public string CredentialID { get; set; }
Expand Down Expand Up @@ -50,6 +52,15 @@ public Credential()

public string PwdOptions { get; set; }

public string Tags { get; set; }

public string TagDisplay { get; set; }

public object[] TagArray =>
Tags?
.Split('|', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(t => new { TagID = t, CredentialID }).ToArray() ?? [];

public Credential WithNewID()
{
var credentialWithGuid = (Credential)MemberwiseClone();
Expand Down
2 changes: 0 additions & 2 deletions Vault/Models/CredentialSummary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ public class CredentialSummary
{
public string CredentialID { get; set; }

public string UserID { get; set; }

public string Description { get; set; }

public string Username { get; set; }
Expand Down
13 changes: 13 additions & 0 deletions Vault/Models/DatabaseType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Vault.Models
{
#pragma warning disable SA1602 // Enumeration items should be documented
public enum DatabaseType
{
Unknown,

SQLite,

SqlServer
}
#pragma warning restore SA1602 // Enumeration items should be documented
}
2 changes: 1 addition & 1 deletion Vault/Models/LoginResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public LoginResult(string userID) =>
UserID = userID;

public static LoginResult Failed =>
new (null);
new(null);

public string UserID { get; }

Expand Down
5 changes: 4 additions & 1 deletion Vault/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Serialization;
using Vault.Models;
using Vault.Support;

namespace Vault
Expand All @@ -32,9 +33,11 @@ public void ConfigureServices(IServiceCollection services)

services.AddMvc(options => options.Filters.Add<ProtectWithSecurityKeyFilter>());

SqlStatements.DatabaseType = Configuration["DbType"] == "SQLite" ? DatabaseType.SQLite : DatabaseType.SqlServer;

var connectionString = Configuration.GetConnectionString("Main");

var connectionFactory = Configuration["DbType"] == "SQLite"
var connectionFactory = SqlStatements.DatabaseType == DatabaseType.SQLite
? new Func<IServiceProvider, IConnectionFactory>(_ => new SQLiteConnectionFactory(connectionString))
: _ => new SqlConnectionFactory(connectionString);

Expand Down
4 changes: 2 additions & 2 deletions Vault/Support/InlineJsGlobalSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Vault.Support
public static class InlineJsGlobalSerializer
{
private static readonly JsonSerializerSettings _settings =
new () {
new() {
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new DefaultContractResolver {
NamingStrategy = new CamelCaseNamingStrategy()
Expand Down Expand Up @@ -40,7 +40,7 @@ public static string AsJson(this object o)
}

private static JsonTextWriter GetJsonWriter(StringWriter sw) =>
new (sw) {
new(sw) {
Formatting = Formatting.Indented,
IndentChar = ' ',
Indentation = 4,
Expand Down
137 changes: 105 additions & 32 deletions Vault/Support/SqlStatements.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
namespace Vault.Support
using System;
using Vault.Models;

namespace Vault.Support
{
public static class SqlStatements
{
public const string SelectSummary =
@"SELECT
CredentialID,
UserID,
Description,
Username,
Password,
Expand All @@ -19,38 +21,60 @@ public static class SqlStatements
"SELECT * FROM Credentials WHERE UserID = @UserID";

public const string SelectSingle =
"SELECT * FROM Credentials WHERE CredentialID = @CredentialID";
"""
SELECT
*
FROM
Credentials
WHERE
CredentialID = @CredentialID;

SELECT
tc.TagID,
t.Label
FROM
Tags_Credentials tc
INNER JOIN
Tags t
ON t.TagID = tc.TagID
WHERE
tc.CredentialID = @CredentialID
ORDER BY
t.Label;
""";

public const string Insert =
@"INSERT INTO
Credentials (
CredentialID,
UserID,
Description,
Username,
Password,
Url,
UserDefined1Label,
UserDefined1,
UserDefined2Label,
UserDefined2,
Notes,
PwdOptions
)
VALUES (
@CredentialID,
@UserID,
@Description,
@Username,
@Password,
@Url,
@UserDefined1Label,
@UserDefined1,
@UserDefined2Label,
@UserDefined2,
@Notes,
@PwdOptions
)";
"""
INSERT INTO
Credentials (
CredentialID,
UserID,
Description,
Username,
Password,
Url,
UserDefined1Label,
UserDefined1,
UserDefined2Label,
UserDefined2,
Notes,
PwdOptions
)
VALUES (
@CredentialID,
@UserID,
@Description,
@Username,
@Password,
@Url,
@UserDefined1Label,
@UserDefined1,
@UserDefined2Label,
@UserDefined2,
@Notes,
@PwdOptions
);
""";

public const string Update =
@"UPDATE
Expand All @@ -77,5 +101,54 @@ public static class SqlStatements

public const string Login =
"SELECT UserID FROM Users WHERE Username = @Username AND Password = @Password";

public const string TagIndex =
"""
SELECT
TagID,
Label
FROM
Tags
WHERE
UserID = @UserID
ORDER BY
Label;

SELECT
tc.TagID,
tc.CredentialID
FROM
Tags_Credentials tc
INNER JOIN
Tags t
ON t.TagID = tc.TagID
WHERE
t.UserID = @UserID
ORDER BY
t.Label;
""";

public const string DeleteTagsFromCredential =
"""
DELETE FROM
Tags_Credentials
WHERE
CredentialID = @CredentialID;
""";

public const string TagsToCredential =
"""
INSERT INTO
Tags_Credentials (
TagID,
CredentialID
)
VALUES (
@TagID,
@CredentialID
);
""";

public static DatabaseType DatabaseType { get; internal set; }
}
}
10 changes: 5 additions & 5 deletions Vault/Vault.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.28" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.2" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.1.5" />
<PackageReference Include="Microsoft.TypeScript.MSBuild" Version="5.3.3">
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.6" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.1" />
<PackageReference Include="Microsoft.TypeScript.MSBuild" Version="5.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="17.8.8" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
Expand Down
2 changes: 1 addition & 1 deletion Vault/Views/Home/GenerateVaultCredential.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@

@section foot {

<script src="~/js/dist/GenerateVaultCredential.min.js" asp-append-version="true" integrity="sha512-9OWfKRWszrMsJVs9BfTvW0UVWrtwFoMza9yBfydxO2nKWBc8egYdmqIb1R+qk5c/fhKqb8RU69Ix4V24vSrZwg=="></script>
<script src="~/js/dist/GenerateVaultCredential.min.js" asp-append-version="true" integrity="sha512-23UXvk9rGJ+cQqYRdNSJ1OGFQg0i2IlfETQAiPiRJY8STjomBunAKlPzh82vMdxAsVHhuyFKBTYRXROxZd8kDg=="></script>

<div class="modal-backdrop show"></div>

Expand Down
2 changes: 1 addition & 1 deletion Vault/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@
var _VAULT_GLOBALS = @Html.Raw(Model.AsJson());
</script>

<script src="~/js/dist/Index.min.js" asp-append-version="true" integrity="sha512-UEtyhazndztA2yrv+IH6Z/dqZelvww/TTBVcCmgIO1EUzJey4fh7b1gskCFJDepKUp7cY4iCCFvqi1JxXI345A=="></script>
<script src="~/js/dist/Index.min.js" asp-append-version="true" integrity="sha512-JRoo5LPc8JUVUptWJbAqIZpbVwt7xeoW9Sy687sV+XFzIveba9Tcli48CvpWjD+qjzQFw9+OdboKeo9AU18MAg=="></script>

}
Loading