Description
I put this in a reply on reddit, but it should (also) be put here.
Here are some points which could make this package better. (IMHO)
REPETITION
Seeing as this module has a very specific name, you can drop all the /[hH]aveIBeenOwned/
in the names and just advise the user to import this module qualified. That makes the amount the user types be exactly the same: i.e. HaveIBeenPwned.Config
instead of HaveIBeenOwnedConfig
. PLUS the user can just import [...] as HIBP
so that they only have to type HIBP.Config
.
TRIMMING
The fields of the Config
don't need to start with underscores, you're not using lenses, so is this just an oversight?
I also don't think the haveIBeenOwned
function needs to be a method of a type class. It would accomplish the same goal as a function with the following type:
(MonadLogger m, MonadIO m) => Config -> Text -> m Result
You can remove the MonadPwned
type class, remove the PwnedT
data type and the functions that go along with it, don't export the passwdDigest
and parseHIBPResponse
(because the user doesn't need to ever use those) and you're down to just a Config
, Result
and haveIBeenPwned
. Nice and clean, and really easy to understand in one look at the module.
ADDITION
Maybe add a hibpAddress :: Text
with the current URL for convenience? (https://haveibeenpwned.com
)
And add a paragraph in the module documentation about this being the URL at the time of creation of that package version, and that if it changes in the future, the user can just provide a different URL in the Config
DOCUMENTATION
It could use a bit more explanation in the module about what the goal is, what HIBP is, a bit of explanation what's used under the hood (for example, that this will throw an exception if the apiHost is not a valid URL) and maybe a really short example code snippet of how to use the module.
import Network.HTTP.Client (newManager)
import Network.HTTP.Client.TLS (tlsManagerSettings)
import HaveIBeenPwned as HIBP
main :: IO ()
main = do
mgr <- newManager tlsManagerSettings
let cfg = HIBP.Config mgr hibpAddress
result <- HIBP.haveIBeenPwned cfg "P4ssw0rdT0T35t!"
putStrLn $ case result of
Secure -> "All's good"
Pwned i -> "This password has been pwned " ++ show i ++ " times"
Error -> "Something went wrong, please try again"