1
0
mirror of https://github.com/bitwarden/server.git synced 2025-01-26 22:31:30 +01:00

events for collections, groups, and org users

This commit is contained in:
Kyle Spearrin 2017-12-01 16:00:30 -05:00
parent a8fefb54c4
commit 28770d3761
20 changed files with 182 additions and 27 deletions

View File

@ -135,7 +135,7 @@ namespace Bit.Api.Controllers
throw new NotFoundException();
}
await _collectionRepository.DeleteAsync(collection);
await _collectionService.DeleteAsync(collection);
}
[HttpDelete("{id}/user/{orgUserId}")]

View File

@ -121,7 +121,7 @@ namespace Bit.Api.Controllers
throw new NotFoundException();
}
await _groupRepository.DeleteAsync(group);
await _groupService.DeleteAsync(group);
}
[HttpDelete("{id}/user/{orgUserId}")]

View File

@ -178,8 +178,8 @@ namespace Bit.Api.Controllers
{
throw new BadRequestException("Only owners can update other owners.");
}
await _organizationUserRepository.UpdateGroupsAsync(organizationUser.Id, model.GroupIds.Select(g => new Guid(g)));
await _organizationService.UpdateUserGroupsAsync(organizationUser, model.GroupIds.Select(g => new Guid(g)));
}
[HttpDelete("{id}")]

View File

@ -29,6 +29,9 @@
OrganizationUser_Invited = 1500,
OrganizationUser_Confirmed = 1501,
OrganizationUser_Updated = 1502,
OrganizationUser_Removed = 1503
OrganizationUser_Removed = 1503,
OrganizationUser_UpdatedGroups = 1504,
Organization_Updated = 1600
}
}

View File

@ -7,7 +7,7 @@ namespace Bit.Core.Models.Data
{
public class CipherEvent : EventTableEntity
{
public CipherEvent(Cipher cipher, EventType type, Guid? actingUserId = null)
public CipherEvent(Cipher cipher, Guid? actingUserId, EventType type)
{
OrganizationId = cipher.OrganizationId;
UserId = cipher.UserId;

View File

@ -0,0 +1,23 @@
using System;
using Bit.Core.Enums;
using Bit.Core.Models.Table;
using Bit.Core.Utilities;
namespace Bit.Core.Models.Data
{
public class CollectionEvent : EventTableEntity
{
public CollectionEvent(Collection collection, Guid actingUserId, EventType type)
{
OrganizationId = collection.OrganizationId;
CollectionId = collection.Id;
Type = (int)type;
ActingUserId = actingUserId;
Timestamp = DateTime.UtcNow;
PartitionKey = $"OrganizationId={OrganizationId}";
RowKey = string.Format("Date={0}__ActingUserId={1}__Type={2}",
CoreHelpers.DateTimeToTableStorageKey(Timestamp.DateTime), ActingUserId, Type);
}
}
}

View File

@ -11,6 +11,9 @@ namespace Bit.Core.Models.Data
public Guid? OrganizationId { get; set; }
public Guid? CipherId { get; set; }
public ICollection<Guid> CipherIds { get; set; }
public Guid? CollectionId { get; set; }
public Guid? GroupId { get; set; }
public Guid? OrganizationUserId { get; set; }
public Guid? ActingUserId { get; set; }
}
}

View File

@ -0,0 +1,23 @@
using System;
using Bit.Core.Enums;
using Bit.Core.Models.Table;
using Bit.Core.Utilities;
namespace Bit.Core.Models.Data
{
public class GroupEvent : EventTableEntity
{
public GroupEvent(Group group, Guid actingUserId, EventType type)
{
OrganizationId = group.OrganizationId;
GroupId = group.Id;
Type = (int)type;
ActingUserId = actingUserId;
Timestamp = DateTime.UtcNow;
PartitionKey = $"OrganizationId={OrganizationId}";
RowKey = string.Format("Date={0}__ActingUserId={1}__Type={2}",
CoreHelpers.DateTimeToTableStorageKey(Timestamp.DateTime), ActingUserId, Type);
}
}
}

View File

@ -1,32 +1,22 @@
using System;
using Bit.Core.Enums;
using Bit.Core.Models.Table;
using Bit.Core.Utilities;
namespace Bit.Core.Models.Data
{
public class OrganizationEvent : EventTableEntity
{
public OrganizationEvent(Guid organizationId, EventType type)
public OrganizationEvent(Organization organization, Guid actingUserId, EventType type)
{
OrganizationId = organizationId;
OrganizationId = organization.Id;
Type = (int)type;
ActingUserId = actingUserId;
Timestamp = DateTime.UtcNow;
PartitionKey = $"OrganizationId={OrganizationId}";
RowKey = string.Format("Date={0}__Type={1}",
CoreHelpers.DateTimeToTableStorageKey(Timestamp.DateTime), Type);
}
public OrganizationEvent(Guid organizationId, Guid userId, EventType type)
{
OrganizationId = organizationId;
UserId = userId;
Type = (int)type;
Timestamp = DateTime.UtcNow;
PartitionKey = $"OrganizationId={OrganizationId}";
RowKey = string.Format("Date={0}__UserId={1}__Type={2}",
CoreHelpers.DateTimeToTableStorageKey(Timestamp.DateTime), UserId, Type);
RowKey = string.Format("Date={0}__ActingUserId={1}__Type={2}",
CoreHelpers.DateTimeToTableStorageKey(Timestamp.DateTime), ActingUserId, Type);
}
}
}

View File

@ -0,0 +1,24 @@
using System;
using Bit.Core.Enums;
using Bit.Core.Models.Table;
using Bit.Core.Utilities;
namespace Bit.Core.Models.Data
{
public class OrganizationUserEvent : EventTableEntity
{
public OrganizationUserEvent(OrganizationUser organizationUser, Guid actingUserId, EventType type)
{
OrganizationId = organizationUser.OrganizationId;
UserId = organizationUser.UserId;
OrganizationUserId = organizationUser.Id;
Type = (int)type;
ActingUserId = actingUserId;
Timestamp = DateTime.UtcNow;
PartitionKey = $"OrganizationId={OrganizationId}";
RowKey = string.Format("Date={0}__ActingUserId={1}__Type={2}",
CoreHelpers.DateTimeToTableStorageKey(Timestamp.DateTime), ActingUserId, Type);
}
}
}

View File

@ -1,7 +1,6 @@
using System.Threading.Tasks;
using Bit.Core.Models.Table;
using System.Collections.Generic;
using System;
using Bit.Core.Models.Data;
namespace Bit.Core.Services
@ -9,5 +8,6 @@ namespace Bit.Core.Services
public interface ICollectionService
{
Task SaveAsync(Collection collection, IEnumerable<SelectionReadOnly> groups = null);
Task DeleteAsync(Collection collection);
}
}

View File

@ -9,5 +9,9 @@ namespace Bit.Core.Services
{
Task LogUserEventAsync(Guid userId, EventType type);
Task LogCipherEventAsync(Cipher cipher, EventType type);
Task LogCollectionEventAsync(Collection collection, EventType type);
Task LogGroupEventAsync(Group group, EventType type);
Task LogOrganizationUserEventAsync(OrganizationUser organizationUser, EventType type);
Task LogOrganizationEventAsync(Organization organization, EventType type);
}
}

View File

@ -8,5 +8,6 @@ namespace Bit.Core.Services
public interface IGroupService
{
Task SaveAsync(Group group, IEnumerable<SelectionReadOnly> collections = null);
Task DeleteAsync(Group group);
}
}

View File

@ -36,6 +36,7 @@ namespace Bit.Core.Services
Task SaveUserAsync(OrganizationUser user, Guid savingUserId, IEnumerable<SelectionReadOnly> collections);
Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid deletingUserId);
Task DeleteUserAsync(Guid organizationId, Guid userId);
Task UpdateUserGroupsAsync(OrganizationUser organizationUser, IEnumerable<Guid> groupIds);
Task<OrganizationLicense> GenerateLicenseAsync(Guid organizationId, Guid installationId);
Task<OrganizationLicense> GenerateLicenseAsync(Organization organization, Guid installationId);
Task ImportAsync(Guid organizationId, Guid importingUserId, IEnumerable<ImportedGroup> groups,

View File

@ -10,6 +10,7 @@ namespace Bit.Core.Services
{
public class CollectionService : ICollectionService
{
private readonly IEventService _eventService;
private readonly IOrganizationRepository _organizationRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly ICollectionRepository _collectionRepository;
@ -17,12 +18,14 @@ namespace Bit.Core.Services
private readonly IMailService _mailService;
public CollectionService(
IEventService eventService,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
ICollectionRepository collectionRepository,
IUserRepository userRepository,
IMailService mailService)
{
_eventService = eventService;
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
_collectionRepository = collectionRepository;
@ -58,6 +61,8 @@ namespace Bit.Core.Services
{
await _collectionRepository.CreateAsync(collection, groups);
}
await _eventService.LogCollectionEventAsync(collection, Enums.EventType.Collection_Created);
}
else
{
@ -69,7 +74,15 @@ namespace Bit.Core.Services
{
await _collectionRepository.ReplaceAsync(collection, groups ?? new List<SelectionReadOnly>());
}
await _eventService.LogCollectionEventAsync(collection, Enums.EventType.Collection_Updated);
}
}
public async Task DeleteAsync(Collection collection)
{
await _collectionRepository.DeleteAsync(collection);
await _eventService.LogCollectionEventAsync(collection, Enums.EventType.Collection_Deleted);
}
}
}

View File

@ -63,7 +63,31 @@ namespace Bit.Core.Services
return;
}
var e = new CipherEvent(cipher, type, _currentContext?.UserId);
var e = new CipherEvent(cipher, _currentContext?.UserId, type);
await _eventRepository.CreateAsync(e);
}
public async Task LogCollectionEventAsync(Collection collection, EventType type)
{
var e = new CollectionEvent(collection, _currentContext.UserId.Value, type);
await _eventRepository.CreateAsync(e);
}
public async Task LogGroupEventAsync(Group group, EventType type)
{
var e = new GroupEvent(group, _currentContext.UserId.Value, type);
await _eventRepository.CreateAsync(e);
}
public async Task LogOrganizationUserEventAsync(OrganizationUser organizationUser, EventType type)
{
var e = new OrganizationUserEvent(organizationUser, _currentContext.UserId.Value, type);
await _eventRepository.CreateAsync(e);
}
public async Task LogOrganizationEventAsync(Organization organization, EventType type)
{
var e = new OrganizationEvent(organization, _currentContext.UserId.Value, type);
await _eventRepository.CreateAsync(e);
}
}

View File

@ -10,13 +10,16 @@ namespace Bit.Core.Services
{
public class GroupService : IGroupService
{
private readonly IEventService _eventService;
private readonly IOrganizationRepository _organizationRepository;
private readonly IGroupRepository _groupRepository;
public GroupService(
IEventService eventService,
IOrganizationRepository organizationRepository,
IGroupRepository groupRepository)
{
_eventService = eventService;
_organizationRepository = organizationRepository;
_groupRepository = groupRepository;
}
@ -46,12 +49,21 @@ namespace Bit.Core.Services
{
await _groupRepository.CreateAsync(group, collections);
}
await _eventService.LogGroupEventAsync(group, Enums.EventType.Group_Created);
}
else
{
group.RevisionDate = DateTime.UtcNow;
await _groupRepository.ReplaceAsync(group, collections ?? new List<SelectionReadOnly>());
await _eventService.LogGroupEventAsync(group, Enums.EventType.Group_Updated);
}
}
public async Task DeleteAsync(Group group)
{
await _groupRepository.DeleteAsync(group);
await _eventService.LogGroupEventAsync(group, Enums.EventType.Group_Deleted);
}
}
}

View File

@ -29,6 +29,7 @@ namespace Bit.Core.Services
private readonly IPushRegistrationService _pushRegistrationService;
private readonly IDeviceRepository _deviceRepository;
private readonly ILicensingService _licensingService;
private readonly IEventService _eventService;
private readonly IInstallationRepository _installationRepository;
private readonly StripePaymentService _stripePaymentService;
private readonly GlobalSettings _globalSettings;
@ -45,6 +46,7 @@ namespace Bit.Core.Services
IPushRegistrationService pushRegistrationService,
IDeviceRepository deviceRepository,
ILicensingService licensingService,
IEventService eventService,
IInstallationRepository installationRepository,
GlobalSettings globalSettings)
{
@ -59,6 +61,7 @@ namespace Bit.Core.Services
_pushRegistrationService = pushRegistrationService;
_deviceRepository = deviceRepository;
_licensingService = licensingService;
_eventService = eventService;
_installationRepository = installationRepository;
_stripePaymentService = new StripePaymentService();
_globalSettings = globalSettings;
@ -803,6 +806,7 @@ namespace Bit.Core.Services
}
await _organizationRepository.ReplaceAsync(organization);
await _eventService.LogOrganizationEventAsync(organization, EventType.Organization_Updated);
if(updateBilling && !string.IsNullOrWhiteSpace(organization.GatewayCustomerId))
{
@ -1008,6 +1012,7 @@ namespace Bit.Core.Services
orgUser.Key = key;
orgUser.Email = null;
await _organizationUserRepository.ReplaceAsync(orgUser);
await _eventService.LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_Confirmed);
var user = await _userRepository.GetByIdAsync(orgUser.UserId.Value);
await _mailService.SendOrganizationConfirmedEmailAsync(org.Name, user.Email);
@ -1057,6 +1062,7 @@ namespace Bit.Core.Services
collections = new List<SelectionReadOnly>();
}
await _organizationUserRepository.ReplaceAsync(user, collections);
await _eventService.LogOrganizationUserEventAsync(user, EventType.OrganizationUser_Updated);
}
public async Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid deletingUserId)
@ -1088,6 +1094,7 @@ namespace Bit.Core.Services
}
await _organizationUserRepository.DeleteAsync(orgUser);
await _eventService.LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_Removed);
if(orgUser.UserId.HasValue)
{
@ -1112,6 +1119,7 @@ namespace Bit.Core.Services
}
await _organizationUserRepository.DeleteAsync(orgUser);
await _eventService.LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_Removed);
if(orgUser.UserId.HasValue)
{
@ -1121,6 +1129,12 @@ namespace Bit.Core.Services
}
}
public async Task UpdateUserGroupsAsync(OrganizationUser organizationUser, IEnumerable<Guid> groupIds)
{
await _organizationUserRepository.UpdateGroupsAsync(organizationUser.Id, groupIds);
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_UpdatedGroups);
}
public async Task<OrganizationLicense> GenerateLicenseAsync(Guid organizationId, Guid installationId)
{
var organization = await _organizationRepository.GetByIdAsync(organizationId);

View File

@ -12,6 +12,26 @@ namespace Bit.Core.Services
return Task.FromResult(0);
}
public Task LogCollectionEventAsync(Collection collection, EventType type)
{
return Task.FromResult(0);
}
public Task LogGroupEventAsync(Group group, EventType type)
{
return Task.FromResult(0);
}
public Task LogOrganizationEventAsync(Organization organization, EventType type)
{
return Task.FromResult(0);
}
public Task LogOrganizationUserEventAsync(OrganizationUser organizationUser, EventType type)
{
return Task.FromResult(0);
}
public Task LogUserEventAsync(Guid userId, EventType type)
{
return Task.FromResult(0);

View File

@ -57,9 +57,9 @@ namespace Bit.Core.Utilities
services.AddScoped<ICipherService, CipherService>();
services.AddScoped<IUserService, UserService>();
services.AddSingleton<IDeviceService, DeviceService>();
services.AddSingleton<IOrganizationService, OrganizationService>();
services.AddSingleton<ICollectionService, CollectionService>();
services.AddSingleton<IGroupService, GroupService>();
services.AddScoped<IOrganizationService, OrganizationService>();
services.AddScoped<ICollectionService, CollectionService>();
services.AddScoped<IGroupService, GroupService>();
services.AddScoped<Services.IEventService, EventService>();
}