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: Add support for modifiable retention policies & enable deleting retention policy assignment #420

Merged
merged 1 commit into from
Nov 2, 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
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'
]
Comment on lines +61 to +64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate a bit on the reason for including the option to set modifiable as string? I thought this was done to allow new values without changing the code in the future (as it cannot be done with boolean flags), but I see that we are still limiting the possible options.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this to be compatible with update method, when we can only update type to 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