Skip to content

Commit

Permalink
Merge pull request #42 from Turistforeningen/feat/validate-checkin-ti…
Browse files Browse the repository at this point in the history
…meout

Feat/validate checkin timeout 🕰
  • Loading branch information
Håvard Ranum authored Sep 8, 2016
2 parents e8d12ee + b7c2749 commit dafe4fc
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 12 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ docker-compose run --rm node npm run test
docker-compose run --rm node npm run lint
```

### Environment

* `CHECKIN_MAX_DISTANCE=200` - Used to validate a users proximity to the coordinates it's checking in to. Distance in meters.
* `CHECKIN_TIMEOUT=86400` - Used to validate that a user is not checking in to the same place more often than this timeout allows. Time in seconds.

## API

### Authentication
Expand Down
7 changes: 4 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ services:
- .:/usr/src/app
env_file: .env
environment:
- CHECKIN_MAX_DISTANCE=200
- CHECKIN_TIMEOUT=86400
- CHOKIDAR_USEPOLLING=true
- MONGO_DB=test
- NODE_ENV=development
- NPM_CONFIG_LOGLEVEL=silent
- NPM_CONFIG_PROGRESS=false
- NPM_CONFIG_SPIN=false
- MONGO_DB=test
- CHOKIDAR_USEPOLLING=true
- VIRTUAL_HOST=sjekkut.app.dnt.privat
- VIRTUAL_PORT=8080
- VIRTUAL_PATH=/api/v2/
- CHECKIN_MAX_DISTANCE=200
command: npm start
20 changes: 20 additions & 0 deletions models/Checkin.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,26 @@ checkinSchema.path('location.coordinates').validate(function validateCoordinates
});
}, `Checkin only within ${process.env.CHECKIN_MAX_DISTANCE} m. radius`);

checkinSchema.path('timestamp').validate(function validateTimestamp(value, cb) {
// Check for checkins from the future
if (new Date(value) > new Date()) {
cb(false);
}

const Checkin = mongoose.model('Checkin', checkinSchema);
const checkinQuarantine = new Date(value);
checkinQuarantine.setSeconds(checkinQuarantine.getSeconds() - process.env.CHECKIN_TIMEOUT);

Checkin.find()
.where('dnt_user_id')
.equals(this.dnt_user_id)
.where('timestamp')
.gt(checkinQuarantine)
.exec((err, result) => {
cb(!result.length);
});
}, `User can not check in to same place twice within ${process.env.CHECKIN_TIMEOUT} seconds`);

checkinSchema.statics.getCheckinsForList = function getCheckinsForList(list) {
const env = process.env.NTB_API_ENV || 'api';
const key = process.env.NTB_API_KEY;
Expand Down
2 changes: 1 addition & 1 deletion test/acceptance/checkin.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ describe('POST /steder/:sted/besok', () => {
const checkinData = {
lon: 8.312466144561768,
lat: 61.63644183145977,
timestamp: '2016-07-07T23:32:50.923Z',
timestamp: '2016-08-01T23:59:59.923Z',
};

it('returns error for missing user auth', () => (
Expand Down
101 changes: 93 additions & 8 deletions test/models/Checkin.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ const assert = require('assert');
const mockery = require('mockery');

describe('Checkin', () => {
before(() => mockery.enable({
useCleanCache: true,
warnOnReplace: false,
warnOnUnregistered: false,
}));
describe('#getCheckinsForList()', () => {
before(() => mockery.enable({
useCleanCache: true,
warnOnReplace: false,
warnOnUnregistered: false,
}));

afterEach(() => mockery.deregisterMock('node-fetch'));
afterEach(() => mockery.deregisterMock('node-fetch'));

after(() => mockery.disable());
after(() => mockery.disable());

describe('#getCheckinsForList()', () => {
it('it returns existing checkins for existing list', () => {
// Mock node-fetch
mockery.registerMock('node-fetch', () => Promise.resolve({
Expand All @@ -34,4 +34,89 @@ describe('Checkin', () => {
});
});
});

describe('#saveCheckin()', () => {
let Checkin;

before(() => mockery.enable({
useCleanCache: true,
warnOnReplace: false,
warnOnUnregistered: false,
}));

beforeEach(() => mockery.registerMock('node-fetch', () => Promise.resolve({
status: 200,
json: () => ({
_id: '400000000000000000000000',
geojson: { type: 'Point', coordinates: [8.31323888888889, 61.63635277777777] },
}),
})));

afterEach(() => mockery.deregisterMock('node-fetch'));

after(() => mockery.disable());

it('rejects checkin from position outside radius', done => {
Checkin = require('../../models/Checkin'); // eslint-disable-line global-require

const checkin = new Checkin({
dnt_user_id: 1234,
ntb_steder_id: '400000000000000000000000',
timestamp: '2016-07-09T23:50:50.923Z',
location: { coordinates: [8.304591, 61.635695] },
});
checkin.save((err, doc) => {
assert.equal(typeof doc, 'undefined');
done();
});
});

it('saves checkin from position inside radius', done => {
const checkinData = {
dnt_user_id: 1234,
ntb_steder_id: '400000000000000000000000',
timestamp: '2016-07-09T23:50:50.923Z',
location: { coordinates: [8.312466144561768, 61.63644183145977] },
};
const checkin = new Checkin(checkinData);

checkin.save((err, doc) => {
assert.equal(err, null);
assert.equal(doc.ntb_steder_id, checkinData.ntb_steder_id);
done();
});
});

it('rejects a second checkin before checkin timeout', done => {
const checkinData = {
dnt_user_id: 1234,
ntb_steder_id: '400000000000000000000000',
timestamp: '2016-07-07T23:50:50.923Z',
location: { coordinates: [8.312466144561768, 61.63644183145977] },
};
const checkin = new Checkin(checkinData);

checkin.save((err, doc) => {
assert.equal(typeof doc, 'undefined');
assert.equal(typeof err.errors.timestamp, 'object');
done();
});
});

it('rejects a checkin from the future', done => {
const checkinData = {
dnt_user_id: 1234,
ntb_steder_id: '400000000000000000000000',
timestamp: new Date().setHours(new Date().getHours() + 24),
location: { coordinates: [8.312466144561768, 61.63644183145977] },
};
const checkin = new Checkin(checkinData);

checkin.save((err, doc) => {
assert.equal(typeof doc, 'undefined');
assert.equal(typeof err.errors.timestamp, 'object');
done();
});
});
});
});

0 comments on commit dafe4fc

Please sign in to comment.