/// <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>(); }
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)); }
/// <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)); }
/// <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(); } }