2020module DeckGo.Handler where
2121
2222-- TODO: created_at, updated_at
23+ -- TODO: nullable slide content
2324-- TODO: improve swagger description
2425-- TODO: feed API
2526
@@ -45,9 +46,11 @@ import Servant (Context ((:.)))
4546import Servant.API
4647import Servant.Auth.Firebase (Protected )
4748import UnliftIO
49+ import Data.Char
4850import qualified Data.Aeson as Aeson
4951import qualified Data.Aeson.Types as Aeson
5052import qualified Data.ByteString.Char8 as BS8
53+ import qualified Data.ByteString.Lazy as BSL
5154import qualified Data.HashMap.Strict as HMS
5255import qualified Data.Text as T
5356import qualified Data.Text.Encoding as T
@@ -187,9 +190,6 @@ instance ToJSONObject User where
187190 , " firebase_uid" .= userFirebaseId user
188191 ]
189192
190- instance Aeson. ToJSON User where
191- toJSON = Aeson. Object . toJSONObject
192-
193193instance Aeson. ToJSON UserInfo where
194194 toJSON = Aeson. Object . toJSONObject
195195
@@ -472,19 +472,32 @@ usersPost conn fuid uinfo = do
472472 liftIO $ putStrLn " got DB interface"
473473
474474 let userId = UserId (userInfoFirebaseId uinfo)
475- user = userInfoToUser uinfo
475+ user <- case userInfoToUser uinfo of
476+ Left e -> Servant. throwError Servant. err400
477+ { Servant. errBody = BSL. fromStrict $ T. encodeUtf8 e }
478+ Right user -> pure user
476479 liftIO (dbCreateUser iface userId user) >>= \ case
477480 Left () -> Servant. throwError $ Servant. err409
481+ { Servant. errBody = Aeson. encode (Item userId user) }
478482 Right () -> pure $ Item userId user
479483
480- userInfoToUser :: UserInfo -> User
481- userInfoToUser uinfo = User
482- { userFirebaseId = userInfoFirebaseId uinfo
483- , userUsername = emailToUsername <$> userInfoEmail uinfo
484- }
485-
486- emailToUsername :: T. Text -> Username
487- emailToUsername = Username
484+ userInfoToUser :: UserInfo -> Either T. Text User
485+ userInfoToUser uinfo = User <$>
486+ pure (userInfoFirebaseId uinfo) <*>
487+ (traverse emailToUsername (userInfoEmail uinfo))
488+
489+ emailToUsername :: T. Text -> Either T. Text Username
490+ emailToUsername t = case T. breakOn " @" t of
491+ (" " , _) -> Left (" Invalid email: " <> t)
492+ (out', _) -> case dropBadChars (T. toLower out') of
493+ " " -> Left (" No valid char found: " <> out')
494+ out -> Right $ Username out
495+ where
496+ dropBadChars :: T. Text -> T. Text
497+ dropBadChars = T. concatMap
498+ $ \ case
499+ c | isAscii c && isAlphaNum c -> T. singleton c
500+ | otherwise -> " "
488501
489502usersPostSession :: UserId -> User -> HS. Session (Either () () )
490503usersPostSession uid u = do
@@ -580,7 +593,10 @@ usersPut conn fuid userId uinfo = do
580593 Servant. throwError Servant. err400
581594
582595 iface <- liftIO $ getDbInterface conn
583- let user = userInfoToUser uinfo
596+ user <- case userInfoToUser uinfo of
597+ Left e -> Servant. throwError Servant. err400
598+ { Servant. errBody = BSL. fromStrict $ T. encodeUtf8 e }
599+ Right user -> pure user
584600 liftIO (dbUpdateUser iface userId user) >>= \ case
585601 UserUpdateOk -> pure $ Item userId user -- TODO: check # of affected rows
586602 e -> do -- TODO: handle not found et al.
0 commit comments