2 // AccountSettingsViewController.m
5 // Created by Mike Mayo on 12/14/10.
6 // The OpenStack project is provided under the Apache 2.0 license.
9 #import "AccountSettingsViewController.h"
10 #import "OpenStackAccount.h"
11 #import "AccountManager.h"
12 #import "APICallback.h"
13 #import "ActivityIndicatorView.h"
15 #import "RSTextFieldCell.h"
16 #import "UIColor+MoreColors.h"
17 #import "OpenStackAppDelegate.h"
18 #import "UIViewController+Conveniences.h"
19 #import "OpenStackRequest.h"
23 #define kDisplayname 2
25 @implementation AccountSettingsViewController
27 @synthesize account, username, authToken, displayname;
29 #pragma mark - View lifecycle
31 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
32 return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
37 self.navigationItem.title = @"Authentication";
38 userDetailsSection = 0;
40 displayname = [[self.account displaynameForUUID:self.account.username safe:NO] retain];
42 self.navigationItem.rightBarButtonItem.enabled = NO;
45 #pragma mark - Memory management
50 [displayname release];
55 #pragma mark - Internal
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]));
64 #pragma mark - Properties
66 - (void)setUsername:(NSString *)aUsername {
68 username = [aUsername retain];
69 self.displayname = [self.account displaynameForUUID:username safe:NO];
70 [self updateSaveButtonForUsername:username andAuthToken:authTokenTextField.text];
73 - (void)setAuthToken:(NSString *)anAuthToken {
75 authToken = [anAuthToken retain];
76 [self updateSaveButtonForUsername:usernameTextField.text andAuthToken:authToken];
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];
89 #pragma mark - Actions
91 - (void)setUsername:(NSString *)aUsername andAuthToken:(NSString *)anAuthToken {
94 username = [aUsername retain];
95 self.displayname = [self.account displaynameForUUID:username safe:NO];
99 authToken = [anAuthToken retain];
101 [self updateSaveButtonForUsername:username andAuthToken:authToken];
104 #pragma mark - UITableViewDataSource
106 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
110 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
111 if (section == userDetailsSection)
117 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
118 if (section == userDetailsSection)
119 return [NSString stringWithFormat:@"%@ Login", self.account.provider.name];
124 - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
125 if (section == userDetailsSection)
126 return @"API Version 1.0";
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];
137 cell = [[[RSTextFieldCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
138 cell.selectionStyle = UITableViewCellSelectionStyleNone;
141 if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
142 cell.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.8];
145 [cell.textLabel setBackgroundColor:[UIColor clearColor]];
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;
169 cell = (RSTextFieldCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
171 cell = [[[RSTextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
174 cell.textLabel.text = @"Get Token";
179 #pragma mark - UITableViewDelegate
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];
190 #pragma mark - UITextFieldDelegate
192 - (BOOL)textFieldShouldReturn:(UITextField *)textField {
193 [textField resignFirstResponder];
194 if ([textField isEqual:usernameTextField]) {
195 [authTokenTextField becomeFirstResponder];
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;
210 #pragma mark - Button Handlers
212 - (void)saveButtonPressed:(id)sender {
213 self.navigationItem.rightBarButtonItem.enabled = NO;
217 #pragma mark - Authentication
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];
229 OpenStackAccount *temporaryAccount = [[[OpenStackAccount alloc] init] autorelease];
230 temporaryAccount.provider = account.provider;
231 temporaryAccount.username = usernameTextField.text;
232 temporaryAccount.authToken = authTokenTextField.text;
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];
245 account.filesURL = [account.provider.authEndpointURL URLByAppendingPathComponent:account.username];
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];
254 failure:^(OpenStackRequest *request) {
255 [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
258 [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
259 self.navigationItem.rightBarButtonItem.enabled = YES;
260 [self alert:@"Authentication Failure" message:@"Please check your UUID and Token."];
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."];
269 [self failOnBadConnection];