Slide 1

Slide 1 text

RealtimeDBルールでの頑張り 自作オンラインマインドマップサービスの実装例

Slide 2

Slide 2 text

自己紹介 小宮山智也 メドピア株式会社 フロントエンドエンジニア ボルダリング

Slide 3

Slide 3 text

近況 https://hopeful-visvesvaraya-3dafb6.netlify.com/ https://qiita.com/miyanokomiya/items/4b0bf8561adc5f7a0754

Slide 4

Slide 4 text

話すこと概要 ● FirebaseとVueで作ったマインドマップサービス紹介 ● 作り込んだRealtimeDB権限ルール紹介 ● Firestoreとの比較 ● 質問などあれば ここを見ながらだと理解が捗るかもしれないです https://gitlab.com/miyanokomiya/mind-xx-acpr/blob/master/database.rules.json

Slide 5

Slide 5 text

機能と権限

Slide 6

Slide 6 text

マインドマップ機能 ● ルートから左右にノードを生やせる ○ DnDでノードを移動 ○ WebSocketでリアルタイム編集 ● ノードにコメントできる ● 普通に使えるマインドマップ(多分) フリースペースはこちら(質問書いてくれたら最後に拾えるかも) https://mind-xx-acpr.firebaseapp.com/map/-LfJzihYKQJLt9hHuNFQ

Slide 7

Slide 7 text

database.rules.jsonのルート要素 ● users ● file_invitations ● file_authorities ● work_spaces ● files ● nodes ● comments ● ユーザー情報 ● ファイル共有招待トリガー用 ● ファイル権限 ● ワークスペース情報 ● ファイル情報 ● ファイル毎のノード情報 ● ファイル毎のコメント情報

Slide 8

Slide 8 text

ファイル権限ルール1 ● file_authorities ○ ファイル権限 ● files ○ ファイル情報 ● nodes ○ ノード情報 ● comments ○ コメント情報 - file_authorities - $file_id (ファイル毎に) - users (ユーザー毎に) - $uid (データがあればreadは可) - write (write権限フラグ) - owner (所有者フラグ)

Slide 9

Slide 9 text

ファイル権限ルール2 ● files、nodes、commentsは同じ閲覧・権限ルール ○ データアクセスの都合で階層分けているが、実態は1つのファイル単位 ○ 他人コメントは削除不可など細かなルールはマジムリなので UIだけで妥協している ● read ○ root.child('file_authorities/' + $file_id + '/users/' + auth.uid).exists() ● write ○ root.child('file_authorities/' + $file_id + '/users/' + auth.uid + '/write').val() === true

Slide 10

Slide 10 text

ワークスペース ● ファイル管理 ○ 作成、編集、削除、複製 ■ ファイル権限 ● ファイル一覧表示 ○ 自分の一覧 ○ 共有中一覧 ○ 自分&共有中の一覧

Slide 11

Slide 11 text

ワークスペースデータ構造 ● work_spaces - $uid (自分のワークスペースのみアクセス可 ) - files (自分が所有者のファイル ) - $file_id - invited_files (共有中のファイル) - $file_id ● 都度selectではなく、予め一覧のデータ構造を作っている ○ id一覧を取得してフロントエンドで個別にファイルと権限情報を get ○ where条件などは妥協・・

Slide 12

Slide 12 text

ファイル共有と招待

Slide 13

Slide 13 text

ファイル共有 ● 他のユーザーとファイルを共有 ○ 閲覧のみ可 ○ 編集も可 ● サービス内ユーザーのみ ○ サービス自体への招待機能はない ○ メール機能とか使えばできるかも?

Slide 14

Slide 14 text

ファイルへの招待フロー ● まずはRealtimeDBに招待用データを登録 ● file_invitations - $file_id (ファイルへの招待権限はファイルと同じ ) - $tmp_id (ただの識別子) - email (招待するユーザーのメアド ) - write (write権限フラグ) ● 登録をトリガーとしてCloud Functionsで権限とワークスペースを整える

Slide 15

Slide 15 text

ファイル権限ルール再掲 ● file_authorities - $file_id (ファイル毎に) - users (ユーザー毎に) - $uid (データがあればreadは可) - write (write権限フラグ) - owner (所有者フラグ) 共有したユーザーの権限もこの構造で 表現可能(owner: falseとなる)

Slide 16

Slide 16 text

なぜCloud Functions ● file_authoritiesは新規作成のみ可、変更不可としている ○ readかwriteルールしか付けられない ○ 共有中のユーザーも招待可能にしたい => write: true => ownerを乗っ取れてしまう ○ Cloud Functionsならコードに書いた変更しかできない ■ トップダウン式なRealtimeDBルールでは意図せぬ変更への対応は限界がある ● 招待されたユーザーのワークスペースにファイルを追加したい ○ 他人のワークスペース編集を許可するわけにはいかない ○ Cloud Functionsなら裏側でルールを突き破ることが可能

Slide 17

Slide 17 text

Beyond Borders ● work_spaces - $uid (本人のみアクセス可 ) - files (自分が所有者のファイル ) - $file_id - invited_files (共有中のファイル) - $file_id - file_authorities - $file_id (ownerのみwrite可) - users - $uid - write - owner Could Functionsでルールを無視して書き込む

Slide 18

Slide 18 text

公開ファイル

Slide 19

Slide 19 text

公開ファイル ● 認証不要でアクセス可能 ○ 閲覧のみ可 ○ 編集も可 ○ https://mind-xx-acpr.firebaseapp.com/map/-L1kyhrBlrHGorkL4ws_ Cloud Functions不要で、ファイル編集 権限があれば変更可能としている ● file_authorities - $file_id (ファイル毎に) - public (データがあればreadは可) - write (write権限フラグ)

Slide 20

Slide 20 text

ファイル権限ルール2の拡張 ● files、nodes、commentsは同じ閲覧・権限ルール ○ データアクセスの都合で階層分けているが、実態は1つのファイル単位 ○ 他人コメントは削除不可など細かなルールはマジムリなので UIだけで妥協している ● read ○ root.child('file_authorities/' + $file_id + '/users/' + auth.uid).exists() ○ or root.child('file_authorities/' + $file_id + '/public').exists() ● write ○ root.child('file_authorities/' + $file_id + '/users/' + auth.uid + '/write').val() === true ○ or root.child('file_authorities/' + $file_id + '/public/write').val() === true

Slide 21

Slide 21 text

ファイル削除

Slide 22

Slide 22 text

ファイル削除 ● ここまでの作り込みによってファイル権限はとても複雑 ○ 行きはよいよい帰りは怖い ○ 意図せぬ編集を防いだまま削除だけは許すなんて Firebaseの天才でないとムリ Cloud Functionsで消してしまえ!!

Slide 23

Slide 23 text

ワークスペースデータ構造再掲 ● work_spaces - $uid (自分のワークスペースのみアクセス可 ) - files (自分が所有者のファイル ) - $file_id - invited_files (共有中のファイル) - $file_id ここの$file_id削除をトリガーとして ファイル削除のCloud Functionsを起動

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

RealtimeDBまとめ

Slide 26

Slide 26 text

RealtimeDBルールの所感 ● jsonでルールを書くのでとにかく冗長 ○ トップダウンのルール適用&データ取得なのでネストを浅くする => ルールをコピペの嵐 ● readとwriteしかないのは辛い ○ せめてupdateとdeleteは分けたい ● 困ったらCloud Functionsでなんとかする ○ Cloud Functionsなしでルールを組み上げきったのなら、それは芸術作品 ● よっぽどの理由がなければ今後はFirestoreを検討しよう! ○ ルールに関数を使える! ○ read、create、update、deleteの設定ができる! ○ でも最終的には困ったらCloud Functions!

Slide 27

Slide 27 text

とはいえRealtimeDBのメリット ● FirestoreはDocumentのread数課金 ○ 今回のようなマインドマップツールだと、ノードが Documentになるのでreadが嵩む ○ 権限判定時もreadが加算されるので、ルールが複雑になるにつれて readが嵩む ○ 個別Documentのデータ量が少ないなら RealtimeDBの課金体系は有利(※要検証) ● とにかくシンプル ○ 全てがトップダウンで jsonな構造なので覚えるべき概念がほとんどない ○ FirestoreはDocumentやCollectionなどある程度の学習コストが必要 ● Firestoreはまだベータ

Slide 28

Slide 28 text

そうはいっても流れはFirestore ● RealtimeDBとFirestoreの選択で判断に迷う箇所は課金体系くらい ● 学習コストはあるが、それに見合う高機能が用意されている ● ベータとはいえ、機能は十分にあるし常に進化している ○ 本リリースになったタイミングである程度のマイグレーションコストは払う覚悟は必要 ○ Cloud Functionsもそれほどの規模ではなかったがマイグレーションが必要だった ■ 本リリースに気付かず一時期放置してたら動かなくなっていた・・

Slide 29

Slide 29 text

ご静聴ありがとうございました ● 何か質問などあれば ● メドピア、フロントエンド募集してます ● 水曜夜は新宿ロッキー(or 秋パン)でボルダリング