Use service-core
This commit is contained in:
parent
9a0fca4a22
commit
666c4bee89
20 changed files with 436 additions and 393 deletions
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"NODE_ENV": "development",
|
||||
"server": {
|
||||
"port": 4020,
|
||||
"host": "0.0.0.0"
|
||||
},
|
||||
"bunyan": {
|
||||
"name": "storage-upload",
|
||||
"streams": [{
|
||||
"stream": "process.stdout",
|
||||
"level": "debug"
|
||||
}
|
||||
]
|
||||
},
|
||||
"jwt": {
|
||||
"secret": "this-is-my-secret",
|
||||
"options": {
|
||||
"expiresIn": 604800
|
||||
}
|
||||
},
|
||||
"fileSize": 524288000
|
||||
}
|
|
@ -1,67 +1,61 @@
|
|||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
import Nconf from 'nconf-lite'
|
||||
import { Util } from 'service-core'
|
||||
|
||||
const nconf = new Nconf()
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
let pckg = JSON.parse(fs.readFileSync(path.resolve(path.join(__dirname, '../package.json'))))
|
||||
|
||||
|
||||
// Helper method for global usage.
|
||||
nconf.inTest = () => nconf.get('NODE_ENV') === 'test'
|
||||
|
||||
// Config follow the following priority check order:
|
||||
// 1. package.json
|
||||
// 2. Enviroment variables
|
||||
// 1. Enviroment variables
|
||||
// 2. package.json
|
||||
// 3. config/config.json
|
||||
// 4. config/config.default.json
|
||||
|
||||
|
||||
pckg = {
|
||||
name: pckg.name,
|
||||
version: pckg.version,
|
||||
description: pckg.description,
|
||||
author: pckg.author,
|
||||
license: pckg.license,
|
||||
homepage: pckg.homepage,
|
||||
}
|
||||
// Load enviroment variables as first priority
|
||||
nconf.env({
|
||||
separator: '__',
|
||||
whitelist: [
|
||||
'NODE_ENV',
|
||||
'server__port',
|
||||
'server__host',
|
||||
'bunyan__name',
|
||||
'frontend__url',
|
||||
'fileSize',
|
||||
'name',
|
||||
'NODE_VERSION',
|
||||
],
|
||||
parseValues: true,
|
||||
})
|
||||
|
||||
|
||||
// Load overrides as first priority
|
||||
nconf.overrides(pckg)
|
||||
// Load empty overrides that can be overwritten later
|
||||
nconf.overrides({})
|
||||
|
||||
let util = new Util(import.meta.url)
|
||||
let pckg = JSON.parse(fs.readFileSync(util.getPathFromRoot(`../package.json`)))
|
||||
|
||||
// Load enviroment variables as second priority
|
||||
nconf.env()
|
||||
|
||||
|
||||
// Load any overrides from the appropriate config file
|
||||
let configFile = '../config/config.json'
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (nconf.get('NODE_ENV') === 'test') {
|
||||
configFile = '../config/config.test.json'
|
||||
}
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (nconf.get('NODE_ENV') === 'production') {
|
||||
configFile = '../config/config.production.json'
|
||||
}
|
||||
|
||||
nconf.file('main', path.resolve(path.join(__dirname, configFile)))
|
||||
|
||||
// Load defaults
|
||||
nconf.file('default', path.resolve(path.join(__dirname, '../api/config.default.json')))
|
||||
|
||||
|
||||
// Final sanity checks
|
||||
/* istanbul ignore if */
|
||||
if (typeof global.it === 'function' & !nconf.inTest()) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Critical: potentially running test on production enviroment. Shutting down.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
nconf.defaults({
|
||||
"name": pckg.name,
|
||||
"version": pckg.version,
|
||||
"NODE_ENV": "development",
|
||||
"server": {
|
||||
"port": 4040,
|
||||
"host": "0.0.0.0"
|
||||
},
|
||||
"bunyan": {
|
||||
"name": "storage-upload",
|
||||
"streams": [{
|
||||
"stream": "process.stdout",
|
||||
"level": "debug"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sites": {
|
||||
},
|
||||
"uploadFolder": "./public",
|
||||
"fileSize": 524288000
|
||||
})
|
||||
|
||||
export default nconf
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
export class HttpError extends Error {
|
||||
constructor(message, status = 500) {
|
||||
super(message)
|
||||
this.status = status
|
||||
}
|
||||
}
|
22
api/log.mjs
22
api/log.mjs
|
@ -1,22 +0,0 @@
|
|||
import bunyan from 'bunyan-lite'
|
||||
import config from './config.mjs'
|
||||
import * as defaults from './defaults.mjs'
|
||||
|
||||
|
||||
// Clone the settings as we will be touching
|
||||
// on them slightly.
|
||||
let settings = defaults.default(config.get('bunyan'))
|
||||
|
||||
// Replace any instance of 'process.stdout' with the
|
||||
// actual reference to the process.stdout.
|
||||
for (let i = 0; i < settings.streams.length; i++) {
|
||||
/* istanbul ignore else */
|
||||
if (settings.streams[i].stream === 'process.stdout') {
|
||||
settings.streams[i].stream = process.stdout
|
||||
}
|
||||
}
|
||||
|
||||
// Create our logger.
|
||||
const log = bunyan.createLogger(settings)
|
||||
|
||||
export default log
|
|
@ -1,5 +1,5 @@
|
|||
import fs from 'fs'
|
||||
import { HttpError } from '../error.mjs'
|
||||
import { HttpError } from 'flaska'
|
||||
import formidable from 'formidable'
|
||||
import config from '../config.mjs'
|
||||
|
||||
|
@ -36,12 +36,12 @@ export function uploadFile(ctx, siteName, noprefix = false) {
|
|||
let prefix = ''
|
||||
|
||||
var form = new formidable.IncomingForm()
|
||||
form.uploadDir = `./public/${siteName}`
|
||||
form.uploadDir = `${config.get('uploadFolder')}/${siteName}`
|
||||
form.maxFileSize = config.get('fileSize')
|
||||
|
||||
form.parse(ctx.req, function(err, fields, files) {
|
||||
if (err) return rej(err)
|
||||
if (!files || !files.file) return rej(new HttpError('File in body was missing', 422))
|
||||
if (!files || !files.file) return rej(new HttpError(422, 'File in body was missing'))
|
||||
let file = files.file
|
||||
|
||||
Object.keys(fields).forEach(function(key) {
|
||||
|
@ -51,13 +51,13 @@ export function uploadFile(ctx, siteName, noprefix = false) {
|
|||
})
|
||||
ctx.req.body = fields
|
||||
|
||||
if (!noprefix || fs.existsSync(`./public/${siteName}/${prefix}${file.name}`)) {
|
||||
if (!noprefix || fs.existsSync(`${config.get('uploadFolder')}/${siteName}/${prefix}${file.name}`)) {
|
||||
prefix = getPrefix()
|
||||
}
|
||||
|
||||
fs.rename(files.file.path, `./public/${siteName}/${prefix}${file.name}`, function(err) {
|
||||
fs.rename(files.file.path, `${config.get('uploadFolder')}/${siteName}/${prefix}${file.name}`, function(err) {
|
||||
if (err) return rej(err)
|
||||
file.path = `./public/${siteName}/${prefix}${file.name}`
|
||||
file.path = `${config.get('uploadFolder')}/${siteName}/${prefix}${file.name}`
|
||||
file.filename = `${prefix}${file.name}`
|
||||
|
||||
return res(file)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import path from 'path'
|
||||
import sharp from 'sharp'
|
||||
import fs from 'fs/promises'
|
||||
import { HttpError } from '../error.mjs'
|
||||
import config from '../config.mjs'
|
||||
import { HttpError } from 'flaska'
|
||||
import * as security from './security.mjs'
|
||||
import * as formidable from './formidable.mjs'
|
||||
|
||||
|
@ -17,13 +18,27 @@ export default class MediaRoutes {
|
|||
this.collator = new Intl.Collator('is-IS', { numeric: false, sensitivity: 'accent' })
|
||||
}
|
||||
|
||||
register(server) {
|
||||
this.init().then(function() {}, function(err) {
|
||||
server.core.log.error(err, 'Error initing media')
|
||||
})
|
||||
|
||||
server.flaska.get('/media', [server.queryHandler()], this.listFiles.bind(this))
|
||||
server.flaska.get('/media/:site', this.listPublicFiles.bind(this))
|
||||
server.flaska.post('/media', [server.queryHandler()], this.upload.bind(this))
|
||||
server.flaska.post('/media/noprefix', [server.queryHandler()], this.uploadNoPrefix.bind(this))
|
||||
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))
|
||||
}
|
||||
|
||||
init() {
|
||||
return fs.readdir('./public').then(folders => {
|
||||
return fs.readdir(config.get('uploadFolder')).then(folders => {
|
||||
return Promise.all(folders.map(folder => {
|
||||
return fs.readdir('./public/' + folder)
|
||||
return fs.readdir(config.get('uploadFolder') + '/' + folder)
|
||||
.then(files => {
|
||||
return Promise.all(files.map(file => {
|
||||
return fs.stat(`./public/${folder}/${file}`)
|
||||
return fs.stat(`${config.get('uploadFolder')}/${folder}/${file}`)
|
||||
.then(function(stat) {
|
||||
return { filename: file, size: stat.size }
|
||||
})
|
||||
|
@ -94,7 +109,7 @@ export default class MediaRoutes {
|
|||
|
||||
ctx.log.info(`Uploaded ${result.filename}`)
|
||||
|
||||
let stat = await this.fs.stat(`./public/${ctx.state.site}/${result.filename}`)
|
||||
let stat = await this.fs.stat(`${config.get('uploadFolder')}/${ctx.state.site}/${result.filename}`)
|
||||
this.filesCacheAdd(ctx.state.site, result.filename, stat.size)
|
||||
|
||||
ctx.body = {
|
||||
|
@ -124,7 +139,7 @@ export default class MediaRoutes {
|
|||
return Promise.resolve()
|
||||
.then(async () => {
|
||||
let item = ctx.req.body[key]
|
||||
let sharp = this.sharp(`./public/${ctx.state.site}/${sourceFile}`)
|
||||
let sharp = this.sharp(`${config.get('uploadFolder')}/${ctx.state.site}/${sourceFile}`)
|
||||
.rotate()
|
||||
|
||||
for (let operation of allowedOperations) {
|
||||
|
@ -147,9 +162,9 @@ export default class MediaRoutes {
|
|||
}
|
||||
return
|
||||
}
|
||||
await sharp.toFile(`./public/${ctx.state.site}/${target}`)
|
||||
await sharp.toFile(`${config.get('uploadFolder')}/${ctx.state.site}/${target}`)
|
||||
|
||||
let stat = await this.fs.stat(`./public/${ctx.state.site}/${target}`)
|
||||
let stat = await this.fs.stat(`${config.get('uploadFolder')}/${ctx.state.site}/${target}`)
|
||||
this.filesCacheAdd(ctx.state.site, target, stat.size)
|
||||
|
||||
ctx.body[key] = {
|
||||
|
@ -159,7 +174,7 @@ export default class MediaRoutes {
|
|||
}).then(
|
||||
function() {},
|
||||
function(err) {
|
||||
throw new HttpError(`Error processing ${key}: ${err.message}`, 422)
|
||||
throw new HttpError(422, `Error processing ${key}: ${err.message}`)
|
||||
}
|
||||
)
|
||||
}))
|
||||
|
@ -184,9 +199,9 @@ export default class MediaRoutes {
|
|||
|
||||
this.filesCacheRemove(site, ctx.params.filename)
|
||||
|
||||
await this.fs.unlink(`./public/${site}/${ctx.params.filename}`)
|
||||
await this.fs.unlink(`${config.get('uploadFolder')}/${site}/${ctx.params.filename}`)
|
||||
.catch(function(err) {
|
||||
throw new HttpError(`Error removing ${site}/${ctx.params.filename}: ${err.message}`, 422)
|
||||
throw new HttpError(422, `Error removing ${site}/${ctx.params.filename}: ${err.message}`)
|
||||
})
|
||||
|
||||
ctx.status = 204
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { HttpError } from '../error.mjs'
|
||||
import { HttpError } from 'flaska'
|
||||
import decode from '../jwt/decode.mjs'
|
||||
import config from '../config.mjs'
|
||||
|
||||
export function verifyToken(ctx) {
|
||||
let token = ctx.query.get('token')
|
||||
if (!token) {
|
||||
throw new HttpError('Token is missing in query', 422)
|
||||
throw new HttpError(422, 'Token is missing in query')
|
||||
}
|
||||
|
||||
let org = config.get('sites')
|
||||
|
@ -21,14 +21,14 @@ export function verifyToken(ctx) {
|
|||
return decoded.iss
|
||||
} catch (err) {
|
||||
ctx.log.error(err, 'Error decoding token: ' + token)
|
||||
throw new HttpError('Token was invalid', 422)
|
||||
throw new HttpError(422, 'Token was invalid')
|
||||
}
|
||||
}
|
||||
|
||||
export function throwIfNotPublic(site) {
|
||||
let sites = config.get('sites')
|
||||
if (!sites[site] || sites[site].public !== true) {
|
||||
throw new HttpError(`Requested site ${site} did not exist`, 404)
|
||||
throw new HttpError(404, `Requested site ${site} did not exist`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,34 +48,34 @@ export function verifyBody(ctx) {
|
|||
|
||||
for (let key of keys) {
|
||||
if (key === 'filename' || key === 'path') {
|
||||
throw new HttpError('Body item with name filename or path is not allowed', 422)
|
||||
throw new HttpError(422, 'Body item with name filename or path is not allowed')
|
||||
}
|
||||
let item = ctx.req.body[key]
|
||||
|
||||
if (typeof(item) !== 'object'
|
||||
|| !item
|
||||
|| Array.isArray(item)) {
|
||||
throw new HttpError(`Body item ${key} was not valid`, 422)
|
||||
throw new HttpError(422, `Body item ${key} was not valid`)
|
||||
}
|
||||
|
||||
if (typeof(item.format) !== 'string'
|
||||
|| !item.format
|
||||
|| validObjectOperations.includes(item.format)
|
||||
|| item.format === 'out') {
|
||||
throw new HttpError(`Body item ${key} missing valid format`, 422)
|
||||
throw new HttpError(422, `Body item ${key} missing valid format`)
|
||||
}
|
||||
|
||||
if (typeof(item[item.format]) !== 'object'
|
||||
|| !item[item.format]
|
||||
|| Array.isArray(item[item.format])) {
|
||||
throw new HttpError(`Body item ${key} options for format ${item.format} was not valid`, 422)
|
||||
throw new HttpError(422, `Body item ${key} options for format ${item.format} was not valid`)
|
||||
}
|
||||
|
||||
if (item.out != null) {
|
||||
if (typeof(item.out) !== 'string'
|
||||
|| (item.out !== '' && item.out !== 'file' && item.out !== 'base64')
|
||||
) {
|
||||
throw new HttpError(`Body item ${key} key out was invalid`, 422)
|
||||
throw new HttpError(422, `Body item ${key} key out was invalid`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ export function verifyBody(ctx) {
|
|||
if (item[operation] != null) {
|
||||
if (typeof(item[operation]) !== 'object'
|
||||
|| Array.isArray(item[operation])) {
|
||||
throw new HttpError(`Body item ${key} key ${operation} was invalid`, 422)
|
||||
throw new HttpError(422, `Body item ${key} key ${operation} was invalid`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ export function verifyBody(ctx) {
|
|||
for (let operation of validNumberOperations) {
|
||||
if (item[operation] != null) {
|
||||
if (typeof(item[operation]) !== 'number') {
|
||||
throw new HttpError(`Body item ${key} key ${operation} was invalid`, 422)
|
||||
throw new HttpError(422, `Body item ${key} key ${operation} was invalid`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,20 +5,44 @@ import TestRoutes from './test/routes.mjs'
|
|||
import MediaRoutes from './media/routes.mjs'
|
||||
|
||||
import config from './config.mjs'
|
||||
import log from './log.mjs'
|
||||
|
||||
const app = new Flaska({
|
||||
log: log,
|
||||
})
|
||||
export default class Server {
|
||||
constructor(http, port, core, opts = {}) {
|
||||
Object.assign(this, opts)
|
||||
this.http = http
|
||||
this.port = port
|
||||
this.core = core
|
||||
|
||||
app.before(function(ctx) {
|
||||
this.jsonHandler = JsonHandler
|
||||
this.queryHandler = QueryHandler
|
||||
|
||||
this.flaskOptions = {
|
||||
log: this.core.log,
|
||||
}
|
||||
|
||||
this.routes = {
|
||||
test: new TestRoutes(),
|
||||
media: new MediaRoutes(),
|
||||
}
|
||||
}
|
||||
|
||||
run() {
|
||||
// Create our server
|
||||
this.flaska = new Flaska(this.flaskOptions, this.http)
|
||||
|
||||
// configure our server
|
||||
if (config.get('NODE_ENV') === 'development') {
|
||||
this.flaska.devMode()
|
||||
}
|
||||
|
||||
this.flaska.before(function(ctx) {
|
||||
ctx.__started = performance.now()
|
||||
ctx.log = ctx.log.child({
|
||||
ip: ctx.req.headers['x-forwarded-for'] || ctx.req.connection.remoteAddress,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
app.after(function(ctx) {
|
||||
this.flaska.after(function(ctx) {
|
||||
let ended = performance.now() - ctx.__started
|
||||
|
||||
let status = ''
|
||||
|
@ -35,10 +59,9 @@ app.after(function(ctx) {
|
|||
duration: Math.round(ended),
|
||||
status: ctx.status,
|
||||
}, `<-- ${status}${ctx.method} ${ctx.url}`)
|
||||
})
|
||||
|
||||
app.onerror(function(err, ctx) {
|
||||
})
|
||||
|
||||
this.flaska.onerror(function(err, ctx) {
|
||||
if (err.status && err.status >= 400 && err.status < 500) {
|
||||
if (err.body && err.body.request) {
|
||||
ctx.log.warn({ request: err.body.request}, err.message)
|
||||
|
@ -61,26 +84,18 @@ app.onerror(function(err, ctx) {
|
|||
message: err.message,
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const test = new TestRoutes()
|
||||
app.get('/', test.static.bind(test))
|
||||
app.get('/error', test.error.bind(test))
|
||||
// Register our routes
|
||||
let keys = Object.keys(this.routes)
|
||||
for (let key of keys) {
|
||||
this.routes[key].register(this)
|
||||
}
|
||||
|
||||
const media = new MediaRoutes()
|
||||
media.init().then(function() {}, function(err) {
|
||||
log.error(err, 'Error initing media')
|
||||
})
|
||||
app.get('/media', [QueryHandler()], media.listFiles.bind(media))
|
||||
app.get('/media/:site', media.listPublicFiles.bind(media))
|
||||
app.post('/media', [QueryHandler()], media.upload.bind(media))
|
||||
app.post('/media/noprefix', [QueryHandler()], media.uploadNoPrefix.bind(media))
|
||||
app.post('/media/resize', [QueryHandler()], media.resize.bind(media))
|
||||
app.post('/media/resize/:filename', [QueryHandler(), JsonHandler()], media.resizeExisting.bind(media))
|
||||
app.delete('/media/:filename', [QueryHandler()], media.remove.bind(media))
|
||||
// Start listening
|
||||
|
||||
app.listen(config.get('server:port'), function(a,b) {
|
||||
log.info(`Server listening at ${config.get('server:port')}`)
|
||||
})
|
||||
|
||||
export default app
|
||||
return this.flaska.listenAsync(this.port).then(() => {
|
||||
this.core.log.info(`Server is listening on port ${this.port} uploading to ${config.get('uploadFolder')}`)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,11 @@ export default class TestRoutes {
|
|||
Object.assign(this, { })
|
||||
}
|
||||
|
||||
register(server) {
|
||||
server.flaska.get('/', this.static.bind(this))
|
||||
server.flaska.get('/error', this.error.bind(this))
|
||||
}
|
||||
|
||||
static(ctx) {
|
||||
ctx.body = {
|
||||
name: config.get('name'),
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"bunyan": {
|
||||
"name": "storage-upload-test",
|
||||
"streams": [{
|
||||
"stream": "process.stdout",
|
||||
"level": "error"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sites": {
|
||||
"development": {
|
||||
"keys": {
|
||||
"default@HS256": "asdf1234"
|
||||
}
|
||||
},
|
||||
"existing": {
|
||||
"public": true,
|
||||
"keys": {
|
||||
"default@HS256": "asdf1234"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
dev.mjs
Normal file
34
dev.mjs
Normal file
|
@ -0,0 +1,34 @@
|
|||
import fs from 'fs'
|
||||
import { ServiceCore } from 'service-core'
|
||||
import * as index from './index.mjs'
|
||||
|
||||
const port = 4040
|
||||
|
||||
var core = new ServiceCore('storage-upload', import.meta.url, port, '')
|
||||
|
||||
let config = {
|
||||
"sites": {
|
||||
"development": {
|
||||
"keys": {
|
||||
"default@HS256": "asdf1234"
|
||||
}
|
||||
},
|
||||
"existing": {
|
||||
"public": true,
|
||||
"keys": {
|
||||
"default@HS256": "asdf1234"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
config = JSON.parse(fs.readFileSync('./config.json'))
|
||||
} catch {}
|
||||
|
||||
config.port = port
|
||||
|
||||
core.setConfig(config)
|
||||
core.init(index).then(function() {
|
||||
return core.run()
|
||||
})
|
11
index.mjs
Normal file
11
index.mjs
Normal file
|
@ -0,0 +1,11 @@
|
|||
import config from './api/config.mjs'
|
||||
|
||||
export function start(http, port, ctx) {
|
||||
config.sources[1].store = ctx.config
|
||||
|
||||
return import('./api/server.mjs')
|
||||
.then(function(module) {
|
||||
let server = new module.default(http, port, ctx)
|
||||
return server.run()
|
||||
})
|
||||
}
|
17
package.json
17
package.json
|
@ -8,9 +8,20 @@
|
|||
"start:bunyan": "node api/server.mjs | bunyan",
|
||||
"test": "set NODE_ENV=test&& eltro test/**/*.test.mjs -r dot",
|
||||
"test:linux": "NODE_ENV=test eltro 'test/**/*.test.mjs' -r dot",
|
||||
"test:watch": "npm-watch test"
|
||||
"test:watch": "npm-watch test",
|
||||
"dev": "npm-watch dev:server",
|
||||
"dev:server": "node dev.mjs | bunyan"
|
||||
},
|
||||
"watch": {
|
||||
"dev:server": {
|
||||
"patterns": [
|
||||
"api/*",
|
||||
"{index,dev}.mjs"
|
||||
],
|
||||
"extensions": "js,mjs",
|
||||
"quiet": true,
|
||||
"inherit": true
|
||||
},
|
||||
"test": {
|
||||
"patterns": [
|
||||
"{api,test}/*"
|
||||
|
@ -31,13 +42,13 @@
|
|||
},
|
||||
"homepage": "https://github.com/nfp-projects/storage-upload#readme",
|
||||
"dependencies": {
|
||||
"bunyan-lite": "^1.2.0",
|
||||
"flaska": "^1.2.3",
|
||||
"formidable": "^1.2.2",
|
||||
"nconf-lite": "^2.0.0",
|
||||
"sharp": "^0.30.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eltro": "^1.2.3"
|
||||
"eltro": "^1.2.3",
|
||||
"service-core": "^3.0.0"
|
||||
}
|
||||
}
|
||||
|
|
27
test.js
27
test.js
|
@ -1,27 +0,0 @@
|
|||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
|
||||
const env = process.env;
|
||||
|
||||
const mkdirSync = function (dirPath) {
|
||||
try {
|
||||
fs.mkdirSync(dirPath, { recursive: true });
|
||||
} catch (err) {
|
||||
/* istanbul ignore next */
|
||||
if (err.code !== 'EEXIST') {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const cachePath = function () {
|
||||
const npmCachePath = env.npm_config_cache || /* istanbul ignore next */
|
||||
(env.APPDATA ? path.join(env.APPDATA, 'npm-cache') : path.join(os.homedir(), '.npm'));
|
||||
mkdirSync(npmCachePath);
|
||||
const libvipsCachePath = path.join(npmCachePath, '_libvips');
|
||||
mkdirSync(libvipsCachePath);
|
||||
return libvipsCachePath;
|
||||
};
|
||||
|
||||
cachePath()
|
|
@ -1 +0,0 @@
|
|||
{"name":"storage-upload","hostname":"JonatanPC","pid":26596,"level":30,"path":"/","status":200,"ms":4,"msg":"Request finished","time":"2021-10-10T23:55:12.390Z","v":0}
|
|
@ -1,29 +1,66 @@
|
|||
import { stub } from 'eltro'
|
||||
import { ServiceCore } from 'service-core'
|
||||
import Client from './helper.client.mjs'
|
||||
import defaults from '../api/defaults.mjs'
|
||||
import serv from '../api/server.mjs'
|
||||
import * as index from '../index.mjs'
|
||||
|
||||
serv.log = {
|
||||
export const port = 5030
|
||||
|
||||
export const log = {
|
||||
log: stub(),
|
||||
warn: stub(),
|
||||
info: stub(),
|
||||
error: stub(),
|
||||
child: stub(),
|
||||
event: {
|
||||
warn: stub(),
|
||||
info: stub(),
|
||||
error: stub(),
|
||||
}
|
||||
}
|
||||
log.child.returns(log)
|
||||
|
||||
let serverRunning = false
|
||||
|
||||
export function startServer() {
|
||||
if (serverRunning) return Promise.resolve()
|
||||
serverRunning = true
|
||||
|
||||
var core = new ServiceCore('storage-upload', import.meta.url, port, '')
|
||||
core.setConfig({
|
||||
"port": port,
|
||||
"sites": {
|
||||
"development": {
|
||||
"keys": {
|
||||
"default@HS256": "asdf1234"
|
||||
}
|
||||
},
|
||||
"existing": {
|
||||
"public": true,
|
||||
"keys": {
|
||||
"default@HS256": "asdf1234"
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
core.log = log
|
||||
|
||||
return core.init(index).then(function() {
|
||||
return core.run()
|
||||
})
|
||||
}
|
||||
|
||||
serv.log.child.returns(serv.log)
|
||||
|
||||
export const server = serv
|
||||
|
||||
export function createClient() {
|
||||
return new Client()
|
||||
return new Client(port)
|
||||
}
|
||||
|
||||
export function resetLog() {
|
||||
serv.log.log.reset()
|
||||
serv.log.info.reset()
|
||||
serv.log.warn.reset()
|
||||
serv.log.error.reset()
|
||||
log.log.reset()
|
||||
log.info.reset()
|
||||
log.warn.reset()
|
||||
log.error.reset()
|
||||
}
|
||||
|
||||
export function createContext(opts) {
|
||||
|
|
|
@ -4,8 +4,7 @@ import fs from 'fs/promises'
|
|||
import { fileURLToPath } from 'url'
|
||||
import path from 'path'
|
||||
|
||||
import { server, resetLog } from '../helper.server.mjs'
|
||||
import Client from '../helper.client.mjs'
|
||||
import { createClient, startServer, log, resetLog } from '../helper.server.mjs'
|
||||
import encode from '../../api/jwt/encode.mjs'
|
||||
|
||||
let __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
@ -17,10 +16,15 @@ function resolve(file) {
|
|||
const currYear = new Date().getFullYear().toString()
|
||||
|
||||
t.describe('Media (API)', () => {
|
||||
const client = new Client()
|
||||
const secret = 'asdf1234'
|
||||
let client
|
||||
let secret = 'asdf1234'
|
||||
let testFiles = []
|
||||
|
||||
t.before(function() {
|
||||
client = createClient()
|
||||
return startServer()
|
||||
})
|
||||
|
||||
t.after(function() {
|
||||
return Promise.all(testFiles.map(function(file) {
|
||||
return fs.unlink(resolve(`../../public/${file}`)).catch(function() {})
|
||||
|
@ -33,8 +37,8 @@ t.describe('Media (API)', () => {
|
|||
t.timeout(10000).describe('POST /media', function temp() {
|
||||
t.test('should require authentication', async () => {
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
let err = await assert.isRejected(
|
||||
client.upload('/media',
|
||||
resolve('test.png')
|
||||
|
@ -45,19 +49,19 @@ t.describe('Media (API)', () => {
|
|||
assert.match(err.message, /[Tt]oken/)
|
||||
assert.match(err.message, /[Mm]issing/)
|
||||
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(server.log.warn.firstCall[0]), 'string')
|
||||
assert.match(server.log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(server.log.warn.firstCall[0], /[Mm]issing/)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(log.warn.firstCall[0]), 'string')
|
||||
assert.match(log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(log.warn.firstCall[0], /[Mm]issing/)
|
||||
})
|
||||
|
||||
t.test('should verify token correctly', async () => {
|
||||
const assertToken = 'asdf.asdf.asdf'
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(server.log.info.callCount, 0)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
assert.strictEqual(log.info.callCount, 0)
|
||||
|
||||
let err = await assert.isRejected(
|
||||
client.upload('/media?token=' + assertToken,
|
||||
|
@ -69,13 +73,13 @@ t.describe('Media (API)', () => {
|
|||
assert.match(err.message, /[Tt]oken/)
|
||||
assert.match(err.message, /[Ii]nvalid/)
|
||||
|
||||
assert.strictEqual(server.log.error.callCount, 1)
|
||||
assert.strictEqual(server.log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(server.log.warn.firstCall[0]), 'string')
|
||||
assert.match(server.log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(server.log.warn.firstCall[0], /[Ii]nvalid/)
|
||||
assert.ok(server.log.error.lastCall[0] instanceof Error)
|
||||
assert.match(server.log.error.lastCall[1], new RegExp(assertToken))
|
||||
assert.strictEqual(log.error.callCount, 1)
|
||||
assert.strictEqual(log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(log.warn.firstCall[0]), 'string')
|
||||
assert.match(log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(log.warn.firstCall[0], /[Ii]nvalid/)
|
||||
assert.ok(log.error.lastCall[0] instanceof Error)
|
||||
assert.match(log.error.lastCall[1], new RegExp(assertToken))
|
||||
})
|
||||
|
||||
t.test('should upload file and create file', async () => {
|
||||
|
@ -111,8 +115,8 @@ t.describe('Media (API)', () => {
|
|||
t.timeout(10000).describe('POST /media/noprefix', function temp() {
|
||||
t.test('should require authentication', async () => {
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
let err = await assert.isRejected(
|
||||
client.upload('/media/noprefix',
|
||||
resolve('test.png')
|
||||
|
@ -123,19 +127,19 @@ t.describe('Media (API)', () => {
|
|||
assert.match(err.message, /[Tt]oken/)
|
||||
assert.match(err.message, /[Mm]issing/)
|
||||
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(server.log.warn.firstCall[0]), 'string')
|
||||
assert.match(server.log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(server.log.warn.firstCall[0], /[Mm]issing/)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(log.warn.firstCall[0]), 'string')
|
||||
assert.match(log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(log.warn.firstCall[0], /[Mm]issing/)
|
||||
})
|
||||
|
||||
t.test('should verify token correctly', async () => {
|
||||
const assertToken = 'asdf.asdf.asdf'
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(server.log.info.callCount, 0)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
assert.strictEqual(log.info.callCount, 0)
|
||||
|
||||
let err = await assert.isRejected(
|
||||
client.upload('/media/noprefix?token=' + assertToken,
|
||||
|
@ -147,13 +151,13 @@ t.describe('Media (API)', () => {
|
|||
assert.match(err.message, /[Tt]oken/)
|
||||
assert.match(err.message, /[Ii]nvalid/)
|
||||
|
||||
assert.strictEqual(server.log.error.callCount, 1)
|
||||
assert.strictEqual(server.log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(server.log.warn.firstCall[0]), 'string')
|
||||
assert.match(server.log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(server.log.warn.firstCall[0], /[Ii]nvalid/)
|
||||
assert.ok(server.log.error.lastCall[0] instanceof Error)
|
||||
assert.match(server.log.error.lastCall[1], new RegExp(assertToken))
|
||||
assert.strictEqual(log.error.callCount, 1)
|
||||
assert.strictEqual(log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(log.warn.firstCall[0]), 'string')
|
||||
assert.match(log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(log.warn.firstCall[0], /[Ii]nvalid/)
|
||||
assert.ok(log.error.lastCall[0] instanceof Error)
|
||||
assert.match(log.error.lastCall[1], new RegExp(assertToken))
|
||||
})
|
||||
|
||||
t.test('should upload and create file with no prefix', async () => {
|
||||
|
@ -227,8 +231,8 @@ t.describe('Media (API)', () => {
|
|||
t.timeout(10000).describe('POST /media/resize', function temp() {
|
||||
t.test('should require authentication', async () => {
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
let err = await assert.isRejected(
|
||||
client.upload('/media/resize',
|
||||
resolve('test.png')
|
||||
|
@ -239,19 +243,19 @@ t.describe('Media (API)', () => {
|
|||
assert.match(err.message, /[Tt]oken/)
|
||||
assert.match(err.message, /[Mm]issing/)
|
||||
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(server.log.warn.firstCall[0]), 'string')
|
||||
assert.match(server.log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(server.log.warn.firstCall[0], /[Mm]issing/)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(log.warn.firstCall[0]), 'string')
|
||||
assert.match(log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(log.warn.firstCall[0], /[Mm]issing/)
|
||||
})
|
||||
|
||||
t.test('should verify token correctly', async () => {
|
||||
const assertToken = 'asdf.asdf.asdf'
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(server.log.info.callCount, 0)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
assert.strictEqual(log.info.callCount, 0)
|
||||
|
||||
let err = await assert.isRejected(
|
||||
client.upload('/media/resize?token=' + assertToken,
|
||||
|
@ -263,13 +267,13 @@ t.describe('Media (API)', () => {
|
|||
assert.match(err.message, /[Tt]oken/)
|
||||
assert.match(err.message, /[Ii]nvalid/)
|
||||
|
||||
assert.strictEqual(server.log.error.callCount, 1)
|
||||
assert.strictEqual(server.log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(server.log.warn.firstCall[0]), 'string')
|
||||
assert.match(server.log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(server.log.warn.firstCall[0], /[Ii]nvalid/)
|
||||
assert.ok(server.log.error.lastCall[0] instanceof Error)
|
||||
assert.match(server.log.error.lastCall[1], new RegExp(assertToken))
|
||||
assert.strictEqual(log.error.callCount, 1)
|
||||
assert.strictEqual(log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(log.warn.firstCall[0]), 'string')
|
||||
assert.match(log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(log.warn.firstCall[0], /[Ii]nvalid/)
|
||||
assert.ok(log.error.lastCall[0] instanceof Error)
|
||||
assert.match(log.error.lastCall[1], new RegExp(assertToken))
|
||||
})
|
||||
|
||||
t.test('should upload file and create file', async () => {
|
||||
|
@ -458,8 +462,8 @@ t.describe('Media (API)', () => {
|
|||
|
||||
t.test('should require authentication', async () => {
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
let err = await assert.isRejected(
|
||||
client.post(`/media/resize/${sourceFilename}`, {})
|
||||
)
|
||||
|
@ -468,19 +472,19 @@ t.describe('Media (API)', () => {
|
|||
assert.match(err.message, /[Tt]oken/)
|
||||
assert.match(err.message, /[Mm]issing/)
|
||||
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(server.log.warn.firstCall[0]), 'string')
|
||||
assert.match(server.log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(server.log.warn.firstCall[0], /[Mm]issing/)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(log.warn.firstCall[0]), 'string')
|
||||
assert.match(log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(log.warn.firstCall[0], /[Mm]issing/)
|
||||
})
|
||||
|
||||
t.test('should verify token correctly', async () => {
|
||||
const assertToken = 'asdf.asdf.asdf'
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(server.log.info.callCount, 0)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
assert.strictEqual(log.info.callCount, 0)
|
||||
|
||||
let err = await assert.isRejected(
|
||||
client.post(`/media/resize/${sourceFilename}?token=${assertToken}`, {})
|
||||
|
@ -490,13 +494,13 @@ t.describe('Media (API)', () => {
|
|||
assert.match(err.message, /[Tt]oken/)
|
||||
assert.match(err.message, /[Ii]nvalid/)
|
||||
|
||||
assert.strictEqual(server.log.error.callCount, 1)
|
||||
assert.strictEqual(server.log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(server.log.warn.firstCall[0]), 'string')
|
||||
assert.match(server.log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(server.log.warn.firstCall[0], /[Ii]nvalid/)
|
||||
assert.ok(server.log.error.lastCall[0] instanceof Error)
|
||||
assert.match(server.log.error.lastCall[1], new RegExp(assertToken))
|
||||
assert.strictEqual(log.error.callCount, 1)
|
||||
assert.strictEqual(log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(log.warn.firstCall[0]), 'string')
|
||||
assert.match(log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(log.warn.firstCall[0], /[Ii]nvalid/)
|
||||
assert.ok(log.error.lastCall[0] instanceof Error)
|
||||
assert.match(log.error.lastCall[1], new RegExp(assertToken))
|
||||
})
|
||||
|
||||
t.test('should create multiple sizes for existing file', async () => {
|
||||
|
@ -596,8 +600,8 @@ t.describe('Media (API)', () => {
|
|||
t.timeout(10000).describe('DELETE /media/:filename', function temp() {
|
||||
t.test('should require authentication', async () => {
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
let err = await assert.isRejected(
|
||||
client.del('/media/20220105_101610_test1.jpg',
|
||||
resolve('test.png')
|
||||
|
@ -608,19 +612,19 @@ t.describe('Media (API)', () => {
|
|||
assert.match(err.message, /[Tt]oken/)
|
||||
assert.match(err.message, /[Mm]issing/)
|
||||
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(server.log.warn.firstCall[0]), 'string')
|
||||
assert.match(server.log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(server.log.warn.firstCall[0], /[Mm]issing/)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(log.warn.firstCall[0]), 'string')
|
||||
assert.match(log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(log.warn.firstCall[0], /[Mm]issing/)
|
||||
})
|
||||
|
||||
t.test('should verify token correctly', async () => {
|
||||
const assertToken = 'asdf.asdf.asdf'
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(server.log.info.callCount, 0)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
assert.strictEqual(log.info.callCount, 0)
|
||||
|
||||
let err = await assert.isRejected(
|
||||
client.del('/media/20220105_101610_test1.jpg?token=' + assertToken,
|
||||
|
@ -632,13 +636,13 @@ t.describe('Media (API)', () => {
|
|||
assert.match(err.message, /[Tt]oken/)
|
||||
assert.match(err.message, /[Ii]nvalid/)
|
||||
|
||||
assert.strictEqual(server.log.error.callCount, 1)
|
||||
assert.strictEqual(server.log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(server.log.warn.firstCall[0]), 'string')
|
||||
assert.match(server.log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(server.log.warn.firstCall[0], /[Ii]nvalid/)
|
||||
assert.ok(server.log.error.lastCall[0] instanceof Error)
|
||||
assert.match(server.log.error.lastCall[1], new RegExp(assertToken))
|
||||
assert.strictEqual(log.error.callCount, 1)
|
||||
assert.strictEqual(log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(log.warn.firstCall[0]), 'string')
|
||||
assert.match(log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(log.warn.firstCall[0], /[Ii]nvalid/)
|
||||
assert.ok(log.error.lastCall[0] instanceof Error)
|
||||
assert.match(log.error.lastCall[1], new RegExp(assertToken))
|
||||
})
|
||||
|
||||
t.test('should remove the file', async () => {
|
||||
|
@ -691,27 +695,27 @@ t.describe('Media (API)', () => {
|
|||
t.describe('GET /media', function() {
|
||||
t.test('should require authentication', async () => {
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
let err = await assert.isRejected(client.get('/media'))
|
||||
|
||||
assert.strictEqual(err.status, 422)
|
||||
assert.match(err.message, /[Tt]oken/)
|
||||
assert.match(err.message, /[Mm]issing/)
|
||||
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(server.log.warn.firstCall[0]), 'string')
|
||||
assert.match(server.log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(server.log.warn.firstCall[0], /[Mm]issing/)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(log.warn.firstCall[0]), 'string')
|
||||
assert.match(log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(log.warn.firstCall[0], /[Mm]issing/)
|
||||
})
|
||||
|
||||
t.test('should verify token correctly', async () => {
|
||||
const assertToken = 'asdf.asdf.asdf'
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.error.callCount, 0)
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(server.log.info.callCount, 0)
|
||||
assert.strictEqual(log.error.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
assert.strictEqual(log.info.callCount, 0)
|
||||
|
||||
let err = await assert.isRejected(client.get('/media?token=' + assertToken))
|
||||
|
||||
|
@ -719,13 +723,13 @@ t.describe('Media (API)', () => {
|
|||
assert.match(err.message, /[Tt]oken/)
|
||||
assert.match(err.message, /[Ii]nvalid/)
|
||||
|
||||
assert.strictEqual(server.log.error.callCount, 1)
|
||||
assert.strictEqual(server.log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(server.log.warn.firstCall[0]), 'string')
|
||||
assert.match(server.log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(server.log.warn.firstCall[0], /[Ii]nvalid/)
|
||||
assert.ok(server.log.error.lastCall[0] instanceof Error)
|
||||
assert.match(server.log.error.lastCall[1], new RegExp(assertToken))
|
||||
assert.strictEqual(log.error.callCount, 1)
|
||||
assert.strictEqual(log.warn.callCount, 2)
|
||||
assert.strictEqual(typeof(log.warn.firstCall[0]), 'string')
|
||||
assert.match(log.warn.firstCall[0], /[Tt]oken/)
|
||||
assert.match(log.warn.firstCall[0], /[Ii]nvalid/)
|
||||
assert.ok(log.error.lastCall[0] instanceof Error)
|
||||
assert.match(log.error.lastCall[1], new RegExp(assertToken))
|
||||
})
|
||||
|
||||
t.test('should return list of files in specified folder', async () => {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import fs from 'fs/promises'
|
||||
import { Eltro as t, assert, stub } from 'eltro'
|
||||
import { HttpError } from 'flaska'
|
||||
import { createContext } from '../helper.server.mjs'
|
||||
|
||||
import MediaRoutes from '../../api/media/routes.mjs'
|
||||
import { HttpError } from '../../api/error.mjs'
|
||||
|
||||
t.before(function() {
|
||||
return Promise.all([
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
import { Eltro as t, assert} from 'eltro'
|
||||
import { HttpError } from 'flaska'
|
||||
|
||||
import { createContext } from '../helper.server.mjs'
|
||||
import { verifyToken, verifyBody, throwIfNotPublic } from '../../api/media/security.mjs'
|
||||
import { HttpError } from '../../api/error.mjs'
|
||||
import encode from '../../api/jwt/encode.mjs'
|
||||
import config from '../../api/config.mjs'
|
||||
|
||||
t.describe('#throwIfNotPublic()', function() {
|
||||
let backup = {}
|
||||
|
||||
t.before(function() {
|
||||
config.set('sites', {
|
||||
backup = config.sources[1].store
|
||||
config.sources[1].store = {
|
||||
sites: {
|
||||
justatest: {
|
||||
},
|
||||
justatest2: {
|
||||
|
@ -17,7 +21,12 @@ t.describe('#throwIfNotPublic()', function() {
|
|||
justatest3: {
|
||||
public: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
t.after(function() {
|
||||
config.sources[1].store = backup
|
||||
})
|
||||
|
||||
t.test('should throw for sites that do not exist or are null', function() {
|
||||
|
@ -53,14 +62,22 @@ t.describe('#throwIfNotPublic()', function() {
|
|||
})
|
||||
|
||||
t.describe('#verifyToken()', function() {
|
||||
let backup = {}
|
||||
t.before(function() {
|
||||
config.set('sites', {
|
||||
backup = config.sources[1].store
|
||||
config.sources[1].store = {
|
||||
sites: {
|
||||
justatest: {
|
||||
keys: {
|
||||
'default@HS512': 'mysharedkey',
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
t.after(function() {
|
||||
config.sources[1].store = backup
|
||||
})
|
||||
|
||||
t.test('should fail if query token is missing', function() {
|
||||
|
|
|
@ -1,39 +1,41 @@
|
|||
import { Eltro as t, assert} from 'eltro'
|
||||
|
||||
import { createClient, server, resetLog } from './helper.server.mjs'
|
||||
import { createClient, startServer, log, resetLog } from './helper.server.mjs'
|
||||
|
||||
t.describe('Server', function() {
|
||||
let client
|
||||
|
||||
t.before(function() {
|
||||
client = createClient()
|
||||
|
||||
return startServer()
|
||||
})
|
||||
|
||||
t.test('should run', async function() {
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.info.callCount, 0)
|
||||
assert.strictEqual(log.info.callCount, 0)
|
||||
let data = await client.get('/')
|
||||
|
||||
assert.ok(data)
|
||||
assert.ok(data.name)
|
||||
assert.ok(data.version)
|
||||
assert.strictEqual(server.log.info.callCount, 1)
|
||||
assert.strictEqual(server.log.info.lastCall[0].status, 200)
|
||||
assert.match(server.log.info.lastCall[1], /\<-- GET \//)
|
||||
assert.strictEqual(log.info.callCount, 1)
|
||||
assert.strictEqual(log.info.lastCall[0].status, 200)
|
||||
assert.match(log.info.lastCall[1], /\<-- GET \//)
|
||||
})
|
||||
|
||||
t.test('should handle errors fine', async function() {
|
||||
resetLog()
|
||||
assert.strictEqual(server.log.warn.callCount, 0)
|
||||
assert.strictEqual(log.warn.callCount, 0)
|
||||
let data = await assert.isRejected(client.get('/error'))
|
||||
|
||||
assert.ok(data)
|
||||
assert.ok(data.body)
|
||||
assert.strictEqual(data.body.status, 500)
|
||||
assert.match(data.body.message, /test/)
|
||||
assert.strictEqual(server.log.error.firstCall[0].message, 'This is a test')
|
||||
assert.strictEqual(server.log.error.callCount, 2)
|
||||
assert.strictEqual(server.log.error.secondCall[0].status, 500)
|
||||
assert.match(server.log.error.secondCall[1], /\<-- 500 GET \/error/)
|
||||
assert.strictEqual(log.error.firstCall[0].message, 'This is a test')
|
||||
assert.strictEqual(log.error.callCount, 2)
|
||||
assert.strictEqual(log.error.secondCall[0].status, 500)
|
||||
assert.match(log.error.secondCall[1], /\<-- 500 GET \/error/)
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue