1
0
mirror of https://github.com/bitwarden/server.git synced 2024-12-24 17:17:40 +01:00

equivalent domains APIs and data models

This commit is contained in:
Kyle Spearrin 2017-01-09 22:20:34 -05:00
parent 90607f6d93
commit 7abde8c771
18 changed files with 138 additions and 29 deletions

View File

@ -157,6 +157,13 @@ namespace Bit.Api.Controllers
return Task.FromResult(response); return Task.FromResult(response);
} }
[HttpGet("domains")]
public Task<DomainsResponseModel> GetDomains()
{
var response = new DomainsResponseModel(_currentContext.User);
return Task.FromResult(response);
}
[HttpPut("profile")] [HttpPut("profile")]
[HttpPost("profile")] [HttpPost("profile")]
public async Task<ProfileResponseModel> PutProfile([FromBody]UpdateProfileRequestModel model) public async Task<ProfileResponseModel> PutProfile([FromBody]UpdateProfileRequestModel model)
@ -167,8 +174,18 @@ namespace Bit.Api.Controllers
return response; 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")] [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; var user = _currentContext.User;
if(!await _userManager.CheckPasswordAsync(user, masterPasswordHash)) if(!await _userManager.CheckPasswordAsync(user, masterPasswordHash))
@ -200,7 +217,7 @@ namespace Bit.Api.Controllers
throw new BadRequestException("Token", "Invalid token."); throw new BadRequestException("Token", "Invalid token.");
} }
user.TwoFactorProvider = TwoFactorProvider.Authenticator; user.TwoFactorProvider = TwoFactorProviderType.Authenticator;
user.TwoFactorEnabled = model.Enabled.Value; user.TwoFactorEnabled = model.Enabled.Value;
user.TwoFactorRecoveryCode = user.TwoFactorEnabled ? Guid.NewGuid().ToString("N") : null; user.TwoFactorRecoveryCode = user.TwoFactorEnabled ? Guid.NewGuid().ToString("N") : null;
await _userService.SaveUserAsync(user); await _userService.SaveUserAsync(user);

View File

@ -14,7 +14,7 @@ using Bit.Core.Services;
namespace Bit.Api.Controllers namespace Bit.Api.Controllers
{ {
[Route("logins")] [Route("logins")]
// sites route is deprecated // "sites" route is deprecated
[Route("sites")] [Route("sites")]
[Authorize("Application")] [Authorize("Application")]
public class LoginsController : Controller public class LoginsController : Controller

View 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;
}
}
}

View 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; }
}
}

View File

@ -21,7 +21,7 @@ namespace Bit.Api.Models
} }
public bool TwoFactorEnabled { get; set; } public bool TwoFactorEnabled { get; set; }
public TwoFactorProvider? TwoFactorProvider { get; set; } public TwoFactorProviderType? TwoFactorProvider { get; set; }
public string AuthenticatorKey { get; set; } public string AuthenticatorKey { get; set; }
public string TwoFactorRecoveryCode { get; set; } public string TwoFactorRecoveryCode { get; set; }
} }

View File

@ -15,9 +15,11 @@ namespace Bit.Core.Domains
public string Culture { get; set; } = "en-US"; public string Culture { get; set; } = "en-US";
public string SecurityStamp { get; set; } public string SecurityStamp { get; set; }
public bool TwoFactorEnabled { get; set; } public bool TwoFactorEnabled { get; set; }
public TwoFactorProvider? TwoFactorProvider { get; set; } public TwoFactorProviderType? TwoFactorProvider { get; set; }
public string AuthenticatorKey { get; set; } public string AuthenticatorKey { get; set; }
public string TwoFactorRecoveryCode { 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 CreationDate { get; internal set; } = DateTime.UtcNow;
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow; public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;

View File

@ -1,6 +1,6 @@
namespace Bit.Core.Enums namespace Bit.Core.Enums
{ {
public enum CipherType : short public enum CipherType : byte
{ {
Folder = 0, Folder = 0,
Login = 1 Login = 1

View File

@ -1,6 +1,6 @@
namespace Bit.Core.Enums namespace Bit.Core.Enums
{ {
public enum DeviceType : short public enum DeviceType : byte
{ {
Android = 0, Android = 0,
iOS = 1 iOS = 1

View File

@ -0,0 +1,8 @@
namespace Bit.Core.Enums
{
public enum GlobalEquivalentDomainsType : byte
{
Google = 0,
Apple = 1
}
}

View File

@ -1,6 +1,6 @@
namespace Bit.Core.Enums namespace Bit.Core.Enums
{ {
public enum PushType : short public enum PushType : byte
{ {
SyncCipherUpdate = 0, SyncCipherUpdate = 0,
SyncCipherCreate = 1, SyncCipherCreate = 1,

View File

@ -1,6 +1,6 @@
namespace Bit.Core.Enums namespace Bit.Core.Enums
{ {
public enum TwoFactorProvider public enum TwoFactorProviderType : byte
{ {
Authenticator = 0 Authenticator = 0
} }

View File

@ -14,7 +14,7 @@ namespace Bit.Core.Identity
{ {
var canGenerate = user.TwoFactorEnabled var canGenerate = user.TwoFactorEnabled
&& user.TwoFactorProvider.HasValue && user.TwoFactorProvider.HasValue
&& user.TwoFactorProvider.Value == TwoFactorProvider.Authenticator && user.TwoFactorProvider.Value == TwoFactorProviderType.Authenticator
&& !string.IsNullOrWhiteSpace(user.AuthenticatorKey); && !string.IsNullOrWhiteSpace(user.AuthenticatorKey);
return Task.FromResult(canGenerate); return Task.FromResult(canGenerate);

View File

@ -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> 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> ChangePasswordAsync(User user, string currentMasterPasswordHash, string newMasterPasswordHash, IEnumerable<Cipher> ciphers);
Task<IdentityResult> RefreshSecurityStampAsync(User user, string masterPasswordHash); 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<bool> RecoverTwoFactorAsync(string email, string masterPassword, string recoveryCode);
Task<IdentityResult> DeleteAsync(User user); Task<IdentityResult> DeleteAsync(User user);
} }

View File

@ -216,13 +216,13 @@ namespace Bit.Core.Services
return IdentityResult.Failed(_identityErrorDescriber.PasswordMismatch()); 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) if(user.TwoFactorEnabled && user.TwoFactorProvider.HasValue && user.TwoFactorProvider.Value == provider)
{ {
switch(provider) switch(provider)
{ {
case Enums.TwoFactorProvider.Authenticator: case Enums.TwoFactorProviderType.Authenticator:
if(!string.IsNullOrWhiteSpace(user.AuthenticatorKey)) if(!string.IsNullOrWhiteSpace(user.AuthenticatorKey))
{ {
return; return;
@ -239,7 +239,7 @@ namespace Bit.Core.Services
switch(provider) switch(provider)
{ {
case Enums.TwoFactorProvider.Authenticator: case Enums.TwoFactorProviderType.Authenticator:
var key = KeyGeneration.GenerateRandomKey(20); var key = KeyGeneration.GenerateRandomKey(20);
user.AuthenticatorKey = Base32Encoder.Encode(key); user.AuthenticatorKey = Base32Encoder.Encode(key);
break; break;
@ -269,7 +269,7 @@ namespace Bit.Core.Services
return false; return false;
} }
user.TwoFactorProvider = TwoFactorProvider.Authenticator; user.TwoFactorProvider = TwoFactorProviderType.Authenticator;
user.TwoFactorEnabled = false; user.TwoFactorEnabled = false;
user.TwoFactorRecoveryCode = null; user.TwoFactorRecoveryCode = null;
await SaveUserAsync(user); await SaveUserAsync(user);

View 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; }
}
}

View File

@ -11,6 +11,8 @@
@TwoFactorProvider TINYINT, @TwoFactorProvider TINYINT,
@AuthenticatorKey NVARCHAR(50), @AuthenticatorKey NVARCHAR(50),
@TwoFactorRecoveryCode NVARCHAR(32), @TwoFactorRecoveryCode NVARCHAR(32),
@EquivalentDomains NVARCHAR(MAX),
@ExcludedGlobalEquivalentDomains NVARCHAR(MAX),
@CreationDate DATETIME2(7), @CreationDate DATETIME2(7),
@RevisionDate DATETIME2(7) @RevisionDate DATETIME2(7)
AS AS
@ -31,6 +33,8 @@ BEGIN
[TwoFactorProvider], [TwoFactorProvider],
[AuthenticatorKey], [AuthenticatorKey],
[TwoFactorRecoveryCode], [TwoFactorRecoveryCode],
[EquivalentDomains],
[ExcludedGlobalEquivalentDomains],
[CreationDate], [CreationDate],
[RevisionDate] [RevisionDate]
) )
@ -48,6 +52,8 @@ BEGIN
@TwoFactorProvider, @TwoFactorProvider,
@AuthenticatorKey, @AuthenticatorKey,
@TwoFactorRecoveryCode, @TwoFactorRecoveryCode,
@EquivalentDomains,
@ExcludedGlobalEquivalentDomains,
@CreationDate, @CreationDate,
@RevisionDate @RevisionDate
) )

View File

@ -11,6 +11,8 @@
@TwoFactorProvider TINYINT, @TwoFactorProvider TINYINT,
@AuthenticatorKey NVARCHAR(50), @AuthenticatorKey NVARCHAR(50),
@TwoFactorRecoveryCode NVARCHAR(32), @TwoFactorRecoveryCode NVARCHAR(32),
@EquivalentDomains NVARCHAR(MAX),
@ExcludedGlobalEquivalentDomains NVARCHAR(MAX),
@CreationDate DATETIME2(7), @CreationDate DATETIME2(7),
@RevisionDate DATETIME2(7) @RevisionDate DATETIME2(7)
AS AS
@ -31,6 +33,8 @@ BEGIN
[TwoFactorProvider] = @TwoFactorProvider, [TwoFactorProvider] = @TwoFactorProvider,
[AuthenticatorKey] = @AuthenticatorKey, [AuthenticatorKey] = @AuthenticatorKey,
[TwoFactorRecoveryCode] = @TwoFactorRecoveryCode, [TwoFactorRecoveryCode] = @TwoFactorRecoveryCode,
[EquivalentDomains] = @EquivalentDomains,
[ExcludedGlobalEquivalentDomains] = @ExcludedGlobalEquivalentDomains,
[CreationDate] = @CreationDate, [CreationDate] = @CreationDate,
[RevisionDate] = @RevisionDate [RevisionDate] = @RevisionDate
WHERE WHERE

View File

@ -1,18 +1,20 @@
CREATE TABLE [dbo].[User] ( CREATE TABLE [dbo].[User] (
[Id] UNIQUEIDENTIFIER NOT NULL, [Id] UNIQUEIDENTIFIER NOT NULL,
[Name] NVARCHAR (50) NULL, [Name] NVARCHAR (50) NULL,
[Email] NVARCHAR (50) NOT NULL, [Email] NVARCHAR (50) NOT NULL,
[EmailVerified] BIT NOT NULL, [EmailVerified] BIT NOT NULL,
[MasterPassword] NVARCHAR (300) NOT NULL, [MasterPassword] NVARCHAR (300) NOT NULL,
[MasterPasswordHint] NVARCHAR (50) NULL, [MasterPasswordHint] NVARCHAR (50) NULL,
[Culture] NVARCHAR (10) NOT NULL, [Culture] NVARCHAR (10) NOT NULL,
[SecurityStamp] NVARCHAR (50) NOT NULL, [SecurityStamp] NVARCHAR (50) NOT NULL,
[TwoFactorEnabled] BIT NOT NULL, [TwoFactorEnabled] BIT NOT NULL,
[TwoFactorProvider] TINYINT NULL, [TwoFactorProvider] TINYINT NULL,
[AuthenticatorKey] NVARCHAR (50) NULL, [AuthenticatorKey] NVARCHAR (50) NULL,
[TwoFactorRecoveryCode] NVARCHAR (32) NULL, [TwoFactorRecoveryCode] NVARCHAR (32) NULL,
[CreationDate] DATETIME2 (7) NOT NULL, [EquivalentDomains] NVARCHAR (MAX) NULL,
[RevisionDate] DATETIME2 (7) NOT NULL, [ExcludedGlobalEquivalentDomains] NVARCHAR (MAX) NULL,
[CreationDate] DATETIME2 (7) NOT NULL,
[RevisionDate] DATETIME2 (7) NOT NULL,
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED ([Id] ASC) CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED ([Id] ASC)
); );