Skip to content

Commit

Permalink
feat: Add support for modifiable retention policies & enable deleting…
Browse files Browse the repository at this point in the history
… retention policy assignment (#420)
  • Loading branch information
arjankowski authored Nov 2, 2022
1 parent 32eac6c commit 26ab5b4
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 103 deletions.
193 changes: 100 additions & 93 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@oclif/plugin-help": "^2.2.1",
"@oclif/plugin-not-found": "^1.2.0",
"archiver": "^3.0.0",
"box-node-sdk": "^2.4.0",
"box-node-sdk": "^2.7.1",
"chalk": "^2.4.1",
"cli-progress": "^2.1.0",
"csv": "^3.1.0",
Expand Down
6 changes: 3 additions & 3 deletions src/box-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -900,21 +900,21 @@ class BoxCommand extends Command {
},
});

writeFunc = async (savePath) => {
writeFunc = async(savePath) => {
await pipeline(
stringifiedOutput,
appendNewLineTransform,
fs.createWriteStream(savePath, { encoding: 'utf8' })
);
};

logFunc = async () => {
logFunc = async() => {
await this.logStream(stringifiedOutput);
};
} else {
stringifiedOutput = await this._stringifyOutput(formattedOutputData);

writeFunc = async (savePath) => {
writeFunc = async(savePath) => {
await fs.writeFile(savePath, stringifiedOutput + os.EOL, {
encoding: 'utf8',
});
Expand Down
31 changes: 31 additions & 0 deletions src/commands/retention-policies/assignments/remove.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict';

const BoxCommand = require('../../../box-command');

class RetentionPoliciesRemoveAssignmentCommand extends BoxCommand {
async run() {
const { flags, args } = this.parse(RetentionPoliciesRemoveAssignmentCommand);

await this.client.retentionPolicies.deleteAssignment(args.id);
this.info(`Removed retention policy assignment ${args.id}`);
}
}

RetentionPoliciesRemoveAssignmentCommand.description = 'Remove a retention policy assignment applied to content';
RetentionPoliciesRemoveAssignmentCommand.examples = ['box retention-policies:assignments:remove 1235'];
RetentionPoliciesRemoveAssignmentCommand._endpoint = 'delete_retention_policy_assignments_id';

RetentionPoliciesRemoveAssignmentCommand.flags = {
...BoxCommand.flags
};

RetentionPoliciesRemoveAssignmentCommand.args = [
{
name: 'id',
required: true,
hidden: false,
description: 'ID of the retention policy assignment to remove',
}
];

module.exports = RetentionPoliciesRemoveAssignmentCommand;
37 changes: 35 additions & 2 deletions src/commands/retention-policies/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,25 @@ class RetentionPoliciesCreateCommand extends BoxCommand {
if (flags.hasOwnProperty('allow-extension')) {
options.can_owner_extend_retention = flags['allow-extension'];
}

if (flags['retention-length']) {
policyType = 'finite';
options.retention_length = flags['retention-length'];
}
if (flags['retention-type']) {
options.retention_type = flags['retention-type'];
} else if (flags.modifiable) {
options.retention_type = this.client.retentionPolicies.retentionTypes.MODIFIABLE;
} else if (flags['non-modifiable']) {
options.retention_type = this.client.retentionPolicies.retentionTypes.NON_MODIFIABLE;
}

let policy = await this.client.retentionPolicies.create(args.policyName, policyType, dispositionAction, options);
await this.output(policy);
}
}

RetentionPoliciesCreateCommand.description = 'Create a new retention policy';
RetentionPoliciesCreateCommand.examples = ['box retention-policies:create "Tax Documents" --retention-length 2555 --disposition-action permanently_delete'];
RetentionPoliciesCreateCommand.examples = ['box retention-policies:create "Tax Documents" --retention-length 2555 --retention-type "non_modifiable" --disposition-action permanently_delete'];
RetentionPoliciesCreateCommand._endpoint = 'post_retention_policies';

RetentionPoliciesCreateCommand.flags = {
Expand All @@ -46,6 +52,33 @@ RetentionPoliciesCreateCommand.flags = {
char: 'l',
description: 'The number of days to apply the retention policy. If not set, policy will be indefinite',
}),
'retention-type': flags.string({
description: 'The type of retention for the new policy',
exclusive: [
'modifiable',
'non-modifiable'
],
options: [
'modifiable',
'non_modifiable'
]
}),
modifiable: flags.boolean({
description: 'Set retention type to modifiable',
hidden: true,
exclusive: [
'retention-type',
'non-modifiable',
]
}),
'non-modifiable': flags.boolean({
description: 'Set retention type to non_modifiable',
hidden: true,
exclusive: [
'retention-type',
'modifiable',
]
}),
'disposition-action': flags.string({
required: true,
description: 'For indefinite policies, disposition action must be remove_retention',
Expand Down
6 changes: 6 additions & 0 deletions src/commands/retention-policies/update.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ class RetentionPoliciesUpdateCommand extends BoxCommand {
if (flags['retention-length']) {
updates.retention_length = parseInt(flags['retention-length'], 10);
}
if (flags['non-modifiable']) {
updates.retention_type = this.client.retentionPolicies.retentionTypes.NON_MODIFIABLE;
}
if (flags.retire) {
updates.status = 'retired';
}
Expand Down Expand Up @@ -61,6 +64,9 @@ RetentionPoliciesUpdateCommand.flags = {
char: 'l',
description: 'The amount of time, in days, to apply the retention policy. Required for finite policies'
}),
'non-modifiable': flags.boolean({
description: 'Set retention type to non_modifiable. '
}),
retire: flags.boolean({
char: 'r',
description: 'Retire a retention policy'
Expand Down
6 changes: 3 additions & 3 deletions test/commands/collaborations.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ describe('Collaborations', () => {
'--token=test'
])
.it('should send fields param and filter output when --fields flag is passed', ctx => {
let lb = "\n";
let lb = '\n';
assert.equal(ctx.stdout, `Type: collaboration${lb}ID: '1234567890'${lb}Status: accepted${lb}Role: editor${os.EOL}`);
});
});
Expand Down Expand Up @@ -211,7 +211,7 @@ describe('Collaborations', () => {
'--token=test'
])
.it('should send fields param and filter output when --fields flag is passed', ctx => {
let lb = "\n";
let lb = '\n';
assert.equal(ctx.stdout, `Type: collaboration${lb}ID: '1234567890'${lb}Status: accepted${lb}Role: viewer${os.EOL}`);
});

Expand Down Expand Up @@ -491,7 +491,7 @@ describe('Collaborations', () => {
'--token=test'
])
.it('should send fields param and filter output when --fields flag is passed', ctx => {
let lb = "\n";
let lb = '\n';
assert.equal(ctx.stdout, `Type: collaboration${lb}ID: '1234567890'${lb}Status: accepted${lb}Role: previewer${os.EOL}`);
});

Expand Down
2 changes: 1 addition & 1 deletion test/commands/request.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe('Manual Request', () => {
'--token=test'
])
.it('should make simple GET request when resource given as path (YAML Output)', ctx => {
let lb = "\n"
let lb = '\n';
let expectedOutput = `Status Code: 200${lb}Headers: {}${lb}Body: {}${os.EOL}`;

assert.equal(ctx.stdout, expectedOutput);
Expand Down
43 changes: 43 additions & 0 deletions test/commands/retention-policies.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ const { test } = require('@oclif/test');
const { assert } = require('chai');
const leche = require('leche');
const { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');
const os = require('os');

describe('Retention Policies', () => {

describe('retention-policies:create', () => {
let policyName = 'Financial Records',
retentionLength = 365,
dispositionAction = 'remove_retention',
retentionType = 'modifiable',
fixture = getFixture('retention-policies/post_retention_policies'),
yamlOutput = getFixture('output/retention_policies_create_yaml.txt');

Expand Down Expand Up @@ -88,6 +90,7 @@ describe('Retention Policies', () => {
...expectedBody,
policy_type: 'finite',
retention_length: retentionLength,
retention_type: retentionType,
are_owners_notified: true,
can_owner_extend_retention: true,
})
Expand All @@ -99,6 +102,7 @@ describe('Retention Policies', () => {
policyName,
`--disposition-action=${dispositionAction}`,
`--retention-length=${retentionLength}`,
`--retention-type=${retentionType}`,
'--notify-owners',
'--allow-extension',
'--json',
Expand All @@ -115,6 +119,7 @@ describe('Retention Policies', () => {
dispositionAction = 'permanently_delete',
policyType = 'finite',
retentionLength = 500,
retentionType = 'non_modifiable',
fixture = getFixture('retention-policies/put_retention_policies_id'),
yamlOutput = getFixture('output/retention_policies_update_yaml.txt');

Expand Down Expand Up @@ -181,6 +186,25 @@ describe('Retention Policies', () => {
.it('should update policy type, disposition, and length when appropriate flags are passed', ctx => {
assert.equal(ctx.stdout, fixture);
});

test
.nock(TEST_API_ROOT, api => api
.put(`/2.0/retention_policies/${policyId}`, {
retention_type: retentionType,
})
.reply(200, fixture)
)
.stdout()
.command([
'retention-policies:update',
policyId,
'--non-modifiable',
'--json',
'--token=test'
])
.it('should update retention type when appropriate flag is passed', ctx => {
assert.equal(ctx.stdout, fixture);
});
});

describe('retention-policies:get', () => {
Expand Down Expand Up @@ -351,6 +375,25 @@ describe('Retention Policies', () => {
.it('should send fields param to the API when --fields flag is passed');
});

describe('retention-policies:assignments:remove', () => {
let assignmentId = '123456';

test
.nock(TEST_API_ROOT, api => api
.delete(`/2.0/retention_policy_assignments/${assignmentId}`)
.reply(204)
)
.stderr()
.command([
'retention-policies:assignments:remove',
assignmentId,
'--token=test'
])
.it('should remove a retention policy assignment', ctx => {
assert.equal(ctx.stderr, `Removed retention policy assignment ${assignmentId}${os.EOL}`);
});
});

describe('retention-policies:assign', () => {
let policyId = '11111',
type = 'folder',
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/output/retention_policies_create_yaml.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ ID: '11111'
Policy Name: Financial Records
Policy Type: finite
Retention Length: '365'
Retention Type: modifiable
Disposition Action: remove_retention
Can Owner Extend Retention: false
Status: active
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/output/retention_policies_update_yaml.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ ID: '11111'
Policy Name: Retained Financial Records
Policy Type: finite
Retention Length: '365'
Retention Type: non_modifiable
Disposition Action: remove_retention
Can Owner Extend Retention: false
Status: active
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"policy_name": "Financial Records",
"policy_type": "finite",
"retention_length": "365",
"retention_type": "modifiable",
"disposition_action": "remove_retention",
"can_owner_extend_retention": false,
"status": "active",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"policy_name": "Retained Financial Records",
"policy_type": "finite",
"retention_length": "365",
"retention_type": "non_modifiable",
"disposition_action": "remove_retention",
"can_owner_extend_retention": false,
"status": "active",
Expand Down

0 comments on commit 26ab5b4

Please sign in to comment.