diff --git a/src/Core/Models/Table/U2f.cs b/src/Core/Models/Table/U2f.cs new file mode 100644 index 0000000000..a376e5186c --- /dev/null +++ b/src/Core/Models/Table/U2f.cs @@ -0,0 +1,20 @@ +using System; + +namespace Bit.Core.Models.Table +{ + public class U2f : IDataObject + { + public int Id { get; set; } + public Guid UserId { get; set; } + public string KeyHandle { get; set; } + public string Challenge { get; set; } + public string AppId { get; set; } + public string Version { get; set; } + public DateTime CreationDate { get; internal set; } = DateTime.UtcNow; + + public void SetNewId() + { + // do nothing since it is an identity + } + } +} diff --git a/src/Core/Repositories/IU2fRepository.cs b/src/Core/Repositories/IU2fRepository.cs new file mode 100644 index 0000000000..d655f17617 --- /dev/null +++ b/src/Core/Repositories/IU2fRepository.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Bit.Core.Models.Table; + +namespace Bit.Core.Repositories +{ + public interface IU2fRepository : IRepository + { + Task> GetManyByUserIdAsync(Guid userId); + Task DeleteManyByUserIdAsync(Guid userId); + } +} diff --git a/src/Core/Repositories/SqlServer/U2fRepository.cs b/src/Core/Repositories/SqlServer/U2fRepository.cs new file mode 100644 index 0000000000..b5b5cd62a7 --- /dev/null +++ b/src/Core/Repositories/SqlServer/U2fRepository.cs @@ -0,0 +1,66 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Threading.Tasks; +using Bit.Core.Models.Table; +using System.Data; +using Dapper; + +namespace Bit.Core.Repositories.SqlServer +{ + public class U2fRepository : Repository, IU2fRepository + { + public U2fRepository(GlobalSettings globalSettings) + : this(globalSettings.SqlServer.ConnectionString) + { } + + public U2fRepository(string connectionString) + : base(connectionString) + { } + + public async Task> GetManyByUserIdAsync(Guid userId) + { + using(var connection = new SqlConnection(ConnectionString)) + { + var results = await connection.QueryAsync( + $"[{Schema}].[U2f_ReadByUserId]", + new { UserId = userId }, + commandType: CommandType.StoredProcedure); + + return results.ToList(); + } + } + + public async Task DeleteManyByUserIdAsync(Guid userId) + { + using(var connection = new SqlConnection(ConnectionString)) + { + await connection.ExecuteAsync( + $"[{Schema}].[U2f_DeleteByUserId]", + new { UserId = userId }, + commandType: CommandType.StoredProcedure); + } + } + + public override Task GetByIdAsync(int id) + { + throw new NotSupportedException(); + } + + public override Task ReplaceAsync(U2f obj) + { + throw new NotSupportedException(); + } + + public override Task UpsertAsync(U2f obj) + { + throw new NotSupportedException(); + } + + public override Task DeleteAsync(U2f obj) + { + throw new NotSupportedException(); + } + } +} diff --git a/src/Sql/Sql.sqlproj b/src/Sql/Sql.sqlproj index 6359386d84..efa8becfe8 100644 --- a/src/Sql/Sql.sqlproj +++ b/src/Sql/Sql.sqlproj @@ -195,5 +195,10 @@ + + + + + \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/U2f_Create.sql b/src/Sql/dbo/Stored Procedures/U2f_Create.sql new file mode 100644 index 0000000000..b446e431d5 --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/U2f_Create.sql @@ -0,0 +1,33 @@ +CREATE PROCEDURE [dbo].[U2f_Create] + @Id INT, + @UserId UNIQUEIDENTIFIER, + @KeyHandle VARCHAR(50), + @Challenge VARCHAR(50), + @AppId VARCHAR(50), + @Version VARCHAR(50), + @CreationDate DATETIME2(7) +AS +BEGIN + SET NOCOUNT ON + + INSERT INTO [dbo].[U2f] + ( + [Id], + [UserId], + [KeyHandle], + [Challenge], + [AppId], + [Version], + [CreationDate] + ) + VALUES + ( + @Id, + @UserId, + @KeyHandle, + @Challenge, + @AppId, + @Version, + @CreationDate + ) +END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/U2f_DeleteByUserId.sql b/src/Sql/dbo/Stored Procedures/U2f_DeleteByUserId.sql new file mode 100644 index 0000000000..306207adc1 --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/U2f_DeleteByUserId.sql @@ -0,0 +1,12 @@ +CREATE PROCEDURE [dbo].[U2f_DeleteByUserId] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + DELETE + FROM + [dbo].[U2f] + WHERE + [UserId] = @UserId +END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/U2f_ReadByUserId.sql b/src/Sql/dbo/Stored Procedures/U2f_ReadByUserId.sql new file mode 100644 index 0000000000..5f92199fdd --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/U2f_ReadByUserId.sql @@ -0,0 +1,13 @@ +CREATE PROCEDURE [dbo].[U2f_ReadByUserId] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + * + FROM + [dbo].[U2fView] + WHERE + [UserId] = @UserId +END \ No newline at end of file diff --git a/src/Sql/dbo/Tables/U2f.sql b/src/Sql/dbo/Tables/U2f.sql new file mode 100644 index 0000000000..1765c2a114 --- /dev/null +++ b/src/Sql/dbo/Tables/U2f.sql @@ -0,0 +1,11 @@ +CREATE TABLE [dbo].[U2f] ( + [Id] INT NOT NULL IDENTITY, + [UserId] UNIQUEIDENTIFIER NOT NULL, + [KeyHandle] VARCHAR (50) NOT NULL, + [Challenge] VARCHAR (50) NOT NULL, + [AppId] VARCHAR (50) NOT NULL, + [Version] VARCHAR (50) NOT NULL, + [CreationDate] DATETIME2 (7) NOT NULL, + CONSTRAINT [PK_U2f] PRIMARY KEY CLUSTERED ([Id] ASC), + CONSTRAINT [FK_U2f_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]) +); diff --git a/src/Sql/dbo/Views/U2fView.sql b/src/Sql/dbo/Views/U2fView.sql new file mode 100644 index 0000000000..72a84ac4cc --- /dev/null +++ b/src/Sql/dbo/Views/U2fView.sql @@ -0,0 +1,6 @@ +CREATE VIEW [dbo].[U2fView] +AS +SELECT + * +FROM + [dbo].[U2f]