Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ニコニコ漫画と認可

fusagiko
September 29, 2020

 ニコニコ漫画と認可

Gotanda.rb#46 "管理画面/権限" https://gotanda-rb.connpass.com/event/187557/ にて発表した内容です。

fusagiko

September 29, 2020
Tweet

Other Decks in Programming

Transcript

  1. ニコニコ漫画と認可
    2020/9/29
    株式会社トリスタ
    フサギコ(髙﨑 尚人)

    View full-size slide

  2. 自己紹介
    • 名前:フサギコ
    • Twitter :fusagiko
    • GitHub :takayamaki
    • 本名 :髙﨑 尚人
    • 主な分野:Ruby(Rails), Terraform(AWS)
    • 他に :TypeScript, React, Ansible
    • Ruby:2.1.2~
    • 大学院生の時に修士論文用のシミュレータを
    Pure Rubyフルスクラッチで書いたのが最初
    • 趣味:アイドルマスター
    • 全作品、それぞれ楽しんでるタイプ

    View full-size slide

  3. 自己紹介(OSS活動)
    • マストドン
    • 本家(tootsuite/mastodon)コントリビュータ
    • 2年弱PR送れてないけどまだcommit数37位らしい
    • imastodon.net構築、運用、管理人
    • アイドルマスターのファン向け非公式マストドン
    • 2017年4月開設
    • アカウント数4817、アクティブ数500/週程度
    • 本家に独自改造が入っている
    • 完全に袂を分かったわけではないのでVariety(変種)と自称
    • 追従は遅れ気味…

    View full-size slide

  4. 自己紹介(仕事)
    • ~ 2016/3 工学院大学大学院
    • 修士(工学) 修論:情報指向ネットワーク
    • 2016/4~2017/7 NHN テコラス株式会社
    • 2017/8~2019/6 株式会社ドワンゴ
    • friends.nico
    • ドワンゴ公式マストドン (サービス終了)
    • N Air
    • ニコニコ生放送向け 配信ソフト
    • 2019/7~現在 株式会社トリスタ
    • 読書メーター
    • 読書愛好家コミュニティサイト
    • ニコニコ漫画
    • UGC/PGC漫画連載プラットフォーム

    View full-size slide

  5. 自己紹介(仕事)
    • ~ 2016/3 工学院大学大学院
    • 修士(工学) 修論:情報指向ネットワーク
    • 2016/4~2017/7 NHN テコラス株式会社
    • 2017/8~2019/6 株式会社ドワンゴ
    • friends.nico
    • ドワンゴ公式マストドン (サービス終了)
    • N Air
    • ニコニコ生放送向け 配信ソフト
    • 2019/7~現在 株式会社トリスタ
    • 読書メーター
    • 読書愛好家コミュニティサイト
    • ニコニコ漫画
    • UGC/PGC漫画連載プラットフォーム

    View full-size slide

  6. ニコニコ漫画と認可
    2020/9/29
    株式会社トリスタ
    フサギコ(髙﨑 尚人)

    View full-size slide

  7. ニコニコ漫画
    ニコニコ漫画

    View full-size slide

  8. ニコニコ漫画
    UGC/PGC漫画連載
    プラットフォーム

    View full-size slide

  9. ニコニコ漫画
    多くの編集部様から
    ご連載頂いています

    View full-size slide

  10. ニコニコ漫画はRailsで…
    ニコニコ漫画は
    Railsで作られている…

    View full-size slide

  11. ニコニコ漫画はRailsで…
    ニコニコ漫画は
    Railsで作られている…

    View full-size slide

  12. ニコニコ漫画はRailsではない
    現行はPHP
    かつ
    モノリシック

    View full-size slide

  13. ニコニコ漫画はPHP
    静画の派生として
    漫画が始まってから10年超え
    2010/8/27に特設ページ扱いで開始…らしい
    by Wikipedia

    View full-size slide

  14. ニコニコ漫画はPHP
    コード構造が結構厳しい

    View full-size slide

  15. ニコニコ漫画はPHP
    テストが
    十分でない

    View full-size slide

  16. Railsでリプレイスしよう
    ビジネスロジックを
    Rails APIサーバとして
    切り出し・リプレイスしよう

    View full-size slide

  17. Railsでリプレイスしよう
    現行のPHPは
    Backends For Frontends的
    立ち位置に寄せていく

    View full-size slide

  18. Railsでリプレイスしよう
    そのRails APIサーバにおける
    認可機構の話をします

    View full-size slide

  19. その前に
    と、その前に

    View full-size slide

  20. 認証と認可
    認証と認可
    それぞれの意味について
    念のため確認

    View full-size slide

  21. 認証と認可
    認証 authentication 認可 authorization
    “それ”が誰であるかを
    確かめること
    to prove that something
    is real
    “それ”に許可を
    与えること
    to give permission for
    something

    View full-size slide

  22. このように
    認可と認証は
    異なる行為

    View full-size slide

  23. 認証と認可
    認可
    しない する





    何もわからないし
    何もさせない
    誰であるかは
    自己申告を信じ、
    操作を許可する


    それが誰かわかるが、
    何もさせない
    それが誰かを識別し、
    誰であるかによって
    操作を許可する

    View full-size slide

  24. 認可 と 認証が間違われるのは
    全部TwitterのOAuthが悪い
    いわゆるログイン連携がしたいだけなら
    認証(”それ”の識別)さえできれば良かったはずなのに

    View full-size slide

  25. 全部TwitterのOAuthが悪い
    閑話休題

    View full-size slide

  26. ニコニコ漫画における権限とは
    ニコニコ漫画で
    権限管理が
    最も必要な場所

    View full-size slide

  27. ニコニコ漫画で権限管理が必要な場所
    編集部様からの
    作品原稿の納入
    作品・各話のメタ情報編集
    公開期間の設定
    など

    View full-size slide

  28. ニコニコ漫画で権限管理が必要な場所
    他編集部の
    公開前の作品が見えたり、
    編集できたりしてはならない

    View full-size slide

  29. 他編集部の作品が弄れてはならない
    これを実現するために
    権限に基づく認可を行う

    View full-size slide

  30. Rubyにおける権限管理のgemの選択肢
    Rubyにおける
    権限管理のgemの選択肢

    View full-size slide

  31. Rubyにおける権限管理のgem
    •CanCanCan
    •Pundit
    •Banken

    View full-size slide

  32. CanCanCan
    • ユーザを中心に、何へどのアクションを認可するか
    DSL的に記述
    • can 【アクション】, 【対象】, 【各種条件】
    • 対象にはActive Record継承したClassも指定できる
    • クエリインターフェイスに統合した形で使えて便利
    • Active Recordに関係ない対象はシンボルで表現
    • can? 【アクション】, 【対象】で判定
    • => Boolean
    • 対象がActive Recordモデルの場合
    • Article.accessible_by(current_ability) とかできる

    View full-size slide

  33. Pundit
    • 認可系gemとしてはおそらくもっとも有名か
    • モデルを中心に、誰にどのアクションを
    認可するか記述
    • ActiveRecordモデルに対する操作タイミングで認
    可を行う
    • 複雑になってきたRailsアプリケーションではモ
    デルとコントローラが一対一ではなくなりがち
    • コントローラごとに認可条件を変えたい場合詰む

    View full-size slide

  34. Banken
    • コントローラのアクションメソッドと認可条件
    を紐づける
    • アクションを中心に、誰に許可するか記述
    • コントローラのアクションメソッドと対応付ける
    ので対象リソースは自ずと導き出せるはず

    View full-size slide

  35. 認可系gemの概観
    権限記述の中心 判定タイミング
    Pubdit モデル モデルへの操作
    Banken アクション コントローラのアクション
    CanCanCan ユーザ
    モデルへの操作
    OR
    任意タイミング

    View full-size slide

  36. ニコニコ漫画は
    権限判定に
    どのgemを使ったか

    View full-size slide

  37. ニコニコ漫画は
    どれも採用しなかった

    View full-size slide

  38. どの認可系gemも使わなかった
    • 現行PHPとDBを共有しながらの順次リプレイス
    • 現行が不完全なレベルベースの認可
    • モデルと必要権限が一対一で対応しない
    • 特定カラムの更新だけ上位権限が要る場合がある
    • アクションメソッドと必要権限も対応しない
    • 「このカラムの更新には上位権限が要る」といった知識を
    BFFに流出させてはならない
    • バルク(一括)操作がある
    • 唯一可能性があったのはCanCanCanだが…
    • どう考えても大規模になるのでメンテしづらそう
    • ユーザの権限情報のDB上の表現からCanCanCanの
    DSLに落とし込める確信が持てなかった

    View full-size slide

  39. gemを使わない…というか使えない
    前述の通り、
    新ニコニコ漫画は
    既にRails的でない部分がある

    View full-size slide

  40. 決めた方針
    更なるRails的でない構造や
    大きな変更が襲来しても
    耐えられるようにしたい

    View full-size slide

  41. そのために
    インターフェイスを決めて
    コードの独立性を保ち、
    変更の影響範囲を狭める
    後続処理と重複したSELECTが多くなるのは妥協、許容する

    View full-size slide

  42. 認可によって知りたいのは
    誰が
    どのような操作を
    どれに対して行えるか

    View full-size slide

  43. 認可の最小限のインターフェイス
    authorize
    (主体, 操作, 対象)
    => boolean

    View full-size slide

  44. 認可の最小限のインターフェイス
    authorize
    (user_id, action, target_ids)
    => boolean

    View full-size slide

  45. 具体的利用例
    エピソード無料公開期間の
    作成を例として
    処理を追いかける
    エピソード:第一話、第二話前半、単行本告知など
    ニコニコ漫画上での公開単位

    View full-size slide

  46. 具体例:無料公開期間を作成するとき
    Api::V1::FreeViewingTermsController#create

    View full-size slide

  47. 具体例:無料公開期間を作成するとき
    ざっくりとした各処理の区分
    バリデーション
    認可
    DB書き込み
    ビューモデル & ビュー

    View full-size slide

  48. 具体例:無料公開期間を作成するとき
    ここで認可部を呼んでいる

    View full-size slide

  49. 認可部のエントリポイント
    authorize!がauthorizeを呼ぶ

    View full-size slide

  50. 認可部のエントリポイント
    authorize!がauthorizeを呼ぶ

    View full-size slide

  51. 認可部のエントリポイント
    target_idsが単体な場合もKernel.#Arrayでカバー

    View full-size slide

  52. 認可部のエントリポイント
    targetによって各Authorizerに分岐

    View full-size slide

  53. 認可部のエントリポイント
    targetの種類はactionから導ける

    View full-size slide

  54. 認可部のエントリポイント
    無料公開期間のAuthorizerへ

    View full-size slide

  55. 無料公開期間のAuthorizer
    各Authorizerの中でまたactionで分岐

    View full-size slide

  56. 無料公開期間のAuthorizer
    各Authorizerの中でまたactionで分岐

    View full-size slide

  57. 無料公開期間のcreate権限判定

    View full-size slide

  58. 無料公開期間のcreate権限判定
    まずEpisodeを引く

    View full-size slide

  59. 無料公開期間のcreate権限判定
    Episodeを不足なく
    取得できたか

    View full-size slide

  60. 無料公開期間のcreate権限判定
    公式連載でない作品の
    エピソードが混ざって
    いないか

    View full-size slide

  61. 無料公開期間のcreate権限判定
    権限付与の単位は作品なので
    エピソードが属するComicを
    Comic::OfficialComicとして引きなおす
    (ここ微妙ポイント)

    View full-size slide

  62. 無料公開期間のcreate権限判定
    ユーザの権限情報を
    DBから引いてくる

    View full-size slide

  63. 無料公開期間のcreate権限判定
    全作品対象の権限が
    あったら早期return

    View full-size slide

  64. 無料公開期間のcreate権限判定
    権限の付与範囲ごとに
    認可された作品を
    Arrayから取り除いていく

    View full-size slide

  65. 無料公開期間のcreate権限判定
    最終的に空ならば
    全て認可されている

    View full-size slide

  66. Authorizer.authorize!に戻ってきて
    認可されたならばraiseされないので後続処理へ

    View full-size slide

  67. 以上が最も基本的な
    認可の仕組み

    View full-size slide

  68. ところでDRYにはしたい
    他のアクションと
    判定基準が同じ場合も
    当然ある

    View full-size slide

  69. 権限判定の移譲
    アクションだけ差し替えて
    移譲先Authorizerのauthorizeメソッドを呼ぶ

    View full-size slide

  70. ここで疑問
    Actionごとに渡すべき
    IDの種類が違うのでは?

    View full-size slide

  71. Actionごとに渡すべきIDの種類が違う
    Actionごとに渡すべきIDの種類が違うのでは?

    View full-size slide

  72. Actionごとに渡すべきIDの種類が違う
    Actionごとに渡すべきIDの種類が違うのでは?
    無料公開期間は
    エピソードに対して
    作るのでepisode_id

    View full-size slide

  73. Actionごとに渡すべきIDの種類が違う
    Actionごとに渡すべきIDの種類が違うのでは?
    無料公開期間は
    エピソードに対して
    作るのでepisode_id
    無料公開期間を消すときは
    free_viewing_term_id

    View full-size slide

  74. Actionごとに渡すべきIDの種類が違う
    Actionごとに渡すべきIDの種類が違うのでは?
    無料公開期間は
    エピソードに対して
    作るのでepisode_id
    無料公開期間を消すときは
    free_viewing_term_id
    episode_id
    free_viewing_term_id
    free_viewing_term_id

    View full-size slide

  75. IDの種類が混ざらないのはなぜか
    様々な種類のIDをどうやって
    区別しているのか

    View full-size slide

  76. IDの種類を判別するしくみ
    • 各アクションのinterface class的なものを作る
    • 引数になりうるIDをインスタンス変数として持つ
    • attr_readerで読めるようにする
    • ID種別が非互換ならNo such methodで死ぬ
    • つまりダックタイピング

    View full-size slide

  77. 引数になるID種別が移譲先と違う場合
    移譲先のID種別に詰め替える
    eql?とhashを実装すると
    uniqできる

    View full-size slide

  78. 未実装な機能
    • ユーザがINDEXできるものだけINDEXする機能
    • 現状、絞り込みのクエリパラメータが必ず付いて
    いるのでそれを起点に許可、拒否が決定できる
    • 現状、権限を持っている対象だけを絞ってINDEX
    したいという要求がまだないので困っていない
    • それが来たときにどう実現するかは要検討
    • モデルのpublicメソッドにする?
    • どうにかしてActiveRecordスコープを作る?
    • CanCanCanのaccessible_byが参考になりそうか?

    View full-size slide

  79. まとめ
    • ニコニコ漫画の現行はモノリシックなPHP
    • ビジネスロジックのRails APIモードへのリプレイスが進行中
    • 現行PHPはBFF的立ち位置に寄せていく
    • 認証と認可の定義
    • ニコニコ漫画では公式連載の原稿納入、公開期間設定などが認可の
    対象
    • Rubyの権限管理系gem 3種概観
    • 検討した結果、いずれも使わなかった
    • ニコニコ漫画の認可機構はどのように実装をしているか
    • 無料公開期間の作成を例とした具体的流れ
    • 判定基準が同じアクションは判定を移譲している
    • 多数あるIDの種類をどうやって区別しているか
    • 今後の課題
    • ユーザがINDEXできるものだけINDEXする機能

    View full-size slide

  80. 付録 ユーザの権限情報のDB上の表現
    Watch: 作品・エピソードのINDEXとSHOW, 公開期間のINDEX
    Publish: 公開期間のCREATE, UPDATE, DESTROY
    Edit: 作品・エピソードのUPDATE, DESTROY

    View full-size slide