mirror of
https://github.com/bitwarden/server.git
synced 2025-07-04 09:32:48 -05:00
cipher events
This commit is contained in:
@ -1,12 +1,13 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Core.Services
|
||||
{
|
||||
public interface IEventService
|
||||
{
|
||||
Task LogUserEventAsync(Guid userId, EventType type);
|
||||
Task LogUserEventAsync(Guid userId, CurrentContext currentContext, EventType type);
|
||||
Task LogCipherEventAsync(Cipher cipher, EventType type);
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ namespace Bit.Core.Services
|
||||
private readonly ICollectionCipherRepository _collectionCipherRepository;
|
||||
private readonly IPushNotificationService _pushService;
|
||||
private readonly IAttachmentStorageService _attachmentStorageService;
|
||||
private readonly IEventService _eventService;
|
||||
|
||||
public CipherService(
|
||||
ICipherRepository cipherRepository,
|
||||
@ -31,7 +32,8 @@ namespace Bit.Core.Services
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
ICollectionCipherRepository collectionCipherRepository,
|
||||
IPushNotificationService pushService,
|
||||
IAttachmentStorageService attachmentStorageService)
|
||||
IAttachmentStorageService attachmentStorageService,
|
||||
IEventService eventService)
|
||||
{
|
||||
_cipherRepository = cipherRepository;
|
||||
_folderRepository = folderRepository;
|
||||
@ -41,6 +43,7 @@ namespace Bit.Core.Services
|
||||
_collectionCipherRepository = collectionCipherRepository;
|
||||
_pushService = pushService;
|
||||
_attachmentStorageService = attachmentStorageService;
|
||||
_eventService = eventService;
|
||||
}
|
||||
|
||||
public async Task SaveAsync(Cipher cipher, Guid savingUserId, bool orgAdmin = false)
|
||||
@ -53,6 +56,7 @@ namespace Bit.Core.Services
|
||||
if(cipher.Id == default(Guid))
|
||||
{
|
||||
await _cipherRepository.CreateAsync(cipher);
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Created);
|
||||
|
||||
// push
|
||||
await _pushService.PushSyncCipherCreateAsync(cipher);
|
||||
@ -61,6 +65,7 @@ namespace Bit.Core.Services
|
||||
{
|
||||
cipher.RevisionDate = DateTime.UtcNow;
|
||||
await _cipherRepository.ReplaceAsync(cipher);
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Updated);
|
||||
|
||||
// push
|
||||
await _pushService.PushSyncCipherUpdateAsync(cipher);
|
||||
@ -78,6 +83,7 @@ namespace Bit.Core.Services
|
||||
if(cipher.Id == default(Guid))
|
||||
{
|
||||
await _cipherRepository.CreateAsync(cipher);
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Created);
|
||||
|
||||
if(cipher.OrganizationId.HasValue)
|
||||
{
|
||||
@ -92,6 +98,7 @@ namespace Bit.Core.Services
|
||||
{
|
||||
cipher.RevisionDate = DateTime.UtcNow;
|
||||
await _cipherRepository.ReplaceAsync(cipher);
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Updated);
|
||||
|
||||
// push
|
||||
await _pushService.PushSyncCipherUpdateAsync(cipher);
|
||||
@ -159,6 +166,7 @@ namespace Bit.Core.Services
|
||||
};
|
||||
|
||||
await _cipherRepository.UpdateAttachmentAsync(attachment);
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_AttachmentCreated);
|
||||
cipher.AddAttachment(attachmentId, data);
|
||||
}
|
||||
catch
|
||||
@ -222,6 +230,7 @@ namespace Bit.Core.Services
|
||||
|
||||
await _cipherRepository.DeleteAsync(cipher);
|
||||
await _attachmentStorageService.DeleteAttachmentsForCipherAsync(cipher.Id);
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Deleted);
|
||||
|
||||
// push
|
||||
await _pushService.PushSyncCipherDeleteAsync(cipher);
|
||||
@ -249,6 +258,7 @@ namespace Bit.Core.Services
|
||||
await _cipherRepository.DeleteAttachmentAsync(cipher.Id, attachmentId);
|
||||
cipher.DeleteAttachment(attachmentId);
|
||||
await _attachmentStorageService.DeleteAttachmentAsync(cipher.Id, attachmentId);
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_AttachmentDeleted);
|
||||
|
||||
// push
|
||||
await _pushService.PushSyncCipherUpdateAsync(cipher);
|
||||
@ -344,6 +354,7 @@ namespace Bit.Core.Services
|
||||
}
|
||||
|
||||
updatedCipher = true;
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_Shared);
|
||||
|
||||
if(hasAttachments)
|
||||
{
|
||||
@ -413,6 +424,8 @@ namespace Bit.Core.Services
|
||||
await _collectionCipherRepository.UpdateCollectionsAsync(cipher.Id, savingUserId, collectionIds);
|
||||
}
|
||||
|
||||
await _eventService.LogCipherEventAsync(cipher, Enums.EventType.Cipher_UpdatedCollections);
|
||||
|
||||
// push
|
||||
await _pushService.PushSyncCipherUpdateAsync(cipher);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using Bit.Core.Models.Data;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.WindowsAzure.Storage.Table;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Core.Services
|
||||
{
|
||||
@ -13,24 +14,37 @@ namespace Bit.Core.Services
|
||||
{
|
||||
private readonly IEventRepository _eventRepository;
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly CurrentContext _currentContext;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
public EventService(
|
||||
IEventRepository eventRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
CurrentContext currentContext,
|
||||
GlobalSettings globalSettings)
|
||||
{
|
||||
_eventRepository = eventRepository;
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_currentContext = currentContext;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public async Task LogUserEventAsync(Guid userId, EventType type)
|
||||
{
|
||||
var events = new List<ITableEntity> { new UserEvent(userId, type) };
|
||||
var orgs = await _organizationUserRepository.GetManyByUserAsync(userId);
|
||||
var orgEvents = orgs.Where(o => o.Status == OrganizationUserStatusType.Confirmed)
|
||||
.Select(o => new UserEvent(userId, o.Id, type));
|
||||
|
||||
IEnumerable<UserEvent> orgEvents;
|
||||
if(_currentContext.UserId.HasValue)
|
||||
{
|
||||
orgEvents = _currentContext.Organizations.Select(o => new UserEvent(userId, o.Id, type));
|
||||
}
|
||||
else
|
||||
{
|
||||
var orgs = await _organizationUserRepository.GetManyByUserAsync(userId);
|
||||
orgEvents = orgs.Where(o => o.Status == OrganizationUserStatusType.Confirmed)
|
||||
.Select(o => new UserEvent(userId, o.Id, type));
|
||||
}
|
||||
|
||||
if(orgEvents.Any())
|
||||
{
|
||||
events.AddRange(orgEvents);
|
||||
@ -42,19 +56,15 @@ namespace Bit.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
public async Task LogUserEventAsync(Guid userId, CurrentContext currentContext, EventType type)
|
||||
public async Task LogCipherEventAsync(Cipher cipher, EventType type)
|
||||
{
|
||||
var events = new List<ITableEntity> { new UserEvent(userId, type) };
|
||||
var orgEvents = currentContext.Organizations.Select(o => new UserEvent(userId, o.Id, type));
|
||||
if(orgEvents.Any())
|
||||
if(!cipher.OrganizationId.HasValue || (!_currentContext?.UserId.HasValue ?? true))
|
||||
{
|
||||
events.AddRange(orgEvents);
|
||||
await _eventRepository.CreateManyAsync(events);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _eventRepository.CreateAsync(events.First());
|
||||
return;
|
||||
}
|
||||
|
||||
var e = new CipherEvent(cipher, type, _currentContext?.UserId);
|
||||
await _eventRepository.CreateAsync(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,8 +90,7 @@ namespace Bit.Core.Services
|
||||
|
||||
public Guid? GetProperUserId(ClaimsPrincipal principal)
|
||||
{
|
||||
Guid userIdGuid;
|
||||
if(!Guid.TryParse(GetUserId(principal), out userIdGuid))
|
||||
if(!Guid.TryParse(GetUserId(principal), out var userIdGuid))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -107,8 +106,7 @@ namespace Bit.Core.Services
|
||||
return _currentContext.User;
|
||||
}
|
||||
|
||||
Guid userIdGuid;
|
||||
if(!Guid.TryParse(userId, out userIdGuid))
|
||||
if(!Guid.TryParse(userId, out var userIdGuid))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -425,7 +423,7 @@ namespace Bit.Core.Services
|
||||
user.Key = key;
|
||||
|
||||
await _userRepository.ReplaceAsync(user);
|
||||
await _eventService.LogUserEventAsync(user.Id, _currentContext, EventType.User_ChangedPassword);
|
||||
await _eventService.LogUserEventAsync(user.Id, EventType.User_ChangedPassword);
|
||||
|
||||
return IdentityResult.Success;
|
||||
}
|
||||
@ -503,7 +501,7 @@ namespace Bit.Core.Services
|
||||
user.TwoFactorRecoveryCode = CoreHelpers.SecureRandomString(32, upper: false, special: false);
|
||||
}
|
||||
await SaveUserAsync(user);
|
||||
await _eventService.LogUserEventAsync(user.Id, _currentContext, EventType.User_Enabled2fa);
|
||||
await _eventService.LogUserEventAsync(user.Id, EventType.User_Enabled2fa);
|
||||
}
|
||||
|
||||
public async Task DisableTwoFactorProviderAsync(User user, TwoFactorProviderType type)
|
||||
@ -517,7 +515,7 @@ namespace Bit.Core.Services
|
||||
providers.Remove(type);
|
||||
user.SetTwoFactorProviders(providers);
|
||||
await SaveUserAsync(user);
|
||||
await _eventService.LogUserEventAsync(user.Id, _currentContext, EventType.User_Disabled2fa);
|
||||
await _eventService.LogUserEventAsync(user.Id, EventType.User_Disabled2fa);
|
||||
}
|
||||
|
||||
public async Task<bool> RecoverTwoFactorAsync(string email, string masterPassword, string recoveryCode)
|
||||
@ -542,7 +540,7 @@ namespace Bit.Core.Services
|
||||
user.TwoFactorProviders = null;
|
||||
user.TwoFactorRecoveryCode = CoreHelpers.SecureRandomString(32, upper: false, special: false);
|
||||
await SaveUserAsync(user);
|
||||
await _eventService.LogUserEventAsync(user.Id, _currentContext, EventType.User_Recovered2fa);
|
||||
await _eventService.LogUserEventAsync(user.Id, EventType.User_Recovered2fa);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Core.Services
|
||||
{
|
||||
public class NoopEventService : IEventService
|
||||
{
|
||||
public Task LogUserEventAsync(Guid userId, EventType type)
|
||||
public Task LogCipherEventAsync(Cipher cipher, EventType type)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task LogUserEventAsync(Guid userId, CurrentContext currentContext, EventType type)
|
||||
public Task LogUserEventAsync(Guid userId, EventType type)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
Reference in New Issue
Block a user