mirror of
https://github.com/bitwarden/server.git
synced 2024-12-22 16:57:36 +01:00
Add support for crypto agent (#1623)
This commit is contained in:
parent
dea694193f
commit
c5d5601464
@ -328,12 +328,7 @@ namespace Bit.Sso.Controllers
|
|||||||
throw new Exception(_i18nService.T("OrganizationOrSsoConfigNotFound"));
|
throw new Exception(_i18nService.T("OrganizationOrSsoConfigNotFound"));
|
||||||
}
|
}
|
||||||
|
|
||||||
var options = new JsonSerializerOptions
|
var ssoConfigData = ssoConfig.GetData();
|
||||||
{
|
|
||||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
||||||
};
|
|
||||||
var ssoConfigData = JsonSerializer.Deserialize<SsoConfigurationData>(ssoConfig.Data, options);
|
|
||||||
|
|
||||||
var externalUser = result.Principal;
|
var externalUser = result.Principal;
|
||||||
|
|
||||||
// Validate acr claim against expectation before going further
|
// Validate acr claim against expectation before going further
|
||||||
|
@ -270,12 +270,7 @@ namespace Bit.Core.Business.Sso
|
|||||||
|
|
||||||
private DynamicAuthenticationScheme GetSchemeFromSsoConfig(SsoConfig config)
|
private DynamicAuthenticationScheme GetSchemeFromSsoConfig(SsoConfig config)
|
||||||
{
|
{
|
||||||
var options = new JsonSerializerOptions
|
var data = config.GetData();
|
||||||
{
|
|
||||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
||||||
};
|
|
||||||
var data = JsonSerializer.Deserialize<SsoConfigurationData>(config.Data, options);
|
|
||||||
|
|
||||||
return data.ConfigType switch
|
return data.ConfigType switch
|
||||||
{
|
{
|
||||||
SsoType.OpenIdConnect => GetOidcAuthenticationScheme(config.OrganizationId.ToString(), data),
|
SsoType.OpenIdConnect => GetOidcAuthenticationScheme(config.OrganizationId.ToString(), data),
|
||||||
|
@ -256,6 +256,29 @@ namespace Bit.Api.Controllers
|
|||||||
throw new BadRequestException(ModelState);
|
throw new BadRequestException(ModelState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("set-crypto-agent-key")]
|
||||||
|
public async Task PostSetCryptoAgentKeyAsync([FromBody]SetCryptoAgentKeyRequestModel model)
|
||||||
|
{
|
||||||
|
var user = await _userService.GetUserByPrincipalAsync(User);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new UnauthorizedAccessException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await _userService.SetCryptoAgentKeyAsync(model.ToUser(user), model.Key, model.OrgIdentifier);
|
||||||
|
if (result.Succeeded)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var error in result.Errors)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(string.Empty, error.Description);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BadRequestException(ModelState);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost("kdf")]
|
[HttpPost("kdf")]
|
||||||
public async Task PostKdf([FromBody]KdfRequestModel model)
|
public async Task PostKdf([FromBody]KdfRequestModel model)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Bit.Core.Models.Table;
|
using System;
|
||||||
|
using Bit.Core.Models.Table;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
using IdentityServer4.Validation;
|
using IdentityServer4.Validation;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
@ -9,7 +10,9 @@ using Bit.Core.Services;
|
|||||||
using Bit.Core.Settings;
|
using Bit.Core.Settings;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
using Bit.Core.Identity;
|
using Bit.Core.Identity;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using IdentityServer4.Extensions;
|
using IdentityServer4.Extensions;
|
||||||
using IdentityModel;
|
using IdentityModel;
|
||||||
@ -20,6 +23,7 @@ namespace Bit.Core.IdentityServer
|
|||||||
ICustomTokenRequestValidator
|
ICustomTokenRequestValidator
|
||||||
{
|
{
|
||||||
private UserManager<User> _userManager;
|
private UserManager<User> _userManager;
|
||||||
|
private readonly ISsoConfigRepository _ssoConfigRepository;
|
||||||
|
|
||||||
public CustomTokenRequestValidator(
|
public CustomTokenRequestValidator(
|
||||||
UserManager<User> userManager,
|
UserManager<User> userManager,
|
||||||
@ -35,12 +39,14 @@ namespace Bit.Core.IdentityServer
|
|||||||
ILogger<ResourceOwnerPasswordValidator> logger,
|
ILogger<ResourceOwnerPasswordValidator> logger,
|
||||||
ICurrentContext currentContext,
|
ICurrentContext currentContext,
|
||||||
GlobalSettings globalSettings,
|
GlobalSettings globalSettings,
|
||||||
IPolicyRepository policyRepository)
|
IPolicyRepository policyRepository,
|
||||||
|
ISsoConfigRepository ssoConfigRepository)
|
||||||
: base(userManager, deviceRepository, deviceService, userService, eventService,
|
: base(userManager, deviceRepository, deviceService, userService, eventService,
|
||||||
organizationDuoWebTokenProvider, organizationRepository, organizationUserRepository,
|
organizationDuoWebTokenProvider, organizationRepository, organizationUserRepository,
|
||||||
applicationCacheService, mailService, logger, currentContext, globalSettings, policyRepository)
|
applicationCacheService, mailService, logger, currentContext, globalSettings, policyRepository)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
_ssoConfigRepository = ssoConfigRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ValidateAsync(CustomTokenRequestValidationContext context)
|
public async Task ValidateAsync(CustomTokenRequestValidationContext context)
|
||||||
@ -52,6 +58,25 @@ namespace Bit.Core.IdentityServer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await ValidateAsync(context, context.Result.ValidatedRequest);
|
await ValidateAsync(context, context.Result.ValidatedRequest);
|
||||||
|
|
||||||
|
if (context.Result.CustomResponse != null)
|
||||||
|
{
|
||||||
|
var organizationClaim = context.Result.ValidatedRequest.Subject?.FindFirst(c => c.Type == "organizationId");
|
||||||
|
var organizationId = organizationClaim?.Value ?? "";
|
||||||
|
|
||||||
|
var ssoConfig = await _ssoConfigRepository.GetByOrganizationIdAsync(new Guid(organizationId));
|
||||||
|
var ssoConfigData = ssoConfig.GetData();
|
||||||
|
|
||||||
|
if (ssoConfigData is { UseCryptoAgent: true } && !string.IsNullOrEmpty(ssoConfigData.CryptoAgentUrl))
|
||||||
|
{
|
||||||
|
context.Result.CustomResponse["CryptoAgentUrl"] = ssoConfigData.CryptoAgentUrl;
|
||||||
|
// Prevent clients redirecting to set-password
|
||||||
|
// TODO: Figure out if we can move this logic to the clients since this might break older clients
|
||||||
|
// although we will have issues either way with some clients supporting crypto anent and some not
|
||||||
|
// suggestion: We should roll out the clients before enabling it server wise
|
||||||
|
context.Result.CustomResponse["ResetMasterPassword"] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async override Task<(User, bool)> ValidateContextAsync(CustomTokenRequestValidationContext context)
|
protected async override Task<(User, bool)> ValidateContextAsync(CustomTokenRequestValidationContext context)
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.Table;
|
||||||
|
|
||||||
|
namespace Bit.Core.Models.Api.Request.Accounts
|
||||||
|
{
|
||||||
|
public class SetCryptoAgentKeyRequestModel
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string Key { get; set; }
|
||||||
|
[Required]
|
||||||
|
public KeysRequestModel Keys { get; set; }
|
||||||
|
[Required]
|
||||||
|
public KdfType Kdf { get; set; }
|
||||||
|
[Required]
|
||||||
|
public int KdfIterations { get; set; }
|
||||||
|
[Required]
|
||||||
|
public string OrgIdentifier { get; set; }
|
||||||
|
|
||||||
|
public User ToUser(User existingUser)
|
||||||
|
{
|
||||||
|
existingUser.Kdf = Kdf;
|
||||||
|
existingUser.KdfIterations = KdfIterations;
|
||||||
|
existingUser.Key = Key;
|
||||||
|
Keys.ToUser(existingUser);
|
||||||
|
return existingUser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -31,10 +31,7 @@ namespace Bit.Core.Models.Api
|
|||||||
{
|
{
|
||||||
existingConfig.Enabled = Enabled;
|
existingConfig.Enabled = Enabled;
|
||||||
var configurationData = Data.ToConfigurationData();
|
var configurationData = Data.ToConfigurationData();
|
||||||
existingConfig.Data = JsonSerializer.Serialize(configurationData, new JsonSerializerOptions
|
existingConfig.SetData(configurationData);
|
||||||
{
|
|
||||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
||||||
});
|
|
||||||
return existingConfig;
|
return existingConfig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,6 +43,8 @@ namespace Bit.Core.Models.Api
|
|||||||
public SsoConfigurationDataRequest(SsoConfigurationData configurationData)
|
public SsoConfigurationDataRequest(SsoConfigurationData configurationData)
|
||||||
{
|
{
|
||||||
ConfigType = configurationData.ConfigType;
|
ConfigType = configurationData.ConfigType;
|
||||||
|
UseCryptoAgent = configurationData.UseCryptoAgent;
|
||||||
|
CryptoAgentUrl = configurationData.CryptoAgentUrl;
|
||||||
Authority = configurationData.Authority;
|
Authority = configurationData.Authority;
|
||||||
ClientId = configurationData.ClientId;
|
ClientId = configurationData.ClientId;
|
||||||
ClientSecret = configurationData.ClientSecret;
|
ClientSecret = configurationData.ClientSecret;
|
||||||
@ -79,6 +78,10 @@ namespace Bit.Core.Models.Api
|
|||||||
[Required]
|
[Required]
|
||||||
public SsoType ConfigType { get; set; }
|
public SsoType ConfigType { get; set; }
|
||||||
|
|
||||||
|
// Crypto Agent
|
||||||
|
public bool UseCryptoAgent { get; set; }
|
||||||
|
public string CryptoAgentUrl { get; set; }
|
||||||
|
|
||||||
// OIDC
|
// OIDC
|
||||||
public string Authority { get; set; }
|
public string Authority { get; set; }
|
||||||
public string ClientId { get; set; }
|
public string ClientId { get; set; }
|
||||||
@ -193,6 +196,8 @@ namespace Bit.Core.Models.Api
|
|||||||
return new SsoConfigurationData
|
return new SsoConfigurationData
|
||||||
{
|
{
|
||||||
ConfigType = ConfigType,
|
ConfigType = ConfigType,
|
||||||
|
UseCryptoAgent = UseCryptoAgent,
|
||||||
|
CryptoAgentUrl = CryptoAgentUrl,
|
||||||
Authority = Authority,
|
Authority = Authority,
|
||||||
ClientId = ClientId,
|
ClientId = ClientId,
|
||||||
ClientSecret = ClientSecret,
|
ClientSecret = ClientSecret,
|
||||||
|
@ -13,10 +13,7 @@ namespace Bit.Core.Models.Api
|
|||||||
if (config != null)
|
if (config != null)
|
||||||
{
|
{
|
||||||
Enabled = config.Enabled;
|
Enabled = config.Enabled;
|
||||||
Data = JsonSerializer.Deserialize<SsoConfigurationData>(config.Data, new JsonSerializerOptions
|
Data = config.GetData();
|
||||||
{
|
|
||||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,10 @@ namespace Bit.Core.Models.Data
|
|||||||
|
|
||||||
public SsoType ConfigType { get; set; }
|
public SsoType ConfigType { get; set; }
|
||||||
|
|
||||||
|
// Crypto Agent
|
||||||
|
public bool UseCryptoAgent { get; set; }
|
||||||
|
public string CryptoAgentUrl { get; set; }
|
||||||
|
|
||||||
// OIDC
|
// OIDC
|
||||||
public string Authority { get; set; }
|
public string Authority { get; set; }
|
||||||
public string ClientId { get; set; }
|
public string ClientId { get; set; }
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
|
|
||||||
namespace Bit.Core.Models.Table
|
namespace Bit.Core.Models.Table
|
||||||
{
|
{
|
||||||
@ -10,11 +12,26 @@ namespace Bit.Core.Models.Table
|
|||||||
public string Data { get; set; }
|
public string Data { get; set; }
|
||||||
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
|
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
|
||||||
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
|
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
|
||||||
|
|
||||||
|
private JsonSerializerOptions _jsonSerializerOptions = new()
|
||||||
|
{
|
||||||
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||||
|
};
|
||||||
|
|
||||||
public void SetNewId()
|
public void SetNewId()
|
||||||
{
|
{
|
||||||
// int will be auto-populated
|
// int will be auto-populated
|
||||||
Id = 0;
|
Id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SsoConfigurationData GetData()
|
||||||
|
{
|
||||||
|
return JsonSerializer.Deserialize<SsoConfigurationData>(Data, _jsonSerializerOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetData(SsoConfigurationData data)
|
||||||
|
{
|
||||||
|
Data = JsonSerializer.Serialize(data, _jsonSerializerOptions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ namespace Bit.Core.Models.Table
|
|||||||
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
|
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
|
||||||
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
|
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
|
||||||
public bool ForcePasswordReset { get; set; }
|
public bool ForcePasswordReset { get; set; }
|
||||||
|
public bool UsesCryptoAgent { get; set; }
|
||||||
|
|
||||||
public void SetNewId()
|
public void SetNewId()
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,7 @@ namespace Bit.Core.Services
|
|||||||
string token, string key);
|
string token, string key);
|
||||||
Task<IdentityResult> ChangePasswordAsync(User user, string masterPassword, string newMasterPassword, string key);
|
Task<IdentityResult> ChangePasswordAsync(User user, string masterPassword, string newMasterPassword, string key);
|
||||||
Task<IdentityResult> SetPasswordAsync(User user, string newMasterPassword, string key, string orgIdentifier = null);
|
Task<IdentityResult> SetPasswordAsync(User user, string newMasterPassword, string key, string orgIdentifier = null);
|
||||||
|
Task<IdentityResult> SetCryptoAgentKeyAsync(User user, string key, string orgIdentifier);
|
||||||
Task<IdentityResult> AdminResetPasswordAsync(OrganizationUserType type, Guid orgId, Guid id, string newMasterPassword, string key);
|
Task<IdentityResult> AdminResetPasswordAsync(OrganizationUserType type, Guid orgId, Guid id, string newMasterPassword, string key);
|
||||||
Task<IdentityResult> UpdateTempPasswordAsync(User user, string newMasterPassword, string key, string hint);
|
Task<IdentityResult> UpdateTempPasswordAsync(User user, string newMasterPassword, string key, string hint);
|
||||||
Task<IdentityResult> ChangeKdfAsync(User user, string masterPassword, string newMasterPassword, string key,
|
Task<IdentityResult> ChangeKdfAsync(User user, string masterPassword, string newMasterPassword, string key,
|
||||||
|
@ -635,6 +635,33 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
return IdentityResult.Success;
|
return IdentityResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IdentityResult> SetCryptoAgentKeyAsync(User user, string key, string orgIdentifier)
|
||||||
|
{
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.UsesCryptoAgent)
|
||||||
|
{
|
||||||
|
Logger.LogWarning("Already uses crypto agent.");
|
||||||
|
return IdentityResult.Failed(_identityErrorDescriber.UserAlreadyHasPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
user.RevisionDate = user.AccountRevisionDate = DateTime.UtcNow;
|
||||||
|
user.Key = key;
|
||||||
|
user.UsesCryptoAgent = true;
|
||||||
|
|
||||||
|
await _userRepository.ReplaceAsync(user);
|
||||||
|
// TODO: Use correct event
|
||||||
|
await _eventService.LogUserEventAsync(user.Id, EventType.User_ChangedPassword);
|
||||||
|
|
||||||
|
await _organizationService.AcceptUserAsync(orgIdentifier, user, this);
|
||||||
|
|
||||||
|
return IdentityResult.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<IdentityResult> AdminResetPasswordAsync(OrganizationUserType callingUserType, Guid orgId, Guid id, string newMasterPassword, string key)
|
public async Task<IdentityResult> AdminResetPasswordAsync(OrganizationUserType callingUserType, Guid orgId, Guid id, string newMasterPassword, string key)
|
||||||
{
|
{
|
||||||
|
@ -179,6 +179,10 @@ namespace Bit.Identity.Controllers
|
|||||||
IsPersistent = true,
|
IsPersistent = true,
|
||||||
ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(1)
|
ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(1)
|
||||||
};
|
};
|
||||||
|
if (result.Properties != null && result.Properties.Items.TryGetValue("domain_hint", out var organization))
|
||||||
|
{
|
||||||
|
additionalLocalClaims.Add(new Claim("organizationId", organization));
|
||||||
|
}
|
||||||
ProcessLoginCallback(result, additionalLocalClaims, localSignInProps);
|
ProcessLoginCallback(result, additionalLocalClaims, localSignInProps);
|
||||||
|
|
||||||
// Issue authentication cookie for user
|
// Issue authentication cookie for user
|
||||||
|
@ -30,7 +30,8 @@
|
|||||||
@CreationDate DATETIME2(7),
|
@CreationDate DATETIME2(7),
|
||||||
@RevisionDate DATETIME2(7),
|
@RevisionDate DATETIME2(7),
|
||||||
@ApiKey VARCHAR(30),
|
@ApiKey VARCHAR(30),
|
||||||
@ForcePasswordReset BIT = 0
|
@ForcePasswordReset BIT = 0,
|
||||||
|
@UsesCryptoAgent BIT = 0
|
||||||
AS
|
AS
|
||||||
BEGIN
|
BEGIN
|
||||||
SET NOCOUNT ON
|
SET NOCOUNT ON
|
||||||
@ -68,7 +69,8 @@ BEGIN
|
|||||||
[CreationDate],
|
[CreationDate],
|
||||||
[RevisionDate],
|
[RevisionDate],
|
||||||
[ApiKey],
|
[ApiKey],
|
||||||
[ForcePasswordReset]
|
[ForcePasswordReset],
|
||||||
|
[UsesCryptoAgent]
|
||||||
)
|
)
|
||||||
VALUES
|
VALUES
|
||||||
(
|
(
|
||||||
@ -103,6 +105,7 @@ BEGIN
|
|||||||
@CreationDate,
|
@CreationDate,
|
||||||
@RevisionDate,
|
@RevisionDate,
|
||||||
@ApiKey,
|
@ApiKey,
|
||||||
@ForcePasswordReset
|
@ForcePasswordReset,
|
||||||
|
@UsesCryptoAgent
|
||||||
)
|
)
|
||||||
END
|
END
|
||||||
|
@ -30,7 +30,8 @@
|
|||||||
@CreationDate DATETIME2(7),
|
@CreationDate DATETIME2(7),
|
||||||
@RevisionDate DATETIME2(7),
|
@RevisionDate DATETIME2(7),
|
||||||
@ApiKey VARCHAR(30),
|
@ApiKey VARCHAR(30),
|
||||||
@ForcePasswordReset BIT = 0
|
@ForcePasswordReset BIT = 0,
|
||||||
|
@UsesCryptoAgent BIT = 0
|
||||||
AS
|
AS
|
||||||
BEGIN
|
BEGIN
|
||||||
SET NOCOUNT ON
|
SET NOCOUNT ON
|
||||||
@ -68,7 +69,8 @@ BEGIN
|
|||||||
[CreationDate] = @CreationDate,
|
[CreationDate] = @CreationDate,
|
||||||
[RevisionDate] = @RevisionDate,
|
[RevisionDate] = @RevisionDate,
|
||||||
[ApiKey] = @ApiKey,
|
[ApiKey] = @ApiKey,
|
||||||
[ForcePasswordReset] = @ForcePasswordReset
|
[ForcePasswordReset] = @ForcePasswordReset,
|
||||||
|
[UsesCryptoAgent] = @UsesCryptoAgent
|
||||||
WHERE
|
WHERE
|
||||||
[Id] = @Id
|
[Id] = @Id
|
||||||
END
|
END
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
[RevisionDate] DATETIME2 (7) NOT NULL,
|
[RevisionDate] DATETIME2 (7) NOT NULL,
|
||||||
[ApiKey] VARCHAR (30) NOT NULL,
|
[ApiKey] VARCHAR (30) NOT NULL,
|
||||||
[ForcePasswordReset] BIT NOT NULL,
|
[ForcePasswordReset] BIT NOT NULL,
|
||||||
|
[UsesCryptoAgent] BIT NOT NULL,
|
||||||
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED ([Id] ASC)
|
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED ([Id] ASC)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -32,9 +32,7 @@ namespace Bit.Core.Test.AutoFixture.SsoConfigFixtures
|
|||||||
var fixture = new Fixture();
|
var fixture = new Fixture();
|
||||||
var ssoConfig = fixture.WithAutoNSubstitutions().Create<TableModel.SsoConfig>();
|
var ssoConfig = fixture.WithAutoNSubstitutions().Create<TableModel.SsoConfig>();
|
||||||
var ssoConfigData = fixture.WithAutoNSubstitutions().Create<SsoConfigurationData>();
|
var ssoConfigData = fixture.WithAutoNSubstitutions().Create<SsoConfigurationData>();
|
||||||
ssoConfig.Data = JsonSerializer.Serialize(ssoConfigData, new JsonSerializerOptions(){
|
ssoConfig.SetData(ssoConfigData);
|
||||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
||||||
});
|
|
||||||
return ssoConfig;
|
return ssoConfig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
239
util/Migrator/DbScripts/2021-10-13_00_CryptoAgent.sql
Normal file
239
util/Migrator/DbScripts/2021-10-13_00_CryptoAgent.sql
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
IF COL_LENGTH('[dbo].[User]', 'UsesCryptoAgent') IS NULL
|
||||||
|
BEGIN
|
||||||
|
ALTER TABLE
|
||||||
|
[dbo].[User]
|
||||||
|
ADD
|
||||||
|
[UsesCryptoAgent] BIT NULL
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
UPDATE
|
||||||
|
[dbo].[User]
|
||||||
|
SET
|
||||||
|
[UsesCryptoAgent] = 0
|
||||||
|
WHERE
|
||||||
|
[UsesCryptoAgent] IS NULL
|
||||||
|
GO
|
||||||
|
|
||||||
|
ALTER TABLE
|
||||||
|
[dbo].[User]
|
||||||
|
ALTER COLUMN
|
||||||
|
[UsesCryptoAgent] BIT NOT NULL
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- View: User
|
||||||
|
IF EXISTS(SELECT * FROM sys.views WHERE [Name] = 'UserView')
|
||||||
|
BEGIN
|
||||||
|
DROP VIEW [dbo].[UserView]
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE VIEW [dbo].[UserView]
|
||||||
|
AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
[dbo].[User]
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF OBJECT_ID('[dbo].[User_Create]') IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
DROP PROCEDURE [dbo].[User_Create]
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[User_Create]
|
||||||
|
@Id UNIQUEIDENTIFIER OUTPUT,
|
||||||
|
@Name NVARCHAR(50),
|
||||||
|
@Email NVARCHAR(256),
|
||||||
|
@EmailVerified BIT,
|
||||||
|
@MasterPassword NVARCHAR(300),
|
||||||
|
@MasterPasswordHint NVARCHAR(50),
|
||||||
|
@Culture NVARCHAR(10),
|
||||||
|
@SecurityStamp NVARCHAR(50),
|
||||||
|
@TwoFactorProviders NVARCHAR(MAX),
|
||||||
|
@TwoFactorRecoveryCode NVARCHAR(32),
|
||||||
|
@EquivalentDomains NVARCHAR(MAX),
|
||||||
|
@ExcludedGlobalEquivalentDomains NVARCHAR(MAX),
|
||||||
|
@AccountRevisionDate DATETIME2(7),
|
||||||
|
@Key NVARCHAR(MAX),
|
||||||
|
@PublicKey NVARCHAR(MAX),
|
||||||
|
@PrivateKey NVARCHAR(MAX),
|
||||||
|
@Premium BIT,
|
||||||
|
@PremiumExpirationDate DATETIME2(7),
|
||||||
|
@RenewalReminderDate DATETIME2(7),
|
||||||
|
@Storage BIGINT,
|
||||||
|
@MaxStorageGb SMALLINT,
|
||||||
|
@Gateway TINYINT,
|
||||||
|
@GatewayCustomerId VARCHAR(50),
|
||||||
|
@GatewaySubscriptionId VARCHAR(50),
|
||||||
|
@ReferenceData VARCHAR(MAX),
|
||||||
|
@LicenseKey VARCHAR(100),
|
||||||
|
@Kdf TINYINT,
|
||||||
|
@KdfIterations INT,
|
||||||
|
@CreationDate DATETIME2(7),
|
||||||
|
@RevisionDate DATETIME2(7),
|
||||||
|
@ApiKey VARCHAR(30),
|
||||||
|
@ForcePasswordReset BIT = 0,
|
||||||
|
@UsesCryptoAgent BIT = 0
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
INSERT INTO [dbo].[User]
|
||||||
|
(
|
||||||
|
[Id],
|
||||||
|
[Name],
|
||||||
|
[Email],
|
||||||
|
[EmailVerified],
|
||||||
|
[MasterPassword],
|
||||||
|
[MasterPasswordHint],
|
||||||
|
[Culture],
|
||||||
|
[SecurityStamp],
|
||||||
|
[TwoFactorProviders],
|
||||||
|
[TwoFactorRecoveryCode],
|
||||||
|
[EquivalentDomains],
|
||||||
|
[ExcludedGlobalEquivalentDomains],
|
||||||
|
[AccountRevisionDate],
|
||||||
|
[Key],
|
||||||
|
[PublicKey],
|
||||||
|
[PrivateKey],
|
||||||
|
[Premium],
|
||||||
|
[PremiumExpirationDate],
|
||||||
|
[RenewalReminderDate],
|
||||||
|
[Storage],
|
||||||
|
[MaxStorageGb],
|
||||||
|
[Gateway],
|
||||||
|
[GatewayCustomerId],
|
||||||
|
[GatewaySubscriptionId],
|
||||||
|
[ReferenceData],
|
||||||
|
[LicenseKey],
|
||||||
|
[Kdf],
|
||||||
|
[KdfIterations],
|
||||||
|
[CreationDate],
|
||||||
|
[RevisionDate],
|
||||||
|
[ApiKey],
|
||||||
|
[ForcePasswordReset],
|
||||||
|
[UsesCryptoAgent]
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(
|
||||||
|
@Id,
|
||||||
|
@Name,
|
||||||
|
@Email,
|
||||||
|
@EmailVerified,
|
||||||
|
@MasterPassword,
|
||||||
|
@MasterPasswordHint,
|
||||||
|
@Culture,
|
||||||
|
@SecurityStamp,
|
||||||
|
@TwoFactorProviders,
|
||||||
|
@TwoFactorRecoveryCode,
|
||||||
|
@EquivalentDomains,
|
||||||
|
@ExcludedGlobalEquivalentDomains,
|
||||||
|
@AccountRevisionDate,
|
||||||
|
@Key,
|
||||||
|
@PublicKey,
|
||||||
|
@PrivateKey,
|
||||||
|
@Premium,
|
||||||
|
@PremiumExpirationDate,
|
||||||
|
@RenewalReminderDate,
|
||||||
|
@Storage,
|
||||||
|
@MaxStorageGb,
|
||||||
|
@Gateway,
|
||||||
|
@GatewayCustomerId,
|
||||||
|
@GatewaySubscriptionId,
|
||||||
|
@ReferenceData,
|
||||||
|
@LicenseKey,
|
||||||
|
@Kdf,
|
||||||
|
@KdfIterations,
|
||||||
|
@CreationDate,
|
||||||
|
@RevisionDate,
|
||||||
|
@ApiKey,
|
||||||
|
@ForcePasswordReset,
|
||||||
|
@UsesCryptoAgent
|
||||||
|
)
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF OBJECT_ID('[dbo].[User_Update]') IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
DROP PROCEDURE [dbo].[User_Update]
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[User_Update]
|
||||||
|
@Id UNIQUEIDENTIFIER,
|
||||||
|
@Name NVARCHAR(50),
|
||||||
|
@Email NVARCHAR(256),
|
||||||
|
@EmailVerified BIT,
|
||||||
|
@MasterPassword NVARCHAR(300),
|
||||||
|
@MasterPasswordHint NVARCHAR(50),
|
||||||
|
@Culture NVARCHAR(10),
|
||||||
|
@SecurityStamp NVARCHAR(50),
|
||||||
|
@TwoFactorProviders NVARCHAR(MAX),
|
||||||
|
@TwoFactorRecoveryCode NVARCHAR(32),
|
||||||
|
@EquivalentDomains NVARCHAR(MAX),
|
||||||
|
@ExcludedGlobalEquivalentDomains NVARCHAR(MAX),
|
||||||
|
@AccountRevisionDate DATETIME2(7),
|
||||||
|
@Key NVARCHAR(MAX),
|
||||||
|
@PublicKey NVARCHAR(MAX),
|
||||||
|
@PrivateKey NVARCHAR(MAX),
|
||||||
|
@Premium BIT,
|
||||||
|
@PremiumExpirationDate DATETIME2(7),
|
||||||
|
@RenewalReminderDate DATETIME2(7),
|
||||||
|
@Storage BIGINT,
|
||||||
|
@MaxStorageGb SMALLINT,
|
||||||
|
@Gateway TINYINT,
|
||||||
|
@GatewayCustomerId VARCHAR(50),
|
||||||
|
@GatewaySubscriptionId VARCHAR(50),
|
||||||
|
@ReferenceData VARCHAR(MAX),
|
||||||
|
@LicenseKey VARCHAR(100),
|
||||||
|
@Kdf TINYINT,
|
||||||
|
@KdfIterations INT,
|
||||||
|
@CreationDate DATETIME2(7),
|
||||||
|
@RevisionDate DATETIME2(7),
|
||||||
|
@ApiKey VARCHAR(30),
|
||||||
|
@ForcePasswordReset BIT = 0,
|
||||||
|
@UsesCryptoAgent BIT = 0
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
UPDATE
|
||||||
|
[dbo].[User]
|
||||||
|
SET
|
||||||
|
[Name] = @Name,
|
||||||
|
[Email] = @Email,
|
||||||
|
[EmailVerified] = @EmailVerified,
|
||||||
|
[MasterPassword] = @MasterPassword,
|
||||||
|
[MasterPasswordHint] = @MasterPasswordHint,
|
||||||
|
[Culture] = @Culture,
|
||||||
|
[SecurityStamp] = @SecurityStamp,
|
||||||
|
[TwoFactorProviders] = @TwoFactorProviders,
|
||||||
|
[TwoFactorRecoveryCode] = @TwoFactorRecoveryCode,
|
||||||
|
[EquivalentDomains] = @EquivalentDomains,
|
||||||
|
[ExcludedGlobalEquivalentDomains] = @ExcludedGlobalEquivalentDomains,
|
||||||
|
[AccountRevisionDate] = @AccountRevisionDate,
|
||||||
|
[Key] = @Key,
|
||||||
|
[PublicKey] = @PublicKey,
|
||||||
|
[PrivateKey] = @PrivateKey,
|
||||||
|
[Premium] = @Premium,
|
||||||
|
[PremiumExpirationDate] = @PremiumExpirationDate,
|
||||||
|
[RenewalReminderDate] = @RenewalReminderDate,
|
||||||
|
[Storage] = @Storage,
|
||||||
|
[MaxStorageGb] = @MaxStorageGb,
|
||||||
|
[Gateway] = @Gateway,
|
||||||
|
[GatewayCustomerId] = @GatewayCustomerId,
|
||||||
|
[GatewaySubscriptionId] = @GatewaySubscriptionId,
|
||||||
|
[ReferenceData] = @ReferenceData,
|
||||||
|
[LicenseKey] = @LicenseKey,
|
||||||
|
[Kdf] = @Kdf,
|
||||||
|
[KdfIterations] = @KdfIterations,
|
||||||
|
[CreationDate] = @CreationDate,
|
||||||
|
[RevisionDate] = @RevisionDate,
|
||||||
|
[ApiKey] = @ApiKey,
|
||||||
|
[ForcePasswordReset] = @ForcePasswordReset,
|
||||||
|
[UsesCryptoAgent] = @UsesCryptoAgent
|
||||||
|
WHERE
|
||||||
|
[Id] = @Id
|
||||||
|
END
|
Loading…
Reference in New Issue
Block a user