snaplet-sqlite-simple-jwt-auth 0.1.0.0 → 0.1.1.0
raw patch · 3 files changed
+89/−4 lines, 3 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: DbUser :: Int -> Text -> ByteString -> DbUser
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: [dbuserHashedPass] :: DbUser -> ByteString
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: [dbuserId] :: DbUser -> Int
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: [dbuserLogin] :: DbUser -> Text
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: createInitialSchema :: Connection -> IO ()
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: createTableIfMissing :: MVar Connection -> IO ()
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: data DbUser
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: executeSingle :: (ToRow q) => Query -> q -> H b ()
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: fromDbUser :: DbUser -> User
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: insertUser :: Text -> ByteString -> Handler b SqliteJwt ()
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: instance Database.SQLite.Simple.FromRow.FromRow Snap.Snaplet.SqliteSimple.JwtAuth.Db.DbUser
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: instance GHC.Classes.Eq Snap.Snaplet.SqliteSimple.JwtAuth.Db.DbUser
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: instance GHC.Show.Show Snap.Snaplet.SqliteSimple.JwtAuth.Db.DbUser
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: jwtAuthTable :: Text
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: qconcat :: [Text] -> Query
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: querySingle :: (ToRow q, FromRow a) => Query -> q -> H b (Maybe a)
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: queryUser :: Text -> Handler b SqliteJwt (Maybe DbUser)
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: schemaVersion :: Connection -> IO Int
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: setSchemaVersion :: Connection -> Int -> IO ()
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: tableExists :: Connection -> Text -> IO Bool
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: upgradeSchema :: Connection -> Int -> IO ()
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: userTable :: Text
- Snap.Snaplet.SqliteSimple.JwtAuth.Db: versionTable :: Text
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: DuplicateLogin :: AuthFailure
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: SqliteJwt :: Secret -> MVar Connection -> SqliteJwt
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: UnknownUser :: AuthFailure
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: User :: Int -> Text -> User
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: WrongPassword :: AuthFailure
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: [siteSecret] :: SqliteJwt -> Secret
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: [sqliteJwtConn] :: SqliteJwt -> MVar Connection
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: [userId] :: User -> Int
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: [userLogin] :: User -> Text
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: createUser :: Text -> Text -> Handler b SqliteJwt (Either AuthFailure User)
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: data AuthFailure
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: data SqliteJwt
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: data User
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: jsonResponse :: MonadSnap m => m ()
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: login :: Text -> Text -> Handler b SqliteJwt (Either AuthFailure User)
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: loginUser :: Handler b SqliteJwt ()
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: registerUser :: Handler b SqliteJwt ()
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: reqJSON :: (MonadSnap m, FromJSON b) => m b
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: requireAuth :: (User -> Handler b SqliteJwt a) -> Handler b SqliteJwt a
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: sqliteJwtInit :: String -> Snaplet Sqlite -> SnapletInit b SqliteJwt
- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth: writeJSON :: (MonadSnap m, ToJSON a) => a -> m ()
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: DuplicateLogin :: AuthFailure
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: HttpError :: Int -> String -> HttpError
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: LoginParams :: Text -> Text -> LoginParams
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: SqliteJwt :: Secret -> MVar Connection -> SqliteJwt
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: UnknownUser :: AuthFailure
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: User :: Int -> Text -> User
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: WrongPassword :: AuthFailure
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: [lpLogin] :: LoginParams -> Text
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: [lpPass] :: LoginParams -> Text
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: [siteSecret] :: SqliteJwt -> Secret
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: [sqliteJwtConn] :: SqliteJwt -> MVar Connection
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: [userId] :: User -> Int
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: [userLogin] :: User -> Text
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: data AuthFailure
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: data HttpError
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: data LoginParams
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: data SqliteJwt
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: data User
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: instance Data.Aeson.Types.FromJSON.FromJSON Snap.Snaplet.SqliteSimple.JwtAuth.Types.LoginParams
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: instance Data.Aeson.Types.FromJSON.FromJSON Snap.Snaplet.SqliteSimple.JwtAuth.Types.User
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: instance Data.Aeson.Types.ToJSON.ToJSON Snap.Snaplet.SqliteSimple.JwtAuth.Types.User
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: instance GHC.Classes.Eq Snap.Snaplet.SqliteSimple.JwtAuth.Types.AuthFailure
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: instance GHC.Classes.Eq Snap.Snaplet.SqliteSimple.JwtAuth.Types.User
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: instance GHC.Show.Show Snap.Snaplet.SqliteSimple.JwtAuth.Types.AuthFailure
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: instance GHC.Show.Show Snap.Snaplet.SqliteSimple.JwtAuth.Types.User
- Snap.Snaplet.SqliteSimple.JwtAuth.Types: type H a b = Handler a SqliteJwt b
- Snap.Snaplet.SqliteSimple.JwtAuth.Util: finishEarly :: MonadSnap m => Int -> ByteString -> m b
- Snap.Snaplet.SqliteSimple.JwtAuth.Util: getBoundedJSON :: (MonadSnap m, FromJSON a) => Int64 -> m (Either String a)
- Snap.Snaplet.SqliteSimple.JwtAuth.Util: getKey :: FilePath -> IO ByteString
- Snap.Snaplet.SqliteSimple.JwtAuth.Util: jsonResponse :: MonadSnap m => m ()
- Snap.Snaplet.SqliteSimple.JwtAuth.Util: reqBoundedJSON :: (MonadSnap m, FromJSON a) => Int64 -> m a
- Snap.Snaplet.SqliteSimple.JwtAuth.Util: reqJSON :: (MonadSnap m, FromJSON b) => m b
- Snap.Snaplet.SqliteSimple.JwtAuth.Util: writeJSON :: (MonadSnap m, ToJSON a) => a -> m ()
Files
- snaplet-sqlite-simple-jwt-auth.cabal +2/−2
- src/Snap/Snaplet/SqliteSimple/JwtAuth.hs +17/−2
- src/Snap/Snaplet/SqliteSimple/JwtAuth/JwtAuth.hs +70/−0
snaplet-sqlite-simple-jwt-auth.cabal view
@@ -1,5 +1,5 @@ name: snaplet-sqlite-simple-jwt-auth-version: 0.1.0.0+version: 0.1.1.0 synopsis: Snaplet for JWT authentication with snaplet-sqlite-simple description: JWT authentication snaplet for snaplet-sqlite-simple.@@ -22,7 +22,7 @@ library hs-source-dirs: src exposed-modules: Snap.Snaplet.SqliteSimple.JwtAuth- Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth+ other-modules: Snap.Snaplet.SqliteSimple.JwtAuth.JwtAuth Snap.Snaplet.SqliteSimple.JwtAuth.Db Snap.Snaplet.SqliteSimple.JwtAuth.Util Snap.Snaplet.SqliteSimple.JwtAuth.Types
src/Snap/Snaplet/SqliteSimple/JwtAuth.hs view
@@ -17,10 +17,23 @@ -- | Use these handlers to implement user registration, login and protecting -- routes with authentication. --+ -- The 'registerUser' and 'loginUser' handlers follow a fixed convention for+ -- request parameters and response. To sign up a user or login an existing+ -- user, make a POST request to a route handled by 'registerUser' or+ -- 'loginUser'. Both require input parameters to be passed in as JSON. A+ -- successful user creation or a login will return HTTP 400 code and reply+ -- with a JSON object containing the JWT. Failed login attempts will reply+ -- with an HTTP 401 error and will reply with a JSON object containing the+ -- error message.+ --+ -- Use the 'requireAuth' wrapper for implementing routes that require+ -- authentication. The client side is responsible for passing in a valid+ -- JWT in the Authentication header.+ -- -- If you need to customize error handling or need a different JSON schema -- for communicating between the server and client, you may wish the re-- -- implement these using the low-level handlers documented later in the- -- API ref.+ -- implement 'registerUser' and 'loginUser' using the low-level handlers+ -- documented later in the API ref. , registerUser , loginUser , requireAuth@@ -47,6 +60,8 @@ -- accounts persisted in a SQLite3 database. It's intended use is to protect -- server API routes used in single-page web applications (SPA) and mobile -- applications.+--+-- Passwords are hashed and salted using the BCrypt library. -- -- See the https://github.com/nurpax/snap-reactjs-todo project for a full -- application using this library. It implements a todo application as an SPA
src/Snap/Snaplet/SqliteSimple/JwtAuth/JwtAuth.hs view
@@ -133,6 +133,15 @@ -- Verify authentication from the JWT token passed in the Authorization -- header, and run the user provided 'action' with the logged in user. --+-- Use the following syntax for constructing the Authorization header:+--+-- @+-- Bearer \<JWT\>+-- @+--+-- where \<JWT\> is obtained from the "token" field of a successful call to+-- 'registerUser' or 'loginUser'.+-- -- On errors such as missing or malformed JWT or failure to verify the JWT, -- error out early and issue an HTTP 401 error. requireAuth :: (User -> Handler b SqliteJwt a) -> Handler b SqliteJwt a@@ -173,6 +182,36 @@ jwt <- jwtFromUser user writeJSON $ object [ "token" .= jwt ] +-- | Create a new user.+--+-- Use a POST request for this handler with password and login encoded as JSON+-- in the body of the request:+--+-- @+-- {+-- "login": \<login name\>,+-- "pass": \<password\>+-- }+-- @+--+-- A successful login will reply with an HTTP 400 code and the following JSON:+--+-- @+-- {+-- "token": \<JWT\>+-- }+-- @+--+-- The returned token can be used to make authenticated requests.+--+-- Login and user registration errors will be reported with an HTTP error code+-- 401 and the error message will be sent as a JSON object:+--+-- @+-- {+-- "error": \<message\>+-- }+-- @ registerUser :: Handler b SqliteJwt () registerUser = method POST newUser where@@ -181,8 +220,39 @@ userOrErr <- createUser (lpLogin params) (lpPass params) either handleLoginError loginOK userOrErr +-- | Login an existing user.+--+-- Use a POST request for this handler with password and login encoded as JSON+-- in the body of the request:+--+-- @+-- {+-- "login": \<login name\>,+-- "pass": \<password\>+-- }+-- @+--+-- A successful login will reply with an HTTP 400 code and the following JSON:+--+-- @+-- {+-- "token": \<JWT\>+-- }+-- @+--+-- The returned token can be used to make authenticated requests.+--+-- Login and user registration errors will be reported with an HTTP error code+-- 401 and the error message will be sent as a JSON object:+--+-- @+-- {+-- "error": \<message\>+-- }+-- @ loginUser :: Handler b SqliteJwt () loginUser = method POST $ do params <- reqJSON userOrErr <- login (lpLogin params) (lpPass params) either handleLoginError loginOK userOrErr+