diff --git a/src/app.ts b/src/app.ts index a77dd94cbe..30b670b362 100644 --- a/src/app.ts +++ b/src/app.ts @@ -273,7 +273,12 @@ function createApp(isSecure: boolean): express.Application { extended: false, }) ); - app.use(bodyParser.json({ limit: '1mb' })); + app.use( + bodyParser.json({ + limit: '1mb', + strict: false, + }) + ); // Use fileUpload to handle multi-part uploads app.use(fileUpload()); diff --git a/src/controllers/actions_controller.ts b/src/controllers/actions_controller.ts index 09b6a109c5..498947a1a6 100644 --- a/src/controllers/actions_controller.ts +++ b/src/controllers/actions_controller.ts @@ -95,47 +95,26 @@ function build(): express.Router { */ controller.post('/:actionName', async (request, response) => { const actionName = request.params.actionName; - - const keys = Object.keys(request.body); - if (keys.length != 1) { - const err = 'Incorrect number of parameters.'; - console.log(err, request.body); - response.status(400).send(err); - return; - } - - if (actionName !== keys[0]) { - const err = `Action name must be ${actionName}`; - console.log(err, request.body); - response.status(400).send(err); - return; - } - - if (!Object.prototype.hasOwnProperty.call(request.body[actionName], 'input')) { - response.status(400).send('Missing input'); - return; - } - - const actionParams = request.body[actionName].input; + const input = request.body; const thingId = request.params.thingId; let action = null; if (thingId) { try { const thing = await Things.getThing(thingId); - action = new Action(actionName, actionParams, thing); + action = new Action(actionName, input, thing); } catch (e) { console.error('Thing does not exist', thingId, e); - response.status(404).send(e); return; + response.status(404).send(e); } } else { - action = new Action(actionName, actionParams); + action = new Action(actionName, input); } try { if (thingId) { - await AddonManager.requestAction(thingId, action.getId(), actionName, actionParams); + await AddonManager.requestAction(thingId, action.getId(), actionName, input); } await Actions.add(action); diff --git a/src/models/thing.ts b/src/models/thing.ts index 288cc23dc7..f80ae36774 100644 --- a/src/models/thing.ts +++ b/src/models/thing.ts @@ -324,6 +324,10 @@ export default class Thing extends EventEmitter { return this.properties; } + getActions(): Record { + return this.actions; + } + getEvents(): Record { return this.events; } diff --git a/src/test/integration/actions-test.ts b/src/test/integration/actions-test.ts index cff11902d9..b245d153ef 100644 --- a/src/test/integration/actions-test.ts +++ b/src/test/integration/actions-test.ts @@ -89,19 +89,6 @@ describe('actions/', () => { expect(err.status).toEqual(400); }); - it('should fail to create a new action (wrong name)', async () => { - const descr = { - potato: {}, - }; - const err = await chai - .request(server) - .post(`${Constants.ACTIONS_PATH}/pair`) - .set(...headerAuth(jwt)) - .set('Accept', 'application/json') - .send(descr); - expect(err.status).toEqual(400); - }); - it('should fail when plugin rejects requestAction', async () => { const { id } = thingLight; await addDevice(thingLight); @@ -185,11 +172,7 @@ describe('actions/', () => { it('should list and retrieve the new action by name', async () => { const descr = { - pair: { - input: { - timeout: 60, - }, - }, + timeout: 60, }; const pair = await chai diff --git a/static/js/schema-impl/action/action.js b/static/js/schema-impl/action/action.js index 66d8be75bb..14822207e6 100644 --- a/static/js/schema-impl/action/action.js +++ b/static/js/schema-impl/action/action.js @@ -60,7 +60,7 @@ class ActionDetail { handleClick() { const input = {}; if (typeof this.input === 'undefined') { - API.postJson(this.href, { [this.name]: { input } }).catch((e) => { + API.postJson(this.href, input).catch((e) => { console.error(`Error performing action "${this.name}": ${e}`); }); } else { diff --git a/static/js/schema-impl/capability/thing.js b/static/js/schema-impl/capability/thing.js index 46c6a9e563..8324036db2 100644 --- a/static/js/schema-impl/capability/thing.js +++ b/static/js/schema-impl/capability/thing.js @@ -297,33 +297,34 @@ class Thing { if (format === Constants.ThingFormat.EXPANDED) { // Parse actions if (description.actions) { - let href; - for (const link of description.links) { - if (link.rel === 'actions') { - href = link.href; - break; + for (const name in description.actions) { + const action = description.actions[name]; + + let href; + for (const link of description.actions[name].links) { + if (link.rel === 'action') { + href = link.href; + break; + } } - } - if (href) { - for (const name in description.actions) { - const action = description.actions[name]; - - let detail; - switch (action['@type']) { - case 'LockAction': - detail = new LockActionDetail(this, name, action, href); - break; - case 'UnlockAction': - detail = new UnlockActionDetail(this, name, action, href); - break; - default: - detail = new ActionDetail(this, name, action, href); - break; - } + if (!href) { + continue; + } - this.displayedActions[name] = { detail }; + let detail; + switch (action['@type']) { + case 'LockAction': + detail = new LockActionDetail(this, name, action, href); + break; + case 'UnlockAction': + detail = new UnlockActionDetail(this, name, action, href); + break; + default: + detail = new ActionDetail(this, name, action, href); + break; } + this.displayedActions[name] = { detail }; } } diff --git a/static/js/views/action-input-form.js b/static/js/views/action-input-form.js index 4211b5e9a3..650ba17c2f 100644 --- a/static/js/views/action-input-form.js +++ b/static/js/views/action-input-form.js @@ -242,14 +242,7 @@ class ActionInputForm { } } - let body; - if (input) { - body = { [this.name]: { input } }; - } else { - body = { [this.name]: { input: {} } }; - } - - API.postJson(this.href, body) + API.postJson(this.href, input) .then(() => { window.history.back(); }) diff --git a/static/js/views/things.js b/static/js/views/things.js index 3bbf9ecd89..09bb4d19af 100644 --- a/static/js/views/things.js +++ b/static/js/views/things.js @@ -216,8 +216,8 @@ const ThingsScreen = { } let href; - for (const link of description.links) { - if (link.rel === 'actions') { + for (const link of description.actions[actionName].links) { + if (link.rel === 'action') { href = link.href; break; }