1
0
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:
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);
}
[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);

View File

@ -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

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 TwoFactorProvider? TwoFactorProvider { get; set; }
public TwoFactorProviderType? TwoFactorProvider { get; set; }
public string AuthenticatorKey { 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 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;

View File

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

View File

@ -1,6 +1,6 @@
namespace Bit.Core.Enums
{
public enum DeviceType : short
public enum DeviceType : byte
{
Android = 0,
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
{
public enum PushType : short
public enum PushType : byte
{
SyncCipherUpdate = 0,
SyncCipherCreate = 1,

View File

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

View File

@ -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);

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

View File

@ -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);

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,
@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
)

View File

@ -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

View File

@ -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)
);