Create Architecture Skeleton
Create Architecture Skeleton
Our first requirement is to copy general files and folders into each individual
user's root folder on account creation. This problem has been solved within
standard Linux distributions through a directory called /etc/skel
,
which we'll emulate with a Box specific solution here. When adding a new user in
Linux, the files and folders within /etc/skel
are copied to the new user's
home directory.
When creating a JWT-based Box application, a Service Account is created within the Box Enterprise. A Service Account is similar in functionality to a co-admin within a Box Enterprise, and most useful to this use case, can own, copy, and collaborate other users on files and folders. More importantly, you don't have to use a Service Account strictly for developing custom applications for users, and instead, can use a Service Account in more of an automation capacity.
We'll start by creating the etc
and skel
folders and granting ownership of
the folders to the Service Account.
{
"name": "etc",
"parent": {
"id": "0"
},
"children": [
{
"name": "skel",
"children": []
}
]
}
The code here can optionally be reused to build any folder structure formatted as the JSON objects above demonstrate.
"use strict";
const fs = require("fs");
const box = require("box-node-sdk");
class BoxFolderTreeCreator {
constructor(boxClient, options) {
options = options || {};
if (options.boxClient) {
throw new Error("Must include a boxClient field.");
}
options.boxFolderTreeName = options.boxFolderTreeName || "tree.json";
this.boxClient = boxClient;
this.boxFolderTree = JSON.parse(fs.readFileSync(options.boxFolderTreeName));
this.createdBoxFolders = [];
}
async createFolderTree(branch = null, parentFolderId = "0") {
this.createdBoxFolders = [];
if (Array.isArray(this.boxFolderTree)) {
let folderTasks = [];
this.boxFolderTree.forEach(folder => {
folderTasks.push(this._createFolder(folder, ""));
});
await Promise.all(folderTasks);
return this.createdBoxFolders;
} else if (typeof this.boxFolderTree === "object") {
console.log("Is object");
await this._createFolders(this.boxFolderTree, "");
return this.createdBoxFolders;
} else {
throw new Error("Incorrectly formatted JSON folder tree.");
}
}
async _createFolders(branch, parentFolderId = "0") {
if (branch.parent != null && branch.parent.id != null) {
parentFolderId = branch.parent.id;
}
let folder;
try {
folder = await this.boxClient.folders.create(parentFolderId, branch.name);
} catch (e) {
let existingFolderId = BoxFolderTreeCreator.handleFolderConflictError(e);
folder = await this.boxClient.folders.get(existingFolderId);
}
this.createdBoxFolders.push(folder);
if (branch.children.length <= 0) {
console.log("No more folders to create...");
return;
} else {
let createFolderTasks = [];
branch.children.forEach(child => {
console.log("Creating folder...");
console.log(child.name);
createFolderTasks.push(this._createFolders(child, folder.id));
});
return await Promise.all(createFolderTasks);
}
}
static handleFolderConflictError(e) {
if (e && e.response && e.response.body) {
let errorBody = e.response.body;
if (errorBody.status === 409) {
if (
errorBody.context_info &&
errorBody.context_info.conflicts &&
errorBody.context_info.conflicts.length > 0
) {
let conflict = errorBody.context_info.conflicts[0];
if (conflict && conflict.id) {
return conflict.id;
}
}
}
}
}
}
let configFile = fs.readFileSync("config.json");
configFile = JSON.parse(configFile);
let session = box.getPreconfiguredInstance(configFile);
let serviceAccountClient = session.getAppAuthClient("enterprise");
let treeCreator = new BoxFolderTreeCreator(serviceAccountClient);
(async () => {
let createdFolders = await treeCreator.createFolderTree();
console.log(createdFolders);
})();