/// <summary>
        /// Initializes the commands and sets <see cref="CredentialTokens"/> to an empty collection.
        /// The ViewModel must be activated before use.
        /// </summary>
        /// <param name="credentialProvider">Provider to use for accessing stored credentials.</param>
        public SavedCredentialsViewModel(
            ICredentialStorageProvider credentialProvider
            )
        {
            this.credentialProvider = credentialProvider ?? throw new ArgumentNullException(nameof(credentialProvider));

            this.deleteCredentialCommand = new AsyncTypedCommand <string>(
                (token) => token != null,
                async(token) =>
            {
                if (this.allCredentials.Contains(token))
                {
                    await this.credentialProvider.DeleteAsync(token);
                    this.allCredentials.Remove(token);
                }
            }
                );

            this.deleteAllCommand = new AsyncActionCommand(
                async() =>
            {
                await this.credentialProvider.ClearAsync();
                this.allCredentials.Clear();
            }
                );

            this.allCredentials = new ObservableCollection <string>();
        }
Esempio n. 2
0
        public async Task Init()
        {
            // Get database from test attributes
            Utils.DatabaseInfo dbInfo = await Utils.GetDatabaseInfoForTest(TestContext);

            this.dbPassword = dbInfo.Password;
            this.dbKeyFile  = dbInfo.Keyfile;

            // Assert that databases named *ReadOnly* are actually readonly after a clone
            if (dbInfo.Database.Name.IndexOf("ReadOnly", StringComparison.OrdinalIgnoreCase) >= 0)
            {
                Assert.IsFalse(
                    await dbInfo.Database.CheckWritableAsync(),
                    $"This file is expected to be read-only; please verify this before testing: {dbInfo.Database.Name}"
                    );
            }

            this.saveFile = (await dbInfo.Database.AsIStorageFile.CopyAsync(
                                 ApplicationData.Current.TemporaryFolder,
                                 $"PersistenceTestDb-{Guid.NewGuid()}.kdbx",
                                 NameCollisionOption.ReplaceExisting
                                 )).AsWrapper();

            // Use a KdbxReader to parse the database and get a corresponding writer
            KdbxReader reader = new KdbxReader();

            using (IRandomAccessStream stream = await this.saveFile.AsIStorageFile.OpenReadAsync())
            {
                await reader.ReadHeaderAsync(stream, CancellationToken.None);

                KdbxDecryptionResult decryption = await reader.DecryptFileAsync(stream, dbInfo.Password, dbInfo.Keyfile, CancellationToken.None);

                Assert.AreEqual(KdbxParserCode.Success, decryption.Result.Code);
                this.document = decryption.GetDocument();
            }

            // Construct services we can use for the test
            this.writer             = reader.GetWriter();
            this.persistenceService = new DefaultFilePersistenceService(
                this.writer,
                this.writer,
                new StorageFileDatabaseCandidate(this.saveFile, true),
                new MockSyncContext(),
                true
                );
            this.credentialStorage = new MockCredentialProvider();
            this.masterKeyVm       = new MasterKeyChangeViewModel(
                this.document,
                this.saveFile,
                new DatabaseCredentialProvider(this.persistenceService, this.credentialStorage),
                new MockFileService()
                );
            this.settingsVm = new DatabaseSettingsViewModel(this.writer);
        }
 public CredentialStorageFailureEventArgs(
     ICredentialStorageProvider credentialProvider,
     ISavedCredentialsViewModelFactory credentialViewModelFactory,
     IDatabaseCandidate candidate,
     IBuffer credential
     ) : base()
 {
     this.credentialProvider         = credentialProvider ?? throw new ArgumentNullException(nameof(credentialProvider));
     this.credentialViewModelFactory = credentialViewModelFactory ?? throw new ArgumentNullException(nameof(credentialViewModelFactory));
     this.candidate  = candidate ?? throw new ArgumentNullException(nameof(candidate));
     this.credential = credential ?? throw new ArgumentNullException(nameof(credential));
 }
Esempio n. 4
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));
        }
Esempio n. 5
0
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <param name="syncContext">Synchronization context used for marshalling to the UI thread.</param>
        /// <param name="file">The candidate document file.</param>
        /// <param name="isSampleFile">Whether the file is a PassKeep sample.</param>
        /// <param name="futureAccessList">A database access list for persisting permission to the database.</param>
        /// <param name="reader">The IKdbxReader implementation used for parsing document files.</param>
        /// <param name="proxyProvider">Generates file proxies that the app controls.</param>
        /// <param name="candidateFactory">Factory used to generate new candidate files as needed.</param>
        /// <param name="keyChangeVmFactory">Factory used to generate the objects used to modify the master key of the database.</param>
        /// <param name="taskNotificationService">A service used to notify the UI of blocking operations.</param>
        /// <param name="identityService">The service used to verify the user's consent for saving credentials.</param>
        /// <param name="credentialProvider">The provider used to store/load saved credentials.</param>
        /// <param name="credentialViewModelFactory">A factory used to generate <see cref="ISavedCredentialsViewModel"/> instances.</param>
        public DatabaseUnlockViewModel(
            ISyncContext syncContext,
            IDatabaseCandidate file,
            bool isSampleFile,
            IDatabaseAccessList futureAccessList,
            IKdbxReader reader,
            IFileProxyProvider proxyProvider,
            IDatabaseCandidateFactory candidateFactory,
            IMasterKeyChangeViewModelFactory keyChangeVmFactory,
            ITaskNotificationService taskNotificationService,
            IIdentityVerificationService identityService,
            ICredentialStorageProvider credentialProvider,
            ISavedCredentialsViewModelFactory credentialViewModelFactory
            )
        {
            this.syncContext                = syncContext ?? throw new ArgumentNullException(nameof(syncContext));
            this.futureAccessList           = futureAccessList;
            this.kdbxReader                 = reader ?? throw new ArgumentNullException(nameof(reader));
            this.proxyProvider              = proxyProvider ?? throw new ArgumentNullException(nameof(proxyProvider));
            this.candidateFactory           = candidateFactory ?? throw new ArgumentNullException(nameof(candidateFactory));
            this.keyChangeVmFactory         = keyChangeVmFactory ?? throw new ArgumentNullException(nameof(keyChangeVmFactory));
            this.taskNotificationService    = taskNotificationService ?? throw new ArgumentNullException(nameof(taskNotificationService));
            this.identityService            = identityService ?? throw new ArgumentNullException(nameof(identityService));
            this.credentialProvider         = credentialProvider ?? throw new ArgumentNullException(nameof(credentialProvider));
            this.credentialViewModelFactory = credentialViewModelFactory ?? throw new ArgumentNullException(nameof(credentialViewModelFactory));

            SaveCredentials            = false;
            IdentityVerifiability      = UserConsentVerifierAvailability.Available;
            UnlockCommand              = new AsyncActionCommand(CanUnlock, DoUnlockAsync);
            UseSavedCredentialsCommand = new AsyncActionCommand(
                () => UnlockCommand.CanExecute(null) && HasSavedCredentials,
                DoUnlockWithSavedCredentials
                );
            IsSampleFile     = isSampleFile;
            RememberDatabase = true;

            this.initialConstruction = UpdateCandidateFileAsync(file);
        }
 public DatabaseCredentialProviderFactory(ICredentialStorageProvider credentialStorage)
 {
     this.credentialStorage = credentialStorage;
 }
 /// <summary>
 /// Initializes the provider with the provided dependencies.
 /// </summary>
 /// <param name="persistenceService">Used to save the database after updating credentials.</param>
 /// <param name="credentialStorage">Used to manage previously saved credentials.</param>
 public DatabaseCredentialProvider(IDatabasePersistenceService persistenceService, ICredentialStorageProvider credentialStorage)
 {
     this.persistenceService = persistenceService ?? throw new ArgumentNullException(nameof(persistenceService));
     this.credentialStorage  = credentialStorage ?? throw new ArgumentNullException(nameof(credentialStorage));
 }
        public async Task Initialize()
        {
            TestDataAttribute dataAttr = GetTestAttribute <TestDataAttribute>();

            if (dataAttr != null && dataAttr.SkipInitialization)
            {
                return;
            }

            this.testDatabaseInfo = null;
            IDatabaseCandidate databaseValue = null;
            bool sampleValue = false;

            try
            {
                this.testDatabaseInfo = await Utils.GetDatabaseInfoForTest(TestContext);
            }
            catch (InvalidOperationException) { }

            if (dataAttr?.UseRealProxyProvider != true)
            {
                this.proxyProvider = new MockFileProxyProvider
                {
                    ScopeValue = (dataAttr?.InAppScope == true)
                };
            }
            else
            {
                StorageFolder proxyFolder = ApplicationData.Current.TemporaryFolder;
                proxyFolder = await proxyFolder.CreateFolderAsync("Proxies", CreationCollisionOption.OpenIfExists);

                this.proxyProvider = new FileProxyProvider(proxyFolder);
            }

            IDatabaseCandidateFactory candidateFactory = new StorageFileDatabaseCandidateFactory(this.proxyProvider);

            if (this.testDatabaseInfo != null)
            {
                databaseValue = await candidateFactory.AssembleAsync(this.testDatabaseInfo.Database);

                sampleValue = (dataAttr != null && dataAttr.InitSample);
            }

            if (dataAttr != null && !dataAttr.InitDatabase)
            {
                databaseValue = null;
            }

            this.accessList = new MockStorageItemAccessList();

            this.identityService = new MockIdentityVerifier()
            {
                CanVerify = dataAttr?.IdentityVerifierAvailable ?? UserConsentVerifierAvailability.NotConfiguredForUser,
                Verified  = dataAttr?.IdentityVerified ?? false
            };
            this.credentialProvider = new MockCredentialProvider();

            if (dataAttr?.StoredCredentials == true && databaseValue != null && this.testDatabaseInfo != null)
            {
                Assert.IsTrue(
                    await this.credentialProvider.TryStoreRawKeyAsync(
                        databaseValue.File,
                        this.testDatabaseInfo.RawKey
                        )
                    );
            }

            Utils.DatabaseInfo backupDatabase = await Utils.DatabaseMap["StructureTesting"];
            this.alwaysStoredCandidate = await candidateFactory.AssembleAsync(
                backupDatabase.Database
                );

            Assert.IsTrue(
                await this.credentialProvider.TryStoreRawKeyAsync(
                    this.alwaysStoredCandidate.File,
                    backupDatabase.RawKey
                    )
                );

            this.viewModel = new DatabaseUnlockViewModel(
                new MockSyncContext(),
                databaseValue,
                sampleValue,
                this.accessList,
                new KdbxReader(),
                this.proxyProvider,
                candidateFactory,
                new MasterKeyChangeViewModelFactory(new DatabaseCredentialProviderFactory(this.credentialProvider), new MockFileService()),
                new TaskNotificationService(),
                this.identityService,
                this.credentialProvider,
                new MockCredentialStorageViewModelFactory()
                );

            await this.viewModel.ActivateAsync();

            // Set various ViewModel properties if desired
            if (this.testDatabaseInfo != null && dataAttr != null)
            {
                if (dataAttr.SetPassword)
                {
                    this.viewModel.Password = this.testDatabaseInfo.Password;
                }

                if (dataAttr.SetKeyFile)
                {
                    this.viewModel.KeyFile = this.testDatabaseInfo.Keyfile;
                }
            }

            if (databaseValue != null)
            {
                await ViewModelHeaderValidated();
            }
        }