Improvements in REST API
This commit is contained in:
parent
d980a31c05
commit
7c8f7874a9
2 changed files with 300 additions and 288 deletions
|
|
@ -31,8 +31,8 @@ function defaultFailParams(e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkAuthToken(token) {
|
function checkAuthToken(token) {
|
||||||
if (token !== Meteor.settings.private.internalApiToken) {
|
if (!Meteor.settings.private.internalApiToken || token !== Meteor.settings.private.internalApiToken) {
|
||||||
const message = `Unauthorized auth token '${token}' in REST API`;
|
const message = 'Unauthorized auth token in REST API';
|
||||||
console.warn(message);
|
console.warn(message);
|
||||||
return restivusError(401, message);
|
return restivusError(401, message);
|
||||||
}
|
}
|
||||||
|
|
@ -45,18 +45,20 @@ function checkLatLonDist(km, lat, lng) {
|
||||||
check(km, NumberBetween(0, Meteor.isDevelopment ? 1000 : 100));
|
check(km, NumberBetween(0, Meteor.isDevelopment ? 1000 : 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Meteor.settings.private.internalApiToken) {
|
||||||
|
console.warn('Meteor.settings.private.internalApiToken is not configured so we don\'t enable our REST API');
|
||||||
|
} else {
|
||||||
// export
|
// export
|
||||||
const apiV1 = new Restivus({
|
const apiV1 = new Restivus({
|
||||||
useDefaultAuth: true,
|
useDefaultAuth: true,
|
||||||
apiPath: 'api',
|
apiPath: 'api',
|
||||||
version: 'v1',
|
version: 'v1',
|
||||||
prettyJson: true
|
prettyJson: true
|
||||||
});
|
});
|
||||||
|
|
||||||
// Generates: POST on /api/users and GET, DELETE /api/users/:id for
|
// Generates: POST on /api/users and GET, DELETE /api/users/:id for
|
||||||
// Meteor.users collection
|
// Meteor.users collection
|
||||||
/* apiV1.addCollection(Meteor.users, {
|
/* apiV1.addCollection(Meteor.users, {
|
||||||
* excludedEndpoints: ['getAll', 'put', 'delete', 'patch', 'get'],
|
* excludedEndpoints: ['getAll', 'put', 'delete', 'patch', 'get'],
|
||||||
* routeOptions: {
|
* routeOptions: {
|
||||||
* authRequired: true
|
* authRequired: true
|
||||||
|
|
@ -71,7 +73,7 @@ const apiV1 = new Restivus({
|
||||||
* }
|
* }
|
||||||
* }); */
|
* }); */
|
||||||
|
|
||||||
apiV1.addCollection(Fires, {
|
apiV1.addCollection(Fires, {
|
||||||
excludedEndpoints: ['put', 'post', 'patch', 'delete'],
|
excludedEndpoints: ['put', 'post', 'patch', 'delete'],
|
||||||
// excludedEndpoints: ['getAll', 'put', 'post', 'patch', 'delete'],
|
// excludedEndpoints: ['getAll', 'put', 'post', 'patch', 'delete'],
|
||||||
routeOptions: {
|
routeOptions: {
|
||||||
|
|
@ -84,37 +86,37 @@ apiV1.addCollection(Fires, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Maps to: /api/v1/status/last-fire-check
|
// Maps to: /api/v1/status/last-fire-check
|
||||||
apiV1.addRoute('status/last-fire-check', { authRequired: false }, {
|
apiV1.addRoute('status/last-fire-check', { authRequired: false }, {
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return SiteSettings.findOne({ name: 'last-fire-check' });
|
return SiteSettings.findOne({ name: 'last-fire-check' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Maps to: /api/v1/status/last-fire-detected
|
// Maps to: /api/v1/status/last-fire-detected
|
||||||
apiV1.addRoute('status/last-fire-detected', { authRequired: false }, {
|
apiV1.addRoute('status/last-fire-detected', { authRequired: false }, {
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return ActiveFiresCollection.findOne({}, { sort: { when: -1 } });
|
return ActiveFiresCollection.findOne({}, { sort: { when: -1 } });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Maps to: /api/v1/status/active-fires-count
|
// Maps to: /api/v1/status/active-fires-count
|
||||||
apiV1.addRoute('status/active-fires-count', { authRequired: false }, {
|
apiV1.addRoute('status/active-fires-count', { authRequired: false }, {
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return { total: ActiveFiresCollection.find({}).count() };
|
return { total: ActiveFiresCollection.find({}).count() };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Maps to: /api/v1/status/uptime
|
// Maps to: /api/v1/status/uptime
|
||||||
apiV1.addRoute('status/uptime', { authRequired: false }, {
|
apiV1.addRoute('status/uptime', { authRequired: false }, {
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return { ms: new Date() - uptime };
|
return { ms: new Date() - uptime };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function getFires(route, full) {
|
function getFires(route, full) {
|
||||||
const lat = Number(route.urlParams.lat);
|
const lat = Number(route.urlParams.lat);
|
||||||
const lng = Number(route.urlParams.lng);
|
const lng = Number(route.urlParams.lng);
|
||||||
const km = Number(route.urlParams.km);
|
const km = Number(route.urlParams.km);
|
||||||
|
|
@ -173,29 +175,29 @@ function getFires(route, full) {
|
||||||
return {
|
return {
|
||||||
total: 0, real: 0, fires: [], falsePos: [], industries: []
|
total: 0, real: 0, fires: [], falsePos: [], industries: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maps to: /api/v1/fires-in/:lat/:lng/:km
|
// Maps to: /api/v1/fires-in/:lat/:lng/:km
|
||||||
// 100 km max
|
// 100 km max
|
||||||
// Ex: http://127.0.0.1:3000/api/v1/fires-in/token/38.736946/-9.142685/100
|
// Ex: http://127.0.0.1:3000/api/v1/fires-in/token/38.736946/-9.142685/100
|
||||||
apiV1.addRoute('fires-in/:token/:lat/:lng/:km', { authRequired: false }, {
|
apiV1.addRoute('fires-in/:token/:lat/:lng/:km', { authRequired: false }, {
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return getFires(this, false);
|
return getFires(this, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiV1.addRoute('fires-in-full/:token/:lat/:lng/:km', { authRequired: false }, {
|
apiV1.addRoute('fires-in-full/:token/:lat/:lng/:km', { authRequired: false }, {
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return getFires(this, true);
|
return getFires(this, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add mobile user:
|
// Add mobile user:
|
||||||
// curl -X POST http://localhost:3000/api/v1/users/mobile -d "token: thisAppAutToken" -d "mobileToken: user-mobile-firebase-token"
|
// curl -X POST http://localhost:3000/api/v1/users/mobile -d "token: thisAppAutToken" -d "mobileToken: user-mobile-firebase-token"
|
||||||
// Response:
|
// Response:
|
||||||
//
|
//
|
||||||
// https://docs.meteor.com/api/passwords.html#Accounts-createUser
|
// https://docs.meteor.com/api/passwords.html#Accounts-createUser
|
||||||
apiV1.addRoute('mobile/users', { authRequired: false }, {
|
apiV1.addRoute('mobile/users', { authRequired: false }, {
|
||||||
post: function post() {
|
post: function post() {
|
||||||
const { token, mobileToken, lang } = this.bodyParams;
|
const { token, mobileToken, lang } = this.bodyParams;
|
||||||
try {
|
try {
|
||||||
|
|
@ -211,14 +213,22 @@ apiV1.addRoute('mobile/users', { authRequired: false }, {
|
||||||
|
|
||||||
let username;
|
let username;
|
||||||
|
|
||||||
|
const already = Meteor.users.find({ fireBaseToken: mobileToken });
|
||||||
|
|
||||||
|
if (already.count() > 1) {
|
||||||
|
return restivusError(500, 'Unexpected error in REST call: several users with that mobile token?');
|
||||||
|
} else if (already.count() === 1) {
|
||||||
|
username = already.fetch()[0].username;
|
||||||
|
} else {
|
||||||
do {
|
do {
|
||||||
username = Random.id(15);
|
username = Random.id(15);
|
||||||
} while (Meteor.users.find({ username }).count() !== 0);
|
} while (Meteor.users.find({ username }).count() !== 0);
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME check valid lang
|
// FIXME check valid lang
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
// Accounts.createUser({ username: mobileToken, lang: 'FIXME' profile: {} });
|
|
||||||
const result = Meteor.users.upsert({
|
const result = Meteor.users.upsert({
|
||||||
fireBaseToken: mobileToken
|
fireBaseToken: mobileToken
|
||||||
}, {
|
}, {
|
||||||
|
|
@ -232,27 +242,30 @@ apiV1.addRoute('mobile/users', { authRequired: false }, {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
console.log(this.bodyParams);
|
console.log(this.bodyParams);
|
||||||
console.log(this.urlParams);
|
console.log(this.urlParams);
|
||||||
console.log(this.queryParams);
|
console.log(this.queryParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
const newUser = Meteor.users.findOne({ username });
|
const upsertUser = Meteor.users.findOne({ username });
|
||||||
|
|
||||||
|
if (debug) console.log(upsertUser);
|
||||||
|
|
||||||
return jsend.success({
|
return jsend.success({
|
||||||
upsertResult: result,
|
upsertResult: result,
|
||||||
username,
|
username,
|
||||||
userId: newUser._id,
|
userId: upsertUser._id,
|
||||||
lang: newUser.lang,
|
lang: upsertUser.lang,
|
||||||
mobileToken: newUser.fireBaseToken
|
mobileToken: upsertUser.fireBaseToken
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// max sitance: 100km
|
// max sitance: 100km
|
||||||
apiV1.addRoute('mobile/subscriptions', { authRequired: false }, {
|
apiV1.addRoute('mobile/subscriptions', { authRequired: false }, {
|
||||||
post: function post() {
|
post: function post() {
|
||||||
const {
|
const {
|
||||||
token,
|
token,
|
||||||
|
|
@ -320,9 +333,9 @@ apiV1.addRoute('mobile/subscriptions', { authRequired: false }, {
|
||||||
|
|
||||||
return jsend.success({});
|
return jsend.success({});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiV1.addRoute('mobile/subscriptions/all', { authRequired: false }, {
|
apiV1.addRoute('mobile/subscriptions/all', { authRequired: false }, {
|
||||||
get: function get() {
|
get: function get() {
|
||||||
const { token, mobileToken } = this.bodyParams;
|
const { token, mobileToken } = this.bodyParams;
|
||||||
try {
|
try {
|
||||||
|
|
@ -363,4 +376,5 @@ apiV1.addRoute('mobile/subscriptions/all', { authRequired: false }, {
|
||||||
|
|
||||||
return jsend.success({ count: toRemove });
|
return jsend.success({ count: toRemove });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -270,9 +270,8 @@ describe('basic api v1 returns', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should del all mobile user subscriptions', async (done) => {
|
it('should del all mobile user subscriptions', async (done) => {
|
||||||
// Add two
|
// Add subs
|
||||||
addSubs(() => {});
|
addSubs(() => {
|
||||||
addSubs(() => {});
|
|
||||||
HTTP.del(url('api/v1/mobile/subscriptions/all'), {
|
HTTP.del(url('api/v1/mobile/subscriptions/all'), {
|
||||||
data: {
|
data: {
|
||||||
token,
|
token,
|
||||||
|
|
@ -284,10 +283,9 @@ describe('basic api v1 returns', () => {
|
||||||
const jsendResult = result.data;
|
const jsendResult = result.data;
|
||||||
chai.expect(jsendResult.status).equal('success');
|
chai.expect(jsendResult.status).equal('success');
|
||||||
chai.expect(typeof jsendResult.data.count).to.equal('number');
|
chai.expect(typeof jsendResult.data.count).to.equal('number');
|
||||||
chai.expect(jsendResult.data.count).to.equal(2);
|
chai.expect(jsendResult.data.count).to.equal(1);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
// TODO remove all subs
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue