Skip to content
This repository was archived by the owner on Feb 6, 2024. It is now read-only.

Commit 00477dc

Browse files
committed
handler: add decks by owner
1 parent 5e3a591 commit 00477dc

File tree

4 files changed

+93
-45
lines changed

4 files changed

+93
-45
lines changed

infra/firebase-login/src/Servant/Auth/Firebase.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ verifyUser mgr (ProjectId projectId) (UnverifiedJWT jwt) = do
5353
-- TODO: proper error handling here
5454
let req =
5555
HTTP.setRequestSecure True .
56+
HTTP.setRequestPort 443 .
5657
HTTP.setRequestHost "www.googleapis.com" .
5758
HTTP.setRequestPath "/robot/v1/metadata/x509/[email protected]" .
5859
HTTP.setRequestManager mgr $

infra/handler/app/Handler.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ main = do
1919
liftIO $ putStrLn "Booted!"
2020

2121
-- TODO: from env
22-
let projectId = ProjectId "my-project-id"
22+
let projectId = ProjectId "deckdeckgo-studio-beta"
2323

2424
Lambda.run $ Cors.simpleCors $ DeckGo.Handler.application (env ^. Aws.envManager) projectId env

infra/handler/app/Test.hs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,16 @@ main = do
2525
Right [] -> pure ()
2626
Right decks -> error $ "Expected 0 users, got: " <> show decks
2727

28-
runClientM (decksGet' b) clientEnv >>= \case
28+
runClientM (decksGet' b Nothing) clientEnv >>= \case
2929
Left err -> error $ "Expected decks, got error: " <> show err
3030
Right [] -> pure ()
3131
Right decks -> error $ "Expected 0 decks, got: " <> show decks
3232

33-
let someDeck = Deck { deckSlides = [] , deckDeckname = Deckname "foo" }
33+
let someUserId = UserId "foo"
3434

35-
deckId <- runClientM (decksPost' someDeck) clientEnv >>= \case
35+
let someDeck = Deck { deckSlides = [] , deckDeckname = Deckname "foo", deckOwnerId = someUserId }
36+
37+
deckId <- runClientM (decksPost' b someDeck) clientEnv >>= \case
3638
Left err -> error $ "Expected new deck, got error: " <> show err
3739
Right (WithId deckId _) -> pure deckId
3840

@@ -42,13 +44,13 @@ main = do
4244
Left err -> error $ "Expected new slide, got error: " <> show err
4345
Right (WithId slideId _) -> pure slideId
4446

45-
let newDeck = Deck { deckSlides = [ slideId ], deckDeckname = Deckname "bar" }
47+
let newDeck = Deck { deckSlides = [ slideId ], deckDeckname = Deckname "bar", deckOwnerId = someUserId }
4648

4749
runClientM (decksPut' b deckId newDeck) clientEnv >>= \case
4850
Left err -> error $ "Expected updated deck, got error: " <> show err
4951
Right {} -> pure ()
5052

51-
runClientM (decksGet' b) clientEnv >>= \case
53+
runClientM (decksGet' b Nothing) clientEnv >>= \case
5254
Left err -> error $ "Expected decks, got error: " <> show err
5355
Right decks ->
5456
if decks == [WithId deckId newDeck] then pure () else (error $ "Expected updated decks, got: " <> show decks)
@@ -92,7 +94,7 @@ main = do
9294
Left err -> error $ "Expected deck delete, got error: " <> show err
9395
Right {} -> pure ()
9496

95-
runClientM (decksGet' b) clientEnv >>= \case
97+
runClientM (decksGet' b Nothing) clientEnv >>= \case
9698
Left err -> error $ "Expected no decks, got error: " <> show err
9799
Right decks ->
98100
if decks == [] then pure () else (error $ "Expected no decks, got: " <> show decks)
@@ -104,9 +106,9 @@ _usersPost' :: T.Text -> User -> ClientM (WithId UserId User)
104106
_usersPut' :: T.Text -> UserId -> User -> ClientM (WithId UserId User)
105107
_usersDelete' :: T.Text -> UserId -> ClientM ()
106108

107-
decksGet' :: T.Text -> ClientM [WithId DeckId Deck]
109+
decksGet' :: T.Text -> Maybe UserId -> ClientM [WithId DeckId Deck]
108110
decksGetDeckId' :: T.Text -> DeckId -> ClientM (WithId DeckId Deck)
109-
decksPost' :: Deck -> ClientM (WithId DeckId Deck)
111+
decksPost' :: T.Text -> Deck -> ClientM (WithId DeckId Deck)
110112
decksPut' :: T.Text -> DeckId -> Deck -> ClientM (WithId DeckId Deck)
111113
decksDelete' :: T.Text -> DeckId -> ClientM ()
112114

infra/handler/src/DeckGo/Handler.hs

Lines changed: 81 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ data ServerContext = ServerContext { firebaseProjectId :: Firebase.ProjectId }
5353
data WithId id a = WithId id a
5454
deriving (Show, Eq, Generic)
5555

56+
-- data Item a = Item { itemId :: T.Text, itemContent :: a }
57+
58+
-- class ToJSONObject a where
59+
-- toJSONObject :: a -> Aeson.Object
60+
61+
62+
-- instance ToJSONObject a => Aeson.ToJSON a where
63+
5664
-- USERS
5765

5866
type UsersAPI =
@@ -71,9 +79,11 @@ newtype Username = Username { unUsername :: T.Text }
7179
deriving newtype (Aeson.FromJSON, Aeson.ToJSON)
7280

7381
data User = User
74-
{ userDecks :: [DeckId]
75-
, userFirebaseId :: FirebaseId -- TODO: enforce uniqueness
76-
, userUsername :: Username
82+
-- { userDecks :: [DeckId]
83+
{ userFirebaseId :: FirebaseId -- TODO: enforce uniqueness
84+
-- , userUsername :: Username -- drop for now
85+
, userAnonymous :: Bool
86+
-- isanonymous
7787
} deriving (Show, Eq)
7888

7989
newtype UserId = UserId { unUserId :: T.Text }
@@ -103,39 +113,42 @@ newtype FirebaseId = FirebaseId { unFirebaseId :: T.Text }
103113
instance Aeson.FromJSON User where
104114
parseJSON = Aeson.withObject "user" $ \obj ->
105115
User
106-
<$> obj .: "user_username"
107-
<*> obj .: "user_decks"
108-
<*> obj .: "user_firebaseid"
116+
-- potentially return "error exists" + user object
117+
<$> obj .: "user_firebase_uid"
118+
<*> obj .: "user_anonymous" -- TODO: TTL
109119

110120
instance Aeson.ToJSON User where
111121
toJSON user = Aeson.object
112-
[ "user_username" .= userUsername user
113-
, "user_decks" .= userDecks user
114-
, "user_firebaseid" .= userFirebaseId user
122+
[ "user_firebase_uid" .= userFirebaseId user -- firebaseid -> firebaseuid
123+
, "user_anonymous" .= userAnonymous user -- firebaseid -> firebaseuid
115124
]
116125

126+
-- TODO: check user is in DB
127+
-- TODO: check permissions
128+
-- TODO: created_at, updated_at
129+
117130
-- TODO: deduplicate those instances
118131
instance Aeson.FromJSON (WithId UserId User) where
119132
parseJSON = Aeson.withObject "WithId UserId User" $ \o ->
120133
WithId <$>
121134
(UserId <$> o .: "user_id") <*>
122-
(User <$> o .: "user_decks" <*> o .: "user_username" <*> o .: "user_firebaseid")
135+
(User <$> o .: "user_firebase_uid" <*> o .: "user_anonymous" )
123136

124137
instance Aeson.ToJSON (WithId UserId User) where
125138
toJSON (WithId userId user) = Aeson.object
126139
[ "user_id" .= userId
127-
, "user_decks" .= userDecks user
128-
, "user_name" .= userUsername user
140+
, "user_firebase_uid" .= userFirebaseId user
141+
, "user_anonymous" .= userAnonymous user
129142
]
130143

131144
-- DECKS
132145

133146
type DecksAPI =
134-
Protected :> Get '[JSON] [WithId DeckId Deck] :<|>
147+
Protected :> QueryParam "owner_id" UserId :> Get '[JSON] [WithId DeckId Deck] :<|>
135148
Protected :>
136149
Capture "deck_id" DeckId :>
137150
Get '[JSON] (WithId DeckId Deck) :<|>
138-
ReqBody '[JSON] Deck :> Post '[JSON] (WithId DeckId Deck) :<|> --TODO: protect
151+
Protected :> ReqBody '[JSON] Deck :> Post '[JSON] (WithId DeckId Deck) :<|>
139152
Protected :>
140153
Capture "deck_id" DeckId :>
141154
ReqBody '[JSON] Deck :> Put '[JSON] (WithId DeckId Deck) :<|>
@@ -151,32 +164,36 @@ newtype Deckname = Deckname { unDeckname :: T.Text }
151164
data Deck = Deck
152165
{ deckSlides :: [SlideId]
153166
, deckDeckname :: Deckname -- TODO: enforce uniqueness
167+
, deckOwnerId :: UserId
154168
} deriving (Show, Eq)
155169

156170
instance Aeson.FromJSON Deck where
157171
parseJSON = Aeson.withObject "deck" $ \obj ->
158172
Deck
159173
<$> obj .: "deck_slides"
160174
<*> obj .: "deck_name"
175+
<*> obj .: "deck_owner_id"
161176

162177
instance Aeson.ToJSON Deck where
163178
toJSON deck = Aeson.object
164179
[ "deck_slides" .= deckSlides deck
165180
, "deck_name" .= deckDeckname deck
181+
, "deck_owner_id" .= deckOwnerId deck
166182
]
167183

168184
-- TODO: deduplicate those instances
169185
instance Aeson.FromJSON (WithId DeckId Deck) where
170186
parseJSON = Aeson.withObject "WithId DeckId Deck" $ \o ->
171187
WithId <$>
172188
(DeckId <$> o .: "deck_id") <*>
173-
(Deck <$> o .: "deck_slides" <*> o .: "deck_name")
189+
(Deck <$> o .: "deck_slides" <*> o .: "deck_name" <*> o .: "deck_owner_id")
174190

175191
instance Aeson.ToJSON (WithId DeckId Deck) where
176192
toJSON (WithId deckId deck) = Aeson.object
177193
[ "deck_id" .= deckId
178194
, "deck_slides" .= deckSlides deck
179195
, "deck_name" .= deckDeckname deck
196+
, "deck_owner_id" .= deckOwnerId deck
180197
]
181198

182199
-- SLIDES
@@ -382,9 +399,16 @@ usersDelete env _ userId = do
382399

383400
-- DECKS
384401

385-
decksGet :: Aws.Env -> Firebase.UserId -> Servant.Handler [WithId DeckId Deck]
386-
decksGet env _uid = do
387-
res <- runAWS env $ Aws.send $ DynamoDB.scan "Decks"
402+
decksGet :: Aws.Env -> Firebase.UserId -> Maybe UserId -> Servant.Handler [WithId DeckId Deck]
403+
decksGet env _uid mUserId = do
404+
405+
let updateReq = case mUserId of
406+
Nothing -> id
407+
Just userId -> \req -> req &
408+
DynamoDB.sFilterExpression .~ Just "DeckOwnerId = :o" &
409+
DynamoDB.sExpressionAttributeValues .~ HMS.singleton ":o" (userIdToAttributeValue userId)
410+
411+
res <- runAWS env $ Aws.send $ updateReq $ DynamoDB.scan "Decks"
388412
case res of
389413
Right scanResponse ->
390414
case sequence $ scanResponse ^. DynamoDB.srsItems <&> itemToDeck of
@@ -422,8 +446,8 @@ decksGetDeckId env _ deckId = do
422446
liftIO $ print e
423447
Servant.throwError Servant.err500
424448

425-
decksPost :: Aws.Env -> Deck -> Servant.Handler (WithId DeckId Deck)
426-
decksPost env deck = do
449+
decksPost :: Aws.Env -> Firebase.UserId -> Deck -> Servant.Handler (WithId DeckId Deck)
450+
decksPost env _ deck = do
427451

428452
deckId <- liftIO $ DeckId <$> newId
429453

@@ -567,24 +591,28 @@ slidesDelete env slideId = do
567591
-- USERS
568592

569593
userToItem :: UserId -> User -> HMS.HashMap T.Text DynamoDB.AttributeValue
570-
userToItem userId User{userDecks, userUsername, userFirebaseId} =
594+
userToItem userId User{userFirebaseId, userAnonymous} =
571595
HMS.singleton "UserId" (userIdToAttributeValue userId) <>
572-
HMS.singleton "UserDecks" (userDecksToAttributeValue userDecks) <>
596+
-- HMS.singleton "UserDecks" (userDecksToAttributeValue userDecks) <>
573597
HMS.singleton "UserFirebaseId" (userFirebaseIdToAttributeValue userFirebaseId) <>
574-
HMS.singleton "UserUsername" (userNameToAttributeValue userUsername)
598+
HMS.singleton "UserAnonymous" (userAnonymousToAttributeValue userAnonymous) -- <>B
599+
-- HMS.singleton "UserFirebaseId" (userFirebaseIdToAttributeValue userFirebaseId) <>
600+
-- HMS.singleton "UserUsername" (userNameToAttributeValue userUsername)
575601

576602
userToItem' :: User -> HMS.HashMap T.Text DynamoDB.AttributeValue
577-
userToItem' User{userDecks, userUsername, userFirebaseId} =
578-
HMS.singleton ":s" (userDecksToAttributeValue userDecks) <>
579-
HMS.singleton ":i" (userFirebaseIdToAttributeValue userFirebaseId) <>
580-
HMS.singleton ":n" (userNameToAttributeValue userUsername)
603+
userToItem' User{userFirebaseId, userAnonymous} =
604+
-- HMS.singleton ":s" (userDecksToAttributeValue userDecks) <>
605+
HMS.singleton ":i" (userFirebaseIdToAttributeValue userFirebaseId) <> -- <>
606+
HMS.singleton ":a" (userAnonymousToAttributeValue userAnonymous) -- <>
607+
-- HMS.singleton ":n" (userNameToAttributeValue userUsername)
581608

582609
itemToUser :: HMS.HashMap T.Text DynamoDB.AttributeValue -> Maybe (WithId UserId User)
583610
itemToUser item = do
584611
userId <- HMS.lookup "UserId" item >>= userIdFromAttributeValue
585-
userDecks <- HMS.lookup "UserDecks" item >>= userDecksFromAttributeValue
586-
userUsername <- HMS.lookup "UserUsername" item >>= userNameFromAttributeValue
612+
-- userDecks <- HMS.lookup "UserDecks" item >>= userDecksFromAttributeValue
613+
-- userUsername <- HMS.lookup "UserUsername" item >>= userNameFromAttributeValue
587614
userFirebaseId <- HMS.lookup "UserFirebaseId" item >>= userFirebaseIdFromAttributeValue
615+
userAnonymous <- HMS.lookup "UserAnonymous" item >>= userAnonymousFromAttributeValue
588616
pure $ WithId userId User{..}
589617

590618
-- USER ATTRIBUTES
@@ -610,6 +638,13 @@ userFirebaseIdToAttributeValue (FirebaseId userId) =
610638
userFirebaseIdFromAttributeValue :: DynamoDB.AttributeValue -> Maybe FirebaseId
611639
userFirebaseIdFromAttributeValue attr = FirebaseId <$> attr ^. DynamoDB.avS
612640

641+
userAnonymousToAttributeValue :: Bool -> DynamoDB.AttributeValue
642+
userAnonymousToAttributeValue b =
643+
DynamoDB.attributeValue & DynamoDB.avBOOL .~ Just b
644+
645+
userAnonymousFromAttributeValue :: DynamoDB.AttributeValue -> Maybe Bool
646+
userAnonymousFromAttributeValue attr = attr ^. DynamoDB.avBOOL
647+
613648
userDecksToAttributeValue :: [DeckId] -> DynamoDB.AttributeValue
614649
userDecksToAttributeValue userDecks =
615650
DynamoDB.attributeValue & DynamoDB.avL .~
@@ -622,21 +657,24 @@ userDecksFromAttributeValue attr =
622657
-- DECKS
623658

624659
deckToItem :: DeckId -> Deck -> HMS.HashMap T.Text DynamoDB.AttributeValue
625-
deckToItem deckId Deck{deckSlides, deckDeckname} =
660+
deckToItem deckId Deck{deckSlides, deckDeckname, deckOwnerId} =
626661
HMS.singleton "DeckId" (deckIdToAttributeValue deckId) <>
627662
HMS.singleton "DeckSlides" (deckSlidesToAttributeValue deckSlides) <>
628-
HMS.singleton "DeckName" (deckNameToAttributeValue deckDeckname)
663+
HMS.singleton "DeckName" (deckNameToAttributeValue deckDeckname) <>
664+
HMS.singleton "DeckOwnerId" (deckOwnerIdToAttributeValue deckOwnerId)
629665

630666
deckToItem' :: Deck -> HMS.HashMap T.Text DynamoDB.AttributeValue
631-
deckToItem' Deck{deckSlides, deckDeckname} =
667+
deckToItem' Deck{deckSlides, deckDeckname, deckOwnerId} =
632668
HMS.singleton ":s" (deckSlidesToAttributeValue deckSlides) <>
633-
HMS.singleton ":n" (deckNameToAttributeValue deckDeckname)
669+
HMS.singleton ":n" (deckNameToAttributeValue deckDeckname) <>
670+
HMS.singleton ":o" (deckOwnerIdToAttributeValue deckOwnerId)
634671

635672
itemToDeck :: HMS.HashMap T.Text DynamoDB.AttributeValue -> Maybe (WithId DeckId Deck)
636673
itemToDeck item = do
637674
deckId <- HMS.lookup "DeckId" item >>= deckIdFromAttributeValue
638675
deckSlides <- HMS.lookup "DeckSlides" item >>= deckSlidesFromAttributeValue
639676
deckDeckname <- HMS.lookup "DeckName" item >>= deckNameFromAttributeValue
677+
deckOwnerId <- HMS.lookup "DeckOwnerId" item >>= deckOwnerIdFromAttributeValue
640678
pure $ WithId deckId Deck{..}
641679

642680
-- DECK ATTRIBUTES
@@ -645,16 +683,16 @@ deckIdToAttributeValue :: DeckId -> DynamoDB.AttributeValue
645683
deckIdToAttributeValue (DeckId deckId) =
646684
DynamoDB.attributeValue & DynamoDB.avS .~ Just deckId
647685

686+
deckIdFromAttributeValue :: DynamoDB.AttributeValue -> Maybe DeckId
687+
deckIdFromAttributeValue attr = DeckId <$> attr ^. DynamoDB.avS
688+
648689
deckNameToAttributeValue :: Deckname -> DynamoDB.AttributeValue
649690
deckNameToAttributeValue (Deckname deckname) =
650691
DynamoDB.attributeValue & DynamoDB.avS .~ Just deckname
651692

652693
deckNameFromAttributeValue :: DynamoDB.AttributeValue -> Maybe Deckname
653694
deckNameFromAttributeValue attr = Deckname <$> attr ^. DynamoDB.avS
654695

655-
deckIdFromAttributeValue :: DynamoDB.AttributeValue -> Maybe DeckId
656-
deckIdFromAttributeValue attr = DeckId <$> attr ^. DynamoDB.avS
657-
658696
deckSlidesToAttributeValue :: [SlideId] -> DynamoDB.AttributeValue
659697
deckSlidesToAttributeValue deckSlides =
660698
DynamoDB.attributeValue & DynamoDB.avL .~
@@ -664,6 +702,13 @@ deckSlidesFromAttributeValue :: DynamoDB.AttributeValue -> Maybe [SlideId]
664702
deckSlidesFromAttributeValue attr =
665703
traverse slideIdFromAttributeValue (attr ^. DynamoDB.avL)
666704

705+
deckOwnerIdToAttributeValue :: UserId -> DynamoDB.AttributeValue
706+
deckOwnerIdToAttributeValue (UserId deckOwnerId) =
707+
DynamoDB.attributeValue & DynamoDB.avS .~ Just deckOwnerId
708+
709+
deckOwnerIdFromAttributeValue :: DynamoDB.AttributeValue -> Maybe UserId
710+
deckOwnerIdFromAttributeValue attr = UserId <$> attr ^. DynamoDB.avS
711+
667712
-- SLIDES
668713

669714
slideToItem :: SlideId -> Slide -> HMS.HashMap T.Text DynamoDB.AttributeValue

0 commit comments

Comments
 (0)