Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added support for file requests #742

Merged
merged 4 commits into from
Jul 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/box-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import Trash from './managers/trash';
import Users from './managers/users';
import WebLinks from './managers/web-links';
import Webhooks from './managers/webhooks';
import FileRequestsManager from "./managers/file-requests-manager";

// ------------------------------------------------------------------------------
// Typedefs and Callbacks
Expand Down Expand Up @@ -204,6 +205,7 @@ class BoxClient {

users: any;
files: Files;
fileRequests: FileRequestsManager;
folders: Folders;
comments: any;
collaborations: any;
Expand Down Expand Up @@ -276,6 +278,7 @@ class BoxClient {
// Attach API Resource Managers
this.users = new Users(this);
this.files = new Files(this);
this.fileRequests = new FileRequestsManager(this);
this.folders = new Folders(this);
this.comments = new Comments(this);
this.collaborations = new Collaborations(this);
Expand Down
102 changes: 102 additions & 0 deletions src/managers/file-requests-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import BoxClient from "../box-client";
import {FileRequest, FileRequestCopyBody, FileRequestUpdateBody} from "../schemas";
import urlPath from "../util/url-path";

class FileRequestsManager {
client: BoxClient;

constructor(client: BoxClient) {
// Attach the client, for making API calls
this.client = client;
}

/**
* Gets File Request by ID.
* @param {string} fileRequestId File Request ID
* @param {Function} [callback] passed the user info if it was acquired successfully
* @returns {Promise<FileRequest>} a promise with FileRequest details
*/
getById(fileRequestId: string, callback?: Function): Promise<FileRequest> {
const apiPath = urlPath('file_requests', fileRequestId);
return this.client.wrapWithDefaultHandler(this.client.get)(
apiPath,
callback
);
}

/**
* Delete File Request.
* @param {string} fileRequestId File Request ID
* @param {Function} [callback] passed the user info if it was acquired successfully
* @returns {Promise<void>} Returns a promise resolving to nothing
*/
delete(fileRequestId: string, callback?: Function): Promise<FileRequest> {
const apiPath = urlPath('file_requests', fileRequestId);
return this.client.wrapWithDefaultHandler(this.client.del)(
apiPath,
callback
);
}

/**
* Copies existing FileRequest to new folder
* @param {string} fileRequestIdToCopy ID of file request to copy
* @param copyRequest copy request details
* @param {string} copyRequest.folder.id ID of folder to which file request will be copied
* @param {string} copyRequest.folder.type type of folder. Value is always 'folder'
* @param {string} [copyRequest.title] new title of file request
* @param {string} [copyRequest.description] new description of file request
* @param {string} [copyRequest.expires_at] new date when file request expires
* @param {boolean} [copyRequest.is_description_required] is file request submitter required to provide a description
* of the files they are submitting
* @param {boolean} [copyRequest.is_email_required] is file request submitter required to provide their email address
* @param {string} [copyRequest.status] new status of file request
* @param {Function} [callback] passed the user info if it was acquired successfully
* @returns {Promise<FileRequest>} Returns a promise with FileRequest details
*/
copy(fileRequestIdToCopy: string, copyRequest: FileRequestCopyBody, callback?: Function): Promise<FileRequest> {
const apiPath = urlPath('file_requests', fileRequestIdToCopy, 'copy');
return this.client.wrapWithDefaultHandler(this.client.post)(
apiPath,
{body: copyRequest},
callback
);
}

/**
* Update existing file request
* @param {string} fileRequestId ID of file request
* @param {string} fileRequestChange change of file request
* @param {string} [fileRequestChange.description] new description of file request
* @param {string} [fileRequestChange.expires_at] new date when file request expires
* @param {boolean} [fileRequestChange.is_description_required] is file request submitter required to provide a
* description of the files they are submitting
* @param {boolean} [fileRequestChange.is_email_required] is file request submitter required to provide their
* email address
* @param {string} [fileRequestChange.status] new status of file request
* @param {string} [fileRequestChange.title] new title of file request
* @param {string} [originalRequestEtag] pass in the item's last observed etag value into this header and
* the endpoint will fail with a 412 Precondition Failed if it has changed since.
* @param {Function} callback passed the user info if it was acquired successfully
* @returns {Promise<FileRequest>} Returns a promise with FileRequest details
*/
update(
fileRequestId: string,
fileRequestChange: FileRequestUpdateBody,
originalRequestEtag?: string,
callback?: Function
): Promise<FileRequest> {
const apiPath = urlPath('file_requests', fileRequestId);
let params: any = {body: fileRequestChange};
if(originalRequestEtag) {
params = {...params, headers: {"if-match": originalRequestEtag}};
}
return this.client.wrapWithDefaultHandler(this.client.put)(
apiPath,
params,
callback
);
}
}

export = FileRequestsManager;
44 changes: 44 additions & 0 deletions src/schemas/file-request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {FolderMini} from "./folder-mini.generated";
import {UserMini} from "./user-mini";

type FileRequestStatus = 'active' | 'inactive';

export interface FileRequest {
id: string;
type: 'file_request';
title: string;
description: string;
etag: string;
is_email_required: boolean;
is_description_required: boolean;
expires_at?: string;
url: string;
created_at: string;
created_by: UserMini;
updated_at?: string;
updated_by?: UserMini;
status: FileRequestStatus;
folder: FolderMini;
}

export interface FileRequestCopyBody {
folder: {
id: string;
type: 'folder';
};
title?: string;
description?: string;
expires_at?: string;
is_description_required?: boolean;
is_email_required?: boolean;
status?: FileRequestStatus;
}

export interface FileRequestUpdateBody {
description?: string;
expires_at?: string;
is_description_required?: boolean;
is_email_required?: boolean;
status?: FileRequestStatus;
title?: string;
}
2 changes: 2 additions & 0 deletions src/schemas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ export * from './sign-request-signer-input.generated';
export * from './sign-request-signer.generated';
export * from './sign-request.generated';
export * from './sign-requests.generated';
export * from './file-request';
export * from './user-mini';
6 changes: 6 additions & 0 deletions src/schemas/user-mini.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface UserMini {
id: string;
type: string;
login: string;
name: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"folder": {
"id": "157979815641",
"type": "folder",
"name": "Folder with reqes",
"etag": "0",
"sequence_id": "0"
},
"created_by": {
"id": "18188499134",
"type": "user",
"name": "Test",
"login": "[email protected]"
},
"id": "2484517969",
"type": "file_request",
"title": "Submit files",
"description": "",
"etag": "1656573853000",
"is_email_required": true,
"is_description_required": false,
"expires_at": "2022-07-30T15:00:00-07:00",
"url": "/f/5131693291084d9f9f39954e56172513",
"created_at": "2022-06-30T00:22:59-07:00",
"updated_at": "2022-06-30T00:24:13-07:00",
"status": "active"
}
128 changes: 128 additions & 0 deletions tests/lib/managers/file-requests-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/**
* @fileoverview FileRequests Manager Tests
*/
'use strict';
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const sinon = require('sinon');
const mockery = require('mockery');
const leche = require('leche');
const BoxClient = require('../../../lib/box-client');
const Promise = require('bluebird');
const fs = require('fs');
const path = require('path');
const assert = require('chai').assert;
// ------------------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------------------
let sandbox = sinon.createSandbox(),
boxClientFake = leche.fake(BoxClient.prototype),
FileRequestsManager,
fileRequests,
BASE_PATH = '/file_requests',
MODULE_FILE_PATH = '../../../lib/managers/file-requests-manager';

/**
* Loads JSON fixture file
* @param {string} fixture tath to fixture file without '.json'
* @returns {Object} JSON with content from fixture
*/
function getFixture(fixture) {
// eslint-disable-next-line no-sync
return JSON.parse(fs.readFileSync(
path.resolve(__dirname, `../../fixtures/endpoints/${fixture}.json`)
));
}

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------
describe('FileRequests', () => {
const fileRequestId = '234567';
before(() => {
// Enable Mockery
mockery.enable({
useCleanCache: true,
});
// Register Mocks
mockery.registerAllowable('../util/url-path');
mockery.registerAllowable(MODULE_FILE_PATH);
});
beforeEach(() => {
// Setup File Under Test
// eslint-disable-next-line global-require
FileRequestsManager = require(MODULE_FILE_PATH);
fileRequests = new FileRequestsManager(boxClientFake);
});
afterEach(() => {
sandbox.verifyAndRestore();
mockery.resetCache();
});
after(() => {
mockery.deregisterAll();
mockery.disable();
});
it('get by id', async() => {
const fixture = getFixture('file-requests/get_file_requests_id_200');
sandbox.stub(boxClientFake, 'wrapWithDefaultHandler').returnsArg(0);
sandbox
.mock(boxClientFake)
.expects('get')
.withArgs(`${BASE_PATH}/${fileRequestId}`)
.returns(Promise.resolve(fixture));
const response = await fileRequests.getById(fileRequestId);
assert.strictEqual(response, fixture);
});
it('delete', async() => {
sandbox.stub(boxClientFake, 'wrapWithDefaultHandler').returnsArg(0);
sandbox
.mock(boxClientFake)
.expects('del')
.withArgs(`${BASE_PATH}/${fileRequestId}`);
await fileRequests.delete(fileRequestId);
});
it('copy existing file request', async() => {
const fixture = getFixture('file-requests/get_file_requests_id_200');
sandbox.stub(boxClientFake, 'wrapWithDefaultHandler').returnsArg(0);
sandbox
.mock(boxClientFake)
.expects('post')
.withArgs(`${BASE_PATH}/${fileRequestId}/copy`)
.returns(Promise.resolve(fixture));
const response = await fileRequests.copy(fileRequestId, {folder: {id: '1234', type: 'folder'}});
assert.strictEqual(response, fixture);
});
it('update existing file request', async() => {
const fixture = getFixture('file-requests/get_file_requests_id_200');
sandbox.stub(boxClientFake, 'wrapWithDefaultHandler').returnsArg(0);
const updateRequest = {
title: 'Updated title'
};
sandbox
.mock(boxClientFake)
.expects('put')
.withArgs(`${BASE_PATH}/${fileRequestId}`, {body: updateRequest})
.returns(Promise.resolve(fixture));
const response = await fileRequests.update(fileRequestId, updateRequest);
assert.strictEqual(response, fixture);
});
it('update existing file request with version checking', async() => {
const fixture = getFixture('file-requests/get_file_requests_id_200');
sandbox.stub(boxClientFake, 'wrapWithDefaultHandler').returnsArg(0);
const updateRequest = {
title: 'Updated title'
};
const etag = '2345678765432';
sandbox
.mock(boxClientFake)
.expects('put')
.withArgs(`${BASE_PATH}/${fileRequestId}`, {
body: updateRequest,
headers: {'if-match': etag}
})
.returns(Promise.resolve(fixture));
const response = await fileRequests.update(fileRequestId, updateRequest, etag);
assert.strictEqual(response, fixture);
});
});