f6121db5663409ac1164666e819df4e876dc08cd
[pithos-ios] / Classes / AccountSettingsViewController.m
1 //
2 //  AccountSettingsViewController.m
3 //  OpenStack
4 //
5 //  Created by Mike Mayo on 12/14/10.
6 //  The OpenStack project is provided under the Apache 2.0 license.
7 //
8
9 #import "AccountSettingsViewController.h"
10 #import "OpenStackAccount.h"
11 #import "AccountManager.h"
12 #import "APICallback.h"
13 #import "ActivityIndicatorView.h"
14 #import "Provider.h"
15 #import "RSTextFieldCell.h"
16 #import "UIColor+MoreColors.h"
17 #import "OpenStackAppDelegate.h"
18 #import "UIViewController+Conveniences.h"
19 #import "OpenStackRequest.h"
20
21 #define kUsername 0
22 #define kAuthToken 1
23 #define kDisplayname 2
24
25 @implementation AccountSettingsViewController
26
27 @synthesize account, username, authToken, displayname;
28
29 #pragma mark - View lifecycle
30
31 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
32     return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
33 }
34
35 - (void)viewDidLoad {
36     [super viewDidLoad];
37     self.navigationItem.title = @"Authentication";
38     userDetailsSection = 0;
39     getTokenSection = 1;
40     displayname = [[self.account displaynameForUUID:self.account.username safe:NO] retain];
41     [self addSaveButton];
42     self.navigationItem.rightBarButtonItem.enabled = NO;
43 }
44
45 #pragma mark - Memory management
46
47 - (void)dealloc {
48     [username release];
49     [authToken release];
50     [displayname release];
51     [account release];
52     [super dealloc];
53 }
54
55 #pragma mark - Internal
56
57 - (void) updateSaveButtonForUsername:(NSString *)checkUsername andAuthToken:(NSString *)checkAuthToken {
58     self.navigationItem.rightBarButtonItem.enabled = (checkUsername && checkUsername.length &&
59                                                       checkAuthToken && checkAuthToken.length &&
60                                                       (![checkUsername isEqualToString:account.username] ||
61                                                        ![checkAuthToken isEqualToString:account.authToken]));
62 }
63
64 #pragma mark - Properties
65
66 - (void)setUsername:(NSString *)aUsername {
67     [username release];
68     username = [aUsername retain];
69     self.displayname = [self.account displaynameForUUID:username safe:NO];
70     [self updateSaveButtonForUsername:username andAuthToken:authTokenTextField.text];
71 }
72
73 - (void)setAuthToken:(NSString *)anAuthToken {
74     [authToken release];
75     authToken = [anAuthToken retain];
76     [self updateSaveButtonForUsername:usernameTextField.text andAuthToken:authToken];
77 }
78
79 - (void)setDisplayname:(NSString *)aDisplayname {
80     BOOL reloadDisplayname = (displayname && ![displayname isEqualToString:aDisplayname]) || (!displayname && aDisplayname);
81     [displayname release];
82     displayname = [aDisplayname retain];
83     if (reloadDisplayname) {
84         [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:kDisplayname inSection:userDetailsSection]]
85                               withRowAnimation:UITableViewRowAnimationNone];
86     }
87 }
88
89 #pragma mark - Actions
90
91 - (void)setUsername:(NSString *)aUsername andAuthToken:(NSString *)anAuthToken {
92     if (aUsername) {
93         [username release];
94         username = [aUsername retain];
95         self.displayname = [self.account displaynameForUUID:username safe:NO];
96     }
97     if (anAuthToken) {
98         [authToken release];
99         authToken = [anAuthToken retain];
100     }
101     [self updateSaveButtonForUsername:username andAuthToken:authToken];
102 }
103
104 #pragma mark - UITableViewDataSource
105
106 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
107     return 2;
108 }
109
110 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
111     if (section == userDetailsSection)
112         return 3;
113     else
114         return 1;
115 }
116
117 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
118     if (section == userDetailsSection)
119         return [NSString stringWithFormat:@"%@ Login", self.account.provider.name];
120     else
121         return nil;
122 }
123
124 - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
125     if (section == userDetailsSection)
126         return @"API Version 1.0";
127     else
128         return nil;
129 }
130
131 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
132     static NSString *CellIdentifier = @"Cell";
133     RSTextFieldCell *cell = nil;
134     if (indexPath.section == userDetailsSection) {
135         cell = (RSTextFieldCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
136         if (cell == nil) {
137             cell = [[[RSTextFieldCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
138             cell.selectionStyle = UITableViewCellSelectionStyleNone;
139         }
140         
141         if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
142             cell.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.8];
143         }
144         
145         [cell.textLabel setBackgroundColor:[UIColor clearColor]];
146         
147         if (indexPath.row == kUsername) {
148             cell.textLabel.text = @"UUID";
149             cell.userInteractionEnabled = YES;
150             cell.textField.delegate = self;
151             cell.textField.returnKeyType = UIReturnKeyNext;
152             cell.textField.text = (username ? username : self.account.username);
153             usernameTextField = cell.textField;
154         } else if (indexPath.row == kAuthToken) {
155             cell.textLabel.text = @"Token";
156             cell.userInteractionEnabled = YES;
157             cell.textField.delegate = self;
158             cell.textField.returnKeyType = UIReturnKeyDone;
159             cell.textField.text = (authToken ? authToken : self.account.authToken);
160             authTokenTextField = cell.textField;
161         } else if (indexPath.row == kDisplayname) {
162             cell.textLabel.text = @"User";
163             cell.userInteractionEnabled = NO;
164             cell.textField.textColor = [UIColor grayColor];
165             cell.textField.delegate = nil;
166             cell.textField.text = displayname;
167         }
168     } else {
169         cell = (RSTextFieldCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
170         if (cell == nil) {
171             cell = [[[RSTextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
172         }
173         
174         cell.textLabel.text = @"Get Token";
175     }
176     return cell;
177 }
178
179 #pragma mark - UITableViewDelegate
180
181 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
182     if (indexPath.section == getTokenSection) {
183         NSString *protocol = [[[[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"] objectAtIndex:0] objectForKey:@"CFBundleURLSchemes"] objectAtIndex:0];
184         NSString *loginURL = [NSString stringWithFormat:@"%@?next=%@://login&force=", account.provider.loginURL, protocol];
185         [[UIApplication sharedApplication] openURL:[NSURL URLWithString:loginURL]];
186         [tableView deselectRowAtIndexPath:indexPath animated:NO];
187     }
188 }
189
190 #pragma mark - UITextFieldDelegate
191
192 - (BOOL)textFieldShouldReturn:(UITextField *)textField {
193     [textField resignFirstResponder];
194     if ([textField isEqual:usernameTextField]) {
195         [authTokenTextField becomeFirstResponder];
196     }
197     return NO;
198 }
199
200 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
201     NSString *result = [textField.text stringByReplacingCharactersInRange:range withString:string];
202     if ([textField isEqual:usernameTextField]) {
203         self.username = result;
204     } else if ([textField isEqual:authTokenTextField]) {
205         self.authToken = result;
206     }
207     return YES;
208 }
209
210 #pragma mark - Button Handlers
211
212 - (void)saveButtonPressed:(id)sender {
213     self.navigationItem.rightBarButtonItem.enabled = NO;
214     [self authenticate];
215 }
216
217 #pragma mark - Authentication
218
219 - (void)authenticate {
220     if (!usernameTextField.text || [usernameTextField.text isEqualToString:@""]) {
221         [self alert:nil message:@"Please enter your UUID."];
222         self.navigationItem.rightBarButtonItem.enabled = YES;
223         [usernameTextField becomeFirstResponder];
224     } else if (!authTokenTextField.text || [authTokenTextField.text isEqualToString:@""]) {
225         [self alert:nil message:@"Please enter your Token."];
226         self.navigationItem.rightBarButtonItem.enabled = YES;
227         [authTokenTextField becomeFirstResponder];
228     } else {
229         OpenStackAccount *temporaryAccount = [[[OpenStackAccount alloc] init] autorelease];
230         temporaryAccount.provider = account.provider;
231         temporaryAccount.username = usernameTextField.text;
232         temporaryAccount.authToken = authTokenTextField.text;
233         
234         __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Authenticating..."
235                                                                                                        andAddToView:self.view];
236         [[temporaryAccount.manager authenticate]
237          success:^(OpenStackRequest *request) {
238              if ([request isSuccess]) {
239                  account.username = request.account.username;
240                  account.authToken = request.account.authToken;
241                  NSString *storageURLString = [[request responseHeaders] objectForKey:@"X-Storage-Url"];
242                  if (storageURLString) {
243                      account.filesURL = [NSURL URLWithString:storageURLString];
244                  } else {
245                      account.filesURL = [account.provider.authEndpointURL URLByAppendingPathComponent:account.username];
246                  }
247                  [account persist];
248                  [[account.manager userCatalogForDisplaynames:nil
249                                                         UUIDs:[NSArray arrayWithObject:account.username]]
250                   success:^(OpenStackRequest *request) {
251                       [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
252                       self.displayname = [account displaynameForUUID:account.username safe:NO];
253                   }
254                   failure:^(OpenStackRequest *request) {
255                       [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
256                   }];
257              } else {
258                  [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
259                  self.navigationItem.rightBarButtonItem.enabled = YES;
260                  [self alert:@"Authentication Failure" message:@"Please check your UUID and Token."];
261              }
262          }
263          failure:^(OpenStackRequest *request) {
264              [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
265              self.navigationItem.rightBarButtonItem.enabled = YES;
266              if ([request responseStatusCode] == 401) {
267                  [self alert:@"Authentication Failure" message:@"Please check your UUID and Token."];
268              } else {
269                  [self failOnBadConnection];
270              }
271          }];
272     }
273 }
274
275 @end