mirror of
https://github.com/bitwarden/server.git
synced 2025-03-02 04:11:04 +01:00
Optimized implementations of sqlite and other db interactions.
This commit is contained in:
parent
406f941538
commit
23c049a617
@ -31,7 +31,7 @@ public class DeviceAuthRequestResponseModel : ResponseModel
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a better way to do this in Dapper so that I don't need to explicitly
|
||||
* Is there a better way to do this for Dapper so that I don't need to explicitly
|
||||
* enumerate all the properties in the constructor for mapping?
|
||||
*/
|
||||
public DeviceAuthRequestResponseModel(
|
||||
@ -56,7 +56,9 @@ public class DeviceAuthRequestResponseModel : ResponseModel
|
||||
Type = (DeviceType)type;
|
||||
Identifier = identifier;
|
||||
CreationDate = creationDate;
|
||||
IsTrusted = active;
|
||||
IsTrusted = !string.IsNullOrEmpty(encryptedUserKey) &&
|
||||
!string.IsNullOrEmpty(encryptedPublicKey) &&
|
||||
!string.IsNullOrEmpty(encryptedPrivateKey);
|
||||
if (authRequestId != Guid.Empty && authRequestCreationDate != DateTime.MinValue)
|
||||
{
|
||||
DevicePendingAuthRequest = new PendingAuthRequest()
|
||||
@ -67,6 +69,7 @@ public class DeviceAuthRequestResponseModel : ResponseModel
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public DeviceType Type { get; set; }
|
||||
|
@ -90,6 +90,19 @@ public class DeviceRepository : Repository<Device, Guid>, IDeviceRepository
|
||||
},
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
foreach (var result in results)
|
||||
{
|
||||
result.IsTrusted = result.IsTrusted;
|
||||
if (result.DevicePendingAuthRequest != null)
|
||||
{
|
||||
result.DevicePendingAuthRequest = new DeviceAuthRequestResponseModel.PendingAuthRequest
|
||||
{
|
||||
Id = result.DevicePendingAuthRequest.Id,
|
||||
CreationDate = result.DevicePendingAuthRequest.CreationDate
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return results.ToList();
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
using AutoMapper;
|
||||
using Bit.Core.Auth.Models.Api.Response;
|
||||
|
||||
namespace Bit.Infrastructure.EntityFramework.Auth.Models;
|
||||
|
||||
public class DeviceAuthRequestResponseModelMapperProfile : Profile
|
||||
{
|
||||
public DeviceAuthRequestResponseModelMapperProfile()
|
||||
{
|
||||
CreateMap<Core.Entities.Device, DeviceAuthRequestResponseModel>().ReverseMap();
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models.Api.Response;
|
||||
using Bit.Infrastructure.EntityFramework.Repositories;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Bit.Infrastructure.EntityFramework.Auth.Repositories.Queries;
|
||||
|
||||
public class DeviceWithPendingAuthByUserIdQuery
|
||||
{
|
||||
public IQueryable<DeviceAuthRequestResponseModel> GetQuery(
|
||||
DatabaseContext dbContext,
|
||||
Guid userId,
|
||||
int expirationMinutes)
|
||||
{
|
||||
// Handle sqlite differently because it cannot convert some linq queries into sql syntax.
|
||||
// This error is thrown when trying to run the join else clause below with sqlite:
|
||||
// 'Translating this query requires the SQL APPLY operation, which is not supported on SQLite.'
|
||||
if (dbContext.Database.IsSqlite())
|
||||
{
|
||||
var query =
|
||||
(from device in dbContext.Devices
|
||||
where device.UserId == userId && device.Active
|
||||
select new
|
||||
{
|
||||
device,
|
||||
authRequest =
|
||||
(from authRequest in dbContext.AuthRequests
|
||||
where authRequest.RequestDeviceIdentifier == device.Identifier
|
||||
where authRequest.Type == AuthRequestType.AuthenticateAndUnlock ||
|
||||
authRequest.Type == AuthRequestType.Unlock
|
||||
where authRequest.Approved == null
|
||||
where authRequest.UserId == userId
|
||||
where authRequest.CreationDate.AddMinutes(expirationMinutes) > DateTime.UtcNow
|
||||
orderby authRequest.CreationDate descending
|
||||
select authRequest).First()
|
||||
}
|
||||
).Select(deviceWithAuthRequest => new DeviceAuthRequestResponseModel(
|
||||
deviceWithAuthRequest.device,
|
||||
deviceWithAuthRequest.authRequest != null ? deviceWithAuthRequest.authRequest.Id : Guid.Empty,
|
||||
deviceWithAuthRequest.authRequest != null
|
||||
? deviceWithAuthRequest.authRequest.CreationDate
|
||||
: DateTime.MinValue));
|
||||
|
||||
return query;
|
||||
}
|
||||
else
|
||||
{
|
||||
var query =
|
||||
from device in dbContext.Devices
|
||||
join authRequest in dbContext.AuthRequests
|
||||
on device.Identifier equals authRequest.RequestDeviceIdentifier
|
||||
into deviceRequests
|
||||
from authRequest in deviceRequests
|
||||
.Where(ar => ar.Type == AuthRequestType.AuthenticateAndUnlock || ar.Type == AuthRequestType.Unlock)
|
||||
.Where(ar => ar.Approved == null)
|
||||
.Where(ar => ar.CreationDate.AddMinutes(expirationMinutes) > DateTime.UtcNow)
|
||||
.OrderByDescending(ar => ar.CreationDate)
|
||||
.Take(1)
|
||||
where device.UserId == userId && device.Active == true
|
||||
select new
|
||||
{
|
||||
Device = device,
|
||||
AuthRequestId = authRequest.Id,
|
||||
AuthRequestCreationDate = authRequest.CreationDate
|
||||
};
|
||||
|
||||
var devicesWithAuthQuery = query.Select(deviceAndAuthProperty => new DeviceAuthRequestResponseModel(
|
||||
deviceAndAuthProperty.Device, deviceAndAuthProperty.AuthRequestId, deviceAndAuthProperty.AuthRequestCreationDate));
|
||||
|
||||
return devicesWithAuthQuery;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
using AutoMapper;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models.Api.Response;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Infrastructure.EntityFramework.Auth.Repositories.Queries;
|
||||
using Bit.Infrastructure.EntityFramework.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@ -77,29 +77,8 @@ public class DeviceRepository : Repository<Core.Entities.Device, Device, Guid>,
|
||||
using (var scope = ServiceScopeFactory.CreateScope())
|
||||
{
|
||||
var dbContext = GetDatabaseContext(scope);
|
||||
|
||||
var query = from device in dbContext.Devices
|
||||
where device.UserId == userId && device.Active
|
||||
select new
|
||||
{
|
||||
device,
|
||||
authRequest = (from authRequest in dbContext.AuthRequests
|
||||
where authRequest.RequestDeviceIdentifier == device.Identifier
|
||||
where authRequest.Type == AuthRequestType.AuthenticateAndUnlock || authRequest.Type == AuthRequestType.Unlock
|
||||
where authRequest.Approved == null
|
||||
where authRequest.UserId == userId
|
||||
where authRequest.CreationDate.AddMinutes(expirationMinutes) > DateTime.UtcNow
|
||||
orderby authRequest.CreationDate descending
|
||||
select authRequest).First()
|
||||
};
|
||||
|
||||
var devices =
|
||||
await query.Select(deviceWithAuthRequest => new DeviceAuthRequestResponseModel(
|
||||
deviceWithAuthRequest.device,
|
||||
deviceWithAuthRequest.authRequest != null ? deviceWithAuthRequest.authRequest.Id : Guid.Empty,
|
||||
deviceWithAuthRequest.authRequest != null ? deviceWithAuthRequest.authRequest.CreationDate : DateTime.MinValue)).ToListAsync();
|
||||
|
||||
return devices;
|
||||
var query = new DeviceWithPendingAuthByUserIdQuery();
|
||||
return await query.GetQuery(dbContext, userId, expirationMinutes).ToListAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user