Open jkarni opened 8 years ago
I think the first question is, what behavior do we want?
My opinion is that a mock server that has AuthProtect should randomly (with some frequency) choose between throwing a 401, a 403, and letting the request pass (to return the random value from the rest of the combinators).
The second question is, how do we get there? And I think your solution goes in the right direction. I think, more generally, we should perhaps consider generating arbitrary values of the Context
. We'd add instances to Arbitrary a => Arbitrary AuthHandler ...
etc. Then not only would we solve the auth-mock problem, but the more general problem of mocking things that need context.
This will run into a problem: contexts are actually polymorphic. So we'll need an existential datatype and a little wit. But if everyone thinks this is the way to go, we can hash it out.
(Your instance looks right to me. But why do you need the HasContextEntry constraint?)
From @RocketPuppy on September 6, 2016 1:29
I should have mentioned it in the original post, but it's late here and it slipped my mind. The reason why I needed to disable authentication in the mock server was because I was using servant-auth-cookie to generate encrypted session cookies. There's no way (that I know of) to generate those cookies manually. The only way I would be able to authenticate is by copying a session cookie from the canonical implementation, and that's not really sustainable.
I think the idea of choosing between 401, 403, and success has merit. My intention with servant-mock is to use it in tests to stub out APIs. With that in mind, having endpoints non-deterministically return 401, 403, or success probably isn't what is wanted in that situation. A test would want to be able to know when it will successfully authenticate, and when it won't in order to test behavior. I do recognize that the same could be said about the Arbitrary response bodies as well. That feels different to me, but I haven't articulated why.
I'm not sure why the HasContextEntry constraint was needed. GHC (7.10) seemed to want it, but it caused the need for UndecidableInstances so I'd be happy to see it gotten rid of. It might have something to do with servant-auth-cookie.
One other thing I forgot to mention is that I also needed an Arbitrary instance for NoContent. Not a hard instance to write, but still another stumbling block.
I opened #2 for the Arbitrary
instance.
From @RocketPuppy on September 6, 2016 0:53
While working on generating a mock server of my API (which is really cool now that I have it working), I ran into several issues regarding AuthProtect.
The first issue is simply that there isn't an instance for HasMock covering the AuthProtect combinator. Now that I've "implemented" one I think I'm starting to see why. The second issue is that authentication using AuthProtect is still done even in the mock servers. I have something working now but I'm not confident in it. I'll try and walk through my steps below.
Suppose an API like:
In order to mock I did the following:
context
is used in the canonical implementation of the API to provide the authentication handler. The first problem I ran into was the lack of aHasMock
instance. I came up with the following:Which I'm not very happy with because it requires UndecidableInstances. The second problem I ran into, after I had that working, was that authentication still happens on the mock server. I'm on the fence as to whether this is actually a problem, but it was undesirable in my circumstances. I came up with the following solution:
mockAuthHandler
is always successful at authenticating a user.Altogether this solution works, in that I can run a mock server and get arbitrary values from the endpoints. But I wouldn't say that servant-mock plays well with AuthProtect.
I'd be interested in better solutions than the one I hacked up here.
Copied from original issue: haskell-servant/servant#596