Compare commits
2 Commits
developmen
...
ft/arsenal
Author | SHA1 | Date |
---|---|---|
Dora Korpar | 77836d57c5 | |
Dora Korpar | e5fe2d2b7f |
|
@ -220,6 +220,10 @@
|
|||
"code": 400,
|
||||
"description": "Request body is empty"
|
||||
},
|
||||
"MissingRequiredParameter": {
|
||||
"code": 400,
|
||||
"description": "Your request is missing a required parameter."
|
||||
},
|
||||
"MissingSecurityElement": {
|
||||
"code": 400,
|
||||
"description": "The SOAP 1.1 request is missing a security element."
|
||||
|
|
|
@ -127,8 +127,8 @@ class LifecycleConfiguration {
|
|||
const rulesArray = lifecycleConf.Rule;
|
||||
if (!rulesArray || !Array.isArray(rulesArray)
|
||||
|| rulesArray.length === 0) {
|
||||
rules.error = errors.MalformedXML.customizeDescription(
|
||||
'request xml does not include at least one rule');
|
||||
rules.error = errors.MissingRequiredParameter.customizeDescription(
|
||||
'missing required key \'Rules\' in LifecycleConfiguration');
|
||||
return rules;
|
||||
}
|
||||
if (rulesArray.length > 1000) {
|
||||
|
@ -197,8 +197,8 @@ class LifecycleConfiguration {
|
|||
return ruleObj;
|
||||
}
|
||||
if (!rule.Status) {
|
||||
ruleObj.error = errors.MalformedXML.customizeDescription(
|
||||
'Rule xml does not include Status');
|
||||
ruleObj.error = errors.MissingRequiredParameter.
|
||||
customizeDescription('Rule xml does not include Status');
|
||||
return ruleObj;
|
||||
}
|
||||
const subFilter = rule.Filter ? rule.Filter[0] : rule.Prefix;
|
||||
|
@ -254,12 +254,8 @@ class LifecycleConfiguration {
|
|||
filterObj.rulePrefix = '';
|
||||
if (Array.isArray(filter)) {
|
||||
// if Prefix was included, not Filter, filter will be Prefix array
|
||||
if (filter.length > 1) {
|
||||
filterObj.error = errors.MalformedXML.customizeDescription(
|
||||
'Rule includes more than one Prefix');
|
||||
return filterObj;
|
||||
}
|
||||
filterObj.rulePrefix = filter[0];
|
||||
// if more than one Prefix is included, we ignore all but the last
|
||||
filterObj.rulePrefix = filter.pop();
|
||||
return filterObj;
|
||||
}
|
||||
if (filter.And && (filter.Prefix || filter.Tag) ||
|
||||
|
@ -269,12 +265,7 @@ class LifecycleConfiguration {
|
|||
return filterObj;
|
||||
}
|
||||
if (filter.Prefix) {
|
||||
if (filter.Prefix.length > 1) {
|
||||
filterObj.error = errors.MalformedXML.customizeDescription(
|
||||
'Filter includes more than one Prefix');
|
||||
return filterObj;
|
||||
}
|
||||
filterObj.rulePrefix = filter.Prefix[0];
|
||||
filterObj.rulePrefix = filter.Prefix.pop();
|
||||
return filterObj;
|
||||
}
|
||||
if (filter.Tag) {
|
||||
|
@ -288,22 +279,19 @@ class LifecycleConfiguration {
|
|||
}
|
||||
if (filter.And) {
|
||||
const andF = filter.And[0];
|
||||
if (!andF.Tag || (!andF.Prefix && andF.Tag.length < 2)) {
|
||||
if (!andF.Tags || (!andF.Prefix && andF.Tags.length < 2)) {
|
||||
filterObj.error = errors.MalformedXML.customizeDescription(
|
||||
'And should include Prefix and Tag or more than one Tag');
|
||||
'And should include Prefix and Tags or more than one Tag');
|
||||
return filterObj;
|
||||
}
|
||||
if (andF.Prefix && andF.Prefix.length > 1) {
|
||||
filterObj.error = errors.MalformedXML.customizeDescription(
|
||||
'And includes more than one Prefix');
|
||||
return filterObj;
|
||||
if (andF.Prefix && andF.Prefix.length >= 1) {
|
||||
filterObj.rulePrefix = andF.Prefix.pop();
|
||||
}
|
||||
const tagObj = this._parseTags(andF.Tag[0]);
|
||||
const tagObj = this._parseTags(andF.Tags[0]);
|
||||
if (tagObj.error) {
|
||||
filterObj.error = tagObj.error;
|
||||
return filterObj;
|
||||
}
|
||||
filterObj.rulePrefix = andF.Prefix ? andF.Prefix[0] : null;
|
||||
filterObj.tags = tagObj.tags;
|
||||
return filterObj;
|
||||
}
|
||||
|
@ -329,8 +317,11 @@ class LifecycleConfiguration {
|
|||
_parseTags(tags) {
|
||||
const tagObj = {};
|
||||
tagObj.tags = [];
|
||||
// reset _tagKeys to empty because keys cannot overlap within a rule,
|
||||
// but different rules can have the same tag keys
|
||||
this._tagKeys = [];
|
||||
if (!tags.Key || !tags.Value) {
|
||||
tagObj.error = errors.MalformedXML.customizeDescription(
|
||||
tagObj.error = errors.MissingRequiredParameter.customizeDescription(
|
||||
'Tag XML does not contain both Key and Value');
|
||||
return tagObj;
|
||||
}
|
||||
|
@ -414,7 +405,7 @@ class LifecycleConfiguration {
|
|||
_parseStatus(status) {
|
||||
const statusObj = {};
|
||||
statusObj.propName = 'ruleStatus';
|
||||
const validStatuses = ['Enabled', 'Suspended'];
|
||||
const validStatuses = ['Enabled', 'Disabled'];
|
||||
if (!validStatuses.includes(status)) {
|
||||
statusObj.error = errors.MalformedXML.customizeDescription(
|
||||
'Status is not valid');
|
||||
|
@ -456,7 +447,7 @@ class LifecycleConfiguration {
|
|||
}
|
||||
});
|
||||
if (actionsObj.actions.length === 0) {
|
||||
actionsObj.error = errors.MalformedXML.customizeDescription(
|
||||
actionsObj.error = errors.InvalidRequest.customizeDescription(
|
||||
'Rule does not include valid action');
|
||||
return actionsObj;
|
||||
}
|
||||
|
@ -501,7 +492,7 @@ class LifecycleConfiguration {
|
|||
}
|
||||
}
|
||||
if (filter && filter.Tag) {
|
||||
abortObj.error = errors.MalformedXML.customizeDescription(
|
||||
abortObj.error = errors.InvalidRequest.customizeDescription(
|
||||
'Tag-based filter cannot be used with ' +
|
||||
'AbortIncompleteMultipartUpload action');
|
||||
return abortObj;
|
||||
|
@ -515,7 +506,7 @@ class LifecycleConfiguration {
|
|||
}
|
||||
const daysInt = parseInt(subAbort.DaysAfterInitiation[0], 10);
|
||||
if (daysInt < 1) {
|
||||
abortObj.error = errors.MalformedXML.customizeDescription(
|
||||
abortObj.error = errors.InvalidArgument.customizeDescription(
|
||||
'DaysAfterInitiation is not a positive integer');
|
||||
return abortObj;
|
||||
}
|
||||
|
@ -540,19 +531,25 @@ class LifecycleConfiguration {
|
|||
_parseExpiration(rule) {
|
||||
const expObj = {};
|
||||
const subExp = rule.Expiration[0];
|
||||
if (!subExp.Date && !subExp.Days && !subExp.ExpiredObjDeleteMarker) {
|
||||
if (!subExp.Date && !subExp.Days && !subExp.ExpiredObjectDeleteMarker) {
|
||||
expObj.error = errors.MalformedXML.customizeDescription(
|
||||
'Expiration action does not include an action time');
|
||||
return expObj;
|
||||
}
|
||||
const eodm = 'ExpiredObjectDeleteMarker';
|
||||
if (subExp.Date && (subExp.Days || subExp[eodm]) ||
|
||||
(subExp.Days && subExp[eodm])) {
|
||||
expObj.error = errors.MalformedXML.customizeDescription(
|
||||
'Expiration action includes more than one time');
|
||||
return expObj;
|
||||
}
|
||||
if (subExp.Date) {
|
||||
const isoRegex = new RegExp('^(-?(?:[1-9][0-9]*)?[0-9]{4})-' +
|
||||
'(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])T(2[0-3]|[0-1]' +
|
||||
'[0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]' +
|
||||
'|[0-1][0-9]):[0-5][0-9])?$');
|
||||
'(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9])' +
|
||||
':([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$');
|
||||
if (!isoRegex.test(subExp.Date[0])) {
|
||||
expObj.error = errors.MalformedXML.customizeDescription(
|
||||
'Date is not in proper ISO 8601 format');
|
||||
expObj.error = errors.InvalidArgument.customizeDescription(
|
||||
'Date must be in ISO 8601 format');
|
||||
} else {
|
||||
expObj.date = subExp.Date[0];
|
||||
}
|
||||
|
@ -560,19 +557,33 @@ class LifecycleConfiguration {
|
|||
if (subExp.Days) {
|
||||
const daysInt = parseInt(subExp.Days[0], 10);
|
||||
if (daysInt < 1) {
|
||||
expObj.error = errors.MalformedXML.customizeDescription(
|
||||
expObj.error = errors.InvalidArgument.customizeDescription(
|
||||
'Expiration days is not a positive integer');
|
||||
} else {
|
||||
expObj.days = daysInt;
|
||||
}
|
||||
}
|
||||
if (subExp.ExpiredObjDeleteMarker) {
|
||||
if (subExp.ExpiredObjectDeleteMarker) {
|
||||
let filter = null;
|
||||
if (rule.Filter && rule.Filter[0]) {
|
||||
if (rule.Filter[0].And) {
|
||||
filter = rule.Filter[0].And[0];
|
||||
} else {
|
||||
filter = rule.Filter[0];
|
||||
}
|
||||
}
|
||||
if (filter && filter.Tag) {
|
||||
expObj.error = errors.InvalidRequest.customizeDescription(
|
||||
'Tag-based filter cannot be used with ' +
|
||||
'ExpiredObjectDeleteMarker action');
|
||||
return expObj;
|
||||
}
|
||||
const validValues = ['true', 'false'];
|
||||
if (!validValues.includes(subExp.ExpiredObjDeleteMarker[0])) {
|
||||
if (!validValues.includes(subExp.ExpiredObjectDeleteMarker[0])) {
|
||||
expObj.error = errors.MalformedXML.customizeDescription(
|
||||
'ExpiredObjDeleteMarker is not true or false');
|
||||
} else {
|
||||
expObj.deleteMarker = subExp.ExpiredObjDeleteMarker[0];
|
||||
expObj.deleteMarker = subExp.ExpiredObjectDeleteMarker[0];
|
||||
}
|
||||
}
|
||||
return expObj;
|
||||
|
@ -601,7 +612,7 @@ class LifecycleConfiguration {
|
|||
}
|
||||
const daysInt = parseInt(subNVExp.NoncurrentDays[0], 10);
|
||||
if (daysInt < 1) {
|
||||
nvExpObj.error = errors.MalformedXML.customizeDescription(
|
||||
nvExpObj.error = errors.InvalidArgument.customizeDescription(
|
||||
'NoncurrentDays is not a positive integer');
|
||||
} else {
|
||||
nvExpObj.days = daysInt;
|
||||
|
@ -666,12 +677,20 @@ class LifecycleConfiguration {
|
|||
const Prefix = rulePrefix ? `<Prefix>${rulePrefix}</Prefix>` : '';
|
||||
let tagXML = '';
|
||||
if (tags) {
|
||||
tagXML = tags.map(t => {
|
||||
if (Prefix || tags.length > 1) {
|
||||
const keysVals = tags.map(t => {
|
||||
const { key, val } = t;
|
||||
const Tag = `<Tag><Key>${key}</Key>` +
|
||||
`<Value>${val}</Value></Tag>`;
|
||||
const Tag = `<Key>${key}</Key>` +
|
||||
`<Value>${val}</Value>`;
|
||||
return Tag;
|
||||
}).join('');
|
||||
tagXML = `<Tags>${keysVals}</Tags>`;
|
||||
} else {
|
||||
// only one tag included
|
||||
const { key, val } = tags[0];
|
||||
tagXML = `<Tag><Key>${key}</Key>` +
|
||||
`<Value>${val}</Value></Tag>`;
|
||||
}
|
||||
}
|
||||
let Filter;
|
||||
if (rulePrefix && !tags) {
|
||||
|
@ -686,7 +705,7 @@ class LifecycleConfiguration {
|
|||
const Actions = actions.map(action => {
|
||||
const { actionName, days, date, deleteMarker } = action;
|
||||
let Action;
|
||||
if (actionName === 'AbortIncompleteMultipartUploads') {
|
||||
if (actionName === 'AbortIncompleteMultipartUpload') {
|
||||
Action = `<${actionName}><DaysAfterInitiation>${days}` +
|
||||
`</DaysAfterInitiation></${actionName}>`;
|
||||
} else if (actionName === 'NoncurrentVersionExpiration') {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"engines": {
|
||||
"node": "6.9.5"
|
||||
},
|
||||
"version": "7.4.0",
|
||||
"version": "7.4.0-foo",
|
||||
"description": "Common utilities for the S3 project components",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
|
|
|
@ -4,6 +4,15 @@ const { parseString } = require('xml2js');
|
|||
const LifecycleConfiguration =
|
||||
require('../../../lib/models/LifecycleConfiguration.js');
|
||||
|
||||
const days = {
|
||||
AbortIncompleteMultipartUpload: 'DaysAfterInitiation',
|
||||
NoncurrentVersionExpiration: 'NoncurrentDays',
|
||||
Expiration: 'Days',
|
||||
};
|
||||
|
||||
const date = new Date();
|
||||
date.setUTCHours(0, 0, 0, 0);
|
||||
|
||||
/**
|
||||
* Format of xml request:
|
||||
<LifecycleConfiguration>
|
||||
|
@ -37,32 +46,17 @@ const LifecycleConfiguration =
|
|||
*/
|
||||
|
||||
const requiredTags = [
|
||||
{ tag: 'LifecycleConfiguration',
|
||||
{ tag: 'LifecycleConfiguration', error: 'MalformedXML',
|
||||
errMessage: 'request xml is undefined or empty' },
|
||||
{ tag: 'Rule',
|
||||
errMessage: 'request xml does not include at least one rule' },
|
||||
{ tag: 'Status', errMessage: 'Rule xml does not include Status' },
|
||||
{ tag: 'Filter', errMessage: 'Rule xml does not include valid Filter ' +
|
||||
'or Prefix' },
|
||||
{ tag: 'Action', errMessage: 'Rule does not include valid action' }];
|
||||
|
||||
const validActions = [
|
||||
{ tag: 'Expiration',
|
||||
errMessage: 'Expiration action does not include an action time' },
|
||||
{ tag: 'NoncurrentVersionExpiration',
|
||||
errMessage: 'NoncurrentVersionExpiration action does not include ' +
|
||||
'NoncurrentDays' },
|
||||
{ tag: 'AbortIncompleteMultipartUpload',
|
||||
errMessage: 'AbortIncompleteMultipartUpload action does not ' +
|
||||
'include DaysAfterInitiation' }];
|
||||
|
||||
const invalidActions = [
|
||||
{ tag: 'foo', errMessage: 'Rule does not include valid action' },
|
||||
{ tag: 'invalid-days-value',
|
||||
errMessage: 'Expiration days is not a positive integer' },
|
||||
{ tag: 'abortMPU-tag',
|
||||
errMessage: 'Tag-based filter cannot be used with ' +
|
||||
'AbortIncompleteMultipartUpload action' }];
|
||||
{ tag: 'Rule', error: 'MissingRequiredParameter',
|
||||
errMessage: 'missing required key \'Rules\' in ' +
|
||||
'LifecycleConfiguration' },
|
||||
{ tag: 'Status', error: 'MissingRequiredParameter',
|
||||
errMessage: 'Rule xml does not include Status' },
|
||||
{ tag: 'Filter', error: 'MalformedXML',
|
||||
errMessage: 'Rule xml does not include valid Filter or Prefix' },
|
||||
{ tag: 'Action', error: 'InvalidRequest',
|
||||
errMessage: 'Rule does not include valid action' }];
|
||||
|
||||
const notImplementedActions = [
|
||||
{ tag: 'Transition',
|
||||
|
@ -70,100 +64,175 @@ const notImplementedActions = [
|
|||
{ tag: 'NoncurrentVersionTransition',
|
||||
errMessage: 'Transition lifecycle action not yet implemented' }];
|
||||
|
||||
const invalidFilters = [
|
||||
{ tag: 'two-prefixes',
|
||||
errMessage: 'Filter includes more than one Prefix' },
|
||||
{ tag: 'invalid-tag',
|
||||
errMessage: 'Tag XML does not contain both Key and Value' }];
|
||||
const invalidActions = [
|
||||
{ tag: 'AbortIncompleteMultipartUpload', label: 'no-time',
|
||||
error: 'MalformedXML',
|
||||
errMessage: 'AbortIncompleteMultipartUpload action does not ' +
|
||||
'include DaysAfterInitiation' },
|
||||
{ tag: 'AbortIncompleteMultipartUpload', label: 'no-tags',
|
||||
error: 'InvalidRequest', errMessage: 'Tag-based filter cannot be ' +
|
||||
'used with AbortIncompleteMultipartUpload action' },
|
||||
{ tag: 'AbortIncompleteMultipartUpload', label: 'invalid-days',
|
||||
error: 'InvalidArgument',
|
||||
errMessage: 'DaysAfterInitiation is not a positive integer' },
|
||||
{ tag: 'Expiration', label: 'no-time', error: 'MalformedXML',
|
||||
errMessage: 'Expiration action does not include an action time' },
|
||||
{ tag: 'Expiration', label: 'mult-times', error: 'MalformedXML',
|
||||
errMessage: 'Expiration action includes more than one time' },
|
||||
{ tag: 'Expiration', label: 'non-iso', error: 'InvalidArgument',
|
||||
errMessage: 'Date must be in ISO 8601 format' },
|
||||
{ tag: 'Expiration', label: 'invalid-days', error: 'InvalidArgument',
|
||||
errMessage: 'Expiration days is not a positive integer' },
|
||||
{ tag: 'Expiration', label: 'no-tags', inTag: 'ExpiredObjectDeleteMarker',
|
||||
error: 'InvalidRequest',
|
||||
errMessage: 'Tag-based filter cannot be used with ' +
|
||||
'ExpiredObjectDeleteMarker action' },
|
||||
{ tag: 'Expiration', label: 'invalid-eodm', error: 'MalformedXML',
|
||||
errMessage: 'ExpiredObjDeleteMarker is not true or false' },
|
||||
{ tag: 'NoncurrentVersionExpiration', label: 'no-time',
|
||||
error: 'MalformedXML',
|
||||
errMessage: 'NoncurrentVersionExpiration action does not include ' +
|
||||
'NoncurrentDays' },
|
||||
{ tag: 'NoncurrentVersionExpiration', label: 'invalid-days',
|
||||
error: 'InvalidArgument',
|
||||
errMessage: 'NoncurrentDays is not a positive integer' }];
|
||||
|
||||
const invalidRequests = [
|
||||
{ tag: 'not-unique-id',
|
||||
errMessage: 'Rule ID must be unique' },
|
||||
{ tag: 'key-too-long',
|
||||
const invalidFilters = [
|
||||
{ tag: 'Filter', label: 'also-prefix', error: 'MalformedXML',
|
||||
errMessage: 'Rule xml should not include both Filter and Prefix' },
|
||||
{ tag: 'Filter', label: 'and-prefix-tag', error: 'MalformedXML',
|
||||
errMessage: 'Filter should only include one of And, Prefix, or ' +
|
||||
'Tag key' },
|
||||
{ tag: 'And', label: 'only-prefix', error: 'MalformedXML',
|
||||
errMessage: 'And should include Prefix and Tags or more than one Tag' },
|
||||
{ tag: 'And', label: 'single-tag', error: 'MalformedXML',
|
||||
errMessage: 'And should include Prefix and Tags or more than one Tag' },
|
||||
{ tag: 'Tag', label: 'no-key', error: 'MissingRequiredParameter',
|
||||
errMessage: 'Tag XML does not contain both Key and Value' },
|
||||
{ tag: 'Tag', label: 'no-value', error: 'MissingRequiredParameter',
|
||||
errMessage: 'Tag XML does not contain both Key and Value' },
|
||||
{ tag: 'Tag', label: 'key-too-long', error: 'InvalidRequest',
|
||||
errMessage: 'Tag Key must be a length between 1 and 128 char' }];
|
||||
|
||||
function generateFilter(errorTag, tagValue) {
|
||||
function generateAction(errorTag, tagObj) {
|
||||
const xmlObj = {};
|
||||
if (tagObj) {
|
||||
let middleTags = '';
|
||||
if (tagObj.label === 'no-time') {
|
||||
middleTags = '';
|
||||
}
|
||||
if (tagObj.label === 'no-tags') {
|
||||
middleTags = tagObj.inTag ?
|
||||
`<${tagObj.inTag}>true</${tagObj.inTag}>` :
|
||||
`<${days[tagObj.tag]}>1</${days[tagObj.tag]}>`;
|
||||
xmlObj.filter = '<Filter><Tag><Key>key</Key>' +
|
||||
'<Value></Value></Tag></Filter>';
|
||||
}
|
||||
if (tagObj.label === 'invalid-days') {
|
||||
middleTags = `<${days[tagObj.tag]}>0</${days[tagObj.tag]}>`;
|
||||
}
|
||||
if (tagObj.label === 'mult-times') {
|
||||
middleTags = `<Days>1</Days><Date>${date}</Date>`;
|
||||
}
|
||||
if (tagObj.label === 'non-iso') {
|
||||
middleTags = '<Date>03-08-2018</Date>';
|
||||
}
|
||||
if (tagObj.label === 'invalid-eodm') {
|
||||
middleTags = '<ExpiredObjectDeleteMarker>foo' +
|
||||
'</ExpiredObjectDeleteMarker>';
|
||||
}
|
||||
xmlObj.actions = `<${tagObj.tag}>${middleTags}</${tagObj.tag}>`;
|
||||
} else {
|
||||
xmlObj.actions = '';
|
||||
}
|
||||
return xmlObj;
|
||||
}
|
||||
|
||||
function generateFilter(errorTag, tagObj) {
|
||||
let Filter;
|
||||
if (tagValue && tagValue.filter === 'two-prefixes') {
|
||||
Filter = '<Filter><Prefix>foo</Prefix>' +
|
||||
'<Prefix>foo2</Prefix></Filter>';
|
||||
} else if (tagValue && tagValue.filter === 'invalid-tag') {
|
||||
Filter = '<Filter><Tag></Tag></Filter>';
|
||||
let middleTags = '';
|
||||
if (tagObj) {
|
||||
if (tagObj.label === 'and-prefix-tag') {
|
||||
middleTags = '<And></And><Prefix></Prefix><Tag></Tag>';
|
||||
}
|
||||
if (tagObj.label === 'only-prefix') {
|
||||
middleTags = '<And><Prefix></Prefix></And>';
|
||||
}
|
||||
if (tagObj.label === 'single-tag') {
|
||||
middleTags = '<And><Tags><Key>fo</Key><Value></Value></Tags></And>';
|
||||
}
|
||||
if (tagObj.label === 'no-key') {
|
||||
middleTags = '<Tag><Value></Value></Tag>';
|
||||
}
|
||||
if (tagObj.label === 'no-value') {
|
||||
middleTags = '<Tag><Key></Key></Tag>';
|
||||
}
|
||||
if (tagObj.label === 'key-too-long') {
|
||||
const longKey = 'a'.repeat(129);
|
||||
middleTags = `<Tag><Key>${longKey}</Key><Value></Value></Tag>`;
|
||||
}
|
||||
if (tagObj.label === 'mult-prefixes') {
|
||||
middleTags = '<Prefix>foo</Prefix><Prefix>bar</Prefix>' +
|
||||
`<Prefix>${tagObj.lastPrefix}</Prefix>`;
|
||||
}
|
||||
Filter = `<Filter>${middleTags}</Filter>`;
|
||||
if (tagObj.label === 'also-prefix') {
|
||||
Filter = '<Filter></Filter><Prefix></Prefix>';
|
||||
}
|
||||
} else {
|
||||
Filter = '';
|
||||
}
|
||||
return Filter;
|
||||
}
|
||||
|
||||
function generateAction(errorTag, tagValue) {
|
||||
const xmlObj = {};
|
||||
if (tagValue && tagValue.action === 'invalid-days-value') {
|
||||
xmlObj.actions = '<Expiration><Days>0</Days></Expiration>';
|
||||
} else if (tagValue && tagValue.action === 'abortMPU-tag') {
|
||||
xmlObj.actions = '<AbortIncompleteMultipartUpload>' +
|
||||
'</AbortIncompleteMultipartUpload>';
|
||||
xmlObj.filter = '<Filter><Tag><Key>key</Key>' +
|
||||
'<Value></Value></Tag></Filter>';
|
||||
} else {
|
||||
xmlObj.actions = tagValue && tagValue.action ?
|
||||
`<${tagValue.action}></${tagValue.action}>` : '';
|
||||
}
|
||||
return xmlObj;
|
||||
}
|
||||
|
||||
function generateRule(errorTag, tagValue, ID, Status, Filter, Action) {
|
||||
function generateRule(errorTag, tagObj, ID, Status, Filter, Action) {
|
||||
let Rule;
|
||||
if (tagValue && tagValue.rule === 'not-unique-id') {
|
||||
if (tagObj && tagObj.rule === 'not-unique-id') {
|
||||
Rule = `<Rule>${ID + Status + Filter + Action}</Rule>` +
|
||||
`<Rule>${ID + Status + Filter + Action}</Rule>`;
|
||||
} else if (tagValue && tagValue.rule === 'too-many-rules') {
|
||||
} else if (tagObj && tagObj.rule === 'too-many-rules') {
|
||||
for (let i = 0; i <= 1000; i++) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
ID = `<ID>foo${i}</ID>`;
|
||||
Rule = `${Rule}<Rule>${ID + Status + Filter + Action}</Rule>`;
|
||||
}
|
||||
} else if (tagValue && tagValue.rule === 'key-too-long') {
|
||||
const key = 'a'.repeat(129);
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
Filter = `<Filter><Tag><Key>${key}</Key><Value></Value></Tag></Filter>`;
|
||||
Rule = `${Rule}<Rule>${ID + Status + Filter + Action}</Rule>`;
|
||||
} else {
|
||||
Rule = '';
|
||||
}
|
||||
return Rule;
|
||||
}
|
||||
|
||||
function generateXml(errorTag, tagValue) {
|
||||
function generateXml(errorTag, tagObj) {
|
||||
let ID;
|
||||
let Status;
|
||||
let Filter;
|
||||
let Action;
|
||||
let Rule;
|
||||
if (errorTag === 'ID') {
|
||||
ID = tagValue && tagValue.id ? `<ID>${tagValue.id}</ID>` : '';
|
||||
ID = tagObj && tagObj.id ? `<ID>${tagObj.id}</ID>` : '';
|
||||
} else {
|
||||
ID = '<ID>foo</ID>';
|
||||
}
|
||||
if (errorTag === 'Status') {
|
||||
Status = tagValue && tagValue.status ?
|
||||
`<Status>${tagValue.status}</Status>` : '';
|
||||
Status = tagObj && tagObj.status ?
|
||||
`<Status>${tagObj.status}</Status>` : '';
|
||||
} else {
|
||||
Status = '<Status>Enabled</Status>';
|
||||
}
|
||||
if (errorTag === 'Filter') {
|
||||
Filter = generateFilter(errorTag, tagValue);
|
||||
Filter = generateFilter(errorTag, tagObj);
|
||||
} else {
|
||||
Filter = '<Filter></Filter>';
|
||||
}
|
||||
if (errorTag === 'Action') {
|
||||
const xmlObj = generateAction(errorTag, tagValue);
|
||||
const xmlObj = generateAction(errorTag, tagObj);
|
||||
Action = xmlObj.actions;
|
||||
Filter = xmlObj.filter ? xmlObj.filter : Filter;
|
||||
} else {
|
||||
Action = '<Expiration><Days>1</Days></Expiration>';
|
||||
}
|
||||
if (errorTag === 'Rule') {
|
||||
Rule = generateRule(errorTag, tagValue, ID, Status, Filter, Action);
|
||||
Rule = generateRule(errorTag, tagObj, ID, Status, Filter, Action);
|
||||
} else {
|
||||
Rule = `<Rule>${ID + Status + Filter + Action}</Rule>`;
|
||||
}
|
||||
|
@ -173,8 +242,8 @@ function generateXml(errorTag, tagValue) {
|
|||
return Lifecycle;
|
||||
}
|
||||
|
||||
function generateParsedXml(errorTag, tagValue, cb) {
|
||||
const xml = generateXml(errorTag, tagValue);
|
||||
function generateParsedXml(errorTag, tagObj, cb) {
|
||||
const xml = generateXml(errorTag, tagObj);
|
||||
parseString(xml, (err, parsedXml) => {
|
||||
assert.equal(err, null, 'Error parsing xml');
|
||||
cb(parsedXml);
|
||||
|
@ -182,90 +251,102 @@ function generateParsedXml(errorTag, tagValue, cb) {
|
|||
}
|
||||
|
||||
function checkError(parsedXml, error, errMessage, cb) {
|
||||
const lifecycleConfig =
|
||||
new LifecycleConfiguration(parsedXml).
|
||||
const lcConfig = new LifecycleConfiguration(parsedXml).
|
||||
getLifecycleConfiguration();
|
||||
assert.strictEqual(
|
||||
lifecycleConfig.error[error], true);
|
||||
assert.strictEqual(
|
||||
lifecycleConfig.error.description, errMessage);
|
||||
assert.strictEqual(lcConfig.error[error], true);
|
||||
assert.strictEqual(lcConfig.error.description, errMessage);
|
||||
cb();
|
||||
}
|
||||
|
||||
describe('LifecycleConfiguration class getLifecycleConfiguration', () => {
|
||||
const tagValue = {};
|
||||
requiredTags.forEach(tag => {
|
||||
it(`should return MalformedXML error if ${tag.tag} tag is missing`,
|
||||
let tagObj;
|
||||
beforeEach(() => {
|
||||
tagObj = {};
|
||||
});
|
||||
|
||||
it('should return MalformedXML error if request xml is empty', done => {
|
||||
const errMessage = 'request xml is undefined or empty';
|
||||
checkError('', 'MalformedXML', errMessage, done);
|
||||
});
|
||||
|
||||
requiredTags.forEach(t => {
|
||||
it(`should return ${t.error} error if ${t.tag} tag is missing`,
|
||||
done => {
|
||||
generateParsedXml(tag.tag, tagValue, parsedXml => {
|
||||
checkError(parsedXml, 'MalformedXML', tag.errMessage, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
validActions.forEach(action => {
|
||||
it(`should return MalformedXML error if time for ${action.tag} ` +
|
||||
'is not included', done => {
|
||||
tagValue.action = action.tag;
|
||||
generateParsedXml('Action', tagValue, parsedXml => {
|
||||
checkError(parsedXml, 'MalformedXML', action.errMessage, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
invalidActions.forEach(action => {
|
||||
it(`should return MalformedXML error for invalid action ${action.tag}`,
|
||||
done => {
|
||||
tagValue.action = action.tag;
|
||||
generateParsedXml('Action', tagValue, parsedXml => {
|
||||
checkError(parsedXml, 'MalformedXML', action.errMessage, done);
|
||||
generateParsedXml(t.tag, null, parsedXml => {
|
||||
checkError(parsedXml, t.error, t.errMessage, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
notImplementedActions.forEach(action => {
|
||||
it(`should return NotImplemented error for ${action.tag} action`,
|
||||
const expError = 'NotImplemented';
|
||||
it(`should return ${expError} error for ${action.tag} action`,
|
||||
done => {
|
||||
tagValue.action = action.tag;
|
||||
generateParsedXml('Action', tagValue, parsedXml => {
|
||||
checkError(parsedXml, 'NotImplemented',
|
||||
action.errMessage, done);
|
||||
generateParsedXml('Action', action, parsedXml => {
|
||||
checkError(parsedXml, expError, action.errMessage, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
invalidActions.forEach(a => {
|
||||
it(`should return ${a.error} for ${a.label} action error`,
|
||||
done => {
|
||||
generateParsedXml('Action', a, parsedXml => {
|
||||
checkError(parsedXml, a.error, a.errMessage, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
invalidFilters.forEach(filter => {
|
||||
it(`should return MalformedXML error for ${filter.tag} filter error`,
|
||||
it(`should return ${filter.error} for ${filter.label} filter error`,
|
||||
done => {
|
||||
tagValue.filter = filter.tag;
|
||||
generateParsedXml('Filter', tagValue, parsedXml => {
|
||||
checkError(parsedXml, 'MalformedXML', filter.errMessage, done);
|
||||
generateParsedXml('Filter', filter, parsedXml => {
|
||||
checkError(parsedXml, filter.error, filter.errMessage, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return MalformedXML error if invalid status', done => {
|
||||
tagValue.status = 'foo';
|
||||
tagObj.status = 'foo';
|
||||
const errMessage = 'Status is not valid';
|
||||
generateParsedXml('Status', tagValue, parsedXml => {
|
||||
generateParsedXml('Status', tagObj, parsedXml => {
|
||||
checkError(parsedXml, 'MalformedXML', errMessage, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return InvalidRequest error if ID not unique', done => {
|
||||
tagObj.rule = 'not-unique-id';
|
||||
const errMessage = 'Rule ID must be unique';
|
||||
generateParsedXml('Rule', tagObj, parsedXml => {
|
||||
checkError(parsedXml, 'InvalidRequest', errMessage, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return InvalidArgument error if invalid ID', done => {
|
||||
tagValue.id = 'a'.repeat(256);
|
||||
tagObj.id = 'a'.repeat(256);
|
||||
const errMessage = 'Rule ID is greater than 255 characters long';
|
||||
generateParsedXml('ID', tagValue, parsedXml => {
|
||||
generateParsedXml('ID', tagObj, parsedXml => {
|
||||
checkError(parsedXml, 'InvalidArgument', errMessage, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return MalformedXML error if over 1000 rules', done => {
|
||||
tagValue.rule = 'too-many-rules';
|
||||
tagObj.rule = 'too-many-rules';
|
||||
const errMessage = 'request xml includes over max limit of 1000 rules';
|
||||
generateParsedXml('Rule', tagValue, parsedXml => {
|
||||
generateParsedXml('Rule', tagObj, parsedXml => {
|
||||
checkError(parsedXml, 'MalformedXML', errMessage, done);
|
||||
});
|
||||
});
|
||||
invalidRequests.forEach(req => {
|
||||
it(`should return InvalidRequest error for ${req.tag}`, done => {
|
||||
tagValue.rule = req.tag;
|
||||
generateParsedXml('Rule', tagValue, parsedXml => {
|
||||
checkError(parsedXml, 'InvalidRequest', req.errMessage, done);
|
||||
});
|
||||
|
||||
it('should use last listed Prefix if multiple Prefixes included', done => {
|
||||
tagObj.label = 'mult-prefixes';
|
||||
tagObj.lastPrefix = 'coco';
|
||||
generateParsedXml('Filter', tagObj, parsedXml => {
|
||||
const lcConfig = new LifecycleConfiguration(parsedXml).
|
||||
getLifecycleConfiguration();
|
||||
assert.strictEqual(tagObj.lastPrefix,
|
||||
lcConfig.rules[0].filter.rulePrefix);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue