codeconsole opened a new pull request, #16291:
URL: https://github.com/apache/grails-core/pull/16291

   Grails 8 makes an unconstrained persistent property nullable by default 
(documented in `upgrading80x.adoc`, "GORM Properties Are Nullable by Default"). 
The `spring-boot-starter-security` `User` template was never updated for that 
flip, so its `blank: false` constraints no longer make the credentials required 
— a `User` with a null username and a null password validates clean, and the 
scaffolded user admin will save one.
   
   Every other domain template in the forge already declares `nullable: false`, 
which is what makes this look like a miss rather than a choice:
   
   | Template | Constraint |
   |---|---|
   | `role.rocker.raw` | `authority unique: true, nullable: false` |
   | `userClassic.rocker.raw` | `username unique: true, nullable: false` / 
`password nullable: false` |
   | `userRole.rocker.raw` | `user nullable: false` / `role nullable: false, 
unique: 'user'` |
   | `user.rocker.raw` | `username blank: false, unique: true` ← missing |
   
   ```groovy
   static constraints = {
       username nullable: false, blank: false, unique: true
       password nullable: false, blank: false, password: true
   }
   ```
   
   ## The generated spec failed out of the box
   
   Creating an app with this feature produced a red build on the very first 
`./gradlew test`:
   
   ```
   UserSpec > username and password are required FAILED
       Condition not satisfied:
       !new User(username: '', password: '').validate()
       ||                                    |
       |example.User : (unsaved)             true
       false
   ```
   
   The assertion exercised neither constraint it appeared to test. The domain 
map constructor binds through data binding with `convertEmptyStringsToNull`, so 
`username: ''` arrives as `null` — the `blank` constraint never sees an empty 
string — and nullable-by-default then let the nulls through.
   
   The spec now covers the two constraints as separate features, assigning the 
blank values directly since that is the only way a blank string actually 
reaches the property:
   
   ```groovy
   void 'a user whose username and password are blank is rejected'() {
       given: 'the values are assigned directly, since the map constructor 
binds an empty string to null'
       User user = new User()
       user.username = ''
       user.password = ''
   
       expect:
       !user.validate()
   
       and:
       with(user.errors) {
           getFieldError('username').code == 'blank'
           getFieldError('password').code == 'blank'
       }
   }
   ```
   
   `SpringBootStarterSecuritySpec` asserted on the old constraint string and is 
updated to match.
   
   ## Verification
   
   Generated a real app (`create-app --data mongodb --features 
spring-boot-starter-security --jdk 25`) and ran it, rather than only asserting 
on template text:
   
   - `:grails-forge-core:test` — 343 tests, 0 failures
   - `grails-forge` `codeStyle` — clean
   - Generated app's `UserSpec` — 4/4 pass
   - Reverting `nullable: false` and re-running makes the nullable feature 
fail, so the new spec is not vacuous. The blank feature passes either way — 
`blank: false` was always correct; the nullable gap was the whole defect.
   
   The app was also exercised end to end on embedded MongoDB: `/` anonymous 
200, `/user` anonymous redirects to login, form login succeeds, `/user` as 
`ROLE_ADMIN` 200, `/user` as `ROLE_USER` 403.
   
   ## Not addressed here
   
   `user.rocker.raw` declares `static mapping = { table 'users' }`, a Hibernate 
directive, but the template is also generated for the `mongodb` data 
implementation where the equivalent is `collection`. It is inert today — the 
app boots and persists fine — so I left it out of this change rather than widen 
the scope.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to