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:
parent
a8fefb54c4
commit
28770d3761
@ -135,7 +135,7 @@ namespace Bit.Api.Controllers
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
await _collectionRepository.DeleteAsync(collection);
|
||||
await _collectionService.DeleteAsync(collection);
|
||||
}
|
||||
|
||||
[HttpDelete("{id}/user/{orgUserId}")]
|
||||
|
@ -121,7 +121,7 @@ namespace Bit.Api.Controllers
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
await _groupRepository.DeleteAsync(group);
|
||||
await _groupService.DeleteAsync(group);
|
||||
}
|
||||
|
||||
[HttpDelete("{id}/user/{orgUserId}")]
|
||||
|
@ -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}")]
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
23
src/Core/Models/Data/CollectionEvent.cs
Normal file
23
src/Core/Models/Data/CollectionEvent.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
23
src/Core/Models/Data/GroupEvent.cs
Normal file
23
src/Core/Models/Data/GroupEvent.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
24
src/Core/Models/Data/OrganizationUserEvent.cs
Normal file
24
src/Core/Models/Data/OrganizationUserEvent.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -8,5 +8,6 @@ namespace Bit.Core.Services
|
||||
public interface IGroupService
|
||||
{
|
||||
Task SaveAsync(Group group, IEnumerable<SelectionReadOnly> collections = null);
|
||||
Task DeleteAsync(Group group);
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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>();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user