Compare commits
5 Commits
developmen
...
feature/S3
Author | SHA1 | Date |
---|---|---|
Ilke | be948a9bf4 | |
Dora Korpar | 2abcdb8cc4 | |
Dora Korpar | 986e79ed11 | |
Dora Korpar | 26abc2148b | |
Dora Korpar | a3738fef29 |
|
@ -97,7 +97,6 @@ const constants = {
|
||||||
'publicAccessBlock',
|
'publicAccessBlock',
|
||||||
'requestPayment',
|
'requestPayment',
|
||||||
'restore',
|
'restore',
|
||||||
'retention',
|
|
||||||
'torrent',
|
'torrent',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ const objectPutACL = require('./objectPutACL');
|
||||||
const objectPutTagging = require('./objectPutTagging');
|
const objectPutTagging = require('./objectPutTagging');
|
||||||
const objectPutPart = require('./objectPutPart');
|
const objectPutPart = require('./objectPutPart');
|
||||||
const objectPutCopyPart = require('./objectPutCopyPart');
|
const objectPutCopyPart = require('./objectPutCopyPart');
|
||||||
|
const objectPutRetention = require('./objectPutRetention');
|
||||||
const prepareRequestContexts
|
const prepareRequestContexts
|
||||||
= require('./apiUtils/authorization/prepareRequestContexts');
|
= require('./apiUtils/authorization/prepareRequestContexts');
|
||||||
const serviceGet = require('./serviceGet');
|
const serviceGet = require('./serviceGet');
|
||||||
|
@ -210,6 +211,7 @@ const api = {
|
||||||
objectPutTagging,
|
objectPutTagging,
|
||||||
objectPutPart,
|
objectPutPart,
|
||||||
objectPutCopyPart,
|
objectPutCopyPart,
|
||||||
|
objectPutRetention,
|
||||||
serviceGet,
|
serviceGet,
|
||||||
websiteGet,
|
websiteGet,
|
||||||
websiteHead,
|
websiteHead,
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
const { policies } = require('arsenal');
|
const { policies } = require('arsenal');
|
||||||
const { config } = require('../../../Config');
|
const { config } = require('../../../Config');
|
||||||
|
|
||||||
const RequestContext = policies.RequestContext;
|
const { RequestContext, requestUtils } = policies;
|
||||||
const requestUtils = policies.requestUtils;
|
|
||||||
let apiMethodAfterVersionCheck;
|
let apiMethodAfterVersionCheck;
|
||||||
const apiMethodWithVersion = { objectGetACL: true, objectPutACL: true,
|
const apiMethodWithVersion = {
|
||||||
objectGet: true, objectDelete: true, objectPutTagging: true,
|
objectGetACL: true,
|
||||||
objectGetTagging: true, objectDeleteTagging: true };
|
objectPutACL: true,
|
||||||
|
objectGet: true,
|
||||||
|
objectDelete: true,
|
||||||
|
objectPutTagging: true,
|
||||||
|
objectGetTagging: true,
|
||||||
|
objectDeleteTagging: true,
|
||||||
|
objectPutRetention: true,
|
||||||
|
};
|
||||||
|
|
||||||
function isHeaderAcl(headers) {
|
function isHeaderAcl(headers) {
|
||||||
return headers['x-amz-grant-read'] || headers['x-amz-grant-read-acp'] ||
|
return headers['x-amz-grant-read'] || headers['x-amz-grant-read-acp'] ||
|
||||||
|
|
|
@ -11,6 +11,7 @@ const locationConstraintCheck = require('./locationConstraintCheck');
|
||||||
const { versioningPreprocessing } = require('./versioning');
|
const { versioningPreprocessing } = require('./versioning');
|
||||||
const removeAWSChunked = require('./removeAWSChunked');
|
const removeAWSChunked = require('./removeAWSChunked');
|
||||||
const getReplicationInfo = require('./getReplicationInfo');
|
const getReplicationInfo = require('./getReplicationInfo');
|
||||||
|
const getObjectLockInfo = require('./getObjectLockInfo');
|
||||||
const { config } = require('../../../Config');
|
const { config } = require('../../../Config');
|
||||||
const validateWebsiteHeader = require('./websiteServing')
|
const validateWebsiteHeader = require('./websiteServing')
|
||||||
.validateWebsiteHeader;
|
.validateWebsiteHeader;
|
||||||
|
@ -194,6 +195,7 @@ function createAndStoreObject(bucketName, bucketMD, objectKey, objMD, authInfo,
|
||||||
logger.newRequestLoggerFromSerializedUids(log.getSerializedUids());
|
logger.newRequestLoggerFromSerializedUids(log.getSerializedUids());
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
function storeData(next) {
|
function storeData(next) {
|
||||||
|
console.log(`\n####\n[lib/api/apiUtils/object/createAndStoreObject.js] waterfall ! L197!`);
|
||||||
if (size === 0 && !dontSkipBackend[locationType]) {
|
if (size === 0 && !dontSkipBackend[locationType]) {
|
||||||
metadataStoreParams.contentMD5 = constants.emptyFileMd5;
|
metadataStoreParams.contentMD5 = constants.emptyFileMd5;
|
||||||
return next(null, null, null);
|
return next(null, null, null);
|
||||||
|
|
|
@ -36,6 +36,7 @@ function checkHashMatchMD5(stream, hashedStream, dataRetrievalInfo, log, cb) {
|
||||||
return cb(errors.BadDigest);
|
return cb(errors.BadDigest);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
console.log(`\n^^^^^\n[lib/api/apiUtils/object/storeObject.js] dataRetrievalInfo:${JSON.stringify(dataRetrievalInfo, null,2)}!\n`);
|
||||||
return cb(null, dataRetrievalInfo, completedHash);
|
return cb(null, dataRetrievalInfo, completedHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
const async = require('async');
|
||||||
|
const { errors, s3middleware } = require('arsenal');
|
||||||
|
|
||||||
|
const { decodeVersionId, getVersionIdResHeader }
|
||||||
|
= require('./apiUtils/object/versioning');
|
||||||
|
|
||||||
|
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
|
||||||
|
const { pushMetric } = require('../utapi/utilities');
|
||||||
|
const collectCorsHeaders = require('../utilities/collectCorsHeaders');
|
||||||
|
|
||||||
|
const { convertToXml } = s3middleware.retention;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object Get Retention - Return retention info for object
|
||||||
|
* @param {AuthInfo} authInfo - Instance of AuthInfo class with requester's info
|
||||||
|
* @param {object} request - http request object
|
||||||
|
* @param {object} log - Werelogs logger
|
||||||
|
* @param {function} callback - callback to server
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
function objectGetRetention(authInfo, request, log, callback) {
|
||||||
|
log.debug('processing request', { method: 'objectGetRetention' });
|
||||||
|
|
||||||
|
const { bucketName, objectKey } = request;
|
||||||
|
|
||||||
|
const decodedVidResult = decodeVersionId(request.query);
|
||||||
|
if (decodedVidResult instanceof Error) {
|
||||||
|
log.trace('invalid versionId query', {
|
||||||
|
versionId: request.query.versionId,
|
||||||
|
error: decodedVidResult,
|
||||||
|
});
|
||||||
|
return process.nextTick(() => callback(decodedVidResult));
|
||||||
|
}
|
||||||
|
const reqVersionId = decodedVidResult;
|
||||||
|
|
||||||
|
const metadataValParams = {
|
||||||
|
authInfo,
|
||||||
|
bucketName,
|
||||||
|
objectKey,
|
||||||
|
requestType: 'objectGetRetention',
|
||||||
|
versionId: reqVersionId,
|
||||||
|
};
|
||||||
|
|
||||||
|
return async.waterfall([
|
||||||
|
next => metadataValidateBucketAndObj(metadataValParams, log,
|
||||||
|
(err, bucket, objectMD) => {
|
||||||
|
if (err) {
|
||||||
|
log.trace('request authorization failed',
|
||||||
|
{ method: 'objectGetRetention', error: err });
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
if (!objectMD) {
|
||||||
|
const err = reqVersionId ? errors.NoSuchVersion :
|
||||||
|
errors.NoSuchKey;
|
||||||
|
log.trace('error no object metadata found',
|
||||||
|
{ method: 'objectGetRetention', error: err });
|
||||||
|
return next(err, bucket);
|
||||||
|
}
|
||||||
|
if (objectMD.isDeleteMarker) {
|
||||||
|
if (reqVersionId) {
|
||||||
|
log.trace('requested version is delete marker',
|
||||||
|
{ method: 'objectGetRetention' });
|
||||||
|
return next(errors.MethodNotAllowed);
|
||||||
|
}
|
||||||
|
log.trace('most recent version is delete marker',
|
||||||
|
{ method: 'objectGetRetention' });
|
||||||
|
return next(errors.NoSuchKey);
|
||||||
|
}
|
||||||
|
if (!bucket.isObjectLockEnabled()) {
|
||||||
|
log.trace('object lock not enabled on bucket',
|
||||||
|
{ method: 'objectGetRetention' });
|
||||||
|
return next(errors.InvalidRequest.customizeDescription(
|
||||||
|
'Bucket is missing Object Lock Configuration'));
|
||||||
|
}
|
||||||
|
return next(null, bucket, objectMD);
|
||||||
|
}),
|
||||||
|
(bucket, objectMD, next) => {
|
||||||
|
const { retentionInfo } = objectMD;
|
||||||
|
const xml = convertToXml(retentionInfo);
|
||||||
|
if (xml === '') {
|
||||||
|
return next(errors.NoSuchObjectLockConfiguration);
|
||||||
|
}
|
||||||
|
return next(null, bucket, xml, objectMD);
|
||||||
|
},
|
||||||
|
], (err, bucket, xml, objectMD) => {
|
||||||
|
const additionalResHeaders = collectCorsHeaders(request.headers.origin,
|
||||||
|
request.method, bucket);
|
||||||
|
if (err) {
|
||||||
|
log.trace('error processing request', { error: err,
|
||||||
|
method: 'objectGetRetention' });
|
||||||
|
} else {
|
||||||
|
pushMetric('getObjectRetention', log, {
|
||||||
|
authInfo,
|
||||||
|
bucket: bucketName,
|
||||||
|
});
|
||||||
|
const verCfg = bucket.getVersioningConfiguration();
|
||||||
|
additionalResHeaders['x-amz-version-id'] =
|
||||||
|
getVersionIdResHeader(verCfg, objectMD);
|
||||||
|
}
|
||||||
|
return callback(err, xml, additionalResHeaders);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = objectGetRetention;
|
|
@ -4,6 +4,7 @@ const { errors, versioning } = require('arsenal');
|
||||||
const aclUtils = require('../utilities/aclUtils');
|
const aclUtils = require('../utilities/aclUtils');
|
||||||
const { cleanUpBucket } = require('./apiUtils/bucket/bucketCreation');
|
const { cleanUpBucket } = require('./apiUtils/bucket/bucketCreation');
|
||||||
const collectCorsHeaders = require('../utilities/collectCorsHeaders');
|
const collectCorsHeaders = require('../utilities/collectCorsHeaders');
|
||||||
|
const getObjectLockInfo = require('./apiUtils/object/getObjectLockInfo');
|
||||||
const createAndStoreObject = require('./apiUtils/object/createAndStoreObject');
|
const createAndStoreObject = require('./apiUtils/object/createAndStoreObject');
|
||||||
const { checkQueryVersionId } = require('./apiUtils/object/versioning');
|
const { checkQueryVersionId } = require('./apiUtils/object/versioning');
|
||||||
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
|
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
|
||||||
|
@ -53,6 +54,7 @@ function objectPut(authInfo, request, streamingV4Params, log, callback) {
|
||||||
|
|
||||||
return metadataValidateBucketAndObj(valParams, log,
|
return metadataValidateBucketAndObj(valParams, log,
|
||||||
(err, bucket, objMD) => {
|
(err, bucket, objMD) => {
|
||||||
|
console.log(`\n------\n[lib/api/objectPut.js] request.headers:${JSON.stringify(request.headers, null, 2)}\n`);
|
||||||
const responseHeaders = collectCorsHeaders(request.headers.origin,
|
const responseHeaders = collectCorsHeaders(request.headers.origin,
|
||||||
request.method, bucket);
|
request.method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -67,6 +69,11 @@ function objectPut(authInfo, request, streamingV4Params, log, callback) {
|
||||||
'from non-owner account');
|
'from non-owner account');
|
||||||
return callback(errors.NoSuchBucket);
|
return callback(errors.NoSuchBucket);
|
||||||
}
|
}
|
||||||
|
// const retentionHeaders = collectRetentionHeaders(headers, bucket);
|
||||||
|
const objectLockEnabledForBucket = bucket.isObjectLockEnabled();
|
||||||
|
// console.log(`\n---\n[lib/api/objectPut.js] retentionHeaders: ${retentionHeaders}`);
|
||||||
|
console.log(`\n+++++++\n[lib/api/objectPut.js] objectLockEnabledForBucket: ${objectLockEnabledForBucket}`);
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
function handleTransientOrDeleteBuckets(next) {
|
function handleTransientOrDeleteBuckets(next) {
|
||||||
if (bucket.hasTransientFlag() || bucket.hasDeletedFlag()) {
|
if (bucket.hasTransientFlag() || bucket.hasDeletedFlag()) {
|
||||||
|
@ -86,7 +93,23 @@ function objectPut(authInfo, request, streamingV4Params, log, callback) {
|
||||||
}
|
}
|
||||||
return next(null, null);
|
return next(null, null);
|
||||||
},
|
},
|
||||||
|
// function validateObjectLockConditions(next) {
|
||||||
|
// const objectHasRetention = request.headers['x-amz-object-lock-mode']
|
||||||
|
// && request.headers['x-amz-object-lock-retain-until-date'];
|
||||||
|
// const objectHasLegalHold
|
||||||
|
// = request.headers['x-amz-object-lock-legal-hold'];
|
||||||
|
// // If retention headers and/or legal hold header present but
|
||||||
|
// // object lock is not enabled on the bucket
|
||||||
|
// if ((objectHasRetention || objectHasLegalHold)
|
||||||
|
// && !bucket.isObjectLockEnabled()) {
|
||||||
|
// return errors.InvalidRequest.customizeDescription(
|
||||||
|
// 'Bucket is missing ObjectLockConfiguration'
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// return next();
|
||||||
|
// },
|
||||||
function objectCreateAndStore(cipherBundle, next) {
|
function objectCreateAndStore(cipherBundle, next) {
|
||||||
|
console.log(`\n+++++++\n[lib/api/objectPut.js] bucket.isObjectLockEnabled(): ${bucket.isObjectLockEnabled()}`);
|
||||||
return createAndStoreObject(bucketName,
|
return createAndStoreObject(bucketName,
|
||||||
bucket, objectKey, objMD, authInfo, canonicalID, cipherBundle,
|
bucket, objectKey, objMD, authInfo, canonicalID, cipherBundle,
|
||||||
request, false, streamingV4Params, log, next);
|
request, false, streamingV4Params, log, next);
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
const async = require('async');
|
||||||
|
const { errors, s3middleware } = require('arsenal');
|
||||||
|
|
||||||
|
const { decodeVersionId, getVersionIdResHeader } =
|
||||||
|
require('./apiUtils/object/versioning');
|
||||||
|
|
||||||
|
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
|
||||||
|
const { pushMetric } = require('../utapi/utilities');
|
||||||
|
const getReplicationInfo = require('./apiUtils/object/getReplicationInfo');
|
||||||
|
const collectCorsHeaders = require('../utilities/collectCorsHeaders');
|
||||||
|
const metadata = require('../metadata/wrapper');
|
||||||
|
const { config } = require('../Config');
|
||||||
|
const multipleBackendGateway = require('../data/multipleBackendGateway');
|
||||||
|
|
||||||
|
const { parseRetentionXml } = s3middleware.retention;
|
||||||
|
const REPLICATION_ACTION = 'PUT_RETENTION';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object Put Retention - Adds retention information to object
|
||||||
|
* @param {AuthInfo} authInfo - Instance of AuthInfo class with requester's info
|
||||||
|
* @param {object} request - http request object
|
||||||
|
* @param {object} log - Werelogs logger
|
||||||
|
* @param {function} callback - callback to server
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
function objectPutRetention(authInfo, request, log, callback) {
|
||||||
|
log.debug('processing request', { method: 'objectPutRetention' });
|
||||||
|
|
||||||
|
const { bucketName, objectKey } = request;
|
||||||
|
|
||||||
|
const decodedVidResult = decodeVersionId(request.query);
|
||||||
|
if (decodedVidResult instanceof Error) {
|
||||||
|
log.trace('invalid versionId query', {
|
||||||
|
versionId: request.query.versionId,
|
||||||
|
error: decodedVidResult,
|
||||||
|
});
|
||||||
|
return process.nextTick(() => callback(decodedVidResult));
|
||||||
|
}
|
||||||
|
const reqVersionId = decodedVidResult;
|
||||||
|
|
||||||
|
const metadataValParams = {
|
||||||
|
authInfo,
|
||||||
|
bucketName,
|
||||||
|
objectKey,
|
||||||
|
requestType: 'objectPutRetention',
|
||||||
|
versionId: reqVersionId,
|
||||||
|
};
|
||||||
|
|
||||||
|
return async.waterfall([
|
||||||
|
next => metadataValidateBucketAndObj(metadataValParams, log,
|
||||||
|
(err, bucket, objectMD) => {
|
||||||
|
if (err) {
|
||||||
|
log.trace('request authorization failed',
|
||||||
|
{ method: 'objectPutRetention', error: err });
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
if (!objectMD) {
|
||||||
|
const err = reqVersionId ? errors.NoSuchVersion :
|
||||||
|
errors.NoSuchKey;
|
||||||
|
log.trace('error no object metadata found',
|
||||||
|
{ method: 'objectPutRetention', error: err });
|
||||||
|
return next(err, bucket);
|
||||||
|
}
|
||||||
|
if (objectMD.isDeleteMarker) {
|
||||||
|
log.trace('version is a delete marker',
|
||||||
|
{ method: 'objectPutRetention' });
|
||||||
|
return next(errors.MethodNotAllowed, bucket);
|
||||||
|
}
|
||||||
|
if (!bucket.isObjectLockEnabled()) {
|
||||||
|
log.trace('object lock not enabled on bucket',
|
||||||
|
{ method: 'objectPutRetention' });
|
||||||
|
return next(errors.InvalidRequest.customizeDescription(
|
||||||
|
'Bucket is missing Object Lock Configuration'
|
||||||
|
), bucket);
|
||||||
|
}
|
||||||
|
return next(null, bucket, objectMD);
|
||||||
|
}),
|
||||||
|
(bucket, objectMD, next) => {
|
||||||
|
log.trace('parsing retention information');
|
||||||
|
parseRetentionXml(request.post, log,
|
||||||
|
(err, retentionInfo) => next(err, bucket, retentionInfo, objectMD));
|
||||||
|
},
|
||||||
|
(bucket, retentionInfo, objectMD, next) => {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
objectMD.retentionInfo = retentionInfo;
|
||||||
|
const params = objectMD.versionId ?
|
||||||
|
{ versionId: objectMD.versionId } : {};
|
||||||
|
const replicationInfo = getReplicationInfo(objectKey, bucket, true,
|
||||||
|
0, REPLICATION_ACTION, objectMD);
|
||||||
|
if (replicationInfo) {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
objectMD.replicationInfo = Object.assign({},
|
||||||
|
objectMD.replicationInfo, replicationInfo);
|
||||||
|
}
|
||||||
|
metadata.putObjectMD(bucket.getName(), objectKey, objectMD, params,
|
||||||
|
log, err => next(err, bucket, objectMD));
|
||||||
|
},
|
||||||
|
(bucket, objectMD, next) => {
|
||||||
|
if (config.backends.data === 'multiple') {
|
||||||
|
return multipleBackendGateway.objectRetention('Put', objectKey,
|
||||||
|
bucket, objectMD, log, err => next(err, bucket, objectMD));
|
||||||
|
}
|
||||||
|
return next(null, bucket, objectMD);
|
||||||
|
},
|
||||||
|
], (err, bucket, objectMD) => {
|
||||||
|
const additionalResHeaders = collectCorsHeaders(request.headers.origin,
|
||||||
|
request.method, bucket);
|
||||||
|
if (err) {
|
||||||
|
log.trace('error processing request',
|
||||||
|
{ error: err, method: 'objectPutRetention' });
|
||||||
|
} else {
|
||||||
|
pushMetric('putObjectRetention', log, {
|
||||||
|
authInfo,
|
||||||
|
bucket: bucketName,
|
||||||
|
keys: [objectKey],
|
||||||
|
});
|
||||||
|
const verCfg = bucket.getVersioningConfiguration();
|
||||||
|
additionalResHeaders['x-amz-version-id'] =
|
||||||
|
getVersionIdResHeader(verCfg, objectMD);
|
||||||
|
}
|
||||||
|
return callback(err, additionalResHeaders);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = objectPutRetention;
|
|
@ -94,6 +94,7 @@ const metadata = {
|
||||||
objVal.getValue() : objVal;
|
objVal.getValue() : objVal;
|
||||||
client.putObject(bucketName, objName, value, params, log,
|
client.putObject(bucketName, objName, value, params, log,
|
||||||
(err, data) => {
|
(err, data) => {
|
||||||
|
console.log(`\n[lib/metadata/wrapper.js] L97 putObjectMD: data: ${data} `)
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error from metadata', { implName, error: err });
|
log.debug('error from metadata', { implName, error: err });
|
||||||
return cb(err);
|
return cb(err);
|
||||||
|
|
|
@ -95,7 +95,7 @@ const services = {
|
||||||
contentType, cacheControl, contentDisposition, contentEncoding,
|
contentType, cacheControl, contentDisposition, contentEncoding,
|
||||||
expires, multipart, headers, overrideMetadata, log,
|
expires, multipart, headers, overrideMetadata, log,
|
||||||
lastModifiedDate, versioning, versionId, tagging, taggingCopy,
|
lastModifiedDate, versioning, versionId, tagging, taggingCopy,
|
||||||
replicationInfo, dataStoreName } = params;
|
replicationInfo, objectLockInfo, dataStoreName } = params;
|
||||||
log.trace('storing object in metadata');
|
log.trace('storing object in metadata');
|
||||||
assert.strictEqual(typeof bucketName, 'string');
|
assert.strictEqual(typeof bucketName, 'string');
|
||||||
const md = new ObjectMD();
|
const md = new ObjectMD();
|
||||||
|
@ -128,6 +128,24 @@ const services = {
|
||||||
if (headers && headers['x-amz-website-redirect-location']) {
|
if (headers && headers['x-amz-website-redirect-location']) {
|
||||||
md.setRedirectLocation(headers['x-amz-website-redirect-location']);
|
md.setRedirectLocation(headers['x-amz-website-redirect-location']);
|
||||||
}
|
}
|
||||||
|
if (headers && headers['x-amz-object-lock-retain-until-date']
|
||||||
|
&& headers['x-amz-object-lock-mode']) {
|
||||||
|
console.log(`\n++++++\n[lib/services.js] HERE! (retentionInfo)\n ~~~~~~\n`);
|
||||||
|
const retention = {
|
||||||
|
mode: headers['x-amz-object-lock-mode'],
|
||||||
|
retainUntilDate: headers['x-amz-object-lock-retain-until-date'],
|
||||||
|
}
|
||||||
|
md.setRetentionInfo(retention);
|
||||||
|
}
|
||||||
|
console.log(`\n!!!!\n[lib/services.js] L140 headers['x-amz-object-lock-legal-hold']: ${headers['x-amz-object-lock-legal-hold']}`);
|
||||||
|
if (headers && headers['x-amz-object-lock-legal-hold']) {
|
||||||
|
const legalHold = headers['x-amz-object-lock-legal-hold']
|
||||||
|
=== 'ON' ? true : false;
|
||||||
|
console.log(`\n++++++\n[lib/services.js] HERE! legalHold: ${legalHold}\n ~~~~~~\n`);
|
||||||
|
// md.setLegalHold(legalHold);
|
||||||
|
}
|
||||||
|
console.log(`\n!!!!\n[lib/services.js] L147 md.getRetentionInfo: ${JSON.stringify(md.getRetentionInfo())}`);
|
||||||
|
// console.log(`\n!!!!\n[lib/services.js] L141 md: ${JSON.stringify(md, null, 2)}`);
|
||||||
if (replicationInfo) {
|
if (replicationInfo) {
|
||||||
md.setReplicationInfo(replicationInfo);
|
md.setReplicationInfo(replicationInfo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,19 @@ function collectResponseHeaders(objectMD, corsHeaders, versioningCfg,
|
||||||
responseMetaHeaders['x-amz-tagging-count'] =
|
responseMetaHeaders['x-amz-tagging-count'] =
|
||||||
Object.keys(objectMD.tags).length;
|
Object.keys(objectMD.tags).length;
|
||||||
}
|
}
|
||||||
|
if (objectMD.retentionInfo && objectMD.retentionInfo.retainUntilDate
|
||||||
|
&& objectMD.retentionInfo.mode) {
|
||||||
|
responseMetaHeaders['x-amz-object-lock-retain-until-date']
|
||||||
|
= objectMD.retentionInfo.retainUntilDate;
|
||||||
|
responseMetaHeaders['x-amz-object-lock-mode']
|
||||||
|
= objectMD.retentionInfo.mode;
|
||||||
|
console.log(`\n[lib/utilities/collectResponseHeaders.js]\n Y e HU UUUU uuu UU !!! @@@ \n\n`);
|
||||||
|
}
|
||||||
|
if (objectMD.legalHold !== undefined) {
|
||||||
|
console.log(`\n[lib/utilities/collectResponseHeaders.js]\n legal hold !!!\n`);
|
||||||
|
responseMetaHeaders['x-amz-replication-status'] =
|
||||||
|
objectMD.legalHold ? 'ON' : 'OFF';
|
||||||
|
}
|
||||||
if (objectMD.replicationInfo && objectMD.replicationInfo.status) {
|
if (objectMD.replicationInfo && objectMD.replicationInfo.status) {
|
||||||
responseMetaHeaders['x-amz-replication-status'] =
|
responseMetaHeaders['x-amz-replication-status'] =
|
||||||
objectMD.replicationInfo.status;
|
objectMD.replicationInfo.status;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/scality/S3#readme",
|
"homepage": "https://github.com/scality/S3#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"arsenal": "github:scality/Arsenal#0d49eff",
|
"arsenal": "github:scality/Arsenal#bdd8368",
|
||||||
"async": "~2.5.0",
|
"async": "~2.5.0",
|
||||||
"aws-sdk": "2.363.0",
|
"aws-sdk": "2.363.0",
|
||||||
"azure-storage": "^2.1.0",
|
"azure-storage": "^2.1.0",
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const { bucketPut } = require('../../../lib/api/bucketPut');
|
||||||
|
const objectPut = require('../../../lib/api/objectPut');
|
||||||
|
const objectPutRetention = require('../../../lib/api/objectPutRetention');
|
||||||
|
const objectGetRetention = require('../../../lib/api/objectGetRetention');
|
||||||
|
const { cleanup, DummyRequestLogger, makeAuthInfo } = require('../helpers');
|
||||||
|
const DummyRequest = require('../DummyRequest');
|
||||||
|
|
||||||
|
const log = new DummyRequestLogger();
|
||||||
|
const authInfo = makeAuthInfo('accessKey1');
|
||||||
|
const namespace = 'default';
|
||||||
|
const bucketName = 'bucketname';
|
||||||
|
const objectName = 'objectName';
|
||||||
|
const postBody = Buffer.from('I am a body', 'utf8');
|
||||||
|
|
||||||
|
const date = new Date();
|
||||||
|
date.setDate(date.getDate() + 1);
|
||||||
|
|
||||||
|
const bucketPutRequest = {
|
||||||
|
bucketName,
|
||||||
|
headers: { host: `${bucketName}.s3.amazonaws.com` },
|
||||||
|
url: '/',
|
||||||
|
};
|
||||||
|
|
||||||
|
const putObjectRequest = new DummyRequest({
|
||||||
|
bucketName,
|
||||||
|
namespace,
|
||||||
|
objectKey: objectName,
|
||||||
|
headers: {},
|
||||||
|
url: `/${bucketName}/${objectName}`,
|
||||||
|
}, postBody);
|
||||||
|
|
||||||
|
const objectRetentionXml = '<ObjectRetention ' +
|
||||||
|
'xmlns="http://s3.amazonaws.com/doc/2006-03-01/">' +
|
||||||
|
'<Mode>GOVERNANCE</Mode>' +
|
||||||
|
`<RetainUntilDate>${date.toISOString()}</RetainUntilDate>` +
|
||||||
|
'</ObjectRetention>';
|
||||||
|
|
||||||
|
const putObjRetRequest = {
|
||||||
|
bucketName,
|
||||||
|
objectKey: objectName,
|
||||||
|
headers: { host: `${bucketName}.s3.amazonaws.com` },
|
||||||
|
post: objectRetentionXml,
|
||||||
|
};
|
||||||
|
|
||||||
|
const getObjRetRequest = {
|
||||||
|
bucketName,
|
||||||
|
objectKey: objectName,
|
||||||
|
headers: { host: `${bucketName}.s3.amazonaws.com` },
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('getObjectRetention API', () => {
|
||||||
|
before(() => cleanup());
|
||||||
|
|
||||||
|
describe('without Object Lock enabled on bucket', () => {
|
||||||
|
beforeEach(done => {
|
||||||
|
bucketPut(authInfo, bucketPutRequest, log, err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
objectPut(authInfo, putObjectRequest, undefined, log, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
afterEach(() => cleanup());
|
||||||
|
|
||||||
|
it('should return InvalidRequest error', done => {
|
||||||
|
objectGetRetention(authInfo, getObjRetRequest, log, err => {
|
||||||
|
assert.strictEqual(err.InvalidRequest, true);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with Object Lock enabled on bucket', () => {
|
||||||
|
const bucketObjLockRequest = Object.assign({}, bucketPutRequest,
|
||||||
|
{ headers: { 'x-amz-bucket-object-lock-enabled': true } });
|
||||||
|
|
||||||
|
beforeEach(done => {
|
||||||
|
bucketPut(authInfo, bucketObjLockRequest, log, err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
objectPut(authInfo, putObjectRequest, undefined, log, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
afterEach(() => cleanup());
|
||||||
|
|
||||||
|
it('should return NoSuchObjectLockConfiguration if no retention set',
|
||||||
|
done => {
|
||||||
|
objectGetRetention(authInfo, getObjRetRequest, log, err => {
|
||||||
|
assert.strictEqual(err.NoSuchObjectLockConfiguration, true);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get an object\'s retention info', done => {
|
||||||
|
objectPutRetention(authInfo, putObjRetRequest, log, err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
objectGetRetention(authInfo, getObjRetRequest, log,
|
||||||
|
(err, xml) => {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.strictEqual(xml, objectRetentionXml);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -162,6 +162,75 @@ describe('objectPut API', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const generatePutObjectReq = (date, mode) => new DummyRequest({
|
||||||
|
bucketName,
|
||||||
|
namespace,
|
||||||
|
objectKey: objectName,
|
||||||
|
headers: {
|
||||||
|
'x-amz-object-lock-retain-until-date': date,
|
||||||
|
'x-amz-object-lock-mode': mode,
|
||||||
|
},
|
||||||
|
url: `/${bucketName}/${objectName}`,
|
||||||
|
calculatedHash: 'vnR+tLdVF79rPPfF+7YvOg==',
|
||||||
|
}, postBody);
|
||||||
|
|
||||||
|
const retentionInfo = (date, mode) => ({
|
||||||
|
retainUntilDate: date,
|
||||||
|
mode: mode,
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should successfully put an object with valid retention date and COMPLIANCE mode', done => {
|
||||||
|
bucketPut(authInfo, testPutBucketRequest, log, () => {
|
||||||
|
const testDate = new Date(2022, 6, 3);
|
||||||
|
const testModeComp = 'COMPLIANCE';
|
||||||
|
const request = generatePutObjectReq(testDate, testModeComp);
|
||||||
|
const expectedRetention = retentionInfo(testDate, testModeComp);
|
||||||
|
objectPut(authInfo, request, undefined, log, (err, resHeaders) => {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.strictEqual(resHeaders.ETag, `"${correctMD5}"`);
|
||||||
|
metadata.getObjectMD(bucketName, objectName, {}, log,
|
||||||
|
(err, objectMD) => {
|
||||||
|
assert(objectMD);
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.deepStrictEqual(objectMD.retentionInfo,
|
||||||
|
expectedRetention);
|
||||||
|
assert.strictEqual(objectMD.retentionInfo.mode,
|
||||||
|
expectedRetention.mode);
|
||||||
|
assert.strictEqual(
|
||||||
|
objectMD.retentionInfo.retainUntilDate,
|
||||||
|
expectedRetention.retainUntilDate);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should successfully put an object with valid retention date and GOVERNANCE mode', done => {
|
||||||
|
bucketPut(authInfo, testPutBucketRequest, log, () => {
|
||||||
|
const testDate = new Date(2022, 6, 3);
|
||||||
|
const testModeComp = 'GOVERNANCE';
|
||||||
|
const request = generatePutObjectReq(testDate, testModeComp);
|
||||||
|
const expectedRetention = retentionInfo(testDate, testModeComp);
|
||||||
|
objectPut(authInfo, request, undefined, log, (err, resHeaders) => {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.strictEqual(resHeaders.ETag, `"${correctMD5}"`);
|
||||||
|
metadata.getObjectMD(bucketName, objectName, {}, log,
|
||||||
|
(err, objectMD) => {
|
||||||
|
assert(objectMD);
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.deepStrictEqual(objectMD.retentionInfo,
|
||||||
|
expectedRetention);
|
||||||
|
assert.strictEqual(objectMD.retentionInfo.mode,
|
||||||
|
expectedRetention.mode);
|
||||||
|
assert.strictEqual(
|
||||||
|
objectMD.retentionInfo.retainUntilDate,
|
||||||
|
expectedRetention.retainUntilDate);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should successfully put an object with user metadata', done => {
|
it('should successfully put an object with user metadata', done => {
|
||||||
const testPutObjectRequest = new DummyRequest({
|
const testPutObjectRequest = new DummyRequest({
|
||||||
bucketName,
|
bucketName,
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const { bucketPut } = require('../../../lib/api/bucketPut');
|
||||||
|
const objectPut = require('../../../lib/api/objectPut');
|
||||||
|
const objectPutRetention = require('../../../lib/api/objectPutRetention');
|
||||||
|
const { cleanup, DummyRequestLogger, makeAuthInfo } = require('../helpers');
|
||||||
|
const metadata = require('../../../lib/metadata/wrapper');
|
||||||
|
const DummyRequest = require('../DummyRequest');
|
||||||
|
|
||||||
|
const log = new DummyRequestLogger();
|
||||||
|
const authInfo = makeAuthInfo('accessKey1');
|
||||||
|
const namespace = 'default';
|
||||||
|
const bucketName = 'bucketname';
|
||||||
|
const objectName = 'objectName';
|
||||||
|
const postBody = Buffer.from('I am a body', 'utf8');
|
||||||
|
|
||||||
|
const date = new Date();
|
||||||
|
date.setDate(date.getDate() + 1);
|
||||||
|
|
||||||
|
const bucketPutRequest = {
|
||||||
|
bucketName,
|
||||||
|
headers: { host: `${bucketName}.s3.amazonaws.com` },
|
||||||
|
url: '/',
|
||||||
|
};
|
||||||
|
|
||||||
|
const putObjectRequest = new DummyRequest({
|
||||||
|
bucketName,
|
||||||
|
namespace,
|
||||||
|
objectKey: objectName,
|
||||||
|
headers: {},
|
||||||
|
url: `/${bucketName}/${objectName}`,
|
||||||
|
}, postBody);
|
||||||
|
|
||||||
|
const objectRetentionXml = '<ObjectRetention ' +
|
||||||
|
'xmlns="http://s3.amazonaws.com/doc/2006-03-01/">' +
|
||||||
|
'<Mode>GOVERNANCE</Mode>' +
|
||||||
|
`<RetainUntilDate>${date.toISOString()}</RetainUntilDate>` +
|
||||||
|
'</ObjectRetention>';
|
||||||
|
|
||||||
|
const putObjRetRequest = {
|
||||||
|
bucketName,
|
||||||
|
objectKey: objectName,
|
||||||
|
headers: { host: `${bucketName}.s3.amazonaws.com` },
|
||||||
|
post: objectRetentionXml,
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedRetInfo = {
|
||||||
|
retention: {
|
||||||
|
mode: 'GOVERNANCE',
|
||||||
|
retainUntilDate: date.toISOString(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('putObjectRetention API', () => {
|
||||||
|
before(() => cleanup());
|
||||||
|
|
||||||
|
describe('without Object Lock enabled on bucket', () => {
|
||||||
|
beforeEach(done => {
|
||||||
|
bucketPut(authInfo, bucketPutRequest, log, err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
objectPut(authInfo, putObjectRequest, undefined, log, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
afterEach(() => cleanup());
|
||||||
|
|
||||||
|
it('should return InvalidRequest error', done => {
|
||||||
|
objectPutRetention(authInfo, putObjRetRequest, log, err => {
|
||||||
|
assert.strictEqual(err.InvalidRequest, true);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with Object Lock enabled on bucket', () => {
|
||||||
|
const bucketObjLockRequest = Object.assign({}, bucketPutRequest,
|
||||||
|
{ headers: { 'x-amz-bucket-object-lock-enabled': true } });
|
||||||
|
|
||||||
|
beforeEach(done => {
|
||||||
|
bucketPut(authInfo, bucketObjLockRequest, log, err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
objectPut(authInfo, putObjectRequest, undefined, log, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
afterEach(() => cleanup());
|
||||||
|
|
||||||
|
it('should update an object\'s metadata with retention info', done => {
|
||||||
|
objectPutRetention(authInfo, putObjRetRequest, log, err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
return metadata.getObjectMD(bucketName, objectName, {}, log,
|
||||||
|
(err, objMD) => {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.deepStrictEqual(objMD.retentionInfo,
|
||||||
|
expectedRetInfo);
|
||||||
|
return done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
80
yarn.lock
80
yarn.lock
|
@ -210,9 +210,9 @@ arraybuffer.slice@0.0.6:
|
||||||
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca"
|
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca"
|
||||||
integrity sha1-8zshWfBTKj8xB6JywMz70a0peco=
|
integrity sha1-8zshWfBTKj8xB6JywMz70a0peco=
|
||||||
|
|
||||||
"arsenal@github:scality/Arsenal#0d49eff":
|
"arsenal@github:scality/Arsenal#bdd8368":
|
||||||
version "7.5.0"
|
version "7.5.0"
|
||||||
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/0d49eff7e4da07eb27c516820e258221d543d082"
|
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/bdd8368c39097d9f367cc0901dd643f1b97ea532"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@hapi/joi" "^15.1.0"
|
"@hapi/joi" "^15.1.0"
|
||||||
JSONStream "^1.0.0"
|
JSONStream "^1.0.0"
|
||||||
|
@ -236,7 +236,7 @@ arraybuffer.slice@0.0.6:
|
||||||
ioctl "2.0.0"
|
ioctl "2.0.0"
|
||||||
|
|
||||||
arsenal@scality/Arsenal#32c895b:
|
arsenal@scality/Arsenal#32c895b:
|
||||||
version "7.5.0"
|
version "7.4.3"
|
||||||
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/32c895b21a31eb67dacc6e76d7f58b8142bf3ad1"
|
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/32c895b21a31eb67dacc6e76d7f58b8142bf3ad1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@hapi/joi" "^15.1.0"
|
"@hapi/joi" "^15.1.0"
|
||||||
|
@ -379,9 +379,9 @@ aws-sdk@2.363.0:
|
||||||
xml2js "0.4.19"
|
xml2js "0.4.19"
|
||||||
|
|
||||||
aws-sdk@^2.2.23:
|
aws-sdk@^2.2.23:
|
||||||
version "2.678.0"
|
version "2.686.0"
|
||||||
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.678.0.tgz#b16230f4894d40ead50f9e23805c874f4ca62549"
|
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.686.0.tgz#c58c3874eff4c76c763d137df617e87971321eb7"
|
||||||
integrity sha512-i8t7+1/C6maQzUYUFRQXPAsUPT0YdpNsf/oHZKmmZrsOX+epnn2jmAGIBTZgUakY8jRrZxCJka+QokUIadUVQg==
|
integrity sha512-QhYhJ5y8tUG5SlmY3CSf9RBaa3EFbta28oarOyiwceHKmY80cMCafRI1YypT6CVDx/q91dbnSNQfWhs0cZPbBQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
buffer "4.9.1"
|
buffer "4.9.1"
|
||||||
events "1.1.1"
|
events "1.1.1"
|
||||||
|
@ -399,9 +399,9 @@ aws-sign2@~0.7.0:
|
||||||
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
|
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
|
||||||
|
|
||||||
aws4@^1.8.0:
|
aws4@^1.8.0:
|
||||||
version "1.9.1"
|
version "1.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e"
|
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2"
|
||||||
integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==
|
integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==
|
||||||
|
|
||||||
axios@^0.18.0:
|
axios@^0.18.0:
|
||||||
version "0.18.1"
|
version "0.18.1"
|
||||||
|
@ -814,12 +814,12 @@ cron-parser@1.1.0:
|
||||||
integrity sha1-B1uExFnBVejEgqtNVq/5na5YNS4=
|
integrity sha1-B1uExFnBVejEgqtNVq/5na5YNS4=
|
||||||
|
|
||||||
cron-parser@^2.11.0:
|
cron-parser@^2.11.0:
|
||||||
version "2.13.0"
|
version "2.15.0"
|
||||||
resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.13.0.tgz#6f930bb6f2931790d2a9eec83b3ec276e27a6725"
|
resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.15.0.tgz#04803cd51d8efcfcc6f83ac08e60f3f8c40c7ec5"
|
||||||
integrity sha512-UWeIpnRb0eyoWPVk+pD3TDpNx3KCFQeezO224oJIkktBrcW6RoAPOx5zIKprZGfk6vcYSmA8yQXItejSaDBhbQ==
|
integrity sha512-rMFkrQw8+oG5OuwjiXesup4KeIlEG/IU82YtG4xyAHbO5jhKmYaHPp/ZNhq9+7TjSJ65E3zV3kQPUbmXSff2/g==
|
||||||
dependencies:
|
dependencies:
|
||||||
is-nan "^1.2.1"
|
is-nan "^1.3.0"
|
||||||
moment-timezone "^0.5.25"
|
moment-timezone "^0.5.31"
|
||||||
|
|
||||||
cross-spawn@^6.0.5:
|
cross-spawn@^6.0.5:
|
||||||
version "6.0.5"
|
version "6.0.5"
|
||||||
|
@ -1627,9 +1627,9 @@ hosted-git-info@^2.1.4:
|
||||||
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
|
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
|
||||||
|
|
||||||
http-proxy@^1.17.0:
|
http-proxy@^1.17.0:
|
||||||
version "1.18.0"
|
version "1.18.1"
|
||||||
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a"
|
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
|
||||||
integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==
|
integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
eventemitter3 "^4.0.0"
|
eventemitter3 "^4.0.0"
|
||||||
follow-redirects "^1.0.0"
|
follow-redirects "^1.0.0"
|
||||||
|
@ -1745,9 +1745,9 @@ ioredis@4.9.5:
|
||||||
standard-as-callback "^2.0.1"
|
standard-as-callback "^2.0.1"
|
||||||
|
|
||||||
ioredis@^4.9.5:
|
ioredis@^4.9.5:
|
||||||
version "4.16.3"
|
version "4.17.1"
|
||||||
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.16.3.tgz#6a6b85830206fd98353b7ff8536521f17943be53"
|
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.17.1.tgz#06ef3d3b2cb96b7e6bc90a7b8839a33e743843ad"
|
||||||
integrity sha512-Ejvcs2yW19Vq8AipvbtfcX3Ig8XG9EAyFOvGbhI/Q1QoVOK9ZdgY092kdOyOWIYBnPHjfjMJhU9qhsnp0i0K1w==
|
integrity sha512-kfxkN/YO1dnyaoAGyNdH3my4A1eoGDy4QOfqn6o86fo4dTboxyxYVW0S0v/d3MkwCWlvSWhlwq6IJMY9BlWs6w==
|
||||||
dependencies:
|
dependencies:
|
||||||
cluster-key-slot "^1.1.0"
|
cluster-key-slot "^1.1.0"
|
||||||
debug "^4.1.1"
|
debug "^4.1.1"
|
||||||
|
@ -1822,7 +1822,7 @@ is-my-json-valid@^2.10.0:
|
||||||
jsonpointer "^4.0.0"
|
jsonpointer "^4.0.0"
|
||||||
xtend "^4.0.0"
|
xtend "^4.0.0"
|
||||||
|
|
||||||
is-nan@^1.2.1:
|
is-nan@^1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.0.tgz#85d1f5482f7051c2019f5673ccebdb06f3b0db03"
|
resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.0.tgz#85d1f5482f7051c2019f5673ccebdb06f3b0db03"
|
||||||
integrity sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ==
|
integrity sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ==
|
||||||
|
@ -2028,9 +2028,9 @@ js-tokens@^3.0.2:
|
||||||
integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
|
integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
|
||||||
|
|
||||||
js-yaml@3.x, js-yaml@^3.5.1, js-yaml@^3.7.0:
|
js-yaml@3.x, js-yaml@^3.5.1, js-yaml@^3.7.0:
|
||||||
version "3.13.1"
|
version "3.14.0"
|
||||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
|
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482"
|
||||||
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
|
integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==
|
||||||
dependencies:
|
dependencies:
|
||||||
argparse "^1.0.7"
|
argparse "^1.0.7"
|
||||||
esprima "^4.0.0"
|
esprima "^4.0.0"
|
||||||
|
@ -2425,9 +2425,9 @@ mime@^1.3.4:
|
||||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||||
|
|
||||||
mime@^2.2.0:
|
mime@^2.2.0:
|
||||||
version "2.4.5"
|
version "2.4.6"
|
||||||
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.5.tgz#d8de2ecb92982dedbb6541c9b6841d7f218ea009"
|
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1"
|
||||||
integrity sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w==
|
integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==
|
||||||
|
|
||||||
minimatch@0.3:
|
minimatch@0.3:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
|
@ -2523,17 +2523,17 @@ mocha@^2.3.3, mocha@^2.3.4:
|
||||||
supports-color "1.2.0"
|
supports-color "1.2.0"
|
||||||
to-iso-string "0.0.2"
|
to-iso-string "0.0.2"
|
||||||
|
|
||||||
moment-timezone@^0.5.25:
|
moment-timezone@^0.5.31:
|
||||||
version "0.5.28"
|
version "0.5.31"
|
||||||
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.28.tgz#f093d789d091ed7b055d82aa81a82467f72e4338"
|
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.31.tgz#9c40d8c5026f0c7ab46eda3d63e49c155148de05"
|
||||||
integrity sha512-TDJkZvAyKIVWg5EtVqRzU97w0Rb0YVbfpqyjgu6GwXCAohVRqwZjf4fOzDE6p1Ch98Sro/8hQQi65WDXW5STPw==
|
integrity sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==
|
||||||
dependencies:
|
dependencies:
|
||||||
moment ">= 2.9.0"
|
moment ">= 2.9.0"
|
||||||
|
|
||||||
"moment@>= 2.9.0":
|
"moment@>= 2.9.0":
|
||||||
version "2.25.3"
|
version "2.26.0"
|
||||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.25.3.tgz#252ff41319cf41e47761a1a88cab30edfe9808c0"
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a"
|
||||||
integrity sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg==
|
integrity sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==
|
||||||
|
|
||||||
ms@0.7.1:
|
ms@0.7.1:
|
||||||
version "0.7.1"
|
version "0.7.1"
|
||||||
|
@ -3287,9 +3287,9 @@ source-map@^0.6.1:
|
||||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||||
|
|
||||||
spdx-correct@^3.0.0:
|
spdx-correct@^3.0.0:
|
||||||
version "3.1.0"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4"
|
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
|
||||||
integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==
|
integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
|
||||||
dependencies:
|
dependencies:
|
||||||
spdx-expression-parse "^3.0.0"
|
spdx-expression-parse "^3.0.0"
|
||||||
spdx-license-ids "^3.0.0"
|
spdx-license-ids "^3.0.0"
|
||||||
|
@ -3640,9 +3640,9 @@ uc.micro@^1.0.0, uc.micro@^1.0.1:
|
||||||
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
|
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
|
||||||
|
|
||||||
uglify-js@^3.1.4:
|
uglify-js@^3.1.4:
|
||||||
version "3.9.3"
|
version "3.9.4"
|
||||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.9.3.tgz#4a285d1658b8a2ebaef9e51366b3a0f7acd79ec2"
|
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.9.4.tgz#867402377e043c1fc7b102253a22b64e5862401b"
|
||||||
integrity sha512-r5ImcL6QyzQGVimQoov3aL2ZScywrOgBXGndbWrdehKoSvGe/RmiE5Jpw/v+GvxODt6l2tpBXwA7n+qZVlHBMA==
|
integrity sha512-8RZBJq5smLOa7KslsNsVcSH+KOXf1uDU8yqLeNuVKwmT0T3FA0ZoXlinQfRad7SDcbZZRZE4ov+2v71EnxNyCA==
|
||||||
dependencies:
|
dependencies:
|
||||||
commander "~2.20.3"
|
commander "~2.20.3"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue