mirror of
https://github.com/bitwarden/server.git
synced 2024-12-23 17:07:42 +01:00
equivalent domains APIs and data models
This commit is contained in:
parent
90607f6d93
commit
7abde8c771
@ -157,6 +157,13 @@ namespace Bit.Api.Controllers
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
|
||||
[HttpGet("domains")]
|
||||
public Task<DomainsResponseModel> GetDomains()
|
||||
{
|
||||
var response = new DomainsResponseModel(_currentContext.User);
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
|
||||
[HttpPut("profile")]
|
||||
[HttpPost("profile")]
|
||||
public async Task<ProfileResponseModel> PutProfile([FromBody]UpdateProfileRequestModel model)
|
||||
@ -165,10 +172,20 @@ namespace Bit.Api.Controllers
|
||||
|
||||
var response = new ProfileResponseModel(_currentContext.User);
|
||||
return response;
|
||||
}
|
||||
|
||||
[HttpPut("domains")]
|
||||
[HttpPost("domains")]
|
||||
public async Task<DomainsResponseModel> PutDomains([FromBody]UpdateDomainsRequestModel model)
|
||||
{
|
||||
await _userService.SaveUserAsync(model.ToUser(_currentContext.User));
|
||||
|
||||
var response = new DomainsResponseModel(_currentContext.User);
|
||||
return response;
|
||||
}
|
||||
|
||||
[HttpGet("two-factor")]
|
||||
public async Task<TwoFactorResponseModel> GetTwoFactor(string masterPasswordHash, TwoFactorProvider provider)
|
||||
public async Task<TwoFactorResponseModel> GetTwoFactor(string masterPasswordHash, TwoFactorProviderType provider)
|
||||
{
|
||||
var user = _currentContext.User;
|
||||
if(!await _userManager.CheckPasswordAsync(user, masterPasswordHash))
|
||||
@ -200,7 +217,7 @@ namespace Bit.Api.Controllers
|
||||
throw new BadRequestException("Token", "Invalid token.");
|
||||
}
|
||||
|
||||
user.TwoFactorProvider = TwoFactorProvider.Authenticator;
|
||||
user.TwoFactorProvider = TwoFactorProviderType.Authenticator;
|
||||
user.TwoFactorEnabled = model.Enabled.Value;
|
||||
user.TwoFactorRecoveryCode = user.TwoFactorEnabled ? Guid.NewGuid().ToString("N") : null;
|
||||
await _userService.SaveUserAsync(user);
|
||||
|
@ -14,7 +14,7 @@ using Bit.Core.Services;
|
||||
namespace Bit.Api.Controllers
|
||||
{
|
||||
[Route("logins")]
|
||||
// sites route is deprecated
|
||||
// "sites" route is deprecated
|
||||
[Route("sites")]
|
||||
[Authorize("Application")]
|
||||
public class LoginsController : Controller
|
||||
|
21
src/Api/Models/Request/Accounts/UpdateDomainsRequestModel.cs
Normal file
21
src/Api/Models/Request/Accounts/UpdateDomainsRequestModel.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using Bit.Core.Domains;
|
||||
using System.Collections.Generic;
|
||||
using Bit.Core.Enums;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Bit.Api.Models
|
||||
{
|
||||
public class UpdateDomainsRequestModel
|
||||
{
|
||||
public IEnumerable<IEnumerable<string>> EquivalentDomains { get; set; }
|
||||
public IEnumerable<GlobalEquivalentDomainsType> ExcludedGlobalEquivalentDomains { get; set; }
|
||||
|
||||
public User ToUser(User existingUser)
|
||||
{
|
||||
existingUser.EquivalentDomains = EquivalentDomains != null ? JsonConvert.SerializeObject(EquivalentDomains) : null;
|
||||
existingUser.ExcludedGlobalEquivalentDomains = ExcludedGlobalEquivalentDomains != null ?
|
||||
JsonConvert.SerializeObject(ExcludedGlobalEquivalentDomains) : null;
|
||||
return existingUser;
|
||||
}
|
||||
}
|
||||
}
|
30
src/Api/Models/Response/DomainsResponseModel.cs
Normal file
30
src/Api/Models/Response/DomainsResponseModel.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using Bit.Core.Domains;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Api.Models
|
||||
{
|
||||
public class DomainsResponseModel : ResponseModel
|
||||
{
|
||||
public DomainsResponseModel(User user)
|
||||
: base("domains")
|
||||
{
|
||||
if(user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
EquivalentDomains = user.EquivalentDomains != null ?
|
||||
JsonConvert.DeserializeObject<List<List<string>>>(user.EquivalentDomains) : null;
|
||||
GlobalEquivalentDomains = Core.Utilities.EquivalentDomains.Global;
|
||||
ExcludedGlobalEquivalentDomains = user.ExcludedGlobalEquivalentDomains != null ?
|
||||
JsonConvert.DeserializeObject<List<GlobalEquivalentDomainsType>>(user.ExcludedGlobalEquivalentDomains) : null;
|
||||
}
|
||||
|
||||
public IEnumerable<IEnumerable<string>> EquivalentDomains { get; set; }
|
||||
public IDictionary<GlobalEquivalentDomainsType, IEnumerable<string>> GlobalEquivalentDomains { get; set; }
|
||||
public IEnumerable<GlobalEquivalentDomainsType> ExcludedGlobalEquivalentDomains { get; set; }
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ namespace Bit.Api.Models
|
||||
}
|
||||
|
||||
public bool TwoFactorEnabled { get; set; }
|
||||
public TwoFactorProvider? TwoFactorProvider { get; set; }
|
||||
public TwoFactorProviderType? TwoFactorProvider { get; set; }
|
||||
public string AuthenticatorKey { get; set; }
|
||||
public string TwoFactorRecoveryCode { get; set; }
|
||||
}
|
||||
|
@ -15,9 +15,11 @@ namespace Bit.Core.Domains
|
||||
public string Culture { get; set; } = "en-US";
|
||||
public string SecurityStamp { get; set; }
|
||||
public bool TwoFactorEnabled { get; set; }
|
||||
public TwoFactorProvider? TwoFactorProvider { get; set; }
|
||||
public TwoFactorProviderType? TwoFactorProvider { get; set; }
|
||||
public string AuthenticatorKey { get; set; }
|
||||
public string TwoFactorRecoveryCode { get; set; }
|
||||
public string EquivalentDomains { get; set; }
|
||||
public string ExcludedGlobalEquivalentDomains { get; set; }
|
||||
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
|
||||
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace Bit.Core.Enums
|
||||
{
|
||||
public enum CipherType : short
|
||||
public enum CipherType : byte
|
||||
{
|
||||
Folder = 0,
|
||||
Login = 1
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace Bit.Core.Enums
|
||||
{
|
||||
public enum DeviceType : short
|
||||
public enum DeviceType : byte
|
||||
{
|
||||
Android = 0,
|
||||
iOS = 1
|
||||
|
8
src/Core/Enums/GlobalEquivalentDomainsType.cs
Normal file
8
src/Core/Enums/GlobalEquivalentDomainsType.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Bit.Core.Enums
|
||||
{
|
||||
public enum GlobalEquivalentDomainsType : byte
|
||||
{
|
||||
Google = 0,
|
||||
Apple = 1
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
namespace Bit.Core.Enums
|
||||
{
|
||||
public enum PushType : short
|
||||
public enum PushType : byte
|
||||
{
|
||||
SyncCipherUpdate = 0,
|
||||
SyncCipherCreate = 1,
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace Bit.Core.Enums
|
||||
{
|
||||
public enum TwoFactorProvider
|
||||
public enum TwoFactorProviderType : byte
|
||||
{
|
||||
Authenticator = 0
|
||||
}
|
@ -14,7 +14,7 @@ namespace Bit.Core.Identity
|
||||
{
|
||||
var canGenerate = user.TwoFactorEnabled
|
||||
&& user.TwoFactorProvider.HasValue
|
||||
&& user.TwoFactorProvider.Value == TwoFactorProvider.Authenticator
|
||||
&& user.TwoFactorProvider.Value == TwoFactorProviderType.Authenticator
|
||||
&& !string.IsNullOrWhiteSpace(user.AuthenticatorKey);
|
||||
|
||||
return Task.FromResult(canGenerate);
|
||||
|
@ -16,7 +16,7 @@ namespace Bit.Core.Services
|
||||
Task<IdentityResult> ChangeEmailAsync(User user, string masterPassword, string newEmail, string newMasterPassword, string token, IEnumerable<Cipher> ciphers);
|
||||
Task<IdentityResult> ChangePasswordAsync(User user, string currentMasterPasswordHash, string newMasterPasswordHash, IEnumerable<Cipher> ciphers);
|
||||
Task<IdentityResult> RefreshSecurityStampAsync(User user, string masterPasswordHash);
|
||||
Task GetTwoFactorAsync(User user, Enums.TwoFactorProvider provider);
|
||||
Task GetTwoFactorAsync(User user, Enums.TwoFactorProviderType provider);
|
||||
Task<bool> RecoverTwoFactorAsync(string email, string masterPassword, string recoveryCode);
|
||||
Task<IdentityResult> DeleteAsync(User user);
|
||||
}
|
||||
|
@ -216,13 +216,13 @@ namespace Bit.Core.Services
|
||||
return IdentityResult.Failed(_identityErrorDescriber.PasswordMismatch());
|
||||
}
|
||||
|
||||
public async Task GetTwoFactorAsync(User user, Enums.TwoFactorProvider provider)
|
||||
public async Task GetTwoFactorAsync(User user, Enums.TwoFactorProviderType provider)
|
||||
{
|
||||
if(user.TwoFactorEnabled && user.TwoFactorProvider.HasValue && user.TwoFactorProvider.Value == provider)
|
||||
{
|
||||
switch(provider)
|
||||
{
|
||||
case Enums.TwoFactorProvider.Authenticator:
|
||||
case Enums.TwoFactorProviderType.Authenticator:
|
||||
if(!string.IsNullOrWhiteSpace(user.AuthenticatorKey))
|
||||
{
|
||||
return;
|
||||
@ -239,7 +239,7 @@ namespace Bit.Core.Services
|
||||
|
||||
switch(provider)
|
||||
{
|
||||
case Enums.TwoFactorProvider.Authenticator:
|
||||
case Enums.TwoFactorProviderType.Authenticator:
|
||||
var key = KeyGeneration.GenerateRandomKey(20);
|
||||
user.AuthenticatorKey = Base32Encoder.Encode(key);
|
||||
break;
|
||||
@ -269,7 +269,7 @@ namespace Bit.Core.Services
|
||||
return false;
|
||||
}
|
||||
|
||||
user.TwoFactorProvider = TwoFactorProvider.Authenticator;
|
||||
user.TwoFactorProvider = TwoFactorProviderType.Authenticator;
|
||||
user.TwoFactorEnabled = false;
|
||||
user.TwoFactorRecoveryCode = null;
|
||||
await SaveUserAsync(user);
|
||||
|
19
src/Core/Utilities/EquivalentDomains.cs
Normal file
19
src/Core/Utilities/EquivalentDomains.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Bit.Core.Enums;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bit.Core.Utilities
|
||||
{
|
||||
public class EquivalentDomains
|
||||
{
|
||||
static EquivalentDomains()
|
||||
{
|
||||
Global = new Dictionary<GlobalEquivalentDomainsType, IEnumerable<string>>();
|
||||
|
||||
Global.Add(GlobalEquivalentDomainsType.Apple, new List<string>() { "apple.com", "icloud.com" });
|
||||
Global.Add(GlobalEquivalentDomainsType.Google, new List<string> { "google.com", "youtube.com", "gmail.com" });
|
||||
}
|
||||
|
||||
public static IDictionary<GlobalEquivalentDomainsType, IEnumerable<string>> Global { get; set; }
|
||||
|
||||
}
|
||||
}
|
@ -11,6 +11,8 @@
|
||||
@TwoFactorProvider TINYINT,
|
||||
@AuthenticatorKey NVARCHAR(50),
|
||||
@TwoFactorRecoveryCode NVARCHAR(32),
|
||||
@EquivalentDomains NVARCHAR(MAX),
|
||||
@ExcludedGlobalEquivalentDomains NVARCHAR(MAX),
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7)
|
||||
AS
|
||||
@ -31,6 +33,8 @@ BEGIN
|
||||
[TwoFactorProvider],
|
||||
[AuthenticatorKey],
|
||||
[TwoFactorRecoveryCode],
|
||||
[EquivalentDomains],
|
||||
[ExcludedGlobalEquivalentDomains],
|
||||
[CreationDate],
|
||||
[RevisionDate]
|
||||
)
|
||||
@ -48,6 +52,8 @@ BEGIN
|
||||
@TwoFactorProvider,
|
||||
@AuthenticatorKey,
|
||||
@TwoFactorRecoveryCode,
|
||||
@EquivalentDomains,
|
||||
@ExcludedGlobalEquivalentDomains,
|
||||
@CreationDate,
|
||||
@RevisionDate
|
||||
)
|
||||
|
@ -11,6 +11,8 @@
|
||||
@TwoFactorProvider TINYINT,
|
||||
@AuthenticatorKey NVARCHAR(50),
|
||||
@TwoFactorRecoveryCode NVARCHAR(32),
|
||||
@EquivalentDomains NVARCHAR(MAX),
|
||||
@ExcludedGlobalEquivalentDomains NVARCHAR(MAX),
|
||||
@CreationDate DATETIME2(7),
|
||||
@RevisionDate DATETIME2(7)
|
||||
AS
|
||||
@ -31,6 +33,8 @@ BEGIN
|
||||
[TwoFactorProvider] = @TwoFactorProvider,
|
||||
[AuthenticatorKey] = @AuthenticatorKey,
|
||||
[TwoFactorRecoveryCode] = @TwoFactorRecoveryCode,
|
||||
[EquivalentDomains] = @EquivalentDomains,
|
||||
[ExcludedGlobalEquivalentDomains] = @ExcludedGlobalEquivalentDomains,
|
||||
[CreationDate] = @CreationDate,
|
||||
[RevisionDate] = @RevisionDate
|
||||
WHERE
|
||||
|
@ -1,18 +1,20 @@
|
||||
CREATE TABLE [dbo].[User] (
|
||||
[Id] UNIQUEIDENTIFIER NOT NULL,
|
||||
[Name] NVARCHAR (50) NULL,
|
||||
[Email] NVARCHAR (50) NOT NULL,
|
||||
[EmailVerified] BIT NOT NULL,
|
||||
[MasterPassword] NVARCHAR (300) NOT NULL,
|
||||
[MasterPasswordHint] NVARCHAR (50) NULL,
|
||||
[Culture] NVARCHAR (10) NOT NULL,
|
||||
[SecurityStamp] NVARCHAR (50) NOT NULL,
|
||||
[TwoFactorEnabled] BIT NOT NULL,
|
||||
[TwoFactorProvider] TINYINT NULL,
|
||||
[AuthenticatorKey] NVARCHAR (50) NULL,
|
||||
[TwoFactorRecoveryCode] NVARCHAR (32) NULL,
|
||||
[CreationDate] DATETIME2 (7) NOT NULL,
|
||||
[RevisionDate] DATETIME2 (7) NOT NULL,
|
||||
[Id] UNIQUEIDENTIFIER NOT NULL,
|
||||
[Name] NVARCHAR (50) NULL,
|
||||
[Email] NVARCHAR (50) NOT NULL,
|
||||
[EmailVerified] BIT NOT NULL,
|
||||
[MasterPassword] NVARCHAR (300) NOT NULL,
|
||||
[MasterPasswordHint] NVARCHAR (50) NULL,
|
||||
[Culture] NVARCHAR (10) NOT NULL,
|
||||
[SecurityStamp] NVARCHAR (50) NOT NULL,
|
||||
[TwoFactorEnabled] BIT NOT NULL,
|
||||
[TwoFactorProvider] TINYINT NULL,
|
||||
[AuthenticatorKey] NVARCHAR (50) NULL,
|
||||
[TwoFactorRecoveryCode] NVARCHAR (32) NULL,
|
||||
[EquivalentDomains] NVARCHAR (MAX) NULL,
|
||||
[ExcludedGlobalEquivalentDomains] NVARCHAR (MAX) NULL,
|
||||
[CreationDate] DATETIME2 (7) NOT NULL,
|
||||
[RevisionDate] DATETIME2 (7) NOT NULL,
|
||||
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED ([Id] ASC)
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user