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 |
} |