diff --git a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/App.xaml.cs b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/App.xaml.cs index 08c9be0..f1ff3a0 100644 --- a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/App.xaml.cs +++ b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/App.xaml.cs @@ -1,7 +1,9 @@ using System; using SafeMessageStorage.Encryption.Hash.Providers; +using SafeMessageStorage.Encryption.Symmetric; using SafeMessageStorage.Pages; using SafeMessageStorage.Services.AuthorizationService; +using SafeMessageStorage.Services.MessageStorageService; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace SafeMessageStorage @@ -12,7 +14,9 @@ namespace SafeMessageStorage public App() { InitializeComponent(); - MainPage = new NavigationPage(new AuthorizationPage(new AuthorizationService(new Sha256HashProvider()))); + var authorizationService = new AuthorizationService(new Sha256HashProvider()); + var messageStorageService = new SafeMessageStorageService(authorizationService, new SymmetricEncryptionEngine()); + MainPage = new NavigationPage(new AuthorizationPage(authorizationService,messageStorageService)); } protected override void OnStart() diff --git a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Encryption/Symmetric/SymmetricEncryptionEngine.cs b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Encryption/Symmetric/SymmetricEncryptionEngine.cs new file mode 100644 index 0000000..249ec9b --- /dev/null +++ b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Encryption/Symmetric/SymmetricEncryptionEngine.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; + +namespace SafeMessageStorage.Encryption.Symmetric +{ + public class SymmetricEncryptionEngine : ISymmetricEncryptionEngine + { + public string Encrypt(string content, string key) + { + byte[] iv = new byte[16]; + byte[] array; + + using (Aes aes = Aes.Create()) + { + aes.Key = Encoding.UTF8.GetBytes(key).Take(16).ToArray(); + aes.IV = iv; + + ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); + + using (MemoryStream memoryStream = new MemoryStream()) + { + using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write)) + { + using (StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream)) + { + streamWriter.Write(content); + } + + array = memoryStream.ToArray(); + } + } + } + + return Convert.ToBase64String(array); + } + + public string Decrypt(string cipher, string key) + { + byte[] iv = new byte[16]; + byte[] buffer = Convert.FromBase64String(cipher); + + using (Aes aes = Aes.Create()) + { + aes.Key = Encoding.UTF8.GetBytes(key).Take(16).ToArray(); + aes.IV = iv; + ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); + + using (MemoryStream memoryStream = new MemoryStream(buffer)) + { + using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read)) + { + using (StreamReader streamReader = new StreamReader((Stream)cryptoStream)) + { + return streamReader.ReadToEnd(); + } + } + } + } + } + } +} diff --git a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Models/Message.cs b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Models/Message.cs index 6b1ce2b..f80522c 100644 --- a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Models/Message.cs +++ b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Models/Message.cs @@ -19,13 +19,13 @@ namespace SafeMessageStorage.Models } - public string Id { get; } + public string Id { get; set; } - public string Title { get; } + public string Title { get; set; } - public string Content { get; } + public string Content { get; set; } - public DateTimeOffset TimeOfCreation { get; } + public DateTimeOffset TimeOfCreation { get; set; } } } diff --git a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/AddMessagePage.xaml.cs b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/AddMessagePage.xaml.cs index 02476d3..bfe719c 100644 --- a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/AddMessagePage.xaml.cs +++ b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/AddMessagePage.xaml.cs @@ -13,20 +13,38 @@ namespace SafeMessageStorage.Pages [XamlCompilation(XamlCompilationOptions.Compile)] public partial class AddMessagePage : ContentPage { - //private IMessageStorageService _messageStorage; + private IMessageStorageService _messageStorage; - public AddMessagePage(/*IMessageStorageService messageStorageService*/) + public AddMessagePage(IMessageStorageService messageStorageService) { InitializeComponent(); + _messageStorage = messageStorageService; } private async void Button_OnClicked(object sender, EventArgs e) { + if (string.IsNullOrWhiteSpace(TitleEntry.Text)) + { + await DisplayAlert("Message not valid", "Title cannot be empty", "ok"); + return; + } + if (string.IsNullOrWhiteSpace(ContentEntry.Text)) + { + await DisplayAlert("Message not valid", "Content cannot be empty", "ok"); + return; + } + var message = new Message(TitleEntry.Text,ContentEntry.Text); - //if(await _messageStorage.SaveMessageAsync(message)) - MessageAdded?.Invoke(this,message); + if (await _messageStorage.SaveMessageAsync(message)) + { + MessageAdded?.Invoke(this, message); await Navigation.PopAsync(); + } + else + { + await DisplayAlert("Failed", "Unable to add message, try again", "ok"); + } } public event EventHandler MessageAdded; diff --git a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/AuthorizationPage.xaml.cs b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/AuthorizationPage.xaml.cs index e26b444..02ba3c4 100644 --- a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/AuthorizationPage.xaml.cs +++ b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/AuthorizationPage.xaml.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using SafeMessageStorage.Services.AuthorizationService; +using SafeMessageStorage.Services.MessageStorageService; using SafeMessageStorage.ViewModels; using Xamarin.Forms; using Xamarin.Forms.Xaml; @@ -15,11 +16,13 @@ namespace SafeMessageStorage.Pages { private AuthorizationPageViewModel _viewModel => this.BindingContext as AuthorizationPageViewModel; private IAuthorizationService _authorizationService; - public AuthorizationPage(IAuthorizationService authorizationService) + private IMessageStorageService _messageStorage; + public AuthorizationPage(IAuthorizationService authorizationService, IMessageStorageService messageStorage) { InitializeComponent(); BindingContext = new AuthorizationPageViewModel(authorizationService); _authorizationService = authorizationService; + _messageStorage = messageStorage; _viewModel.AuthorizationFailed += _viewModel_AuthorizationFailed; _viewModel.AuthorizationSucceeded += _viewModel_AuthorizationSucceeded; @@ -38,7 +41,7 @@ namespace SafeMessageStorage.Pages private async void _viewModel_AuthorizationSucceeded(object sender, EventArgs e) { - await Navigation.PushAsync(new MessagesListPage()); + await Navigation.PushAsync(new MessagesListPage(_messageStorage)); } private async void _viewModel_AuthorizationFailed(object sender, string e) diff --git a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/MessageDetailPage.xaml.cs b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/MessageDetailPage.xaml.cs index 5427fa1..d030ade 100644 --- a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/MessageDetailPage.xaml.cs +++ b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/MessageDetailPage.xaml.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using SafeMessageStorage.Models; +using SafeMessageStorage.Services.MessageStorageService; using Xamarin.Forms; using Xamarin.Forms.Xaml; @@ -13,12 +14,12 @@ namespace SafeMessageStorage.Pages public partial class MessageDetailPage : ContentPage { private string _messageId; - - public MessageDetailPage(Message message) + private IMessageStorageService _messageStorage; + public MessageDetailPage(Message message, IMessageStorageService messageStorage) { InitializeComponent(); _messageId = message.Id; - + _messageStorage = messageStorage; Title = message.Title; MessageContent.Text = message.Content; @@ -27,11 +28,10 @@ namespace SafeMessageStorage.Pages private async void DeleteMessage() { - MessageDeleted?.Invoke(this,_messageId); - await Navigation.PopAsync(); + if (await _messageStorage.DeleteMessageAsync(_messageId)) + await Navigation.PopAsync(); + else + await DisplayAlert("Unable to delete messafe", "please try again", "ok"); } - - public event EventHandler MessageDeleted; - } } \ No newline at end of file diff --git a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/MessagesListPage.xaml b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/MessagesListPage.xaml index 48b1c59..1761c20 100644 --- a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/MessagesListPage.xaml +++ b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Pages/MessagesListPage.xaml @@ -4,7 +4,8 @@ xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" - x:Class="SafeMessageStorage.Pages.MessagesListPage"> + x:Class="SafeMessageStorage.Pages.MessagesListPage" + Title="Messages"> Messages { get; set; } - - public MessagesListPage() + + public MessagesListPage(IMessageStorageService messageStorage) { InitializeComponent(); - Messages = new ObservableCollection() - { - new Message("Siemano","jakas wiadomosc"), - new Message("Kanapka","elo") - }; + _messageStorage = messageStorage; + Messages = new ObservableCollection(); BindingContext = this; } + protected override async void OnAppearing() + { + base.OnAppearing(); + Messages.Clear(); + var messages = await _messageStorage.ReadMessagesAsync(); + foreach (var message in messages) + { + Messages.Add(message); + } + } + async void Handle_ItemTapped(object sender, ItemTappedEventArgs e) { if (e.Item == null) return; var message = ((ListView) sender).SelectedItem as Message; - var detailPage = new MessageDetailPage(message); - detailPage.MessageDeleted += (sender, messageId) => OnMessageDeleted(messageId); + var detailPage = new MessageDetailPage(message, _messageStorage); + //detailPage.MessageDeleted += (sender, messageId) => OnMessageDeleted(messageId); await Navigation.PushAsync(detailPage); ////Deselect Item @@ -41,17 +52,10 @@ namespace SafeMessageStorage.Pages private async void Button_OnClicked(object sender, EventArgs e) { - var addMessagePage = new AddMessagePage(); - addMessagePage.MessageAdded+= (o, message) => Dispatcher.BeginInvokeOnMainThread(()=>Messages.Add(message)); + var addMessagePage = new AddMessagePage(_messageStorage); + //addMessagePage.MessageAdded+= (o, message) => Dispatcher.BeginInvokeOnMainThread(()=>Messages.Add(message)); await Navigation.PushAsync(addMessagePage); } - - - private void OnMessageDeleted(string messageId) - { - var toRemove = Messages.FirstOrDefault(m => m.Id == messageId); - Messages.Remove(toRemove); - } } } diff --git a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Services/MessageStorageService/SafeMessageStorageService.cs b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Services/MessageStorageService/SafeMessageStorageService.cs index 9ff911f..96f763f 100644 --- a/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Services/MessageStorageService/SafeMessageStorageService.cs +++ b/src/SafeMessageStorage/SafeMessageStorage/SafeMessageStorage/Services/MessageStorageService/SafeMessageStorageService.cs @@ -16,6 +16,12 @@ namespace SafeMessageStorage.Services.MessageStorageService private ISymmetricEncryptionEngine _encryptionEngine; private readonly string _messagesKey = "377f2486-d2c3-48a7-b821-45d7314479cd"; + public SafeMessageStorageService(IAuthorizationService authorizationService, ISymmetricEncryptionEngine encryptionEngine) + { + _authorizationService = authorizationService; + _encryptionEngine = encryptionEngine; + } + public bool IsStorageEmpty => Xamarin.Essentials.SecureStorage.GetAsync(_messagesKey).Result != null; public async Task SaveMessageAsync(Message message) @@ -34,10 +40,10 @@ namespace SafeMessageStorage.Services.MessageStorageService CheckIfAuthorized(); var encryptedMessage =await Xamarin.Essentials.SecureStorage.GetAsync(_messagesKey); if (encryptedMessage == null) - return null; + return new List(); var decryptedMessage = _encryptionEngine.Decrypt(encryptedMessage, _authorizationService.AuthorizedUserHash); - return JsonConvert.DeserializeObject>(decryptedMessage); + return JsonConvert.DeserializeObject>(decryptedMessage).Where(x=>x.Id!=null); } public async Task DeleteMessageAsync(string messageId)