log some events

This commit is contained in:
Kyle Spearrin 2019-07-12 17:29:40 -04:00
parent df2af5459e
commit 38d702b6fe
8 changed files with 121 additions and 8 deletions

View File

@ -120,6 +120,7 @@
<Compile Include="Push\FirebaseInstanceIdService.cs" />
<Compile Include="Push\FirebaseMessagingService.cs" />
<Compile Include="Receivers\ClearClipboardAlarmReceiver.cs" />
<Compile Include="Receivers\EventUploadReceiver.cs" />
<Compile Include="Receivers\LockAlarmReceiver.cs" />
<Compile Include="Receivers\PackageReplacedReceiver.cs" />
<Compile Include="Renderers\CipherViewCellRenderer.cs" />

View File

@ -39,8 +39,10 @@ namespace Bit.Droid
private IAppIdService _appIdService;
private IStorageService _storageService;
private IStateService _stateService;
private IEventService _eventService;
private PendingIntent _lockAlarmPendingIntent;
private PendingIntent _clearClipboardPendingIntent;
private PendingIntent _eventUploadPendingIntent;
private AppOptions _appOptions;
private string _activityKey = $"{nameof(MainActivity)}_{Java.Lang.JavaSystem.CurrentTimeMillis().ToString()}";
private Java.Util.Regex.Pattern _otpPattern =
@ -48,6 +50,9 @@ namespace Bit.Droid
protected override void OnCreate(Bundle savedInstanceState)
{
var eventUploadIntent = new Intent(this, typeof(EventUploadReceiver));
_eventUploadPendingIntent = PendingIntent.GetBroadcast(this, 0, eventUploadIntent,
PendingIntentFlags.UpdateCurrent);
var alarmIntent = new Intent(this, typeof(LockAlarmReceiver));
_lockAlarmPendingIntent = PendingIntent.GetBroadcast(this, 0, alarmIntent,
PendingIntentFlags.UpdateCurrent);
@ -65,6 +70,7 @@ namespace Bit.Droid
_appIdService = ServiceContainer.Resolve<IAppIdService>("appIdService");
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
_eventService = ServiceContainer.Resolve<IEventService>("eventService");
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
@ -91,10 +97,10 @@ namespace Bit.Droid
{
if(message.Command == "scheduleLockTimer")
{
var alarmManager = GetSystemService(AlarmService) as AlarmManager;
var lockOptionMinutes = (int)message.Data;
var lockOptionMs = lockOptionMinutes * 60000;
var triggerMs = Java.Lang.JavaSystem.CurrentTimeMillis() + lockOptionMs + 10;
var alarmManager = GetSystemService(AlarmService) as AlarmManager;
alarmManager.Set(AlarmType.RtcWakeup, triggerMs, _lockAlarmPendingIntent);
}
else if(message.Command == "cancelLockTimer")
@ -102,6 +108,14 @@ namespace Bit.Droid
var alarmManager = GetSystemService(AlarmService) as AlarmManager;
alarmManager.Cancel(_lockAlarmPendingIntent);
}
else if(message.Command == "startEventTimer")
{
StartEventAlarm();
}
else if(message.Command == "stopEventTimer")
{
var task = StopEventAlarmAsync();
}
else if(message.Command == "finishMainActivity")
{
Xamarin.Forms.Device.BeginInvokeOnMainThread(() => Finish());
@ -372,5 +386,18 @@ namespace Bit.Droid
var alarmManager = GetSystemService(AlarmService) as AlarmManager;
alarmManager.Set(AlarmType.Rtc, triggerMs, _clearClipboardPendingIntent);
}
private void StartEventAlarm()
{
var alarmManager = GetSystemService(AlarmService) as AlarmManager;
alarmManager.SetInexactRepeating(AlarmType.ElapsedRealtime, 120000, 300000, _eventUploadPendingIntent);
}
private async Task StopEventAlarmAsync()
{
var alarmManager = GetSystemService(AlarmService) as AlarmManager;
alarmManager.Cancel(_eventUploadPendingIntent);
await _eventService.UploadEventsAsync();
}
}
}

View File

@ -0,0 +1,16 @@
using Android.Content;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
namespace Bit.Droid.Receivers
{
[BroadcastReceiver(Name = "com.x8bit.bitwarden.EventUploadReceiver", Exported = false)]
public class EventUploadReceiver : BroadcastReceiver
{
public async override void OnReceive(Context context, Intent intent)
{
var eventService = ServiceContainer.Resolve<IEventService>("eventService");
await eventService.UploadEventsAsync();
}
}
}

View File

@ -173,6 +173,7 @@ namespace Bit.App
SyncIfNeeded();
}
}
_messagingService.Send("startEventTimer");
}
protected async override void OnSleep()
@ -184,6 +185,7 @@ namespace Bit.App
}
SetTabsPageFromAutofill();
await HandleLockingAsync();
_messagingService.Send("stopEventTimer");
}
protected override void OnResume()
@ -198,6 +200,7 @@ namespace Bit.App
private async void ResumedAsync()
{
_messagingService.Send("cancelLockTimer");
_messagingService.Send("startEventTimer");
await ClearCacheIfNeededAsync();
await TryClearCiphersCacheAsync();
Prime();

View File

@ -23,6 +23,7 @@ namespace Bit.App.Pages
private readonly IPlatformUtilsService _platformUtilsService;
private readonly IAuditService _auditService;
private readonly IMessagingService _messagingService;
private readonly IEventService _eventService;
private CipherView _cipher;
private bool _showNotesSeparator;
private bool _showPassword;
@ -34,6 +35,7 @@ namespace Bit.App.Pages
private int _folderSelectedIndex;
private int _ownershipSelectedIndex;
private bool _hasCollections;
private string _previousCipherId;
private List<Core.Models.View.CollectionView> _writeableCollections;
private string[] _additionalCipherProperties = new string[]
{
@ -74,6 +76,7 @@ namespace Bit.App.Pages
_auditService = ServiceContainer.Resolve<IAuditService>("auditService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_collectionService = ServiceContainer.Resolve<ICollectionService>("collectionService");
_eventService = ServiceContainer.Resolve<IEventService>("eventService");
GeneratePasswordCommand = new Command(GeneratePassword);
TogglePasswordCommand = new Command(TogglePassword);
ToggleCardCodeCommand = new Command(ToggleCardCode);
@ -365,9 +368,16 @@ namespace Bit.App.Pages
}
if(Cipher.Fields != null)
{
Fields.ResetWithRange(Cipher.Fields?.Select(f => new AddEditPageFieldViewModel(f)));
Fields.ResetWithRange(Cipher.Fields?.Select(f => new AddEditPageFieldViewModel(Cipher, f)));
}
}
if(EditMode && _previousCipherId != CipherId)
{
var task = _eventService.CollectAsync(EventType.Cipher_ClientViewed, CipherId);
}
_previousCipherId = CipherId;
return true;
}
@ -591,7 +601,7 @@ namespace Bit.App.Pages
Fields = new ExtendedObservableCollection<AddEditPageFieldViewModel>();
}
var type = _fieldTypeOptions.FirstOrDefault(f => f.Value == typeSelection).Key;
Fields.Add(new AddEditPageFieldViewModel(new FieldView
Fields.Add(new AddEditPageFieldViewModel(Cipher, new FieldView
{
Type = type,
Name = string.IsNullOrWhiteSpace(name) ? null : name
@ -602,11 +612,19 @@ namespace Bit.App.Pages
public void TogglePassword()
{
ShowPassword = !ShowPassword;
if(EditMode && ShowPassword)
{
var task = _eventService.CollectAsync(EventType.Cipher_ClientToggledPasswordVisible, CipherId);
}
}
public void ToggleCardCode()
{
ShowCardCode = !ShowCardCode;
if(EditMode && ShowCardCode)
{
var task = _eventService.CollectAsync(EventType.Cipher_ClientToggledCardCodeVisible, CipherId);
}
}
public async Task UpdateTotpKeyAsync(string key)
@ -720,6 +738,7 @@ namespace Bit.App.Pages
public class AddEditPageFieldViewModel : ExtendedViewModel
{
private FieldView _field;
private CipherView _cipher;
private bool _showHiddenValue;
private bool _booleanValue;
private string[] _additionalFieldProperties = new string[]
@ -729,8 +748,9 @@ namespace Bit.App.Pages
nameof(IsTextType),
};
public AddEditPageFieldViewModel(FieldView field)
public AddEditPageFieldViewModel(CipherView cipher, FieldView field)
{
_cipher = cipher;
Field = field;
ToggleHiddenValueCommand = new Command(ToggleHiddenValue);
BooleanValue = IsBooleanType && field.Value == "true";
@ -775,6 +795,11 @@ namespace Bit.App.Pages
public void ToggleHiddenValue()
{
ShowHiddenValue = !ShowHiddenValue;
if(ShowHiddenValue && _cipher?.Id != null)
{
var eventService = ServiceContainer.Resolve<IEventService>("eventService");
var task = eventService.CollectAsync(EventType.Cipher_ClientToggledHiddenFieldVisible, _cipher.Id);
}
}
public void TriggerFieldChanged()

View File

@ -22,6 +22,7 @@ namespace Bit.App.Pages
private readonly IPlatformUtilsService _platformUtilsService;
private readonly IAuditService _auditService;
private readonly IMessagingService _messagingService;
private readonly IEventService _eventService;
private CipherView _cipher;
private List<ViewPageFieldViewModel> _fields;
private bool _canAccessPremium;
@ -32,6 +33,7 @@ namespace Bit.App.Pages
private string _totpSec;
private bool _totpLow;
private DateTime? _totpInterval = null;
private string _previousCipherId;
public ViewPageViewModel()
{
@ -42,6 +44,7 @@ namespace Bit.App.Pages
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
_auditService = ServiceContainer.Resolve<IAuditService>("auditService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_eventService = ServiceContainer.Resolve<IEventService>("eventService");
CopyCommand = new Command<string>((id) => CopyAsync(id, null));
CopyUriCommand = new Command<LoginUriView>(CopyUri);
CopyFieldCommand = new Command<FieldView>(CopyField);
@ -217,7 +220,7 @@ namespace Bit.App.Pages
}
Cipher = await cipher.DecryptAsync();
CanAccessPremium = await _userService.CanAccessPremiumAsync();
Fields = Cipher.Fields?.Select(f => new ViewPageFieldViewModel(f)).ToList();
Fields = Cipher.Fields?.Select(f => new ViewPageFieldViewModel(Cipher, f)).ToList();
if(Cipher.Type == Core.Enums.CipherType.Login && !string.IsNullOrWhiteSpace(Cipher.Login.Totp) &&
(Cipher.OrganizationUseTotp || CanAccessPremium))
@ -236,6 +239,11 @@ namespace Bit.App.Pages
return true;
});
}
if(_previousCipherId != CipherId)
{
var task = _eventService.CollectAsync(Core.Enums.EventType.Cipher_ClientViewed, CipherId);
}
_previousCipherId = CipherId;
finishedLoadingAction?.Invoke();
return true;
}
@ -248,11 +256,20 @@ namespace Bit.App.Pages
public void TogglePassword()
{
ShowPassword = !ShowPassword;
if(ShowPassword)
{
var task = _eventService.CollectAsync(Core.Enums.EventType.Cipher_ClientToggledPasswordVisible, CipherId);
}
}
public void ToggleCardCode()
{
ShowCardCode = !ShowCardCode;
if(ShowCardCode)
{
var task = _eventService.CollectAsync(
Core.Enums.EventType.Cipher_ClientToggledCardCodeVisible, CipherId);
}
}
public async Task<bool> DeleteAsync()
@ -434,7 +451,7 @@ namespace Bit.App.Pages
{
name = AppResources.URI;
}
else if(id == "FieldValue")
else if(id == "FieldValue" || id == "H_FieldValue")
{
name = AppResources.Value;
}
@ -456,6 +473,18 @@ namespace Bit.App.Pages
{
_platformUtilsService.ShowToast("info", null, string.Format(AppResources.ValueHasBeenCopied, name));
}
if(id == "LoginPassword")
{
await _eventService.CollectAsync(Core.Enums.EventType.Cipher_ClientCopiedPassword, CipherId);
}
else if(id == "CardCode")
{
await _eventService.CollectAsync(Core.Enums.EventType.Cipher_ClientCopiedCardCode, CipherId);
}
else if(id == "H_FieldValue")
{
await _eventService.CollectAsync(Core.Enums.EventType.Cipher_ClientCopiedHiddenField, CipherId);
}
}
}
@ -466,7 +495,7 @@ namespace Bit.App.Pages
private void CopyField(FieldView field)
{
CopyAsync("FieldValue", field.Value);
CopyAsync(field.Type == Core.Enums.FieldType.Hidden ? "H_FieldValue" : "FieldValue", field.Value);
}
private void LaunchUri(LoginUriView uri)
@ -481,10 +510,12 @@ namespace Bit.App.Pages
public class ViewPageFieldViewModel : ExtendedViewModel
{
private FieldView _field;
private CipherView _cipher;
private bool _showHiddenValue;
public ViewPageFieldViewModel(FieldView field)
public ViewPageFieldViewModel(CipherView cipher, FieldView field)
{
_cipher = cipher;
Field = field;
ToggleHiddenValueCommand = new Command(ToggleHiddenValue);
}
@ -526,6 +557,12 @@ namespace Bit.App.Pages
public void ToggleHiddenValue()
{
ShowHiddenValue = !ShowHiddenValue;
if(ShowHiddenValue)
{
var eventService = ServiceContainer.Resolve<IEventService>("eventService");
var task = eventService.CollectAsync(
Core.Enums.EventType.Cipher_ClientToggledHiddenFieldVisible, _cipher.Id);
}
}
}
}

View File

@ -16,6 +16,7 @@ namespace Bit.App.Utilities
public static async Task<string> CipherListOptions(ContentPage page, CipherView cipher)
{
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
var eventService = ServiceContainer.Resolve<IEventService>("eventService");
var options = new List<string> { AppResources.View, AppResources.Edit };
if(cipher.Type == Core.Enums.CipherType.Login)
{
@ -79,6 +80,7 @@ namespace Bit.App.Utilities
await platformUtilsService.CopyToClipboardAsync(cipher.Login.Password);
platformUtilsService.ShowToast("info", null,
string.Format(AppResources.ValueHasBeenCopied, AppResources.Password));
var task = eventService.CollectAsync(Core.Enums.EventType.Cipher_ClientCopiedPassword, cipher.Id);
}
else if(selection == AppResources.CopyTotp)
{
@ -106,6 +108,7 @@ namespace Bit.App.Utilities
await platformUtilsService.CopyToClipboardAsync(cipher.Card.Code);
platformUtilsService.ShowToast("info", null,
string.Format(AppResources.ValueHasBeenCopied, AppResources.SecurityCode));
var task = eventService.CollectAsync(Core.Enums.EventType.Cipher_ClientCopiedCardCode, cipher.Id);
}
else if(selection == AppResources.CopyNotes)
{

View File

@ -43,5 +43,6 @@
Organization_Updated = 1600,
Organization_PurgedVault = 1601,
// Organization_ClientExportedVault = 1602,
}
}