1st Step

まずは、テキストの認証&アクセス制御のところでやったユーザ登録の手続きを確認してから、 アンケート登録機構を作成していきましょう。

「オプション」と書いてある場所は、余力のある人だけ対応してくれれば OK です。

ユーザ公開情報

テキストの認証&アクセス制御で、realtime DB に以下のような情報を登録してきたので、それをそのまま使いましょう。 uidA などと書いているのは、各ユーザの firebase における User ID です。

{ "protected": {
    "users": {
      "uidA": { ... },
      "uidB": { ... }
    }
  }
}

各ユーザは自分の uid 以下に自身の公開情報を配置します。 アクセス制御ルールも前回同様ですが、認証済みユーザに protected 以下全体の read 権限を与えるため、ルールを少し緩和しています。

{
  "rules": {
    "protected": {
      "users": {
        "$uid": {
          ".write": "$uid === auth.uid",
        }
      },
      ".read": "auth.uid !== null"
    }
  }
}

API も前回のものがそのまま使えます。ただ、このあとユーザ情報以外も扱うので、クラス名をUserDbService から変更して、 あと get, put などのメソッド名も、getUserInfoget_user_info などに変えてもらって構いません(変更を推奨します)。

アンケート機能の概略

最終的に作成するアンケート機能は、こんなものを作ろうと思っています。

  • 全ユーザが質問を登録できる。
    • とりあえず、質問は単純な文字列ってことにしておきましょう。
    • 拡張したい人は、質問&回答を JSON 化してもよいです。
  • 各ユーザが各質問への回答を登録できる。
    • 全ユーザは各質問への回答をすべて閲覧できる。

データ構造はこんな感じにしようかと。

{ "protected": {
    "questions": {
      "qId0": {
        "sender": uidA,
        "content": ...
      },
      "qId1": {
        "sender": uidB,
        "content": ...    
      }
    },
    "answers": {
      "qId0": {
         "uidA": ...,
         "uidB": ...,
      },
      "qId1": { ... }
    }
  }
}
  • 質問は questions 以下に、それぞれ質問識別用の qId をつける(基本 POST で自動でつけてもらう)
    • 作成者を sender とし、修正できるようにする。
  • 回答は answers 以下に、各質問の qId 毎に、各回答者の回答を key-value 形式にまとめて登録する。
    • 回答者は自分の回答を編集できるようにする予定。

security rule

セキュリティルールはとりあえず以下のようにしてください。少しだけ解説するとこんな感じ。

  • protected 以下は認証済みユーザは基本 read できる。
  • protected/users 以下は自分の uid 以下にしか書き込めない
  • protected/questions 以下は、以下の3条件が成立したときのみ書き込み可能
    • 認証済みで
    • 書込み場所にデータがないか、書込み場所データのsenderと書込みユーザが合致し、
    • 書込みデータのsender が書込みユーザと一致する
  • protected/answers/{$qid} は、対応する質問が存在する時、自分の uid 以下にしか書き込めない
{
  "rules": {
    "protected": {
      "users": {
	      "$uid": {
  	      ".write": "$uid === auth.uid"
      	}
      },
      "questions": {
        "$qid": {
          ".write": "auth.uid !== null 
            && (!data.exists() || data.child('sender').val() === auth.uid) 
            && newData.child('sender').val() === auth.uid"
        }
      },
      "answers": {
        "$qid": {
          "$uid": {
            ".write": "auth.uid === $uid && root.child('protected').child('questions').child($qid).exists()"
          }
        }
      }
    },
    ".read": "auth.uid !== null"
  }
}

: questions のルールが 3行にわたっていて copy & paste でうまく認識できないときは、1行に変更してみてください。

アンケート登録・閲覧機能

API は以下のようにしましょうか。

  • 質問登録(POST): 質問用 JSON (sendercontent を保持)と token を引数として渡す
    • Java+GSON 利用者は Question クラスでも作成してください。
    • 返り値は、{ "name": ..... } という形で ... 質問の qid が入っています。
    • オプション: 質問修正用 PUT API も作成したい人はどうぞ。
    • : POST は難しいっていう方は、PUT操作にして、qid と質問用 JSON, token を引数として渡すのでもOKです。
  • 質問一覧取得: token を引数とし、返り値は qid と質問用 JSON のペアのリスト
    • Java+GSON の場合は、Map<String,Question> が返り値
    • python+dict の場合は JSON 相当の dict 要素が返り値
    • オプション: qid を指定して質問を取得したい人は、そのような API も追加してください。

初日は、このあたりまで完成させたいですね。厳しかった人は復習しておきましょう。

回答登録・閲覧機能

ついでに回答登録・閲覧まで完成させたい人はどうぞ。

  • 回答登録(POST PUT です。書き間違えです。すみません。): qid, uid と回答および token を引数に API を呼び出す
    • 回答は Java: String, python: str でよいかと。
    • python の人は json.dumps(str) して Body に渡しましょう
  • 回答一覧取得: qid と token を引数とし、返り値は uid と回答のペアのリスト
    • Java+GSON の場合は、Map<String,String> が返り値
    • python+dict の場合は対応する dict 要素が返り値