匿名SNSを覚えたてのFirebaseで3時間で作ったらWeb1.0が爆誕した

クソアプリアドベントカレンダー 5日目の投稿がないので代打します。 @ampersand です。

# 完全匿名SNSつくりました
https://tan-tubo.firebaseapp.com/
![ogp.gif](https://qiita-image-store.s3.amazonaws.com/0/7193/e14270a2-fddd-5c8d-d2ce-1f445db4dcd7.gif)

## 全景
<img width="450" alt="スクリーンショット 2018-12-06 1.55.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/7193/51f4caa9-3234-1111-3cba-d68e71ad7937.png">

## SNS上で行われる微笑ましい会話
<img width="450" alt="スクリーンショット 2018-12-05 13.47.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/7193/98b1774a-446d-db68-0c2b-2c6235eb1585.png">


# Firebase勉強したので復習がてら３時間で作った話
動作環境なんて何でもさくらVPS使ったらええできるやんけガハハって過ごしてた脳筋ゴリラの自分なのですが、いい加減にモダンなMBaaSだのPaaSだの使えないと恥ずかしいかもな〜と感じていた所、開発者ギルドというコミュニティでお世話になっている[morixさん](https://twitter.com/morix1500)が講師となってハンズオン会を開催してくれるイベントがあったので参加させてもらい、勉強した内容を振り返って作りました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">あんどさんのスピード感が早すぎてマジやばい<br>まさか翌日サービスできてるとは思わなかったわい <a href="https://t.co/R5rhJMtLzJ">https://t.co/R5rhJMtLzJ</a></p>&mdash; Morix💪😼✨ (@morix1500) <a href="https://twitter.com/morix1500/status/1070118921003446272?ref_src=twsrc%5Etfw">2018年12月5日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

サッと作れたのは講師が良かったおかげです。改めてありがとうございます。

# 学習内容と使った知識
firebaseとは、という概要やメリット・デメリットの話を聞いた後、
https://github.com/firebase/quickstart-js
firebaseのクイックスタートチュートリアルの内容をなぞって進行しました。

## 前段処理
firebaseにログインが必要です。コンソールからログイン（ブラウザで確認すると完了）

```
【必要なnpmモジュールをグローバルインストール】
npm install -g firebase-tools 

　【firebaseにログイン。仮想マシン使ってる人は --no-localhost のオプション指定とポートフォワーディングが必要とのこと】
firebase login
```

## Authentication
Firebaseの認証機能。利用する機能の設定をONにするだけであっという間に認証処理が使えるようになる。（逆にここの設定を忘れてるとうんともすんとも言わない）
<img width="966" alt="スクリーンショット 2018-12-06 1.22.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/7193/6574a6a4-00e9-9014-7dd0-0977ffc5d2c4.png">

### 匿名ログイン機能
認証情報無しでユーザの一意情報を識別できる匿名ログインという機能が有ることを知る。自前で実装するのは結構大変だった([このアプリ](https://meeemo.space/)でログイン無しで使えるようにするために作ったことがあったけど、途中から認証ユーザに切り替えるとかで見落としがないかとかが大変）のが、こんなに手軽にやれるのか。となかなか嬉しくなりました。

実装は https://github.com/firebase/quickstart-js/blob/master/auth/anon.html これを参考に、いらない部分を切り貼りして雑に作成。
これは純粋にログインのみを行っており、ログインされたかの状態を監視して何かする処理は別になるのでそれは参考側の方を見ていただくほうがいいと思います。


```js
// 匿名ログインに必要な処理はこれだけ
firebase
  .auth()
  .signInAnonymously()
  .catch(function(error) {
    var errorCode = error.code;
    if (errorCode === "auth/operation-not-allowed") {
      alert("You must enable Anonymous auth in the Firebase Console.");
    } else {
      console.error(error);
    }
  });

```

匿名ログインをさせることで、なんかやべーことがあっても発信元を追跡するための情報を保存しておけるようになりました（後述のメッセージの発信とログイン者が紐づくためです。万が一犯罪予告とかやべーもんがあったときに追跡できる情報を残してあるよ、という程度で誰が誰なのかはマジでわかりませんし知るすべもありません。）


## Functions
firebase functionsとはサーバーサイドで行う処理を実装できるものになります。執筆当時現在はサーバサイドの処理はnode.jsでのみ記述可能とのこと。
参考はこちら https://github.com/firebase/quickstart-js/tree/master/functions

サーバーでなんかやれるということ＋画面デモでなんかログインしてからメッセージ投稿できるやつを見かけて「これ使ったらまあまぁなんかできそう」感を得る。

サンプルの内容としては投稿された内容が文字列であるかどうか、空でないかどうかや、サブミットされた際にユーザ情報が存在しているか（ログイン済みか）などを確認している。以下抜粋

```js
exports.addMessage = functions.https.onCall((data, context) => {
  // postされた本文データ
  const text = data.text;
  // 本文が文字列か？空ではないか？
  if (!(typeof text === 'string') || text.length === 0) {
    throw new functions.https.HttpsError('invalid-argument', '本文が投稿されてないぞ〜');
  }

  /* 以下、サニタイズ処理やDBへの保存処理 */
```
わかりやすいですね。文字列長制限をしたければここにかけばいいわけです。
また、firebase の databaseの設定に文字列やその他のバリデーション制限となるruleを設定して、バリデーションエラーを返却させるという方法でデータの内容にルール付けを行うということも教えてもらいました。

文字列長チェックはruleでやってエラーを返却してやるという方が実装としても方法としてもスマートな形であると思います（今回、どうやるんだっけ？って悩んだので一旦リリースしてしまいました）

## Hosting
Firebaseの設定ファイルと配置構造が揃っていれば

```
firebase deploy
```
ってやるだけでデプロイできちゃうの反則すぎませんか。今までVPSだけ使ってた脳筋ゴリラは文明の明るさに目がやられるところでした。

この体験を試すには
https://github.com/firebase/quickstart-js/tree/master/functions

この位置で以下のコマンドを実行します

```
【firebase functionsを使うためのなんかだと思う】
npm --prefix functions install 

 【このプロジェクトを使う確認（だっけ？）。プロジェクトのエイリアスを聞かれるので適宜入力する】
firebase use --add 

【これこれ〜！！！これでデプロイできちゃう。すごい。】
firebase deploy  

【デプロイされたサイトがインターネットにあるのを見られる！すごい！】
firebase open hosting:site  
```

## 反省点とセキュリティ周りの話
ちょっとリリース後に一個失敗してしまったことが有りまして、改行表示対応させるために改行コードを`<br>`タグに変換してタグとして評価されるようにする形でリストにappendしたら、他のタグも評価されるようになってしまい、XSSが発生する状況になってしまっていました（現在は修正済み）。
かなり長い文字数を投稿できる仕様にしていたため、やろうと思えばめちゃくちゃ悪いスクリプトを流して閲覧してた人を攻撃することができるという危険な状況を作ってしまっていました。初歩の対策なのにもかかわらず、幾ら習作であろうとも人前に出したアプリでそういったミスを起こすのは大惨事を起こしていた可能性もあるので本当に反省すべき点となりました。
alertだけで済ませてくれたXSSニキ、ありがとうやで。
最近、初学者の方がプログラミングを勉強する機運も高まってきているようなので、自分の失敗を踏まえてきちんと啓蒙できたらと思います。


## UIとか
なんかもう特に考えてません。アングラ感的なイメージで昔の侍魂（アラサー用語）のオマージュで黒背景、白文字、赤アクセントにしました。
後はなんとなく見た目を整えたりして完成です。


## Firebaseって無料で大抵なんとかなるんでしょ！？すごいじゃん！！
って思っていたんですけども、予想外に沢山人が・・・というか、何故かチャットみたいに使われるようになり、投稿数が予想より遥かに多くなってしまい、無料枠からはみ出してしまいました。それと同時に機能が動かなくなるためメチャメチャ問い合わせが来ました。ふぇぇ〜〜〜〜！！

<img width="417" alt="スクリーンショット 2018-12-06 1.57.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/7193/6ee3a4f1-c118-7198-3656-c25fb2225c04.png">

みんなきゃっきゃしてんな〜〜！！

<img width="690" alt="スクリーンショット 2018-12-05 22.34.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/7193/46ce5152-b72a-572d-784b-2ac81b2c1e34.png">

お金払うと解決するよっていうエラーメッセージが出ました。
ので、とりあえず２５ドル払いました。脳筋ゴリラなのであんまり細かいことは気にしません。ただ、課金はしましたがこういうのは多分数日したら廃れるんじゃないかなという気持ちはしています。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">笑わせてもらったから気にすんなよ！ <a href="https://t.co/4tNDivEbqG">pic.twitter.com/4tNDivEbqG</a></p>&mdash; あんど＠クイズをよろしく頼むよ (@ampersand_xyz) <a href="https://twitter.com/ampersand_xyz/status/1070312732786741248?ref_src=twsrc%5Etfw">2018年12月5日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# やってみてわかったこと

+ Firebaseは確かにサッとホスティングできるし、今回みたいにバンバン投稿されないような作りにしてる限りは無料枠で十分収まると思う。クソアプリアドベントカレンダーにうってつけ過ぎてビックリした。
    + ただFirebaseを使って不特定多数がワイワイやるチャット（にするつもりはなかったけどそうなった）を作ったりするには制限数が足りない。
+ FirebaseでのKVSの設計には慣れがいりそう
    + ここはまだ自分がKVSの取り回し方を分かっていない部分が大きいけれども、基本APIをコールする回数やDBを参照する回数は抑えないといけないという前提を踏まえて設計しなくてはいけない。マスタになるデータの変更を一括アップデートする方法や反映までのラグが致命的になるような場合は難しそうだけど、ある程度の雑さが許容されるなら有り。
    + この辺りの許容できる複雑さの温度感は分からないけど、RDBで言うところの中間エンティティ一つもたせるだけでもコツがいりそうだなーと感じた。逆にそれさえ分かってしまえばすごく良い使い方ができるのかもしれない。
+ 結局良いとか悪いのはなしではなく、規模や用途にあった環境で開発するのが良い。
    + 自分はまたさくらのVPSのお世話になります。

### 余談的なわかったこと
+ インターネット老人会文化は意外とまだまだ需要がある感じがする
+ SNS疲れしてる人は多いのかもしれない
+ もっと殺伐とするかと思ったら意外と和やかムードで和んだ。やさしいいんたーねっと。
+ 匿名チャットやってスッキリして元気になったというフィードバックがあって、たとえお世辞だとしても大変うれしかった。痰壺なのに…。

#### ZARDの歌をテンポよく歌えない痰壺民
<img width="383" alt="スクリーンショット 2018-12-05 20.45.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/7193/accaf8c9-f960-f9c0-a69e-4e090a997482.png">

ここには確かにWeb1.0が生まれた。

以上、代打記事をお届けしました〜。