Skip to content

Commit

Permalink
Use native DB type in injected auth models if user uses it
Browse files Browse the repository at this point in the history
  • Loading branch information
infomiho committed Aug 21, 2024
1 parent 6ca8446 commit 788202b
Show file tree
Hide file tree
Showing 4 changed files with 276 additions and 2 deletions.
24 changes: 22 additions & 2 deletions waspc/src/Wasp/Generator/DbGenerator/Auth.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
module Wasp.Generator.DbGenerator.Auth where
module Wasp.Generator.DbGenerator.Auth
( injectAuth,
authEntityName,
authIdentityEntityName,
sessionEntityName,
userFieldOnAuthEntityName,
authFieldOnUserEntityName,
identitiesFieldOnAuthEntityName,
authFieldOnAuthIdentityEntityName,
)
where

import Data.Maybe (fromJust)
import qualified Data.Text as T
Expand All @@ -9,7 +19,9 @@ import Wasp.Generator.Monad
GeneratorError (GenericGeneratorError),
logAndThrowGeneratorError,
)
import qualified Wasp.Psl.Ast.Attribute as Psl.Attribute
import qualified Wasp.Psl.Ast.Model as Psl.Model
import qualified Wasp.Psl.Generator.Attribute as Psl.Generator.Attribute
import qualified Wasp.Psl.Parser.Model as Psl.Parser.Model
import qualified Wasp.Util as Util

Expand Down Expand Up @@ -111,7 +123,7 @@ makeAuthEntity userEntityIdField (userEntityName, _) = case Psl.Parser.Model.par
T.unpack
[trimming|
id ${authEntityIdTypeText} @id @default(uuid())
userId ${userEntityIdTypeText}? @unique
userId ${userEntityIdTypeText}? ${userEntityIdFieldAttributesText}
${userFieldOnAuthEntityNameText} ${userEntityNameText}? @relation(fields: [userId], references: [${userEntityIdFieldName}], onDelete: Cascade)
${identitiesFieldOnAuthEntityNameText} ${authIdentityEntityNameText}[]
${sessionsFieldOnAuthEntityNameText} ${sessionEntityNameText}[]
Expand All @@ -127,6 +139,14 @@ makeAuthEntity userEntityIdField (userEntityName, _) = case Psl.Parser.Model.par

userEntityIdTypeText = T.pack $ show . Psl.Model._type $ userEntityIdField
userEntityIdFieldName = T.pack $ Psl.Model._name userEntityIdField
userEntityIdFieldAttributesText = T.pack $ makeUserEntityIdFieldAttributes userEntityIdField

makeUserEntityIdFieldAttributes :: Psl.Model.Field -> String
makeUserEntityIdFieldAttributes field = unwords attrs
where
attrs = waspDefinedAttrs ++ (Psl.Generator.Attribute.generateAttribute <$> userDefinedNativeDbTypeAttributes)
waspDefinedAttrs = ["@unique"]
userDefinedNativeDbTypeAttributes = filter Psl.Attribute.isNativeDbTypeAttr $ Psl.Model._attrs field

makeSessionEntity :: Generator (String, AS.Entity.Entity)
makeSessionEntity = case Psl.Parser.Model.parseBody sessionEntityPslBody of
Expand Down
6 changes: 6 additions & 0 deletions waspc/src/Wasp/Psl/Ast/Attribute.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

module Wasp.Psl.Ast.Attribute
( Attribute (..),
isNativeDbTypeAttr,
)
where

import Data.Data (Data)
import Data.List (isPrefixOf)
import qualified Wasp.Psl.Ast.Argument as Psl.Argument
import Prelude hiding (Enum)

Expand All @@ -19,3 +21,7 @@ data Attribute = Attribute
_attrArgs :: [Psl.Argument.Argument]
}
deriving (Show, Eq, Data)

-- | @db.Uuid or @db.String or @db.VarChar are examples of native db types.
isNativeDbTypeAttr :: Attribute -> Bool
isNativeDbTypeAttr = isPrefixOf "db." . _attrName
247 changes: 247 additions & 0 deletions waspc/test/Generator/AuthInjectionTest.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
module Generator.AuthInjectionTest where

import Data.Either (fromRight)
import Test.Tasty.Hspec
import qualified Wasp.AppSpec.Entity as AS.Entity
import Wasp.Generator.DbGenerator.Auth (injectAuth)
import Wasp.Generator.Monad (runGenerator)
import qualified Wasp.Psl.Ast.Argument as Psl.Argument
import qualified Wasp.Psl.Ast.Attribute as Psl.Attribute
import qualified Wasp.Psl.Ast.Model as Psl.Model

spec_GeneratorCrudTest :: Spec
spec_GeneratorCrudTest = do
describe "injectAuth" $ do
it "injects auth entities and user entity relation" $ do
let (_generatorWarnings, generatorResult) = runGenerator $ injectAuth [("User", userEntity)] ("User", userEntity)
let entities = fromRight (error "Auth injection test failed") generatorResult
entities
`shouldBe` [ ("User", userEntityWithInjectedRelationship),
( "Auth",
makeAuthEntity Psl.Model.Int [Psl.Attribute.Attribute "unique" []]
),
("AuthIdentity", authIdentityEntity),
("Session", sessionEntity)
]

it "injects auth entities and user entity relation (user ID is a native db fields)" $ do
let (_, generatorResult) = runGenerator $ injectAuth [("User", userEntityWithNativeIdField)] ("User", userEntityWithNativeIdField)
let entities = fromRight (error "Auth injection test failed") generatorResult
entities
`shouldBe` [ ("User", userEntityWithNativeIdFieldAndInjectedRelationship),
( "Auth",
makeAuthEntity
Psl.Model.String
[ Psl.Attribute.Attribute "unique" [],
Psl.Attribute.Attribute "db.Uuid" []
]
),
("AuthIdentity", authIdentityEntity),
("Session", sessionEntity)
]
where
userEntity =
AS.Entity.makeEntity
( Psl.Model.Body
[ Psl.Model.ElementField $
Psl.Model.Field
"id"
Psl.Model.Int
[]
[ Psl.Attribute.Attribute "id" [],
Psl.Attribute.Attribute
"default"
[ Psl.Argument.ArgUnnamed $ Psl.Argument.FuncExpr "autoincrement" []
]
]
]
)

userEntityWithInjectedRelationship =
AS.Entity.makeEntity
( Psl.Model.Body
[ Psl.Model.ElementField $
Psl.Model.Field
"id"
Psl.Model.Int
[]
[ Psl.Attribute.Attribute "id" [],
Psl.Attribute.Attribute
"default"
[ Psl.Argument.ArgUnnamed $ Psl.Argument.FuncExpr "autoincrement" []
]
],
Psl.Model.ElementField $
Psl.Model.Field
"auth"
(Psl.Model.UserType "Auth")
[Psl.Model.Optional]
[]
]
)

userEntityWithNativeIdField =
AS.Entity.makeEntity
( Psl.Model.Body
[ Psl.Model.ElementField $
Psl.Model.Field
"id"
Psl.Model.String
[]
[ Psl.Attribute.Attribute "id" [],
Psl.Attribute.Attribute "db.Uuid" []
]
]
)

userEntityWithNativeIdFieldAndInjectedRelationship =
AS.Entity.makeEntity
( Psl.Model.Body
[ Psl.Model.ElementField $
Psl.Model.Field
"id"
Psl.Model.String
[]
[ Psl.Attribute.Attribute "id" [],
Psl.Attribute.Attribute "db.Uuid" []
],
Psl.Model.ElementField $
Psl.Model.Field
"auth"
(Psl.Model.UserType "Auth")
[Psl.Model.Optional]
[]
]
)

makeAuthEntity userIdType userIdAttributes =
AS.Entity.makeEntity
( Psl.Model.Body
[ Psl.Model.ElementField $
Psl.Model.Field
"id"
Psl.Model.String
[]
[ Psl.Attribute.Attribute "id" [],
Psl.Attribute.Attribute "default" [Psl.Argument.ArgUnnamed $ Psl.Argument.FuncExpr "uuid" []]
],
Psl.Model.ElementField $
Psl.Model.Field
"userId"
userIdType
[Psl.Model.Optional]
userIdAttributes,
Psl.Model.ElementField $
Psl.Model.Field
"user"
(Psl.Model.UserType "User")
[Psl.Model.Optional]
[ Psl.Attribute.Attribute
"relation"
[ Psl.Argument.ArgNamed "fields" (Psl.Argument.ArrayExpr [Psl.Argument.IdentifierExpr "userId"]),
Psl.Argument.ArgNamed "references" (Psl.Argument.ArrayExpr [Psl.Argument.IdentifierExpr "id"]),
Psl.Argument.ArgNamed "onDelete" (Psl.Argument.IdentifierExpr "Cascade")
]
],
Psl.Model.ElementField $
Psl.Model.Field
"identities"
(Psl.Model.UserType "AuthIdentity")
[Psl.Model.List]
[],
Psl.Model.ElementField $
Psl.Model.Field
"sessions"
(Psl.Model.UserType "Session")
[Psl.Model.List]
[]
]
)

authIdentityEntity =
AS.Entity.makeEntity
( Psl.Model.Body
[ Psl.Model.ElementField $
Psl.Model.Field
"providerName"
Psl.Model.String
[]
[],
Psl.Model.ElementField $
Psl.Model.Field
"providerUserId"
Psl.Model.String
[]
[],
Psl.Model.ElementField $
Psl.Model.Field
"providerData"
Psl.Model.String
[]
[ Psl.Attribute.Attribute "default" [Psl.Argument.ArgUnnamed $ Psl.Argument.StringExpr "{}"]
],
Psl.Model.ElementField $
Psl.Model.Field
"authId"
Psl.Model.String
[]
[],
Psl.Model.ElementField $
Psl.Model.Field
"auth"
(Psl.Model.UserType "Auth")
[]
[ Psl.Attribute.Attribute
"relation"
[ Psl.Argument.ArgNamed "fields" (Psl.Argument.ArrayExpr [Psl.Argument.IdentifierExpr "authId"]),
Psl.Argument.ArgNamed "references" (Psl.Argument.ArrayExpr [Psl.Argument.IdentifierExpr "id"]),
Psl.Argument.ArgNamed "onDelete" (Psl.Argument.IdentifierExpr "Cascade")
]
],
Psl.Model.ElementBlockAttribute $
Psl.Attribute.Attribute "id" [Psl.Argument.ArgUnnamed $ Psl.Argument.ArrayExpr [Psl.Argument.IdentifierExpr "providerName", Psl.Argument.IdentifierExpr "providerUserId"]]
]
)

sessionEntity =
AS.Entity.makeEntity
( Psl.Model.Body
[ Psl.Model.ElementField $
Psl.Model.Field
"id"
Psl.Model.String
[]
[ Psl.Attribute.Attribute "id" [],
Psl.Attribute.Attribute "unique" []
],
Psl.Model.ElementField $
Psl.Model.Field
"expiresAt"
Psl.Model.DateTime
[]
[],
Psl.Model.ElementField $
Psl.Model.Field
"userId"
Psl.Model.String
[]
[],
Psl.Model.ElementField $
Psl.Model.Field
"auth"
(Psl.Model.UserType "Auth")
[]
[ Psl.Attribute.Attribute
"relation"
[ Psl.Argument.ArgNamed "references" (Psl.Argument.ArrayExpr [Psl.Argument.IdentifierExpr "id"]),
Psl.Argument.ArgNamed "fields" (Psl.Argument.ArrayExpr [Psl.Argument.IdentifierExpr "userId"]),
Psl.Argument.ArgNamed "onDelete" (Psl.Argument.IdentifierExpr "Cascade")
]
],
Psl.Model.ElementBlockAttribute $
Psl.Attribute.Attribute
"index"
[ Psl.Argument.ArgUnnamed $ Psl.Argument.ArrayExpr [Psl.Argument.IdentifierExpr "userId"]
]
]
)
1 change: 1 addition & 0 deletions waspc/waspc.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ test-suite waspc-test
ErrorTest
FilePath.ExtraTest
Fixtures
Generator.AuthInjectionTest
Generator.DbGeneratorTest
Generator.FileDraft.CopyFileDraftTest
Generator.FileDraft.CopyAndModifyTextFileDraftTest
Expand Down

0 comments on commit 788202b

Please sign in to comment.