diff --git a/src/main/java/cat/udl/eps/softarch/demo/config/WebSecurityConfig.java b/src/main/java/cat/udl/eps/softarch/demo/config/WebSecurityConfig.java index 2f9353e..ae965d1 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/config/WebSecurityConfig.java +++ b/src/main/java/cat/udl/eps/softarch/demo/config/WebSecurityConfig.java @@ -36,6 +36,8 @@ protected SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exce .requestMatchers(HttpMethod.POST, "/users/*").denyAll() .requestMatchers(HttpMethod.POST, "/rooms").authenticated() .requestMatchers(HttpMethod.POST, "/rooms/*").hasAnyRole("OWNER") + .requestMatchers(HttpMethod.PATCH, "/rooms").authenticated() + .requestMatchers(HttpMethod.PATCH, "/rooms/*").hasAnyRole("OWNER") .requestMatchers(HttpMethod.POST, "/properties").hasAuthority("ROLE_OWNER") .requestMatchers(HttpMethod.PUT, "/properties/*").hasAuthority("ROLE_OWNER") .requestMatchers(HttpMethod.DELETE, "/properties/*").hasAuthority("ROLE_OWNER") diff --git a/src/main/java/cat/udl/eps/softarch/demo/domain/Room.java b/src/main/java/cat/udl/eps/softarch/demo/domain/Room.java index 3c5a032..18162e6 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/domain/Room.java +++ b/src/main/java/cat/udl/eps/softarch/demo/domain/Room.java @@ -34,10 +34,10 @@ public class Room extends UriEntity { @NotNull private Apartment apart; + private String ownerId; + public void setOwner(Owner owner) { + ownerId = owner.getId(); + } - @JsonProperty(access = JsonProperty.Access.READ_ONLY) - @NotNull - @ManyToOne - private Owner owner; } \ No newline at end of file diff --git a/src/main/java/cat/udl/eps/softarch/demo/handler/RoomEventHandler.java b/src/main/java/cat/udl/eps/softarch/demo/handler/RoomEventHandler.java index 308d907..dee6066 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/handler/RoomEventHandler.java +++ b/src/main/java/cat/udl/eps/softarch/demo/handler/RoomEventHandler.java @@ -1,40 +1,77 @@ -package cat.udl.eps.softarch.demo.handler; - - -import cat.udl.eps.softarch.demo.domain.Apartment; -import cat.udl.eps.softarch.demo.domain.Owner; -import cat.udl.eps.softarch.demo.domain.Room; -import cat.udl.eps.softarch.demo.repository.ApartmentRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.rest.core.annotation.HandleBeforeCreate; -import org.springframework.data.rest.core.annotation.RepositoryEventHandler; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Component -@RepositoryEventHandler -public class RoomEventHandler { - - final Logger logger = LoggerFactory.getLogger(Room.class); - final ApartmentRepository apartmentRepository; - - public RoomEventHandler(ApartmentRepository apartmentRepository) { - this.apartmentRepository = apartmentRepository; - } - - @HandleBeforeCreate - public void handleBeforeCreate(Room room) { - Owner owner = (Owner) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - room.setOwner(owner); - - List apartmentList = apartmentRepository.findByOwner(owner); - if (!apartmentList.isEmpty()) { - room.setApart(apartmentList.get(0)); - } - logger.info("New room created: {}", room); - } -} - +package cat.udl.eps.softarch.demo.handler; + + +import cat.udl.eps.softarch.demo.domain.Apartment; +import cat.udl.eps.softarch.demo.domain.Owner; +import cat.udl.eps.softarch.demo.domain.Room; +import cat.udl.eps.softarch.demo.repository.ApartmentRepository; +import cat.udl.eps.softarch.demo.repository.RoomRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.rest.core.annotation.HandleBeforeCreate; +import org.springframework.data.rest.core.annotation.HandleBeforeDelete; +import org.springframework.data.rest.core.annotation.HandleBeforeSave; +import org.springframework.data.rest.core.annotation.RepositoryEventHandler; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.server.ResponseStatusException; + + +@Component +@RepositoryEventHandler +public class RoomEventHandler { + + final Logger logger = LoggerFactory.getLogger(Room.class); + final ApartmentRepository apartmentRepository; + + public RoomEventHandler(ApartmentRepository apartmentRepository, RoomRepository roomRepository) { + this.apartmentRepository = apartmentRepository; + } + + @HandleBeforeSave + public void handleBeforeSave(Room room) { + Owner owner = (Owner) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + Apartment apart = room.getApart(); + Owner roomOwner = apart.getOwner(); + assert roomOwner.getId() != null; + if(!roomOwner.getId().equals(owner.getId())){ + throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Unauthorized owner."); } + logger.info("New room updated: {}", room); + } + + @HandleBeforeCreate + public void handleBeforeCreate(Room room) { + Owner owner; + try{ + owner = (Owner) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + }catch (Exception e){ + throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Not owner type."); + } + Apartment apart = room.getApart(); + Owner roomOwner = apart.getOwner(); + assert roomOwner.getId() != null; + if(!roomOwner.getId().equals(owner.getId())){ + throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Unauthorized owner."); } + logger.info("New room updated: {}", room); + } + + @HandleBeforeDelete + public void handleBeforeDelate(Room room) { + Owner owner; + try{ + owner = (Owner) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + }catch (Exception e){ + throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Not owner type."); + } + Apartment apart = room.getApart(); + Owner roomOwner = apart.getOwner(); + assert roomOwner.getId() != null; + if(!roomOwner.getId().equals(owner.getId())){ + throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Unauthorized owner."); } + logger.info("New room updated: {}", room); + } + + +} \ No newline at end of file diff --git a/src/main/java/cat/udl/eps/softarch/demo/repository/RoomRepository.java b/src/main/java/cat/udl/eps/softarch/demo/repository/RoomRepository.java index 8a0a3f6..1a25e1b 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/repository/RoomRepository.java +++ b/src/main/java/cat/udl/eps/softarch/demo/repository/RoomRepository.java @@ -14,6 +14,5 @@ public interface RoomRepository extends CrudRepository, PagingAndSortingRepository { @NotNull Optional findById(@Param("long")@NotNull Long id); - List findByOwner(@Param("owner") Owner owner); List findByApart(@Param("apart") Apartment apart); } diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/CreateRoomStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/CreateRoomStepDefs.java index d16c241..a4d6842 100644 --- a/src/test/java/cat/udl/eps/softarch/demo/steps/CreateRoomStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/CreateRoomStepDefs.java @@ -46,20 +46,16 @@ public void thereIsARoomWithSurfaceIsOccupiedHasWindowHasDeskAndHaveBedByOwnerUs Owner owner = owner_list_by_userid.get(); Room room = RoomUtils.buildRoom(surface,IsOccupied,HasWindow,HasDesk,HasBed); room.setApart(apart); - room.setOwner(owner); roomRepository.save(room); } } - @When("I create a Room with the surface {string}, occupied {string}, window {string}, desk {string} and bed {string}, by owner username {string} and the apartment_name {string}") - public void iCreateARoomWithDetails(String surface, String occupied, String window, String desk, String bed, String UserName, String ApartmentName) throws Exception { - Optional owner_list_by_userid = ownerRepository.findById(UserName); + @When("I create a Room with the surface {string}, occupied {string}, window {string}, desk {string} and bed {string} and the apartment_name {string}") + public void iCreateARoomWithDetails(String surface, String occupied, String window, String desk, String bed, String ApartmentName) throws Exception { Apartment apart = apartmentRepository.findByName(ApartmentName).get(0); - Owner owner = owner_list_by_userid.get(); Room room = RoomUtils.buildRoom(surface,occupied,window,desk,bed); room.setApart(apart); - room.setOwner(owner); stepDefs.result = stepDefs.mockMvc.perform( post("/rooms") .contentType(MediaType.APPLICATION_JSON) @@ -84,7 +80,6 @@ public void iCreateARoomWithTheSurfaceOccupiedWindowDeskAndBed(String surface, S Apartment apartment = apartmentList.iterator().next(); Owner owner = usersList.iterator().next(); room.setApart(apartment); - room.setOwner(owner); stepDefs.result = stepDefs.mockMvc.perform( post("/rooms") .contentType(MediaType.APPLICATION_JSON) diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/DeleteRoomStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/DeleteRoomStepDefs.java index 3773c63..4449cb9 100644 --- a/src/test/java/cat/udl/eps/softarch/demo/steps/DeleteRoomStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/DeleteRoomStepDefs.java @@ -9,11 +9,14 @@ import io.cucumber.java.en.Then; import io.cucumber.java.en.When; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; public class DeleteRoomStepDefs { @@ -51,4 +54,23 @@ public void iTryToDeleteRoomOfTheApartment(String apartmentName) throws Throwabl .with(AuthenticationStepDefs.authenticate())) .andDo(print()); } + + @When("I try to delete Room with the id {string}") + public void iTryToDeleteRoomWithTheId(String id) throws Exception { + if(roomRepository.findById(Long.parseLong(id)).isEmpty()) { + stepDefs.result = stepDefs.mockMvc.perform( + delete("/rooms/" + id) // Ruta para eliminar el Room con el ID dado + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andExpect(status().isNotFound()) + .andDo(print()); + + }else{ + stepDefs.result = stepDefs.mockMvc.perform( + delete("/rooms/" + id) + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())).andDo(print()); + } + + } } diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/UpdateRoomStepsDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/UpdateRoomStepsDefs.java index 6f648c0..fad6739 100644 --- a/src/test/java/cat/udl/eps/softarch/demo/steps/UpdateRoomStepsDefs.java +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/UpdateRoomStepsDefs.java @@ -14,9 +14,12 @@ import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Optional; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; public class UpdateRoomStepsDefs { @Autowired @@ -28,30 +31,41 @@ public class UpdateRoomStepsDefs { @Autowired private OwnerRepository ownerRepository; - @When("I update an apartment called {string}") - public void iUpdateAnApartmentCalled(String apartmentName) throws Exception { - Apartment apartment = apartmentRepository.findByName(apartmentName).get(0); - Room room = RoomUtils.getRoom(roomRepository, apartment); - if (room != null) { + @When("I update the room {string}") + public void iUpdateAnRoom(String id) throws Exception { + Optional RoomList = roomRepository.findById(Long.parseLong(id)); + if(RoomList.isEmpty()) { + JSONObject json = new JSONObject(); json.put("surface", 20); json.put("isOccupied", true); json.put("hasWindow", true); json.put("hasDesk", true); json.put("hasBed", true); + stepDefs.result = stepDefs.mockMvc.perform( + patch("/rooms/" + id) // Ruta para eliminar el Room con el ID dado + .contentType(MediaType.APPLICATION_JSON) + .content(json.toString()) + .characterEncoding(StandardCharsets.UTF_8) + .accept(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andExpect(status().isNotFound()) + .andDo(print()); + + }else{ + Room room = roomRepository.findById(Long.parseLong(id)).get(); + + room.setSurface(3); stepDefs.result = stepDefs.mockMvc.perform(patch(room.getUri()) .contentType(MediaType.APPLICATION_JSON) - .content(json.toString()) + .content(stepDefs.mapper.writeValueAsString(room)) .characterEncoding(StandardCharsets.UTF_8) .accept(MediaType.APPLICATION_JSON) .with(AuthenticationStepDefs.authenticate())) .andDo(print()); - - stepDefs.result.andReturn().getResponse().getHeader("Location"); - } else { - throw new RuntimeException("Room not found."); } + } } diff --git a/src/test/resources/features/CreateRoom.feature b/src/test/resources/features/CreateRoom.feature index f824406..031a151 100644 --- a/src/test/resources/features/CreateRoom.feature +++ b/src/test/resources/features/CreateRoom.feature @@ -4,16 +4,31 @@ Feature: Create Room I must be able to create Room Background: + Given There is a registered user with username "demo" and password "password" and email "demo@sample.app" + Given There is a registered owner with username "owner" and password "password" and email "owner@sample.app" Given There is a registered owner with username "owner1" and password "password" and email "owner1@sample.app" - Given There is a apartment with the name "test", floor "2", address "123 Wall Street", postal code "10005", city "New York", country "United States of America", description "..." and a creation date "2024-10-16T10:30:00-04:00" by owner username "owner" + Given There is a apartment with the name "testApartment", floor "0", address "roomAddressX", postal code "postalCodeX", city "cityX", country "countryX", description "roomDescriptionX" and a creation date "2024-10-18T17:44:30.551316+00:00" by owner username "owner1" Scenario: Create a new Room while logged in Given I login as "owner1" with password "password" - When I create a Room with the surface "30", occupied "false", window "false", desk "false" and bed "false", by owner username "owner1" and the apartment_name "test" + When I create a Room with the surface "30", occupied "false", window "false", desk "false" and bed "false" and the apartment_name "testApartment" Then The response code is 201 Scenario: Create a Room without being logged in Given I'm not logged in - When I create a Room with the surface "30", occupied "false", window "false", desk "false" and bed "false", by owner username "owner1" and the apartment_name "test" - Then The response code is 401 \ No newline at end of file + When I create a Room with the surface "30", occupied "false", window "false", desk "false" and bed "false" and the apartment_name "testApartment" + Then The response code is 401 + + Scenario: Create Room as a non-owner + Given I login as "demo" with password "password" + When I create a Room with the surface "30", occupied "false", window "false", desk "false" and bed "false" and the apartment_name "testApartment" + Then The response code is 403 + And The error message is "Not owner type." + + + Scenario: Create Room as a other owner + Given I login as "owner" with password "password" + When I create a Room with the surface "30", occupied "false", window "false", desk "false" and bed "false" and the apartment_name "testApartment" + Then The response code is 403 + And The error message is "Unauthorized owner." \ No newline at end of file diff --git a/src/test/resources/features/DeleteRoom.feature b/src/test/resources/features/DeleteRoom.feature index 8be3aac..05bbb55 100644 --- a/src/test/resources/features/DeleteRoom.feature +++ b/src/test/resources/features/DeleteRoom.feature @@ -10,10 +10,29 @@ Feature: Delete Room Scenario: Delete a Room with owner and room not logged in Given I'm not logged in - When I try to delete Room of the apartment "testApartment" + When I try to delete Room with the id "1" Then The response code is 401 Scenario: Delete a Room with owner and room logged in + Given I login as "owner" with password "password" + When I try to delete Room with the id "1" + Then The response code is 200 + + Scenario: Delete a Room that not exists + Given I login as "owner" with password "password" + When I try to delete Room with the id "3" + Then The response code is 404 + + Scenario: Delete Room as a non-owner + Given I login as "demo" with password "password" + When I try to delete Room with the id "1" + Then The response code is 403 + And The error message is "Not owner type." + + Scenario: Delete Room as another owner Given I login as "owner1" with password "password" - When I try to delete Room of the apartment "testApartment" - Then The response code is 200 \ No newline at end of file + When I try to delete Room with the id "1" + Then The response code is 403 + And The error message is "Unauthorized owner." + + diff --git a/src/test/resources/features/UpdateRoom.feature b/src/test/resources/features/UpdateRoom.feature index 3f76bf1..3fe106a 100644 --- a/src/test/resources/features/UpdateRoom.feature +++ b/src/test/resources/features/UpdateRoom.feature @@ -4,33 +4,56 @@ Feature: Update Room I must be able to update Room Background: - Given There is a registered user with username "user" and password "password" and email "user@sample.app" - Given There is a apartment with the name "testApartment", floor "0", address "roomAddressX", postal code "postalCodeX", city "cityX", country "countryX", description "roomDescriptionX" and a creation date "2024-10-18T17:44:30.551316+00:00" by owner username "owner" - Given There is a room with surface "30", is occupied "true", has window "true", has desk "false" and have bed "true", by owner username "owner" and the apartment_name "testApartment" + Given There is a registered user with username "demo" and password "password" and email "demo@sample.app" + Given There is a registered owner with username "owner" and password "password" and email "owner@sample.app" + Given There is a registered owner with username "owner1" and password "password" and email "owner1@sample.app" + Given There is a apartment with the name "testApartment", floor "0", address "roomAddressX", postal code "postalCodeX", city "cityX", country "countryX", description "roomDescriptionX" and a creation date "2024-10-18T17:44:30.551316+00:00" by owner username "owner1" + Given There is a room with surface "30", is occupied "true", has window "true", has desk "false" and have bed "true", by owner username "owner1" and the apartment_name "testApartment" Scenario: Update Room without being logged in Given I'm not logged in - When I update an apartment called "testApartment" + When I update the room "1" Then The response code is 401 And The error message is "Unauthorized" - Scenario: Update Room being logged in - Given I login as "user" with password "password" - When I update an apartment called "testApartment" + Scenario: Update Room being logged in as owner + Given I login as "owner1" with password "password" + When I update the room "1" Then The response code is 200 Scenario: Update Room being logged in without surface - Given I login as "user" with password "password" - When I update an apartment called "testApartment" + Given I login as "owner1" with password "password" + When I update the room "1" Then The response code is 200 - Scenario: Update Room being logged in without occupancy status - Given I login as "user" with password "password" - When I update an apartment called "testApartment" + + + Scenario: Update Room being logged in as owner without occupancy status + Given I login as "owner1" with password "password" + When I update the room "1" Then The response code is 200 Scenario: Update Room with non-existing ID Given I login as "wrong-user" with password "wrong-password" - When I update an apartment called "testApartment" + When I update the room "1" Then The response code is 401 - And The error message is "Unauthorized" \ No newline at end of file + And The error message is "Unauthorized" + + Scenario: Update Room that not exist + Given I login as "owner" with password "password" + When I update the room "3" + Then The response code is 404 + + Scenario: Update Room as a non-owner + Given I login as "demo" with password "password" + When I update the room "1" + Then The response code is 403 + And The error message is "Forbidden" + + + Scenario: Update Room as a other owner + Given I login as "owner" with password "password" + When I update the room "1" + Then The response code is 403 + And The error message is "Unauthorized owner." +