Expect a complete Login for update in Login API #80
Conversation
| delete updatedLogin.timesUsed; | ||
| } | ||
| const updatedLoginBag = LoginHelper.newPropertyBag(updatedLogin); | ||
| const updatedLoginInfo = LoginHelper.vanillaObjectToLogin(updatedLogin); |
lmorchard
Feb 13, 2019
Author
Contributor
I scratched my head at the description of this issue for a little bit. But, I think the crux of the issue is where modifyLogin() can accept either an nsIPropertyBag or an nsILoginMetaInfo instance.
Switched to the latter, here, on assumption of a full login object modified by the calling code as necessary, rather than a sparse set of updates. So I think that's me understanding the issue correctly.
I scratched my head at the description of this issue for a little bit. But, I think the crux of the issue is where modifyLogin() can accept either an nsIPropertyBag or an nsILoginMetaInfo instance.
Switched to the latter, here, on assumption of a full login object modified by the calling code as necessary, rather than a sparse set of updates. So I think that's me understanding the issue correctly.
jaredhirsch
Feb 13, 2019
Contributor
I think it'd be better to stick with the PropertyBag as the second argument to modifyLogin.
Sorry this wasn't clearer from the bug description. The LoginInfo fields can be updated in this way, but not the LoginMetaInfo fields (timestamps and usage count). As I understand it, the only reason there's a separate interface for the MetaInfo fields is that they were needed after login sync was already done, so each login object actually implements both interfaces: the syncable part, and the non-syncable part. Even with the historical background in mind, it's a confusing and, uh, suboptimal situation.
We could just rely on the touch() method to alter the MetaInfo fields, but that makes update() an annoyingly misleading function name, and causes the grody dual-interface situation to complicate our lives.
I think it'd be better to stick with the PropertyBag as the second argument to modifyLogin.
Sorry this wasn't clearer from the bug description. The LoginInfo fields can be updated in this way, but not the LoginMetaInfo fields (timestamps and usage count). As I understand it, the only reason there's a separate interface for the MetaInfo fields is that they were needed after login sync was already done, so each login object actually implements both interfaces: the syncable part, and the non-syncable part. Even with the historical background in mind, it's a confusing and, uh, suboptimal situation.
We could just rely on the touch() method to alter the MetaInfo fields, but that makes update() an annoyingly misleading function name, and causes the grody dual-interface situation to complicate our lives.
lmorchard
Feb 15, 2019
Author
Contributor
Switched back to a property bag. But, it looks like we might have to rely on touch() for using the timesUsedIncrement property.
Switched back to a property bag. But, it looks like we might have to rely on touch() for using the timesUsedIncrement property.
linuxwolf
Feb 19, 2019
Contributor
relying on touch() seems reasonable to me.
relying on touch() seems reasonable to me.
| then(log, log); | ||
| browser.experiments.logins.get(mockLogin.guid) | ||
| .then(login => | ||
| browser.experiments.logins.update({ ...login, username: "updated" })) |
lmorchard
Feb 13, 2019
Author
Contributor
Oh, and also I think this represents correctly the change in assumptions. I was already using the API this way in datastore.js, oddly enough, which made no functional difference really.
Oh, and also I think this represents correctly the change in assumptions. I was already using the API this way in datastore.js, oddly enough, which made no functional difference really.
jaredhirsch
Feb 13, 2019
Contributor
This looks good, but I'm wondering if we should add clues about the special MetaInfo fields (including the magic timesUsedIncrement property). Would you mind also setting timesUsedIncrement: 1 here, and also bump one of the MetaInfo timestamp fields, then adding the corresponding asserts on the test side? Maybe this'll help future contributors detect the weirdness of the underlying APIs.
This looks good, but I'm wondering if we should add clues about the special MetaInfo fields (including the magic timesUsedIncrement property). Would you mind also setting timesUsedIncrement: 1 here, and also bump one of the MetaInfo timestamp fields, then adding the corresponding asserts on the test side? Maybe this'll help future contributors detect the weirdness of the underlying APIs.
lmorchard
Feb 15, 2019
•
Author
Contributor
Banged my head on this for awhile and I think I've discovered this:
If we supply both timesUsed and timesUsedIncrement in the property bag at the same time, the explicit timesUsed value will likely clobber whatever the result of timesUsedIncrement might be.
That is, depending on whatever the order of enumerated properties ends up being. I haven't dug deep enough to figure out what that order is, though it seemed pretty consistently to clobber the increment.
Worse news is if I try to omit timesUsed in the update call, it comes in as null - which is treated as a 0 for the update.
On the bright side, I was able to update timePasswordChanged.
Banged my head on this for awhile and I think I've discovered this:
If we supply both timesUsed and timesUsedIncrement in the property bag at the same time, the explicit timesUsed value will likely clobber whatever the result of timesUsedIncrement might be.
That is, depending on whatever the order of enumerated properties ends up being. I haven't dug deep enough to figure out what that order is, though it seemed pretty consistently to clobber the increment.
Worse news is if I try to omit timesUsed in the update call, it comes in as null - which is treated as a 0 for the update.
On the bright side, I was able to update timePasswordChanged.
linuxwolf
Feb 19, 2019
Contributor
I think it's reasonable for update() to actively omit timesUsedIncrement -- either the user of this API is properly incrementing timesUsed by hand, or they can use touch().
thoughts? @lmorchard @6a68
I think it's reasonable for update() to actively omit timesUsedIncrement -- either the user of this API is properly incrementing timesUsed by hand, or they can use touch().
thoughts? @lmorchard @6a68
|
Looking good! We've gotten well into the sketch of the LoginInfo and LoginMetaInfo APIs here, couple changes to hopefully smooth the road for future selves or future contributors. |
| delete updatedLogin.timesUsed; | ||
| } | ||
| const updatedLoginBag = LoginHelper.newPropertyBag(updatedLogin); | ||
| const updatedLoginInfo = LoginHelper.vanillaObjectToLogin(updatedLogin); |
jaredhirsch
Feb 13, 2019
Contributor
I think it'd be better to stick with the PropertyBag as the second argument to modifyLogin.
Sorry this wasn't clearer from the bug description. The LoginInfo fields can be updated in this way, but not the LoginMetaInfo fields (timestamps and usage count). As I understand it, the only reason there's a separate interface for the MetaInfo fields is that they were needed after login sync was already done, so each login object actually implements both interfaces: the syncable part, and the non-syncable part. Even with the historical background in mind, it's a confusing and, uh, suboptimal situation.
We could just rely on the touch() method to alter the MetaInfo fields, but that makes update() an annoyingly misleading function name, and causes the grody dual-interface situation to complicate our lives.
I think it'd be better to stick with the PropertyBag as the second argument to modifyLogin.
Sorry this wasn't clearer from the bug description. The LoginInfo fields can be updated in this way, but not the LoginMetaInfo fields (timestamps and usage count). As I understand it, the only reason there's a separate interface for the MetaInfo fields is that they were needed after login sync was already done, so each login object actually implements both interfaces: the syncable part, and the non-syncable part. Even with the historical background in mind, it's a confusing and, uh, suboptimal situation.
We could just rely on the touch() method to alter the MetaInfo fields, but that makes update() an annoyingly misleading function name, and causes the grody dual-interface situation to complicate our lives.
| then(log, log); | ||
| browser.experiments.logins.get(mockLogin.guid) | ||
| .then(login => | ||
| browser.experiments.logins.update({ ...login, username: "updated" })) |
jaredhirsch
Feb 13, 2019
Contributor
This looks good, but I'm wondering if we should add clues about the special MetaInfo fields (including the magic timesUsedIncrement property). Would you mind also setting timesUsedIncrement: 1 here, and also bump one of the MetaInfo timestamp fields, then adding the corresponding asserts on the test side? Maybe this'll help future contributors detect the weirdness of the underlying APIs.
This looks good, but I'm wondering if we should add clues about the special MetaInfo fields (including the magic timesUsedIncrement property). Would you mind also setting timesUsedIncrement: 1 here, and also bump one of the MetaInfo timestamp fields, then adding the corresponding asserts on the test side? Maybe this'll help future contributors detect the weirdness of the underlying APIs.
|
@lmorchard Definitely owe you a beer for this one; I was wrong to suggest sticking with the |
e6ffb9a
to
fd1e141
fd1e141
to
3b17efa
|
Okie doke, I'll merge this and then we can see if anything else needs doing from here. |
|
FWIW, I was about to file a follow-up issue since I thought |
Fixes #58
Testing and Review Notes
Nothing apparent should change. Integration tests should pass, manual item editing should work as expected.