Skip to content

Lägg till rollbaserade endpoint-regler i SecurityConfig #210

Description

@annikaholmqvist94

Beskrivning:

Just nu använder SecurityConfig.securityFilterChain() bara anyRequest().authenticated() för alla endpoints utom auth och publika kliniker. Det betyder att alla inloggade användare — även OWNER —
kan nå endpoints som är tänkta för VET/ADMIN. Rollkontroll sker idag bara i policy-lagret, vilket gör oss sårbara om en policy har en bugg eller saknar rollcheck.

Den här issuen lägger till ett andra lager av skydd i SecurityConfig.

Fil som ändras

src/main/java/org/example/vet1177/security/SecurityConfig.java — endast authorizeHttpRequests-blocket (~rad 70-80).

Ändring

Ersätt befintligt block:

.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/").permitAll()
.requestMatchers(HttpMethod.GET, "/api/clinics", "/api/clinics/
").permitAll()
.anyRequest().authenticated()
)

Med:

.authorizeHttpRequests(auth -> auth
// ─── Öppet för alla ───
.requestMatchers("/api/auth/").permitAll()
.requestMatchers(HttpMethod.GET, "/api/clinics", "/api/clinics/
").permitAll()

      // ─── Admin-only ───           
      .requestMatchers("/api/users/**").hasRole("ADMIN")                                                                                                                                          
      .requestMatchers(HttpMethod.POST, "/api/vets").hasRole("ADMIN")                                                                                                                             
      .requestMatchers(HttpMethod.POST, "/api/clinics").hasRole("ADMIN")
      .requestMatchers(HttpMethod.PUT, "/api/clinics/**").hasRole("ADMIN")                                                                                                                        
      .requestMatchers(HttpMethod.DELETE, "/api/clinics/**").hasRole("ADMIN")                                                                                                                     
                                          
      // ─── VET/ADMIN: mutera ärenden ───                                                                                                                                                        
      .requestMatchers(HttpMethod.PUT, "/api/medical-records/*/close").hasAnyRole("VET", "ADMIN")
      .requestMatchers(HttpMethod.PUT, "/api/medical-records/*/assign-vet").hasAnyRole("VET", "ADMIN")                                                                                            
      .requestMatchers(HttpMethod.PUT, "/api/medical-records/*/status").hasAnyRole("VET", "ADMIN")
      .requestMatchers(HttpMethod.PUT, "/api/medical-records/*").hasAnyRole("VET", "ADMIN")                                                                                                       
                                                                                                                                                                                                  
      // ─── VET/ADMIN: se klinik-data ───                                                                                                                                                        
      .requestMatchers(HttpMethod.GET, "/api/medical-records/clinic/**").hasAnyRole("VET", "ADMIN")                                                                                               
                                                                                                                                                                                                  
      // ─── VET/ADMIN: bilagor ───                                                                                                                                                               
      .requestMatchers(HttpMethod.POST, "/api/attachments/**").hasAnyRole("VET", "ADMIN")                                                                                                         
      .requestMatchers(HttpMethod.DELETE, "/api/attachments/**").hasAnyRole("VET", "ADMIN")                                                                                                       
                                          
      // ─── Alla inloggade (policy finjusterar) ───                                                                                                                                              
      .anyRequest().authenticated()                                                                                                                                                               

)

Viktigt att veta

  • Ordningen spelar roll. Första matchande regel vinner. Specifika regler måste ligga före generella. I mallen ovan är det redan rätt ordning.
  • hasRole("ADMIN") matchar automatiskt ROLE_ADMIN — Spring lägger till prefixet. Vårt User.getAuthorities() returnerar "ROLE_" + role.name() så det stämmer.
  • @PreAuthorize("hasRole('ADMIN')") på /api/users/search i UserController är fortfarande kompatibelt — det är en extra kontroll ovanpå URL-reglerna.

Vad som INTE ska ändras

  • Policy-klasserna (MedicalRecordPolicy, PetPolicy etc.) — dessa fortsätter som finjusterande kontroll ("VET på rätt klinik", "OWNER äger detta djur").
  • Controller-metoder — inga @PreAuthorize läggs till på nya ställen.
  • CORS, CSRF, sessionManagement, filter-kedjan — alla andra delar av SecurityConfig lämnas orörda.

Acceptanskriterier

  • SecurityConfig.authorizeHttpRequests uppdaterad enligt mallen ovan
  • ./mvnw test — alla tester gröna (0 failures, 0 errors)
  • @PreAuthorize på UserController.searchByEmail lämnad orörd
  • Inga andra filer ändrade
  • Manuell verifiering med curl att:
    • OWNER får 403 på PUT /api/medical-records/{id}/close
    • VET får 200 på samma endpoint
    • OWNER får 403 på GET /api/users
    • Inloggad VET får 200 på GET /api/medical-records/my-records (egna ärenden) — vänta, detta är ett undantag: my-records är OWNER-specifik logik. Bekräfta att den fortfarande funkar eftersom den
      faller under authenticated().

Testning av befintliga tester

Flera controller-tester använder en specifik roll i authenticatedAs(user) och kan börja returnera 403 istället för 200 efter ändringen om rollen inte matchar de nya reglerna. Exempel:

  • MedicalRecordControllerTest.update_shouldReturn200WithUpdatedRecord — använder vetUser, ska fortsätta funka.
  • Om något test använder en OWNER för en VET-only endpoint → byt till vetUser eller lägg till separat 403-test.

Kör ./mvnw test och fixa eventuella röda tester innan merge.

Metadata

Metadata

Labels

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions