refactor(token): remove ability to pass createdAt to Token.create #1764
Conversation
var now = Date.now() - 1 | ||
return Token.createNewToken(Token, { createdAt: now }).then(token => { | ||
assert.equal(token.createdAt, now, 'token.createdAt is correct') | ||
assert.notEqual(token.createdAt, now, 'token.createdAt is new') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The anally-retentive pedant inside me thinks this should assert that token.createdAt > now
rather than just asserting inequality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mocha pretty prints equal
and notEqual
assertions better than it can ok
assertions. 🤷♂️
@@ -41,41 +41,13 @@ module.exports = function (log, config, random, P, hkdf, Bundle, error) { | |||
this.createdAt = details.createdAt || 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every time I see this line, it confuses me. Can someone remind me why we need || 0
here again please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I mean, as opposed to || Date.now()
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most recently, because the API test client in ./tests/client/ calls fromHex
without specifying the createdAt
time, so we gotta default it to something, and zero is much safer than e.g. the current time.
Of course the right answer might be to fix those damn tests to use the API correctly, or to use a simpler wrapper around it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Defaulting to Date.now might give us back that bug with tokens that never expire.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yeah, thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's this perhaps unintuitive contract in the Token
API, which is:
Token.create
is for generating brand new tokens, and socreatedAt = Date.now()
Token.from
(fromHex
,fromId
) is for building a pre-existingToken
, and socreatedAt
should definitely be providednew Token
doesn't know which context it is being used in, so just defaults to believing the token is from 1969 until told otherwise.
) | ||
} | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something about deleting all three of these tests sits uneasily with me. I feel like, to some extent, they were legitimately asserting edge-case behaviour of the devices API.
Now that the tests are run in-process, is it possible to retain some of this coverage by mocking the result of Date.now()
? Do we want to do that or am I being over-cautious?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It all depends on what exactly we hoped these were testing. My Pull Request CSI suggested that this was added as a regression test that our joi validation of lastAccessTime
allowed a value of 0
. This was the main reason for it being a "remote" test, so that it went through response validation.
If we want to still test that, a simple unit test in local should be pretty easy:
const schema = getRoute('/accounts/devices').config.response.schema.lastAccessTime
assert(!Joi.validate({ lastAccessTime: 0 }, schema).error)
If we were testing specific behavior of handlers, and not response validation, that can probably also become local tests, with the edges cases specifically mocked in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It all depends on what exactly we hoped these were testing. My Pull Request CSI suggested that this was added as a regression test that our joi validation of
lastAccessTime
allowed a value of0
.
That's definitely case for the first one, above, but the two underneath look different to me. It seems like they're testing how the guts of the devices endpoint behaves when it encounters odd session tokens. Is that something we're definitely happy to lose coverage of?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can definitely adapt these tests to not pass _createdAt, but I don't fully understand what they are testing. Is it the behavior of updateDevice? The devices get route? I'll be sure to update the test description too once we know XD
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be wrong about all this of course, but for what it's worth I read them as testing the behaviour of GET /account/devices
. Definitely don't keep them if you don't think they add value though. I just wanted to make sure we'd considered them is all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I've audited what these tests were doing:
sessionToken.lastAccessTime === 0
: Testing that the route allows returning a last access time of 0, because of the default value in the DB of 0. I've added a local unit test making asserting thatlastAccessTime: 0
passes the Joi validation.sessionToken.lastAccessTime === -1
: Simply is testing that/account/create
fails with_createdAt=-1
. Since that parameter is not even accepted anymore, test is no longer needed.sessionToken.lastAccessTime === FUTURE
: The access time is not adjusted anywhere in devices.upsert or devices.get routes, so this was only testing the initial creation of a device with a sessionToken from the future. The only code that adjusted the timestamp if it was in the future was inoptionallyOverrideCreatedAt
. So, the test was exercising our optional override, which has also been removed in this PR.
I believe the tests now accurately reflect the world.
I support this change and will be glad to see the back of |
bf2cf0c
to
c4255d2
Compare
This exists to support passing `_createdAt` as a query parameter, but only for our tests. Those tests were to exercise our response validation in a way that the `lastAccessTime` allows a value of 0. That validation was fixed long ago, and supporting this hacky parameter has done nothing but plague us since. Burn the heretic.
c4255d2
to
dac8f64
Compare
This exists to support passing
_createdAt
as a query parameter, butonly for our tests. Those tests were to exercise our response
validation in a way that the
lastAccessTime
allows a value of 0. Thatvalidation was fixed long ago, and supporting this hacky parameter has
done nothing but plague us since.
Burn the heretic.
/cc @philbooth @rfk