🔥

WixStudioでVeloを使う Step 25 「コレクションのアイテムを更新できる会員をフックで限定する」

2023/10/06に公開

はじめに

前回の記事でやり残したことを考える。WixStudioのコレクションをVeloで操作するときに気になることがある。それは権限。どうしても緩くなる。この表現は不適切か。例えば最近の記事で扱った会員同士のメッセージング機能。Messagesコレクションのアイテムに対して、複数の会員から更新できるようにする必要があった。だからMessagesコレクションの権限は 『サイト会員』はコンテンツの更新が可能 となっている。で、これが問題。このメッセージの更新操作はメッセージに関係するサイト会員二人に限定されているのではない。サイト会員全員に与えられた権限という状態。要は、今の状態では他人が送ったメッセージの内容も自由に書き換えられる状態になっている。これを回避するにはやっぱりフックを使うことになるのかな。それをやってみる。

サイト会員はコンテンツの更新が可能
サイト会員は佐コンテンツの更新が可能

https://support.wix.com/ja/article/velo:データフックを使用する

目標

とりあえず緩くなってしまった権限をフックで解消する。具体的に言えばMessagesコレクションのアイテムに対する更新はメッセージの所有者にのみ許可するということ。注意点としてメッセージ削除機能の都合上、コレクションの権限機能による制限が出来ないということ。

準備

前回の記事「WixStudioでVeloを使う Step 24 「ライトボックスを使う。リピータで表示しているアイテムを編集する」」の続き。

データフックを用意する

データフックの作成は、まずbackend/data.jsを作成することから始まる。Veloを有効にして、WiXIDEを開きファイルを作成すれば良い。データフックの作成は他のやり方もある。本当はこっちの方が良いのかも。
データフックを作成したいコレクションのメニューを開いて「データフックを追加」を選択する。

データフックを追加
データフックを追加

「データフックを追加」ダイアログが開かれる。追加したいフックを選択すれば良い。今回はデータを更新する直前に権限を確認したいので、更新前を選択する。

更新前を選択
更新前を選択

WixIDEを開くとbackend/data.jsが既に作成されている。先程、選択した更新前のフックも用意された状態になる。

フック関数:Messages_beforeUpdateが用意されている
フック関数:Messages_beforeUpdateが用意されている

後はスクリプトを書くだけ。

スクリプトを書く

フック関数Messages_beforeUpdateで判定したいことは二つ。

  1. 編集を加えようとしている会員が誰か
  2. その会員はメッセージを送信した会員かどうか
backend/data.js
export function Messages_beforeUpdate(item, context) {
  const me = context.userId
  const currentItem = context.currentItem
  const owner = currentItem._owner
  if(me==owner){
    return item
  }
  return Promise.reject('forbidden')
}

編集を加えようとしている会員はconst me = context.userIdで取得する。メッセージの所有者はconst owner = currentItem._ownerで取得する。itemにも所有者情報が入ってる可能性はあるけど、所有者情報が偽造されている可能性は避けたいのでcontextから取得した。const currentItem = context.currentItem編集対象となっているアイテムを取得している。
contextで色々な情報が取得出来るので使う前には中身を確認する。
ログイン中の会員(me)とメッセージの所有者(owner)が一致しているか判定する(if(me==owner){return item})。条件を満たせばitemを返して終了。条件を満たさなければreturn Promise.reject('forbidden')として処理をやめさせる。これでメッセージの更新者の判定は完了。

https://www.wix.com/velo/reference/wix-data/hooks/beforeupdate

もう一つスクリプトを修正する。必須ではないけどやるべき。ページコード(sendMessage.##.js)。

sendMessage.##.js(抜粋)
if (me._id == itemData._owner) {
  $item('#box3').onDblClick(event => {
    openLightbox('Center', itemData)
      .then(message => {
        if (message) {
          saveMessage(message)
            .then(result => {
              initData()
              $w('#text4').text = 'メッセージが保存されました'
            })
            .catch(error => {
              $w('#text4').text = 'メッセージが保存されませんでした'
            })
        }
      })
  })
}

メッセージをダブルクリックしたら表示されるライトボックス。これは自分が送信したメッセージ以外では不要な機能。それを除外するため$item('#box3').onDblClick()if (me._id == itemData._owner) {..}で括る。これでログイン会員自身が送信したメッセージのみでライトボックスが表示されるようになる。

まとめ

コレクションの権限変更は簡単に行える。しかし、管理するデータに対する操作を柔軟に行おうとすれば権限を緩くする必要が出てくる。これを回避するために今回はフックを使った。具体的には更新直前にアイテムの所有者を照合する手段を執った。フックも比較的簡単に追加出来るし、必要な情報はcontextから取得出来る。コレクションの権限設定とフックを組み合わせることが大切だと思う。ただ、フックに頼り過ぎも良くない。そもそもで当たり前なことだけど何か作るときはしっかりと設計してから行うべき。設計を疎かに実装を始めれば、最後はスクリプトで力技になる。今回はそうなりかけているような気がした。

参考

正直、重要なことではないけど。もし、メッセージの編集権限をメッセージに関連する2名(送信した会員と受信した会員)とする場合も考えてみる。

backend/data.js
export function Messages_beforeUpdate(item, context) {
  const me = context.userId
  const fromMember = currentItem.fromMember
  const toMember = currentItem.toMember
  const isPermit = [fromMember,toMember].includes( me )
  if(isPermit ){
    return item
  }
  return Promise.reject('forbidden')
}

これもやり方は色々あると思う。今回は関連する会員IDの配列を用意([fromMember,toMember])。同配列に対してログイン中の会員(me)が含まれているか確認する。その結果で判定してみた。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

つづき

https://zenn.dev/niibori/articles/veloonwixstudio-beginner-0026

Discussion