[個人開発]SNSを公開して起こった3つの事件

# 初めに
一週間前にrailsで作ったSNSを公開しました。そこで起こったことを書いていこうと思います。

#作ったアプリ
![453789.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480294/307b1e92-ebd7-82f1-ee72-e880ed5d44c0.png)

AmmotというSNSでコンセプトは「制限の少ない自由な投稿を」です。
文字数制限が6000字まで、画像・動画・PDF・音声は同時に10個まで投稿可能なブログに近いSNSです。今はマークダウンにも対応しています。

https://ammot.net/dashboard

以前にもqiitaで宣伝させていただきました。
[【個人開発】制限のない自由なSNS作ってみた!](https://qiita.com/UTOG/items/d5e6194aaa31b54e97c9)

#事件１　XSS攻撃大量発生
![スクリーンショット 2021-04-14 224914.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480294/7f06ed2c-66bd-2fe5-b16e-0a3e8c785737.png)
![スクリーンショット 2021-04-14 224903.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480294/b28d8db9-607b-9af6-96ad-50383fa2a2ca.png)
![スクリーンショット 2021-04-14 224850.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480294/cd2fde5b-608d-e5e7-a47c-692a7079c876.png)
※一部です

まぁ公開したてのwebアプリあるあるだと思いますが、Qiitaで宣伝して「いっぱい人来るかなー？」なんてワクワクしてたらXSSを狙う投稿が大量発生してちょっと萎えました（普通に使ってくれる人ももちろんいました）。

##事件１の対策

```slim
= sanitize markdown(g.content)
```
html_safeを消してsanitizeを追加するだけ。
[こんな記事](https://qiita.com/ei-ei-eiichi/items/0c2bb126b858a62a39e5)もあるがtagsやattributesを設定しなくてもsanitize だけで十分対策になる。
逆にtagsなどを書くとシンタックスハイライトができなくなったので注意です。

てかhtml_safeってなんでこんな使われてるんでしょうか？名前に反して結構危険なメソッドなのに...。

#事件2　速度おっそ！！
ログなどは取り忘れましたがログイン後のトップページを開くのに10秒くらいかかってました。
SNSに速度はかなり重要なのに...。
開発環境では結構いいPCを使っているのでパフォーマンスとか全く気にせず作っていました。

## 事件２の対策
###countメソッドを徹底的に消す。

```slim
//悪い例
= g.comments.count
= g.likes.count
```

こういう文よく見ますよね。ただまじでこれはやめたほうがいいです。自分の場合、countメソッドからlengthメソッドに変えただけで速度が倍くらいになった。countメソッド怖ええ..

```slim
//良い例
= g.comments.pluck(:id).length
= g.likes.pluck(:id).length
```

動作は全く変わりません。

### キャッシュに対応する
キャッシュに対応するだけでActiveRecordが3分の1くらいになります。
ただこれが３つ目の事件となります。


#事件３　キャッシュ
自分はキャッシュに触れるのが初めてだったので???って状態でした。やっとキャッシュに対応したと思いリリースしたらバグの連続。

・無限スクロールが動かない
・違うユーザーの投稿が自分の投稿一覧に現れる
・てかそもそも全然早くないしむしろ遅くなった気がする
などなど

この時に修正しようと何度も連続でアプデしたのでサーバーが重くなりどんどん動作が遅くなり...利用者が減ったのかなと考えています。
一回すべて取っ払いシンプルにコレクションキャッシュで実装したらうまくいきました。

```ruby
  def dashboard
    #フォローしてるユーザーと自分の投稿を取得
    @posts = Post.where(user_id: [current_user.id, *current_user.following_ids]).where(public: true).order(created_at: :desc).page(params[:page]).without_count.per(20)
  end
```

```slim:dashboard
h1 dashboard
= render "datas", posts: @posts
```

```slim:_datas.html.slim
.jscroll
//投稿かいいねかリツイートされたらキャッシュキーが更新される
  = render partial: 'data', collection: posts, as: "g", cached: -> (g) { [g, g.likes.ids, g.reports.ids] } 
  .none
    = link_to_prev_page posts, '前のページ', class: "prev"
    = link_to_next_page posts, '次のページ', class: "next"

javascript:
  $('.jscroll').jscroll({
    contentSelector: '.jscroll', 
    nextSelector: 'a.next',
    loadingHtml: '読み込み中'
  });
```

```slim:_data.html.slim
= g.content
```

こんな感じでうまくいきました。

###番外編　windows redisの入れ方

最初キャッシュで困ったのがwindowsでredisをダウンロードする記事が見当たらないこと。
なので自分が忘れないためにもここに書いておきます。

1: https://github.com/microsoftarchive/redis/releases/tag/win-3.2.100
にアクセスして一番上の.msiをダウンロード。すこし更新日が古いですがこれが最新のようです。

2: 出来たらダウンロードしたものを起動してNEXT連打。最後のfinishまで変更する場所は特にありません。

3: 動作確認

```
redis-server
```
ターミナルで実行

# まとめ
・html_safeとcountには気を付けろ
・キャッシュはしっかり動作確認をしよう
・XSS攻撃はやめてくれ
・Qiitaのトップページをトレンドに戻してくれ
・Ammot使ってみてくれ

↓Ammot URL
https://ammot.net/

↓僕のAmmotのアカウント
https://ammot.net/user/yamada(%E9%96%8B%E7%99%BA%E8%80%85)

↓僕のツイッターのアカウント
https://twitter.com/yamada1531