mirror of
https://github.com/bitwarden/server.git
synced 2025-02-23 03:01:23 +01:00
org invite validation and email tweaks
This commit is contained in:
parent
da29160218
commit
472a4ade8f
@ -10,6 +10,7 @@ namespace Bit.Core.Repositories
|
||||
public interface IOrganizationUserRepository : IRepository<OrganizationUser, Guid>
|
||||
{
|
||||
Task<OrganizationUser> GetByOrganizationAsync(Guid organizationId, Guid userId);
|
||||
Task<OrganizationUser> GetByOrganizationAsync(Guid organizationId, string email);
|
||||
Task<Tuple<OrganizationUserUserDetails, ICollection<SubvaultUserDetails>>> GetDetailsByIdAsync(Guid id);
|
||||
Task<ICollection<OrganizationUserUserDetails>> GetManyDetailsByOrganizationAsync(Guid organizationId);
|
||||
Task<ICollection<OrganizationUserOrganizationDetails>> GetManyDetailsByUserAsync(Guid userId,
|
||||
|
@ -34,6 +34,19 @@ namespace Bit.Core.Repositories.SqlServer
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<OrganizationUser> GetByOrganizationAsync(Guid organizationId, string email)
|
||||
{
|
||||
using(var connection = new SqlConnection(ConnectionString))
|
||||
{
|
||||
var results = await connection.QueryAsync<OrganizationUser>(
|
||||
"[dbo].[OrganizationUser_ReadByOrganizationIdEmail]",
|
||||
new { OrganizationId = organizationId, Email = email },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
return results.SingleOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Tuple<OrganizationUserUserDetails, ICollection<SubvaultUserDetails>>> GetDetailsByIdAsync(Guid id)
|
||||
{
|
||||
using(var connection = new SqlConnection(ConnectionString))
|
||||
|
@ -105,9 +105,15 @@ namespace Bit.Core.Services
|
||||
throw new BadRequestException("Cannot invite users.");
|
||||
}
|
||||
|
||||
// TODO: make sure user is not already invited
|
||||
// Make sure user is not already invited
|
||||
var existingOrgUser = await _organizationUserRepository.GetByOrganizationAsync(organizationId, email);
|
||||
if(existingOrgUser != null)
|
||||
{
|
||||
throw new BadRequestException("User already invited.");
|
||||
}
|
||||
|
||||
// TODO: validate subvaults?
|
||||
var orgSubvaults = await _subvaultRepository.GetManyByOrganizationIdAsync(organizationId);
|
||||
var filteredSubvaults = subvaults.Where(s => orgSubvaults.Any(os => os.Id == s.SubvaultId));
|
||||
|
||||
var orgUser = new OrganizationUser
|
||||
{
|
||||
@ -122,7 +128,7 @@ namespace Bit.Core.Services
|
||||
};
|
||||
|
||||
await _organizationUserRepository.CreateAsync(orgUser);
|
||||
await SaveUserSubvaultsAsync(orgUser, subvaults, true);
|
||||
await SaveUserSubvaultsAsync(orgUser, filteredSubvaults, true);
|
||||
await SendInviteAsync(orgUser);
|
||||
|
||||
return orgUser;
|
||||
@ -147,10 +153,11 @@ namespace Bit.Core.Services
|
||||
|
||||
private async Task SendInviteAsync(OrganizationUser orgUser)
|
||||
{
|
||||
var org = await _organizationRepository.GetByIdAsync(orgUser.OrganizationId);
|
||||
var nowMillis = CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow);
|
||||
var token = _dataProtector.Protect(
|
||||
$"OrganizationUserInvite {orgUser.Id} {orgUser.Email} {nowMillis}");
|
||||
await _mailService.SendOrganizationInviteEmailAsync("Organization Name", orgUser, token);
|
||||
await _mailService.SendOrganizationInviteEmailAsync(org.Name, orgUser, token);
|
||||
}
|
||||
|
||||
public async Task<OrganizationUser> AcceptUserAsync(Guid organizationUserId, User user, string token)
|
||||
|
@ -4,6 +4,7 @@ using System.Threading.Tasks;
|
||||
using Bit.Core.Models.Table;
|
||||
using SendGrid;
|
||||
using SendGrid.Helpers.Mail;
|
||||
using System.Net;
|
||||
|
||||
namespace Bit.Core.Services
|
||||
{
|
||||
@ -98,6 +99,7 @@ namespace Bit.Core.Services
|
||||
message.AddSubstitution("{{organizationId}}", orgUser.OrganizationId.ToString());
|
||||
message.AddSubstitution("{{organizationUserId}}", orgUser.Id.ToString());
|
||||
message.AddSubstitution("{{token}}", token);
|
||||
message.AddSubstitution("{{email}}", WebUtility.UrlEncode(orgUser.Email));
|
||||
message.AddCategories(new List<string> { AdministrativeCategoryName, "Organization Invite" });
|
||||
|
||||
await _client.SendEmailAsync(message);
|
||||
|
@ -177,5 +177,6 @@
|
||||
<Build Include="dbo\Stored Procedures\CipherFullDetails_ReadByIdUserId.sql" />
|
||||
<Build Include="dbo\Functions\UserCanEditCipher.sql" />
|
||||
<Build Include="dbo\Stored Procedures\Cipher_UpdatePartial.sql" />
|
||||
<Build Include="dbo\Stored Procedures\OrganizationUser_ReadByOrganizationIdEmail.sql" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,15 @@
|
||||
CREATE PROCEDURE [dbo].[OrganizationUser_ReadByOrganizationIdEmail]
|
||||
@OrganizationId UNIQUEIDENTIFIER,
|
||||
@Email NVARCHAR(50)
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
[dbo].[OrganizationUserView]
|
||||
WHERE
|
||||
[OrganizationId] = @OrganizationId
|
||||
AND [Email] = @Email
|
||||
END
|
Loading…
Reference in New Issue
Block a user