diff --git a/api/media/routes.mjs b/api/media/routes.mjs index fb2fbce..891b6c6 100644 --- a/api/media/routes.mjs +++ b/api/media/routes.mjs @@ -16,6 +16,7 @@ export default class MediaRoutes { }) this.siteCache = new Map() this.collator = new Intl.Collator('is-IS', { numeric: false, sensitivity: 'accent' }) + this.cors = CorsHandler({ allowedOrigins: ['*'] }) } register(server) { @@ -30,7 +31,7 @@ export default class MediaRoutes { server.flaska.post('/media/resize', [server.queryHandler()], this.resize.bind(this)) server.flaska.post('/media/resize/:filename', [server.queryHandler(), server.jsonHandler()], this.resizeExisting.bind(this)) server.flaska.delete('/media/:filename', [server.queryHandler()], this.remove.bind(this)) - server.flaska.options('/::path', [server.queryHandler(), this.security.verifyCorsEnabled], CorsHandler({ allowedOrigins: ['*'] })) + server.flaska.options('/::path', [server.queryHandler(), this.security.verifyCorsEnabled], this.cors) } init(server) { @@ -90,20 +91,32 @@ export default class MediaRoutes { } } + getSite(ctx) { + let site = this.security.verifyToken(ctx) + if (this.security.hasCors(site)) { + this.cors(ctx) + } + return site + } + async listFiles(ctx) { - let site = await this.security.verifyToken(ctx) + let site = this.getSite(ctx) ctx.body = this.filesCacheGet(site) } async listPublicFiles(ctx) { this.security.throwIfNotPublic(ctx.params.site) + + if (this.security.hasCors(ctx.params.site)) { + this.cors(ctx) + } ctx.body = this.filesCacheGet(ctx.params.site) } async upload(ctx, noprefix = false) { - let site = await this.security.verifyToken(ctx) + let site = this.getSite(ctx) ctx.state.site = site let result = await this.formidable.uploadFile(ctx, ctx.state.site, noprefix) @@ -182,7 +195,7 @@ export default class MediaRoutes { } async resizeExisting(ctx) { - let site = await this.security.verifyToken(ctx) + let site = this.getSite(ctx) ctx.state.site = site ctx.body = {} @@ -196,7 +209,7 @@ export default class MediaRoutes { } async remove(ctx) { - let site = await this.security.verifyToken(ctx) + let site = this.getSite(ctx) this.filesCacheRemove(site, ctx.params.filename) diff --git a/api/media/security.mjs b/api/media/security.mjs index 31a3184..67f8b07 100644 --- a/api/media/security.mjs +++ b/api/media/security.mjs @@ -25,6 +25,11 @@ export function verifyToken(ctx) { } } +export function hasCors(site) { + let sites = config.get('sites') + return sites[site]?.cors === true +} + export function verifyCorsEnabled(ctx) { let site try { @@ -32,9 +37,8 @@ export function verifyCorsEnabled(ctx) { } catch (err) { throw new HttpError(404) } - - let sites = config.get('sites') - if (!sites[site] || sites[site].cors !== true) { + + if (!hasCors(site)) { throw new HttpError(404) } } diff --git a/package.json b/package.json index b95aaf3..9f12efd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "storage-upload", - "version": "2.2.10", + "version": "2.2.11", "description": "Micro service for uploading and image resizing files to a storage server.", "main": "index.js", "scripts": { diff --git a/public/existing_cors/20220105_101610_test1.jpg b/public/existing_cors/20220105_101610_test1.jpg new file mode 100644 index 0000000..09fe12f Binary files /dev/null and b/public/existing_cors/20220105_101610_test1.jpg differ diff --git a/public/existing_cors/20220105_101610_test2.png b/public/existing_cors/20220105_101610_test2.png new file mode 100644 index 0000000..0cfeace Binary files /dev/null and b/public/existing_cors/20220105_101610_test2.png differ diff --git a/test/helper.client.mjs b/test/helper.client.mjs index a5be504..2311045 100644 --- a/test/helper.client.mjs +++ b/test/helper.client.mjs @@ -26,6 +26,9 @@ Client.prototype.customRequest = function(method = 'GET', path, body, options) { host: urlObj.hostname, port: Number(urlObj.port), path: urlObj.pathname + urlObj.search, + headers: { + origin: 'http://localhost' + } })) const req = http.request(opts) @@ -44,7 +47,9 @@ Client.prototype.customRequest = function(method = 'GET', path, body, options) { }) res.on('end', function () { - if (!output) return resolve(null) + let headers = opts.includeHeaders ? res.headers : null + + if (!output) return resolve(headers ? { headers } : null) try { output = JSON.parse(output) } catch (e) { @@ -56,29 +61,29 @@ Client.prototype.customRequest = function(method = 'GET', path, body, options) { err.status = output.status return reject(err) } - resolve(output) + resolve(headers ? { headers, output } : output) }) }) req.end() }) } -Client.prototype.get = function(url = '/') { - return this.customRequest('GET', url, null) +Client.prototype.get = function(url = '/', options) { + return this.customRequest('GET', url, null, options) } -Client.prototype.post = function(url = '/', body = {}) { +Client.prototype.post = function(url = '/', body = {}, options) { let parsed = JSON.stringify(body) - return this.customRequest('POST', url, parsed, { + return this.customRequest('POST', url, parsed, defaults(options, { headers: { 'Content-Type': 'application/json', 'Content-Length': parsed.length, }, - }) + })) } -Client.prototype.del = function(url = '/', body = {}) { - return this.customRequest('DELETE', url, JSON.stringify(body)) +Client.prototype.del = function(url = '/', body = {}, options) { + return this.customRequest('DELETE', url, JSON.stringify(body), options) } const random = (length = 8) => { @@ -92,7 +97,7 @@ const random = (length = 8) => { return str; } -Client.prototype.upload = function(url, file, method = 'POST', body = {}) { +Client.prototype.upload = function(url, file, method = 'POST', body = {}, options) { return fs.readFile(file).then(data => { const crlf = '\r\n' const filename = path.basename(file) @@ -114,12 +119,12 @@ Client.prototype.upload = function(url, file, method = 'POST', body = {}) { Buffer.from(`${crlf}--${boundary}--`), ]) - return this.customRequest(method, url, multipartBody, { + return this.customRequest(method, url, multipartBody, defaults(options, { timeout: 5000, headers: { 'Content-Type': 'multipart/form-data; boundary=' + boundary, 'Content-Length': multipartBody.length, }, - }) + })) }) } diff --git a/test/helper.server.mjs b/test/helper.server.mjs index fa3956a..e6a7b91 100644 --- a/test/helper.server.mjs +++ b/test/helper.server.mjs @@ -46,7 +46,14 @@ export function startServer() { "keys": { "default@HS256": "asdf1234" } - } + }, + "existing_cors": { + "public": true, + "keys": { + "default@HS256": "asdf1234" + }, + "cors": true + }, }, }) diff --git a/test/media/api.test.mjs b/test/media/api.test.mjs index a9e011c..75a2b6d 100644 --- a/test/media/api.test.mjs +++ b/test/media/api.test.mjs @@ -75,6 +75,7 @@ t.timeout(10000).describe('Media (API)', () => { }) t.test('should work if specified has cors enabled', async () => { + const assertOrigin = 'http://localhost:9999' let token = encode(null, { iss: 'development_cors' }, secret) const testPaths = [ '/media', @@ -87,7 +88,12 @@ t.timeout(10000).describe('Media (API)', () => { ] for (let path of testPaths) { - await client.customRequest('OPTIONS', path + `?token=${token}`, null) + let res = await client.customRequest('OPTIONS', path + `?token=${token}`, null, { + includeHeaders: true, + headers: { origin: assertOrigin, 'access-control-request-method': 'POST' }, + }) + assert.strictEqual(res.headers['access-control-allow-origin'], assertOrigin) + assert.match(res.headers['access-control-allow-methods'], /post/i) } }) }) @@ -146,27 +152,68 @@ t.timeout(10000).describe('Media (API)', () => { let data = await assert.isFulfilled( client.upload( `/media?token=${token}`, - resolve('test.png') + resolve('test.png'), + 'POST', + { }, + { includeHeaders: true } ) ) - testFiles.push(data.path) + testFiles.push(data?.output?.path) - assert.ok(data) - assert.ok(data.filename) - assert.ok(data.filename.startsWith(currYear)) - assert.ok(data.path) + assert.ok(data.output) + assert.ok(data.output.filename) + assert.ok(data.output.filename.startsWith(currYear)) + assert.ok(data.output.path) let stats = await Promise.all([ fs.stat(resolve('test.png')), - fs.stat(resolve(`../../public/${data.path}`)), + fs.stat(resolve(`../../public/${data.output.path}`)), ]) assert.strictEqual(stats[0].size, stats[1].size) - let img = await sharp(resolve(`../../public/${data.path}`)).metadata() + let img = await sharp(resolve(`../../public/${data.output.path}`)).metadata() assert.strictEqual(img.width, 600) assert.strictEqual(img.height, 700) assert.strictEqual(img.format, 'png') + assert.notOk(data.headers['access-control-allow-origin']) + }) + + t.test('should upload file and create file and return cors if site has cors', async () => { + const assertOrigin = 'http://localhost:9000' + let token = encode(null, { iss: 'development_cors' }, secret) + + let data = await assert.isFulfilled( + client.upload( + `/media?token=${token}`, + resolve('test.png'), + 'POST', + { }, + { + includeHeaders: true, + headers: { origin: assertOrigin, 'access-control-request-method': 'POST' }, + } + ) + ) + + testFiles.push(data.output?.path) + + assert.ok(data.output) + assert.ok(data.output.filename) + assert.ok(data.output.filename.startsWith(currYear)) + assert.ok(data.output.path) + + let stats = await Promise.all([ + fs.stat(resolve('test.png')), + fs.stat(resolve(`../../public/${data.output.path}`)), + ]) + assert.strictEqual(stats[0].size, stats[1].size) + + let img = await sharp(resolve(`../../public/${data.output.path}`)).metadata() + assert.strictEqual(img.width, 600) + assert.strictEqual(img.height, 700) + assert.strictEqual(img.format, 'png') + assert.strictEqual(data.headers['access-control-allow-origin'], assertOrigin) }) t.test('should properly replace spaces and other stuff', async () => { @@ -200,6 +247,35 @@ t.timeout(10000).describe('Media (API)', () => { assert.strictEqual(img.height, 720) assert.strictEqual(img.format, 'png') }) + + t.test('should return cors for cors-enabled sites', async () => { + let token = encode(null, { iss: 'development' }, secret) + + let data = await assert.isFulfilled( + client.upload( + `/media?token=${token}`, + resolve('test.png') + ) + ) + + testFiles.push(data.path) + + assert.ok(data) + assert.ok(data.filename) + assert.ok(data.filename.startsWith(currYear)) + assert.ok(data.path) + + let stats = await Promise.all([ + fs.stat(resolve('test.png')), + fs.stat(resolve(`../../public/${data.path}`)), + ]) + assert.strictEqual(stats[0].size, stats[1].size) + + let img = await sharp(resolve(`../../public/${data.path}`)).metadata() + assert.strictEqual(img.width, 600) + assert.strictEqual(img.height, 700) + assert.strictEqual(img.format, 'png') + }) }) t.describe('POST /media/noprefix', function temp() { @@ -256,15 +332,18 @@ t.timeout(10000).describe('Media (API)', () => { let data = await assert.isFulfilled( client.upload( `/media/noprefix?token=${token}`, - resolve('test.png') + resolve('test.png'), + 'POST', + { }, + { includeHeaders: true } ) ) - testFiles.push(data.path) + testFiles.push(data?.output?.path) - assert.ok(data) - assert.strictEqual(data.filename, 'test.png') - assert.ok(data.path) + assert.ok(data.output) + assert.strictEqual(data.output.filename, 'test.png') + assert.ok(data.output.path) let stats = await Promise.all([ fs.stat(resolve('test.png')), @@ -276,6 +355,44 @@ t.timeout(10000).describe('Media (API)', () => { assert.strictEqual(img.width, 600) assert.strictEqual(img.height, 700) assert.strictEqual(img.format, 'png') + assert.notOk(data.headers['access-control-allow-origin']) + }) + + + t.test('should upload and create file with no prefix', async () => { + const assertOrigin = 'http://localhost:9000' + let token = encode(null, { iss: 'development_cors' }, secret) + + let data = await assert.isFulfilled( + client.upload( + `/media/noprefix?token=${token}`, + resolve('test.png'), + 'POST', + { }, + { + includeHeaders: true, + headers: { origin: assertOrigin, 'access-control-request-method': 'POST' }, + } + ) + ) + + testFiles.push(data?.output?.path) + + assert.ok(data.output) + assert.strictEqual(data.output.filename, 'test.png') + assert.ok(data.output.path) + + let stats = await Promise.all([ + fs.stat(resolve('test.png')), + fs.stat(resolve('../../public/development/test.png')), + ]) + assert.strictEqual(stats[0].size, stats[1].size) + + let img = await sharp(resolve('../../public/development/test.png')).metadata() + assert.strictEqual(img.width, 600) + assert.strictEqual(img.height, 700) + assert.strictEqual(img.format, 'png') + assert.strictEqual(data.headers['access-control-allow-origin'], assertOrigin) }) t.test('should upload and create file with prefix if exists', async () => { @@ -374,27 +491,66 @@ t.timeout(10000).describe('Media (API)', () => { `/media/resize?token=${token}`, resolve('test.png'), 'POST', - { } + { }, + { includeHeaders: true } ) ) - testFiles.push(data.path) + testFiles.push(data?.output?.path) - assert.ok(data) - assert.ok(data.filename) - assert.ok(data.filename.startsWith(currYear)) - assert.ok(data.path) + assert.ok(data.output) + assert.ok(data.output.filename) + assert.ok(data.output.filename.startsWith(currYear)) + assert.ok(data.output.path) let stats = await Promise.all([ fs.stat(resolve('test.png')), - fs.stat(resolve(`../../public/${data.path}`)), + fs.stat(resolve(`../../public/${data.output.path}`)), ]) assert.strictEqual(stats[0].size, stats[1].size) - let img = await sharp(resolve(`../../public/${data.path}`)).metadata() + let img = await sharp(resolve(`../../public/${data.output.path}`)).metadata() assert.strictEqual(img.width, 600) assert.strictEqual(img.height, 700) assert.strictEqual(img.format, 'png') + assert.notOk(data.headers['access-control-allow-origin']) + }) + + t.test('should upload file and create file and return cors if site has cors', async () => { + const assertOrigin = 'http://localhost:9000' + let token = encode(null, { iss: 'development_cors' }, secret) + + let data = await assert.isFulfilled( + client.upload( + `/media/resize?token=${token}`, + resolve('test.png'), + 'POST', + { }, + { + includeHeaders: true, + headers: { origin: assertOrigin, 'access-control-request-method': 'POST' }, + } + ) + ) + + testFiles.push(data?.output?.path) + + assert.ok(data.output) + assert.ok(data.output.filename) + assert.ok(data.output.filename.startsWith(currYear)) + assert.ok(data.output.path) + + let stats = await Promise.all([ + fs.stat(resolve('test.png')), + fs.stat(resolve(`../../public/${data.output.path}`)), + ]) + assert.strictEqual(stats[0].size, stats[1].size) + + let img = await sharp(resolve(`../../public/${data.output.path}`)).metadata() + assert.strictEqual(img.width, 600) + assert.strictEqual(img.height, 700) + assert.strictEqual(img.format, 'png') + assert.strictEqual(data.headers['access-control-allow-origin'], assertOrigin) }) t.test('should upload file and create multiple sizes for file', async () => { @@ -560,29 +716,40 @@ t.timeout(10000).describe('Media (API)', () => { t.describe('POST /media/resize/:filename', function temp() { let sourceFilename + let sourceFilenameCors let sourcePath + let sourcePathCors t.before(async function() { - let token = encode(null, { iss: 'development' }, secret) + let issuers = ['development', 'development_cors'] - let data = await assert.isFulfilled( - client.upload( - `/media/resize?token=${token}`, - resolve('test.png'), - 'POST', - { } + for (let iss of issuers) { + let token = encode(null, { iss }, secret) + + let data = await assert.isFulfilled( + client.upload( + `/media/resize?token=${token}`, + resolve('test.png'), + 'POST', + { } + ) ) - ) - testFiles.push(data.path) + testFiles.push(data.path) - assert.ok(data) - assert.ok(data.filename) - assert.ok(data.filename.startsWith(currYear)) - assert.ok(data.path) + assert.ok(data) + assert.ok(data.filename) + assert.ok(data.filename.startsWith(currYear)) + assert.ok(data.path) - sourceFilename = data.filename - sourcePath = data.path + if (iss === 'development') { + sourceFilename = data.filename + sourcePath = data.path + } else { + sourceFilenameCors = data.filename + sourcePathCors = data.path + } + } }) t.test('should require authentication', async () => { @@ -658,34 +825,75 @@ t.timeout(10000).describe('Media (API)', () => { compressionLevel: 9, } }, - } + }, + { includeHeaders: true } ) ) - testFiles.push(data.test1.path) - testFiles.push(data.test2.path) + testFiles.push(data.output.test1.path) + testFiles.push(data.output.test2.path) - assert.ok(data.test1.filename) - assert.ok(data.test1.filename.startsWith(currYear)) - assert.ok(data.test1.path) - assert.ok(data.test2.filename) - assert.ok(data.test2.filename.startsWith(currYear)) - assert.ok(data.test2.path) + assert.ok(data.output.test1.filename) + assert.ok(data.output.test1.filename.startsWith(currYear)) + assert.ok(data.output.test1.path) + assert.ok(data.output.test2.filename) + assert.ok(data.output.test2.filename.startsWith(currYear)) + assert.ok(data.output.test2.path) let img = await sharp(resolve(`../../public/${sourcePath}`)).metadata() assert.strictEqual(img.width, 600) assert.strictEqual(img.height, 700) assert.strictEqual(img.format, 'png') - img = await sharp(resolve(`../../public/${data.test1.path}`)).metadata() + img = await sharp(resolve(`../../public/${data.output.test1.path}`)).metadata() assert.strictEqual(img.width, 320) assert.strictEqual(img.height, 413) assert.strictEqual(img.format, 'jpeg') - img = await sharp(resolve(`../../public/${data.test2.path}`)).metadata() + img = await sharp(resolve(`../../public/${data.output.test2.path}`)).metadata() assert.strictEqual(img.width, 150) assert.strictEqual(img.height, 175) assert.strictEqual(img.format, 'png') + assert.notOk(data.headers['access-control-allow-origin']) + }) + + t.test('should create sizes for existing file and return cors if site has cors', async () => { + const assertOrigin = 'http://localhost:9000' + let token = encode(null, { iss: 'development_cors' }, secret) + + let data = await assert.isFulfilled( + client.post( + `/media/resize/${sourceFilenameCors}?token=${token}`, + { + test2: { + format: 'png', + resize: { width: 150 }, + png: { compressionLevel: 9 } + }, + }, + { + includeHeaders: true, + headers: { origin: assertOrigin, 'access-control-request-method': 'POST' }, + } + ) + ) + + testFiles.push(data.output.test2.path) + + assert.ok(data.output.test2.filename) + assert.ok(data.output.test2.filename.startsWith(currYear)) + assert.ok(data.output.test2.path) + + let img = await sharp(resolve(`../../public/${sourcePath}`)).metadata() + assert.strictEqual(img.width, 600) + assert.strictEqual(img.height, 700) + assert.strictEqual(img.format, 'png') + + img = await sharp(resolve(`../../public/${data.output.test2.path}`)).metadata() + assert.strictEqual(img.width, 150) + assert.strictEqual(img.height, 175) + assert.strictEqual(img.format, 'png') + assert.strictEqual(data.headers['access-control-allow-origin'], assertOrigin) }) t.test('should base64 output of existing file', async () => { @@ -771,7 +979,7 @@ t.timeout(10000).describe('Media (API)', () => { }) t.test('should remove the file', async () => { - let token = encode(null, { iss: 'existing' }, secret) + let token = encode(null, { iss: 'development' }, secret) let data = await client.upload( `/media/noprefix?token=${token}`, @@ -781,11 +989,11 @@ t.timeout(10000).describe('Media (API)', () => { let filepath = data.path testFiles.push(filepath) - let files = await client.get('/media/existing') + let files = await client.get('/media?token=' + token) let found = false for (let file of files) { - if (file.filename === 'test.png') { + if (file.filename === data.filename) { found = true } } @@ -795,17 +1003,19 @@ t.timeout(10000).describe('Media (API)', () => { fs.stat(resolve(`../../public/${filepath}`)) ) - await assert.isFulfilled( - client.del(`/media/test.png?token=${token}`) + let res = await assert.isFulfilled( + client.del(`/media/${data.filename}?token=${token}`, {}, { + includeHeaders: true + }) ) testFiles.splice(testFiles.length - 1) - files = await client.get('/media/existing') + files = await client.get('/media?token=' + token) found = false for (let file of files) { - if (file.filename === 'test.png') { + if (file.filename === data.filename) { found = true } } @@ -814,6 +1024,58 @@ t.timeout(10000).describe('Media (API)', () => { await assert.isRejected( fs.stat(resolve(`../../public/${filepath}`)) ) + assert.notOk(res.headers['access-control-allow-origin']) + }) + + t.test('should remove the file and return cors if site has cors', async () => { + const assertOrigin = 'http://localhost:9000' + let token = encode(null, { iss: 'development_cors' }, secret) + + let data = await client.upload( + `/media/noprefix?token=${token}`, + resolve('test.png') + ) + + let filepath = data.path + testFiles.push(filepath) + + let files = await client.get('/media?token=' + token) + + let found = false + for (let file of files) { + if (file.filename === data.filename) { + found = true + } + } + assert.ok(found) + + await assert.isFulfilled( + fs.stat(resolve(`../../public/${filepath}`)) + ) + + let res = await assert.isFulfilled( + client.del(`/media/${data.filename}?token=${token}`, {}, { + includeHeaders: true, + headers: { origin: assertOrigin, 'access-control-request-method': 'POST' }, + }) + ) + + testFiles.splice(testFiles.length - 1) + + files = await client.get('/media?token=' + token) + + found = false + for (let file of files) { + if (file.filename === data.filename) { + found = true + } + } + assert.notOk(found) + + await assert.isRejected( + fs.stat(resolve(`../../public/${filepath}`)) + ) + assert.strictEqual(res.headers['access-control-allow-origin'], assertOrigin) }) }) @@ -860,17 +1122,39 @@ t.timeout(10000).describe('Media (API)', () => { t.test('should return list of files in specified folder', async () => { let token = encode(null, { iss: 'development' }, secret) - let data = await client.get('/media?token=' + token) + let data = await client.get('/media?token=' + token, { includeHeaders: true }) - assert.ok(data.length) + assert.ok(data.output.length) let found = false - for (let file of data) { + for (let file of data.output) { if (file.filename === '.gitkeep') { found = true break } } assert.ok(found) + assert.notOk(data.headers['access-control-allow-origin']) + }) + + t.test('should return list of files in specified folder and return cors if site has cors', async () => { + const assertOrigin = 'http://localhost:9000' + let token = encode(null, { iss: 'development_cors' }, secret) + + let data = await client.get('/media?token=' + token, { + includeHeaders: true, + headers: { origin: assertOrigin, 'access-control-request-method': 'POST' }, + }) + + assert.ok(data.output.length) + let found = false + for (let file of data.output) { + if (file.filename === '.gitkeep') { + found = true + break + } + } + assert.ok(found) + assert.strictEqual(data.headers['access-control-allow-origin'], assertOrigin) }) }) @@ -890,11 +1174,25 @@ t.timeout(10000).describe('Media (API)', () => { }) t.test('should otherwise return list of files for a public site', async () => { - let files = await client.get('/media/existing') - assert.strictEqual(files[0].filename, '20220105_101610_test1.jpg') - assert.strictEqual(files[0].size, null) - assert.strictEqual(files[1].filename, '20220105_101610_test2.png') - assert.strictEqual(files[1].size, null) + let files = await client.get('/media/existing', { includeHeaders: true }) + assert.strictEqual(files.output[0].filename, '20220105_101610_test1.jpg') + assert.strictEqual(files.output[0].size, null) + assert.strictEqual(files.output[1].filename, '20220105_101610_test2.png') + assert.strictEqual(files.output[1].size, null) + assert.notOk(files.headers['access-control-allow-origin']) + }) + + t.test('should otherwise return list of files for a public site and cors if site has cors', async () => { + const assertOrigin = 'http://localhost:9000' + let files = await client.get('/media/existing_cors', { + includeHeaders: true, + headers: { origin: assertOrigin, 'access-control-request-method': 'POST' }, + }) + assert.strictEqual(files.output[0].filename, '20220105_101610_test1.jpg') + assert.strictEqual(files.output[0].size, null) + assert.strictEqual(files.output[1].filename, '20220105_101610_test2.png') + assert.strictEqual(files.output[1].size, null) + assert.strictEqual(files.headers['access-control-allow-origin'], assertOrigin) }) }) }) diff --git a/test/media/routes.test.mjs b/test/media/routes.test.mjs index 8e83cbd..32b9e52 100644 --- a/test/media/routes.test.mjs +++ b/test/media/routes.test.mjs @@ -73,7 +73,7 @@ t.describe('#listFiles()', function() { const stubGetCache = stub() const routes = new MediaRoutes({ - security: { verifyToken: stubVerify }, + security: { verifyToken: stubVerify, hasCors: stub() }, }) routes.filesCacheGet = stubGetCache @@ -87,7 +87,7 @@ t.describe('#listFiles()', function() { let ctx = createContext() const assertError = new Error('temp') - stubVerify.rejects(assertError) + stubVerify.throws(assertError) let err = await assert.isRejected(routes.listFiles(ctx)) @@ -102,7 +102,7 @@ t.describe('#listFiles()', function() { let ctx = createContext() const assertSiteName = 'benshapiro' const assertResult = { a: 1 } - stubVerify.resolves(assertSiteName) + stubVerify.returns(assertSiteName) stubGetCache.returns(assertResult) await routes.listFiles(ctx) @@ -118,7 +118,7 @@ t.describe('#listPublicFiles()', function() { const stubGetCache = stub() const routes = new MediaRoutes({ - security: { throwIfNotPublic: stubSitePublic }, + security: { throwIfNotPublic: stubSitePublic, hasCors: stub() }, }) routes.filesCacheGet = stubGetCache @@ -250,6 +250,7 @@ t.describe('#uploadNoPrefix', function() { security: { verifyToken: stubVerify, verifyBody: stub(), + hasCors: stub(), }, formidable: { uploadFile: stubUpload, }, fs: { stat: stubStat }, @@ -267,7 +268,7 @@ t.describe('#uploadNoPrefix', function() { let ctx = createContext() const assertSiteName = 'benshapiro' const assertError = new Error('hello') - stubVerify.resolves(assertSiteName) + stubVerify.returns(assertSiteName) stubUpload.rejects(assertError) let err = await assert.isRejected(routes.uploadNoPrefix(ctx)) @@ -300,6 +301,7 @@ t.describe('#resizeExisting', function() { security: { verifyToken: stubVerifyToken, verifyBody: stubVerifyBody, + hasCors: stub(), }, fs: { stat: stubStat }, sharp: stubSharp, @@ -338,7 +340,7 @@ t.describe('#resizeExisting', function() { let ctx = createContext({ req: { body: { } } }) const assertError = new Error('temp') - stubVerifyToken.rejects(assertError) + stubVerifyToken.throws(assertError) let err = await assert.isRejected(routes.resizeExisting(ctx)) @@ -367,7 +369,7 @@ t.describe('#resizeExisting', function() { const assertJpeg = { a: 1 } const assertFilename = 'asdfsafd' const assertSite = 'mario' - stubVerifyToken.resolves(assertSite) + stubVerifyToken.returns(assertSite) let ctx = createContext({ req: { body: { [assertKey]: { @@ -418,7 +420,7 @@ t.describe('#resizeExisting', function() { const assertPayload = { a: 1 } const assertFilename = 'asdfsafd' const assertSite = 'mario' - stubVerifyToken.resolves(assertSite) + stubVerifyToken.returns(assertSite) let called = 0 stubStat.returnWith(function() { @@ -467,7 +469,7 @@ t.describe('#resizeExisting', function() { const assertValidKey2 = 'derp' const assertErrorKey = 'throwmyerr' const assertErrorMessage = 'some message here' - stubVerifyToken.resolves('asdf') + stubVerifyToken.returns('asdf') let called = 0 stubStat.returnWith(function() { @@ -512,7 +514,7 @@ t.describe('#resizeExisting', function() { const assertFilename = 'asdfsafd.png' const assertSite = 'mario' const assertBase64Data = 'asdf1234' - stubVerifyToken.resolves(assertSite) + stubVerifyToken.returns(assertSite) let ctx = createContext({ req: { body: { [assertKey]: { @@ -562,6 +564,7 @@ t.describe('#resize', function() { security: { verifyToken: stubVerifyToken, verifyBody: stubVerifyBody, + hasCors: stub(), }, fs: { stat: stubStat }, formidable: { uploadFile: stubUpload }, @@ -618,7 +621,7 @@ t.describe('#resize', function() { const assertJpeg = { a: 1 } const assertFilename = 'asdfsafd' const assertSite = 'mario' - stubVerifyToken.resolves(assertSite) + stubVerifyToken.returns(assertSite) stubUpload.resolves({ filename: assertFilename + '.png' }) let ctx = createContext({ req: { body: { @@ -669,7 +672,7 @@ t.describe('#resize', function() { const assertPayload = { a: 1 } const assertFilename = 'asdfsafd' const assertSite = 'mario' - stubVerifyToken.resolves(assertSite) + stubVerifyToken.returns(assertSite) stubUpload.resolves({ filename: assertFilename + '.png' }) let called = 0 @@ -720,7 +723,7 @@ t.describe('#resize', function() { const assertValidKey2 = 'derp' const assertErrorKey = 'throwmyerr' const assertErrorMessage = 'some message here' - stubVerifyToken.resolves('asdf') + stubVerifyToken.returns('asdf') stubUpload.resolves({ filename: 'file.png' }) let called = 0 @@ -765,7 +768,7 @@ t.describe('#resize', function() { const assertFilename = 'asdfsafd.png' const assertSite = 'mario' const assertBase64Data = 'asdf1234' - stubVerifyToken.resolves(assertSite) + stubVerifyToken.returns(assertSite) stubUpload.resolves({ filename: assertFilename }) let ctx = createContext({ req: { body: { @@ -811,6 +814,7 @@ basicUploadTestRoutes.forEach(function(name) { security: { verifyToken: stubVerify, verifyBody: stub(), + hasCors: stub(), }, formidable: { uploadFile: stubUpload, }, fs: { stat: stubStat }, @@ -827,7 +831,7 @@ basicUploadTestRoutes.forEach(function(name) { let ctx = createContext({ req: { body: { } } }) const assertError = new Error('temp') - stubVerify.rejects(assertError) + stubVerify.throws(assertError) let err = await assert.isRejected(routes[name](ctx)) @@ -842,7 +846,7 @@ basicUploadTestRoutes.forEach(function(name) { let ctx = createContext({ req: { body: { } } }) const assertSiteName = 'benshapiro' const assertError = new Error('hello') - stubVerify.resolves(assertSiteName) + stubVerify.returns(assertSiteName) stubUpload.rejects(assertError) let err = await assert.isRejected(routes[name](ctx)) @@ -860,7 +864,7 @@ basicUploadTestRoutes.forEach(function(name) { const assertSize = 1241412 const assertFilename = 'asdfsafd' const assertSite = 'mario' - stubVerify.resolves(assertSite) + stubVerify.returns(assertSite) stubUpload.resolves({ filename: assertFilename }) stubStat.resolves({ size: assertSize }) await routes[name](ctx) @@ -887,6 +891,7 @@ t.describe('#remove()', function() { const routes = new MediaRoutes({ security: { verifyToken: stubVerify, + hasCors: stub(), }, fs: { unlink: stubUnlink }, }) @@ -905,7 +910,7 @@ t.describe('#remove()', function() { let ctx = createContext({ req: { body: { } } }) const assertError = new Error('temp') - stubVerify.rejects(assertError) + stubVerify.throws(assertError) let err = await assert.isRejected(routes.remove(ctx)) @@ -924,7 +929,7 @@ t.describe('#remove()', function() { let ctx = createContext({ req: { body: { } } }) ctx.params.filename = assertFilename - stubVerify.resolves(assertSiteName) + stubVerify.returns(assertSiteName) stubUnlink.rejects(assertError) let err = await assert.isRejected(routes.remove(ctx)) @@ -948,7 +953,7 @@ t.describe('#remove()', function() { let ctx = createContext({ req: { body: { } } }) ctx.params.filename = assertFilename - stubVerify.resolves(assertSiteName) + stubVerify.returns(assertSiteName) await routes.remove(ctx)