Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / Preferences / AddAccountViewModel.cs @ 2f5fcd2f

History | View | Annotate | Download (12.2 kB)

1
#region
2
/* -----------------------------------------------------------------------
3
 * <copyright file="AddAccountViewModel.cs" company="GRNet">
4
 * 
5
 * Copyright 2011-2012 GRNET S.A. All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or
8
 * without modification, are permitted provided that the following
9
 * conditions are met:
10
 *
11
 *   1. Redistributions of source code must retain the above
12
 *      copyright notice, this list of conditions and the following
13
 *      disclaimer.
14
 *
15
 *   2. Redistributions in binary form must reproduce the above
16
 *      copyright notice, this list of conditions and the following
17
 *      disclaimer in the documentation and/or other materials
18
 *      provided with the distribution.
19
 *
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
 * POSSIBILITY OF SUCH DAMAGE.
33
 *
34
 * The views and conclusions contained in the software and
35
 * documentation are those of the authors and should not be
36
 * interpreted as representing official policies, either expressed
37
 * or implied, of GRNET S.A.
38
 * </copyright>
39
 * -----------------------------------------------------------------------
40
 */
41
#endregion
42
using System;
43
using System.Collections.Generic;
44
using System.ComponentModel.Composition;
45
using System.IO;
46
using System.Linq;
47
using System.Text.RegularExpressions;
48
using System.Threading.Tasks;
49
using System.Windows;
50
using System.Windows.Forms;
51
using Pithos.Client.WPF.Properties;
52
using Pithos.Interfaces;
53
using Pithos.Network;
54
using MessageBox = System.Windows.MessageBox;
55
using Screen = Caliburn.Micro.Screen;
56

    
57
namespace Pithos.Client.WPF.Preferences
58
{
59
    [Export(typeof(AddAccountViewModel))]
60
    public class AddAccountViewModel:Screen
61
    {
62

    
63
        private readonly List<string> _servers;
64

    
65
        public List<string> Servers
66
        {
67
            get { return Settings.Default.Servers.Select(server => server.ServerUri).ToList(); }
68
        }
69

    
70
        private bool _isValidServer;
71
        public bool IsValidServer
72
        {
73
            get { return _isValidServer; }
74
            set
75
            {
76
                _isValidServer = value;
77
                NotifyOfPropertyChange(()=>IsValidServer);
78
            }
79
        }
80

    
81

    
82
        private string _currentServer;
83
        public string CurrentServer
84
        {
85
            get { return _currentServer; }
86
            set
87
            {
88
                if (!Uri.IsWellFormedUriString(value, UriKind.Absolute))
89
                {
90
                    IsValidServer = false;
91
                    throw new UriFormatException();
92
                }
93
                _currentServer = value;
94
                IsValidServer = true;
95
                HasValidCredentials = false;
96
                IsConfirmed = false;
97
                NotifyOfPropertyChange(()=>CurrentServer);
98
            }
99
        }
100

    
101
        private string _accountName;
102
        public string AccountName
103
        {
104
            get { return _accountName; }
105
            set
106
            {
107
                _accountName = value;
108

    
109
                NotifyOfPropertyChange(()=>AccountName);
110
                NotifyOfPropertyChange(() => HasCredentials);
111
            }
112
        }
113

    
114
        private string _token;
115
        public string Token
116
        {
117
            get { return _token; }
118
            set
119
            {
120
                _token = value;
121
                NotifyOfPropertyChange(()=>Token);
122
                NotifyOfPropertyChange(() => HasCredentials);
123
            }
124
        }
125

    
126
        private string _accountPath;
127
        public string AccountPath
128
        {
129
            get { return _accountPath; }
130
            set
131
            {
132
                _accountPath = value;
133
                NotifyOfPropertyChange(() => AccountPath);
134
                NotifyOfPropertyChange(() => HasAccountPath);
135
            }
136
        }
137

    
138

    
139
        public bool HasAccountPath
140
        {
141
            get { return !String.IsNullOrWhiteSpace(AccountPath); }
142
        }
143

    
144
        public bool HasCredentials
145
        {
146
            get { return !(String.IsNullOrWhiteSpace(AccountName) || String.IsNullOrWhiteSpace(Token) ) ; }
147
        }
148

    
149

    
150
        private bool  _isConfirmed;
151

    
152
        public bool IsConfirmed
153
        {
154
            get { return _isConfirmed; }
155
            set
156
            {
157
                _isConfirmed = value;
158
                HasValidCredentials = false;
159
                NotifyOfPropertyChange(() => IsConfirmed);
160
            }
161
        }
162

    
163

    
164
        private bool _isAccountActive;
165

    
166
        public bool IsAccountActive
167
        {
168
            get { return _isAccountActive; }
169
            set
170
            {
171
                _isAccountActive = value;
172
                NotifyOfPropertyChange(() => IsAccountActive);
173
            }
174
        }
175

    
176

    
177
        private bool _shouldCreateOkeanosFolder;
178
        public bool ShouldCreateOkeanosFolder
179
        {
180
            get { return _shouldCreateOkeanosFolder; }
181
            set
182
            {
183
                _shouldCreateOkeanosFolder = value;
184
                NotifyOfPropertyChange(()=>ShouldCreateOkeanosFolder);
185
            }
186
        }
187

    
188
        bool HasNoParentWithCache(DirectoryInfo info)
189
        {
190
            if (info == null)
191
                return false;
192
            var parent = info.Parent;
193
            if (parent == null)
194
                return true;
195
            if (parent.EnumerateDirectories(FolderConstants.CacheFolder).Any())
196
            {
197
                return false;
198
            }
199
            return HasNoParentWithCache(parent);
200
        }
201

    
202
        string GetLowestAboveCache(string path)
203
        {
204
            if (String.IsNullOrWhiteSpace(path))
205
                return null;
206
            var info = new DirectoryInfo(path);
207
            if (!info.Exists)
208
                return path;
209
            while (!HasNoParentWithCache(info))
210
            {
211
                info = info.Parent;
212
            }
213
            if (info == null)
214
                return null;
215
            else
216
                return info.FullName;
217
        }
218

    
219
        public void SelectAccount()
220
        {
221
            using (var dlg = new FolderBrowserDialog{Description=Resources.AddAccountViewModel_SelectAccount_Please_select_a_folder})
222
            {
223
                //Ask the user to select a folder
224
                //Note: We need a parent window here, which we retrieve with GetView            
225
                var view = (Window)GetView();
226
                if (DialogResult.OK != dlg.ShowDialog(new Wpf32Window(view)))
227
                    return;
228

    
229
                //If the selected path is under an account folder, ie a folder containint a .pithos.cache subfolder, try to locate
230
                //the cache's parent folder
231
                var selectedPath = GetLowestAboveCache(dlg.SelectedPath);
232

    
233
                //If the path  ends with /okeanos#/pithos, replace with /okeanos#
234
                var match = _okeanosRegex.Match(selectedPath);
235
                if (match.Success)
236
                {
237
                    selectedPath = match.Groups[1].Value;                    
238
                }
239

    
240
                AccountPath= selectedPath;
241

    
242

    
243

    
244
                ShouldCreateOkeanosFolder=Directory.EnumerateFileSystemEntries(AccountPath).Any();                
245
            }
246
        }
247

    
248

    
249
        public void RetrieveCredentials()
250
        {
251
            SetBusy("Waiting for credentials.", "Please enter your credentials in the Pithos logon page");
252
            IsConfirmed = false;
253

    
254
            try
255
            {
256
                var loginUri = PithosAccount.GetLoginUri(CurrentServer);
257
                var credentials = PithosAccount.RetrieveCredentials(loginUri.ToString());
258
                if (credentials == null)
259
                    return;
260
                AccountName = credentials.UserName;
261
                Token = credentials.Password;
262

    
263
                IsConfirmed = true;
264

    
265
            }
266
            catch (PithosException exc)
267
            {
268
                ClearBusy();
269
                MessageBox.Show(exc.Message, "Unable to retrieve credentials");
270
            }
271
            catch (Exception exc)
272
            {
273
                IsConfirmed = false;
274
                MessageBox.Show(exc.ToString(), "Error");
275
                throw;
276
            }
277
            finally
278
            {
279
                ClearBusy();
280
                
281
                ((Window) GetView()).Activate();
282
            }
283

    
284
            if (IsConfirmed)
285
                TaskEx.Run(()=>TestAccount());
286

    
287
        }
288

    
289
        public AddAccountViewModel()
290
        {
291
            _servers=new List<string>
292
                         {
293
                             Settings.Default.ProductionServer, 
294
                             Settings.Default.DevelopmentServer
295
                         };
296
            CurrentServer = _servers[0];
297
            DisplayName = "Add Pithos+ Account";
298
        }
299

    
300
        private bool _hasValidCredentials;
301
        public bool HasValidCredentials
302
        {
303
            get { return _hasValidCredentials; }
304
            set
305
            {
306
                _hasValidCredentials = value;
307
                NotifyOfPropertyChange(()=>HasValidCredentials);
308
            }
309
        }
310

    
311
        private string _validationMessage;
312
        public string ValidationMessage
313
        {
314
            get { return _validationMessage; }
315
            set
316
            {
317
                _validationMessage = value;
318
                NotifyOfPropertyChange(()=>ValidationMessage);
319
            }
320
        }
321

    
322
        private bool _isWorking;
323
        public bool IsWorking
324
        {
325
            get { return _isWorking; }
326
            set
327
            {
328
                _isWorking = value;
329
                NotifyOfPropertyChange(()=>IsWorking);
330
            }
331
        }
332

    
333
        private string _busyTitle;
334
        public string BusyTitle
335
        {
336
            get { return _busyTitle; }
337
            set
338
            {
339
                _busyTitle = value;
340
                NotifyOfPropertyChange(()=>BusyTitle);
341
            }
342
        }
343

    
344
        private string _busyDetail;
345
        private Regex _okeanosRegex = new Regex(@"(.*okeanos[0-9]*)\\pithos$");
346

    
347
        public string BusyDetail
348
        {
349
            get { return _busyDetail; }
350
            set
351
            {
352
                _busyDetail = value;
353
                NotifyOfPropertyChange(()=>BusyDetail);
354
            }
355
        }
356

    
357
        private void SetBusy(string title,string detail)
358
        {
359
            IsWorking = true;
360
            BusyTitle = title;
361
            BusyDetail = detail;
362
        }
363

    
364
        private void ClearBusy()
365
        {
366
            IsWorking = false;
367
            BusyTitle = "";
368
            BusyDetail = "";
369
            
370
        }
371

    
372
        public async Task TestAccount()
373
        {
374
            try
375
            {
376
                SetBusy("Validating Credentials", "");
377
                var client = new CloudFilesClient(AccountName, Token) { AuthenticationUrl = CurrentServer,/*Proxy=Proxy */};
378
                await client.Authenticate().ConfigureAwait(false);
379
                await client.ListContainers(AccountName).ConfigureAwait(false);
380
                HasValidCredentials = true;
381
                ValidationMessage = "Credentials Validated";
382
            }
383
            catch
384
            {
385
                HasValidCredentials = false;
386
                MessageBox.Show("The account is not valid", "Account Error", MessageBoxButton.OK, MessageBoxImage.Stop);
387
                ValidationMessage = "Credentials validation failed";
388
            }
389
            finally
390
            {
391
                ClearBusy();
392
            }
393
        }
394

    
395
    }
396
}