Fix when wiping an account that hasn't been authenticated
[pithos-ms-client] / trunk / Pithos.Client.WPF / Preferences / AddAccountViewModel.cs
index c295e4b..f4f43b1 100644 (file)
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.ComponentModel.Composition;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Forms;
-using Caliburn.Micro;
-using Pithos.Client.WPF.Properties;
-using Pithos.Core;
-using Pithos.Network;
-using MessageBox = System.Windows.MessageBox;
-using Screen = Caliburn.Micro.Screen;
-
-namespace Pithos.Client.WPF.Preferences
-{
-    [Export(typeof(AddAccountViewModel))]
-    public class AddAccountViewModel:Screen
-    {
-
-        private readonly List<string> _servers;
-
-        public List<string> Servers
-        {
-            get { return _servers; }
-        }
-
-        private bool _isValidServer;
-        public bool IsValidServer
-        {
-            get { return _isValidServer; }
-            set
-            {
-                _isValidServer = value;
-                NotifyOfPropertyChange(()=>IsValidServer);
-            }
-        }
-
-
-        private string _currentServer;
-        public string CurrentServer
-        {
-            get { return _currentServer; }
-            set
-            {
-                if (!Uri.IsWellFormedUriString(value, UriKind.Absolute))
-                {
-                    IsValidServer = false;
-                    throw new UriFormatException();
-                }
-                _currentServer = value;
-                IsValidServer = true;
-                HasValidCredentials = false;
-                IsConfirmed = false;
-                NotifyOfPropertyChange(()=>CurrentServer);
-            }
-        }
-
-        private string _accountName;
-        public string AccountName
-        {
-            get { return _accountName; }
-            set
-            {
-                _accountName = value;
-                NotifyOfPropertyChange(()=>AccountName);
-                NotifyOfPropertyChange(() => HasCredentials);
-            }
-        }
-
-        private string _token;
-        public string Token
-        {
-            get { return _token; }
-            set
-            {
-                _token = value;
-                NotifyOfPropertyChange(()=>Token);
-                NotifyOfPropertyChange(() => HasCredentials);
-            }
-        }
-
-        private string _accountPath;
-        public string AccountPath
-        {
-            get { return _accountPath; }
-            set
-            {
-                _accountPath = value;
-                NotifyOfPropertyChange(() => AccountPath);
-                NotifyOfPropertyChange(() => HasAccountPath);
-            }
-        }
-
-
-        public bool HasAccountPath
-        {
-            get { return !String.IsNullOrWhiteSpace(AccountPath); }
-        }
-
-        public bool HasCredentials
-        {
-            get { return !(String.IsNullOrWhiteSpace(AccountName) || String.IsNullOrWhiteSpace(Token) ) ; }
-        }
-
-
-        private bool  _isConfirmed;
-
-        public bool IsConfirmed
-        {
-            get { return _isConfirmed; }
-            set
-            {
-                _isConfirmed = value;
-                HasValidCredentials = false;
-                NotifyOfPropertyChange(() => IsConfirmed);
-            }
-        }
-
-
-        private bool _isAccountActive;
-
-        public bool IsAccountActive
-        {
-            get { return _isAccountActive; }
-            set
-            {
-                _isAccountActive = value;
-                NotifyOfPropertyChange(() => IsAccountActive);
-            }
-        }
-
-        public void SelectAccount()
-        {
-            using (var dlg = new FolderBrowserDialog())
-            {
-                //Ask the user to select a folder
-                //Note: We need a parent window here, which we retrieve with GetView            
-                var view = (Window)GetView();
-                if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))
-                    return;
-
-                AccountPath= dlg.SelectedPath;
-            }
-        }
-
-
-        private bool _isRetrieving;
-        public bool IsRetrieving
-        {
-            get { return _isRetrieving; }
-            set
-            {
-                _isRetrieving = value;
-                NotifyOfPropertyChange(() => IsRetrieving);
-            }
-        }
-
-        public async void RetrieveCredentials()
-        {
-            IsRetrieving = true;
-            IsConfirmed = false;
-
-            try
-            {
-                var credentials = await PithosAccount.RetrieveCredentials(Settings.Default.PithosLoginUrl);
-                AccountName = credentials.UserName;
-                Token = credentials.Password;
-
-                IsConfirmed = true;
-            }
-            catch (Exception exc)
-            {
-                IsConfirmed = false;
-                MessageBox.Show(exc.ToString(), "Error");
-                throw;
-            }
-            IsRetrieving = false;
-
-        }
-
-        public AddAccountViewModel()
-        {
-            _servers=new List<string>
-                         {
-                             Settings.Default.ProductionServer, 
-                             Settings.Default.DevelopmentServer
-                         };
-            CurrentServer = _servers[0];
-        }
-
-        private bool _hasValidCredentials;
-        public bool HasValidCredentials
-        {
-            get { return _hasValidCredentials; }
-            set
-            {
-                _hasValidCredentials = value;
-                NotifyOfPropertyChange(()=>HasValidCredentials);
-            }
-        }
-
-
-        private bool _isValidating;
-        public bool IsValidating
-        {
-            get { return _isValidating; }
-            set
-            {
-                _isValidating = value;
-                NotifyOfPropertyChange(()=>IsValidating);
-            }
-        }
-
-        public async void TestAccount()
-        {
-            try
-            {
-                IsValidating = true;
-                var client = new CloudFilesClient(AccountName, Token) {AuthenticationUrl = CurrentServer};                
-                var containers = await TaskEx.Run(()=>
-                                                      {
-                                                          client.Authenticate();
-                                                          return client.ListContainers(AccountName);
-                                                      });
-                HasValidCredentials = true;                
-            }
-            catch (Exception ex)
-            {
-                HasValidCredentials = false;
-                MessageBox.Show("The account is not valid", "Account Error", MessageBoxButton.OK, MessageBoxImage.Stop);
-                throw;
-            }
-            finally
-            {
-                IsValidating = false;
-            }
-        }
-
-    }
-}
+#region\r
+/* -----------------------------------------------------------------------\r
+ * <copyright file="AddAccountViewModel.cs" company="GRNet">\r
+ * \r
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ *   1. Redistributions of source code must retain the above\r
+ *      copyright notice, this list of conditions and the following\r
+ *      disclaimer.\r
+ *\r
+ *   2. Redistributions in binary form must reproduce the above\r
+ *      copyright notice, this list of conditions and the following\r
+ *      disclaimer in the documentation and/or other materials\r
+ *      provided with the distribution.\r
+ *\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\r
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\r
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * The views and conclusions contained in the software and\r
+ * documentation are those of the authors and should not be\r
+ * interpreted as representing official policies, either expressed\r
+ * or implied, of GRNET S.A.\r
+ * </copyright>\r
+ * -----------------------------------------------------------------------\r
+ */\r
+#endregion\r
+using System;\r
+using System.Collections.Generic;\r
+using System.ComponentModel.Composition;\r
+using System.IO;\r
+using System.Linq;\r
+using System.Text.RegularExpressions;\r
+using System.Threading.Tasks;\r
+using System.Windows;\r
+using System.Windows.Forms;\r
+using Pithos.Client.WPF.Properties;\r
+using Pithos.Interfaces;\r
+using Pithos.Network;\r
+using MessageBox = System.Windows.MessageBox;\r
+using Screen = Caliburn.Micro.Screen;\r
+\r
+namespace Pithos.Client.WPF.Preferences\r
+{\r
+    [Export(typeof(AddAccountViewModel))]\r
+    public class AddAccountViewModel:Screen\r
+    {\r
+\r
+        private readonly List<string> _servers;\r
+\r
+        public List<string> Servers\r
+        {\r
+            get { return Settings.Default.Servers.Select(server => server.ServerUri).ToList(); }\r
+        }\r
+\r
+        private bool _isValidServer;\r
+        public bool IsValidServer\r
+        {\r
+            get { return _isValidServer; }\r
+            set\r
+            {\r
+                _isValidServer = value;\r
+                NotifyOfPropertyChange(()=>IsValidServer);\r
+            }\r
+        }\r
+\r
+\r
+        private string _currentServer;\r
+        public string CurrentServer\r
+        {\r
+            get { return _currentServer; }\r
+            set\r
+            {\r
+                if (!Uri.IsWellFormedUriString(value, UriKind.Absolute))\r
+                {\r
+                    IsValidServer = false;\r
+                    throw new UriFormatException();\r
+                }\r
+                _currentServer = value;\r
+                IsValidServer = true;\r
+                HasValidCredentials = false;\r
+                IsConfirmed = false;\r
+                NotifyOfPropertyChange(()=>CurrentServer);\r
+            }\r
+        }\r
+\r
+        private string _accountName;\r
+        public string AccountName\r
+        {\r
+            get { return _accountName; }\r
+            set\r
+            {\r
+                _accountName = value;\r
+                NotifyOfPropertyChange(()=>AccountName);\r
+                NotifyOfPropertyChange(() => HasCredentials);\r
+            }\r
+        }\r
+\r
+        private string _token;\r
+        public string Token\r
+        {\r
+            get { return _token; }\r
+            set\r
+            {\r
+                _token = value;\r
+                NotifyOfPropertyChange(()=>Token);\r
+                NotifyOfPropertyChange(() => HasCredentials);\r
+            }\r
+        }\r
+\r
+        private string _accountPath;\r
+        public string AccountPath\r
+        {\r
+            get { return _accountPath; }\r
+            set\r
+            {\r
+                _accountPath = value;\r
+                NotifyOfPropertyChange(() => AccountPath);\r
+                NotifyOfPropertyChange(() => HasAccountPath);\r
+            }\r
+        }\r
+\r
+\r
+        public bool HasAccountPath\r
+        {\r
+            get { return !String.IsNullOrWhiteSpace(AccountPath); }\r
+        }\r
+\r
+        public bool HasCredentials\r
+        {\r
+            get { return !(String.IsNullOrWhiteSpace(AccountName) || String.IsNullOrWhiteSpace(Token) ) ; }\r
+        }\r
+\r
+\r
+        private bool  _isConfirmed;\r
+\r
+        public bool IsConfirmed\r
+        {\r
+            get { return _isConfirmed; }\r
+            set\r
+            {\r
+                _isConfirmed = value;\r
+                HasValidCredentials = false;\r
+                NotifyOfPropertyChange(() => IsConfirmed);\r
+            }\r
+        }\r
+\r
+\r
+        private bool _isAccountActive;\r
+\r
+        public bool IsAccountActive\r
+        {\r
+            get { return _isAccountActive; }\r
+            set\r
+            {\r
+                _isAccountActive = value;\r
+                NotifyOfPropertyChange(() => IsAccountActive);\r
+            }\r
+        }\r
+\r
+\r
+        private bool _shouldCreateOkeanosFolder;\r
+        public bool ShouldCreateOkeanosFolder\r
+        {\r
+            get { return _shouldCreateOkeanosFolder; }\r
+            set\r
+            {\r
+                _shouldCreateOkeanosFolder = value;\r
+                NotifyOfPropertyChange(()=>ShouldCreateOkeanosFolder);\r
+            }\r
+        }\r
+\r
+        bool HasNoParentWithCache(DirectoryInfo info)\r
+        {\r
+            if (info == null)\r
+                return false;\r
+            var parent = info.Parent;\r
+            if (parent == null)\r
+                return true;\r
+            if (parent.EnumerateDirectories(FolderConstants.CacheFolder).Any())\r
+            {\r
+                return false;\r
+            }\r
+            return HasNoParentWithCache(parent);\r
+        }\r
+\r
+        string GetLowestAboveCache(string path)\r
+        {\r
+            if (String.IsNullOrWhiteSpace(path))\r
+                return null;\r
+            var info = new DirectoryInfo(path);\r
+            if (!info.Exists)\r
+                return path;\r
+            while (!HasNoParentWithCache(info))\r
+            {\r
+                info = info.Parent;\r
+            }\r
+            if (info == null)\r
+                return null;\r
+            else\r
+                return info.FullName;\r
+        }\r
+\r
+        public void SelectAccount()\r
+        {\r
+            using (var dlg = new FolderBrowserDialog{Description=Resources.AddAccountViewModel_SelectAccount_Please_select_a_folder})\r
+            {\r
+                //Ask the user to select a folder\r
+                //Note: We need a parent window here, which we retrieve with GetView            \r
+                var view = (Window)GetView();\r
+                if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))\r
+                    return;\r
+\r
+                //If the selected path is under an account folder, ie a folder containint a .pithos.cache subfolder, try to locate\r
+                //the cache's parent folder\r
+                var selectedPath = GetLowestAboveCache(dlg.SelectedPath);\r
+\r
+                //If the path  ends with /okeanos#/pithos, replace with /okeanos#\r
+                var match = _okeanosRegex.Match(selectedPath);\r
+                if (match.Success)\r
+                {\r
+                    selectedPath = match.Groups[1].Value;                    \r
+                }\r
+\r
+                AccountPath= selectedPath;\r
+\r
+\r
+\r
+                ShouldCreateOkeanosFolder=Directory.EnumerateFileSystemEntries(AccountPath).Any();                \r
+            }\r
+        }\r
+\r
+\r
+        public void RetrieveCredentials()\r
+        {\r
+            SetBusy("Waiting for credentials.", "Please enter your credentials in the Pithos logon page");\r
+            IsConfirmed = false;\r
+\r
+            try\r
+            {\r
+                var loginUri=new Uri(CurrentServer).Combine("login");\r
+                var credentials = PithosAccount.RetrieveCredentials(loginUri.ToString());\r
+                if (credentials == null)\r
+                    return;\r
+                AccountName = credentials.UserName;\r
+                Token = credentials.Password;\r
+\r
+                IsConfirmed = true;\r
+\r
+            }\r
+            catch (PithosException exc)\r
+            {\r
+                ClearBusy();\r
+                MessageBox.Show(exc.Message, "Unable to retrieve credentials");\r
+            }\r
+            catch (Exception exc)\r
+            {\r
+                IsConfirmed = false;\r
+                MessageBox.Show(exc.ToString(), "Error");\r
+                throw;\r
+            }\r
+            finally\r
+            {\r
+                ClearBusy();\r
+                \r
+                ((Window) GetView()).Activate();\r
+            }\r
+\r
+            if (IsConfirmed)\r
+                TaskEx.Run(()=>TestAccount());\r
+\r
+        }\r
+\r
+        public AddAccountViewModel()\r
+        {\r
+            _servers=new List<string>\r
+                         {\r
+                             Settings.Default.ProductionServer, \r
+                             Settings.Default.DevelopmentServer\r
+                         };\r
+            CurrentServer = _servers[0];\r
+            DisplayName = "Add Pithos+ Account";\r
+        }\r
+\r
+        private bool _hasValidCredentials;\r
+        public bool HasValidCredentials\r
+        {\r
+            get { return _hasValidCredentials; }\r
+            set\r
+            {\r
+                _hasValidCredentials = value;\r
+                NotifyOfPropertyChange(()=>HasValidCredentials);\r
+            }\r
+        }\r
+\r
+        private string _validationMessage;\r
+        public string ValidationMessage\r
+        {\r
+            get { return _validationMessage; }\r
+            set\r
+            {\r
+                _validationMessage = value;\r
+                NotifyOfPropertyChange(()=>ValidationMessage);\r
+            }\r
+        }\r
+\r
+        private bool _isWorking;\r
+        public bool IsWorking\r
+        {\r
+            get { return _isWorking; }\r
+            set\r
+            {\r
+                _isWorking = value;\r
+                NotifyOfPropertyChange(()=>IsWorking);\r
+            }\r
+        }\r
+\r
+        private string _busyTitle;\r
+        public string BusyTitle\r
+        {\r
+            get { return _busyTitle; }\r
+            set\r
+            {\r
+                _busyTitle = value;\r
+                NotifyOfPropertyChange(()=>BusyTitle);\r
+            }\r
+        }\r
+\r
+        private string _busyDetail;\r
+        private Regex _okeanosRegex = new Regex(@"(.*okeanos[0-9]*)\\pithos$");\r
+\r
+        public string BusyDetail\r
+        {\r
+            get { return _busyDetail; }\r
+            set\r
+            {\r
+                _busyDetail = value;\r
+                NotifyOfPropertyChange(()=>BusyDetail);\r
+            }\r
+        }\r
+\r
+        private void SetBusy(string title,string detail)\r
+        {\r
+            IsWorking = true;\r
+            BusyTitle = title;\r
+            BusyDetail = detail;\r
+        }\r
+\r
+        private void ClearBusy()\r
+        {\r
+            IsWorking = false;\r
+            BusyTitle = "";\r
+            BusyDetail = "";\r
+            \r
+        }\r
+\r
+        public async Task TestAccount()\r
+        {\r
+            try\r
+            {\r
+                SetBusy("Validating Credentials", "");\r
+                var client = new CloudFilesClient(AccountName, Token) { AuthenticationUrl = CurrentServer,/*Proxy=Proxy */};\r
+                await client.Authenticate().ConfigureAwait(false);\r
+                await client.ListContainers(AccountName).ConfigureAwait(false);\r
+                HasValidCredentials = true;\r
+                ValidationMessage = "Credentials Validated";\r
+            }\r
+            catch\r
+            {\r
+                HasValidCredentials = false;\r
+                MessageBox.Show("The account is not valid", "Account Error", MessageBoxButton.OK, MessageBoxImage.Stop);\r
+                ValidationMessage = "Credentials validation failed";\r
+            }\r
+            finally\r
+            {\r
+                ClearBusy();\r
+            }\r
+        }\r
+\r
+    }\r
+}\r