Esempio n. 1
0
        /// <summary>
        /// Build a merged list of safes.
        /// </summary>
        /// <param name="leftItems">List of safes from the left repository, whose order has precedence.</param>
        /// <param name="rightItems">List of safes from the right side repository.</param>
        /// <returns>List of safes for the new merged repository.</returns>
        private static SafeListModel BuildMergedListOfSafes(SafeListModel leftItems, SafeListModel rightItems)
        {
            SafeListModel result = new SafeListModel();

            var map = OuterJoin(leftItems, rightItems, item => item.Id);

            foreach (Tuple <SafeModel, SafeModel> pair in map)
            {
                if (pair.Item1 == null)
                {
                    // Only available on the right side
                    result.Add(pair.Item2.Clone());
                }
                else if (pair.Item2 == null)
                {
                    // Only available on the left side
                    result.Add(pair.Item1.Clone());
                }
                else
                {
                    // Take the more recent
                    SafeModel lastModifiedItem = ChooseLastModified(
                        pair.Item1, pair.Item2, item => item.ModifiedAt, null);
                    result.Add(lastModifiedItem.Clone());
                }
            }
            return(result);
        }
        /// <inheritdoc/>
        public ShortenedNoteViewModel(
            INavigationService navigationService,
            ILanguageService languageService,
            ISvgIconService svgIconService,
            IThemeService themeService,
            IBaseUrlService webviewBaseUrl,
            SearchableHtmlConverter searchableTextConverter,
            IRepositoryStorageService repositoryService,
            IFeedbackService feedbackService,
            ISettingsService settingsService,
            ICryptor cryptor,
            SafeListModel safes,
            NoteModel noteFromRepository)
            : base(navigationService, languageService, svgIconService, themeService, webviewBaseUrl, searchableTextConverter, repositoryService, feedbackService, settingsService, cryptor, safes, noteFromRepository)
        {
            if (_unlockedContent != null)
            {
                // Create a short version for large notes, with only the first part of the note.
                // This is a performance improvement if there are large notes in the repository.
                HtmlShortener shortener = new HtmlShortener();
                shortener.WantedLength    = 600; // Should be enough even for settings with
                shortener.WantedTagNumber = 20;  // small font and very height notes.

                string shortenedContent = shortener.Shorten(_unlockedContent);
                if (shortenedContent.Length != _unlockedContent.Length)
                {
                    // Because the note will be truncated, we have to build the searchable content
                    // first, before overwriting the original content.
                    string dummy = SearchableContent;
                    _unlockedContent = shortenedContent;
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NoteViewModel"/> class.
        /// </summary>
        public NoteViewModel(
            INavigationService navigationService,
            ILanguageService languageService,
            ISvgIconService svgIconService,
            IThemeService themeService,
            IBaseUrlService webviewBaseUrl,
            SearchableHtmlConverter searchableTextConverter,
            IRepositoryStorageService repositoryService,
            IFeedbackService feedbackService,
            ISettingsService settingsService,
            ICryptor cryptor,
            SafeListModel safes,
            NoteModel noteFromRepository)
            : base(navigationService, languageService, svgIconService, themeService, webviewBaseUrl)
        {
            _repositoryService       = repositoryService;
            _feedbackService         = feedbackService;
            _settingsService         = settingsService;
            _searchableTextConverter = searchableTextConverter;
            _cryptor = cryptor;
            _safes   = safes;
            MarkSearchableContentAsDirty();
            PushNoteToOnlineStorageCommand   = new RelayCommand(PushNoteToOnlineStorage);
            PullNoteFromOnlineStorageCommand = new RelayCommand(PullNoteFromOnlineStorage);
            ToggleShoppingModeCommand        = new RelayCommand(ToggleShoppingMode);
            GoBackCommand = new RelayCommand(GoBack);

            Model            = noteFromRepository;
            _unlockedContent = IsInSafe ? UnlockIfSafeOpen(Model.HtmlContent) : Model.HtmlContent;
        }
        public void DoesNotShowContentWhenSafeIsClosed()
        {
            SearchableHtmlConverter          searchableConverter = new SearchableHtmlConverter();
            Mock <IRepositoryStorageService> repositoryService   = new Mock <IRepositoryStorageService>();
            Mock <ISettingsService>          settingsService     = new Mock <ISettingsService>();
            Mock <ICryptor> cryptor = new Mock <ICryptor>();

            SafeListModel safes = new SafeListModel(new[]
            {
                new SafeModel {
                    Id = Guid.NewGuid()
                },
            });
            NoteModel note = new NoteModel {
                Id = Guid.NewGuid(), HtmlContent = "secret", SafeId = safes[0].Id
            };

            NoteViewModel noteViewModel = new NoteViewModel(
                new Mock <INavigationService>().Object,
                new Mock <ILanguageService>().Object,
                new Mock <ISvgIconService>().Object,
                new Mock <IThemeService>().Object,
                new Mock <IBaseUrlService>().Object,
                searchableConverter,
                repositoryService.Object,
                new Mock <IFeedbackService>().Object,
                settingsService.Object,
                cryptor.Object,
                safes,
                new List <string>(),
                note);

            Assert.IsNull(noteViewModel.UnlockedHtmlContent);
            Assert.IsNull(noteViewModel.SearchableContent);
        }
Esempio n. 5
0
        public void MergeSafes()
        {
            Guid     safe1Id    = new Guid("10000000000000000000000000000000");
            Guid     safe2Id    = new Guid("20000000000000000000000000000000");
            Guid     safe3Id    = new Guid("30000000000000000000000000000000");
            Guid     safe4Id    = new Guid("40000000000000000000000000000000");
            Guid     safe5Id    = new Guid("50000000000000000000000000000000");
            Guid     safe6Id    = new Guid("60000000000000000000000000000000");
            DateTime newerDate  = new DateTime(2008, 08, 08);
            DateTime middleDate = new DateTime(2006, 06, 06);

            NoteRepositoryModel serverRepo = new NoteRepositoryModel();
            SafeModel           safeS1     = new SafeModel {
                Id = safe2Id, SerializeableKey = "s1", ModifiedAt = newerDate
            };
            SafeModel safeS2 = new SafeModel {
                Id = safe4Id, SerializeableKey = "s2", ModifiedAt = middleDate
            };
            SafeModel safeS3 = new SafeModel {
                Id = safe6Id, SerializeableKey = "s3", ModifiedAt = middleDate
            };

            serverRepo.Safes.AddRange(new[] { safeS1, safeS2, safeS3 });
            AddNotesWithSafeIds(serverRepo, new[] { safe2Id, safe4Id, safe6Id });

            NoteRepositoryModel clientRepo = new NoteRepositoryModel();
            SafeModel           safeC1     = new SafeModel {
                Id = safe5Id, SerializeableKey = "c1", ModifiedAt = middleDate
            };
            SafeModel safeC2 = new SafeModel {
                Id = safe4Id, SerializeableKey = "c2", ModifiedAt = newerDate
            };
            SafeModel safeC3 = new SafeModel {
                Id = safe2Id, SerializeableKey = "c3", ModifiedAt = middleDate
            };
            SafeModel safeC4 = new SafeModel {
                Id = safe1Id, SerializeableKey = "c4", ModifiedAt = middleDate
            };
            SafeModel safeC5 = new SafeModel {
                Id = safe3Id, SerializeableKey = "c5", ModifiedAt = middleDate
            };

            clientRepo.Safes.AddRange(new[] { safeC1, safeC2, safeC3, safeC4, safeC5 });
            AddNotesWithSafeIds(clientRepo, new[] { safe5Id, safe4Id, safe2Id, safe1Id, safe3Id });

            NoteRepositoryMerger merger = new NoteRepositoryMerger();
            NoteRepositoryModel  result = merger.Merge(clientRepo, serverRepo);
            SafeListModel        safes  = result.Safes;

            Assert.AreEqual(6, safes.Count);
            Assert.AreEqual(safe5Id, safes[0].Id); Assert.AreEqual("c1", safes[0].SerializeableKey);
            Assert.AreEqual(safe2Id, safes[1].Id); Assert.AreEqual("s1", safes[1].SerializeableKey);
            Assert.AreEqual(safe1Id, safes[2].Id); Assert.AreEqual("c4", safes[2].SerializeableKey);
            Assert.AreEqual(safe3Id, safes[3].Id); Assert.AreEqual("c5", safes[3].SerializeableKey);
            Assert.AreEqual(safe4Id, safes[4].Id); Assert.AreEqual("c2", safes[4].SerializeableKey);
            Assert.AreEqual(safe6Id, safes[5].Id); Assert.AreEqual("s3", safes[5].SerializeableKey);
        }
        public void ModifiedNoteIsEncryptedAndStored()
        {
            string modelHtmlContent = "c2VjcmV0";

            byte[]                           safeKey             = new byte[] { 88 };
            SettingsModel                    settingsModel       = new SettingsModel();
            SearchableHtmlConverter          searchableConverter = new SearchableHtmlConverter();
            Mock <IRepositoryStorageService> repositoryService   = new Mock <IRepositoryStorageService>();
            Mock <ISettingsService>          settingsService     = new Mock <ISettingsService>();

            settingsService.
            Setup(m => m.LoadSettingsOrDefault()).Returns(settingsModel);
            Mock <ICryptor> cryptor = new Mock <ICryptor>();

            cryptor.
            Setup(m => m.Decrypt(It.IsAny <byte[]>(), It.Is <byte[]>(v => v == safeKey))).
            Returns(CryptoUtils.StringToBytes("not secret anymore"));

            SafeListModel safes = new SafeListModel(new[]
            {
                new SafeModel {
                    Id = Guid.NewGuid(), Key = safeKey
                },
            });
            NoteModel note = new NoteModel {
                Id = Guid.NewGuid(), HtmlContent = modelHtmlContent, SafeId = safes[0].Id
            };

            NoteViewModel noteViewModel = new NoteViewModel(
                new Mock <INavigationService>().Object,
                new Mock <ILanguageService>().Object,
                new Mock <ISvgIconService>().Object,
                new Mock <IThemeService>().Object,
                new Mock <IBaseUrlService>().Object,
                searchableConverter,
                repositoryService.Object,
                new Mock <IFeedbackService>().Object,
                settingsService.Object,
                cryptor.Object,
                safes,
                new List <string>(),
                note);

            noteViewModel.UnlockedHtmlContent = "something new";
            noteViewModel.OnStoringUnsavedData();

            cryptor.Verify(m => m.Encrypt(
                               It.Is <byte[]>(p => p.SequenceEqual(CryptoUtils.StringToBytes("something new"))),
                               It.Is <byte[]>(p => p.SequenceEqual(safeKey)),
                               It.IsAny <string>(),
                               It.Is <string>(p => p == null)),
                           Times.Once);
            repositoryService.Verify(m => m.TrySaveRepository(It.IsAny <NoteRepositoryModel>()), Times.Once);
        }
        public void ShowsUnlockedContentWhenSafeIsOpen()
        {
            string modelHtmlContent = "c2VjcmV0";

            byte[] safeKey = new byte[] { 88 };
            SearchableHtmlConverter          searchableConverter = new SearchableHtmlConverter();
            Mock <IRepositoryStorageService> repositoryService   = new Mock <IRepositoryStorageService>();
            Mock <ISettingsService>          settingsService     = new Mock <ISettingsService>();
            Mock <ICryptor> cryptor = new Mock <ICryptor>();

            cryptor.
            Setup(m => m.Decrypt(It.IsAny <byte[]>(), It.Is <byte[]>(v => v == safeKey))).
            Returns(CryptoUtils.StringToBytes("not secret anymore"));

            SafeListModel safes = new SafeListModel(new[]
            {
                new SafeModel {
                    Id = Guid.NewGuid(), Key = safeKey
                },
            });
            NoteModel note = new NoteModel {
                Id = Guid.NewGuid(), HtmlContent = modelHtmlContent, SafeId = safes[0].Id
            };

            NoteViewModel noteViewModel = new NoteViewModel(
                new Mock <INavigationService>().Object,
                new Mock <ILanguageService>().Object,
                new Mock <ISvgIconService>().Object,
                new Mock <IThemeService>().Object,
                new Mock <IBaseUrlService>().Object,
                searchableConverter,
                repositoryService.Object,
                new Mock <IFeedbackService>().Object,
                settingsService.Object,
                cryptor.Object,
                safes,
                new List <string>(),
                note);

            Assert.AreEqual("not secret anymore", noteViewModel.UnlockedHtmlContent);
            Assert.AreEqual("not secret anymore", noteViewModel.SearchableContent);
        }
        public void FindOldestOpenSafeWorksCorrectly()
        {
            SafeListModel list = new SafeListModel();

            byte[] testKey = new byte[0];

            // Search in empty list
            Assert.IsNull(list.FindOldestOpenSafe());

            // Search with only one element
            SafeModel safe2002 = new SafeModel {
                CreatedAt = new DateTime(2002, 02, 02), Key = testKey
            };

            list.Add(safe2002);
            Assert.AreSame(safe2002, list.FindOldestOpenSafe());

            // Add newer element
            SafeModel safe2003 = new SafeModel {
                CreatedAt = new DateTime(2003, 03, 03), Key = testKey
            };

            list.Add(safe2003);
            Assert.AreSame(safe2002, list.FindOldestOpenSafe());

            // Add closed safe
            SafeModel safe2000 = new SafeModel {
                CreatedAt = new DateTime(2000, 01, 01), Key = null
            };

            list.Add(safe2000);
            Assert.AreSame(safe2002, list.FindOldestOpenSafe());

            // Add older element
            SafeModel safe2001 = new SafeModel {
                CreatedAt = new DateTime(2001, 01, 01), Key = testKey
            };

            list.Add(safe2001);
            Assert.AreSame(safe2001, list.FindOldestOpenSafe());
        }