1
0
mirror of https://github.com/bitwarden/server.git synced 2024-12-02 13:53:23 +01:00

Have the dapper query working. Working on the ef query.

This commit is contained in:
Patrick Pimentel 2024-11-29 19:15:14 -05:00
parent b974899127
commit bca5eff1a8
No known key found for this signature in database
GPG Key ID: 4B27FC74C6422186
9 changed files with 141 additions and 5 deletions

View File

@ -6,10 +6,10 @@ using Bit.Api.Models.Response;
using Bit.Core.Auth.Models.Api.Request;
using Bit.Core.Auth.Models.Api.Response;
using Bit.Core.Context;
using Bit.Core.Entities;
using Bit.Core.Exceptions;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Settings;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@ -25,6 +25,7 @@ public class DevicesController : Controller
private readonly IUserService _userService;
private readonly IUserRepository _userRepository;
private readonly ICurrentContext _currentContext;
private readonly IGlobalSettings _globalSettings;
private readonly ILogger<DevicesController> _logger;
public DevicesController(
@ -33,6 +34,7 @@ public class DevicesController : Controller
IUserService userService,
IUserRepository userRepository,
ICurrentContext currentContext,
IGlobalSettings globalSettings,
ILogger<DevicesController> logger)
{
_deviceRepository = deviceRepository;
@ -40,6 +42,7 @@ public class DevicesController : Controller
_userService = userService;
_userRepository = userRepository;
_currentContext = currentContext;
_globalSettings = globalSettings;
_logger = logger;
}
@ -69,13 +72,16 @@ public class DevicesController : Controller
return response;
}
// working here
[HttpGet("")]
public async Task<ListResponseModel<DeviceResponseModel>> Get()
public async Task<ListResponseModel<DeviceAuthRequestResponseModel>> Get()
{
ICollection<Device> devices = await _deviceRepository.GetManyByUserIdAsync(_userService.GetProperUserId(User).Value);
var responses = devices.Select(d => new DeviceResponseModel(d));
return new ListResponseModel<DeviceResponseModel>(responses);
var expirationMinutes = _globalSettings.PasswordlessAuth.UserRequestExpiration.TotalMinutes;
var devices = await _deviceRepository.GetManyByUserIdWithDeviceAuth(_userService.GetProperUserId(User).Value, (int)expirationMinutes);
var responses = devices.Select(d => new DeviceAuthRequestResponseModel(d));
return new ListResponseModel<DeviceAuthRequestResponseModel>(responses);
}
// end working here
[HttpPost("")]
public async Task<DeviceResponseModel> Post([FromBody] DeviceRequestModel model)

View File

@ -0,0 +1,41 @@
using Bit.Core.Auth.Utilities;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Api;
namespace Bit.Api.Models.Response;
public class DeviceAuthRequestResponseModel : ResponseModel
{
public DeviceAuthRequestResponseModel(Device device)
: base("device")
{
if (device == null)
{
throw new ArgumentNullException(nameof(device));
}
Id = device.Id;
Name = device.Name;
Type = device.Type;
Identifier = device.Identifier;
CreationDate = device.CreationDate;
IsTrusted = device.IsTrusted();
DevicePendingAuthRequest = new PendingAuthRequest();
}
public Guid Id { get; set; }
public string Name { get; set; }
public DeviceType Type { get; set; }
public string Identifier { get; set; }
public DateTime CreationDate { get; set; }
public bool IsTrusted { get; set; }
public PendingAuthRequest DevicePendingAuthRequest { get; set; }
public class PendingAuthRequest
{
public Guid Id { get; set; }
public DateTime CreationDate { get; set; }
}
}

View File

@ -0,0 +1,6 @@
namespace Bit.Core.Auth.UserFeatures.DeviceReadActiveWithPendingAuthRequestsByUserId;
public interface IDeviceReadActiveWithPendingAuthRequestsByUserIdQuery
{
}

View File

@ -0,0 +1,6 @@
namespace Bit.Core.Auth.UserFeatures.DeviceReadActiveWithPendingAuthRequestsByUserId;
public class DeviceReadActiveWithPendingAuthRequestsByUserIdQuery
{
}

View File

@ -10,5 +10,6 @@ public interface IDeviceRepository : IRepository<Device, Guid>
Task<Device?> GetByIdentifierAsync(string identifier);
Task<Device?> GetByIdentifierAsync(string identifier, Guid userId);
Task<ICollection<Device>> GetManyByUserIdAsync(Guid userId);
Task<ICollection<Device>> GetManyByUserIdWithDeviceAuth(Guid userId, int expirationMinutes);
Task ClearPushTokenAsync(Guid id);
}

View File

@ -76,6 +76,23 @@ public class DeviceRepository : Repository<Device, Guid>, IDeviceRepository
}
}
public async Task<ICollection<Device>> GetManyByUserIdWithDeviceAuth(Guid userId, int expirationMinutes)
{
using (var connection = new SqlConnection(ConnectionString))
{
var results = await connection.QueryAsync<Device>(
$"[{Schema}].[{Table}_ReadActiveWithPendingAuthRequestsByUserId]",
new
{
UserId = userId,
ExpirationMinutes = expirationMinutes
},
commandType: CommandType.StoredProcedure);
return results.ToList();
}
}
public async Task ClearPushTokenAsync(Guid id)
{
using (var connection = new SqlConnection(ConnectionString))

View File

@ -69,4 +69,27 @@ public class DeviceRepository : Repository<Core.Entities.Device, Device, Guid>,
return Mapper.Map<List<Core.Entities.Device>>(devices);
}
}
public async Task<ICollection<Core.Entities.Device>> GetManyByUserIdWithDeviceAuth(Guid userId, int expirationMinutes)
{
using (var scope = ServiceScopeFactory.CreateScope())
{
var dbContext = GetDatabaseContext(scope);
// This is getting closer, need to keep work-shopping it.
var query = from device in dbContext.Devices
join authRequest in dbContext.AuthRequests
on device.UserId equals authRequest.UserId
into deviceRequests
where device.UserId == userId && device.Active == true
select new
{
AuthRequestId = from authRequest in deviceRequests select authRequest.Id,
AuthCreationDate = from authRequest in deviceRequests select authRequest.CreationDate,
};
var devices = await query.ToListAsync();
return Mapper.Map<List<Core.Entities.Device>>(devices);
}
}
}

View File

@ -0,0 +1,18 @@
CREATE PROCEDURE [dbo].[Device_ReadActiveWithPendingAuthRequestsByUserId]
@UserId UNIQUEIDENTIFIER,
@ExpirationMinutes INT
AS
BEGIN
SELECT D.*,
AR.Id as AuthRequestId,
AR.CreationDate as AuthRequestCreationDate
FROM [dbo].[DeviceView] D
LEFT OUTER JOIN [dbo].[AuthRequestView] AR
ON D.userId = AR.userId
AND AR.RequestDeviceIdentifier = D.Identifier
AND AR.Type IN (0, 1) -- Exclude Admin Approval (type 2)
AND DATEADD(mi, @ExpirationMinutes, AR.CreationDate) < GETUTCDATE() -- This means it hasn't expired
AND AR.Approved IS NOT NULL -- This means it hasn't been approved already
WHERE D.UserId = @UserId
AND D.Active = 1 -- Device is active
END

View File

@ -0,0 +1,18 @@
CREATE OR ALTER PROCEDURE [dbo].[Device_ReadActiveWithPendingAuthRequestsByUserId]
@UserId UNIQUEIDENTIFIER,
@ExpirationMinutes INT
AS
BEGIN
SELECT D.*,
AR.Id as AuthRequestId,
AR.CreationDate as AuthRequestCreationDate
FROM [dbo].[DeviceView] D
LEFT OUTER JOIN [dbo].[AuthRequestView] AR
ON D.userId = AR.userId
AND AR.RequestDeviceIdentifier = D.Identifier
AND AR.Type IN (0, 1) -- Exclude Admin Approval (type 2)
AND DATEADD(mi, @ExpirationMinutes, AR.CreationDate) < GETUTCDATE() -- This means it hasn't expired
AND AR.Approved IS NOT NULL -- This means it hasn't been approved already
WHERE D.UserId = @UserId
AND D.Active = 1 -- Device is active
END