1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 15:42:48 -05:00

[SSO] New user provision flow (#945)

* Initial commit of accept user during set password flow

* changed new org user from accepted to invited // moved another check to token accept function

* Revised some white space // Moved business logic to UserService

* Fixed UserServiceTest

* Removed some white-space

* Removed more white-space

* Final white-space issues
This commit is contained in:
Vincent Salucci
2020-10-13 15:00:33 -05:00
committed by GitHub
parent dfe5c571b9
commit 50cf16a3fb
7 changed files with 59 additions and 21 deletions

View File

@ -1074,9 +1074,9 @@ namespace Bit.Core.Services
throw new BadRequestException("User invalid.");
}
if (orgUser.Status != OrganizationUserStatusType.Invited)
if (!CoreHelpers.UserInviteTokenIsValid(_dataProtector, token, user.Email, orgUser.Id, _globalSettings))
{
throw new BadRequestException("Already accepted.");
throw new BadRequestException("Invalid token.");
}
if (string.IsNullOrWhiteSpace(orgUser.Email) ||
@ -1085,6 +1085,42 @@ namespace Bit.Core.Services
throw new BadRequestException("User email does not match invite.");
}
var existingOrgUserCount = await _organizationUserRepository.GetCountByOrganizationAsync(
orgUser.OrganizationId, user.Email, true);
if (existingOrgUserCount > 0)
{
throw new BadRequestException("You are already part of this organization.");
}
return await AcceptUserAsync(orgUser, user, userService);
}
public async Task<OrganizationUser> AcceptUserAsync(string orgIdentifier, User user, IUserService userService)
{
var org = await _organizationRepository.GetByIdentifierAsync(orgIdentifier);
if (org == null)
{
throw new BadRequestException("Organization invalid.");
}
var usersOrgs = await _organizationUserRepository.GetManyByUserAsync(user.Id);
var orgUser = usersOrgs.FirstOrDefault(u => u.OrganizationId == org.Id);
if (orgUser == null)
{
throw new BadRequestException("User not found within organization.");
}
return await AcceptUserAsync(orgUser, user, userService);
}
private async Task<OrganizationUser> AcceptUserAsync(OrganizationUser orgUser, User user,
IUserService userService)
{
if (orgUser.Status != OrganizationUserStatusType.Invited)
{
throw new BadRequestException("Already accepted.");
}
if (orgUser.Type == OrganizationUserType.Owner || orgUser.Type == OrganizationUserType.Admin)
{
var org = await GetOrgById(orgUser.OrganizationId);
@ -1099,18 +1135,6 @@ namespace Bit.Core.Services
}
}
var existingOrgUserCount = await _organizationUserRepository.GetCountByOrganizationAsync(
orgUser.OrganizationId, user.Email, true);
if (existingOrgUserCount > 0)
{
throw new BadRequestException("You are already part of this organization.");
}
if (!CoreHelpers.UserInviteTokenIsValid(_dataProtector, token, user.Email, orgUser.Id, _globalSettings))
{
throw new BadRequestException("Invalid token.");
}
if (!await userService.TwoFactorIsEnabledAsync(user))
{
var policies = await _policyRepository.GetManyByOrganizationIdAsync(orgUser.OrganizationId);
@ -1124,10 +1148,10 @@ namespace Bit.Core.Services
orgUser.Status = OrganizationUserStatusType.Accepted;
orgUser.UserId = user.Id;
orgUser.Email = null;
await _organizationUserRepository.ReplaceAsync(orgUser);
// TODO: send notification emails to org admins and accepting user?
return orgUser;
}

View File

@ -48,6 +48,7 @@ namespace Bit.Core.Services
private readonly IReferenceEventService _referenceEventService;
private readonly CurrentContext _currentContext;
private readonly GlobalSettings _globalSettings;
private readonly IOrganizationService _organizationService;
public UserService(
IUserRepository userRepository,
@ -74,7 +75,8 @@ namespace Bit.Core.Services
IPolicyRepository policyRepository,
IReferenceEventService referenceEventService,
CurrentContext currentContext,
GlobalSettings globalSettings)
GlobalSettings globalSettings,
IOrganizationService organizationService)
: base(
store,
optionsAccessor,
@ -107,6 +109,7 @@ namespace Bit.Core.Services
_referenceEventService = referenceEventService;
_currentContext = currentContext;
_globalSettings = globalSettings;
_organizationService = organizationService;
}
public Guid? GetProperUserId(ClaimsPrincipal principal)
@ -579,7 +582,8 @@ namespace Bit.Core.Services
return IdentityResult.Failed(_identityErrorDescriber.PasswordMismatch());
}
public async Task<IdentityResult> SetPasswordAsync(User user, string masterPassword, string key)
public async Task<IdentityResult> SetPasswordAsync(User user, string masterPassword, string key,
string orgIdentifier = null)
{
if (user == null)
{
@ -603,7 +607,12 @@ namespace Bit.Core.Services
await _userRepository.ReplaceAsync(user);
await _eventService.LogUserEventAsync(user.Id, EventType.User_ChangedPassword);
if (!string.IsNullOrWhiteSpace(orgIdentifier))
{
await _organizationService.AcceptUserAsync(orgIdentifier, user, this);
}
return IdentityResult.Success;
}