SPOリストの閲覧・編集権をPower Automateで制御する

## 自己紹介
こんにちは。[DaddyDaddy](https://twitter.com/daddydaddy "twitter")です。お仕事でひょんなことからPower Automateを活用するようになり、個人的な[ブログでTIPS的なものを公開](https://mocabrown.com/blog/powerautomate "モカ式")しています。2023年1月1日にQiita初投稿依頼ちまちまと書いています。

## 今日のお題
SharePointリストは便利なデータベースとして利用できますが、レコード単位で誰が閲覧や編集ができるのかを細かく制御したくなる場合があります。
たとえば、なにかの申請をSharePointリストで受け付ける場合、上司が承認したあとにはそのレコードを申請者に編集させたくないようなケースもあるでしょう。
この記事ではPowerAutomateを用いてレコード単位の編集権の制御する方法を紹介します。
## まずは準備から
チームに紐づいたSharePointサイトに、testListというリストを作成しました。２つのレコードをあらかじめ作成しておきました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/02c19326-e0a8-b605-ff59-6c3f2415d249.png)

SPOリストには初期状態では隠れている「ID」列を表示しておきます。適当な列名をクリックし、「列の設定」>「列の表示/非表示」の項目をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/6ca5c241-b7df-2ac5-710a-46efc42ddb65.png)

表示可能な列名のなかから「ID」にチェックを入れて「適用」をクリックし、ID列を表示しておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/f811b3f6-3c3a-59c4-2dc9-3f35c652fe30.png)

リストページのURLコピーして、まだこのリストを作成したチームに参加していない他のユーザーにURLを伝えて開いてもらいましょう。この時点でチームに参加していないユーザーにはリストへのアクセス権はありませんから、アクセス権要求の画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/4aa94103-9b80-ebe9-65ab-43f2faf44599.png)

## シンプルなフローでテストしてみる
とりあえずテストするために、Power Automateの「新しいフロー」から「インスタントクラウドフロー」を作成します。
追加するのは「新しいアイテムまたはフォルダーへのアクセス権の付与」アクションです。
先ほど作成したリストが存在するSharePointサイトのアドレスと、リスト名を選択します。
* 「ID」の項目には、アクセス権を与えるレコードのIDを入力します。今回はリストのID番号1だけにアクセス権を与えてみます。
* 「受信者」の項目には、このリストのアクセス権を与えるユーザーを指定します。
* 「ロール」にはCan editまたはCan view のどちらかを選択します。編集可能または閲覧のみ可能のどちらかを設定することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/2a0ee356-96dd-cf50-b207-1f7b931e05f5.png)

クラウドフローを実行した後で、アクセス権を与えたアデルさんのブラウザで開いてみると、２レコードのうちID１だけが編集可能な状態で表示されるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/47fca7b0-d95c-1806-73bb-e21f7a80bb53.png)

## 管理リストから編集権を制御する
ユーザーに入力してもらうためのリスト（testList）を作成したところで、今度はtestListへのアクセス権を制御するControlListを別に作成してみましょう。新たに作成したリストにeditableUser列を種類「ユーザーまたはグループ」で追加しました。ついでにこちらのリストでも「ID」列を表示しておきましょう。２つのリストに同じIDがそろうようにしておきます。

制御リストのIDと同じtestListのレコードを、制御リスト側でeditableUserに指定したユーザーだけが編集できるよう制御するような仕組みを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/30718f6e-1bfa-c363-dfd4-a23d9b408d17.png)

新しく作成したのはこのようなクラウドフローです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/ed0d8077-0296-9373-2977-89521a818e01.png)
トリガーとなるのはcontrolList側の「アイテムまたはファイルが修正されたとき」です。誰がリストの編集ができるのか、設定を変更するとトリガーはcontrolListの何番のIDが編集されたのかという値を持っていますので、これをもとにcontrolListの該当IDの中身を「項目の取得」で取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/69738b82-bbdd-c59a-07a8-e4e5e4fca0fe.png)

次に、testList側の共有をいったんリセットします。ここで使うIDもトリガーで取得したIDです。制御側とユーザー側のリストのIDがここで同期しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/24427676-4221-b719-df23-cad9f91e2935.png)

制御側（controlList）のeditableUserに誰が編集できるのかユーザーが１人でもいるかどうかを判定します。この値がnullならば編集権を設定しません。直前に「itemまたはファイルの共有を停止します」を用いているので、誰も編集できなくなるため制御リストの指定と動作が一致する仕組みです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/30eb6e1c-fd40-c0e0-87cd-f4a744a85478.png)

条件分岐の「いいえの場合」には、ユーザー側リスト（testList）の該当レコードIDに対して制御側（controlList）のeditableUser列に指定されていたユーザーを受信者にして「itemまたはフォルダーへのアクセス権の付与」アクションを使ってアクセス権を設定してやります。今回はロールを「Can Edit」を使い、編集権を与えてみます。

## テストしてみる
作成したクラウドフローを保存し、テスト実行します。自動トリガーのフローのため、トリガーとなるcontrolListに新しいアイテムを追加することでトリガーされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/31c6ea63-d247-08ee-4d51-1e40dff609a0.png)
動作した結果、editableUserに追加したアデルさんに対して編集権が与えられました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/4d6a2f68-862b-9fe8-e485-0a73d0083c69.png)

## １つのレコードに複数のユーザーに対してアクセス権を与えるには
editableUser列には1人のユーザーしか選択できませんでしたが、列の設定を変更すると複数のユーザーを選択できるようになります。
設定＞リストの設定　からeditableUserの項目をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/9cdbc700-0700-5f3a-9400-566def4eff92.png)

「複数選択できるようにする」の項目を「はい」に切り替えて「OK」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/0a385082-d048-e898-d232-ce6cce151df6.png)

editableUser列が複数の値を持つことができるようになると、クラウドフローの条件に少し手を加える必要があります。「ユーザーまたはグループ」型の列は１ユーザーだけを選択できる設定の場合は、空の場合に何も返さないので条件には「null」を指定すればよいのですが、複数のユーザーを指定することが可能な状態にすると、ユーザーを指定しない場合にeditableUserは空の配列（アレイ）となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/4c18f3b4-8c96-42d8-8494-043b857c4444.png)

そのため、出力結果に合わせて「変数の初期化」で空のアレイを作成して条件の左辺はeditableUser、右辺には先ほど定義した「空のアレイ」を設定しなおしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/3943ae59-7a60-e194-b5d5-e507447796c7.png)

editableUserが複数の値を持つ場合には、このような形で出力結果が返ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/9cbfa39e-49ef-d3ac-9d2b-77eb3d32e966.png)
取得するのはenableUser配列のなかのEmail項目ですが、このままでは配列を処理できません。いったん「受信者」に設定してあった項目を削除して、再度動的なコンテンツから「項目の取得」にある「editableUser」を指定しなおします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/3f58ee18-19de-11ec-946d-a4ab7ab510be.png)
すると、enableUserは複数の値を持つ配列ですから、自動的にApply to eachで囲まれて配列ひとつずつのemailを「受信者」に当てはめるような動作に変換されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/f3b40f7f-f7a5-f3db-c0bb-2f1d7554cc13.png)

この状態でふたたびクラウドフローをテスト状態にして、controlListを編集してみましょう。今度はアデルさんとリーさんの２名を指定した状態でcontrolListを保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/8ba9faa8-056c-cf3d-8725-822cb6194627.png)
条件の「いいえ」のなかでeditableUser配列を順番に処理し、そのなかの「Email」項目に入っているユーザーに順番に処理が適用されました。これにより、制御リストを使ってユーザー側リストのID単位で自由に編集可能なユーザーを制御することができるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/578c3811-2e28-adbf-daae-d3cbffb631eb.png)

## １つのリストでも制御できる
今回は制御用のリストと、ユーザー側のリストをわけましたが、１つのリストにeditableUser列を用意して、リストの「ビューの作成」機能をつかってユーザーにはその列を表示させないようにするとさらにシンプルに制御することもできます。

条件によってロールをCan viewにするかCan editにするか制御するのも面白いでしょう。例えばロールの制御に登録日から○日後は編集できないようにCan viewを設定するようなフローを毎日自動実行させるのも面白いかもしれません。