From 25ae4e9c132d6e68ddb389808b8f22c8f43b17cd Mon Sep 17 00:00:00 2001 From: Ben Burwell Date: Mon, 14 Dec 2015 22:23:28 -0500 Subject: Begin rewrite for new OAuth API --- .editorconfig | 11 +++ .npmignore | 3 + Gruntfile.js | 20 ------ LICENSE.md | 25 ++++--- README.md | 164 ++++++++++++--------------------------------- examples/oauth.js | 16 +++++ examples/sample_app.js | 14 ---- lib/Agency.js | 45 ------------- lib/Device.js | 12 ---- lib/active911.js | 63 +---------------- lib/clients/refresh.js | 118 ++++++++++++++++++++++++++++++++ lib/util.js | 3 - package.json | 67 +++++++++--------- tests/active911.js | 128 +++++++++-------------------------- tests/replies/devices.json | 0 15 files changed, 275 insertions(+), 414 deletions(-) create mode 100644 .editorconfig create mode 100644 .npmignore delete mode 100644 Gruntfile.js create mode 100644 examples/oauth.js delete mode 100644 examples/sample_app.js delete mode 100644 lib/Agency.js delete mode 100644 lib/Device.js create mode 100644 lib/clients/refresh.js delete mode 100644 lib/util.js delete mode 100644 tests/replies/devices.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..5ed6bbc --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +max_line_length = 80 + diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..a7abe3b --- /dev/null +++ b/.npmignore @@ -0,0 +1,3 @@ +tests +examples + diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index 34f8dc8..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = function (grunt) { - - grunt.initConfig({ - jshint: { - all: ['lib/*.js', 'examples/*.js'] - }, - mochaTest: { - test: { - options: { - reporter: 'spec' - }, - src: ['tests/*.js'] - } - } - }); - - grunt.loadNpmTasks('grunt-contrib-jshint'); - grunt.loadNpmTasks('grunt-mocha-test'); - grunt.registerTask('default', ['jshint', 'mochaTest']); -}; diff --git a/LICENSE.md b/LICENSE.md index a77e2bf..29a4317 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,13 +1,18 @@ -Copyright 2013 Ben Burwell +The MIT License (MIT) Copyright (c) 2013-2015 Ben Burwell - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: - http://www.apache.org/licenses/LICENSE-2.0 +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 9f3048e..6ec5caa 100644 --- a/README.md +++ b/README.md @@ -1,137 +1,57 @@ Active911 for Node.js ===================== -*Note:* This package was built for an older version of the Active911 API. It will be updated for the new version in the coming weeks. - -by Ben Burwell +by Ben Burwell Installation ------------ -Installation is simple: `npm install active911`. - -You can use it in your project by adding `active911` to your dependencies and running `npm install`. Sample ping: - - var active911 = require('active911')('YOUR_APP_KEY', 'YOUR_API_KEY'); - - active911.ping(function (err) { - if (err) { - return console.log('Could not connect to Active911: ' + err); - } - - console.log('Connection to Active911 established.'); - }); - -Usage ------ - -The `active911` package provides support for the current Active911 API functions. We follow the standard Node.js pattern of `function(options, callback(error, data))`. If an error occurs, the first parameter of the callback will contain the error message. Otherwise, the first parameter will be false and the second parameter will contain the API response. - -### `ping(callback)` - -The `ping` command checks that your API and app keys are valid on the server. It takes only a callback function with a parameter for errors. - -### `getDevice(device_id, callback)` - -Returns some data about the device associated with the `device_id`. - -Example response: - - { - "response_action" : "watch", - "response_alert_id" : 4681099, - "lat" : 44.541404, - "name" : "Joseph Sullivan", - "position_accuracy" : 30, - "response_stamp" : 1371315741, - "device_id" : 2435, - "position_stamp" : 1371463606, - "device_type" : "smartphone", - "lon" : -123.364192 - } - -### `getAlert(alert_id, callback)` - -Returns data about the alert associated with the `alert_id`. - -Example response: - - { - "source" : "", - "priority" : "F3", - "cad_code" : "", - "lat" : 44.5379997, - "place" : "", - "agency_id" : 3, - "state" : "OR", - "map_code" : "", - "city" : "Philomath", - "timestamp" : 1369781684, - "address" : "100 S. 16th ST", - "description" : "Cat in tree", - "details" : "", - "unit" : "", - "lon" : -123.3634479, - "cross_street" : "", - "alert_id" : 4264162, - "units" : "" - } - -### `getLocations(north, south, east, west, callback)` - -Returns an array of locations that exist within the area bounded by `north`, `south`, `east`, and `west`. The parameters should be floating point numbers representing the latitude or longitude, whichever is appropriate for the compass direction. - -For example, - - active911.getLocations(46.12345, 44.54321, -122.00021, -124.132132, function (err, locations) { - if (err) { - return console.log('Unable to retrieve locations: ' + err); - } - - console.log('Returned ' + locations.length + ' locations.'); - }); - -Example response: - - [ - { - "resources" : [], - "lat" : 44.540121, - "name" : "Pinehurst Memorial", - "agency_id" : 3, - "icon_filename" : "icon-flag.png", - "description" : "Main Station Hosp.\nNear the depot\n5 entrances", - "id" : 175, - "lon" : -123.367601, - "icon_color" : "blue" - }, - { - "resources" : [ - { - "extension" : "jpg", - "title" : "Photo", - "id" : 5, - "details" : "", - "size" : 963979 - } - ], - "lat" : 44.541252, - "name" : "Hydrant", - "agency_id" : 3, - "icon_filename" : "icon-hydrant.png", - "description" : "15th & College", - "id" : 700, - "lon" : -123.364689, - "icon_color" : "red" - } - ] +Installation is simple: `npm install --save active911`. + +Basic Usage +----------- + +```javascript +var Active911 = require('active911'); +var client = new Active911.RefreshClient('YOUR REFRESH TOKEN'); + +client.getAgency().then(function(agency) { + console.log(agency.name); +}).catch(function(err) { + console.log('Problem getting Agency details:', err); +}); +``` + +API Methods +----------- + +The following public API methods are available: + +* `getAgency()` +* `getDevice(device_id)` +* `getAlerts()` +* `getDeviceAlerts(device_id)` +* `getAlert(alert_id)` +* `getLocations()` +* `getLocation(location_id)` +* `getResource(resource_id)` + +Each method returns a promise for a result, which will resolve as either an +object or an array, depending on the cardinality (e.g. `getAlerts` resolves as +an array, while `getAlert` resolves as an object). + +For details on the format of the result, please see the [Active911 API +wiki](http://wiki.active911.com/wiki/index.php/Accessing_the_API). Contributing ------------ -Contributions are encouraged. For a list of open issues, see . +Contributions are encouraged. For a list of open issues, see +. More Information ---------------- -More information about the API is available on [the Active911 Github wiki](https://github.com/active911/open-api/wiki). +More information about the API is available on [the Active911 +wiki](http://wiki.active911.com/wiki/index.php/Active911_Developer_API). + diff --git a/examples/oauth.js b/examples/oauth.js new file mode 100644 index 0000000..575d0d0 --- /dev/null +++ b/examples/oauth.js @@ -0,0 +1,16 @@ +var Active911 = require('../'); +var client = new Active911.RefreshClient('YOUR REFRESH TOKEN'); + +client.getAgency().then(function(agency) { + console.log(agency.name); + agency.devices.forEach(function(deviceInfo) { + client.getDevice(deviceInfo.id).then(function(device) { + console.log(device.name); + }).catch(function(err) { + console.log('Error retrieving device info for #' + deviceInfo.id); + }); + }); +}).catch(function(err) { + console.log('Error retrieving agency info:', err); +}); + diff --git a/examples/sample_app.js b/examples/sample_app.js deleted file mode 100644 index a08b039..0000000 --- a/examples/sample_app.js +++ /dev/null @@ -1,14 +0,0 @@ -var Active911 = require('../lib/active911').Active911; - -var oauth_id = '12345'; -var oauth_secret = 'asdf'; -var oauth_scope = 'read_agency read_alert read_device'; - -var api = new Active911(oauth_id, oauth_secret, oauth_scope); -var uri = api.getAuthorizationUri(); -console.log('Please go to ' + uri + ' to authenticate.'); - -api.ready(function() { - console.log('OAuth workflow complete'); - -}); diff --git a/lib/Agency.js b/lib/Agency.js deleted file mode 100644 index c22a141..0000000 --- a/lib/Agency.js +++ /dev/null @@ -1,45 +0,0 @@ -var _util = require('./util'); - -module.exports.Agency = function(options) { - this._id = options.id; - this._name = options.name; - this._address = options.address; - this._city = options.city; - this._state = options.state; - this._latitude = options.latitude; - this._longitude = options.longitude; - this._devices = options.devices; - this._uri = options.uri || _util.API_BASE + '/agency/' + options.id; -}; - -module.exports.Agency.prototype.getId = function() { - return this._id; -}; - -module.exports.Agency.prototype.getName = function() { - return this._name; -}; - -module.exports.Agency.prototype.getAddress = function() { - return this._address; -}; - -module.exports.Agency.prototype.getCity = function() { - return this._city; -}; - -module.exports.Agency.prototype.getState = function() { - return this._state; -}; - -module.exports.Agency.prototype.getLatitude = function() { - return this._latitude; -}; - -module.exports.Agency.prototype.getLongitude = function() { - return this._longitude; -}; - -module.exports.Agency.prototype.getDevices = function() { - return this._devices; -}; diff --git a/lib/Device.js b/lib/Device.js deleted file mode 100644 index bfc4d34..0000000 --- a/lib/Device.js +++ /dev/null @@ -1,12 +0,0 @@ -var _util = require('./util'); - -module.exports.Device = function(options) { - this._id = options.id; - this._name = options.name; - this._latitude = options.latitude; - this._longitude = options.longitude; - this._position_accuracy = options.position_accuracy; - this._position_timestamp = options.position_timestamp; - this._agencies = options.agencies; - this._uri = options.uri || _util.API_BASE + '/devices/' + options.id; -}; diff --git a/lib/active911.js b/lib/active911.js index e75eaca..42e51d0 100644 --- a/lib/active911.js +++ b/lib/active911.js @@ -1,63 +1,6 @@ -var OAuth2 = require('oauth').OAuth2; -var http = require('http'); -var events = require('events'); -var querystring = require('querystring'); -var url = require('url'); -var Agency = require('./Agency.js').Agency; -var Device = require('./Device.js').Device; -var _util = require('./util'); - -module.exports.Agency = Agency; -module.exports.Device = Device; - -// Constructor -module.exports.Active911 = function(client_id, client_secret, scope) { - this._client_id = client_id; - this._client_secret = client_secret; - this._scope = scope; - this._oauth_complete = false; - this._emitter = new events.EventEmitter(); - - // Create the HTTP server that will receive the OAuth code after the user - // has authenticated to Active911. - this._http_server = new http.Server(); - - // The request handler - this._http_server.on('request', function(req, res) { - - // The only thing we care about is the /?code=xxx - var qs = url.parse(req.url).query; - - // If a code has been sent, and we don't already have one, we are good - // to go. - if (qs.split('=')[0] === 'code' && !this._oauth_complete) { - this._oauth_code = qs.split('=')[1]; - this._oauth_complete = true; - emitter.emit('oauth_complete'); - } - - res.writeHead(200, {'Content-Type': 'text/plain'}); - res.end(); - }); - - // Once the server is listening, store its port number for use in auth uri - this._http_server.listen(0, function() { - - }); +var Active911 = { + RefreshClient: require('./clients/refresh.js') }; -module.exports.Active911.prototype.getAuthorizationUri = function() { - - var qs = querystring.stringify({ - client_id: this._client_id, - response_type: 'code', - redirection_uri: 'http://localhost:' + this._oauth_server_port, - scope: this._scope - }); +module.exports = Active911; - return _util.API_BASE_NAME + '/open_api/authorize_agency.php' + qs; -}; - -module.exports.Active911.prototype.ready = function(func) { - emitter.on('oauth_complete', func); -}; diff --git a/lib/clients/refresh.js b/lib/clients/refresh.js new file mode 100644 index 0000000..b4a3930 --- /dev/null +++ b/lib/clients/refresh.js @@ -0,0 +1,118 @@ +var request = require('request'); + +var RefreshClient = function(refreshString) { + if (typeof refreshString !== 'string') { + throw new Error('Refresh token must be supplied'); + } + this._refreshToken = refreshString; + this._accessToken = ''; + this._accessTokenExpiration = Math.floor( new Date()/1000 ); +}; + +RefreshClient.prototype._doRequest = function(url) { + var self = this; + var base = 'https://access.active911.com/interface/open_api/api'; + return new Promise(function(fulfill, reject) { + self._getAccessToken().then(function(token) { + request({ + method: 'GET', + url: base + url, + headers: { + 'Authorization': 'Bearer ' + token + } + }, function(err, res, body) { + if (err) { + reject(err); + } else { + var result = JSON.parse(body); + if (result.result == 'success') { + var properties = Object.getOwnPropertyNames(result.message); + if (properties.length == 0) { + fulfill({}); + } else { + var propertyToReturn = properties[0]; + fulfill(result.message[propertyToReturn]); + } + } else { + reject(result.message); + } + } + }); + }).catch(function(err) { + reject(err); + }); + }); +}; + +RefreshClient.prototype._getAccessToken = function() { + var self = this; + return new Promise(function(fulfill, reject) { + var currentTime = Math.floor( new Date()/1000 ); + if (self._accessTokenExpiration - currentTime <= 10) { + fulfill(self._refreshAccessToken()); + } else { + fulfill(self._accessToken); + } + }); +}; + +RefreshClient.prototype._refreshAccessToken = function() { + var self = this; + return new Promise(function(fulfill, reject) { + request({ + url: 'https://www.active911.com/interface/dev/api_access.php', + method: 'POST', + form: { + 'refresh_token': self._refreshToken + } + }, function(err, res, body) { + if (err) { + reject(err); + } else { + var response = JSON.parse(body); + if (response.access_token && response.expiration) { + self._accessToken = response.access_token; + self._accessTokenExpiration = response.expiration; + fulfill(response.access_token); + } else { + reject(new Error('Malformed access token response')); + } + } + }); + }); +}; + +RefreshClient.prototype.getAgency = function() { + return this._doRequest('/'); +}; + +RefreshClient.prototype.getDevice = function(id) { + return this._doRequest('/devices/' + id); +}; + +RefreshClient.prototype.getAlerts = function() { + return this._doRequest('/alerts'); +}; + +RefreshClient.prototype.getAlert = function(id) { + return this._doRequest('/alerts/' + id); +}; + +RefreshClient.prototype.getDeviceAlerts = function(id) { + return this._doRequest('/devices/' + id + '/alerts'); +}; + +RefreshClient.prototype.getLocations = function() { + return this._doRequest('/locations'); +}; + +RefreshClient.prototype.getLocation = function(id) { + return this._doRequest('/locations/' + id); +}; + +RefreshClient.prototype.getResource = function(id) { + return this._doRequest('/resources/' + id); +}; + +module.exports = RefreshClient; + diff --git a/lib/util.js b/lib/util.js deleted file mode 100644 index 08efbfb..0000000 --- a/lib/util.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports.API_BASE_NAME = 'https://access.active911.com'; -module.exports.API_BASE_PATH = '/interface/open_api/api'; -module.exports.API_BASE = exports.API_BASE_NAME + exports.API_BASE_PATH; diff --git a/package.json b/package.json index 2bf3062..6473beb 100644 --- a/package.json +++ b/package.json @@ -1,33 +1,38 @@ { - "name": "active911", - "version": "0.1.1", - "author": "Ben Burwell ", - "description": "A simple interface to Active911", - "tags": [ "active911", "cad", "fire", "ems", "dispatching" ], - "main": "./lib/active911.js", - "dependencies": { - "oauth": ">=0.9.11" - }, - "devDependencies": { - "mocha": "latest", - "nock": "latest", - "should": "latest", - "grunt-mocha-test": "latest", - "grunt": "latest", - "grunt-cli": "latest", - "grunt-contrib-jshint": "latest" - }, - "scripts": { - "test": "grunt --verbose" - }, - "repository": { - "type": "git", - "url": "https://github.com/benburwell/active911.git" - }, - "bugs": { - "url": "https://github.com/benburwell/active911/issues" - }, - "engines": { - "node": ">=0.10" - } + "name": "active911", + "version": "0.2.0", + "description": "A simple client for the Active911 API", + "main": "./lib/active911.js", + "scripts": { + "test": "mocha tests" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/benburwell/active911.git" + }, + "keywords": [ + "active911", + "client", + "ems", + "fire", + "response", + "api" + ], + "author": "Ben Burwell", + "license": "MIT", + "bugs": { + "url": "https://github.com/benburwell/active911/issues" + }, + "homepage": "https://github.com/benburwell/active911#readme", + "dependencies": { + "request": "^2.67.0" + }, + "engines": { + "node": ">=4.0.0" + }, + "devDependencies": { + "mocha": "^2.3.4", + "nock": "^3.4.0", + "should": "^8.0.1" + } } diff --git a/tests/active911.js b/tests/active911.js index 309aafb..c0a9e1b 100644 --- a/tests/active911.js +++ b/tests/active911.js @@ -1,105 +1,39 @@ -require('should'); -require('nock'); -Active911 = require('../lib/active911.js'); +var should = require('should'); +var nock = require('nock'); +var Active911 = require('../lib/active911.js'); var a911; - -var testDevicesResponse = require('replies/devices.json'); -var testAgencyResponse = require('replies/agency.json'); -var testDeviceResponse = require('replies/device.json'); -var testErrorResponse = require('replies/error.json'); +var testDeviceResponse = require('./replies/device.json'); +var testAgencyResponse = require('./replies/agency.json'); +var testErrorResponse = require('./replies/error.json'); describe('Active911 API', function() { - - beforeEach(function(done) { - a911 = new Active911(); - }); - - describe('#getAgency', function() { - - it('Should return correct agency data', function() { - - nock('https://access.active911.com') - .get('/interface/open_api/api/') - .replyWithFile(200, __dirname + 'replies/agency.json'}); - - a911.getAgency(function(err, agency) { - should.not.exist(err); - agency.should.equal(testAgencyResponse.message.agency); - }); - }); - - it('Should give an error if the API gives an error', function() { - nock('https://access.active911.com') - .get('/interface/open_api/api/') - .replyWithFile(400, __dirname + 'replies/error.json'); - - a911.getAgency(function(err, agency) { - err.should.equal(testErrorResponse.message); - should.not.exist(agency); - }); - }); - - }); - - describe('#getDevices', function() { - it('Should return correct device data', function() { - - nock('https://access.active911.com') - .get('/interface/open_api/api/') - .replyWithFile(400, __dirname + 'replies/agency.json'); - - a911.getDevices(function(err, devices) { - should.not.exist(err); - devices.should.equal(testDevicesResponse.message.devices); - }); - }); - - it('Should give an error if the API gives an error', function() { - nock('https://access.active911.com') - .get('/interface/open_api/api/') - .replyWithFile(400, __dirname + 'replies/error.json'); - - a911.getDevices(function(err, devices) { - err.should.equal(testErrorResponse.message); - should.not.exist(devices); - }); - }); + beforeEach(function(done) { + a911 = new Active911.RefreshClient('CLIENT'); + done(); + }); + + describe('#getAgency', function() { + it('Should return correct agency data', function() { + nock('https://access.active911.com') + .get('/interface/open_api/api/') + .replyWithFile(200, __dirname + 'replies/agency.json'); + a911.getAgency().then(function(agency) { + agency.should.equal(testAgencyResponse.message.agency); + }).catch(function(err) { + should.fail(); + }); }); - describe('#getDevice', function() { - it('Should return correct device data (String id)', function() { - nock('https://access.active911.com') - .get('/interface/open_api/api/devices/1') - .replyWithFile(200, __dirname + 'replies/device.json'); - - a911.getDevice('1', function(err, device) { - should.not.exist(err); - device.should.equal(testDeviceResponse.message.device); - }); - }); - - it('Should return correct device data (Number id)', function() { - nock('https://access.active911.com') - .get('/interface/open_api/api/devices/1') - .replyWithFile(200, __dirname + 'replies/device.json'); - - a911.getDevice(1, function(err, device) { - should.not.exist(err); - device.should.equal(testDeviceResponse.message.device); - }); - }); - - it('Should give an error if the API gives an error', function() { - nock('https://access.active911.com') - .get('/interface/open_api/api/devices/1') - .replyWithFile(400, __dirname + 'replies/error.json'); - - a911.getDevice(1, function(err, device) { - err.should.equal(testErrorResponse.message); - should.not.exist(device); - }); - }); + it('Should give an error if the API gives an error', function() { + nock('https://access.active911.com') + .get('/interface/open_api/api/') + .replyWithFile(400, __dirname + 'replies/error.json'); + a911.getAgency().then(function(err, agency) { + should.fail(); + }).catch(function(err) { + err.should.equal(testErrorResponse.message); + }); }); - + }); }); diff --git a/tests/replies/devices.json b/tests/replies/devices.json deleted file mode 100644 index e69de29..0000000 -- cgit v1.2.3 -- cgit v1.2.3 From b189c8bf0a951b367e610c9941c3aff482a8968e Mon Sep 17 00:00:00 2001 From: Ben Burwell Date: Tue, 15 Dec 2015 21:55:26 -0500 Subject: Update node versions for Travis to test to --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 982fee7..93df440 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,7 @@ language: node_js node_js: - - "0.10" + - "0.12" + - "4.0" + - "4.1" + - "4.2" + -- cgit v1.2.3 From 7636932bc6af6b509269c6adfd620c5283051b3f Mon Sep 17 00:00:00 2001 From: Ben Burwell Date: Wed, 16 Dec 2015 22:09:50 -0500 Subject: Update unit tests --- lib/clients/refresh.js | 6 +- package.json | 10 +-- tests/active911.js | 145 ++++++++++++++++++++++++++++++++++++------- tests/replies/alert.json | 45 ++++++++++++++ tests/replies/alerts.json | 15 +++++ tests/replies/location.json | 22 +++++++ tests/replies/locations.json | 11 ++++ tests/replies/resource.json | 22 +++++++ 8 files changed, 247 insertions(+), 29 deletions(-) create mode 100644 tests/replies/alert.json create mode 100644 tests/replies/alerts.json create mode 100644 tests/replies/location.json create mode 100644 tests/replies/locations.json create mode 100644 tests/replies/resource.json diff --git a/lib/clients/refresh.js b/lib/clients/refresh.js index b4a3930..7b9fde7 100644 --- a/lib/clients/refresh.js +++ b/lib/clients/refresh.js @@ -1,4 +1,6 @@ var request = require('request'); +var Timestamp = require('unix-timestamp'); +Timestamp.round = true; var RefreshClient = function(refreshString) { if (typeof refreshString !== 'string') { @@ -6,7 +8,7 @@ var RefreshClient = function(refreshString) { } this._refreshToken = refreshString; this._accessToken = ''; - this._accessTokenExpiration = Math.floor( new Date()/1000 ); + this._accessTokenExpiration = Timestamp.now(-1); }; RefreshClient.prototype._doRequest = function(url) { @@ -47,7 +49,7 @@ RefreshClient.prototype._doRequest = function(url) { RefreshClient.prototype._getAccessToken = function() { var self = this; return new Promise(function(fulfill, reject) { - var currentTime = Math.floor( new Date()/1000 ); + var currentTime = Timestamp.now(); if (self._accessTokenExpiration - currentTime <= 10) { fulfill(self._refreshAccessToken()); } else { diff --git a/package.json b/package.json index 6473beb..17af6b9 100644 --- a/package.json +++ b/package.json @@ -25,14 +25,16 @@ }, "homepage": "https://github.com/benburwell/active911#readme", "dependencies": { - "request": "^2.67.0" + "request": "^2.67.0", + "unix-timestamp": "^0.2.0" }, "engines": { - "node": ">=4.0.0" + "node": ">=0.12.0" }, "devDependencies": { + "chai": "^3.4.1", + "chai-as-promised": "^5.1.0", "mocha": "^2.3.4", - "nock": "^3.4.0", - "should": "^8.0.1" + "nock": "^3.4.0" } } diff --git a/tests/active911.js b/tests/active911.js index c0a9e1b..0aa9ffa 100644 --- a/tests/active911.js +++ b/tests/active911.js @@ -1,39 +1,138 @@ -var should = require('should'); +var chai = require('chai'); +var should = chai.should(); +var chaiAsPromised = require('chai-as-promised'); +chai.use(chaiAsPromised); var nock = require('nock'); +var Timestamp = require('unix-timestamp'); var Active911 = require('../lib/active911.js'); -var a911; -var testDeviceResponse = require('./replies/device.json'); -var testAgencyResponse = require('./replies/agency.json'); -var testErrorResponse = require('./replies/error.json'); +var client; +var deviceResponse = require('./replies/device.json'); +var agencyResponse = require('./replies/agency.json'); +var alertsResponse = require('./replies/alerts.json'); +var alertResponse = require('./replies/alert.json'); +var locationsResponse = require('./replies/locations.json'); +var locationResponse = require('./replies/location.json'); +var resourceResponse = require('./replies/resource.json'); +var errorResponse = require('./replies/error.json'); + +var nockPath = function(path, response) { + nock('https://access.active911.com') + .get('/interface/open_api/api' + path) + .reply(200, response); +}; + +var nockError = function(path) { + nock('https://access.active911.com') + .get('/interface/open_api/api' + path) + .reply(400, errorResponse); +}; describe('Active911 API', function() { beforeEach(function(done) { - a911 = new Active911.RefreshClient('CLIENT'); + client = new Active911.RefreshClient('CLIENT'); + nock('https://www.active911.com') + .post('/interface/dev/api_access.php') + .reply(200, { + access_token: 'DUMMY', + expiration: Timestamp.now(100) + }); done(); }); describe('#getAgency', function() { - it('Should return correct agency data', function() { - nock('https://access.active911.com') - .get('/interface/open_api/api/') - .replyWithFile(200, __dirname + 'replies/agency.json'); - a911.getAgency().then(function(agency) { - agency.should.equal(testAgencyResponse.message.agency); - }).catch(function(err) { - should.fail(); - }); + it('Should return correct data', function() { + nockPath('/', agencyResponse); + return client.getAgency().should.eventually.deep.equal(agencyResponse.message.agency); }); it('Should give an error if the API gives an error', function() { - nock('https://access.active911.com') - .get('/interface/open_api/api/') - .replyWithFile(400, __dirname + 'replies/error.json'); - a911.getAgency().then(function(err, agency) { - should.fail(); - }).catch(function(err) { - err.should.equal(testErrorResponse.message); - }); + nockError('/'); + return client.getAgency().should.be.rejectedWith(errorResponse.message); + }); + }); + + describe('#getDevice', function() { + it('Should return correct data', function() { + nockPath('/devices/1', deviceResponse); + return client.getDevice(1).should.eventually.deep.equal(deviceResponse.message.device); + }); + + it('Should give an error if the API gives an error', function() { + nockError('/devices/1'); + return client.getDevice(1).should.be.rejectedWith(errorResponse.message); + }); + }); + + describe('#getAlerts', function() { + it('Should return correct data', function() { + nockPath('/alerts', alertsResponse); + return client.getAlerts().should.eventually.deep.equal(alertsResponse.message.alerts); + }); + + it('Should give an error if the API gives an error', function() { + nockError('/alerts'); + return client.getAlerts().should.be.rejectedWith(errorResponse.message); + }); + }); + + describe('#getDeviceAlerts', function() { + it('Should return correct data', function() { + nockPath('/devices/1/alerts', alertsResponse); + return client.getDeviceAlerts(1).should.eventually.deep.equal(alertsResponse.message.alerts); + }); + + it('Should give an error if the API gives an error', function() { + nockError('/devices/1/alerts'); + return client.getDeviceAlerts(1).should.be.rejectedWith(errorResponse.message); + }); + }); + + describe('#getAlert', function() { + it('Should return correct data', function() { + nockPath('/alerts/1', alertResponse); + return client.getAlert(1).should.eventually.deep.equal(alertResponse.message.alert); + }); + + it('Should give an error if the API gives an error', function() { + nockError('/alerts/1'); + return client.getAlert(1).should.be.rejectedWith(errorResponse.message); + }); + }); + + describe('#getLocations', function() { + it('Should return correct data', function() { + nockPath('/locations', locationsResponse); + return client.getLocations().should.eventually.deep.equal(locationsResponse.message.locations); + }); + + it('Should give an error if the API gives an error', function() { + nockError('/locations'); + return client.getLocations().should.be.rejectedWith(errorResponse.message); + }); + }); + + describe('#getLocation', function() { + it('Should return correct data', function() { + nockPath('/locations/1', locationResponse); + return client.getLocation(1).should.eventually.deep.equal(locationResponse.message.location); + }); + + it('Should give an error if the API gives an error', function() { + nockError('/locations/1'); + return client.getLocation(1).should.be.rejectedWith(errorResponse.message); + }); + }); + + describe('#getResource', function() { + it('Should return correct data', function() { + nockPath('/resources/1', resourceResponse); + return client.getResource(1).should.eventually.deep.equal(resourceResponse.message.resource); + }); + + it('Should give an error if the API gives an error', function() { + nockError('/resources/1'); + return client.getResource(1).should.be.rejectedWith(errorResponse.message); }); }); }); diff --git a/tests/replies/alert.json b/tests/replies/alert.json new file mode 100644 index 0000000..f069ae9 --- /dev/null +++ b/tests/replies/alert.json @@ -0,0 +1,45 @@ +{ + "result": "success", + "message": { + "alert": { + "id": "1", + "agency": { + "id": "1", + "uri": "https://access.active911.com/interface/open_api/api/" + }, + "place": "My Place", + "address": "123 Main Street", + "unit": "", + "city": "Allentown", + "state": "PA", + "latitude": 40, + "longitude": -70, + "source": "Source", + "units": "My Units", + "cad_code": "29A1", + "priority": "Priority 3", + "details": "Medical emergency", + "sent": "timestamp", + "description": "My description", + "pagegroups": [ + { + "title": "Group 1", + "prefix": "My Prefix" + } + ], + "map_code": "None", + "received": "Received", + "cross_street": "Cross Street", + "responses": [ + { + "device": { + "id": "1", + "uri": "https://access.active911.com/interface/open_api/api/devices/1" + }, + "timestamp": "123", + "response": "Responding" + } + ] + } + } +} diff --git a/tests/replies/alerts.json b/tests/replies/alerts.json new file mode 100644 index 0000000..0fa10e5 --- /dev/null +++ b/tests/replies/alerts.json @@ -0,0 +1,15 @@ +{ + "result": "success", + "message": { + "alerts": [ + { + "id": 1, + "uri": "https://access.active911.com/interface/open_api/api/alerts/1" + }, + { + "id": 2, + "uri": "https://access.active911.com/interface/open_api/api/alerts/2" + } + ] + } +} diff --git a/tests/replies/location.json b/tests/replies/location.json new file mode 100644 index 0000000..114307e --- /dev/null +++ b/tests/replies/location.json @@ -0,0 +1,22 @@ +{ + "result": "success", + "message": { + "location": { + "id": "1", + "name": "My Resource", + "description": "My Description", + "icon_id": "1", + "icon_color": "blue", + "latitude": 40, + "longitude": -70, + "location_type": "Hydrant", + "resources": [ + { + "id": "1", + "uri": "https://access.active911.com/interface/open_api/api/resources/1" + } + ] + } + } +} + diff --git a/tests/replies/locations.json b/tests/replies/locations.json new file mode 100644 index 0000000..ec12c28 --- /dev/null +++ b/tests/replies/locations.json @@ -0,0 +1,11 @@ +{ + "result": "success", + "message": { + "locations": [ + { + "id": "1", + "uri": "https://access.active911.com/interface/open_api/api/locations/1" + } + ] + } +} diff --git a/tests/replies/resource.json b/tests/replies/resource.json new file mode 100644 index 0000000..19762db --- /dev/null +++ b/tests/replies/resource.json @@ -0,0 +1,22 @@ +{ + "result": "success", + "message": { + "resource": { + "id": "1", + "title": "My Resource", + "filename": "resource.pdf", + "extension": "pdf", + "size": 0, + "details": "My resource details", + "agency": { + "id": "1", + "uri": "https://access.active911.com/interface/open_api/api/" + }, + "location": { + "id": "1", + "uri": "https://access.active911.com/interface/open_api/api/locations/1" + } + } + } +} + -- cgit v1.2.3 From 46a2372c969e075c32ee7a8774c86f3478446510 Mon Sep 17 00:00:00 2001 From: Ben Burwell Date: Wed, 16 Dec 2015 22:22:14 -0500 Subject: Add Travis status to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 6ec5caa..5f48485 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ Active911 for Node.js ===================== +[![Build Status](https://travis-ci.org/benburwell/active911.svg)](https://travis-ci.org/benburwell/active911) + by Ben Burwell Installation -- cgit v1.2.3 From dfd8e6a4543368c16ac9e7d05a860bdedd224ca8 Mon Sep 17 00:00:00 2001 From: Ben Burwell Date: Wed, 16 Dec 2015 22:23:37 -0500 Subject: Add npm version to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5f48485..daf1041 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ Active911 for Node.js ===================== [![Build Status](https://travis-ci.org/benburwell/active911.svg)](https://travis-ci.org/benburwell/active911) +[![npm version](https://badge.fury.io/js/active911.svg)](https://badge.fury.io/js/active911) by Ben Burwell -- cgit v1.2.3 From d82f3d0034d062fb8e76d3b2ef31f7f14c087df8 Mon Sep 17 00:00:00 2001 From: Ben Burwell Date: Sun, 3 Jan 2016 18:29:29 -0500 Subject: Have Travis perform npm releases --- .travis.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 93df440..0149d6d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,15 @@ language: node_js node_js: - - "0.12" - - "4.0" - - "4.1" - - "4.2" - +- '0.12' +- '4.0' +- '4.1' +- '4.2' +deploy: + provider: npm + email: ben@benburwell.com + api_key: + secure: K80NCqYeh/qe9vJXRaXim/C+FJxdbsmtO0exlltRyco8a63cekatzomIRFsVEu6wVxd9vXNyv2ia6hk7nXomYNM+17nFUvG2LKi8o772CpH0b4z/B6Y4YLm1yHlg6fKe+KV6SZkqeNrJnEgJwJ/iMtVSnOfacJQigkuOpz4nhwI= + on: + branch: master + tags: true + repo: benburwell/active911 -- cgit v1.2.3