diff --git a/docs/api.yaml b/docs/api.yaml index 39c26ea5e..df6a59698 100644 --- a/docs/api.yaml +++ b/docs/api.yaml @@ -1785,6 +1785,16 @@ paths: type: object projects: type: object + session: + description: The current session + type: object + properties: + createdAt: + type: string + description: ISO date format + expiresAt: + type: string + description: ISO date format example: createdAt: 2018-04-18T23:19:14.802Z displayName: My Display Name @@ -1802,6 +1812,9 @@ paths: projects: "1": formTrashCollapsed: false + session: + createdAt: 2018-05-18T23:42:11.406Z + expiresAt: 2018-06-18T23:42:11.406Z 403: description: Forbidden content: diff --git a/lib/resources/users.js b/lib/resources/users.js index a463204f1..8208719f1 100644 --- a/lib/resources/users.js +++ b/lib/resources/users.js @@ -7,7 +7,7 @@ // including this file, may be copied, modified, propagated, or distributed // except according to the terms contained in the LICENSE file. -const { always } = require('ramda'); +const { always, pick } = require('ramda'); const { User } = require('../model/frames'); const { verifyPassword } = require('../util/crypto'); const { success, isTrue } = require('../util/http'); @@ -116,7 +116,11 @@ module.exports = (service, endpoint, anonymousEndpoint) => { return user; } const [ verbs, preferences ] = await Promise.all([ Auth.verbsOn(user.actorId, '*'), UserPreferences.getForUser(user.actorId) ]); - return Object.assign({ verbs, preferences }, user.forApi()); + + const session = auth.session + .map(pick(['createdAt', 'expiresAt'])).get(); + + return Object.assign({ verbs, preferences, session }, user.forApi()); })); // Gets full details of a user by actor id. diff --git a/test/integration/api/users.js b/test/integration/api/users.js index 65d94e715..5a9972186 100644 --- a/test/integration/api/users.js +++ b/test/integration/api/users.js @@ -437,6 +437,24 @@ describe('api: /users', () => { .expect(200) .then(({ body }) => body.email.should.equal('chelsea@getodk.org'))))); + it('should not return session details if not extended', testService((service) => + service.login('alice', (asAlice) => + asAlice.get('/v1/users/current') + .expect(200) + .then(({ body }) => { should.not.exist(body.session); })))); + + it('should return session details if extended', testService((service) => + service.login('alice', (asAlice) => + asAlice.get('/v1/users/current') + .set('X-Extended-Metadata', 'true') + .expect(200) + .then(({ body }) => { + body.session.should.be.an.Object(); + body.session.should.only.have.keys('createdAt', 'expiresAt'); + body.session.createdAt.should.be.an.isoDate(); + body.session.expiresAt.should.be.an.isoDate(); + })))); + it('should not return site-wide verbs if not extended', testService((service) => service.login('alice', (asAlice) => asAlice.get('/v1/users/current')