クラウドストレージサービスのboxを触ってみました。
SaaSの良いところは自分でAPIを使って拡張できるところだと思いますが、 例えばboxもWebhookを使ってイベント発生時に通知を行うことができます。
- 参考) Webhookトリガー一覧
フォルダのイベントにWebhookを登録するにはBOXアプリケーションを作成する必要があります。 BOXアプリケーションには以下の2種類があり役割が違います。
- BOX統合
- boxの認証を使用してユーザが自分の権限でファイルを操作したりするアプリケーションを作成する。
- 原則、OAuthを利用したWeb画面の認証を用いる(アプリ開発者向けにトークンの発行も可能)
- BOX PLATFORM
- OAuthと別にアプリ用のユーザを作成してJWT認証も可能
- アプリのユーザがboxと連携するのでユーザにboxのアカウントを意識させない(ことも可能)
ちょっと分かりづらいかもしれませんが「BOX統合」はBOXの機能を拡張するアプリケーションで、 「BOX PLATFORM」はBOXをバックエンドとしたアプリケーションというイメージです。
今回は認証をアプリ用のユーザで行いたかったので「BOX PLATFORM」でアプリを構築します。
boxにサインアップ
まず自分のメールアドレスで「開発者」アカウントを作成します。 (*通常のサインアップと入り口が違うので注意!)
- https://account.box.com/signup/n/developer アカウントの種類が「開発者」になっていることを確認してください。
アプリケーションの作成
- 開発者コンソールからアプリを作成
- https://app.box.com/developers/console
「MyApps」 -> 「アプリの新規作成」 -> 「カスタムアプリ」で「次へ」
「JWTを使用したOAuth2.0」認証を選択。アプリの名前を適当に入力します。
以下のコマンドが出てくるので試してみます。自分が見れるフォルダの一覧が出てきたら動作検証OKです。
curl https://api.box.com/2.0/folders/0 -H "Authorization: Bearer <Developerトークン>"
作成したアプリケーションの登録
- 2段階認証の設定 アプリケーションからの認証に必要な「公開キー」を登録するには2段階認証の設定が必須です。 ユーザの設定から2段階認証の設定をします。
公開キーの作成 以下のコマンドで生成します。パスワードも設定しましょう。
openssl genrsa -aes256 -out private_key.pem 2048 openssl rsa -pubout -in private_key.pem -out public_key.pem- DeveloperConsoleで公開キーの設定 https://app.box.com/developers/console/app//configuration DeveloperConsoleに生成した公開キー(上のコマンドではpublic_key.pemで生成された方)を登録します。 アプリケーションの設定「公開キーの追加と管理」の「公開キーを追加」から中身をコピペで追加します。 公開キーを追加するとIDが自動で振られます。あとで使うのでとっておいてください。
管理コンソールでアプリケーションを承認 https://app.box.com/master/settings/openbox 「管理コンソール」 > 「Business設定」 > 「アプリ」 > 「新しいアプリケーションを承認」を選択 「APIキー」を入力するように言われるのでわかりづらいですが「クライアントID」を入れればOKです。
AppUserの作成
ここからはコードを書きます。PythonのSDKに不具合があり使えなかったのでnode.jsでやります。
box-node-sdkを使用します。
まず、SDKに認証情報を渡して初期化します。
var fs = require('fs');
var BoxSDK = require('box-node-sdk');
var sdk = new BoxSDK({
clientID: '<Developer Consoleに載っているクライアントID>',
clientSecret: '<Developer Consoleに載っているクライアント機密コード>',
appAuth: {
algorithm: 'RS256',
keyID: '<Developer Consoleに登録した秘密鍵のID>',
privateKey: fs.readFileSync('<秘密鍵ファイル>'),
passphrase: '<秘密鍵のパスワード>'
}
});
続いてAppUserを作成します。 「エンタープライズID」は「管理コンソール > Business設定」から確認できます。
// AppUserの作成
var client = sdk.getAppAuthClient('enterprise', '<エンタープライズID>');
var requestParams = {
body: {
name: '<AppUser名(なんでもよい)>',
is_platform_access_only: true
}
};
client.post('/users', requestParams, client.defaultResponseHandler(function (err, data) {
if (err) throw err;
console.log(data);
}));
実行結果はこちら。これでAppUserの作成は完了です。
{
type: 'user',
id: '<AppUserID>',
name: '<AppUser名>',
login: 'AppUser_333333_XXXXXXXXXX@boxdevedition.com',
created_at: '2017-02-17T03:45:22-08:00',
modified_at: '2017-02-17T03:45:22-08:00',
language: 'ja',
timezone: 'Asia/Tokyo',
space_amount: 10737418240,
space_used: 0,
max_upload_size: 2147483648,
status: 'active',
job_title: '',
phone: '',
address: '',
avatar_url: 'https://app.box.com/api/avatar/large/0000000000'
}
AppUserをフォルダに招待する
AppUserは通常のユーザと同様にコラボレーションに参加できるのでメールアドレスで招待を送れます。 Webhookを送信したいフォルダへのアクセスを許可するために通常ユーザからAppUserに対してフォルダへの 招待を送ったら「承諾」というフローが必要なのですがAppUserはログインできないのでこれまたAPIから 「承諾」を実施する必要があります。以下は雑ですが「招待」されたフォルダを全て「承諾」するコードです。
client.collaborations.getPending(function (err, data) {
if (err) throw err;
data.entries.forEach(function (entry) {
var options = {status: 'accepted'};
client.collaborations.update(entry.id, options, function (err, data) {
if (err) console.error(err);
else console.log(data);
});
});
});
Webhookの登録
- Beeceptorで送信先のエンドポイントを作成します Beeceptorの説明は割愛します。便利なサービスです。 ここで注意なのが生成されるURLはhttpなのですがWebhookへはhttpsのURLしか登録できません。 Beeceptorはhttpsにも対応していますので画面に表示されたURLをhttpsに変更して使用します。
Webhookを登録します SDKの初期化までは先ほどと同じ手順です。 ここではクライアントにAppUserを使用しますので先ほど作成したAppUserのIDを設定します。 フォルダIDは画面から確認もできますしクライアントからフォルダの一覧を取得することもできます。 画面から確認する場合は「https://app.box.com/files/0/f/{フォルダID}/{フォルダ名}」 のようになってますので、Webhookを登録したいフォルダにアクセスできる場合は画面から取得します。
var client = sdk.getAppAuthClient('user', '<AppUserID>'); var hookURL = '<Webhookの送信先>'; var triggers = ["FILE.UPLOADED","FILE.DOWNLOADED"]; client.webhooks.create('<フォルダID>', 'folder', hookURL, triggers, function (err, data) { if (err) console.error(err); console.log(data); });- ファイルをアップロードしてBeeceptorを確認
Webhookを登録したフォルダにファイルをアップロードすると、
BeeceptorにWebhookが届いているのが確認できます。
POST <Webhookの送信先> application/json; charset=UTF-8 HEADERS Content-Length: 1519 Accept-Encoding: gzip Connection: close Box-Signature-Algorithm: HmacSHA256 Via: 1.1 vegur Content-Type: application/json; charset=UTF-8 Host: requestb.in Total-Route-Time: 0 Box-Signature-Version: 1 Cf-Ipcountry: US User-Agent: Box-WH-Client/0.1 Box-Signature-Primary: iMjPIbbY7a7SjybSwiNpVFCHkmTY1eTj2N/z61CNqnk= Cache-Control: max-age=259200 Cf-Ray: 333dcfa25a876c58-SJC X-Request-Id: c8f8e876-0347-4f11-a6d2-f8304157e9ac Connect-Time: 1 Cf-Connecting-Ip: 74.112.184.199 Cf-Visitor: {"scheme":"https"} Cookie: __cfduid=d773a71cdae3cece876323b285a4394401487364822 Box-Delivery-Timestamp: 2017-02-19T16:23:38-08:00 Surrogate-Capability: web-proxy2004.sv2.box.net="Surrogate/1.0 ESI/1.0" Box-Delivery-Id: 80bacbb5-e521-47e0-b20a-d100713d4f16{ "type": "webhook_event", "id": "126a0256-62ff-412a-b64f-d3f8749c3b42", "created_at": "2017-02-19T16:23:38-08:00", "trigger": "FILE.UPLOADED", "webhook": { "id": "1777503", "type": "webhook" }, "created_by": { "type": "user", "id": "1065123912", "name": "Yuto Matsuki", "login": "yutomatsuki@mailaddress" }, "source": { "id": "137470151050", "type": "file", "file_version": { "type": "file_version", "id": "146665803658", "sha1": "14a956e7efe7948e16fa489b530a9d34e4f9877d" }, "sequence_id": "0", "etag": "0", "sha1": "14a956e7efe7948e16fa489b530a9d34e4f9877d", "name": "favicon.ico_48x48.png", "description": "", "size": 420, "path_collection": { "total_count": 2, "entries": [{ "type": "folder", "id": "0", "sequence_id": null, "etag": null, "name": "\u3059\u3079\u3066\u306e\u30d5\u30a1\u30a4\u30eb" }, { "type": "folder", "id": "19399950731", "sequence_id": "0", "etag": "0", "name": "Sample" }] }, "created_at": "2017-02-19T16:23:38-08:00", "modified_at": "2017-02-19T16:23:38-08:00", "trashed_at": null, "purged_at": null, "content_created_at": "2017-02-15T02:06:37-08:00", "content_modified_at": "2017-02-15T02:06:37-08:00", "created_by": { "type": "user", "id": "1065123912", "name": "Yuto Matsuki", "login": "yutomatsuki@mailaddress" }, "modified_by": { "type": "user", "id": "1065123912", "name": "Yuto Matsuki", "login": "yutomatsuki@" }, "owned_by": { "type": "user", "id": "1065123912", "name": "Yuto Matsuki", "login": "yutomatsuki@mailaddress" }, "shared_link": null, "parent": { "type": "folder", "id": "19399950731", "sequence_id": "0", "etag": "0", "name": "Sample" }, "item_status": "active" }, "additional_info": [] }
まとめ
box APIをBOX PLATFORMから使い始めるまでは少し手順が多くて面倒ですが、 一度環境ができてしまえばファイルに触り放題なので楽しいです。
Webhook V2はフォルダ毎に違う呼び先に飛ばせるのが特徴なので、 次はフォルダ毎に別々のAWS Lambdaを呼び出すみたいなのも作ってみようと思います。
松木佑徒