ADR-003: Phase 2C - Deny-by-Default per Mutacions
Data: 2024-12
Estat: Implementat
Decisors: Equip de desenvolupament LDP
Context
Abans de Phase 2C, el sistema tenia una regla excessivament permissiva:
.requestMatchers(HttpMethod.POST, "/api/**").authenticated()
.requestMatchers(HttpMethod.PUT, "/api/**").authenticated()
Això permetia a qualsevol usuari autenticat (rol USER) crear o editar recursos de catàleg (Dance, Song, Event), el que no és desitjable:
- El catàleg hauria de ser gestionat per administradors
- Els usuaris normals no haurien de poder crear contingut de catàleg
Decisió
Implementar deny-by-default per a totes les mutacions (POST/PUT) amb permisos explícits per recurs:
Matriu de Permisos
| Recurs | POST | PUT | DELETE | Política |
|---|---|---|---|---|
/api/dances/** | ADMIN | ADMIN | ADMIN | Catàleg gestionat per admin |
/api/songs/** | ADMIN | ADMIN | ADMIN | Catàleg gestionat per admin |
/api/events/** | ADMIN | ADMIN | ADMIN | Temporal; futur: venue owners |
/api/locations/** | authenticated | BOLA | ADMIN | Owner pot editar |
/api/venues/** | authenticated | BOLA | ADMIN | Owner pot editar |
/api/choreographers/* | N/A | BOLA | N/A | Owner pot editar |
Fallback /api/** | ADMIN | ADMIN | ADMIN | Fail-secure |
Canvis Implementats
- SecurityConfig.java: Regles explícites per cada tipus de recurs
- DanceController.java:
@PreAuthorize("hasRole('ADMIN')")per POST/PUT - SongController.java:
@PreAuthorize("hasRole('ADMIN')")per POST/PUT - EventController.java:
@PreAuthorize("hasRole('ADMIN')")per POST/PUT - Security Playbook: Actualitzat a v1.3 amb nova secció de permisos
Conseqüències
Positives
- Fail-secure: Qualsevol endpoint no especificat requereix ADMIN
- Principi de mínim privilegi: USER només pot llegir
- Claritat: La matriu de permisos és explícita i documentada
Negatives
- Més restrictiu: Pot requerir canvis si en el futur es vol permetre que users creïn contingut
- Gestió d'events: Temporalment ADMIN-only; cal implementar ownership per venue promoters
Implementació
SecurityConfig.java (fragment)
// Phase 2C: Catalog resources (Dance/Song) are ADMIN-only
.requestMatchers(HttpMethod.POST, "/api/dances/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT, "/api/dances/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.POST, "/api/songs/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT, "/api/songs/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.POST, "/api/events/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT, "/api/events/**").hasRole("ADMIN")
// Deny-by-default: any other POST/PUT requires ADMIN (fail secure)
.requestMatchers(HttpMethod.POST, "/api/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT, "/api/**").hasRole("ADMIN")
Tests de Referència
CatalogAccessControlTest.java: 12 tests per verificar:- USER rep 403 ACCESS_DENIED en POST/PUT a catàleg
- Anonymous rep 401 Unauthorized
- ADMIN passa la capa d'autorització
Notes
- Els tests d'integració requereixen que l'ApplicationContext Spring Boot funcioni correctament. Si hi ha problemes de configuració (DB, beans), els tests fallaran.
- La validació manual amb curl/Postman confirma el comportament correcte.
Historial
| Data | Versió | Canvis |
|---|---|---|
| 2024-12 | 1.0 | Document inicial |