Power Platform で他人の予定表を操作する


# はじめに

Power Apps や Power Automate を利用して他人の予定表の情報を取得したいという要望をいただくことがあります。


まず、自分の予定表の情報については、Outlook コネクタの以下のアクションを利用することで取得可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/42db994d-0589-39c3-0ed9-5df6738285ef.png)

しかし、基本的に、他人の予定表の情報については上記アクションで取得することはできず、Microsoft Graph API や認証、認可について少なからず知識というか、考慮することが増えるため、個人的に、市民開発者の方にとって難易度が高いと思っています。

また、アプローチ次第では、Power Platform のライセンスについても考慮が必要なため、積極的に全員が利用することは個人的にはお勧めしませんが、私なりに情報を整理してみたいと思います。

# Microsoft Graph API

まず、他人の予定表の情報を取得する場合は、Microsoft Graph API を利用します。

https://learn.microsoft.com/en-us/graph/api/overview?view=graph-rest-1.0

Microsoft Graph API について知らない市民開発者の方も多いと思うので、どんなものか説明していきます。

まず、Microsoft Graph API は、Microsoft のクラウドサービスのリソースを操作するための API で、リクエストの考え方は以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/498c2ff9-1467-52d8-b036-3c1c5b3aea49.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/0fa1638b-bf6b-7f09-d197-606e8aff520e.png)



以下、リクエスト例で、後者は、他人の予定表の情報を取得する際にも利用可能なリクエストです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/7fe61ac0-2ae7-b8cf-a6fe-951c010982b5.png)



実際にはかなり色々なことができますが、どんなリソースに対する操作ができるか、どのようにしてリクエストをしてどのような応答が返ってくるかは、リファレンスを参照したり、Graph Explorer を利用したりして確認します。

https://learn.microsoft.com/ja-jp/graph/api/overview?view=graph-rest-1.0

https://developer.microsoft.com/en-us/graph/graph-explorer

ここまででも難易度がかなり上がると思いますが、更に、こちらの API を利用する場合、二つのアクセス許可の種類があるため、こちらの違いについても説明します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/8a8d20df-874e-0097-6387-5ebcc6f8572a.png)

## 委任されたアクセス許可

ユーザーはアプリケーションにサインインすることで、アプリケーションに対して操作を委任することになり、アプリケーションがユーザーに代わってデータを操作することを意味します。

そのため、サインインするユーザーは、操作したいデータに対するアクセス許可を持っている必要があります。


API のリファレンスの場合、こちらの方を指します。
※職場または学校のアカウントを利用する想定です

https://learn.microsoft.com/ja-jp/graph/api/calendar-list-events?view=graph-rest-1.0&tabs=http

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/451d42cf-f6b2-3b8a-0d73-bd998e8550cf.png)

以下、委任されたアクセス許可の動作イメージです。この例では、ユーザー A は、ユーザー B の予定表フォルダーにして十分な権限を持っていないため、アプリケーションは、ユーザー B の予定表フォルダーの操作に失敗しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/a39df9e3-b288-d1e5-5e61-efe5377ba909.png)

つまり、委任されたアクセス許可の場合、ユーザー A が元々出来ることしか出来ません。

## アプリケーションの許可

ユーザーなしでアプリケーションとしてサインインしてデータを操作することを意味します。

こちらのイメージは以下の通りで、ユーザーが存在しません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/a6d8cad6-07d7-c201-53f1-af626817d2aa.png)

では、何を持ってアプリケーションと認識するかというと、以下の通り、証明書かクライアントシークレットになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/d685997a-718e-e16b-4bea-ce1c405c07d9.png)

おそらく、市民開発者の方からすると、コンピューターの世界の証明書って何？という感じだと思いますし、こういった点からも、敷居が高いと思います。

なお、アプリケーションの許可は権限が強いため、以下のポリシーでアクセス可能なメールボックスを絞ることが可能です。

https://learn.microsoft.com/ja-jp/graph/auth-limit-mailbox-access

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/c8431e4e-ee7f-ad3b-97d7-bd12072679f7.png)

## Microsoft Entra ID (旧 Azure Active Directory) へのアプリ登録

通常、Microsoft Graph API を利用する場合、Microsoft Entra ID にアプリ(の定義) を登録する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/695dd562-4872-2590-6f40-0b07d8b254c6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/ac9ef4da-92dc-e4a4-fc35-bc80e6210142.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/ee54bd98-da4e-975b-5d9e-7653f276e5d1.png)

その際、アプリケーションが利用するアクセス許可や証明書またはクライアントシークレットを登録し、アプリケーションの ID など、必要情報を控えておく必要があります。

多くの組織では、この操作は管理者しか許可されていないため、この点からも、市民開発者の方からすると非常に敷居が高いものとなります。

:::note
通常、Microsoft Graph API を利用して独自のアプリケーションを開発する場合 (Power Platform 含む)、このように Microsoft Entra ID にアプリケーションの登録をする必要があります。その際、そのアプリケーションが利用するアクセス許可も登録し、登録した内容をベースにアプリケーションを開発します。これにより、管理者は、Microsoft Graph API を利用して、組織のリソースを操作するアプリケーションを把握することが可能になります。

人によっては少し面倒くさいと思うかもしれませんが、こちらの仕組みがないと、管理者の知らないところで組織のリソースを操作するアプリケーションが大量に生まれ、それらのアプリケーションから情報が漏洩するリスクも高まります。
:::

## Power Platform からの Microsoft Graph API の利用

Power Platform から Microsoft Graph API を利用する方法について整理いたします。

### 標準コネクタ

実は、Outlook や Teams などの標準コネクタの多くは、裏では Microsoft Graph API を利用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/a5e6ace6-d018-4e73-1765-bf7ddcd10ac6.png)

この際は、Microsoft Entra ID へのアプリ登録は不要で、応答の解析なども不要なため、非常に使いやすく、標準コネクタで利用可能な操作については、こちらを利用することを推奨いたします。

なお、こちらを利用する際は、委任されたアクセス許可であり、自分が元々出来ることしか出来ません。

そして、残念ながら、上述の通り、他人の予定表の情報を取得するためには、Microsoft Graph API を利用する必要があります。

### HTTP コネクタ

HTTP コネクタを利用して Microsoft Graph API を利用する方法は以下のような感じです。こちらを利用する場合は、アプリケーションの許可となります。

クライアント ID やシークレットについては、事前に Microsoft Entra ID に登録しているアプリケーションの情報となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/1357c739-65c6-3b92-b8dd-fde85f1c18c6.png)

:::note
上記はユーザーを新規作成する例ですが、もちろん、他人の予定表の情報も取得可能です。
:::

また、こちらのコネクタを利用する場合、基本的に Power Platform の管理者に申請する必要があると考えます。例えば、Power Platform の環境を払い出して、HTTP コネクタが利用できるよう、その環境向けに DLP ポリシーも別途作成して割り当てるなどの対応が必要になると考えます。

### カスタムコネクタ

こちらの場合も、事前に Microsoft Entra ID へのアプリ登録が必要です。一般的には、以下のようにしてセキュリティの設定をして、委任されたアクセス許可で利用すると考えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/a2c3aecf-40ec-5e62-18b9-afcc32869d3e.png)

こちらのコネクタについても、基本的に Power Platform の管理者に申請する必要があると考えます。

### (標準コネクタの) HTTP 要求アクション

一部のコネクタには、以下のような HTTP 要求を送信するアクションがございます。
こちらを利用して、Microsoft Graph API を利用することが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/6b491eb9-5078-5d7c-e949-3d63b0ee2859.png)

以前は、(何故か?) こちらの、Office 365 Groups コネクタで、Outlook 系の要求含め、HTTP 要求を送信することができましたが、こちらが整理され (?)、嬉しいことに、Outlook コネクタにも HTTP 要求を送信するアクションが登場しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/c6b230a4-81b6-a5de-8c54-a8756a70c2e5.png)

これらのコネクタのアクションは、委任されたアクセス許可で動作します。
そして、こちらを利用するメリットとして、Microsoft Entra ID へのアプリ登録、HTTP コネクタやカスタムコネクタの利用が不要ということが挙げられます。

そうなると、このアクションで具体的にどのような操作が可能か気になると思います。こちらについては、コネクタのリファレンスより確認可能です。

https://learn.microsoft.com/ja-jp/connectors/office365/?WT.mc_id=DX-MVP-5005281#actions

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/52883d1f-5dfa-f488-9e1c-0b40f66dd406.png)

※Office 365 Groups コネクタで、HTTP 要求を送信することができた際は、少なからず混乱もあり、また、本番環境で利用することはちょっと怖い感じでしたが、Outlook コネクタにも HTTP 要求を送信するアクションが登場し、上記の通り利用可能なリソースについてもリファレンスに記載があるため、利用しやすくなったと思います

evetns、calendar のリソースも記載があるため、こちらを利用すると、例えば、以下のように、他人の予定表の情報も取得することが可能でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/ceffeb5e-f989-d9f7-3273-c0ffdaa413cb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/a0f4bb6b-cb47-9780-8619-68e86dded0c2.png)

::: note warn
上記アクションを実行する場合、取得先のユーザーの予定表フォルダーに対する権限が必要です。
具体的には、Reviewer 以上の権限が必要です。

以下、Exchange Online のコマンドで、アクセス権があるか確認した結果です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/56123091-c352-5cb8-d286-f3a7c7a3476d.png)

アクセス権の追加は、相手側にて、Outlook で操作いただくか、管理者の方で以下のようなコマンドを実行します。

```
Add-MailboxFolderPermission -Identity testuser2@contoso.onmicrosoft.com:\予定表 -User testuser1@contoso.onmicrosoft.com -AccessRights Reviewer
```

なお、私の手元では、十分なアクセス権がない場合、以下のような結果となりました。エラーメッセージからは判断しにくいですが、、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/c507a202-5b2a-d36a-60c4-00582f588aea.png)

:::

# HTTP 要求アクションで他人の予定表を操作する

もちろん、シナリオ次第では、Microsoft Entra ID へのアプリ登録をして、HTTP コネクタを利用し、アプリケーション許可を利用するようなケースもあると思います。

しかし、市民開発者の方からすると、 Microsoft Entra ID へのアプリ登録申請し、また、HTTP コネクタやカスタムコネクタを利用するために Power Platform の管理者に申請し、委任されたアクセス許可とアプリケーション許可の違い等を把握してアプリやフローを開発することは簡単ではなく、敷居が高いと思います。

そのため、HTTP 要求アクションをベースに、他人の予定表の情報の取得や操作する方法について整理してみます。

まず、他人の予定表に関する情報は、以下のアクションで取得可能です。

https://learn.microsoft.com/ja-jp/graph/api/calendar-list-events?view=graph-rest-1.0&tabs=http

https://learn.microsoft.com/ja-jp/graph/api/user-list-calendarview?view=graph-rest-1.0&tabs=http

こちらをベースに、Power Apps、Power Automate それぞれで利用する方法を整理いたします。

## Power Apps の場合

Power Apps の場合、以下のようにしてリクエスト可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/d3e81422-1bb3-a490-5f05-51a433904be4.png)

```
Set(
    gblCalendar,
    Office365Outlook.HttpRequest(
        "https://graph.microsoft.com/v1.0/users/testRoom001@contoso.onmicrosoft.com/events",
        "Get",
        "",
        {ContentType: "application/json"}
    )
);
```

しかし、結果を変数に入れると、以下のように、UntypedObject となっており、非常に扱いづいらいです。
こちらが標準で型を把握出来るようになれば良いのですが、現状少しイレギュラーな対応が必要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/dbb0e536-96f9-0744-8086-49fb5fde0f97.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/cb436c7e-c17b-3fd0-7185-a8008480ea98.png)

対策としては、まず、以下のようなアプローチがあります。

https://koruneko.hatenablog.com/entry/2022/12/21/081146

もう一つは、応答を地道に解析して行く方法です。以下のように、応答の value が配列になっているため、Table に変換してギャラリーの`[Items]`プロパティに指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/a9b50a05-80e5-cb41-2a89-f8f8db0c9019.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/799250a0-c777-6a5e-898c-945fd48474c9.png)

そして、表示したいデータについて、上記を参考に、地道に階層を辿って指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/8f3f6c52-cfc2-5cd9-49d0-e2633e249c0d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/81bd08d9-fa84-72a1-1fd5-ed9d4be99dcc.png)

```
DateAdd(
    DateTimeValue(ThisItem.Value.start.dateTime),
    -TimeZoneOffset(),
    TimeUnit.Minutes
) & "～" & Text(
    DateAdd(
        DateTimeValue(ThisItem.Value.end.dateTime),
        -TimeZoneOffset(),
        TimeUnit.Minutes
    ),
    "dd " & "日" & "hh" & "時" & "mm" & "分"
)
```

これにより、Power Apps で他人の予定表の情報を表示できました。

:::note warn
表示可能ですが、各項目についても UntypedObject となっているため、例えば、ThisItem.Value の後にドットを入力しても候補が表示されません。そのため、応答内容を踏まえ、大文字小文字含め正確に指定する必要があります。
:::

:::note
各 API の応答内容について、API の応答のリファレンスを確認、または、モニターツールから確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/7d241bb3-b814-5ead-5b21-8721f32a44d3.png)
:::


## Power Automate の場合

取得した情報について、JSON の解析をして情報を扱いやすくします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/fccf7d46-8a6b-0fe1-ba76-011c5c4325fc.png)

しかし、取得した情報を Power Apps で表示したい場合は、Power Apps への応答の返し方について留意する必要があります。

例えば、JSON の解析結果の Value をそのまま HTTP 応答で返すようにしている場合、以下のようにエラーが発生し、フローを追加出来ません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/2732349f-8672-3656-4530-5b813d109c38.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/bbbb24f7-2534-4a0e-b80c-0d03f230946d.png)

そのため、対策としては、まず、`[PowerApp または Flow に応答する]`アクションの場合は、以下のようにして応答します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/91698b99-4b5e-d0a2-00bc-87b89934728a.png)

呼び出しは以下のような感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/6f7f32a3-7792-c750-0b65-bd9c9fc8a99a.png)

ギャラリーの`[Items]`プロパティは以下のような感じです。一旦テキストで受け取っているので、ParseJSON し、配列の情報を返しているため、Table 関数でテーブル化します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/e5246cb0-4f56-b7fa-b742-4cab858db3b1.png)

あとは、Power Apps から直接呼び出すときと同じようにしてデータを表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/d3488295-ed7d-a0d2-be0d-6f74d24c604d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/269926b7-c309-a80a-2d8c-c4607dd97deb.png)

HTTP 応答が使える場合は、JSON をそのまま返し、結果をコレクションに格納します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/546ecc41-7b17-69f7-cf5c-8e8d0fa217f3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/29fd1062-a8be-8b6f-ef65-c31f86cf42f7.png)

こちらのアプローチの場合、上記のような式で直接コレクションに格納でき、型も識別出来ているため、Power Apps でデータを扱いやすいです。そのため、こちらのアクションが利用できる場合は、こちらを利用した方が良いと考えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/d5d5bf67-0caa-40e8-5166-1c74ce758a99.png)

# 他人の予定表の予定 (イベント) の承諾

以下のアクションでイベントを承諾することも可能です。

https://learn.microsoft.com/ja-jp/graph/api/event-accept?view=graph-rest-1.0&tabs=http

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/99b1c7bb-8592-8fd0-9b74-82fa6d6652d7.png)

そのため、例えば、会議室メールボックスの承諾を代理人として Outlook で手動で行っているようなケースにおいて、その処理を Power Apps、Power Automate で実施するようにすることも可能です。

:::note

事前に以下のようなコマンドで、会議室メールボックスの予定表フォルダーに対して権限を付与します。

```
Add-MailboxFolderPermission -Identity testRoom001@contoso.onmicrosoft.com:\予定表 -User testuser1@contoso.onmicrosoft.com -AccessRights Editor -SharingPermissionFlags Delegate

```
:::

https://learn.microsoft.com/ja-jp/powershell/module/exchange/add-mailboxfolderpermission?view=exchange-ps

そのため、Power Apps から承諾したい予定を選択し、Power Automate に渡して承諾するようなことも可能かと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/79d7a90f-2765-1c83-3972-80f27121c571.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/d76911b5-409b-5b60-3f1c-bcffcb06116a.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/72a15663-57bf-c84d-dfc3-2131fb94d82f.png)

# まとめ

今回は、Power Platform で他人の予定表を操作する方法について整理してみました。
アプローチは複数あり、また、それに応じて学ぶことが出てきたり、管理者の方との連携が必要になることがあったりするため簡単ではないですが、少しでも参考になれば幸いです。