diff options
author | William Carroll <wpcarro@gmail.com> | 2020-07-28T13·15+0100 |
---|---|---|
committer | William Carroll <wpcarro@gmail.com> | 2020-07-28T13·15+0100 |
commit | b3556648582c02fb5a9a10a6a4525e212397f945 (patch) | |
tree | 45632fe6d63b642ab97aff0f7307f86eaa9cd0ca /src/App.hs | |
parent | b170be937532cf976746a50f26b05ff34c4c9c00 (diff) |
Support /login
Support basic authentication. Note the TODOs that this commit introduces to track some of the remaining work.
Diffstat (limited to 'src/App.hs')
-rw-r--r-- | src/App.hs | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/src/App.hs b/src/App.hs index e9c528ec4eac..f8b81ed98672 100644 --- a/src/App.hs +++ b/src/App.hs @@ -1,18 +1,22 @@ +{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE TypeApplications #-} -------------------------------------------------------------------------------- module App where -------------------------------------------------------------------------------- +import Control.Exception (throwIO) import Control.Monad.IO.Class (liftIO) -import Control.Monad.Logger (runStderrLoggingT) import Data.Function ((&)) import Data.String.Conversions (cs) import Data.Text (Text) import Database.SQLite.Simple import Network.Wai.Handler.Warp as Warp import Servant - import API + +import qualified Crypto.KDF.BCrypt as BC +import qualified Data.Text.Encoding as TE import qualified Types as T -------------------------------------------------------------------------------- @@ -23,14 +27,15 @@ server dbFile = createAccountH :<|> createTripH :<|> deleteTripH :<|> listTripsH + :<|> loginH where createAccountH newUser = liftIO $ createAccount newUser deleteAccountH username = liftIO $ deleteAccount username listAccountsH = liftIO $ listAccounts - createTripH trip = liftIO $ createTrip trip deleteTripH tripPK = liftIO $ deleteTrip tripPK listTripsH = liftIO $ listTrips + loginH creds = liftIO $ login creds -- TODO(wpcarro): Handle failed CONSTRAINTs instead of sending 500s createAccount :: T.CreateAccountRequest -> IO NoContent @@ -73,6 +78,23 @@ server dbFile = createAccountH (tripPK & T.tripPKFields) pure NoContent + -- TODO(wpcarro): Create and store a session token + login :: T.AccountCredentials -> IO (Maybe T.Session) + login (T.AccountCredentials username password) = + withConnection dbFile $ \conn -> do + res <- query conn "SELECT * FROM Accounts WHERE username = ?" + (Only username) + case res of + [T.Account{T.accountUsername,T.accountPassword,T.accountRole}] -> + if T.passwordsMatch password accountPassword then + pure $ Just (T.Session accountUsername accountRole) + else + -- TODO(wpcarro): Catch and return errors over HTTP + throwIO $ err401 { errBody = "Your credentials are invalid" } + + -- In this branch, the user didn't supply a known username. + _ -> throwIO $ err401 { errBody = "Your credentials are invalid" } + mkApp :: FilePath -> IO Application mkApp dbFile = do pure $ serve (Proxy @ API) $ server dbFile |