| | | 1 | | using LOCKnet.Core.DataAbstractions; |
| | | 2 | | using Microsoft.Data.Sqlite; |
| | | 3 | | |
| | | 4 | | namespace LOCKnet.Data.Repositories; |
| | | 5 | | |
| | | 6 | | /// <summary> |
| | | 7 | | /// SQLite-Implementierung von <see cref="ICredentialRepository"/>. |
| | | 8 | | /// </summary> |
| | | 9 | | public class CredentialsRepository : RepositoryBase, ICredentialRepository |
| | | 10 | | { |
| | | 11 | | /// <summary>Initialisiert eine neue Instanz von <see cref="CredentialsRepository"/>.</summary> |
| | | 12 | | /// <param name="connectionString">Der vollständige SQLite-Connection-String.</param> |
| | 144 | 13 | | public CredentialsRepository(string connectionString) : base(connectionString) { } |
| | | 14 | | |
| | | 15 | | /// <summary>Initialisiert eine neue Instanz von <see cref="CredentialsRepository"/>.</summary> |
| | | 16 | | /// <param name="connectionFactory">Factory fuer Storage-spezifische SQLite-Verbindungen.</param> |
| | 183 | 17 | | public CredentialsRepository(ISqliteConnectionFactory connectionFactory) : base(connectionFactory) { } |
| | | 18 | | |
| | | 19 | | #region ICredentialRepository |
| | | 20 | | |
| | | 21 | | /// <inheritdoc/> |
| | | 22 | | public void Add(CredentialRecord credential) |
| | 73 | 23 | | { |
| | 73 | 24 | | StoredCredentialGuard.ValidateForPersistence(credential); |
| | | 25 | | |
| | 70 | 26 | | using var conn = GetConnection(); |
| | 70 | 27 | | using var cmd = conn.CreateCommand(); |
| | 70 | 28 | | cmd.CommandText = @" |
| | 70 | 29 | | INSERT INTO Credentials (Title, Username, EncryptedPassword, EncryptedMetadata, CredentialUuid, SecretFormat |
| | 70 | 30 | | VALUES ($title, $username, $password, $encryptedMetadata, $credentialUuid, $secretFormatVersion, $metadataFo |
| | | 31 | | |
| | 70 | 32 | | cmd.Parameters.AddWithValue("$title", credential.Title); |
| | 70 | 33 | | cmd.Parameters.AddWithValue("$username", credential.Username ?? ""); |
| | 70 | 34 | | cmd.Parameters.AddWithValue("$password", credential.EncryptedPassword); |
| | 70 | 35 | | cmd.Parameters.AddWithValue("$encryptedMetadata", (object?)credential.EncryptedMetadata ?? DBNull.Value); |
| | 70 | 36 | | cmd.Parameters.AddWithValue("$credentialUuid", credential.CredentialUuid); |
| | 70 | 37 | | cmd.Parameters.AddWithValue("$secretFormatVersion", credential.SecretFormatVersion); |
| | 70 | 38 | | cmd.Parameters.AddWithValue("$metadataFormatVersion", credential.MetadataFormatVersion); |
| | 70 | 39 | | cmd.Parameters.AddWithValue("$url", credential.Url ?? ""); |
| | 70 | 40 | | cmd.Parameters.AddWithValue("$notes", credential.Notes ?? ""); |
| | 70 | 41 | | cmd.Parameters.AddWithValue("$iconKey", (object?)credential.IconKey ?? DBNull.Value); |
| | 70 | 42 | | cmd.Parameters.AddWithValue("$credentialType", (int)credential.CredentialType); |
| | | 43 | | |
| | 70 | 44 | | cmd.ExecuteNonQuery(); |
| | 138 | 45 | | } |
| | | 46 | | |
| | | 47 | | /// <inheritdoc/> |
| | | 48 | | public IReadOnlyList<CredentialRecord> GetAll() |
| | 90 | 49 | | { |
| | 90 | 50 | | var list = new List<CredentialRecord>(); |
| | 90 | 51 | | using var conn = GetConnection(); |
| | 90 | 52 | | using var cmd = conn.CreateCommand(); |
| | 90 | 53 | | cmd.CommandText = "SELECT Id, Title, Username, EncryptedPassword, EncryptedMetadata, CredentialUuid, SecretFormatVer |
| | | 54 | | |
| | 90 | 55 | | using var reader = cmd.ExecuteReader(); |
| | 146 | 56 | | while (reader.Read()) |
| | 56 | 57 | | list.Add(MapRecord(reader)); |
| | | 58 | | |
| | 90 | 59 | | return list; |
| | 90 | 60 | | } |
| | | 61 | | |
| | | 62 | | /// <inheritdoc/> |
| | | 63 | | public CredentialRecord? GetById(int id) |
| | 10 | 64 | | { |
| | 10 | 65 | | using var conn = GetConnection(); |
| | 10 | 66 | | using var cmd = conn.CreateCommand(); |
| | 10 | 67 | | cmd.CommandText = "SELECT Id, Title, Username, EncryptedPassword, EncryptedMetadata, CredentialUuid, SecretFormatVer |
| | 10 | 68 | | cmd.Parameters.AddWithValue("$id", id); |
| | | 69 | | |
| | 10 | 70 | | using var reader = cmd.ExecuteReader(); |
| | 10 | 71 | | return reader.Read() ? MapRecord(reader) : null; |
| | 10 | 72 | | } |
| | | 73 | | |
| | | 74 | | /// <inheritdoc/> |
| | | 75 | | public void Update(CredentialRecord credential) |
| | 6 | 76 | | { |
| | 6 | 77 | | StoredCredentialGuard.ValidateForPersistence(credential); |
| | | 78 | | |
| | 5 | 79 | | using var conn = GetConnection(); |
| | 5 | 80 | | using var cmd = conn.CreateCommand(); |
| | 5 | 81 | | cmd.CommandText = @" |
| | 5 | 82 | | UPDATE Credentials |
| | 5 | 83 | | SET Title = $title, |
| | 5 | 84 | | Username = $username, |
| | 5 | 85 | | EncryptedPassword = $password, |
| | 5 | 86 | | EncryptedMetadata = $encryptedMetadata, |
| | 5 | 87 | | CredentialUuid = $credentialUuid, |
| | 5 | 88 | | SecretFormatVersion = $secretFormatVersion, |
| | 5 | 89 | | MetadataFormatVersion = $metadataFormatVersion, |
| | 5 | 90 | | URL = $url, |
| | 5 | 91 | | Notes = $notes, |
| | 5 | 92 | | IconKey = $iconKey, |
| | 5 | 93 | | CredentialType = $credentialType, |
| | 5 | 94 | | UpdatedAt = CURRENT_TIMESTAMP |
| | 5 | 95 | | WHERE Id = $id;"; |
| | | 96 | | |
| | 5 | 97 | | cmd.Parameters.AddWithValue("$id", credential.Id); |
| | 5 | 98 | | cmd.Parameters.AddWithValue("$title", credential.Title); |
| | 5 | 99 | | cmd.Parameters.AddWithValue("$username", credential.Username ?? ""); |
| | 5 | 100 | | cmd.Parameters.AddWithValue("$password", credential.EncryptedPassword); |
| | 5 | 101 | | cmd.Parameters.AddWithValue("$encryptedMetadata", (object?)credential.EncryptedMetadata ?? DBNull.Value); |
| | 5 | 102 | | cmd.Parameters.AddWithValue("$credentialUuid", credential.CredentialUuid); |
| | 5 | 103 | | cmd.Parameters.AddWithValue("$secretFormatVersion", credential.SecretFormatVersion); |
| | 5 | 104 | | cmd.Parameters.AddWithValue("$metadataFormatVersion", credential.MetadataFormatVersion); |
| | 5 | 105 | | cmd.Parameters.AddWithValue("$url", credential.Url ?? ""); |
| | 5 | 106 | | cmd.Parameters.AddWithValue("$notes", credential.Notes ?? ""); |
| | 5 | 107 | | cmd.Parameters.AddWithValue("$iconKey", (object?)credential.IconKey ?? DBNull.Value); |
| | 5 | 108 | | cmd.Parameters.AddWithValue("$credentialType", (int)credential.CredentialType); |
| | | 109 | | |
| | 5 | 110 | | cmd.ExecuteNonQuery(); |
| | 10 | 111 | | } |
| | | 112 | | |
| | | 113 | | /// <inheritdoc/> |
| | | 114 | | public void Remove(int id) |
| | 4 | 115 | | { |
| | 4 | 116 | | using var conn = GetConnection(); |
| | 4 | 117 | | using var cmd = conn.CreateCommand(); |
| | 4 | 118 | | cmd.CommandText = "DELETE FROM Credentials WHERE Id = $id;"; |
| | 4 | 119 | | cmd.Parameters.AddWithValue("$id", id); |
| | 4 | 120 | | cmd.ExecuteNonQuery(); |
| | 8 | 121 | | } |
| | | 122 | | |
| | | 123 | | #endregion |
| | | 124 | | |
| | 64 | 125 | | private static CredentialRecord MapRecord(SqliteDataReader reader) => new() |
| | 64 | 126 | | { |
| | 64 | 127 | | Id = reader.GetInt32(0), |
| | 64 | 128 | | Title = reader.GetString(1), |
| | 64 | 129 | | Username = reader.IsDBNull(2) ? null : reader.GetString(2), |
| | 64 | 130 | | EncryptedPassword = (byte[])reader[3], |
| | 64 | 131 | | EncryptedMetadata = reader.IsDBNull(4) ? [] : (byte[])reader[4], |
| | 64 | 132 | | CredentialUuid = reader.IsDBNull(5) ? string.Empty : reader.GetString(5), |
| | 64 | 133 | | SecretFormatVersion = reader.IsDBNull(6) ? CredentialSecretFormatVersion.Legacy : reader.GetInt32(6), |
| | 64 | 134 | | MetadataFormatVersion = reader.IsDBNull(7) ? CredentialMetadataFormatVersion.Legacy : reader.GetInt32(7), |
| | 64 | 135 | | Url = reader.IsDBNull(8) ? null : reader.GetString(8), |
| | 64 | 136 | | Notes = reader.IsDBNull(9) ? null : reader.GetString(9), |
| | 64 | 137 | | CreatedAt = reader.GetDateTime(10), |
| | 64 | 138 | | UpdatedAt = reader.GetDateTime(11), |
| | 64 | 139 | | IconKey = reader.IsDBNull(12) ? null : reader.GetString(12), |
| | 64 | 140 | | CredentialType = reader.IsDBNull(13) ? CredentialType.Password : (CredentialType)reader.GetInt32(13), |
| | 64 | 141 | | }; |
| | | 142 | | } |