Improvements in REST API

This commit is contained in:
vjrj 2018-06-15 06:39:09 +02:00
parent d980a31c05
commit 7c8f7874a9
2 changed files with 300 additions and 288 deletions

View file

@ -31,8 +31,8 @@ function defaultFailParams(e) {
}
function checkAuthToken(token) {
if (token !== Meteor.settings.private.internalApiToken) {
const message = `Unauthorized auth token '${token}' in REST API`;
if (!Meteor.settings.private.internalApiToken || token !== Meteor.settings.private.internalApiToken) {
const message = 'Unauthorized auth token in REST API';
console.warn(message);
return restivusError(401, message);
}
@ -45,18 +45,20 @@ function checkLatLonDist(km, lat, lng) {
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
const apiV1 = new Restivus({
const apiV1 = new Restivus({
useDefaultAuth: true,
apiPath: 'api',
version: 'v1',
prettyJson: true
});
});
// Generates: POST on /api/users and GET, DELETE /api/users/:id for
// Meteor.users collection
/* apiV1.addCollection(Meteor.users, {
// Generates: POST on /api/users and GET, DELETE /api/users/:id for
// Meteor.users collection
/* apiV1.addCollection(Meteor.users, {
* excludedEndpoints: ['getAll', 'put', 'delete', 'patch', 'get'],
* routeOptions: {
* authRequired: true
@ -71,7 +73,7 @@ const apiV1 = new Restivus({
* }
* }); */
apiV1.addCollection(Fires, {
apiV1.addCollection(Fires, {
excludedEndpoints: ['put', 'post', 'patch', 'delete'],
// excludedEndpoints: ['getAll', 'put', 'post', 'patch', 'delete'],
routeOptions: {
@ -84,37 +86,37 @@ apiV1.addCollection(Fires, {
}
}
}
});
});
// Maps to: /api/v1/status/last-fire-check
apiV1.addRoute('status/last-fire-check', { authRequired: false }, {
// Maps to: /api/v1/status/last-fire-check
apiV1.addRoute('status/last-fire-check', { authRequired: false }, {
get: function get() {
return SiteSettings.findOne({ name: 'last-fire-check' });
}
});
});
// Maps to: /api/v1/status/last-fire-detected
apiV1.addRoute('status/last-fire-detected', { authRequired: false }, {
// Maps to: /api/v1/status/last-fire-detected
apiV1.addRoute('status/last-fire-detected', { authRequired: false }, {
get: function get() {
return ActiveFiresCollection.findOne({}, { sort: { when: -1 } });
}
});
});
// Maps to: /api/v1/status/active-fires-count
apiV1.addRoute('status/active-fires-count', { authRequired: false }, {
// Maps to: /api/v1/status/active-fires-count
apiV1.addRoute('status/active-fires-count', { authRequired: false }, {
get: function get() {
return { total: ActiveFiresCollection.find({}).count() };
}
});
});
// Maps to: /api/v1/status/uptime
apiV1.addRoute('status/uptime', { authRequired: false }, {
// Maps to: /api/v1/status/uptime
apiV1.addRoute('status/uptime', { authRequired: false }, {
get: function get() {
return { ms: new Date() - uptime };
}
});
});
function getFires(route, full) {
function getFires(route, full) {
const lat = Number(route.urlParams.lat);
const lng = Number(route.urlParams.lng);
const km = Number(route.urlParams.km);
@ -173,29 +175,29 @@ function getFires(route, full) {
return {
total: 0, real: 0, fires: [], falsePos: [], industries: []
};
}
}
// Maps to: /api/v1/fires-in/:lat/:lng/:km
// 100 km max
// 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 }, {
// Maps to: /api/v1/fires-in/:lat/:lng/:km
// 100 km max
// 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 }, {
get: function get() {
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() {
return getFires(this, true);
}
});
});
// Add mobile user:
// curl -X POST http://localhost:3000/api/v1/users/mobile -d "token: thisAppAutToken" -d "mobileToken: user-mobile-firebase-token"
// Response:
//
// https://docs.meteor.com/api/passwords.html#Accounts-createUser
apiV1.addRoute('mobile/users', { authRequired: false }, {
// Add mobile user:
// curl -X POST http://localhost:3000/api/v1/users/mobile -d "token: thisAppAutToken" -d "mobileToken: user-mobile-firebase-token"
// Response:
//
// https://docs.meteor.com/api/passwords.html#Accounts-createUser
apiV1.addRoute('mobile/users', { authRequired: false }, {
post: function post() {
const { token, mobileToken, lang } = this.bodyParams;
try {
@ -211,14 +213,22 @@ apiV1.addRoute('mobile/users', { authRequired: false }, {
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 {
username = Random.id(15);
} while (Meteor.users.find({ username }).count() !== 0);
}
// FIXME check valid lang
const now = new Date();
// Accounts.createUser({ username: mobileToken, lang: 'FIXME' profile: {} });
const result = Meteor.users.upsert({
fireBaseToken: mobileToken
}, {
@ -232,27 +242,30 @@ apiV1.addRoute('mobile/users', { authRequired: false }, {
}
});
if (debug) {
console.log(this.bodyParams);
console.log(this.urlParams);
console.log(this.queryParams);
}
const newUser = Meteor.users.findOne({ username });
const upsertUser = Meteor.users.findOne({ username });
if (debug) console.log(upsertUser);
return jsend.success({
upsertResult: result,
username,
userId: newUser._id,
lang: newUser.lang,
mobileToken: newUser.fireBaseToken
userId: upsertUser._id,
lang: upsertUser.lang,
mobileToken: upsertUser.fireBaseToken
});
}
});
});
// max sitance: 100km
apiV1.addRoute('mobile/subscriptions', { authRequired: false }, {
// max sitance: 100km
apiV1.addRoute('mobile/subscriptions', { authRequired: false }, {
post: function post() {
const {
token,
@ -320,9 +333,9 @@ apiV1.addRoute('mobile/subscriptions', { authRequired: false }, {
return jsend.success({});
}
});
});
apiV1.addRoute('mobile/subscriptions/all', { authRequired: false }, {
apiV1.addRoute('mobile/subscriptions/all', { authRequired: false }, {
get: function get() {
const { token, mobileToken } = this.bodyParams;
try {
@ -363,4 +376,5 @@ apiV1.addRoute('mobile/subscriptions/all', { authRequired: false }, {
return jsend.success({ count: toRemove });
}
});
});
}

View file

@ -270,9 +270,8 @@ describe('basic api v1 returns', () => {
});
it('should del all mobile user subscriptions', async (done) => {
// Add two
addSubs(() => {});
addSubs(() => {});
// Add subs
addSubs(() => {
HTTP.del(url('api/v1/mobile/subscriptions/all'), {
data: {
token,
@ -284,10 +283,9 @@ describe('basic api v1 returns', () => {
const jsendResult = result.data;
chai.expect(jsendResult.status).equal('success');
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();
});
});
// TODO remove all subs
});
});