mirror of
https://github.com/bitwarden/server.git
synced 2025-04-10 07:38:13 -05:00
allow org user reg. when reg. is disabled
This commit is contained in:
parent
1b1ec7629b
commit
72e95e2a98
@ -45,7 +45,8 @@ namespace Bit.Api.Controllers
|
|||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public async Task PostRegister([FromBody]RegisterRequestModel model)
|
public async Task PostRegister([FromBody]RegisterRequestModel model)
|
||||||
{
|
{
|
||||||
var result = await _userService.RegisterUserAsync(model.ToUser(), model.MasterPasswordHash);
|
var result = await _userService.RegisterUserAsync(model.ToUser(), model.MasterPasswordHash,
|
||||||
|
model.Token, model.OrganizationUserId);
|
||||||
if(result.Succeeded)
|
if(result.Succeeded)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using Bit.Core.Models.Table;
|
using Bit.Core.Models.Table;
|
||||||
|
|
||||||
namespace Bit.Core.Models.Api
|
namespace Bit.Core.Models.Api
|
||||||
@ -18,6 +19,8 @@ namespace Bit.Core.Models.Api
|
|||||||
public string MasterPasswordHint { get; set; }
|
public string MasterPasswordHint { get; set; }
|
||||||
public string Key { get; set; }
|
public string Key { get; set; }
|
||||||
public KeysRequestModel Keys { get; set; }
|
public KeysRequestModel Keys { get; set; }
|
||||||
|
public string Token { get; set; }
|
||||||
|
public Guid? OrganizationUserId { get; set; }
|
||||||
|
|
||||||
public User ToUser()
|
public User ToUser()
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@ namespace Bit.Core.Services
|
|||||||
Task<User> GetUserByPrincipalAsync(ClaimsPrincipal principal);
|
Task<User> GetUserByPrincipalAsync(ClaimsPrincipal principal);
|
||||||
Task<DateTime> GetAccountRevisionDateByIdAsync(Guid userId);
|
Task<DateTime> GetAccountRevisionDateByIdAsync(Guid userId);
|
||||||
Task SaveUserAsync(User user, bool push = false);
|
Task SaveUserAsync(User user, bool push = false);
|
||||||
Task<IdentityResult> RegisterUserAsync(User user, string masterPassword);
|
Task<IdentityResult> RegisterUserAsync(User user, string masterPassword, string token, Guid? orgUserId);
|
||||||
Task SendMasterPasswordHintAsync(string email);
|
Task SendMasterPasswordHintAsync(string email);
|
||||||
Task SendTwoFactorEmailAsync(User user);
|
Task SendTwoFactorEmailAsync(User user);
|
||||||
Task<bool> VerifyTwoFactorEmailAsync(User user, string token);
|
Task<bool> VerifyTwoFactorEmailAsync(User user, string token);
|
||||||
|
@ -1012,26 +1012,7 @@ namespace Bit.Core.Services
|
|||||||
throw new BadRequestException("You are already part of this organization.");
|
throw new BadRequestException("You are already part of this organization.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var tokenValidationFailed = true;
|
if(!CoreHelpers.UserInviteTokenIsValid(_dataProtector, token, user.Email, orgUser.Id))
|
||||||
try
|
|
||||||
{
|
|
||||||
var unprotectedData = _dataProtector.Unprotect(token);
|
|
||||||
var dataParts = unprotectedData.Split(' ');
|
|
||||||
if(dataParts.Length == 4 &&
|
|
||||||
dataParts[0] == "OrganizationUserInvite" &&
|
|
||||||
new Guid(dataParts[1]) == orgUser.Id &&
|
|
||||||
dataParts[2].Equals(user.Email, StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
{
|
|
||||||
var creationTime = CoreHelpers.FromEpocMilliseconds(Convert.ToInt64(dataParts[3]));
|
|
||||||
tokenValidationFailed = creationTime.AddDays(5) < DateTime.UtcNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
tokenValidationFailed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tokenValidationFailed)
|
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Invalid token.");
|
throw new BadRequestException("Invalid token.");
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ using Bit.Core.Exceptions;
|
|||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
|
|
||||||
namespace Bit.Core.Services
|
namespace Bit.Core.Services
|
||||||
{
|
{
|
||||||
@ -38,6 +39,7 @@ namespace Bit.Core.Services
|
|||||||
private readonly IEnumerable<IPasswordValidator<User>> _passwordValidators;
|
private readonly IEnumerable<IPasswordValidator<User>> _passwordValidators;
|
||||||
private readonly ILicensingService _licenseService;
|
private readonly ILicensingService _licenseService;
|
||||||
private readonly IEventService _eventService;
|
private readonly IEventService _eventService;
|
||||||
|
private readonly IDataProtector _organizationServiceDataProtector;
|
||||||
private readonly CurrentContext _currentContext;
|
private readonly CurrentContext _currentContext;
|
||||||
private readonly GlobalSettings _globalSettings;
|
private readonly GlobalSettings _globalSettings;
|
||||||
|
|
||||||
@ -59,6 +61,7 @@ namespace Bit.Core.Services
|
|||||||
ILogger<UserManager<User>> logger,
|
ILogger<UserManager<User>> logger,
|
||||||
ILicensingService licenseService,
|
ILicensingService licenseService,
|
||||||
IEventService eventService,
|
IEventService eventService,
|
||||||
|
IDataProtectionProvider dataProtectionProvider,
|
||||||
CurrentContext currentContext,
|
CurrentContext currentContext,
|
||||||
GlobalSettings globalSettings)
|
GlobalSettings globalSettings)
|
||||||
: base(
|
: base(
|
||||||
@ -84,6 +87,8 @@ namespace Bit.Core.Services
|
|||||||
_passwordValidators = passwordValidators;
|
_passwordValidators = passwordValidators;
|
||||||
_licenseService = licenseService;
|
_licenseService = licenseService;
|
||||||
_eventService = eventService;
|
_eventService = eventService;
|
||||||
|
_organizationServiceDataProtector = dataProtectionProvider.CreateProtector(
|
||||||
|
"OrganizationServiceDataProtector");
|
||||||
_currentContext = currentContext;
|
_currentContext = currentContext;
|
||||||
_globalSettings = globalSettings;
|
_globalSettings = globalSettings;
|
||||||
}
|
}
|
||||||
@ -204,11 +209,19 @@ namespace Bit.Core.Services
|
|||||||
await _mailService.SendVerifyDeleteEmailAsync(user.Email, user.Id, token);
|
await _mailService.SendVerifyDeleteEmailAsync(user.Email, user.Id, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IdentityResult> RegisterUserAsync(User user, string masterPassword)
|
public async Task<IdentityResult> RegisterUserAsync(User user, string masterPassword,
|
||||||
|
string token, Guid? orgUserId)
|
||||||
{
|
{
|
||||||
if(_globalSettings.DisableUserRegistration)
|
var tokenValid = false;
|
||||||
|
if(!string.IsNullOrWhiteSpace(token) && orgUserId.HasValue)
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Registration has been disabled by the system administrator.");
|
tokenValid = CoreHelpers.UserInviteTokenIsValid(_organizationServiceDataProtector, token,
|
||||||
|
user.Email, orgUserId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_globalSettings.DisableUserRegistration && !tokenValid)
|
||||||
|
{
|
||||||
|
throw new BadRequestException("Open registration has been disabled by the system administrator.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await base.CreateAsync(user, masterPassword);
|
var result = await base.CreateAsync(user, masterPassword);
|
||||||
|
@ -13,6 +13,7 @@ using System.Text.RegularExpressions;
|
|||||||
using Dapper;
|
using Dapper;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
|
|
||||||
namespace Bit.Core.Utilities
|
namespace Bit.Core.Utilities
|
||||||
{
|
{
|
||||||
@ -452,5 +453,29 @@ namespace Bit.Core.Utilities
|
|||||||
}
|
}
|
||||||
return new Uri(string.Format("{0}?{1}", baseUri, queryCollection), uriKind);
|
return new Uri(string.Format("{0}?{1}", baseUri, queryCollection), uriKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool UserInviteTokenIsValid(IDataProtector protector, string token,
|
||||||
|
string userEmail, Guid orgUserId)
|
||||||
|
{
|
||||||
|
var invalid = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var unprotectedData = protector.Unprotect(token);
|
||||||
|
var dataParts = unprotectedData.Split(' ');
|
||||||
|
if(dataParts.Length == 4 && dataParts[0] == "OrganizationUserInvite" &&
|
||||||
|
new Guid(dataParts[1]) == orgUserId &&
|
||||||
|
dataParts[2].Equals(userEmail, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
var creationTime = FromEpocMilliseconds(Convert.ToInt64(dataParts[3]));
|
||||||
|
invalid = creationTime.AddDays(5) < DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
invalid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !invalid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user