diff --git a/lib/cli.js b/lib/cli.js index 74909998..25e323e2 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -871,15 +871,24 @@ program , 'secret (or $SECRET)' , String , process.env.SECRET) + .option('-c, --connect-push ' + , 'push endpoint' + , cliutil.list) .action(function(options) { if (!options.secret) { this.missingArgument('--secret') } + if (!options.connectPush) { + this.missingArgument('--connect-push') + } require('./units/api')({ port: options.port , ssid: options.ssid , secret: options.secret + , endpoints: { + push: options.connectPush + } }) }) @@ -1328,6 +1337,7 @@ program 'api' , '--port', options.apiPort , '--secret', options.authSecret + , '--connect-push', options.bindAppPull ]) // websocket , procutil.fork(__filename, [ diff --git a/lib/units/api/controllers/device.js b/lib/units/api/controllers/device.js index 16ef7555..79473c0f 100644 --- a/lib/units/api/controllers/device.js +++ b/lib/units/api/controllers/device.js @@ -5,12 +5,18 @@ var logger = require('../../../util/logger') var datautil = require('../../../util/datautil') var log = logger.createLogger('api:controllers:device') +var wire = require('../../../wire') +var wireutil = require('../../../wire/util') module.exports = { getDevices: getDevices , getDeviceBySerial: getDeviceBySerial +, reserveDeviceBySerial: reserveDeviceBySerial +, releaseDeviceBySerial: releaseDeviceBySerial } +var log = logger.createLogger('api:contoller:device') + function getDevices(req, res) { dbapi.loadDevices() .then(function(cursor) { @@ -59,3 +65,99 @@ function getDeviceBySerial(req, res) { }) }) } + +function reserveDeviceBySerial(req, res) { + var serial = req.swagger.params.serial.value + + dbapi.loadDevice(serial) + .then(function(device) { + if (device) { + datautil.normalize(device, req.user) + if(!device.using) { + + var requirements = { + 'serial': { + 'value': serial, + 'match': 'exact' + } + } + + req.options.push.send([ + device.channel + , wireutil.envelope( + new wire.GroupMessage( + new wire.OwnerMessage( + req.user.email + , req.user.name + , req.user.group + ) + , null + , wireutil.toDeviceRequirements(requirements) + ) + ) + ]) + + res.json({ + success: true + , device: device + }) + + } else { + res.json(500, { + success: false + , description: 'Device is being used' + }) + } + } else { + res.json(500, { + success: false + , description: 'Bad device serial' + }) + } + }) +} + +function releaseDeviceBySerial(req, res) { + var serial = req.swagger.params.serial.value + + dbapi.loadDevice(serial) + .then(function(device) { + if (device) { + datautil.normalize(device, req.user) + if(device.using && device.owner.email == req.user.email) { + + var requirements = { + 'serial': { + 'value': serial, + 'match': 'exact' + } + } + + req.options.push.send([ + device.channel + , wireutil.envelope( + new wire.UngroupMessage( + wireutil.toDeviceRequirements(requirements) + ) + ) + ]) + + res.json({ + success: true + , device: device + }) + + } else { + res.json(500, { + success: false + , description: 'You cannot kick this device' + }) + } + } else { + res.json(500, { + success: false + , description: 'Bad device serial' + }) + } + }) +} diff --git a/lib/units/api/index.js b/lib/units/api/index.js index dd9f51a4..16fc1711 100644 --- a/lib/units/api/index.js +++ b/lib/units/api/index.js @@ -4,38 +4,61 @@ var path = require('path') var express = require('express') var SwaggerExpress = require('swagger-express-mw') var cookieSession = require('cookie-session') +var Promise = require('bluebird') +var _ = require('lodash') var logger = require('../../util/logger') +var zmqutil = require('../../util/zmqutil') +var srv = require('../../util/srv') +var lifecycle = require('../../util/lifecycle') module.exports = function(options) { var log = logger.createLogger('api') , app = express() , server = http.createServer(app) - var config = { - appRoot: __dirname - , swaggerFile: path.resolve(__dirname, 'swagger', 'api_v1.yaml') - }; + var push = zmqutil.socket('push') + Promise.map(options.endpoints.push, function(endpoint) { + return srv.resolve(endpoint).then(function(records) { + return srv.attempt(records, function(record) { + log.info('Sending output to "%s"', record.url) + push.connect(record.url) + return Promise.resolve(true) + }) + }) + }) + .catch(function(err) { + log.fatal('Unable to connect to push endpoint', err) + lifecycle.fatal() + }) - SwaggerExpress.create(config, function(err, swaggerExpress) { - if (err) { throw err; } + var config = { + appRoot: __dirname + , swaggerFile: path.resolve(__dirname, 'swagger', 'api_v1.yaml') + }; - swaggerExpress.register(app); + SwaggerExpress.create(config, function(err, swaggerExpress) { + if (err) { throw err; } + swaggerExpress.register(app); + }) + + // Adding options in request, so that swagger controller + // can use it. + app.use(function(req, res, next) { + var reqOptions = _.merge(options, { + 'push': push }) - // Adding options in request, so that swagger controller - // can use it. - app.use(function(req, res, next) { - req.options = options - next() - }) + req.options = reqOptions + next() + }) - // TODO: Remove this once frontend is stateless - app.use(cookieSession({ - name: options.ssid - , keys: [options.secret] - })) + // TODO: Remove this once frontend is stateless + app.use(cookieSession({ + name: options.ssid + , keys: [options.secret] + })) - server.listen(options.port) - log.info('Listening on port %d', options.port) + server.listen(options.port) + log.info('Listening on port %d', options.port) } diff --git a/lib/units/api/swagger/api_v1.yaml b/lib/units/api/swagger/api_v1.yaml index 23df5f0d..0af4f604 100644 --- a/lib/units/api/swagger/api_v1.yaml +++ b/lib/units/api/swagger/api_v1.yaml @@ -128,6 +128,58 @@ paths: - accessTokenAuth: [] /swagger.json: x-swagger-pipe: swagger_raw + /devices/{serial}/reserve: + x-swagger-router-controller: device + put: + summary: Reseve Device + description: The device reserve enpoint will reserve a device if device it usable + operationId: reserveDeviceBySerial + tags: + - device + parameters: + - name: serial + in: path + description: Device Serial + required: true + type: string + responses: + "200": + description: Device Information + schema: + $ref: "#/definitions/DeviceResponse" + default: + description: Unexpected Error + schema: + $ref: "#/definitions/ErrorResponse" + security: + - accessTokenAuth: [] + /devices/{serial}/release: + x-swagger-router-controller: device + put: + summary: Device Information + description: The device reserve enpoint will release a device + operationId: releaseDeviceBySerial + tags: + - device + parameters: + - name: serial + in: path + description: Device Serial + required: true + type: string + responses: + "200": + description: Device Information + schema: + $ref: "#/definitions/DeviceResponse" + default: + description: Unexpected Error + schema: + $ref: "#/definitions/ErrorResponse" + security: + - accessTokenAuth: [] + /swagger.json: + x-swagger-pipe: swagger_raw definitions: UserResponse: required: