-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Ensure Auth entity has a unique username #1257
Conversation
doesFieldHaveAttribute :: String -> String -> Entity -> Maybe Bool | ||
doesFieldHaveAttribute fieldName attrName entity = | ||
doesPslFieldHaveAttribute attrName <$> findPslFieldByName fieldName entity | ||
|
||
findPslFieldByName :: String -> Entity -> Maybe PslModel.Field | ||
findPslFieldByName fieldName Entity {pslModelBody = PslModel.Body elements} = | ||
find isField [field | (PslModel.ElementField field) <- elements] | ||
where | ||
isField PslModel.Field {_name = name} = name == fieldName | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure how to decide what to put in here vs. in Psl/Util.hs
.
This is the only file that uses Psl/Util.hs
. Should we maybe remove Psl/Util.hs
(especially considering the conversation about keeping PslModel
stuff hidden and working only with regular Field
s)?
Finally, if we do decide to hide everything related to PslModel
, should I refactor the getIdField
and getIdBlockAttribute
functions to make them fit into that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am missing a bit of context so it is somewhat hard for me to make a decisive statement here, but:
- If we have functions operating on PSL stuff and not knowing anything about Entity, then it sounds good to have them in PslUtil.hs, regardgless by how many other modules are using them.
For future, it might help if you give more context. For exmaple, what is in Psl/Util.hs, why do you think it shouldn't be there (besides this being the only place using it), what are pros/cons of each approach (aka "what have you tried"), what do getIdField and getIdBlockAttribute do to make them candidates for this refactoring, how much work is that, what are the benefits, ... .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I like the idea of exposing Entity + ENtity.Filed interface and hiding PSL if possible. If not possible / practical, we can let some PSL seep out.
I can't judge right now how possible / practical it is without diving deeper, but I believe you will know that better!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I liked the split of having Entity
using helper functions from Psl/Util.hs
.
Example of such fn:
getIdField :: Entity -> Maybe PslModel.Field
getIdField = findIdField . getPslModelBody
All the low level work on the PSL schema is hidden away in the PslUtil
module, while Entity is composing those function to get out what they need without worrying about the implementation.
For this PR, I think the split could go like this:
Psl/Util.hs
implements functions for checking if certain field in PSL has some attribute attachedisAttributePresentOnField
Entity.hs
uses that function to come up with a functionisFieldUnique
(looking for@unique
)Valid.hs
can then do something likeEntity.isFieldUnique "username"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main idea was as follows:
If we're hiding PSL as an implementation detail (this is the core assumption), there probably aren't many reasons for having a Utils
file (in its current location).
The only module that should ever be using those utils is Entity
(since all PSL stuff is a "hidden" implementation detail), so we might as well move all those functions there (instead of having them globally available from a different part of the codebase).
Such an organisation colocates all relevant code and discourages/prevents us from acting on PSL directly (i.e., without going through the functions exposed by the Entity
module). The low-level PSL stuff would still be abstracted away by appropriate functions that aren't exported from Entity
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added the isFieldUnique
function and left the other stuff as is for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sodic not so important for this PR, but I would do the opposite -> I would put PSL specific stuff in PSL/Utils.hs or something like that, not in Entity
, IF it makes sense to be standalone. This is useful because it clearly indicates that this code is not Entity specific, in the sense that there are some assumptions they share. Entity would still be having that as an implementation details, that doesn't change. And the fact that nobody else is using it is also not an issue, if it is general it is general -> we might need it in some other parts of the code, even if also hidden as an implementation detail.
Otherwise we could just move the whole PSL module under Entity. But I like it better that we say "hey, look we have PSL module because Wasp knows how to work with it!" without assuming who is using it.
But this is not a biggie, we can in any case move it around if needed.
@Martinsos What did you mean by this comment: #769 (comment). Should I also remove some JS code? |
Unfortunately I can't remember, I wish I wrote more info. I guess we, when creating user via #, check there, in the Prisma request, if username is unique? But we don't enforce it in the schema itself? |
@@ -8,10 +8,17 @@ import qualified Wasp.Psl.Ast.Model as PslModel | |||
spec_AppSpecEntityTest :: Spec | |||
spec_AppSpecEntityTest = do | |||
describe "getIdField" $ do | |||
it "gets primary field from entity when it exists" $ do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have 19 test files where we write the first letter as upper case and 21 files where we write it as lower case.
Obviously we have two competing standards 😄 @sodic @Martinsos
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I vote uppercase, same goes for git messages 😄
They're nicer to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha I also wasn't sure, but sounds good it if is nicer to read! Git messages yes, for sure, upper letter and dot at the end!
waspc/src/Wasp/AppSpec/Valid.hs
Outdated
| doesFieldHaveAttribute "username" "unique" userEntity == Just True = [] | ||
| otherwise = | ||
[ GenericValidationError $ | ||
"The field 'username' on Entity referenced by " ++ userEntityName ++ " must have the '@unique' attribute." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would go for less technical error message like
The username field on the User entity should be marked as unique (add the @unique attribute on the username field).
If some new users this super technical message, it might confuse them IMHO
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, but the rest of the file uses this style so I decided against changing it to save time. I can make an issue for refactoring the error messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider changing this message and the others (I see only one other:
wasp/waspc/src/Wasp/AppSpec/Valid.hs
Line 245 in afe90a2
"Expected an Entity referenced by " ++ entityName ++ " to have field '" ++ fieldName ++ "' of type '" ++ fieldTypeName ++ "'." |
Tested it out locally, it works. Some minor comments regard the error message and code organisation. |
Fixes #1164
I couldn't find any JS code that deals with this: #769 (comment)