Quantcast
Viewing all articles
Browse latest Browse all 8691

Box UI ElementsのContent OpenWithの使いかた

Box UI ElementsのContent OpenWithとは

Content OpenWithのまえに、そもそもBox UI Elementsとはなにかという話ですが、これはBox社が公式に提供しているJavascriptとCSSによるWeb用の部品です。自作のウェブサイトに組み込むことで、標準のBoxの様なUIを簡単に実現可能です。

Box UI Elementsには、現時点で以下の6個のコンポーネントが用意されています。

  • Content Explorer

  • Content OpenWith <= 今回利用

  • Content Picker

  • Content Preview

  • Content Sidebar

  • Content Uploader

この中で、Content OpenWithは、一番ややこしかったので、使いかたを備忘録として残します。

Content OpenWithは、カスタムアプリケーション上にボタンを配置し、BoxEditと連携して、ローカルでエディタを開き、保存時にBoxにデータを書き戻すことができるコンポーネントです。

このコンポーネントを利用すると、カスタムアプリケーションでもBoxからエディタを開くような滑らかな連携が可能になります。

Box UI Elements自体は、Reactで作られています。Reactを利用している場合、npm経由でライブラリをインストールして使うことが可能です。React以外の場合はCDN経由で提供されているjsファイルを利用できます。

基本的な部分は、ここに書いてあることをなぞっています。
https://ja.developer.box.com/guides/embed/ui-elements/

事前準備

このサンプルでは、以下の環境の利用を前提としています。実際にやってみたい人は予め準備が必要です。

  • Boxのアカウント(管理者権限が利用可能なBoxテナント)
  • Box Toolsのインストール(ローカルでエディタを開きBoxに同期するために必要)
  • Herokuのアカウント
  • Heroku CLIのインストール
  • Gitのインストール
  • Nodeおよびパッケージマネージャ(npm or yarn)のインストール

なお、コードは以下のgithubにもおいておきます。
https://github.com/kobay/box-ui-elements-openwith-example

Box環境の準備

Boxの開発者コンソールにアクセスし、「アプリの新規作成」を押します

開発者コンソールへのアクセスが初めての場合は、https://ja.developer.box.com/にアクセスし、マイアプリボタンをクリックすることで、アクセスが可能となります。

アプリの種類はカスタムアプリを選択します。

今回は、認証方法に、「JWTを使用したOAuth 2.0 (サーバー認証)」を選択します。

アプリの名前に任意の文字を入れ、アプリの作成ボタンを押します。

マイアプリ > 構成を開き以下のように設定にします。
(多分こんな感じで大丈夫なはずです・・、アプリケーションアクセスやスコープがたらなければ変えてください)

Image may be NSFW.
Clik here to view.
スクリーンショット 2020-05-11 20.09.52.png

公開キーの追加と管理のセクションで、「公開/秘密キーペアを生成」を押します。

ダウンロードされるファイルは、あとでコードから利用するので、config.jsonとリネームしておきます。

CORSドメインは、公開するHerokuのURLを追加します。

Herokuでのアプリケーション作成が終わったら戻ってきて設定します。

コードの準備

以下の手順で、プロジェクトを用意します。

# 適当な名前のフォルダを作って、フォルダに入るmkdir box-openwith-sample
cd box-openwith-sample

# Nodeプロジェクトとして初期化 (npmでも)
yarn init -y# 必要なライブラリの追加 
yarn add box-node-sdk express ejs axios

# 必要なファイルを追加touch app.js
touch index.ejs

# こちらは事前準備用のファイル(必須ではない)touch setup.js

package.jsonに、startをスクリプトを追加します。(Herokuがstartを実行します)

package.json
{"scripts":{"start":"node app.js"},}

Boxでアプリの設定をしたときにダウンロードしたconfig.jsonをプロジェクトフォルダ直下に配置します。

任意のエディタでsetup.jsを作成します。

このファイルは事前に(1)Appユーザーを作成し、(2)ファイルをアップロードし、(3)BoxEditの統合を使えるようにするという操作をするために作成し、実行します。これらの処理が事前にできればいいだけなので、ファイルとしてプロジェクトに追加する必要はありません。

実行前にSample.docxというダミーのMS Wordのファイルを用意しておきます。
config.jsonが同じフォルダにある前提となっています。

ダミーのファイルはとくにWordである必要も、このファイル名である必要も有りませんが、変更する場合コードも修正してください。

setup.js
constboxSDK=require("box-node-sdk");constconfig=require("./config.json");constaxios=require("axios");constfs=require("fs");/**
 * app.jsで利用する、AppUserと、サンプルのWordファイルを予め登録する。
 * また、OpenWithを利用するために必要な、統合の設定も行う。
 */constmain=async()=>{try{// 作成済みのJWT認証用のConfigファイルを読み込むconstsdk=awaitboxSDK.getPreconfiguredInstance(config);// ServiceAccountのClientオブジェクトを作成constsaClient=sdk.getAppAuthClient("enterprise");// app userを作成 (OpenWithはServiceAccountではつかえず、AppUserが必要なため)letappUser=awaitsaClient.enterprise.addAppUser("Sample App User");// app userのホームフォルダに、サンプルとしてSample.docをアップロードするsaClient.asUser(appUser.id);conststream=fs.createReadStream("./Sample.docx");constfiles=awaitsaClient.files.uploadFile("0","Sample.docx",stream);constfile=files.entries[0];saClient.asSelf();// 念の為、現在利用可能なWebApp統合を一覧する// 13418が入っていないなら、設定がまちがっているconstappIntegs=awaitsaClient.get("/app_integrations");console.log("利用可能なWebApp統合一覧",appIntegs.body);/*
    {
      next_marker: null,
      entries: [
        { type: "app_integration", id: "10897" },
        { type: "app_integration", id: "1338" },
        { type: "app_integration", id: "13418" },  <= 13418がBox Editの統合
        { type: "app_integration", id: "3282" },
      ],
      limit: 100,
    };
    */// 作成したAppUserに、BoxEditのアプリ統合を利用できるようにする。// clientオブジェクトから何故かpostの実行(client.post)がうまく機能しなかったので、axiosで実行する// Authorizationにつけるアクセストークンは、ServiceAccountのものを利用する必要がある。constsaTokenInfo=awaitsdk.getEnterpriseAppAuthTokens();constsaAxios=axios.create({baseURL:"https://api.box.com/2.0",headers:{Authorization:`Bearer ${saTokenInfo.accessToken}`,},});// ここでは13418(BoxEdit)のみを登録するが、他のものも登録しておくと開くボタンから利用可能になるawaitsaAxios.post("/app_integration_assignments",{assignee:{type:"user",id:appUser.id,},app_integration:{type:"app_integration",id:"13418",},});// 以下のAppUserとFileのIDをapp.jsで利用するconsole.log("==================== 以下のIDをメモして、app.jsで利用する ====================");console.log(`const USER_ID = "${appUser.id}"`);console.log(`const FILE_ID = "${file.id}"`);}catch(e){console.error(e.toString());}};main();

config.jsonSample.docxが同じフォルダにあることを確認して、以下のコードを実行し、USER_IDと、FILE_IDをとって置きます。app.jsでは、この部分を書き換えてください。

【注意】config.jsonは、このサンプルでは簡易的にgitに入れていますが、本番環境ではファイルとしてgit等に入れるべきではなく、環境変数等に置くべきです。

任意のエディタでapp.jsを以下の内容で作ります。

app.js
constexpress=require("express");constboxSDK=require("box-node-sdk");constconfig=require("./config.json");constapp=express();app.set("views",".");app.set("view engine","ejs");/**
 * setup.jsで作成したファイルとユーザーを書き換える
 */constUSER_ID="";constFILE_ID="";app.get("/",async(req,res)=>{try{if(!USER_ID||!FILE_ID){res.send("USER_IDとFILE_IDに値をいれてください。");return;}constsdk=awaitboxSDK.getPreconfiguredInstance(config);// AppUserの権限でClientオブジェクトを作成constauClient=awaitsdk.getAppAuthClient("user",USER_ID);// トークンをダウンスコープする// APIリファレンスには載っていないが、UI Elementsの説明には書いてあるAPI// ここでは、OpenWithで必要なものと、Previewで必要なものを両方スコープにいれてトークンをダウンスコープするconstdownToken=awaitauClient.exchangeToken(["item_execute_integration","item_readwrite","item_preview"],`https://api.box.com/2.0/files/${FILE_ID}`);// テンプレート(index.ejs)にパラメータを渡して、HTMLを返すres.render("index",{fileId:FILE_ID,token:downToken.accessToken,});}catch(e){console.error(e.toString());}});constport=process.env.PORT||3000;app.listen(port,()=>{console.log(`express started on port ${port}`);});
ダウンスコープについて

Box UI Elementsは、Javascriptによりブラウザ内実行され、Box APIを直接実行します。このため、アクセストークンをブラウザに渡す必要があります。

これは、ブラウザ上の開発者用コンソールを利用すると、アクセストークンがエンドユーザーに見えてしまうということを意味しています。セキュリティ上問題があるので、アクセストークンのダウンスコープという手順が必要になります。ダウンスコープをすることで、指定したファイルIDに指定した操作だけを許すというアクセストークンに変換可能です。

ダウンスコープ前のアクセストークンをブラウザ側に渡すことは避けるべきでしょう。

任意のエディタでindex.ejsを以下の内容で作ります。

index.ejs
<!DOCTYPE html><htmllang="en-US"><head><metacharset="utf-8"/><title>Sample</title><linkhref="https://cdn01.boxcdn.net/platform/elements/11.0.2/ja-JP/openwith.css"rel="stylesheet"type="text/css"></link><linkhref="https://cdn01.boxcdn.net/platform/preview/2.34.0/ja-JP/preview.css"rel="stylesheet"type="text/css"></link><script src="https://cdn01.boxcdn.net/platform/elements/11.0.2/ja-JP/openwith.js"></script><script src="https://cdn01.boxcdn.net/platform/preview/2.34.0/ja-JP/preview.js"></script></head><body><divclass="openwith"style=""></div><divclass="preview-container"style="height:800px; width:100%;"></div><script>// app.jsから渡されたパラメータconstfileId="<%= fileId %>"// ダウンスコープされたアクセストークンconsttoken="<%= token %>"constopenWith=newBox.ContentOpenWith();openWith.show(fileId,token,{container:".openwith"})constpreview=newBox.Preview();preview.show(fileId,token,{container:".preview-container"});</script></body></html>

Herokuの準備

Content OpenWithはhttpsでしか動かないからherokuにデプロイしているだけです。

ローカルでhttpsで実行でも大丈夫です。

以下のコマンドを実行してHerokuにアプリを作成し、デプロイします。

# herokuにアプリを作成
heroku create

# gitを導入
git init
git add .
git commit -m"init"# herokuにデプロイ
git push heroku master

Boxの設定変更

CORS設定

Box UI Elementsはブラウザ上でAPIを呼び出すので、CORSの設定が必要になります。
もう一度Boxの開発者コンソールに戻り、CORSの設定をします。
HerokuのURLを登録します。

アプリの承認

JWTアプリは管理者に承認されている必要があるので、以下の手順で承認します。
OAuth 2.0資格情報の、クライアントIDをコピー。
管理者コンソール > アプリ(左ナビ) > カスタムアプリ (上部タブ)に移動し、「新しいアプリケーションを承認」というボタンを押します。
クライアントIDを聞かれるので、コピーしたクライアントIDをペーストして承認します。

ローカルのBoxEditの設定

続いて、ローカルマシンでのBoxEditのセーフリストの設定します。

詳細はこちらをご覧ください。

https://ja.developer.box.com/guides/embed/ui-elements/custom-domains/

Macの環境だと、OpenWith.shをダウンロードし、herokuのドメイン:xxx.heorkuapp.comをコマンドから追加するイメージです。

エンドユーザーにContent OpenWithを利用させたい場合は、この操作を1回だけユーザーにやってもらう必要があるので、この点が少しハードルが高いかも、という懸念はあります。

ちなみにこれをやらないとエラーになるとかではなく、OpenWithで描画される開くボタンがdisable状態になるだけです。

実行してみる

(URLがわかっているならわざわざ叩く必要ないですが)以下のコマンドで、ブラウザが立ち上がります。

heroku open

以下のように開くボタンとプレビューが表示され、開くボタンを押すとBoxEditが呼び出され、ローカルのエディタがたちあがります。

Image may be NSFW.
Clik here to view.
openwith.png

MS Wordで内容を変更し、保存ボタンを押した後、Web画面をリロードするとプレビューで変更されていることが確認できます。

感想・まとめ

ちょっとめんどくさいけど、作ると結構スムーズに動くのでカスタムアプリからBoxに連携する際に強力な道具になりそうです。
エンドユーザーのコンピュータにBoxToolsのインストールと、セーフリストの設定をする必要がある部分が少しつらそうです。

あと、OpenWithは、以下が抜けていると動かないので注意。

  • ローカルにBoxToolsが入っている必要がある
  • ローカルでセーフリストにドメインを登録する必要がある
  • HTTPS上でのみOpenWithが動く
  • AppUserで動かす必要がある
  • 統合を事前にAppUserに紐付ける必要あり (これはServiceAccountのトークンでやらないとだめ)
  • BOXの開発者コンソールで適切なスコープとCORSの設定が必要

よくわからなかったこと

上記の一連の手順で基本的にOpenWithの実装ができましたが、以下の点についてはよくわからなかったので、記しておきます。いつか答えがみつかるといいな・・・。

  • MS Word(というか、どんなエディタでも)で保存した後に、標準のBoxであれば内容の変更を察知してRefreshボタンのポップアップが表示されるが、UI Elementではこの動作をしない。このため手動でリロードする必要があるが、ここはなんとかならないものか・・

  • もしかしたら、カスタムアプリに通知を受け取るAPIの口を用意しておけば、Webhookで更新をトリガーにAPI呼び出しをすることで、自動でリロードをかけるたり、それを促す通知をできるかも。


Viewing all articles
Browse latest Browse all 8691

Trending Articles