public void TestLoadEditSaveWithSyncOverwriteBecauseOfNoCheck() { //create the default database: IKp2aApp app = SetupAppWithDefaultDatabase(); //save it and reload it so we have a base version SaveDatabase(app); app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //load it once again: IKp2aApp app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //modify the database by adding a group in both databases: app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true); var group2 = new PwGroup(true, true, "TestGroup2", PwIcon.Energy); app2.GetDb().KpDatabase.RootGroup.AddGroup(group2, true); //save the database from app 1: SaveDatabase(app); //the user doesn't want to perform check for file change: ((TestKp2aApp)app2).SetPreference(PreferenceKey.CheckForFileChangesOnSave, false); //save the database from app 2: This save operation must detect the changes made from app 1 and ask if it should sync: SaveDatabase(app2); //make sure no question was asked Assert.AreEqual(null, ((TestKp2aApp)app2).LastYesNoCancelQuestionTitle); //load database to a new app instance: IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //ensure the sync was NOT performed (overwrite expected!): AssertDatabasesAreEqual(app2.GetDb().KpDatabase, resultApp.GetDb().KpDatabase); }
public void TestLoadEditSaveWithSyncConflict() { //create the default database: IKp2aApp app = SetupAppWithDefaultDatabase(); //save it and reload it so we have a base version SaveDatabase(app); app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //load it once again: IKp2aApp app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //modify the database by renaming the same group in both databases: app.GetDb().KpDatabase.RootGroup.Groups.Single(g => g.Name == "Internet").Name += "abc"; app2.GetDb().KpDatabase.RootGroup.Groups.Single(g => g.Name == "Internet").Name += "abcde"; //app1 also changes the master password: var compositeKey = app.GetDb().KpDatabase.MasterKey; compositeKey.RemoveUserKey(compositeKey.GetUserKey(typeof(KcpPassword))); compositeKey.AddUserKey(new KcpPassword("abc")); //save the database from app 1: SaveDatabase(app); ((TestKp2aApp)app2).SetYesNoCancelResult(TestKp2aApp.YesNoCancelResult.Yes); //save the database from app 2: This save operation must fail because the target file cannot be loaded: Assert.IsFalse(TrySaveDatabase(app2)); //make sure the right question was asked Assert.AreEqual(UiStringKey.TitleSyncQuestion, ((TestKp2aApp)app2).LastYesNoCancelQuestionTitle); }
public void TestLoadEditSaveWithSyncCancel() { //create the default database: IKp2aApp app = SetupAppWithDefaultDatabase(); //save it and reload it so we have a base version SaveDatabase(app); app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //load it once again: IKp2aApp app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //modify the database by adding a group in both databases: app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true); var group2 = new PwGroup(true, true, "TestGroup2", PwIcon.Energy); app2.GetDb().KpDatabase.RootGroup.AddGroup(group2, true); //save the database from app 1: SaveDatabase(app); //the user clicks the "cancel" button when asked if the sync should be performed ((TestKp2aApp)app2).SetYesNoCancelResult(TestKp2aApp.YesNoCancelResult.Cancel); //save the database from app 2: This save operation must detect the changes made from app 1 and ask if it should sync: Assert.AreEqual(false, TrySaveDatabase(app2)); //make sure the right question was asked Assert.AreEqual(UiStringKey.TitleSyncQuestion, ((TestKp2aApp)app2).LastYesNoCancelQuestionTitle); //load database to a new app instance: IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //ensure the sync was NOT performed (cancel expected!): AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase); }
public void TestLoadAndSave_TestIdenticalFiles_kdb() { IKp2aApp app = LoadDatabase(DefaultDirectory + "complexDb.kdb", "test", null); app.GetDb().Root.SortSubGroups(true); string kdbxXml = DatabaseToXml(app); newFilename = TestDbDirectory + "tmp_complexDb.kdb"; if (File.Exists(newFilename)) { File.Delete(newFilename); } app.GetDb().KpDatabase.IOConnectionInfo.Path = newFilename; app.GetDb().SaveData(Application.Context); IKp2aApp appReloaded = LoadDatabase(newFilename, "test", null); appReloaded.GetDb().Root.SortSubGroups(true); string kdbxReloadedXml = DatabaseToXml(appReloaded); RemoveKdbLines(ref kdbxReloadedXml); RemoveKdbLines(ref kdbxXml); Assert.AreEqual(kdbxXml, kdbxReloadedXml); }
public void TestLoadEditSaveWhenDeleted() { //create the default database: IKp2aApp app = SetupAppWithDefaultDatabase(); IOConnection.DeleteFile(new IOConnectionInfo { Path = DefaultFilename }); //save it and reload it so we have a base version SaveDatabase(app); app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //delete the file: File.Delete(DefaultFilename); //modify the database by adding a group: app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true); //save the database again: _testCacheSupervisor.Reset(); SaveDatabase(app); Assert.IsNull(((TestKp2aApp)app).LastYesNoCancelQuestionTitle); _testCacheSupervisor.AssertNoCall(); //load database to a new app instance: IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //ensure the change was saved: AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase); }
public void TestLoadEditSaveWithWriteBecauseTargetNotExists() { //create the default database: IKp2aApp app = SetupAppWithDefaultDatabase(); //save it and reload it so we have a base version SaveDatabase(app); app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //modify the database by adding a group: app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true); //delete the file: File.Delete(DefaultFilename); //save the database: SaveDatabase(app); //make sure no question was asked Assert.AreEqual(null, ((TestKp2aApp)app).LastYesNoCancelQuestionTitle); //load database to a new app instance: IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //ensure the file was saved: AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase); }
public void TestCreateSaveAndLoad_TestIdenticalFiles_kdb() { string filename = DefaultDirectory + "createsaveandload.kdb"; IKp2aApp app = SetupAppWithDatabase(filename); string kdbxXml = DatabaseToXml(app); //save it and reload it Android.Util.Log.Debug("KP2A", "-- Save DB -- "); SaveDatabase(app); Android.Util.Log.Debug("KP2A", "-- Load DB -- "); PwDatabase pwImp = new PwDatabase(); PwDatabase pwDatabase = app.GetDb().KpDatabase; pwImp.New(new IOConnectionInfo(), pwDatabase.MasterKey); pwImp.MemoryProtection = pwDatabase.MemoryProtection.CloneDeep(); pwImp.MasterKey = pwDatabase.MasterKey; IOConnectionInfo ioc = new IOConnectionInfo() { Path = filename }; using (Stream s = app.GetFileStorage(ioc).OpenFileForRead(ioc)) { app.GetDb().DatabaseFormat.PopulateDatabaseFromStream(pwImp, s, null); } string kdbxReloadedXml = DatabaseToXml(app); RemoveKdbLines(ref kdbxReloadedXml); RemoveKdbLines(ref kdbxXml); Assert.AreEqual(kdbxXml, kdbxReloadedXml); }
private static string DatabaseToXml(IKp2aApp app) { KdbxFile kdb = new KdbxFile(app.GetDb().KpDatabase); var sOutput = new OnCloseToStringMemoryStream(); kdb.Save(sOutput, app.GetDb().KpDatabase.RootGroup, KdbxFormat.PlainXml, null); return(sOutput.Text); }
private void TestSync(string filename) { //create the default database: IKp2aApp app = SetupAppWithDatabase(filename); DisplayGroups(app, "After create"); //save it and reload it so we have a base version Android.Util.Log.Debug("KP2A", "-- Save first version -- "); SaveDatabase(app); Android.Util.Log.Debug("KP2A", "-- Load DB -- "); app = LoadDatabase(filename, DefaultPassword, DefaultKeyfile); DisplayGroups(app, "After reload"); //load it once again: Android.Util.Log.Debug("KP2A", "-- Load DB to app 2-- "); IKp2aApp app2 = LoadDatabase(filename, DefaultPassword, DefaultKeyfile); DisplayGroups(app2, "After load to app2"); //modify the database by adding a group in both databases: app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true); var group2 = new PwGroup(true, true, "TestGroup2", PwIcon.Energy); app2.GetDb().KpDatabase.RootGroup.AddGroup(group2, true); //save the database from app 1: Android.Util.Log.Debug("KP2A", "-- Save from app 1 (with TestGroup) -- "); SaveDatabase(app); ((TestKp2aApp)app2).SetYesNoCancelResult(TestKp2aApp.YesNoCancelResult.Yes); //save the database from app 2: This save operation must detect the changes made from app 1 and ask if it should sync: Android.Util.Log.Debug("KP2A", "-- Save from app 2 (with TestGroup2, requires merge) -- "); SaveDatabase(app2); DisplayGroups(app2, "After save with merge"); //make sure the right question was asked Assert.AreEqual(UiStringKey.TitleSyncQuestion, ((TestKp2aApp)app2).LastYesNoCancelQuestionTitle); //add group 2 to app 1: app.GetDb().KpDatabase.RootGroup.AddGroup(group2, true); app.GetDb().KpDatabase.RootGroup.SortSubGroups(true); Android.Util.Log.Debug("KP2A", "-- Load DB to new app -- "); //load database to a new app instance: IKp2aApp resultApp = LoadDatabase(filename, DefaultPassword, DefaultKeyfile); resultApp.GetDb().KpDatabase.RootGroup.SortSubGroups(true); //ensure the sync was successful: string kdbxXml = DatabaseToXml(app); string kdbxResultXml = DatabaseToXml(resultApp); RemoveKdbLines(ref kdbxXml, true); RemoveKdbLines(ref kdbxResultXml, true); Assert.AreEqual(kdbxXml, kdbxResultXml); //AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase); }
/* * public DeleteGroup(Context ctx, Database db, PwGroup group, Activity act, OnFinish finish, bool dontSave) * : base(finish) * { * SetMembers(ctx, db, group, act, dontSave); * } * * public DeleteGroup(Context ctx, Database db, PwGroup group, OnFinish finish, bool dontSave):base(finish) { * SetMembers(ctx, db, group, null, dontSave); * } */ private void SetMembers(Context ctx, IKp2aApp app, PwGroup group, bool dontSave) { base.SetMembers(ctx, app.GetDb()); _group = group; DontSave = dontSave; }
public override void Run() { StatusLogger.UpdateMessage(UiStringKey.exporting_database); var pd = _app.GetDb().KpDatabase; PwExportInfo pwInfo = new PwExportInfo(pd.RootGroup, pd, true); try { using (var writeTransaction = _app.GetFileStorage(_targetIoc).OpenWriteTransaction(_targetIoc, _app.GetDb().KpDatabase.UseFileTransactions)) { Stream sOut = writeTransaction.OpenFile(); _fileFormat.Export(pwInfo, sOut, new NullStatusLogger()); if (sOut != null) { sOut.Close(); } writeTransaction.CommitWrite(); } Finish(true); } catch (Exception ex) { Finish(false, ex.Message); } }
public DeleteEntry(Context ctx, IKp2aApp app, PwEntry entry, OnFinish finish) : base(finish, app) { Ctx = ctx; Db = app.GetDb(); _entry = entry; }
/* * public DeleteGroup(Context ctx, Database db, PwGroup group, Activity act, OnFinish finish, bool dontSave) * : base(finish) * { * SetMembers(ctx, db, group, act, dontSave); * } * * public DeleteGroup(Context ctx, Database db, PwGroup group, OnFinish finish, bool dontSave):base(finish) { * SetMembers(ctx, db, group, null, dontSave); * } */ private void SetMembers(Activity activity, IKp2aApp app, PwGroup group, bool dontSave) { base.SetMembers(activity, app.GetDb()); _group = group; DontSave = dontSave; }
protected AddEntry(Context ctx, IKp2aApp app, PwEntry entry, PwGroup parentGroup, OnFinish finish) : base(finish) { _ctx = ctx; _parentGroup = parentGroup; _app = app; _entry = entry; _onFinishToRun = new AfterAdd(app.GetDb(), entry, OnFinishToRun); }
public void TestLoadAndSave_TestIdenticalFiles() { IKp2aApp app = LoadDatabase(DefaultDirectory + "complexDb.kdbx", "test", null); var kdbxXml = DatabaseToXml(app); newFilename = TestDbDirectory + "tmp_complexDb.kdbx"; if (File.Exists(newFilename)) { File.Delete(newFilename); } app.GetDb().KpDatabase.IOConnectionInfo.Path = newFilename; app.GetDb().SaveData(Application.Context); IKp2aApp appReloaded = LoadDatabase(newFilename, "test", null); var kdbxReloadedXml = DatabaseToXml(appReloaded); Assert.AreEqual(kdbxXml, kdbxReloadedXml); }
public void TestLoadKdbxAndSaveKdbp_TestIdenticalFiles() { IKp2aApp app = LoadDatabase(DefaultDirectory + "complexDb.kdbx", "test", null); //string kdbxXml = DatabaseToXml(app); newFilename = TestDbDirectory + "tmp_complexDb.kdbp"; if (File.Exists(newFilename)) { File.Delete(newFilename); } app.GetDb().KpDatabase.IOConnectionInfo.Path = newFilename; app.GetDb().SaveData(Application.Context); IKp2aApp appReloaded = LoadDatabase(newFilename, "test", null); /* * Unfortunately we cannot compare the xml because there are slight differences: * - the order of ProtectedStrings in the xml is different (which is ok) * - the CustomIconUuids are serialized as Zeros instead of not being serialized (which is ok as well) * string kdbxReloadedXml = DatabaseToXml(appReloaded); * * bool areEqual = kdbxXml.Equals(kdbxReloadedXml); * * if (!areEqual) * { * using (StreamWriter w1 = File.CreateText(TestDbDirectory + "FromOriginalKdbx.xml")) * { * w1.Write(kdbxXml); * } * using (StreamWriter w2 = File.CreateText(TestDbDirectory + "FromKdbp.xml")) * { * w2.Write(kdbxReloadedXml); * } * * } * Assert.IsTrue(areEqual, "reloaded->xml differs from loaded->xml"); */ AssertDatabasesAreEqual(app.GetDb().KpDatabase, appReloaded.GetDb().KpDatabase); }
public override void Run() { try { IOConnectionInfo ioc = _app.GetDb().Ioc; IFileStorage fileStorage = _app.GetFileStorage(ioc); if (fileStorage is CachingFileStorage) { throw new Exception("Cannot sync a cached database!"); } StatusLogger.UpdateMessage(UiStringKey.CheckingDatabaseForChanges); //download file from remote location and calculate hash: StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.DownloadingRemoteFile)); MemoryStream remoteData = new MemoryStream(); using ( HashingStreamEx hashingRemoteStream = new HashingStreamEx(fileStorage.OpenFileForRead(ioc), false, new SHA256Managed())) { hashingRemoteStream.CopyTo(remoteData); hashingRemoteStream.Close(); if (!MemUtil.ArraysEqual(_app.GetDb().KpDatabase.HashOfFileOnDisk, hashingRemoteStream.Hash)) { _app.TriggerReload(_context); Finish(true); } else { Finish(true, _app.GetResourceString(UiStringKey.RemoteDatabaseUnchanged)); } } } catch (Exception e) { Finish(false, e.Message); } }
public void TestLoadEditSave() { //create the default database: IKp2aApp app = SetupAppWithDefaultDatabase(); IOConnection.DeleteFile(new IOConnectionInfo { Path = DefaultFilename }); //save it and reload it so we have a base version SaveDatabase(app); app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //modify the database by adding a group: app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true); //save the database again: SaveDatabase(app); //load database to a new app instance: IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //ensure the change was saved: AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase); }
public override void Run() { if (Success) { // Mark parent group dirty. Even only the last modification date changed, this might affect sort order PwGroup parent = _updatedEntry.ParentGroup; if (parent != null) { // Mark parent group dirty _app.GetDb().Dirty.Add(parent); } } else { StatusLogger.UpdateMessage(UiStringKey.UndoingChanges); // If we fail to save, back out changes to global structure //TODO test fail _updatedEntry.AssignProperties(_backup, false, true, false); } base.Run(); }
private static string DatabaseToXml(IKp2aApp app) { KdbxFile kdb = new KdbxFile(app.GetDb().KpDatabase); var sOutput = new OnCloseToStringMemoryStream(); kdb.Save(sOutput, app.GetDb().KpDatabase.RootGroup, KdbxFormat.PlainXml, null); return sOutput.Text; }
private void DisplayGroups(IKp2aApp app, string name) { LogDebug("Groups display: " + name); DisplayGroupRecursive(0, app.GetDb().Root); }
public DeleteEntry(Activity activiy, IKp2aApp app, PwEntry entry, OnFinish finish) : base(activiy, finish, app) { Ctx = activiy; Db = app.GetDb(); _entry = entry; }
public static bool ContainsAllTemplates(IKp2aApp app) { return(TemplateEntries.All(t => app.GetDb().Entries.ContainsKey(t.Uuid))); }
public override void Run() { try { IOConnectionInfo ioc = _app.GetDb().Ioc; IFileStorage fileStorage = _app.GetFileStorage(ioc); if (!(fileStorage is CachingFileStorage)) { throw new Exception("Cannot sync a non-cached database!"); } StatusLogger.UpdateMessage(UiStringKey.SynchronizingCachedDatabase); CachingFileStorage cachingFileStorage = (CachingFileStorage)fileStorage; //download file from remote location and calculate hash: StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.DownloadingRemoteFile)); string hash; MemoryStream remoteData; try { remoteData = cachingFileStorage.GetRemoteDataAndHash(ioc, out hash); } catch (FileNotFoundException) { StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.RestoringRemoteFile)); cachingFileStorage.UpdateRemoteFile(ioc, _app.GetBooleanPreference(PreferenceKey.UseFileTransactions)); Finish(true, _app.GetResourceString(UiStringKey.SynchronizedDatabaseSuccessfully)); return; } //check if remote file was modified: if (cachingFileStorage.GetBaseVersionHash(ioc) != hash) { //remote file is modified if (cachingFileStorage.HasLocalChanges(ioc)) { //conflict! need to merge _saveDb = new SaveDb(_context, _app, new ActionOnFinish((success, result) => { if (!success) { Finish(false, result); } else { Finish(true, _app.GetResourceString(UiStringKey.SynchronizedDatabaseSuccessfully)); } _saveDb = null; }), false, remoteData); _saveDb.Run(); _app.GetDb().MarkAllGroupsAsDirty(); } else { //only the remote file was modified -> reload database. //note: it's best to lock the database and do a complete reload here (also better for UI consistency in case something goes wrong etc.) _app.TriggerReload(_context); Finish(true); } } else { //remote file is unmodified if (cachingFileStorage.HasLocalChanges(ioc)) { //but we have local changes -> upload: StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.UploadingFile)); cachingFileStorage.UpdateRemoteFile(ioc, _app.GetBooleanPreference(PreferenceKey.UseFileTransactions)); StatusLogger.UpdateSubMessage(""); Finish(true, _app.GetResourceString(UiStringKey.SynchronizedDatabaseSuccessfully)); } else { //files are in sync: just set the result Finish(true, _app.GetResourceString(UiStringKey.FilesInSync)); } } } catch (Exception e) { Finish(false, e.Message); } }
public override void Run() { try { var fileStorage = _app.GetFileStorage(_targetIoc); if (fileStorage is IOfflineSwitchable) { ((IOfflineSwitchable)fileStorage).IsOffline = false; } using (var writeTransaction = fileStorage.OpenWriteTransaction(_targetIoc, _app.GetDb().KpDatabase.UseFileTransactions)) { Stream sOut = writeTransaction.OpenFile(); byte[] byteArray = _data.ReadData(); sOut.Write(byteArray, 0, byteArray.Length); sOut.Close(); writeTransaction.CommitWrite(); } if (fileStorage is IOfflineSwitchable) { ((IOfflineSwitchable)fileStorage).IsOffline = App.Kp2a.OfflineMode; } Finish(true); } catch (Exception ex) { Finish(false, ex.Message); } }
public override void Run() { if (!_dontSave) { try { if (_app.GetDb().CanWrite == false) { //this should only happen if there is a problem in the UI so that the user sees an edit interface. Finish(false, "Cannot save changes. File is read-only!"); return; } StatusLogger.UpdateMessage(UiStringKey.saving_database); IOConnectionInfo ioc = _app.GetDb().Ioc; IFileStorage fileStorage = _app.GetFileStorage(ioc); if (_streamForOrigFile == null) { if ((!_app.GetBooleanPreference(PreferenceKey.CheckForFileChangesOnSave)) || (_app.GetDb().KpDatabase.HashOfFileOnDisk == null)) //first time saving { PerformSaveWithoutCheck(fileStorage, ioc); Finish(true); return; } } if ( (_streamForOrigFile != null) || fileStorage.CheckForFileChangeFast(ioc, _app.GetDb().LastFileVersion) || //first try to use the fast change detection (FileHashChanged(ioc, _app.GetDb().KpDatabase.HashOfFileOnDisk) == FileHashChange.Changed) //if that fails, hash the file and compare: ) { //ask user... _app.AskYesNoCancel(UiStringKey.TitleSyncQuestion, UiStringKey.MessageSyncQuestion, UiStringKey.YesSynchronize, UiStringKey.NoOverwrite, //yes = sync (sender, args) => { Action runHandler = () => { //note: when synced, the file might be downloaded once again from the server. Caching the data //in the hashing function would solve this but increases complexity. I currently assume the files are //small. MergeIn(fileStorage, ioc); PerformSaveWithoutCheck(fileStorage, ioc); Finish(true); }; RunInWorkerThread(runHandler); }, //no = overwrite (sender, args) => { RunInWorkerThread(() => { PerformSaveWithoutCheck(fileStorage, ioc); Finish(true); }); }, //cancel (sender, args) => { RunInWorkerThread(() => Finish(false)); }, _ctx ); } else { PerformSaveWithoutCheck(fileStorage, ioc); Finish(true); } } catch (Exception e) { /* TODO KPDesktop: * catch(Exception exSave) * { * MessageService.ShowSaveWarning(pd.IOConnectionInfo, exSave, true); * bSuccess = false; * } */ Kp2aLog.LogUnexpectedError(e); Finish(false, e.Message); return; } } else { Finish(true); } }
public void TestLoadEditSaveWhenModified() { //create the default database: IKp2aApp app = SetupAppWithDefaultDatabase(); IOConnection.DeleteFile(new IOConnectionInfo { Path = DefaultFilename }); //save it and reload it so we have a base version SaveDatabase(app); app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups) { Kp2aLog.Log("app c: " + group.Name); } //load once more: var app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); //modifiy once: PwGroup group2 = new PwGroup(true, true, "TestGroup2", PwIcon.Apple); app2.GetDb().KpDatabase.RootGroup.AddGroup(group2, true); foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups) { Kp2aLog.Log("app b: " + group.Name); } SaveDatabase(app2); _testCacheSupervisor.Reset(); foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups) { Kp2aLog.Log("app d: " + group.Name); } Assert.IsNull(((TestKp2aApp)app).LastYesNoCancelQuestionTitle); _testCacheSupervisor.AssertNoCall(); //modify the database by adding a group: PwGroup group1 = new PwGroup(true, true, "TestGroup", PwIcon.Apple); app.GetDb().KpDatabase.RootGroup.AddGroup(group1, true); foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups) { Kp2aLog.Log("app a: " + group.Name); } //save the database again: _testCacheSupervisor.Reset(); SaveDatabase(app); Assert.AreEqual(((TestKp2aApp)app).LastYesNoCancelQuestionTitle, UiStringKey.TitleSyncQuestion); _testCacheSupervisor.AssertNoCall(); //load database to a new app instance: IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile); app2.GetDb().KpDatabase.RootGroup.AddGroup(group1, true); foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups) { Kp2aLog.Log("app: " + group.Name); } foreach (var group in resultApp.GetDb().KpDatabase.RootGroup.Groups) { Kp2aLog.Log("resultApp: " + group.Name); } //ensure the change was saved: AssertDatabasesAreEqual(app2.GetDb().KpDatabase, resultApp.GetDb().KpDatabase); }
public override void Run() { //check if we will run into problems. Then finish with error before we start doing anything. foreach (var _elementToMove in _elementsToMove) { PwGroup pgParent = _elementToMove.ParentGroup; if (pgParent != _targetGroup) { if (pgParent != null) { PwGroup group = _elementToMove as PwGroup; if (group != null) { if ((_targetGroup == group) || (_targetGroup.IsContainedIn(group))) { Finish(false, _app.GetResourceString(UiStringKey.CannotMoveGroupHere)); return; } } } } } foreach (var elementToMove in _elementsToMove) { _app.GetDb().Dirty.Add(elementToMove.ParentGroup); PwGroup pgParent = elementToMove.ParentGroup; if (pgParent != _targetGroup) { if (pgParent != null) // Remove from parent { PwEntry entry = elementToMove as PwEntry; if (entry != null) { pgParent.Entries.Remove(entry); _targetGroup.AddEntry(entry, true, true); } else { PwGroup group = (PwGroup)elementToMove; if ((_targetGroup == group) || (_targetGroup.IsContainedIn(group))) { Finish(false, _app.GetResourceString(UiStringKey.CannotMoveGroupHere)); return; } pgParent.Groups.Remove(group); _targetGroup.AddGroup(group, true, true); } } } } _onFinishToRun = new ActionOnFinish(ActiveActivity, (success, message, activity) => { if (!success) { // Let's not bother recovering from a failure. _app.LockDatabase(false); } }, OnFinishToRun); // Save SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun, false); save.SetStatusLogger(StatusLogger); save.Run(); }