はじめに
Dropbox では現在、チーム向け Dropbox をチーム スペースにアップグレードする作業を進めています。この記事では、チーム スペースへのアップグレードで必要となるアプリケーション側での変更について説明します。
チーム スペースのための対応が必要かどうかは、アプリケーションの種類によって異なります。影響を受けるアプリケーションで、チーム スペースのための対応を実施していない場合、チーム スペースにアップグレードしたチームのファイルにアクセスできなくなる可能性があります。
対応が必要なアプリケーションの例を以下に示します。
- Dropbox との間で、ファイルのアップロードやダウンロード、ファイル リストの取得、共有リンクの作成など、ファイルの処理を実施するアプリケーション。特に、チーム フォルダのファイルにアクセスする必要のあるアプリケーション
- チーム フォルダを操作するアプリケーション。新しいチーム フォルダを作成する、アーカイブする、チーム向け選択型同期の設定を更新するなど
対応が不要なアプリケーションの例を以下に示します。
- チーム メンバーの招待やグループ メンバーの更新など、チーム メンバーに対する操作しか実施しないアプリケーション
Dropbox-API-Path-Root
ヘッダーを使用してチーム スペースのための対応を実施済みであり、/team/team_folder
以下の API(チーム フォルダを作成する API など)を使用しないアプリケーション。/files
または/team/team_folder
以下の Dropbox API を使用していないアプリケーション
チーム スペースの概要
チーム スペースは、フォルダの見え方をチーム メンバー全員で同じにしたいというお客様のご要望を受けて開発された機能です。チーム フォルダの場合、同じフォルダを共有しているチーム メンバーでも、人によってフォルダ名やフォルダの場所が違ってしまう場合がありました。
またチーム フォルダでは、同じような名前の共有フォルダが複数ある場合、どのフォルダがどのプロジェクトのフォルダなのか判別するのが困難でした。たとえば、「プロジェクト X」、「プロジェクト Y」、「プロジェクト Z」というプロジェクトがあり、各プロジェクトに「Design」というフォルダが存在し、各フォルダが Wendy さんに共有されているとしましょう。このとき、Wendy さんには「Design」、「Design (1)」、「Design (2)」という 3 つのフォルダが見えることになりますが、どのフォルダが「Project X」のフォルダなのか区別するのは困難です。
このため Wendy さんは、自分個人の環境でフォルダ名を変更したり、フォルダを移動したりするかもしれません。しかしその結果は、Wendy さん個人の環境にしか反映されないので、チーム全体としての作業効率が低下しかねません。
新たに導入されたチーム スペースでは、この混乱を解消するために、フォルダの見え方をチーム メンバー全員で同じにしています。このため、新しいチーム メンバーがオンボーディングの際に戸惑うこともなくなります。
このように、チーム スペースに移行するとチームでの共同作業がスムーズになります。
チーム フォルダとチーム スペースの違い
チーム フォルダを使用しているチームとチーム スペースを使用しているチームでは、フォルダ構造と使用する Dropbox API に違いが出ます。
この違いを理解するために、まず Dropbox フォルダがどのように管理されるかを説明します。
Dropbox が管理する、各メンバーのホーム フォルダ、共有フォルダ、チーム フォルダ、権限が変更されたサブフォルダは、名前空間と呼ばれます。たとえば、メンバー フォルダ以下に作成された共有フォルダ、チームによって共有されたチーム フォルダ、およびそのサブフォルダは、以下の図にあるように名前空間と呼ばれます。
- チーム フォルダを使用するチームでは、ホーム名前空間はユーザーには表示されません。
- 共有されていないフォルダは通常のフォルダとして管理され、名前空間としては管理されません。
- 共有フォルダは名前空間として管理されます。
- チーム フォルダは名前空間として管理されます。
- メンバーが追加されているなど、権限が上位フォルダから変更されているフォルダは名前空間として管理されます。
- メンバーが追加されているなど、権限が上位フォルダから変更されているフォルダは名前空間として管理されます。
チーム フォルダを使用している場合、チーム メンバーのホーム フォルダとチーム フォルダの間に親子関係はなく、両者は並列のフォルダとして扱われます。チーム フォルダへのアクセス権を付与されているメンバーの環境では、チーム フォルダはそのメンバーのホーム フォルダ以下にマウントされます。
共有フォルダとチーム フォルダ以下の名前空間は、メンバーが自由に名前を変更し、別の場所に移動することができます。このため、似たような名前の共有フォルダが複数ある場合、それらを自由に整理できます。しかし、それによってフォルダ構造が他のメンバーと違ってしまい、共同作業のときに混乱が生じる可能性があります。
チーム スペースにアップグレードすると、チームに属する名前空間はすべてチームのルート名前空間以下に移動します。ルート名前空間は特殊な名前空間で、ユーザー インターフェースには表示されません。
チーム スペースの場合、チーム メンバーのホーム フォルダには各メンバーの名前が付けられます。このため、個人用のファイルおよびフォルダと、チームによって共有されたファイルおよびフォルダを区別しやすくなります。また、メンバーがホーム フォルダ以下のフォルダを共有した場合でも、そのフォルダは引き続きチーム メンバー フォルダ以下の名前空間として管理されます。
チーム フォルダは、管理者のみが作成、管理できる特殊なフォルダです。チーム スペースにアップグレードすると、チーム フォルダはトップレベル フォルダと呼ばれる通常のフォルダになり、メンバーも自分自身で作成できるようになります(管理者だけが管理できるよう設定を変更することもできます)。
つまり管理者と、権限を付与されたすべてのメンバーが、通常のフォルダ操作と同じ方法でフォルダを作成し、ファイルを管理できるということです。権限を付与されていないフォルダは、制限付きフォルダとして表示されます。
チーム フォルダを使用している場合、管理者はそのフォルダをアーカイブ フォルダに指定して共有を停止することができます。一方、チーム スペースにアーカイブ機能はなく、この点では通常の共有フォルダと同じように扱われます。チーム フォルダからチーム スペースにアップグレードすると、既存のアーカイブ フォルダは、権限が設定されていない制限付きフォルダに変更されます。
チーム フォルダを使用しているチームとチーム スペースにアップグレードしたチームの違いをまとめると、以下のようになります。
チーム フォルダを使用しているチーム | チーム スペースを使用しているチーム |
---|---|
ホーム フォルダには、個人用フォルダ、共有フォルダ、チーム フォルダが混在する | 個人用フォルダは、チーム メンバー フォルダとは別のフォルダとして扱われる |
チーム フォルダ(管理者が管理可能) | トップレベル フォルダ(管理者または権限を付与されたすべてのチーム メンバーが管理可能) |
アーカイブされたチーム フォルダ | 権限が設定されていない制限付きフォルダ |
Dropbox API とチーム スペース
チーム フォルダを使用するチームとチーム スペースを使用するチームには、ここまで述べてきた違いのほか、ファイル アクセスに関する違いもあります。
ここでは、ファイル アクセスに関する違いと、Dropbox API を使用している場合のアップグレード方法について説明します。
アップグレードの際には、以下の 4 つの違いに対応する必要があります。
- スコープとチーム メンバー フォルダ
- 個人用フォルダをチーム メンバー フォルダに移行する際に生じるパスの変更
- チーム フォルダとトップレベル フォルダの違い(フォルダの作成、削除、名前変更などの操作)
- 追加の OAuth スコープ
ファイル アクセスのスコープ
Dropbox API は、アプリケーションがアクセスできるフォルダのスコープを暗黙的に設定します。スコープの設定は、アプリケーション登録時のアプリケーション タイプの指定と似ています。アプリケーション タイプとして「アプリ フォルダ」を選択した場合、ファイルへのアクセスは、ユーザーのアプリ フォルダ以下にあるアプリごとのフォルダに制限されます。一方、「Dropbox へのフル アクセス権」を選択した場合は、ユーザーのホーム名前空間へのファイル アクセスが認められます。
チーム フォルダを使用しているチームの場合、ホーム名前空間の下に個人用フォルダとチーム フォルダが混在するため、アクセス タイプが「Dropbox へのフル アクセス権」であるアプリケーションは両方のフォルダにアクセスできます。これに対し、チーム スペースを使用しているチームのアクセスは、ホーム名前空間以下の個人用フォルダに制限されます。トップレベル フォルダにアクセスするためには、スコープの変更が必要です。
スコープ外のファイルとフォルダへのアクセスは許可されず、それらは見つからないものとして扱われます。ファイルやフォルダを個別に識別するファイル ID を使用した場合も同様です。
図 1:チーム フォルダを使用しているチームのスコープ | 図 2:チーム スペースを使用しているチームのスコープ(デフォルト) | 図 3:チーム スペース(と Dropbox-API-Path-Root ヘッダー)を使用しているチームのスコープ |
- 図 1 は、チーム フォルダを使用しているチームのアプリケーションでアクセス可能な範囲を示しています。個人用フォルダとチーム フォルダが混在し、両フォルダがそのメンバーのルート名前空間に属しています。
- 図 2 は、チーム スペースを使用しているチームのアプリケーションがデフォルトでアクセス可能な範囲を示しています。スコープは、チーム メンバーのホーム フォルダ以下に制限されています。
- 図 3 は、チーム スペースを使用しつつ、
Dropbox-API-Path-Root
でチームのルート名前空間を指定しているチームのアプリケーションでアクセス可能な範囲を示しています。トップレベル フォルダと個人用フォルダの両方がアクセス可能になっています。
スコープを変更する手順は以下のとおりです。
- チームの
root_namespace_id
を取得します。 Dropbox-API-Path-Root
ヘッダーを使用して、ファイルへのアクセス時にルート名前空間を指定します。
チームの root_namespace_id
を取得する方法は以下のとおりです。 /users/get_current_account
のレスポンスから root_namespace_id
を取得します。
{
...
"root_info": {
".tag": "team",
"root_namespace_id": "2537566656",
"home_namespace_id": "2620045633",
"home_path": "/Wendy"
}
}
ルート名前空間の ID を取得するには、レスポンスの JSON データに含まれる root_info
の情報を使用します。
チーム スペースを使用するチームの場合、 root_namespace_id
はチームのルート名前空間を示し、 home_namespace_id
は対応するユーザーのホーム名前空間を示します。
チーム フォルダを使用するチームの場合、 root_namespace_id
と home_namespace_id
は同じです。チーム スペースに対応した後でトップレベル フォルダとチーム メンバー フォルダの両方にアクセスしたい場合は、 root_namespace_id
を参照することでいつでも必要なスコープを取得できます。
このため、アプリケーションのユーザーが、チーム フォルダを使用するチームのメンバーであるか、チーム スペースを使用するチームのメンバーであるかに関係なく、スコープを指定する方法も用意されています。
レスポンスの JSON データに含まれる root_info
データの概要を以下にまとめます。
チーム フォルダを使用しているチーム | チーム スペースを使用しているチーム | |
---|---|---|
.tag |
user |
team |
root_namespace_id |
チーム メンバーのホーム名前空間の名前空間 ID | チームのルート名前空間の名前空間 ID |
home_namespace_id |
チーム メンバーのホーム名前空間の名前空間 ID | チーム メンバーのホーム名前空間の名前空間 ID |
home_path |
レスポンスには記述されない | チームのルート名前空間から取得したホーム名前空間へのパス |
この結果得られる root_namespace_id
は、API リクエストの Dropbox-API-Path-Root
ヘッダーを使用して、以下のように指定できます。
curl -X POST https://api.dropboxapi.com/2/files/list_folder \
--header 'Authorization: Bearer <token>' \
--header 'Dropbox-API-Path-Root: {".tag": "root", "root": "2537566656"}' \
--header "Content-Type: application/json" \
--data '{"path":""}'
ファイル パス
スコープがチームのルート名前空間に変更された場合は、メンバーのホーム名前空間以下のファイルにアクセスする際にパスを変更する必要があります。
ホーム名前空間以下のファイルにアクセスする際は、前述のように /users/get_current_account
で取得した home_path
を使用してパスを指定します。
以下に示したのは、Dropbox Java SDK を使用して、ここまでに説明した内容を実行するコード例です。ホーム名前空間以下のファイルをトップレベル フォルダにコピーするプロセスは、以下のように実装できます。
public class TeamSpace {
private static final String ACCESS_TOKEN = "YOUR_TOKEN_HERE";
// エントリを処理(フォルダ名を出力)
private static void processEntry(Metadata metadata) {
if (metadata instanceof FolderMetadata) {
FolderMetadata folderMetadata = (FolderMetadata) metadata;
System.out.println(folderMetadata.getName());
}
}
public static void main(String[] args) throws Exception {
DbxRequestConfig config = DbxRequestConfig.newBuilder("team_space").build();
DbxClientV2 clientBase = new DbxClientV2(config, ACCESS_TOKEN);
// ルート名前空間の情報を取得
FullAccount currentAccount = clientBase.users().getCurrentAccount();
// Dropbox-API-Path-Root を持つクライアント
DbxClientV2 client = clientBase.withPathRoot(PathRoot.root(currentAccount.getRootInfo().getRootNamespaceId()));
// フォルダのリストを取得
ListFolderResult result = null;
result = client.files().listFolderBuilder("").start();
result.getEntries().stream().forEach(TeamSpace::processEntry);
while (result.getHasMore()) {
String cursor = result.getCursor();
result = client.files().listFolderContinue(cursor);
result.getEntries().stream().forEach(TeamSpace::processEntry);
}
}
}
トップレベル フォルダにアクセスする必要がない場合に、引き続きホーム フォルダのファイルにアクセスするには、Dropbox-API-Path-Root
ヘッダーを省略するだけです。
チーム フォルダ
前述したように、チーム フォルダは特殊なフォルダです。チーム フォルダは管理者のみが作成でき、作成には管理コンソールを使用します。
Dropbox API にも、team/team_folder
以下に特殊な API が用意されています。この API を実行するには管理者権限が必要です。
一方、チーム スペースのトップレベル フォルダは、通常の共有フォルダと同じように操作できます。すべてのメンバーがトップレベル フォルダの作成を許可されている場合は、sharing/share_folder
で共有フォルダを作成する場合と同じ方法でトップレベル フォルダを使用できます。違いは、前述のように、Dropbox-Path-API-Root
を指定する必要があることです。
メモ: |
---|
チーム スペース構成では team/team_folder 以下の API は一部の例外を除いて利用することができません。詳細はこちらをご参照ください(英語)。また、共有フォルダ数には上限があるケースがあります。このため、サブフォルダの作成に関しましては、 files/create_folder の利用もご検討ください。各種推奨値はこちらの記事をご参照ください。
|
トップレベル フォルダの管理が管理者だけに制限されている場合は、管理者として API を実行します。その際、Dropbox-API-Select-Admin
ヘッダーで管理者のチーム メンバー ID を指定します。
管理者のチーム メンバー ID は次の方法で取得できます。
/members/list
でメンバーのリストを取得し、チーム管理者を選択します。- 管理者のメール アドレスがわかっている場合は、
/members/get_info
を使用してチーム管理者の情報を取得します。 /token/get_authenticated_admin
を使用して、そのアプリケーションを許可した管理者の ID を取得します。該当の管理者がすでに管理者ではなくなっている場合、またはそのアカウントが削除されている場合は、権限が不十分だとしてエラーが返されます。
チーム フォルダを使用しているチームとチーム スペースを使用しているチームでは、使用する API が異なります。このため、現在のチームがチーム フォルダを使用しているチームかチーム スペースを使用しているチームかを判別する必要があります。
- チームがリンクしたアプリを使用している場合は、
/team/features/get_values
エンドポイントを使用して、has_team_shared_dropbox
のブール値を確認します。値が true の場合、そのチームはチーム スペース構成を使用しています。 - ユーザーがリンクしたアプリを使用している場合は、
/users/get_current_account
を呼び出し、返されるRootInfo
のタイプをチェックして、そのユーザーが、チーム スペース構成を使用しているチームのメンバーかどうかを確認します。チームがチーム スペース構成を使用していない場合、返されるroot_info
はUserRootInfo
(.tag
はuser
)となり、チームがチーム スペース構成を使用している場合は、TeamRootInfo(.tag は team)となります。 /team/team_folder/list
を呼び出すと、チームがチーム スペースを使用している場合に、is_team_root
のブール値がtrue
に設定されたチーム フォルダが 1 つ返されます。
これらの違いを踏まえて、チーム フォルダまたはトップレベル フォルダを作成するコードの例を以下に示します。
public class TeamFolderAndTopLevelFolder {
private static final String ACCESS_TOKEN = "YOUR_TOKEN_HERE";
private static void createTopLevelFolder(DbxTeamClientV2 client, String folderName) throws DbxException {
// 管理者ユーザーを確認
TokenGetAuthenticatedAdminResult tokenGetAuthenticatedAdminResult = client.team().tokenGetAuthenticatedAdmin();
String teamAdminMemberId = tokenGetAuthenticatedAdminResult.getAdminProfile().getTeamMemberId();
// クライアントを管理者として作成
DbxClientV2 clientAsAdmin = client.asAdmin(teamAdminMemberId);
// ルート名前空間の情報を取得
FullAccount currentAccount = clientAsAdmin.users().getCurrentAccount();
// Dropbox-API-Path-Root を持つクライアント
DbxClientV2 clientAsAdminWithRoot = clientAsAdmin.withPathRoot(PathRoot.root(currentAccount.getRootInfo().getRootNamespaceId()));
// フォルダを共有し、新しいトップレベル フォルダを作成
clientAsAdminWithRoot.sharing().shareFolder("/"
+ folderName);
}
private static void createTeamFolder(DbxTeamClientV2 client, String folderName) throws DbxException {
client.team().teamFolderCreate(folderName);
}
private static void createTopLevelOrTeamFolder(DbxTeamClientV2 client, String folderName) throws Exception {
// チームがチーム フォルダを使用しているかチーム スペースを使用しているかを確認
FeaturesGetValuesBatchResult hasTeamSharedDropbox = client.team().featuresGetValues(List.of(Feature.HAS_TEAM_SHARED_DROPBOX));
Optional<FeatureValue> hasTeamSharedDropboxVal = hasTeamSharedDropbox.getValues().stream().findFirst();
if (hasTeamSharedDropboxVal.isEmpty()) {
throw new Exception("No feature value");
} else if (hasTeamSharedDropboxVal.get().getHasTeamSharedDropboxValue().getHasTeamSharedDropboxValue()) {
// チームがチーム スペースを使用している場合はトップレベル フォルダを作成
createTopLevelFolder(client, folderName);
} else {
// チームがチーム フォルダを使用している場合はチーム フォルダを作成
createTeamFolder(client, folderName);
}
}
public static void main(String[] args) throws Exception {
DbxRequestConfig config = DbxRequestConfig.newBuilder("list").build();
DbxTeamClientV2 client = new DbxTeamClientV2(config, ACCESS_TOKEN);
createTopLevelOrTeamFolder(client, "Design Team");
}
}
OAuth スコープ
OAuth スコープを使用するアプリケーションを実装する場合は、ルート名前空間またはチームがチーム スペースを使用しているかどうかを確認する API 権限が追加で必要になります。
たとえば、以下の OAuth スコープが必要です。
/users/get_current_account
:account_info.read
/team/features/get_values
:team_info.read
/team/team_folder/list
:team_data.content.read
先ほど示したチーム フォルダを作成するコード例では、team/features/get_values
を使用しているため、team_info.read
スコープが必要です。既存のアプリケーションに必要な権限が付与されていない場合、メンバーまたは管理者が権限を付与し直す必要があります。
アプリケーションのテスト
インテグレーションを開発、テストできる Dropbox チームがない場合は、サポート ページの「よくある質問」にある「アプリケーションをテストするにはどうすればよいですか(How do I test my application?)」をご覧ください。