アプリに必要なAPIが自分のサーバでさくっと作れるBaasBox。その長旅の途中。
前回の記事ではBaasBoxの環境構築までやった。
BaasBoxの環境構築でつまづいたこと
今回はさらにユーザ管理のところまで深みへ・・・
使用したバージョン
1.0.0-M2
ドキュメント
以下のリンクから今回解説する部分が見れる
http://www.baasbox.com/documentation/#user-management
※ただちょこちょこ間違いもあるので悲しみ
サンプルについて
前回も書いたようにBaasBoxはUnity SDKがないのでサンプルコードも書いた。
サンプルコードで特筆することといえば
・UnityWebRequestを使った(WWWクラスの次世代らしい)
・MiniJsonを使った
※当初はJsonUtilityを使おうと思ったけど、JSONのキーでnewとかX-BB-SESSIONとか変数名で使えないのが出てきたので断念。GSONならいけるんだけどなぁ…
BaasBoxAPIのキホン
どちらかもしくは両方の独自のヘッダをAPIコール時に渡す
アプリコード:X-BAASBOX-APPCODE(未ログイン時必須)
セッション:X-BB-SESSION(ログイン後必須)
ユーザ作成
ユーザ名とパスワードが必須で、visibleXXX系はオプションとして指定可能
private IEnumerator SignUp ()
{
string url = "http://localhost:9000/user";
using (UnityWebRequest request = UnityWebRequest.Post (url, " ")) {
// ヘッダ
request.SetRequestHeader ("Content-type", "application/json");
request.SetRequestHeader ("X-BAASBOX-APPCODE", "1234567890");
// リクエストボディ
IDictionary requestBody = new Dictionary<string, object> ();
requestBody.Add ("username", "user1");
requestBody.Add ("password", "password");
string bodyData = Json.Serialize (requestBody);
UploadHandler uploadHandler = new UploadHandlerRaw (System.Text.Encoding.UTF8.GetBytes (bodyData));
request.uploadHandler = uploadHandler;
// 通信開始
yield return request.Send ();
// 通信結果
string json = request.downloadHandler.text;
if (request.responseCode == 201) {
Debug.Log ("Success >>" + json);
} else {
Debug.Log ("Error >>" + json);
}
}
}
コードに記したように基本的にリクエストボディはJSONで渡す。
ユーザ作成で返ってくるJSONの意味
成功時(レスポンスコード:201の時)はこんな感じのJSONが返ってくる
ユーザ作成以外でも基本的にユーザ情報はこの形なのでここさえおさえればOK
※ただし全部が返ってくるわけではない
{
"result": "ok",
"data": {
"user": {
"name": "cesare",
"status": "ACTIVE",
"roles": [{"name": "registered"}]
},
"id": "6d5d8300-4339-40a5-8688-d1547fec6e05",
"visibleByTheUser": { },
"visibleByFriends": { },
"visibleByRegisteredUsers": {
"_social": { }
},
"visibleByAnonymousUsers": { },
"signUpDate": "2015-06-16T16:20:32.032+0200",
"generated_username": false,
"X-BB-SESSION": "7f943d99-5872-4f0e-9865-a02386ef882b"
},
"http_code": 201
}
result
ok
data.user.name
ユーザ名。同じものはつけられない。
user.status
ユーザが有効か無効かの状態。ただし、BaasBoxのコンソール等からユーザをSuspendをするとユーザ情報自体が取れないので、基本的にACTIVE以外は入らない
roles.name
ロール名が入る。これはBaasBoxのコンソールからも確認できる
id
不変のユーザのID(自動生成)
独自で生成したい時はプラグインのスクリプトからのみ可能。後で出てくるLinkに使う要素。
visibleByTheUser
visibleXXX系はユーザ情報取得時に中のJSONをそのまま返してくれるフィールド。可視性が違うだけで用途は同じで自由に使える。
visibleByTheUserフィールドはログインしたユーザのみが確認できる。なので本人しか見ないデータ引継ぎ用のメアドとかそういうのを入れられる。
他のユーザにユーザ名で検索された時にこのフィールドはnullになる。
visibleByFriends
ユーザ本人とフレンドが見れるフィールド
visibleByRegisteredUsers
ユーザとフレンドと登録ユーザが見れるフィールド
visibleByFriends._social
ユーザとフレンドと登録ユーザが見れるフィールド
SNSログインを使用している時に使えば便利とか
visibleByAnonymousUsers
anonymousなユーザも含めて全員が見れるフィールド
signUpDate
登録日時
generated_username
SNSログインをするとtrueになる
X-BB-SESSION
セッションID。ログインを必須とするAPIを使うときに渡す
エラー時のJSON
{
"result": "error",
"bb_code": 000000000,
"message": "a message explaining the problem in plain English",
"resource": "/login",
"method": "POST",
"request_header": { ......... },
"API_version": "1.0.0-M2"
}
result
error
bb_code
BaasBoxのカスタムエラーコード。見かけることは少ない気がする。
message
エラーの詳細メッセージ
resource
リクエスト先
method
GET、POST、PUTとか
request_header
リクエストヘッダそのまま
API_version
使用しているAPIのバージョン
ログイン
ユーザ名、パスワード、アプリコードをボディに渡す。
ユーザ作成と同じレスポンスが返ってくる
private IEnumerator Login ()
{
string url = "http://localhost:9000/login";
using (UnityWebRequest request = UnityWebRequest.Post (url, " ")) {
// ヘッダ
request.SetRequestHeader ("Content-type", "application/json");
// リクエストボディ
IDictionary requestBody = new Dictionary<string, string> ();
requestBody.Add ("username", "user1");
requestBody.Add ("password", "newpassword");
requestBody.Add ("appcode", "1234567890");
string bodyData = Json.Serialize (requestBody);
UploadHandler uploadHandler = new UploadHandlerRaw (System.Text.Encoding.UTF8.GetBytes (bodyData));
request.uploadHandler = uploadHandler;
// 通信開始
yield return request.Send ();
// 通信結果
string json = request.downloadHandler.text;
if (request.responseCode == 200) {
Debug.Log ("Success >>" + json);
} else {
Debug.Log ("Error >>" + json);
}
}
}
ドキュメントのcurlは誤植でJSONになってないので注意。
ログアウト
pushTokenを渡すとプッシュ通知も通知されないようになるらしい(まだ未検証)
private IEnumerator Logout (string session)
{
string url = "http://localhost:9000/logout";
using (UnityWebRequest request = UnityWebRequest.Post (url, " ")) {
// ヘッダ
request.SetRequestHeader ("X-BAASBOX-APPCODE", "1234567890");
request.SetRequestHeader ("X-BB-SESSION", session);
// 通信開始
yield return request.Send ();
// 通信結果
string json = request.downloadHandler.text;
if (request.responseCode == 200) {
Debug.Log ("Success >>" + json);
} else {
Debug.Log ("Error >>" + json);
}
}
}
ユーザの無効化/有効化
adminアカウントからのみ使用できるので省略。
ユーザ情報の再取得
セッションIDからユーザの情報を取得する。アプリではよく使うと思うAPI
※ドキュメントにはセッション情報(X-BB-SESSION)が返ってくるように書いているが、使用したバージョンでは戻ってこなかったので注意。
public IEnumerator Refresh (string session)
{
string url = "http://localhost:9000/me";
using (UnityWebRequest request = UnityWebRequest.Get (url)) {
// ヘッダ
request.SetRequestHeader ("X-BB-SESSION", session);
// 通信開始
yield return request.Send ();
// 通信結果
string json = request.downloadHandler.text;
if (request.responseCode == 200) {
Debug.Log ("Success >>" + json);
} else {
Debug.Log ("Error >>" + json);
}
}
}
ユーザ情報の更新
visibleXXXを更新する
どういうJSONにするかはアプリによって変わってくるトコロ
public IEnumerator Save (string session, object visibleByTheUser, object visibleByFriends, object visibleByRegisteredUsers, object visibleByAnonymousUsers)
{
string url = "http://localhost:9000/me";
using (UnityWebRequest request = UnityWebRequest.Put (url, " ")) {
// ヘッダ
request.SetRequestHeader ("Content-type", "application/json");
request.SetRequestHeader ("X-BB-SESSION", session);
// リクエストボディ
IDictionary payloadDictionary = new Dictionary<string, object> ();
payloadDictionary.Add ("visibleByTheUser", visibleByTheUser);
payloadDictionary.Add ("visibleByFriends", visibleByFriends);
payloadDictionary.Add ("visibleByRegisteredUsers", visibleByRegisteredUsers);
payloadDictionary.Add ("visibleByAnonymousUsers", visibleByAnonymousUsers);
string bodyData = Json.Serialize (payloadDictionary);
UploadHandler uploadHandler = new UploadHandlerRaw (System.Text.Encoding.UTF8.GetBytes (bodyData));
request.uploadHandler = uploadHandler;
// 通信開始
yield return request.Send ();
// 通信結果
string json = request.downloadHandler.text;
if (request.responseCode == 200) {
Debug.Log ("Success >>" + json);
} else {
Debug.Log ("Error >>" + json);
}
}
}
※引数はJSON
ユーザ情報の取得
ユーザIDを指定してユーザ情報の取得を行う
ログインユーザからみた相手の情報が取得できる。つまりフレンドだったりフレンドじゃなかったりでvisibleXXXを取得できるできないが変わる
public IEnumerator Fetch (string session)
{
string url = "http://localhost:9000/user/user1";
using (UnityWebRequest request = UnityWebRequest.Get (url)) {
// ヘッダ
request.SetRequestHeader ("X-BB-SESSION", session);
// 通信開始
yield return request.Send ();
// 通信結果
string json = request.downloadHandler.text;
if (request.responseCode == 200) {
Debug.Log ("Success >>" + json);
} else {
Debug.Log ("Error >>" + json);
}
}
}
全ユーザ情報の取得
全ユーザの情報を取得する。
条件指定、並べ替え、ページングも可能だがかなり膨大な説明になるので今回は省略する
private IEnumerator FetchAll (string session)
{
string url = "http://localhost:9000/users";
using (UnityWebRequest request = UnityWebRequest.Get (url)) {
// ヘッダ
request.SetRequestHeader (BaasBoxConsts.HeaderSession, session);
// 通信開始
yield return request.Send ();
// 通信結果
string json = request.downloadHandler.text;
if (request.responseCode == 200) {
Debug.Log ("Success >>" + json);
} else {
Debug.Log ("Error >>" + json);
}
}
}
パスワードの変更
ログインユーザの古いパスワードと新しいパスワードを与える
これまでのセッションが無効化されるので、ユーザにログインをさせよう
private IEnumerator ChangePassword (string oldPassword, string newPassword, string session)
{
string url = "http://localhost:9000/me/password";
using (UnityWebRequest request = UnityWebRequest.Put (url, " ")) {
// ヘッダ
request.SetRequestHeader ("Content-type", "application/json");
request.SetRequestHeader ("X-BB-SESSION", session);
// リクエストボディ("new"が使えないので手動シリアライズ)
IDictionary<string,string> requestBody = new Dictionary<string,string> ();
requestBody.Add ("old", oldPassword);
requestBody.Add ("new", newPassword);
string bodyData = Json.Serialize (requestBody);
UploadHandler uploadHandler = new UploadHandlerRaw (System.Text.Encoding.UTF8.GetBytes (bodyData));
request.uploadHandler = uploadHandler;
// 通信開始
yield return request.Send ();
// 通信結果
string json = request.downloadHandler.text;
if (request.responseCode == 200) {
Debug.Log ("Success >>" + json);
} else {
Debug.Log ("Error >>" + json);
}
}
}
ユーザ名の変更
ユーザ名を変更する。既に存在するユーザ名は使えない
これまでのセッションが無効化されるので、ユーザにログインをさせよう
private IEnumerator ChangeUserName (string newUserName, string session)
{
string url = "http://localhost:9000/me/username";
using (UnityWebRequest request = UnityWebRequest.Put (url, " ")) {
// ヘッダ
request.SetRequestHeader ("Content-type", "application/json");
request.SetRequestHeader ("X-BB-SESSION", session);
// リクエストボディ
IDictionary<string,string> requestBody = new Dictionary<string,string> ();
requestBody.Add ("username", newUserName);
string bodyData = Json.Serialize (requestBody);
UploadHandler uploadHandler = new UploadHandlerRaw (System.Text.Encoding.UTF8.GetBytes (bodyData));
request.uploadHandler = uploadHandler;
// 通信開始
yield return request.Send ();
// 通信結果
string json = request.downloadHandler.text;
if (request.responseCode == 200) {
Debug.Log ("Success >>" + json);
} else {
Debug.Log ("Error >>" + json);
}
}
}
パスワードリセット
ログインしていない(できない)ユーザのパスワードをリセットする
visibleByTheUser内のemailフィールドに有効なメールアドレスが必須
ユーザにリンク付きメールが送られるので、そのメール内のリンク先でパスワードを変更する
private IEnumerator ResetPassword ()
{
string url = "http://localhost:9000/user/user1/password/reset";
using (UnityWebRequest request = UnityWebRequest.Get (url)) {
// ヘッダ
request.SetRequestHeader (BaasBoxConsts.HeaderAppCode, BaasBox.Instance.AppCode);
// 通信開始
yield return request.Send ();
// 通信結果
string json = request.downloadHandler.text;
if (request.responseCode == 200) {
Debug.Log ("Success >>" + json);
} else {
Debug.Log ("Error >>" + json);
}
}
}
気になったこと
ユーザ名の大文字小文字
ログイン時にユーザ名の大文字・小文字の違いは判別されない
例えばUSER1で登録するとuser1でもUser1でもログイン可。レスポンスのJSONはUSER1のまま
ユーザの削除はないの?
1.0.0-M3には入るみたい
Allow to delete users via api
メールアドレスからリセットできない?
基本機能にはないのでプラグインで対応する。
Password recovery by email instead of username
参考:プラグインの作り方
Plugin-Engine
ユーザのメールアドレスを確認
現状できない
Optional email confirmation when user registers
パスワードリセットに利用するメールアドレスの設定
Gmail(Google Apps含む)を使う場合はこのあたりを参考にする
プリンタ、スキャナ、アプリケーションからメールを送信するための Google Apps の SMTP 設定
SMTP リレーサービスの設定
その他詳細は下記リンクを参考
Use Cases - Password Recovery with Gmail account
[BaasBox] Password recovery
おわりに
##UnityWebRequestについて
今回の本題ではないが、POSTとかPUTの第2引数が上手く動かなかった。UploadHandlerを使わないとうまくいかないのでその辺りは今後変わりそう。
BaasBoxのユーザ管理について
まだ正式版でない分、痒いところに手が届かないといった様子。エラー処理に関しても細かく分類はできなさそうな点もちょっと気がかり。
ただ、海外ツールにありがちな日本語使えない問題も特になさそうだった。
執筆時点でこの部分を詳しく解説している記事があまりないのでもっと流行ってほしいなという期待も込めた記事となった。
あとは、今後の機能追加に期待したい