baqend
Version:
Baqend JavaScript SDK
1,392 lines (1,222 loc) • 56.9 kB
JavaScript
if (typeof module !== 'undefined') {
require('./node');
}
describe('Test file', function () {
// Skip IE9 and IE11 multiple file uploads in one session crashes the ie
if ((typeof Blob === 'undefined' && typeof Buffer === 'undefined') || helper.isIE11) {
return;
}
this.timeout(20 * 1000);
var flames, emf, rootDb;
var dataBase64 = 'data:image/gif;base64,R0lGODlhDAAeALMAAGUJC/SHGvJZI18NDP347fifGeyqlfqqFdjHx/FhIu98HuLY1/NwHvN5G2AMDP///yH5BAAAAAAALAAAAAAMAB4AAARM8MlJ63SWOpzf3t3HVSKolab0qel6mS7LxR6I0OuCw2k9967dj+cYvFAUAJKEGnkKh0OJQggEHgSaRNHoPBheSsJrEIQf5nD6zKZEAAA7';
var dataSvg = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201%201%22%3E%3Cpath%20d%3D%22m0%2C0v1h1V0%22%2F%3E%3C%2Fsvg%3E';
var dataSvgTotal = 86;
var svgBase64 = 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxIDEiPjxwYXRoIGQ9Im0wLDB2MWgxVjAiLz48L3N2Zz4=';
var html = '<html><head><title>Hallo World</title></head><body>Hallo World</body></html>';
var json;
var arrayBuffer;
before(function () {
emf = new DB.EntityManagerFactory(env.TEST_SERVER);
return Promise.all([
helper.asset('flames.png', 'blob'),
helper.asset('rocket.jpg'),
helper.asset('flames.png', 'arraybuffer'),
helper.asset('test.json', 'text'),
]).then(function (data) {
flames = data[0];
arrayBuffer = data[2];
json = JSON.parse(data[3]);
}).then(function () {
return emf.createEntityManager().ready().then(function (em) {
return em.User.login('root', 'root').then(function () {
rootDb = em;
});
});
});
});
it('parses E-Tags correctly', function () {
var { parseETag } = DB.binding.File;
expect(parseETag()).to.be.null;
expect(parseETag(false)).to.be.null;
expect(parseETag(null)).to.be.null;
expect(parseETag(undefined)).to.be.null;
expect(parseETag('"hello"')).to.eql('hello');
expect(parseETag('"12345"')).to.eql('12345');
expect(parseETag('\'hello\'')).to.eql('hello');
expect(parseETag('\'12345\'')).to.eql('12345');
expect(parseETag('w/"hello"')).to.eql('hello');
expect(parseETag('w/"12345"')).to.eql('12345');
expect(parseETag('w/\'hello\'')).to.eql('hello');
expect(parseETag('w/\'12345\'')).to.eql('12345');
expect(parseETag('W/"hello"')).to.eql('hello');
expect(parseETag('W/"12345"')).to.eql('12345');
expect(parseETag('W/\'hello\'')).to.eql('hello');
expect(parseETag('W/\'12345\'')).to.eql('12345');
});
describe('object', function () {
it('should initialize with default parameters', function () {
var file = new rootDb.File();
expect(file.id).eql(`/file/www/${file.key}`);
expect(file.key).is.not.undefined;
expect(file.bucket).eql('www');
expect(file.parent).eql('/www');
expect(file.name).eql(file.key);
expect(function () {
file.acl;
}).throw('is not available');
expect(function () {
file.lastModified;
}).throw('is not available');
expect(function () {
file.eTag;
}).throw('is not available');
expect(function () {
file.mimeType;
}).throw('is not available');
expect(function () {
file.toJSON();
}).throw('is not available');
});
it('should initialize with string parameter', function () {
var file = new rootDb.File('/file/test/myFile.txt');
expect(file.id).eql('/file/test/myFile.txt');
expect(file.key).eql('myFile.txt');
expect(file.bucket).eql('test');
expect(file.parent).eql('/test');
expect(file.name).eql('myFile.txt');
expect(function () {
file.acl;
}).throw('is not available');
expect(function () {
file.lastModified;
}).throw('is not available');
expect(function () {
file.eTag;
}).throw('is not available');
expect(function () {
file.mimeType;
}).throw('is not available');
});
it('should initialize with deep path parameter', function () {
var file = new rootDb.File('/file/test/my/deep/path/myFile.txt');
expect(file.id).eql('/file/test/my/deep/path/myFile.txt');
expect(file.path).eql('/test/my/deep/path/myFile.txt');
expect(file.key).eql('my/deep/path/myFile.txt');
expect(file.bucket).eql('test');
expect(file.parent).eql('/test/my/deep/path');
expect(file.name).eql('myFile.txt');
});
it('should initialize with actual path parameter', function () {
var file = new rootDb.File({ path: 'test/my/deep/path/myFile.txt' });
expect(file.id).eql('/file/test/my/deep/path/myFile.txt');
expect(file.key).eql('my/deep/path/myFile.txt');
expect(file.bucket).eql('test');
expect(file.parent).eql('/test/my/deep/path');
expect(file.name).eql('myFile.txt');
});
it('should initialize with parent parameter', function () {
var file = new rootDb.File({ parent: '/test/my/deep/path/', name: 'myFile.txt' });
expect(file.id).eql('/file/test/my/deep/path/myFile.txt');
expect(file.key).eql('my/deep/path/myFile.txt');
expect(file.bucket).eql('test');
expect(file.parent).eql('/test/my/deep/path');
expect(file.name).eql('myFile.txt');
});
it('should reject invalid path', function () {
expect(function () {
new rootDb.File('/file/myFile.txt');
}).throw('Invalid file reference');
expect(function () {
new rootDb.File('/test/bucket/myFile.txt');
}).throw('Invalid file reference');
});
it('should initialize with blob/buffer parameters', function () {
var file;
if (helper.isNode) {
file = new rootDb.File({ name: 'test.png', data: flames, mimeType: 'image/png' });
} else {
file = new rootDb.File({ name: 'test.png', data: flames });
}
expect(file.id).eql(`/file/www/${file.key}`);
expect(file.key).eql('test.png');
expect(file.bucket).eql('www');
expect(file.parent).eql('/www');
expect(file.name).eql('test.png');
expect(file.acl).is.not.undefined;
expect(file.acl.isPublicReadAllowed()).be.true;
expect(file.acl.isPublicWriteAllowed()).be.true;
expect(file.lastModified).be.undefined;
expect(file.eTag).be.undefined;
expect(file.mimeType).eql('image/png');
});
if (!helper.isNode) {
it('should initialize with file parameter', function () {
return helper.asset('flames.png').then(function (f) {
f.name = 'file.png';
f.lastModifiedDate = new Date();
var file = new rootDb.File({ data: f });
expect(file.id).eql(`/file/www/${file.key}`);
expect(file.key).eql('file.png');
expect(file.bucket).eql('www');
expect(file.parent).eql('/www');
expect(file.name).eql('file.png');
expect(file.acl).is.not.undefined;
expect(file.acl.isPublicReadAllowed()).be.true;
expect(file.acl.isPublicWriteAllowed()).be.true;
expect(file.lastModified).be.undefined;
expect(file.eTag).be.undefined;
expect(file.mimeType).eql('image/png');
});
});
}
if (helper.isNode) {
it('should initialize with stream parameters', function () {
var fs = require('fs');
var file = new rootDb.File({
name: 'test.png',
data: fs.createReadStream('spec/assets/flames.png'),
type: 'stream',
mimeType: 'image/png',
});
expect(file.id).eql(`/file/www/${file.key}`);
expect(file.key).eql('test.png');
expect(file.bucket).eql('www');
expect(file.parent).eql('/www');
expect(file.name).eql('test.png');
expect(file.acl).is.not.undefined;
expect(file.acl.isPublicReadAllowed()).be.true;
expect(file.acl.isPublicWriteAllowed()).be.true;
expect(file.lastModified).be.undefined;
expect(file.eTag).be.undefined;
expect(file.mimeType).eql('image/png');
});
}
it('should initialize with base64 parameter', function () {
var file = new rootDb.File({ data: svgBase64, type: 'base64', mimeType: 'image/svg+xml' });
expect(file.id).eql(`/file/www/${file.key}`);
expect(file.key).is.not.undefined;
expect(file.bucket).eql('www');
expect(file.parent).eql('/www');
expect(file.name).eql(file.key);
expect(file.acl).is.not.undefined;
expect(file.acl.isPublicReadAllowed()).be.true;
expect(file.acl.isPublicWriteAllowed()).be.true;
expect(file.lastModified).be.undefined;
expect(file.eTag).be.undefined;
expect(file.mimeType).eql('image/svg+xml');
});
it('should initialize with data-url base64 parameter', function () {
var file = new rootDb.File({ data: dataBase64, type: 'data-url' });
expect(file.id).eql(`/file/www/${file.key}`);
expect(file.key).is.not.undefined;
expect(file.bucket).eql('www');
expect(file.parent).eql('/www');
expect(file.name).eql(file.key);
expect(file.acl).is.not.undefined;
expect(file.acl.isPublicReadAllowed()).be.true;
expect(file.acl.isPublicWriteAllowed()).be.true;
expect(file.lastModified).be.undefined;
expect(file.eTag).be.undefined;
expect(file.mimeType).eql('image/gif');
});
it('should initialize with data-url parameter', function () {
var file = new rootDb.File({ data: dataSvg, type: 'data-url' });
expect(file.id).eql(`/file/www/${file.key}`);
expect(file.key).is.not.undefined;
expect(file.bucket).eql('www');
expect(file.parent).eql('/www');
expect(file.name).eql(file.key);
expect(file.acl).is.not.undefined;
expect(file.acl.isPublicReadAllowed()).be.true;
expect(file.acl.isPublicWriteAllowed()).be.true;
expect(file.lastModified).be.undefined;
expect(file.eTag).be.undefined;
expect(file.mimeType).eql('image/svg+xml');
});
it('should initialize with all parameters', function () {
return helper.asset('flames.png').then(function (f) {
f.name = 'file.png';
f.lastModifiedDate = new Date();
var acl = new rootDb.Acl();
acl.allowReadAccess(rootDb.User.me);
acl.allowWriteAccess(rootDb.User.me);
var date = new Date('2016-01-01');
var file = new rootDb.File({
data: f,
type: 'blob',
name: 'my.png',
parent: '/www/test',
mimeType: 'text/html',
lastModified: date,
acl: acl,
eTag: '827598375',
});
expect(file.id).eql('/file/www/test/my.png');
expect(file.key).eql('test/my.png');
expect(file.bucket).eql('www');
expect(file.parent).eql('/www/test');
expect(file.name).eql('my.png');
expect(file.acl).eql(acl);
expect(file.lastModified).gte(date);
expect(file.lastModified).lte(date);
expect(file.eTag).eql('827598375');
expect(file.mimeType).eql('text/html');
});
});
it('should initialize with folder and name parameters', function () {
var file = new rootDb.File({ parent: '/testfolder', name: 'test.png' });
expect(file.id).eql('/file/testfolder/test.png');
expect(file.key).eql('test.png');
expect(file.bucket).eql('testfolder');
expect(file.parent).eql('/testfolder');
expect(file.name).eql('test.png');
});
it('should initialize with folder and name parameters', function () {
var file = new rootDb.File({ parent: 'testfolder', name: 'test.png' });
expect(file.id).eql('/file/testfolder/test.png');
expect(file.key).eql('test.png');
expect(file.bucket).eql('testfolder');
expect(file.parent).eql('/testfolder');
expect(file.name).eql('test.png');
});
it('should initialize with folder and name parameters', function () {
var file = new rootDb.File({ parent: '/testfolder/', name: 'test.png' });
expect(file.id).eql('/file/testfolder/test.png');
expect(file.key).eql('test.png');
expect(file.bucket).eql('testfolder');
expect(file.parent).eql('/testfolder');
expect(file.name).eql('test.png');
});
it('should initialize with deep folder', function () {
var file = new rootDb.File({ parent: '/deep/test/folder/', name: 'test.png' });
expect(file.id).eql('/file/deep/test/folder/test.png');
expect(file.key).eql('test/folder/test.png');
expect(file.bucket).eql('deep');
expect(file.parent).eql('/deep/test/folder');
expect(file.name).eql('test.png');
});
it('should reject invalid folder', function () {
expect(function () {
new rootDb.File({ parent: '/', name: 'test.png' });
}).throw('Invalid parent name');
var file = new rootDb.File({ parent: '', name: 'test.png' });
expect(file.parent).eql('/www');
});
it('should reject invalid file name', function () {
expect(function () {
new rootDb.File({ parent: '/www', name: '/test.png' });
}).throw('Invalid path');
var file = new rootDb.File({ parent: '/www', name: '' });
expect(file.name).not.eql('');
});
it('should serialize all properties to json', function () {
var acl = new rootDb.Acl();
acl.allowReadAccess(rootDb.User.me);
acl.allowWriteAccess(rootDb.User.me);
var date = new Date('2016-01-01');
var file = new rootDb.File({
data: dataBase64,
type: 'data-url',
name: 'my.png',
parent: '/www/test',
mimeType: 'text/html',
createdAt: date,
lastModified: date,
acl: acl,
eTag: '827598375',
size: 12345,
headers: {
'test-header': 'value',
},
});
var jsonOfFile = file.toJSON();
expect(jsonOfFile).eql({
id: '/file/www/test/my.png',
mimeType: 'text/html',
createdAt: date.toISOString(),
lastModified: date.toISOString(),
size: 12345,
acl: {
read: {
'/db/User/1': 'allow',
},
write: {
'/db/User/1': 'allow',
},
},
eTag: '827598375',
headers: {
'test-header': 'value',
},
});
expect(jsonOfFile.data).is.undefined;
expect(jsonOfFile.type).is.undefined;
});
it('should deserialize all properties from json', function () {
var acl = new rootDb.Acl();
acl.allowReadAccess(rootDb.User.me);
acl.allowWriteAccess(rootDb.User.me);
var date = new Date('2016-01-01');
var file = rootDb.File.fromJSON({
id: '/file/www/test/my.png',
mimeType: 'text/html',
createdAt: date.toISOString(),
lastModified: date.toISOString(),
size: 12345,
acl: {
read: {
'/db/User/1': 'allow',
},
write: {
'/db/User/1': 'allow',
},
},
eTag: '827598375',
headers: {
'test-header': 'value',
},
});
expect(file.id).eql('/file/www/test/my.png');
expect(file.key).eql('test/my.png');
expect(file.bucket).eql('www');
expect(file.parent).eql('/www/test');
expect(file.name).eql('my.png');
expect(file.acl).eql(acl);
expect(file.lastModified).gte(date);
expect(file.lastModified).lte(date);
expect(file.createdAt).gte(date);
expect(file.createdAt).lte(date);
expect(file.eTag).eql('827598375');
expect(file.mimeType).eql('text/html');
expect(file.headers).eql({ 'test-header': 'value' });
});
it('should not deserialize json to a wrong file instance', function () {
var date = new Date('2016-01-01');
var file = new rootDb.File('/file/www/test/other.png');
expect(function () {
file.fromJSON({
id: '/file/www/test/my.png',
mimeType: 'text/html',
createdAt: date.toISOString(),
lastModified: date.toISOString(),
contentLength: 12345,
acl: {},
eTag: '827598375',
});
}).throws('does not match the given json id');
});
});
describe('url', function () {
var anonymousDB,
uploadFile;
before(function () {
anonymousDB = emf.createEntityManager();
return anonymousDB.ready().then(function () {
var acl = new DB.Acl()
.allowReadAccess(rootDb.User.me)
.allowWriteAccess(rootDb.User.me);
return rootDb.File.saveMetadata('private_bucket', {
load: new DB.util.Permission().allowAccess(rootDb.User.me),
insert: new DB.util.Permission().allowAccess(rootDb.User.me),
update: new DB.util.Permission().allowAccess(rootDb.User.me),
delete: new DB.util.Permission().allowAccess(rootDb.User.me),
query: new DB.util.Permission().allowAccess(rootDb.User.me),
}).then(function () {
uploadFile = new rootDb.File({ parent: 'private_bucket', data: flames, acl: acl });
return uploadFile.upload();
});
});
});
it('should not contains credentials for anonymous user', async function () {
var file = new anonymousDB.File({ name: 'public.png' });
expect(await file.createURL()).be.eql(`${env.TEST_SERVER}/file/www/public.png`);
});
it('should not contains credentials for anonymous user in none www bucket', async function () {
var file = new anonymousDB.File({ parent: '/testfolder/', name: 'private.png' });
expect(await file.createURL()).be.eql(`${env.TEST_SERVER}/file/testfolder/private.png`);
});
it('should not contains credentials for the www bucket', async function () {
var file = new rootDb.File({ name: 'public.png' });
expect(await file.createURL()).be.eql(`${env.TEST_SERVER}/file/www/public.png`);
});
it('should contains credentials for none www bucket', async function () {
var file = new rootDb.File({ parent: '/testfolder/', name: 'private.png' });
expect(await file.createURL()).be.string(`${env.TEST_SERVER}/file/testfolder/private.png?BAT=`);
});
it('should provide no access for none authorized user', async function () {
var file = new anonymousDB.File(uploadFile.id);
var url = await file.createURL();
try {
await helper.req(url);
expect.fail();
} catch {}
});
it('should provide access for authorized user', async function () {
var file = new rootDb.File(uploadFile.id);
var url = await file.createURL()
var data = await helper.req(url);
expectSameBlob(flames, bufferToBlob(data, uploadFile.mimeType));
});
});
describe('upload', function () {
before(function () {
return rootDb.File.loadMetadata('www').then(function (acls) {
acls.update = new rootDb.util.Permission().allowAccess(rootDb.User.me);
acls.insert = new rootDb.util.Permission().allowAccess(rootDb.User.me);
return rootDb.File.saveMetadata('www', acls);
});
});
it('should maintain createdAt', function () {
var file = new rootDb.File({ data: flames });
var creationDate;
return file.upload().then(function () {
creationDate = file.lastModified;
expect(file.createdAt).is.not.undefined;
expect(file.createdAt).eql(creationDate);
return helper.sleep(2000);
}).then(function () {
return file.upload({ data: dataSvg, type: 'data-url' });
}).then(function () {
expect(file.createdAt.getTime()).equal(creationDate.getTime());
expect(file.createdAt.getTime()).not.equal(file.lastModified.getTime());
});
});
it('should denied for anonymous', async function () {
const db = await emf.createEntityManager().ready();
const file = new db.File({ data: flames });
try {
await file.upload();
expect.fail();
} catch (e) {
expect(e.message).to.contain('insert permissions are required');
}
});
it('should handle conditional update', function () {
var file = new rootDb.File({ data: flames });
return file.upload().then(function () {
return file.upload({ data: dataSvg, type: 'data-url' });
}).then(function () {
expect(file.mimeType).string('image/svg+xml');
});
});
it('should reject stale insertion', async function () {
var file = new rootDb.File({ data: flames });
await file.upload();
try {
await new rootDb.File(file.id).upload({ data: flames });
expect.fail();
} catch (e) {
expect(e.message).to.contain(`Unique index violation. Another object already exists with the same value of the newly created/modified object FileRef: ${file.id}`);
}
});
it('should reject stale update', async function () {
var file = new rootDb.File({ data: flames });
await file.upload();
await new rootDb.File(file.id).upload({ data: dataSvg, type: 'data-url', force: true });
try {
await file.upload({ data: dataBase64, type: 'data-url' });
expect.fail();
} catch (e) {
expect(e.message).to.contain('out of date');
}
});
it('should allow stale update with force', function () {
var file = new rootDb.File({ data: flames });
return file.upload().then(function () {
return new rootDb.File(file.id).upload({ data: dataSvg, type: 'data-url', force: true });
}).then(function () {
return file.upload({ data: dataBase64, type: 'data-url', force: true });
}).then(function () {
expect(file.mimeType).eql('image/gif');
});
});
it('should upload blob/buffer format', function () {
var file = new rootDb.File({ data: flames });
return file.upload().then(function () {
expect(file.eTag).is.not.undefined;
expect(file.lastModified).gt(new Date(Date.now() - 5 * 60 * 1000));
expect(file.lastModified).lt(new Date(Date.now() + 5 * 60 * 1000));
expect(file.mimeType).eql('image/png');
expect(file.size).eql(flames.size || flames.length);
});
});
if (helper.isNode) {
it('should upload stream format', function () {
var fs = require('fs');
var file = new rootDb.File({
data: fs.createReadStream('spec/assets/flames.png'),
type: 'stream',
mimeType: 'image/png',
size: fs.statSync('spec/assets/flames.png').size,
});
return file.upload().then(function () {
expect(file.eTag).is.not.undefined;
expect(file.lastModified).gt(new Date(Date.now() - 5 * 60 * 1000));
expect(file.lastModified).lt(new Date(Date.now() + 5 * 60 * 1000));
expect(file.mimeType).eql('image/png');
});
});
it('should reject stream format', async function () {
var fs = require('fs');
var file = new rootDb.File({
data: fs.createReadStream('spec/assets/flames.png'),
type: 'stream',
mimeType: 'image/png',
});
try {
await file.upload();
expect.fail();
} catch {}
});
}
it('should upload json format', function () {
var file = new rootDb.File({ data: json });
return file.upload().then(function () {
expect(file.mimeType.toLowerCase()).eql('application/json; charset=utf-8');
});
});
it('should upload text format', function () {
var file = new rootDb.File({ data: html, mimeType: 'text/html;charset=utf-8' });
return file.upload().then(function () {
expect(file.mimeType.toLowerCase()).eql('text/html; charset=utf-8');
});
});
it('should upload base64 format', function () {
var file = new rootDb.File({ data: svgBase64, type: 'base64', mimeType: 'image/svg+xml' });
return file.upload().then(function () {
expect(file.mimeType).string('image/svg+xml');
});
});
it('should upload data-url base64 format', function () {
var file = new rootDb.File({ data: dataBase64, type: 'data-url' });
return file.upload().then(function () {
expect(file.mimeType).eql('image/gif');
});
});
it('should upload data-url format', function () {
var file = new rootDb.File({ data: dataSvg, type: 'data-url' });
return file.upload().then(function () {
expect(file.mimeType).string('image/svg+xml');
});
});
it('should upload arraybuffer format', function () {
var file = new rootDb.File({ data: arrayBuffer, mimeType: 'image/png' });
return file.upload().then(function () {
expect(file.mimeType).eql('image/png');
});
});
it('should upload auto detect data-url format', function () {
var file = new rootDb.File({ data: dataSvg });
return file.upload().then(function () {
expect(file.mimeType).string('image/svg+xml');
return file.download({ type: 'base64' });
}).then(function (data) {
expect(file.mimeType).string('image/svg+xml');
expect(data).eql(svgBase64);
});
});
if (!helper.isNode) {
it('should have a progress callback which gets called', function () {
var calls = 0;
var file = new rootDb.File({ data: dataSvg });
var cb = function (event) {
expect(event.lengthComputable).to.be.true;
expect(event.loaded).to.be.within(0, dataSvgTotal);
expect(event.total).to.equal(dataSvgTotal);
calls += 1;
};
return file.upload({ progress: cb }).then(function () {
expect(calls).to.be.above(0);
});
});
}
});
describe('download', function () {
var pngFile,
jsonFile,
htmlFile,
gifFile,
svgFile;
before(function () {
pngFile = new rootDb.File({ data: flames });
jsonFile = new rootDb.File({ data: json, mimeType: 'application/json' });
htmlFile = new rootDb.File({ data: html, mimeType: 'text/html;charset=utf-8' });
gifFile = new rootDb.File({ data: dataBase64, type: 'data-url' });
svgFile = new rootDb.File({ data: dataSvg, type: 'data-url' });
return Promise.all([
pngFile.upload(),
jsonFile.upload(),
htmlFile.upload(),
gifFile.upload(),
svgFile.upload(),
]);
});
it('should load default type with createdAt', async function () {
// load the system default binary representation
var fileBinary = await helper.asset('flames.png');
var file = new rootDb.File({ data: fileBinary });
var creationDate;
var loadedFile;
await file.upload();
creationDate = file.lastModified;
expect(file.createdAt.getTime()).equal(creationDate.getTime());
loadedFile = new rootDb.File(file.id);
const data = await loadedFile.download();
expect(data).instanceof(helper.isNode ? Buffer : Blob);
expect(loadedFile.createdAt.getTime()).equal(creationDate.getTime());
expectSameBlob(fileBinary, data);
});
it('should stored under specified name', async function () {
var file = new rootDb.File(pngFile.id);
var data = await file.download();
expect(data).instanceof(helper.isNode ? Buffer : Blob);
expect(file.eTag).eql(pngFile.eTag);
expect(file.lastModified).gt(new Date(Date.now() - 5 * 60 * 1000));
expect(file.lastModified).lt(new Date(Date.now() + 5 * 60 * 1000));
expect(file.mimeType).eql('image/png');
expect(file.size).eql(pngFile.size);
expect(file.acl.isPublicReadAllowed()).be.true;
expect(file.acl.isPublicWriteAllowed()).be.true;
});
it('should be downloadable as anonymous', async function () {
var db = await emf.createEntityManager().ready();
var file = new db.File(pngFile.id);
var data = await file.download();
expect(data).instanceof(helper.isNode ? Buffer : Blob);
expect(file.eTag).eql(pngFile.eTag);
expect(file.lastModified).gt(new Date(Date.now() - 5 * 60 * 1000));
expect(file.lastModified).lt(new Date(Date.now() + 5 * 60 * 1000));
expect(file.mimeType).eql('image/png');
expect(file.size).eql(pngFile.size);
expect(file.acl.isPublicReadAllowed()).be.true;
expect(file.acl.isPublicWriteAllowed()).be.true;
});
it('should download blob/buffer format', function () {
var file = new rootDb.File(pngFile.id);
return file.download({ type: 'blob' }).then(function (data) {
expect(file.mimeType.toLowerCase()).eql('image/png');
expectSameBlob(flames, data);
});
});
it('should allow in URI reserved characters in signed url', async function () {
var acl = new DB.Acl()
.allowReadAccess(rootDb.User.me)
.allowWriteAccess(rootDb.User.me);
await rootDb.File.saveMetadata('testfolder', {})
var file = new rootDb.File({
name: `;,/?:@&=+$#${rootDb.util.uuid()}.png`, data: flames, acl: acl, parent: '/testfolder',
});
var file2 = await file.upload();
var url = await file2.createURL();
var blob = await helper.req(url);
expectSameBlob(flames, bufferToBlob(blob, flames.type));
});
it('should allow in URI unreserved characters in signed url', function () {
var acl = new DB.Acl()
.allowReadAccess(rootDb.User.me)
.allowWriteAccess(rootDb.User.me);
return rootDb.File.saveMetadata('testfolder', {})
.then(function () {
var file = new rootDb.File({
name: `-_.!~*'()${rootDb.util.uuid()}.png`, data: flames, acl: acl, parent: '/testfolder',
});
return file.upload();
})
.then(function (file) { return file.createURL(); })
.then(function (url) {
return helper.req(url);
});
});
it('should allow in alphanumeric characters + spaces in signed url', function () {
var acl = new DB.Acl()
.allowReadAccess(rootDb.User.me)
.allowWriteAccess(rootDb.User.me);
return rootDb.File.saveMetadata('testfolder', {})
.then(function () {
var file = new rootDb.File({
name: `ABC abc 123${rootDb.util.uuid()}.png`, data: flames, acl: acl, parent: '/testfolder',
});
return file.upload();
})
.then(function (file) { return file.createURL(); })
.then(function (url) {
return helper.req(url);
});
});
if (helper.isNode) {
it('should upload stream format', async function () {
var file = new rootDb.File(pngFile.id);
var stream = await file.download({ type: 'stream' });
expect(file.mimeType.toLowerCase()).eql('image/png');
var data = await new Promise(function (resolve) {
var chunks = [];
stream.on('data', function (chunk) {
chunks.push(chunk);
});
stream.on('end', function () {
var buffer = Buffer.concat(chunks)
resolve(bufferToBlob(buffer, file.mimeType))
});
});
expectSameBlob(flames, data);
});
}
it('should download json format', async function () {
var file = new rootDb.File(jsonFile.id);
var data = await file.download({ type: 'json' });
expect(file.mimeType.toLowerCase()).eql('application/json;charset=utf-8');
expect(data).eql(json);
});
it('should download text format', function () {
var file = new rootDb.File(htmlFile.id);
return file.download({ type: 'text' }).then(function (data) {
expect(file.mimeType.toLowerCase()).eql('text/html;charset=utf-8');
expect(data).eql(html);
});
});
it('should download base64 format', function () {
var file = new rootDb.File(svgFile.id);
return file.download({ type: 'base64' }).then(function (data) {
expect(file.mimeType).string('image/svg+xml');
expect(data).eql(svgBase64);
});
});
it('should download data-url base64 format', function () {
var file = new rootDb.File(gifFile.id);
return file.download({ type: 'data-url' }).then(function (data) {
expect(file.mimeType).eql('image/gif');
expect(data).eql(dataBase64);
});
});
it('should download data-url format', function () {
var file = new rootDb.File(svgFile.id);
return file.download({ type: 'data-url' }).then(function (data) {
expect(file.mimeType).string('image/svg+xml');
expect(data).string(svgBase64);
expect(data).string('data:image/svg+xml');
});
});
it('should download arraybuffer format', function () {
var file = new rootDb.File(pngFile.id);
return file.download({ type: 'arraybuffer' }).then(function (data) {
expect(file.mimeType).eql('image/png');
expect(data.byteLength).eql(arrayBuffer.byteLength);
});
});
});
describe('metadata', function () {
var bucket = 'metadataTest';
var pngFile;
var jsonFile;
before(function () {
var cHeads = {
hello: 'World',
schmukey: 'Schmu',
};
pngFile = new rootDb.File({ parent: bucket, data: flames, headers: cHeads });
jsonFile = new rootDb.File({ data: json, mimeType: 'application/json', headers: cHeads });
return rootDb.File.saveMetadata(bucket, {}).then(function () {
return Promise.all([
pngFile.upload(),
jsonFile.upload(),
]);
});
});
it('should be loaded', function () {
var file = new rootDb.File(pngFile.id);
return file.loadMetadata().then(function () {
expect(file !== pngFile).to.be.true;
expect(file.eTag).eql(pngFile.eTag);
expect(file.lastModified).gt(new Date(Date.now() - 5 * 60 * 1000));
expect(file.lastModified).lt(new Date(Date.now() + 5 * 60 * 1000));
expect(file.createdAt).gt(new Date(Date.now() - 5 * 60 * 1000));
expect(file.createdAt).lt(new Date(Date.now() + 5 * 60 * 1000));
expect(file.mimeType).eql('image/png');
expect(file.size).eql(pngFile.size);
expect(file.headers.hello).eql('World');
expect(file.headers.schmukey).eql('Schmu');
expect(file.acl.isPublicReadAllowed()).be.true;
expect(file.acl.isPublicWriteAllowed()).be.true;
});
});
it('should be loaded by download', function () {
var file = new rootDb.File(jsonFile.id);
return file.download().then(function () {
expect(file !== jsonFile).to.be.true;
expect(file.eTag).not.contains('--gzip');
expect(file.eTag).eql(jsonFile.eTag);
expect(file.lastModified).gt(new Date(Date.now() - 5 * 60 * 1000));
expect(file.lastModified).lt(new Date(Date.now() + 5 * 60 * 1000));
expect(file.createdAt).gt(new Date(Date.now() - 5 * 60 * 1000));
expect(file.createdAt).lt(new Date(Date.now() + 5 * 60 * 1000));
expect(file.mimeType).eql('application/json;charset=utf-8');
expect(file.size).eql(jsonFile.size);
expect(file.headers.hello).eql('World');
expect(file.headers.schmukey).eql('Schmu');
expect(file.acl.isPublicReadAllowed()).be.true;
expect(file.acl.isPublicWriteAllowed()).be.true;
});
});
it('should be updated', function () {
var testAcls = new rootDb.Acl()
.allowReadAccess(rootDb.User.me)
.allowWriteAccess(rootDb.User.me);
var file = new rootDb.File(pngFile.id);
var creationDate;
return file.loadMetadata().then(function () {
creationDate = file.createdAt;
file.acl.allowReadAccess(rootDb.User.me)
.allowWriteAccess(rootDb.User.me);
file.headers.hello = 'No';
file.headers.schmu = 'SchmuSchmu';
return helper.sleep(2000);
}).then(function () {
return file.saveMetadata();
}).then(function () {
expect(file.acl).eql(testAcls);
expect(file.createdAt.getTime()).equal(creationDate.getTime());
expect(file.createdAt.getTime()).not.equal(file.lastModified.getTime());
expect(file.headers.hello).equal('No');
expect(file.headers.schmu).equal('SchmuSchmu');
});
});
it('should allow file acls in www bucket', function () {
var testAcls = new rootDb.Acl()
.allowReadAccess(rootDb.User.me)
.allowWriteAccess(rootDb.User.me);
var file = new rootDb.File(jsonFile.id);
return file.loadMetadata().then(function () {
file.acl.allowReadAccess(rootDb.User.me)
.allowWriteAccess(rootDb.User.me);
return file.saveMetadata();
}).then(function () {
expect(file.acl).eql(testAcls);
});
});
});
describe('delete', function () {
var uploadFile;
var fileName;
before(function () {
fileName = `test/${rootDb.util.uuid()}`;
});
beforeEach(function () {
uploadFile = new rootDb.File({ name: fileName, data: flames });
return uploadFile.upload({ force: true });
});
it('should remove file', function () {
return uploadFile.delete().then(function () {
var file = new rootDb.File(uploadFile.id);
return file.download();
}).then(function (data) {
expect(data).be.null;
});
});
it('should remove a removed file', function () {
var parent = new rootDb.File(`/file${uploadFile.parent}/`);
expect(parent.name).be.equal('test/');
return parent.delete().then(function (files) {
expect(files).length(1);
expect(files[0].id).equal(uploadFile.id);
var file = new rootDb.File(uploadFile.id);
return file.download();
}).then(function (data) {
expect(data).be.null;
});
});
it('should remove a removed file', function () {
new rootDb.File({ name: 'unknown' });
return uploadFile.delete();
});
it('should reject a stale deletion', async function () {
var file = new rootDb.File({ name: fileName, data: dataSvg, type: 'data-url' });
await file.upload({ force: true });
try {
await uploadFile.delete();
expect.fail();
} catch (e) {
expect(e.message).to.contain('is out of date');
}
});
it('should remove a stale deletion with force', function () {
var file = new rootDb.File({ name: fileName, data: dataSvg, type: 'data-url' });
return file.upload({ force: true }).then(function () {
return uploadFile.delete({ force: true });
});
});
});
describe('acl', function () {
function createUserDb() {
var em = emf.createEntityManager();
return em.ready(function () {
return em.User.register(helper.makeLogin(), 'secret');
}).then(function () {
return em;
});
}
var db1,
db2,
db3;
before(function () {
return Promise.all([
createUserDb(),
createUserDb(),
createUserDb(),
]).then(function (dbs) {
db1 = dbs[0];
db2 = dbs[1];
db3 = dbs[2];
});
});
describe('on bucket', function () {
var uploadFile,
bucket = `js_${DB.util.uuid().replace(/-/g, '_')}`;
var bucketAcls;
before(function () {
bucketAcls = {
load: new DB.util.Permission().allowAccess(db1.User.me).allowAccess(db2.User.me),
insert: new DB.util.Permission().allowAccess(db1.User.me),
update: new DB.util.Permission().allowAccess(db2.User.me),
delete: new DB.util.Permission().allowAccess(db1.User.me),
query: new DB.util.Permission().allowAccess(db2.User.me),
};
return rootDb.File.saveMetadata(bucket, bucketAcls);
});
beforeEach(function () {
uploadFile = new rootDb.File({ parent: bucket, data: flames });
return uploadFile.upload({ force: true });
});
it('should load the bucket acls', function () {
return rootDb.File.loadMetadata(bucket).then(function (data) {
expect(data).eql(bucketAcls);
});
});
it('should allow setting www bucket access', function () {
return rootDb.File.saveMetadata('www', {}).then(function () {
return rootDb.File.loadMetadata('www');
}).then(function (acls) {
acls.load = new rootDb.util.Permission();
acls.insert = new rootDb.util.Permission();
acls.delete = new rootDb.util.Permission();
acls.query = new rootDb.util.Permission();
acls.update = new rootDb.util.Permission();
return rootDb.File.saveMetadata('www', acls);
}).then(function () {
return rootDb.File.loadMetadata('www');
})
.then(function (acls) {
expect(acls.load.isPublicAllowed()).to.be.true;
expect(acls.insert.isPublicAllowed()).to.be.true;
expect(acls.delete.isPublicAllowed()).to.be.true;
expect(acls.query.isPublicAllowed()).to.be.true;
expect(acls.update.isPublicAllowed()).to.be.true;
})
.then(function () {
return rootDb.File.loadMetadata('www');
})
.then(function (acls) {
acls.load = new rootDb.util.Permission().allowAccess(rootDb.User.me);
acls.insert = new rootDb.util.Permission().allowAccess(rootDb.User.me);
acls.delete = new rootDb.util.Permission().allowAccess(rootDb.User.me);
acls.query = new rootDb.util.Permission().allowAccess(rootDb.User.me);
acls.update = new rootDb.util.Permission().allowAccess(rootDb.User.me);
return rootDb.File.saveMetadata('www', acls);
})
.then(function () {
return rootDb.File.loadMetadata('www');
})
.then(function (acls) {
expect(acls.load.isPublicAllowed()).to.be.false;
expect(acls.insert.isPublicAllowed()).to.be.false;
expect(acls.delete.isPublicAllowed()).to.be.false;
expect(acls.query.isPublicAllowed()).to.be.false;
expect(acls.update.isPublicAllowed()).to.be.false;
})
.then(function () {
return rootDb.File.saveMetadata('www', {});
});
});
it('should allow load with load permission', async function () {
var file = new db1.File(uploadFile.id);
var data = await file.download();
expect(file.mimeType).eql('image/png');
expectSameBlob(flames, bufferToBlob(data, 'image/png'));
});
it('should deny load without load permission', async function () {
var file = new db3.File(uploadFile.id);
try {
await file.download();
expect.fail();
} catch (e) {
expect(e.message).to.contain('load permissions are required');
}
});
it('should allow insert with insert permission', function () {
var file = new db1.File({ parent: bucket, data: flames });
return file.upload().then(function () {
expect(file.mimeType).eql('image/png');
});
});
it('should deny insert without insert permission', async function () {
var file = new db2.File({ parent: bucket, data: flames });
try {
await file.upload();
expect.fail();
} catch (e) {
expect(e.message).to.contain('insert permissions are required');
}
});
it('should allow update with update permission', function () {
var file = new db2.File({
parent: bucket, name: uploadFile.name, data: flames, eTag: uploadFile.eTag,
});
return file.upload().then(function () {
expect(file.mimeType).eql('image/png');
});
});
it('should deny update without update permission', async function () {
var file = new db1.File({
parent: bucket, name: uploadFile.name, data: flames, eTag: uploadFile.eTag,
});
try {
await file.upload();
} catch (e) {
expect(e.message).to.contain('update permissions are required');
}
});
it('should allow delete with delete permission', function () {
var file = new db1.File({
parent: bucket, name: uploadFile.name, data: flames, eTag: uploadFile.eTag,
});
return file.delete();
});
it('should deny delete without delete permission', async function () {
var file = new db2.File({
parent: bucket,
name: uploadFile.name,
data: flames,
eTag: uploadFile.eTag,
});
try {
await file.delete();
} catch (e) {
expect(e.message).to.contain('delete permissions are required');
}
});
});
describe('on object', function () {
var uploadFile,
bucket = `js_${DB.util.uuid().replace(/-/g, '_')}`;
before(function () {
return rootDb.File.saveMetadata(bucket, {
load: new DB.util.Permission(),
insert: new DB.util.Permission().allowAccess(db1.User.me).allowAccess(db2.User.me),
update: new DB.util.Permission().allowAccess(db1.User.me).allowAccess(db2.User.me),
delete: new DB.util.Permission().allowAccess(db1.User.me).allowAccess(db2.User.me),
query: new DB.util.Permission().allowAccess(db1.User.me).allowAccess(db2.User.me),
});
});
beforeEach(function () {
var acl = new DB.Acl()
.allowReadAccess(db1.User.me)
.allowWriteAccess(db1.User.me)
.allowReadAccess(db2.User.me);
uploadFile = new rootDb.File({ parent: bucket, data: flames, acl: acl });
return uploadFile.upload({ force: true });
});
it('should allow load with read permission', async function () {
var file = new db1.File(uploadFile.id);
var data = await file.download();
expect(file.mimeType).eql('image/png');
expectSameBlob(flames, bufferToBlob(data, 'image/png'));
expect(file.acl.isPublicReadAllowed()).be.false;
expect(file.acl.isPublicWriteAllowed()).be.false;
expect(file.acl.isReadAllowed(db1.User.me)).be.true;
expect(file.acl.isReadAllowed(db2.User.me)).be.true;
expect(file.acl.isReadAllowed(db3.User.me)).be.false;
expect(file.acl.isWriteAllowed(db1.User.me)).be.true;
expect(file.acl.isWriteAllowed(db2.User.me)).be.false;
expect(file.acl.isWriteAllowed(db3.User.me)).be.false;
});
it('should deny load without read Permission', async function () {
var file = new db3.File(uploadFile.id);
expect(await file.download()).be.null;
});
it('should allow update with write Permission', function () {
var file = new db1.File({
parent: bucket, name: uploadFile.name, data: flames, eTag: uploadFile.eTag,
});
return file.upload().then(function () {
expect(file.mimeType).eql('image/png');
});
});
it('should deny update without write Permission', async function () {
var file = new db2.File({
parent: bucket, name: uploadFile.name, data: flames, eTag: uploadFile.eTag,
});
try {
await file.upload();
expect.fail();
} catch (e) {
expect(e.message).to.contain('Write permissions are required');
}
});
it('should allow delete with write Permission', function () {
var file = new db1.File({
parent: bucket, name: uploadFile.name, data: flames, eTag: uploadFile.eTag,
});
return file.delete();
});
it('should deny delete without write Permission', async function () {
var file = new db2.File({
parent: bucket, name: uploadFile.name, data: flames, eTag: uploadFile.eTag,
});
try {
await file.delete();
expect.fail();
} catch (e) {
expect(e.message).to.contain('Write permissions are required');
}
});
});
});
describe('listing files', function () {
before(function () {
return rootDb.File.saveMetadata('wwww', {});
});
it('should list files in a folder', function () {
var file1 = new rootDb.File({ parent: '/wwww', name: 'test.png', data: flames });
var file2 = new rootDb.File({ parent: '/wwww/images', name: 'test1.png', data: flames });
var file3 = new rootDb.File({ parent: '/wwww/images', name: 'test2.png', data: flames });
return Promise.all([
file1.upload().catch(function () {
}),
file2.upload().catch(function () {
}),
file3.upload().catch(function () {
}),
]).then(function () {
var folder = new rootDb.File('/file/wwww/');
return rootDb.File.listFiles(folder);
}).then(function (files) {
expect(files.length).eql(2);
expect(files[0].name).eql('images/');
expect(files[1].name).eql('test.png');
var folder = new rootDb.File('/file/wwww/images/');
return rootDb.File.listFiles(folder);
}).then(function (files) {
expect(files.length).eql(2);
expect(files[0].name).eql('test1.png');
expect(files[1].name).eql('test2.png');
var folder = new rootDb.File('/file/wwww/images/');
return rootDb.File.listFiles(folder, null, 1);
})
.then(function (files) {
expect(files.length).eql(1);
expect(files[0].name).eql('test1.png');
var folder = new rootDb.File('/file/wwww/images/');
return rootDb.File.listFiles(folder, files[0], 1);
})
.then(function (files) {
expect(files.length).eql(1);
expect(files[0].name).eql('test2.png');