BoxとServiceNow連携：コラボレーション作成

# 概要
以前記事でServiceNowとBoxの連携について書きはじめました：
- [BoxとServiceNow連携：認証方法](https://qiita.com/mshcruz/items/5e3f8e72d5550b0c3937)
- [BoxとServiceNow連携：フォルダ作成](https://qiita.com/mshcruz/items/879a218bbbf03f91a5d8)

普通は、ServiceNowとBoxを連携する際に、一つの操作ずつを実行することだけではなく、複数の操作が繋がります。今回は「プロジェクトフォルダの作成依頼」というシナリオをベースにして、実装方法を紹介します。

イメージとして、ある会社のBoxユーザーは[ビューアー](https://support.box.com/hc/ja/articles/360044196413-%E3%82%B3%E3%83%A9%E3%83%9C%E3%83%AC%E3%83%BC%E3%82%BF%E3%81%AE%E6%A8%A9%E9%99%90%E3%83%AC%E3%83%99%E3%83%AB%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6#:~:text=%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E3%82%A2%E3%83%BC/%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%80%E3%83%BC-,%E3%83%93%E3%83%A5%E3%83%BC%E3%82%A2%E3%83%BC,-%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E3%82%A2%E3%83%BC)権限しか持っていませんので、自分でフォルダを作成することができません。新しいプロジェクトフォルダを作成したい場合は、ServiceNowの[サービスポータル](https://docs.servicenow.com/csh?topicname=c_ServicePortal.html&version=latest)の[レコードプロデューサー](https://docs.servicenow.com/csh?topicname=c_RecordProducer.html&version=latest)経由で依頼する必要があります。申請する際に、必要な情報は以下通りにします：
1. プロジェクトフォルダ名
2. プロジェクトフォルダの親フォルダID
3. ビューアーとして追加されるコラボレーターのメールアドレス

そして、サービスカタログで依頼したら、フォルダ作成とコラボレーション作成処理を起動する方法を紹介します。

# 準備

本記事では、Boxカスタムアプリ、ServiceNowのアプリケーションレジストリとRESTメッセージが作成・設定されたことを仮定します。それらの設定について、「[BoxとServiceNow連携：認証方法](https://qiita.com/mshcruz/items/5e3f8e72d5550b0c3937)」を参考してください。

また、コラボレーション作成はフォルダIDが必要ですので、フォルダを作成するRESTメッセージのメソッドが実装されていることを仮定します。フォルダ作成について、「[BoxとServiceNow連携：フォルダ作成](https://qiita.com/mshcruz/items/879a218bbbf03f91a5d8)」を参考してください。

# 実装

上記のシナリオを実現するために、以下のステップを実装します：
1. フォルダ作成依頼情報のテーブルを作成
2. レコードプロデューサーを作成
3. 「コラボレーション作成」のHTTPメソッドを追加
4. ビジネスルールを作成

最後に動作確認を行います。

## フォルダ作成依頼情報のテーブルを作成

まずはBoxフォルダ作成依頼の情報を保管するテーブルを作成します：
- ラベル：<任意の名前>（例：Boxフォルダ作成依頼）
- 名前：<任意の名前>（例：u_box_folder_creation_request）

![テーブル作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/2b9d3cb7-0596-f7f3-d53a-e0cc83a56994.png)

新規レコードを保存すると、以下の列を追加します：
- 「フォルダ名」列
  - タイプ：文字列 (完全な UTF-8)
  - 列ラベル：<任意の名前>（例：フォルダ名）
  - 列名：<任意の名前>（例：u_folder_name）
- 「親フォルダID」列
  - タイプ：文字列 (完全な UTF-8)
  - 列ラベル：<任意の名前>（例：親フォルダID）
  - 列名：<任意の名前>（例：u_parent_folder_id）
- 「コラボレーターのメールアドレス」列
  - タイプ：文字列 (完全な UTF-8)
  - 列ラベル：<任意の名前>（例：コラボレーター）
  - 列名：<任意の名前>（例：u_collaborators）

![テーブル列.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/7ef0b3f7-4200-b73b-0646-2573722f1873.png)

:::note warn
この記事では、なるべくわかりやすくするため、テーブル列の設定を極力省いていますが、本番の実装で適切なタイプや最大長などを設定することをお勧めします。
特に、コラボレーターのメールアドレスをただの文字列ではなく、リスト化にした方が最適だと考えられます。
:::

## レコードプロデューサーを作成

次は、サービスカタログで利用するレコードプロデューサーを作成します：
- 名前：<任意の名前>（例：Boxフォルダ作成依頼）
- テーブル名：前のステップで作成したテーブル（例：u_box_folder_creation_request）

![レコードプロデューサー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/2a77c7a5-ef3e-113b-95c1-92d5e51dce0f.png)

レコードを保存すると、画面の下に「変数」タブが表示され、依頼フォームの項目を設定することができます：
- 「フォルダ名」変数
  - フィールドにマップ：チェック
  - タイプ：1行テキスト
  - フィールド：フォルダ名
  - 「質問」タブで「質問」：<任意の名前>（例：フォルダ名）
  - 「質問」タブで「名前」：前のステップで作成したフォルダ名のテーブル列名（例：u_folder_name）
- 「親フォルダID」変数
  - フィールドにマップ：チェック 
  - タイプ：1行テキスト
  - フィールド：親フォルダID
  - 「質問」タブで「質問」：<任意の名前>（例：親フォルダID）
  - 「質問」タブで「名前」：前のステップで作成した親フォルダIDのテーブル列名（例：u_parent_folder_id）
- 「コラボレーター」変数
  - フィールドにマップ：チェック
  - タイプ：1行テキスト
  - フィールド：コラボレーター
  - 「質問」タブで「質問」：<任意の名前>（例：コラボレーターのメールアドレス（カンマ区切り））
  - 「質問」タブで「名前」：前のステップで作成したコラボレーターのテーブル列名（例：u_collaborators）

![レコードプロデューサー変数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/3c1b4095-f47f-32ff-ed4b-edfa979e3b44.png)

最後に、レコードプロデューサーの「カタログ」タブで「サービスカタログ」を追加し、「カテゴリ」タブで適切なカテゴリを選択します（例：アプリケーションとアカウントへのアクセス）。

![レコードプロデューサーカタログ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/e573d650-a26e-633f-db09-03b331b0c5c8.png)

サービスカタログで作成したレコードプロデューサーを検索すると、フォームの見た目などを確認することができます。

テスト値を入力して送信すると、プロデューサーの該当テーブルでレコードが作成されたことも確認できます。

レコード追加に対するアクションはまだ定義されていませんので、テストで申請しても何も起こりません。次のセクションで、コラボレーション作成に対するリクエストを実装し、レコード追加のアクションとして使います。

## 「コラボレーション作成」のHTTPメソッドを追加

Box上でコラボレーション作成は次のAPIエンドポイントへのリクエストで実施できます：`https://api.box.com/2.0/collaborations`（[ガイド](https://ja.developer.box.com/reference/post-collaborations/)）。

パラメータとして、共有するアイテムの種類（フォルダかファイル）とID、コラボレーターの種類（ユーザーかグループ）とID、権限レベルを設定する必要があります。それらはリクエストの本文で指定します。

上記のエンドポイントへリクエストを送信するために、事前に作成されたRESTメッセージで新規なHTTPメソッドを追加します。新規HTTPメソッド画面で以下のように設定します（詳細設定は[Box APIガイド](https://ja.developer.box.com/reference/post-collaborations/)で確認だきます）：
- 名前：<任意の名前>（例：Boxコラボレーション作成）
- HTTP メソッド：POST
- REST エンドポイント：https://api.box.com/2.0/collaborations
- 「HTTP要求」タブの「コンテンツ」の内容は以下のJSONです。JSONでは`item_id`と`user_login`を変数として指定します

```JSON
{
   "item": {
     "type": "folder",
     "id": "${item_id}"
   },
   "accessible_by": {
     "type": "user",
     "login": "${user_login}"
   },
   "role": "viewer"
}
```

:::note warn
この例があまり複雑ならないように、アイテムの種類、ユーザーの種類、権限レベルを固定にしましたが、本番の実装だと変数にすることをお勧めします。
:::

![コラボレーション作成メソッド.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/eb34d527-adb2-d582-2aee-24cb0069bff6.png)

レコードを保存すると、画面の下に「REST メッセージ関数パラメーター」タブが表示されます。「関連リンク」の「変数の自動生成」をクリックすると、JSONで指定した変数がパラメーターとして設定されます。

![Screenshot 2024-10-07 at 20.37.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/4039dd88-0bcb-8660-db3e-015b81b76176.png)

テストのため、変数のデフォルト値（「値」列）列を設定して、「関連リンク」の「テスト」をクリックすると、設定されたメソッドでBox APIへリクエストが送信され、Box上でコラボレーションが作成されたことを確認できます。ただ、今回は前のステップで作成されたレコードプロデューサーと繋いで、サービスカタログでテストします。そのため、RESTメソッドを呼ぶ[ビジネスルール](https://docs.servicenow.com/csh?topicname=c_BusinessRules.html&version=latest)を作成します。

## ビジネスルールを作成
レコードプロデューサーでBoxフォルダ作成を依頼すると、テーブルにレコードが追加されます。その時点のアクションとして、フォルダ作成とコラボレーション作成を実行するには、そのテーブルに対する[ビジネスルール](https://docs.servicenow.com/csh?topicname=c_BusinessRules.html&version=latest)を作成します：
- 名前：<任意の名前>（例：Boxフォルダ作成依頼処理）
- テーブル：前のステップで作成したテーブル（例：u_box_folder_creation_request）
- 詳細：チェック
- 「実行タイミング」タブの「時期」：後
- 「実行タイミング」タブの「挿入時」：チェック

![ビジネスルール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/1d702874-b6b6-d476-0d27-e0cc61560c49.png)

「詳細」タブの「スクリプト」ボックスで以下のJavaScriptコードを入れます。

```javascript
(function executeRule(current, previous) {
	// フォルダ作成リクエストを送信する
	var r = new sn_ws.RESTMessageV2('Box', 'Boxフォルダ作成');
	r.setStringParameterNoEscape('parent_folder_id', current.u_parent_folder_id);
	r.setStringParameterNoEscape('folder_name', current.u_folder_name);
	var response = r.execute();
	var responseBody = JSON.parse(response.getBody());
	var httpStatus = response.getStatusCode();

	// フォルダ作成が成功したら、コラボレーション作成リクエストを送信する
	if (httpStatus == 201 && responseBody.id) {
		// 作成されたフォルダIDをリクエストのレスポンスから取得する
		var folderId = responseBody.id;

		// コラボレーターリストを配列にする
		var collaborators = current.u_collaborators.split(",");

		// コラボレーター毎にコラボレーションリクエストを送信する
		for (var i = 0; i < collaborators.length; i++) {
			var collaborator = collaborators[i];
			r = new sn_ws.RESTMessageV2('Box', 'Boxコラボレーション作成');
			r.setStringParameterNoEscape('item_id', folderId);
			r.setStringParameterNoEscape('user_login', collaborator);
			r.execute();
		}		
	}
})(current, previous);
```

:::note warn
この記事では、なるべくわかりやすくするため、コードを極力省いています。
セキュリティ面での行うべき考慮を省略し、エラーハンドリングなども実装されていません。
具体的な実装時には非機能面の考慮と実装方法を開発者が行う必要があります。
:::

## 動作確認

実装したステップは正常に実行されることを確認するには、サービスカタログでBoxプロジェクトフォルダ作成を依頼します。

![Screenshot 2024-10-08 at 09.51.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/29f46f70-3c2a-910d-89d6-bef5b107e409.png)

「送信」ボタンを押すと、入力した情報でレコードが作成されて、該当テーブルで確認できます。そして、レコードの作成時点で用意したビジネスルールが呼ばれて、フォルダ作成とコラボレーション作成リクエストをBox APIへ送信されます。

その結果、Box上でプロジェクトフォルダが作成されて、フォームで指定されたメールアドレスのユーザー（例：「鈴木一郎」と「佐藤花子」）はビューアーとして追加されたことが確認できます。

![Boxフォルダ作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/d14194e2-6180-9afd-2c83-afb48bddd126.png)

# まとめ

この記事では、ServiceNowからBox上のフォルダに対するコラボレーション作成方法について説明しました。

ビジネスルールで「Boxフォルダ作成」のHTTPメソッドと繋いで、ServiceNowのサービスカタログでフォルダ作成を申請することができました。

このように、Box APIへのリクエストをHTTPメソッドで実装し、様々なコンポーネント（ポータルやワークフローなど）で使えます。