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 "ActivityIndicatorView.h"
13 #import "RSTextFieldCell.h"
14 #import "UIColor+MoreColors.h"
15 #import "OpenStackAppDelegate.h"
16 #import "UIViewController+Conveniences.h"
17 #import "OpenStackRequest.h"
22 @implementation AccountSettingsViewController
24 @synthesize account, username, authToken, activityIndicatorView;
26 #pragma mark - View lifecycle
28 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
29 return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
34 self.navigationItem.title = @"API Account Info";
35 userDetailsSection = 0;
38 self.navigationItem.rightBarButtonItem.enabled = NO;
41 #pragma mark - Memory management
46 [activityIndicatorView release];
51 #pragma mark - Internal
53 - (void) updateSaveButtonForUsername:(NSString *)checkUsername andAuthToken:(NSString *)checkAuthToken {
54 self.navigationItem.rightBarButtonItem.enabled = (checkUsername.length && checkAuthToken.length &&
55 (![checkUsername isEqualToString:account.username] ||
56 ![checkAuthToken isEqualToString:account.authToken]));
59 #pragma mark - Properties
61 - (void)setUsername:(NSString *)aUsername {
63 username = [aUsername retain];
65 [self updateSaveButtonForUsername:username andAuthToken:authTokenTextField.text];
68 - (void)setAuthToken:(NSString *)anAuthToken {
70 authToken = [anAuthToken retain];
72 [self updateSaveButtonForUsername:usernameTextField.text andAuthToken:authToken];
75 #pragma mark - UITableViewDataSource
77 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
81 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
82 if (section == userDetailsSection)
88 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
89 if (section == userDetailsSection)
90 return [NSString stringWithFormat:@"%@ Login", self.account.provider.name];
95 - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
96 if (section == userDetailsSection)
97 return @"API Version 1.0";
102 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
103 static NSString *CellIdentifier = @"Cell";
104 RSTextFieldCell *cell = nil;
105 if (indexPath.section == userDetailsSection) {
106 cell = (RSTextFieldCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
108 cell = [[[RSTextFieldCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
109 cell.selectionStyle = UITableViewCellSelectionStyleNone;
112 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
113 cell.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.8];
116 [cell.textLabel setBackgroundColor:[UIColor clearColor]];
118 if (indexPath.row == kUsername) {
119 cell.textLabel.text = @"Username";
120 usernameTextField = cell.textField;
121 usernameTextField.delegate = self;
122 usernameTextField.secureTextEntry = NO;
123 usernameTextField.returnKeyType = UIReturnKeyNext;
125 usernameTextField.text = username;
127 usernameTextField.text = self.account.username;
129 } else if (indexPath.row == kAuthToken) {
130 cell.textLabel.text = @"Token";
131 authTokenTextField = cell.textField;
132 authTokenTextField.secureTextEntry = NO;
133 authTokenTextField.delegate = self;
134 authTokenTextField.returnKeyType = UIReturnKeyDone;
136 authTokenTextField.text = authToken;
138 authTokenTextField.text = self.account.authToken;
142 cell = (RSTextFieldCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
144 cell = [[[RSTextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
147 cell.textLabel.text = @"Get Token";
152 #pragma mark - UITableViewDelegate
154 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
155 if (indexPath.section == getTokenSection) {
156 NSString *loginURL = [NSString stringWithFormat:@"%@?next=pithos://login&force=", account.pithosLoginURLPrefix];
157 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:loginURL]];
158 [tableView deselectRowAtIndexPath:indexPath animated:NO];
162 #pragma mark - UITextFieldDelegate
164 - (BOOL)textFieldShouldReturn:(UITextField *)textField {
165 [textField resignFirstResponder];
166 if ([textField isEqual:usernameTextField]) {
167 [authTokenTextField becomeFirstResponder];
172 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
173 NSString *result = [textField.text stringByReplacingCharactersInRange:range withString:string];
174 if ([textField isEqual:usernameTextField]) {
175 self.username = result;
176 } else if ([textField isEqual:authTokenTextField]) {
177 self.authToken = result;
182 #pragma mark - Button Handlers
184 - (void)saveButtonPressed:(id)sender {
185 self.navigationItem.rightBarButtonItem.enabled = NO;
189 #pragma mark - HTTP Response Handlers
191 - (void)authenticationSucceded:(OpenStackRequest *)request {
192 [self.activityIndicatorView removeFromSuperview];
193 if ([request isSuccess]) {
194 account.username = request.account.username;
195 account.authToken = request.account.authToken;
196 NSString *storageURLString = [[request responseHeaders] objectForKey:@"X-Storage-Url"];
197 if (storageURLString) {
198 account.filesURL = [NSURL URLWithString:storageURLString];
200 account.filesURL = [[account.hostURL URLByAppendingPathComponent:@"v1"] URLByAppendingPathComponent:account.username];
204 self.navigationItem.rightBarButtonItem.enabled = YES;
205 [self alert:@"Authentication Failure" message:@"Please check your Username and Token."];
209 - (void)authenticationFailed:(OpenStackRequest *)request {
210 [self.activityIndicatorView removeFromSuperview];
211 self.navigationItem.rightBarButtonItem.enabled = YES;
212 if ([request responseStatusCode] == 401) {
213 [self alert:@"Authentication Failure" message:@"Please check your Username and Token."];
215 [self failOnBadConnection];
219 - (void)authenticate {
220 if (!usernameTextField.text || [usernameTextField.text isEqualToString:@""]) {
221 [self alert:nil message:@"Please enter your Username."];
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 self.activityIndicatorView = [[[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:@"Authenticating..."] text:@"Authenticating..."] autorelease];
235 [self.activityIndicatorView addToView:self.view];
237 OpenStackRequest *request = [OpenStackRequest authenticationRequest:temporaryAccount];
238 request.delegate = self;
239 request.didFinishSelector = @selector(authenticationSucceded:);
240 request.didFailSelector = @selector(authenticationFailed:);
241 [request startAsynchronous];