Exemple #1
0
        /// <summary>
        /// Creates a ViewModel wrapping a brand new KdbxGroup as a child of the specified parent group.
        /// </summary>
        /// <param name="resourceProvider">IResourceProvider for localizing strings.</param>
        /// <param name="navigationViewModel">A ViewModel used for tracking navigation history.</param>
        /// <param name="persistenceService">A service used for persisting the document.</param>
        /// <param name="clipboardService">A service used for accessing the clipboard.</param>
        /// <param name="settingsService">A service used for accessing app settings.</param>
        /// <param name="document">A KdbxDocument representing the database we are working on.</param>
        /// <param name="parentGroup">The IKeePassGroup to use as a parent for the new group.</param>
        /// <param name="rng">A random number generator used to protect strings in memory.</param>
        public EntryDetailsViewModel(
            IResourceProvider resourceProvider,
            IDatabaseNavigationViewModel navigationViewModel,
            IDatabasePersistenceService persistenceService,
            ISensitiveClipboardService clipboardService,
            IAppSettingsService settingsService,
            KdbxDocument document,
            IKeePassGroup parentGroup,
            IRandomNumberGenerator rng
            ) : this(
                resourceProvider,
                navigationViewModel,
                persistenceService,
                clipboardService,
                settingsService,
                document,
                new KdbxEntry(parentGroup, rng, document.Metadata),
                true,
                false,
                rng
                )
        {
            if (parentGroup == null)
            {
                throw new ArgumentNullException(nameof(parentGroup));
            }

            if (rng == null)
            {
                throw new ArgumentNullException(nameof(rng));
            }
        }
Exemple #2
0
 /// <summary>
 /// Creates a ViewModel wrapping a brand new KdbxGroup as a child of the specified parent group.
 /// </summary>
 /// <param name="navigationViewModel">A ViewModel used for tracking navigation history.</param>
 /// <param name="persistenceService">A service used for persisting the document.</param>
 /// <param name="document">A KdbxDocument representing the database we are working on.</param>
 /// <param name="parentGroup">The IKeePassGroup to use as a parent for the new group.</param>
 public GroupDetailsViewModel(
     IDatabaseNavigationViewModel navigationViewModel,
     IDatabasePersistenceService persistenceService,
     KdbxDocument document,
     IKeePassGroup parentGroup
     ) : base(navigationViewModel, persistenceService, document, new KdbxGroup(parentGroup), true, false)
 {
     if (parentGroup == null)
     {
         throw new ArgumentNullException("parentGroup");
     }
 }
Exemple #3
0
 /// <summary>
 /// Creates a ViewModel wrapping an existing KdbxGroup.
 /// <param name="navigationViewModel">A ViewModel used for tracking navigation history.</param>
 /// <param name="persistenceService">A service used for persisting the document.</param>
 /// <param name="document">A KdbxDocument representing the database we are working on.</param>
 /// <param name="groupToEdit">The group being viewed.</param>
 /// <param name="isReadOnly">Whether to open the group in read-only mode.</param>
 public GroupDetailsViewModel(
     IDatabaseNavigationViewModel navigationViewModel,
     IDatabasePersistenceService persistenceService,
     KdbxDocument document,
     IKeePassGroup groupToEdit,
     bool isReadOnly
     ) : base(navigationViewModel, persistenceService, document, groupToEdit, false, isReadOnly)
 {
     if (groupToEdit == null)
     {
         throw new ArgumentNullException("groupToEdit");
     }
 }
Exemple #4
0
 /// <summary>
 /// Creates a ViewModel wrapping an existing KdbxGroup.
 /// </summary>
 /// <param name="resourceProvider">IResourceProvider for localizing strings.</param>
 /// <param name="navigationViewModel">A ViewModel used for tracking navigation history.</param>
 /// <param name="persistenceService">A service used for persisting the document.</param>
 /// <param name="clipboardService">A service used for accessing the clipboard.</param>
 /// <param name="settingsService">A service used to access app settings.</param>
 /// <param name="document">A KdbxDocument representing the database we are working on.</param>
 /// <param name="entryToEdit">The entry being viewed.</param>
 /// <param name="isReadOnly">Whether to open the group in read-only mode.</param>
 /// <param name="rng">A random number generator used to protect strings in memory.</param>
 public EntryDetailsViewModel(
     IResourceProvider resourceProvider,
     IDatabaseNavigationViewModel navigationViewModel,
     IDatabasePersistenceService persistenceService,
     ISensitiveClipboardService clipboardService,
     IAppSettingsService settingsService,
     KdbxDocument document,
     IKeePassEntry entryToEdit,
     bool isReadOnly,
     IRandomNumberGenerator rng
     ) : this(resourceProvider, navigationViewModel, persistenceService, clipboardService, settingsService, document, entryToEdit, false, isReadOnly, rng)
 {
     if (entryToEdit == null)
     {
         throw new ArgumentNullException(nameof(entryToEdit));
     }
 }
Exemple #5
0
        /// <summary>
        /// Initializes the instance.
        /// </summary>
        /// <param name="syncContext">Context to use for marshalling to the UI thread.</param>
        /// <param name="timerFactory">Used to create a timer.</param>
        /// <param name="file">The file on disk represented by this database.</param>
        /// <param name="fileIsSample">Whether this file is a sample file.</param>
        /// <param name="document">The decrypted database.</param>
        /// <param name="resourceProvider">A IResourceProvider for the View.</param>
        /// <param name="rng">A random number generator used to protect strings.</param>
        /// <param name="navigationViewModel">A ViewModel representing the navigation of the database.</param>
        /// <param name="masterKeyViewModel">A ViewModel that allows configuring the database's master key.</param>
        /// <param name="persistenceService">A service used to save the database.</param>
        /// <param name="identityService">A service used to authenticate the user.</param>
        /// <param name="credentialStorage">A service used to update saved credentials.</param>
        /// <param name="settingsService">A service used to access app settings.</param>
        /// <param name="clipboardService">A service used to access the clipboard for credentials.</param>
        public DatabaseParentViewModel(
            ISyncContext syncContext,
            ITimerFactory timerFactory,
            ITestableFile file,
            bool fileIsSample,
            KdbxDocument document,
            IResourceProvider resourceProvider,
            IRandomNumberGenerator rng,
            IDatabaseNavigationViewModel navigationViewModel,
            IMasterKeyViewModel masterKeyViewModel,
            IDatabasePersistenceService persistenceService,
            IIdentityVerificationService identityService,
            ICredentialStorageProvider credentialStorage,
            IAppSettingsService settingsService,
            ISensitiveClipboardService clipboardService
            ) : base(document, persistenceService)
        {
            if (timerFactory == null)
            {
                throw new ArgumentNullException(nameof(timerFactory));
            }

            this.syncContext = syncContext ?? throw new ArgumentNullException(nameof(syncContext));
            this.idleTimer   = timerFactory.Assemble(TimeSpan.FromSeconds(1));

            this.file             = file ?? throw new ArgumentNullException(nameof(file));
            this.fileIsSample     = fileIsSample;
            this.document         = document ?? throw new ArgumentNullException(nameof(document));
            this.resourceProvider = resourceProvider ?? throw new ArgumentNullException(nameof(resourceProvider));
            this.rng = rng ?? throw new ArgumentNullException(nameof(rng));
            this.navigationViewModel = navigationViewModel ?? throw new ArgumentNullException(nameof(navigationViewModel));
            this.settingsViewModel   = new DatabaseSettingsViewModel(PersistenceService.SettingsProvider);
            this.masterKeyViewModel  = masterKeyViewModel ?? throw new ArgumentNullException(nameof(masterKeyViewModel));
            this.identityService     = identityService ?? throw new ArgumentNullException(nameof(identityService));
            this.credentialProvider  = credentialStorage ?? throw new ArgumentNullException(nameof(credentialStorage));
            this.settingsService     = settingsService ?? throw new ArgumentNullException(nameof(settingsService));
            this.clipboardService    = clipboardService ?? throw new ArgumentNullException(nameof(clipboardService));
        }
Exemple #6
0
        public async Task Initialize()
        {
            try
            {
                CancellationTokenSource cts = new CancellationTokenSource();

                Utils.DatabaseInfo databaseInfo = await Utils.GetDatabaseInfoForTest(TestContext);

                KdbxReader reader = new KdbxReader();

                using (IRandomAccessStream stream = await databaseInfo.Database.AsIStorageFile.OpenReadAsync())
                {
                    Assert.IsFalse((await reader.ReadHeaderAsync(stream, cts.Token)).IsError);
                    KdbxDecryptionResult decryption = await reader.DecryptFileAsync(stream, databaseInfo.Password, databaseInfo.Keyfile, cts.Token);

                    Assert.IsFalse(decryption.Result.IsError);
                    this.document = decryption.GetDocument();
                }
            }
            catch (InvalidOperationException) { }

            this.viewModel = new DatabaseNavigationViewModel();
        }
        /// <summary>
        /// Initializes the base class from a subclass.
        /// </summary>
        /// <param name="navigationViewModel">A ViewModel used for tracking navigation history.</param>
        /// <param name="persistenceService">A service used for persisting the document.</param>
        /// <param name="document">A KdbxDocument representing the database we are working on.</param>
        /// <param name="item">The item this ViewModel wraps.</param>
        /// <param name="isNew">Whether the child is being created for the first time.</param>
        /// <param name="isReadOnly">Whether the child is being accessed as read-only.</param>
        protected NodeDetailsViewModel(
            IDatabaseNavigationViewModel navigationViewModel,
            IDatabasePersistenceService persistenceService,
            KdbxDocument document,
            T item,
            bool isNew,
            bool isReadOnly
            ) : base(document, persistenceService)
        {
            if (isNew && item.Parent == null)
            {
                throw new ArgumentException("Cannot create a new node with no parent!");
            }

            if (navigationViewModel.ActiveGroup != item.Parent)
            {
                throw new ArgumentException("The database's active group must be the node's parent!");
            }

            NavigationViewModel = navigationViewModel ?? throw new ArgumentNullException(nameof(navigationViewModel));
            Document            = document ?? throw new ArgumentNullException(nameof(document));
            IsNew = isNew;

            if (!isNew)
            {
                this.masterCopy = GetClone(item);
                WorkingCopy     = GetClone(this.masterCopy);
            }
            else
            {
                this.masterCopy = null;
                WorkingCopy     = GetClone(item);
            }

            IsReadOnly = isReadOnly;
        }
Exemple #8
0
        /// <summary>
        /// Provides a means of the parent page requesting a navigate from a clicked breadcrumb to the specified group.
        /// </summary>
        /// <remarks>
        /// This allows the page to preempt the navigate or do necessary cleanup.
        /// </remarks>
        /// <param name="dbViewModel">The DatabaseViewModel to use for the navigation.</param>
        /// <param name="navViewModel">The NavigationViewModel to update.</param>
        /// <param name="clickedGroup">The group to navigate to.</param>
        public override Task RequestBreadcrumbNavigation(IDatabaseViewModel dbViewModel, IDatabaseNavigationViewModel navViewModel, IKeePassGroup clickedGroup)
        {
            Action navCallback = () =>
            {
                navViewModel.SetGroup(clickedGroup);
            };

            Frame.Navigate(typeof(DatabaseView), new CancellableNavigationParameter(navCallback, dbViewModel));
            return(Task.FromResult <object>(null));
        }
Exemple #9
0
        /// <summary>
        /// Passes provided parameters to the base constructor and initializes commands.
        /// </summary>
        /// <param name="resourceProvider">IResourceProvider for localizing strings.</param>
        /// <param name="navigationViewModel"></param>
        /// <param name="persistenceService"></param>
        /// <param name="clipboardService"></param>
        /// <param name="settingsService"></param>
        /// <param name="document"></param>
        /// <param name="entry"></param>
        /// <param name="isNew"></param>
        /// <param name="isReadOnly"></param>
        /// <param name="rng"></param>
        private EntryDetailsViewModel(
            IResourceProvider resourceProvider,
            IDatabaseNavigationViewModel navigationViewModel,
            IDatabasePersistenceService persistenceService,
            ISensitiveClipboardService clipboardService,
            IAppSettingsService settingsService,
            KdbxDocument document,
            IKeePassEntry entry,
            bool isNew,
            bool isReadOnly,
            IRandomNumberGenerator rng
            ) : base(navigationViewModel, persistenceService, document, entry, isNew, isReadOnly)
        {
            this.resourceProvider = resourceProvider;
            this.clipboardService = clipboardService;
            this.settingsService  = settingsService;
            this.rng = rng;

            this.copyFieldValueCommand = new TypedCommand <IProtectedString>(
                str =>
            {
                clipboardService.CopyCredential(str.ClearValue, ClipboardOperationType.Other);
            }
                );

            this.deleteFieldCommand = new TypedCommand <IProtectedString>(
                str => !IsReadOnly && PersistenceService.CanSave,
                str =>
            {
                DebugHelper.Assert(!IsReadOnly);
                WorkingCopy.Fields.Remove(str);
            }
                );

            this.editFieldCommand = new AsyncTypedCommand <IProtectedString>(
                str => PersistenceService.CanSave,
                async str =>
            {
                IsReadOnly = false;
                await UpdateFieldEditorViewModel(new FieldEditorViewModel(str, this.resourceProvider));
            }
                );

            this.newFieldCommand = new AsyncActionCommand(
                () => PersistenceService.CanSave,
                async() =>
            {
                IsReadOnly = false;
                await UpdateFieldEditorViewModel(new FieldEditorViewModel(this.rng, this.resourceProvider));
            }
                );

            this.commitFieldCommand = new AsyncActionCommand(
                () => FieldEditorViewModel?.CommitCommand.CanExecute(WorkingCopy) ?? false,
                async() =>
            {
                FieldEditorViewModel.CommitCommand.Execute(WorkingCopy);
                await UpdateFieldEditorViewModel(null);
            }
                );

            PropertyChanged += (s, e) =>
            {
                if (e.PropertyName == nameof(IsReadOnly))
                {
                    ((TypedCommand <IProtectedString>)DeleteFieldCommand).RaiseCanExecuteChanged();
                }
                else if (e.PropertyName == nameof(WorkingCopy))
                {
                    OnPropertyChanged(nameof(WorkingCopyViewModel));
                }
            };
        }
Exemple #10
0
        /// <summary>
        /// Provides a means of the parent page requesting a navigate from a clicked breadcrumb to the specified group.
        /// </summary>
        /// <remarks>
        /// This doesn't actually navigate, just updates the navViewModel.
        /// </remarks>
        /// <param name="dbViewModel">The DatabaseViewModel to use for the navigation.</param>
        /// <param name="navViewModel">The NavigationViewModel to update.</param>
        /// <param name="clickedGroup">The group to navigate to.</param>
        public override Task RequestBreadcrumbNavigation(IDatabaseViewModel dbViewModel, IDatabaseNavigationViewModel navViewModel, IKeePassGroup clickedGroup)
        {
            navViewModel.SetGroup(clickedGroup);

            // Task.CompletedTask is better here but not available presently.
            return(Task.FromResult(0));
        }
Exemple #11
0
 /// <summary>
 /// Generats a ViewModel representing an existing child in the DOM.
 /// </summary>
 /// <param name="navigationViewModel"></param>
 /// <param name="persistenceService"></param>
 /// <param name="document"></param>
 /// <param name="openForReadOnly"></param>
 /// <returns>A ViewModel representing an existing child in the DOM.</returns>
 protected abstract TViewModel GetExistingViewModel(
     IDatabaseNavigationViewModel navigationViewModel,
     IDatabasePersistenceService persistenceService,
     KdbxDocument document,
     bool openForReadOnly
     );
Exemple #12
0
 /// <summary>
 /// Generates a ViewModel representing a new child.
 /// </summary>
 /// <param name="navigationViewModel"></param>
 /// <param name="persistenceService"></param>
 /// <param name="document"></param>
 /// <param name="parent"></param>
 /// <returns>A ViewModel representing a new child not already in the tree.</returns>
 protected abstract TViewModel GetNewViewModel(
     IDatabaseNavigationViewModel navigationViewModel,
     IDatabasePersistenceService persistenceService,
     KdbxDocument document,
     IKeePassGroup parent
     );
 /// <summary>
 /// Provides a means of the parent page requesting a navigate from a clicked breadcrumb to the specified group.
 /// </summary>
 /// <remarks>
 /// This allows the page to preempt the navigate or do necessary cleanup.
 /// </remarks>
 /// <param name="dbViewModel">The DatabaseViewModel to use for the navigation.</param>
 /// <param name="navViewModel">The NavigationViewModel to update.</param>
 /// <param name="clickedGroup">The group to navigate to.</param>
 /// <returns>A Task representing the request.</returns>
 public abstract Task RequestBreadcrumbNavigation(IDatabaseViewModel dbViewModel, IDatabaseNavigationViewModel navViewModel, IKeePassGroup clickedGroup);