ParseのCloudCodeを使って入力値のvalidationをする

  • 18
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Parse.com を使ってクライアントアプリ開発をする場合、
ACLの書き込み権限のあるユーザなら不正なリクエストによって
どのカラムでも書き換え可能になってしまうため、
ユーザの不正な入力値を拒否するために CloudCode を使って validation する必要がある。

例えばメールアドレス変更のクエリに紛れて User テーブルの birthday カラムを不正に書き換えようとした場合を想定する。
実際の書き換え処理の前に実行したい処理は CloudCode の beforeSave を用いる。
下のコードを main.js に書いて parse deploy すればデプロイされる。

Parse.Cloud.beforeSave("_User", function(request, response) {
    // MASTER_KEYを使った更新、DataBrowserからの更新は成功                                                                                                                                                                                                                               
    if (request.master == true) {
        return response.success();
    }

    var user = request.user;
    // ユーザが存在しない場合(新規登録の場合)は成功
    if (!user) {
        return response.success();
    }

    // 仮に birthday を変更する入力があっても、既に登録されている値を改めて set する
    request.object.set("birthday", user.get("birthday"));
    return response.success();
});

公式ドキュメントにも上記のように
validation する方法が記載されていて、とりあえず問題なく動作する。

しかし、サービスの拡張に伴って影響範囲の洗い出しも困難になってくるので、
そもそもユーザには書き換え権限を与えずに、
PFCloud を使って、サーバサイドでデータ書き換えを扱った方が安全な実装ができる。

Parse.Cloud.define("changeEmail", function(request, response) {
    var user = request.user;
    if (!user) {
        // ログインしていないのでエラー
        return response.error("ERROR: not login");
    }

    var email = request.params.email;

    /* ここで email の文字列を validation をする */

    Parse.Cloud.useMasterKey();
    user.set("email", email);
    user.save(null, {
        success: function(result) {
            return response.success("SUCCESS: change email");
        },
        error: function(result, error) {
            return response.error("ERROR: cannot change email");
        }
    });
}

CloudCode に上記のようなコードを書いて、
クライアントアプリ側で PFCloudのリファレンス を参考に下記のように実行する。

[PFCloud callFunctionInBackground:@"changeEmail"
                   withParameters:[NSDictionary dictionaryWithObject:self.textFieldEmail.text forKey:@"email"]
                            block:^(id result, NSError *error)
{
    if (!error) {
        // サーバ側の処理が成功した場合の処理
    } else {
        // サーバ側の処理が失敗した場合の処理
    }
}];

このように実装しておけば不正にカラムが書き換えられることもない上、
マルチプラットフォーム開発も容易になる。