5. チュートリアル2 : ログイン機能

チュートリアル2では、チュートリアル1の Todo アプリにユーザ登録・ログイン機能を追加します。

チュートリアル1ではデータを全員で共有していましたが、 チュートリアル2ではユーザごとにデータを管理するようにします。

5.1. サンプルの実行

チュートリアル1と同じように、デベロッパコンソールからアプリケーションを新たに作成し、 Config.h に設定を行って下さい。

また、デベロッパコンソールから、オブジェクトバケットを作成します。 バケット名は “TodoTutorial2” としてください。 なお、ACL はデフォルトのまま (認証ユーザのみ読み書き可能)で構いません。

アプリを起動すると、ログイン画面が表示されます。 最初にサインアップボタンを押してサインアップ画面に遷移して下さい。 E-mail アドレスとパスワード(8文字以上)を入力してサインアップします。

サインアップが完了したらログインを行って下さい。 チュートリアル1と同様のアプリ画面が表示されます。 データを入れたら、メニューからログアウトしてください。

ログイン画面に戻りますので、今度は違うユーザ名でサインアップを行い、ログインしてみてください。 先ほど作成したデータが、現在のユーザからは見えなくなっていることを確認してください。

5.2. ファイル構成

ログイン関連のファイルとして、以下のものを追加しています。 (これらのファイルは他のプロジェクトへ容易に転用できるようにしてあります)

  • UserLogin.storyboard : ログイン関連の UI の定義 (UIレイアウト、遷移など)
  • LoginViewController.h/.m : ログイン用の View Controller
  • CreateAccountViewController.h/.m : アカウント作成用の View Controller
  • PasswordResetViewController.h/.m : パスワードリセット用の View Controller

5.3. ログイン状態のチェック

TodoListViewController の viewWillAppear: 内で、ログイン状態のチェックを 行うようにしています。

- (void)viewWillAppear:(BOOL)animated
{
    // ログインチェック
    if ([LoginViewController loginCheck:self]) {
        // ログイン状態であれば、Todo をリロードする
        if (self.todos == nil) {
            [self reloadTodos:nil];
        }
    }
}

LoginViewContoroller の loginCheck: は以下のように実装しています。

+ (BOOL)loginCheck:(UIViewController *)viewController
{
    // ログイン状態チェック
    if ([NBUser loggedIn]) {
        return YES;
    }

    // 未ログイン状態の場合は、ログイン画面を表示させる
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"UserLogin" bundle:nil];
    id firstViewControler = [storyboard instantiateInitialViewController];
    [viewController presentViewController:firstViewControler animated:NO completion:nil];
    return NO;
}

ユーザがログインしているかどうかは、NBUser の loggedIn メソッドで確認できます。 戻り値が YES ならログイン済みです。

ログイン済みでなかった場合は、UserLogin.storyboard を読み込みログイン画面を起動します。

5.4. サインアップ

サインアップは CreateAccountViewController クラスで行っています。 具体的には createAccount: メソッド内で行っています。

// 登録処理
NBUser *user = [NBUser new];
user.username = username;
user.email = email;
[user signUpInBackgroundWithPassword:password block:^(NBUser *user, NSError *error) {
    if (!error) {
        [LoginViewController showAlert:@"正常にアカウント登録しました" withTitle:@"Success"];
        [self dismissViewControllerAnimated:YES completion:nil];
    } else {
        [LoginViewController showError:error];
    }
}];

サインアップを行うには、NBUser インスタンスを作成してパラメータを設定したのち、 signUpInBackgroundWithPassword:block: を呼び出します。

サインアップ処理が終了すると、ブロックが呼び出されます。 成功した場合は Alert を表示して View Contorller を閉じます。

5.5. ログイン

ログインは LoginViewController の doLogin: メソッドで行っています。

5.5.1. ログイン処理

// ログイン処理実行
[NBUser logInInBackgroundWithUsername:username email:email password:password block:^(NBUser *user, NSError *error) {
    if (!error) {
        NSLog(@"Login success");
        [self dismissViewControllerAnimated:YES completion:nil];
    } else {
        NSLog(@"Login error : %@", error);
        [self.class showError:error];
        self.usernameField.text = @"";
        self.passwordField.text = @"";
    }
}];

ログインを行うには、NBUser の logInInBackgroundWithUsername:email:password:block: を呼び出します。

ログイン処理が完了すると、ブロックが呼ばれます。 成功した場合は View Controller を閉じ、アプリケーションに戻ります。

5.6. ログアウト処理

ログアウト処理は、TodoListViewController の logout: で行っています。

具体的な処理は LoginViewController の logout: にあります。

if ([NBUser loggedIn]) {
    [NBUser logOutInBackgroundWithBlock:^(NBUser *user, NSError *error) {
        [self loginCheck:viewController];
    }];
}

NBUser の logOutInBackgroundWithBlock: を呼び出してログアウトを行います。

5.6.1. 保存データのアクセス制御

データの保存処理は TodoListViewController の addTodo: で行っており、処理はチュートリアル1と全く同じです。

ただし、ログイン状態で作成したデータには、そのユーザのみがアクセス可能な ACL が 自動的に設定されます。具体的には以下のような ACL が設定されます。

{
    owner: "オーナのユーザID",
    r: [], w: [], c: [], u: [], d: [], admin: []
}

このため、他のユーザが作成したデータは、同一のバケットに入っていても不可視になります。 また、変更することもできません。

なお、チュートリアル1のように未ログイン状態でデータを作成した場合は、 以下のように誰でも読み書き可能な ACL が自動的に設定されます。

{
    r: ["g:anonymous"], w: ["g:anonymous"], c: [], u: [], d: [], admin: []
}