
こんにちは!今回は、「Bubbleのちょっと怖い話」シリーズの第一弾です。Bubbleのちょっと怖い話シリーズでは、セキュリティ等の観点からBubbleで気を付けたいことをご紹介していきます。第一弾の今回はリストデータの保存に便利な「Option set」を取り上げます。Option setはData Typeよりも軽めのデータテーブルとして使っている方も多そうですが、実は開発ツールで情報が丸見えになってしまうという懸念点があります。
今回は、開発ツールでのOption setの見え方とデータの完全削除方法を中心に、Option setでのデータの取り扱いにおける注意点をご紹介いたします。
1. Option setとは
1.1. Option setの概要
Option setは、データベースのような構造で情報を保持できる静的なリストです。BubbleのメインデータベースData typeとほぼ同様の設計になっており、Data typeで言うFieldのような役割をするAttributeは、Fieldとほぼ同様の属性を設定してデータを保存できます。Attributeでは複数のデータを保存することができたり、別のOption setのデータをリンクさせることもできます。
Option setを作成するには、BubbleのData > Option setsタブを開き、New option setに作成したいOption set名を入力して「Create」ボタンをクリックします。

1.2. Option setとData typeの違い
基本的にはData typeと同じような使い方ができますが、いくつか異なる点があります。Data typeと比較しながら、Option setの特徴をご紹介します。
1つ目は、更新を反映するには新しいバージョンをデプロイする必要がある点です。Data typeではデータが更新されると自動でアプリに反映されますが、Option setについて新しいOptionを追加したりOptionの中身を変更したりした後、アプリに反映させるには新しいバージョンをデプロイする必要があります。
2つ目は、アプリのユーザーはOptionの追加・編集・削除ができない点です。アプリユーザーはOption setに保存されているOptionに変更を加えることが出来ません。ユーザーが自由に変更できるようにしたい場合はOption setではなくData typeを使用する必要があります。
3つ目は、Privacyルールや暗号化でデータを保護することができない点です。Data Typeは、PrivacyルールでData Typeごとに権限を細かく設定することが出来ますが、Option setはそういったセキュリティ保護策を講じることが出来ません。
4つ目は、ソースコードの一部として扱われる点です。Data typeはアプリを開くたびにBubbleのサーバーからデータを取得する必要がありますが、Option setはソースコードの一部として扱われるため、ユーザーの端末にアプリのJavaScriptファイルの一部としてダウンロードされます。このメリットとして、アプリの新しいバージョンをデプロイするまでユーザーの端末にキャッシュされるため、読み込みが早く軽量になるという点が挙げられます。一方でそのデメリットとして、見方さえ分かれば誰でもブラウザの開発ツールでOption setの情報を閲覧できてしまうという点が挙げられます。つまり、機密事項をOption setに保存すると全世界に向けて機密事項を公開していることになります。機密事項を保存したりアプリ上で利用したい場合は、Option setではなくData typeに保存するようにしましょう。
1.3. Option setとData typeの比較まとめ
ここまでの内容も踏まえて要点を比較すると下記のようになります。
| Data type | Option set | |
|---|---|---|
| 暗号化 | あり | なし |
| Privacyルール | あり | なし |
| アプリユーザーによる編集 | 可 | 不可 |
| 変更の反映方法 | 特別な操作不要 | デプロイ |
| 読み込み時のWU消費 | 消費する | 消費しない |
1.4. Option setでの実装が向いているもの
Data typeではなくOption setを使って実装するのが向いているのは、頻繁な変更やユーザーによる変更が不要な非機密情報と言えます。例としては以下のものが挙げられます。
- 多言語対応サイトの言語の選択肢
- 居住地・出身地登録時の選択肢
- ユーザーのステータスの候補
2. 開発ツールでの見え方
2.1. 準備
それでは、実際に開発ツールでOption setがどのように閲覧できてしまうのか確認してみます。
テスト用のアプリでOption setを作成して、いくつかOptionを登録します。今回は、「フルーツ」と「地域」というOption setを作成し、それぞれOptionを複数登録しました。




次に、テスト用のページを作成し、Dropdownを一つ配置します。DropdownのAppearance > Choices styleでDynamic choicesを選択するとType of choicesでOption setを選択できるようになるので、先ほど作成したOption setのどちらかに設定します。

作成したページをPreview表示し、開発ツール(Fn キー+F12キー)を立ち上げます。

準備ができたのでOption setの見え方を確認していきます。
2.2. console.log(app)でOption setの情報を出力
本記事では、開発ツールでconsole.log()を使ってOption setの情報を出力する方法で確認していきます。Console(コンソール)タブでconsole.log(app)と入力してEnterキーをクリックします。

すると下部に出力内容がトグル付きで表示されるので、トグルをクリックします。

取得した内容が表示されます。さらにその中のoption_sets:.....のトグルをクリックします。

すると、作成したOption setのOptionの中身が、画面上で表示されていない値までしっかり確認できます。DropdownでType of chicesに設定した「フルーツ」はもちろん、どのページでも使用していない「地域」も確認できるのが分かります。

ちなみに、Option setの内容以外では、最終変更日時やファビコンの格納URL、アプリ名などが表示されています。

2.3. 変数appの定義
console.log(app)でOption setのデータが出力できたのは、どこかで変数appにOption setをはじめとするデータを代入していたからですよね。実は、appに情報を代入しているコードも開発ツールで確認できます!
早速そのコードを確認してみましょう。開発ツールのSources(ソース) > Page > package > dynamic_jsを開きます。ここではソースコードが確認できます。

46行目を見るとvar app = ....とはじまるコードがあります。

このコードを見てみると、変数appにOption setの内容を含むアプリの情報を代入しているコードだと分かります。下記は46行目のOption setに関する部分をピックアップし、改行などを加えて読みやすく加工したものです。
var app = JSON.parse(`
{
//...(アプリの基本情報など)
},
"option_sets": {
"__": {
"%d": "フルーツ",
"values": {
"bTGyP": {
"%d": "みかん",
"__": "和歌山",
"no": 1,
"db_value": "___",
"sort_factor": 1
},
"bTGyQ": {
"%d": "りんご",
"__": "青森",
"no": 2,
"db_value": "___0",
"sort_factor": 2
},
//...(Optionの情報が続く)
},
"attributes": {
"__": {
"%d": "産地",
"%v": "text",
"creation_source": "editor"
},
"no": {
"%d": "No",
"%v": "number",
"creation_source": "editor"
}
},
"creation_source": "editor"
},
"__0": {
"%d": "地域",
//...(フルーツと同様に地域の情報が続きます)
},
// ... (他の情報)
}
特に事前知識がなくてもソースコードを見れば画面上では表示されないOption setやOptionの中身までしっかりと確認できてしまいますね。
3. 完全削除の方法
3.1. 削除データの見え方
Do a search for クエリでのデータ取得を検証した記事では、Data typeについてPrivacyルールを設定していない状態で削除したFieldに保存していたデータも取得できてしまうという懸念点が見つかりました。
ここでは、Data > Option setsタブ上での削除にフォーカスして、削除したAttributeに保存した値や削除したOptionそのものが開発ツールでどのように見えるのかを、3パターンに分けてconsole.log(app)を実行して確認します。
まずは、Option setに登録した1つのOptionを削除した場合を確認します。下記は、「削除テスト2」というOption setの「青」というOptionを削除した後の出力内容です。

Deleteフラグを登録する%delというAttributeが出力され、値はtrueになっていますが、削除したOptionも確認できるようになっています。
次に、Option setの1つのAttributeを削除した場合です。下記は「フルーツ」というOption setの「Rank」というAttributeを削除した後の出力内容です。

RankというAttribute名の後ろに- deletedが付けられており、Optionを削除したときと同じように%delというAttributeがtrueという値で出力されています。
Attributeに保存していた値はどうなったかというと、該当Attributeに保存した値をそのままでAttributeを削除すると、値がしっかり出力されます。

一方で、Attributeの値を削除してからそのAttributeそのものを削除したとき、Attribute名は出力されますが、値は空欄になり出力されませんでした。

Attributeに保存していた値を残したくない場合は、まずAttributeに保存した値を削除してからAttributeそのものを削除するようにしてください。
最後に、Option setそのものを削除した場合を確認します。下記は「削除テスト」というOption setを作成し、複数のOptionを登録してからOption setそのものを削除した後の出力内容です。

Attributeを削除したときと同様、%delというAttributeが出力され値はtrueになっていますが、登録したOptionの情報はそのまま表示されています。
また、Optionを登録したままOption setをそのまま削除した場合と、Optionを削除してからOption setを削除した場合を比較したのが下記です。

%delAttributeが出力されtrueになるという違いはあれど、どちらも保存していた値が出力されてしまっています。
3.2. 完全削除の方法と結果
Data > Option setのタブ上での削除操作では完全に削除することが出来ないことが分かりました。しかし、Bubbleには不要なデータを消去してアプリの挙動を早くする「Optimize」機能があるのですが、その機能を使うとOption setの削除データの一部を完全に削除することが出来ます。
Optimizeの実行方法とその結果をご紹介します。BubbleアプリエディタのSettings > General > App file managementの項目を探し、「Optimize application」をクリックします。

Optimizeの対象を選択するポップアップが表示されます。中ほどにOption setに関する削除した項目、最後の方に削除したOptionが表示されています。ここで完全に削除したいものを選択します。まずは、先ほど削除した「フルーツ」のOption「れもん」を選択し、「CLEAN APP」をクリックします。

Preview表示中のテストページを再読み込みし操作を反映したら、開発ツールでconsole.log(app)の出力内容を確認します。

Optionのリストに出力されていませんね!
次に、先ほど削除データの見え方のところで削除したOption setフルーツのAttribute「Color」を選択して「CLEAN APP」をクリックします。

Preview表示中のテストページを再読み込みし操作を反映したら、開発ツールでconsole.log(app)の出力内容を確認します。Attributeのリストからは消えていますが、各Optionのデータとしては保存した値もそのままに残ってしまっています。

なお、全OptionのAttributeの値を削除してからAttributeを削除→Optimizeした場合、Attributeのリストには出力されませんが、各OptionのデータとしてはAttribute名が残ってしまっています(Attribute「Taste」をご参照ください)。

したがって、Attributeの値を消すことはできるがAttributeそのものの痕跡を完全に消すことはできないということが分かります。
最後に、Option setごと削除したOption setをOptimizeするとどうなるか確認します。再度Settings > General > App file management> 「Optimize application」をクリックし、先ほどOption setごと削除した「削除テスト」をチェックして「CLEAN APP」をクリックします。

Preview表示中のテストページを再読み込みし操作を反映したら、開発ツールでconsole.log(app)の出力内容を確認します。Option setのリストに出力されていませんね!

ちなみに、Optimizeで完全削除したものは、Data > Option setsタブで「Show deleted」をクリックしても表示されなくなりました。

以上の検証から、Option setに関する削除操作時には下記についてご注意ください。
- Option setを丸ごと削除したい場合はOptimizeで完全に削除できる
- AttributeはOptimizeでも完全に痕跡を消すことが出来ないので、Attributeそのものを削除する前に必ずAttirbuteに保存した値を削除する
- 各Optionを完全削除したい場合はOptimizeで完全に削除できる
4. まとめ
Option setは便利ですが、機密情報の保存には利用しないほうが良いということがご理解いただけたでしょうか。保存する内容や使い道によってOption setとData typeをうまく使い分けてくださいね!
また、万が一Option setに機密情報を保存してしまっている場合は、Attributeに保存した値を1つずつ消していくか、Optimizeで完全に削除することを徹底してくださいね。
Bubbleのちょっと怖い話シリーズでは、今回のようなあまり知られていない危ない話を詳しくご紹介していきます。次回の記事もお楽しみに~!