From 06472395e9545a51014329853363d5b27b63c212 Mon Sep 17 00:00:00 2001 From: Miguel Reboiro Jato Date: Thu, 21 Oct 2021 16:51:04 +0200 Subject: [PATCH] Modifies REST API for a easier client integration The REST API methods for entity creation and modification have been simplified with more basic entities. In addition, the UserResource class has been added so that it is possible now for clients to use it for user authentication. --- .../xcs/domain/entities/Administrator.java | 1 + .../uvigo/esei/xcs/domain/entities/Owner.java | 1 + .../uvigo/esei/xcs/domain/entities/User.java | 13 + .../es/uvigo/esei/xcs/rest/OwnerResource.java | 45 +- .../es/uvigo/esei/xcs/rest/PetResource.java | 23 +- .../es/uvigo/esei/xcs/rest/UserResource.java | 31 ++ .../xcs/rest/entity/OwnerCreationData.java | 31 ++ .../xcs/rest/entity/OwnerEditionData.java | 25 + .../uvigo/esei/xcs/rest/entity/PetData.java | 48 ++ .../esei/xcs/rest/entity/UserCredentials.java | 26 + rest/src/main/webapp/WEB-INF/web.xml | 12 + .../esei/xcs/rest/OwnerResourceRestTest.java | 522 +++++++++--------- .../esei/xcs/rest/OwnerResourceUnitTest.java | 356 ++++++------ .../uvigo/esei/xcs/service/UserService.java | 30 + .../service/PetServiceIntegrationTest.java | 4 +- .../service/ServiceIntegrationTestSuite.java | 4 +- ...erServiceIllegalAccessIntegrationTest.java | 85 +++ .../service/UserServiceIntegrationTest.java | 46 ++ .../xcs/domain/entities/IsEqualToUser.java | 38 ++ .../xcs/domain/entities/OwnersDataset.java | 46 +- .../xcs/domain/entities/UsersDataset.java | 19 + 21 files changed, 925 insertions(+), 481 deletions(-) create mode 100644 rest/src/main/java/es/uvigo/esei/xcs/rest/UserResource.java create mode 100644 rest/src/main/java/es/uvigo/esei/xcs/rest/entity/OwnerCreationData.java create mode 100644 rest/src/main/java/es/uvigo/esei/xcs/rest/entity/OwnerEditionData.java create mode 100644 rest/src/main/java/es/uvigo/esei/xcs/rest/entity/PetData.java create mode 100644 rest/src/main/java/es/uvigo/esei/xcs/rest/entity/UserCredentials.java create mode 100644 service/src/main/java/es/uvigo/esei/xcs/service/UserService.java create mode 100644 service/src/test/java/es/uvigo/esei/xcs/service/UserServiceIllegalAccessIntegrationTest.java create mode 100644 service/src/test/java/es/uvigo/esei/xcs/service/UserServiceIntegrationTest.java create mode 100644 tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToUser.java create mode 100644 tests/src/main/java/es/uvigo/esei/xcs/domain/entities/UsersDataset.java diff --git a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Administrator.java b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Administrator.java index e279bb1..d3b1b30 100644 --- a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Administrator.java +++ b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Administrator.java @@ -35,5 +35,6 @@ public class Administrator extends User implements Serializable { */ public Administrator(String login, String password) { super(login, password); + this.role = "ADMIN"; } } diff --git a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Owner.java b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Owner.java index d3645ec..d6d1168 100644 --- a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Owner.java +++ b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Owner.java @@ -53,6 +53,7 @@ public class Owner extends User implements Serializable { */ public Owner(String login, String password) { super(login, password); + this.role = "OWNER"; this.pets = new HashSet<>(); } diff --git a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/User.java b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/User.java index 289b34a..b55c735 100644 --- a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/User.java +++ b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/User.java @@ -33,6 +33,9 @@ public abstract class User implements Serializable { @Column(length = 32, nullable = false) protected String password; + @Column(name="role", insertable = false, updatable = false) + protected String role; + User() {} /** @@ -78,6 +81,16 @@ public abstract class User implements Serializable { this.login = login; } + + /** + * Returns the role of the user. This value is automatically set by JPA, as + * it is the value used as discriminator in the inheritance. + * + * @return the role of the user. + */ + public String getRole() { + return role; + } /** * Returns the MD5 of the user's password. Capital letters are used diff --git a/rest/src/main/java/es/uvigo/esei/xcs/rest/OwnerResource.java b/rest/src/main/java/es/uvigo/esei/xcs/rest/OwnerResource.java index 8d15c31..7b08121 100644 --- a/rest/src/main/java/es/uvigo/esei/xcs/rest/OwnerResource.java +++ b/rest/src/main/java/es/uvigo/esei/xcs/rest/OwnerResource.java @@ -18,7 +18,8 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import es.uvigo.esei.xcs.domain.entities.Owner; -import es.uvigo.esei.xcs.domain.entities.Pet; +import es.uvigo.esei.xcs.rest.entity.OwnerEditionData; +import es.uvigo.esei.xcs.rest.entity.OwnerCreationData; import es.uvigo.esei.xcs.service.OwnerService; /** @@ -74,19 +75,20 @@ public class OwnerResource { * Creates a new owner. This owner may include a list of pets, that will be * also created. * - * @param owner a new owner to be stored. + * @param ownerData a new owner to be stored. * @return a {@code CREATED} response with the URI of the new owner in the * {@code Location} header. * @throws IllegalArgumentException if owner is {@code null} or if an owner * with the same login already exists. */ @POST - public Response create(Owner owner) { - // Pets are serialized without owner. - assignOwnerToPets(owner); - + public Response create(OwnerCreationData ownerData) { + if (ownerData == null) { + throw new IllegalArgumentException("ownerData can't be null"); + } + try { - final Owner newOwner = this.service.create(owner); + final Owner newOwner = this.service.create(ownerData.toOwner()); final URI ownerUri = uriInfo.getAbsolutePathBuilder() .path(newOwner.getLogin()) .build(); @@ -101,15 +103,24 @@ public class OwnerResource { * Updates an owner. This owner may include a list of pets, that will be * also created or updated. If the owner does not exists it will be created. * - * @param owner an owner to be updated. + * @param ownerData an owner to be updated. * @return an empty {@code OK} response. * @throws IllegalArgumentException if owner is {@code null}. */ + @Path("{login}") @PUT - public Response update(Owner owner) { - // Pets are serialized without owner. - assignOwnerToPets(owner); - + public Response update(@PathParam("login") String login, OwnerEditionData ownerData) { + if (login == null) { + throw new IllegalArgumentException("login can't be null"); + } + if (ownerData == null) { + throw new IllegalArgumentException("ownerData can't be null"); + } + + final Owner owner = this.service.get(login); + + ownerData.assignData(owner); + this.service.update(owner); return Response.ok().build(); @@ -133,14 +144,4 @@ public class OwnerResource { return Response.ok().build(); } - - private static void assignOwnerToPets(Owner owner) { - if (owner == null) - throw new IllegalArgumentException("owner can't be null"); - - for (Pet pet : owner.getPets()) { - if (pet.getOwner() != owner) - pet.setOwner(owner); - } - } } diff --git a/rest/src/main/java/es/uvigo/esei/xcs/rest/PetResource.java b/rest/src/main/java/es/uvigo/esei/xcs/rest/PetResource.java index 9194ef2..a946b50 100644 --- a/rest/src/main/java/es/uvigo/esei/xcs/rest/PetResource.java +++ b/rest/src/main/java/es/uvigo/esei/xcs/rest/PetResource.java @@ -19,6 +19,7 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import es.uvigo.esei.xcs.domain.entities.Pet; +import es.uvigo.esei.xcs.rest.entity.PetData; import es.uvigo.esei.xcs.service.PetService; /** @@ -73,7 +74,7 @@ public class PetResource { /** * Creates a new pet owned by the current user. * - * @param pet a new owner to be stored. + * @param petData a new owner to be stored. * @return a {@code CREATED} response with the URI of the new pet in the * {@code Location} header. * @throws IllegalArgumentException if pet is {@code null} or if a pet with @@ -83,14 +84,15 @@ public class PetResource { * thrown. */ @POST - public Response create(Pet pet) throws SecurityException { - if (pet == null) + public Response create(PetData petData) throws SecurityException { + if (petData == null) throw new IllegalArgumentException("pet can't be null"); try { - final Pet newPet = this.service.create(pet); + final Pet pet = this.service.create(petData.toPet()); + final URI petUri = uriInfo.getAbsolutePathBuilder() - .path(Integer.toString(newPet.getId())) + .path(Integer.toString(pet.getId())) .build(); return Response.created(petUri).build(); @@ -105,18 +107,23 @@ public class PetResource { * Updates the information of a pet. If the pet is not stored, it will be * created. * - * @param pet a pet to be updated. + * @param id the identifier of the pet to be modified. + * @param petData a pet to be updated. * @return an empty {@code OK} response. * @throws IllegalArgumentException if pet is {@code null} of it has no * owner. * @throws SecurityException if the pet's owner is not the current user. */ + @Path("{id}") @PUT - public Response update(Pet pet) throws SecurityException { - if (pet == null) + public Response update(@PathParam("id") int id, PetData petData) throws SecurityException { + if (petData == null) throw new IllegalArgumentException("pet can't be null"); try { + final Pet pet = this.service.get(id); + petData.assignData(pet); + this.service.update(pet); return Response.ok().build(); diff --git a/rest/src/main/java/es/uvigo/esei/xcs/rest/UserResource.java b/rest/src/main/java/es/uvigo/esei/xcs/rest/UserResource.java new file mode 100644 index 0000000..35d0046 --- /dev/null +++ b/rest/src/main/java/es/uvigo/esei/xcs/rest/UserResource.java @@ -0,0 +1,31 @@ +package es.uvigo.esei.xcs.rest; + +import javax.ejb.EJB; +import javax.ejb.EJBAccessException; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import es.uvigo.esei.xcs.domain.entities.User; +import es.uvigo.esei.xcs.rest.entity.UserCredentials; +import es.uvigo.esei.xcs.service.UserService; + +@Path("user") +@Produces(MediaType.APPLICATION_JSON) +public class UserResource { + @EJB + private UserService service; + + @GET + public Response getCredentials() { + try { + final User currentUser = this.service.getCurrentUser(); + + return Response.ok(new UserCredentials(currentUser)).build(); + } catch (EJBAccessException eae) { + throw new SecurityException(eae); + } + } +} diff --git a/rest/src/main/java/es/uvigo/esei/xcs/rest/entity/OwnerCreationData.java b/rest/src/main/java/es/uvigo/esei/xcs/rest/entity/OwnerCreationData.java new file mode 100644 index 0000000..2d35f46 --- /dev/null +++ b/rest/src/main/java/es/uvigo/esei/xcs/rest/entity/OwnerCreationData.java @@ -0,0 +1,31 @@ +package es.uvigo.esei.xcs.rest.entity; + +import java.io.Serializable; + +import es.uvigo.esei.xcs.domain.entities.Owner; + +public class OwnerCreationData implements Serializable { + private static final long serialVersionUID = 1L; + + private String login; + private String password; + + OwnerCreationData() {} + + public OwnerCreationData(String login, String password) { + this.login = login; + this.password = password; + } + + public String getLogin() { + return login; + } + + public String getPassword() { + return password; + } + + public Owner toOwner() { + return new Owner(this.login, this.password); + } +} diff --git a/rest/src/main/java/es/uvigo/esei/xcs/rest/entity/OwnerEditionData.java b/rest/src/main/java/es/uvigo/esei/xcs/rest/entity/OwnerEditionData.java new file mode 100644 index 0000000..867e2dc --- /dev/null +++ b/rest/src/main/java/es/uvigo/esei/xcs/rest/entity/OwnerEditionData.java @@ -0,0 +1,25 @@ +package es.uvigo.esei.xcs.rest.entity; + +import java.io.Serializable; + +import es.uvigo.esei.xcs.domain.entities.Owner; + +public class OwnerEditionData implements Serializable { + private static final long serialVersionUID = 1L; + private String password; + + OwnerEditionData() {} + + public OwnerEditionData(String password) { + this.password = password; + } + + public String getPassword() { + return password; + } + + public void assignData(Owner owner) { + owner.changePassword(this.password); + } + +} diff --git a/rest/src/main/java/es/uvigo/esei/xcs/rest/entity/PetData.java b/rest/src/main/java/es/uvigo/esei/xcs/rest/entity/PetData.java new file mode 100644 index 0000000..f168e80 --- /dev/null +++ b/rest/src/main/java/es/uvigo/esei/xcs/rest/entity/PetData.java @@ -0,0 +1,48 @@ +package es.uvigo.esei.xcs.rest.entity; + +import java.io.Serializable; +import java.util.Date; + +import es.uvigo.esei.xcs.domain.entities.AnimalType; +import es.uvigo.esei.xcs.domain.entities.Pet; + +public class PetData implements Serializable { + private static final long serialVersionUID = 1L; + + private String name; + private AnimalType animal; + private Date birth; + + PetData() {} + + public PetData(String name, AnimalType animal, Date birth) { + this.name = name; + this.animal = animal; + this.birth = birth; + } + + public String getName() { + return name; + } + + public AnimalType getAnimal() { + return animal; + } + + public Date getBirth() { + return birth; + } + + public Pet assignData(Pet pet) { + pet.setName(this.name); + pet.setAnimal(this.animal); + pet.setBirth(this.birth); + + return pet; + } + + public Pet toPet() { + return new Pet(this.name, this.animal, this.birth); + } + +} diff --git a/rest/src/main/java/es/uvigo/esei/xcs/rest/entity/UserCredentials.java b/rest/src/main/java/es/uvigo/esei/xcs/rest/entity/UserCredentials.java new file mode 100644 index 0000000..3a89ab1 --- /dev/null +++ b/rest/src/main/java/es/uvigo/esei/xcs/rest/entity/UserCredentials.java @@ -0,0 +1,26 @@ +package es.uvigo.esei.xcs.rest.entity; + +import java.io.Serializable; + +import es.uvigo.esei.xcs.domain.entities.User; + +public class UserCredentials implements Serializable { + private static final long serialVersionUID = 1L; + + private String login; + private String role; + + public UserCredentials(User user) { + this.login = user.getLogin(); + this.role = user.getRole(); + } + + public String getLogin() { + return login; + } + + public String getRole() { + return role; + } + +} diff --git a/rest/src/main/webapp/WEB-INF/web.xml b/rest/src/main/webapp/WEB-INF/web.xml index f8bf7f3..e36c67f 100644 --- a/rest/src/main/webapp/WEB-INF/web.xml +++ b/rest/src/main/webapp/WEB-INF/web.xml @@ -10,6 +10,18 @@ + + + user + /api/user/* + OPTIONS + + + ADMIN + OWNER + + + admin diff --git a/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceRestTest.java b/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceRestTest.java index dbc2dee..1c77e70 100644 --- a/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceRestTest.java +++ b/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceRestTest.java @@ -7,8 +7,8 @@ import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.NON_EXISTENT_LOGIN import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.OWNER_WITHOUT_PETS_LOGIN; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.OWNER_WITH_PETS_LOGIN; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentOwner; -import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithFreshPets; -import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithPersistentPets; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerLogin; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerPassword; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithoutPets; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newPasswordForExistentOwner; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.owners; @@ -23,7 +23,6 @@ import static org.junit.Assert.assertThat; import java.util.List; import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -48,261 +47,272 @@ import org.junit.runner.RunWith; import es.uvigo.esei.xcs.domain.entities.Owner; import es.uvigo.esei.xcs.rest.GenericTypes.ListOwnerType; +import es.uvigo.esei.xcs.rest.entity.OwnerCreationData; +import es.uvigo.esei.xcs.rest.entity.OwnerEditionData; import es.uvigo.esei.xcs.service.OwnerService; @RunWith(Arquillian.class) public class OwnerResourceRestTest { - private final static String BASE_PATH = "api/owner/"; - private static final String BASIC_AUTHORIZATION = "Basic am9zZTpqb3NlcGFzcw="; - - @Deployment - public static Archive createDeployment() { - return ShrinkWrap.create(WebArchive.class, "test.war") - .addClass(OwnerResource.class) - .addClasses(CORSFilter.class, IllegalArgumentExceptionMapper.class, SecurityExceptionMapper.class) - .addPackage(OwnerService.class.getPackage()) - .addPackage(Owner.class.getPackage()) - .addAsResource("test-persistence.xml", "META-INF/persistence.xml") - .addAsWebInfResource("jboss-web.xml") - .addAsWebInfResource("web.xml") - .addAsResource("arquillian.extension.persistence.properties") - .addAsResource("arquillian.extension.persistence.dbunit.properties") - .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); - } - - @Test @InSequence(1) - @UsingDataSet("owners.xml") - @Cleanup(phase = TestExecutionPhase.NONE) - public void beforeGet() {} - - @Test @InSequence(2) - @RunAsClient - @Header(name = "Authorization", value = BASIC_AUTHORIZATION) - public void testGet( - @ArquillianResteasyResource(BASE_PATH + EXISTENT_LOGIN) ResteasyWebTarget webTarget - ) throws Exception { - final Response response = webTarget.request().get(); - - assertThat(response, hasOkStatus()); - - final Owner owner = response.readEntity(Owner.class); - final Owner expected = existentOwner(); - - assertThat(owner, is(equalToOwner(expected))); - } - - @Test @InSequence(3) - @ShouldMatchDataSet("owners.xml") - @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) - public void afterGet() {} - - - - @Test @InSequence(4) - @UsingDataSet("owners.xml") - @Cleanup(phase = TestExecutionPhase.NONE) - public void beforeGetNonExistent() {} - - @Test @InSequence(5) - @RunAsClient - @Header(name = "Authorization", value = BASIC_AUTHORIZATION) - public void testGetNonExistent( - @ArquillianResteasyResource(BASE_PATH + NON_EXISTENT_LOGIN) ResteasyWebTarget webTarget - ) throws Exception { - final Response response = webTarget.request().get(); - - assertThat(response, hasBadRequestStatus()); - } - - @Test @InSequence(6) - @ShouldMatchDataSet("owners.xml") - @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) - public void afterGetNonExistent() {} - - - - @Test @InSequence(10) - @UsingDataSet("owners.xml") - @Cleanup(phase = TestExecutionPhase.NONE) - public void beforeList() {} - - @Test @InSequence(11) - @RunAsClient - @Header(name = "Authorization", value = BASIC_AUTHORIZATION) - public void testList( - @ArquillianResteasyResource(BASE_PATH) ResteasyWebTarget webTarget - ) throws Exception { - final Response response = webTarget.request().get(); - - assertThat(response, hasOkStatus()); - - final List list = ListOwnerType.readEntity(response); - assertThat(list, containsOwnersInAnyOrder(owners())); - } - - @Test @InSequence(12) - @ShouldMatchDataSet("owners.xml") - @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) - public void afterList() {} - - - - @Test @InSequence(20) - @UsingDataSet("owners.xml") - @Cleanup(phase = TestExecutionPhase.NONE) - public void beforeCreate() {} - - @Test @InSequence(21) - @RunAsClient - @Header(name = "Authorization", value = BASIC_AUTHORIZATION) - public void testCreate( - @ArquillianResteasyResource(BASE_PATH) ResteasyWebTarget webTarget - ) throws Exception { - testCreateOwner(webTarget, newOwnerWithoutPets()); - } - - @Test @InSequence(22) - @ShouldMatchDataSet({"owners.xml", "owners-create-without-pets.xml"}) - @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) - public void afterCreate() {} - - - - @Test @InSequence(23) - @UsingDataSet("owners.xml") - @Cleanup(phase = TestExecutionPhase.NONE) - public void beforeCreateWithPets() {} - - @Test @InSequence(24) - @RunAsClient - @Header(name = "Authorization", value = BASIC_AUTHORIZATION) - public void testCreateWithPets( - @ArquillianResteasyResource(BASE_PATH) ResteasyWebTarget webTarget - ) throws Exception { - testCreateOwner(webTarget, newOwnerWithFreshPets(), newOwnerWithPersistentPets()); - } - - @Test @InSequence(25) - @ShouldMatchDataSet({"owners.xml", "owners-create-with-pets.xml"}) - @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) - public void afterCreateWithPets() {} - - - private void testCreateOwner(WebTarget webTarget, Owner newOwner) { - testCreateOwner(webTarget, newOwner, newOwner); - } - - private void testCreateOwner(WebTarget webTarget, Owner newOwner, Owner persistentOwner) { - final Response response = webTarget.request().post(json(newOwner)); - - assertThat(response, hasCreatedStatus()); - - final String location = response.getHeaderString("Location"); - - final Response responseGet = authorizedJsonRequestGet(location); - final Owner owner = responseGet.readEntity(Owner.class); - assertThat(owner, is(equalToOwner(persistentOwner))); - } - - - @Test @InSequence(30) - @UsingDataSet("owners.xml") - @Cleanup(phase = TestExecutionPhase.NONE) - public void beforeUpdatePassword() {} - - @Test @InSequence(31) - @RunAsClient - @Header(name = "Authorization", value = BASIC_AUTHORIZATION) - public void testUpdatePassword( - @ArquillianResteasyResource(BASE_PATH) ResteasyWebTarget webTarget - ) throws Exception { - final Owner owner = existentOwner(); - owner.changePassword(newPasswordForExistentOwner()); - - final Response response = webTarget.request().put(json(owner)); - - assertThat(response, hasOkStatus()); - } - - @Test @InSequence(32) - @ShouldMatchDataSet("owners-update-password.xml") - @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) - public void afterUpdatePassword() {} - - - - @Test @InSequence(40) - @UsingDataSet("owners.xml") - @Cleanup(phase = TestExecutionPhase.NONE) - public void beforeDeleteWithoutPets() {} - - @Test @InSequence(41) - @RunAsClient - @Header(name = "Authorization", value = BASIC_AUTHORIZATION) - public void testDeleteWithoutPets( - @ArquillianResteasyResource(BASE_PATH + OWNER_WITHOUT_PETS_LOGIN) ResteasyWebTarget webTarget - ) throws Exception { - final Response response = webTarget.request().delete(); - - assertThat(response, hasOkStatus()); - } - - @Test @InSequence(42) - @ShouldMatchDataSet("owners-remove-without-pets.xml") - @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) - public void afterDeleteWithoutPets() {} - - - - @Test @InSequence(43) - @UsingDataSet("owners.xml") - @Cleanup(phase = TestExecutionPhase.NONE) - public void beforeDeleteWithPets() {} - - @Test @InSequence(44) - @RunAsClient - @Header(name = "Authorization", value = BASIC_AUTHORIZATION) - public void testDeleteWithPets( - @ArquillianResteasyResource(BASE_PATH + OWNER_WITH_PETS_LOGIN) ResteasyWebTarget webTarget - ) throws Exception { - final Response response = webTarget.request().delete(); - - assertThat(response, hasOkStatus()); - } - - @Test @InSequence(45) - @ShouldMatchDataSet("owners-remove-with-pets.xml") - @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) - public void afterDeleteWithPets() {} - - - - @Test @InSequence(46) - @UsingDataSet("owners.xml") - @Cleanup(phase = TestExecutionPhase.NONE) - public void beforeDeleteNoLogin() {} - - @Test @InSequence(47) - @RunAsClient - @Header(name = "Authorization", value = BASIC_AUTHORIZATION) - public void testDeleteNoLogin( - @ArquillianResteasyResource(BASE_PATH) ResteasyWebTarget webTarget - ) throws Exception { - final Response response = webTarget.request().delete(); - - assertThat(response, hasMethodNotAllowedStatus()); - } - - @Test @InSequence(48) - @ShouldMatchDataSet("owners.xml") - @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) - public void afterDeleteNoLogin() {} - - - private static Response authorizedJsonRequestGet(String uri) { - return ClientBuilder.newClient().target(uri) - .request(MediaType.APPLICATION_JSON_TYPE) - .header("Authorization", BASIC_AUTHORIZATION) - .get(); - } + private final static String BASE_PATH = "api/owner/"; + private static final String BASIC_AUTHORIZATION = "Basic am9zZTpqb3NlcGFzcw="; + + @Deployment + public static Archive createDeployment() { + return ShrinkWrap.create(WebArchive.class, "test.war") + .addClass(OwnerResource.class) + .addClasses(OwnerCreationData.class, OwnerEditionData.class) + .addClasses(CORSFilter.class, IllegalArgumentExceptionMapper.class, SecurityExceptionMapper.class) + .addPackage(OwnerService.class.getPackage()) + .addPackage(Owner.class.getPackage()) + .addAsResource("test-persistence.xml", "META-INF/persistence.xml") + .addAsWebInfResource("jboss-web.xml") + .addAsWebInfResource("web.xml") + .addAsResource("arquillian.extension.persistence.properties") + .addAsResource("arquillian.extension.persistence.dbunit.properties") + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + @Test + @InSequence(1) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeGet() {} + + @Test + @InSequence(2) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testGet( + @ArquillianResteasyResource(BASE_PATH + EXISTENT_LOGIN) + ResteasyWebTarget webTarget + ) throws Exception { + final Response response = webTarget.request().get(); + + assertThat(response, hasOkStatus()); + + final Owner owner = response.readEntity(Owner.class); + final Owner expected = existentOwner(); + + assertThat(owner, is(equalToOwner(expected))); + } + + @Test + @InSequence(3) + @ShouldMatchDataSet("owners.xml") + @CleanupUsingScript({ + "cleanup.sql", "cleanup-autoincrement.sql" + }) + public void afterGet() {} + + @Test + @InSequence(4) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeGetNonExistent() {} + + @Test + @InSequence(5) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testGetNonExistent( + @ArquillianResteasyResource(BASE_PATH + NON_EXISTENT_LOGIN) + ResteasyWebTarget webTarget + ) throws Exception { + final Response response = webTarget.request().get(); + + assertThat(response, hasBadRequestStatus()); + } + + @Test + @InSequence(6) + @ShouldMatchDataSet("owners.xml") + @CleanupUsingScript({ + "cleanup.sql", "cleanup-autoincrement.sql" + }) + public void afterGetNonExistent() {} + + @Test + @InSequence(10) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeList() {} + + @Test + @InSequence(11) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testList( + @ArquillianResteasyResource(BASE_PATH) + ResteasyWebTarget webTarget + ) throws Exception { + final Response response = webTarget.request().get(); + + assertThat(response, hasOkStatus()); + + final List list = ListOwnerType.readEntity(response); + assertThat(list, containsOwnersInAnyOrder(owners())); + } + + @Test + @InSequence(12) + @ShouldMatchDataSet("owners.xml") + @CleanupUsingScript({ + "cleanup.sql", "cleanup-autoincrement.sql" + }) + public void afterList() {} + + @Test + @InSequence(20) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeCreate() {} + + @Test + @InSequence(21) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testCreate( + @ArquillianResteasyResource(BASE_PATH) + ResteasyWebTarget webTarget + ) throws Exception { + final Owner newOwner = newOwnerWithoutPets(); + final OwnerCreationData ownerData = new OwnerCreationData(newOwnerLogin(), newOwnerPassword()); + + final Response response = webTarget.request().post(json(ownerData)); + + assertThat(response, hasCreatedStatus()); + + final String location = response.getHeaderString("Location"); + + final Response responseGet = authorizedJsonRequestGet(location); + final Owner owner = responseGet.readEntity(Owner.class); + assertThat(owner, is(equalToOwner(newOwner))); + } + + @Test + @InSequence(22) + @ShouldMatchDataSet({ + "owners.xml", "owners-create-without-pets.xml" + }) + @CleanupUsingScript({ + "cleanup.sql", "cleanup-autoincrement.sql" + }) + public void afterCreate() {} + + @Test + @InSequence(30) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeUpdatePassword() {} + + @Test + @InSequence(31) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testUpdatePassword( + @ArquillianResteasyResource(BASE_PATH + EXISTENT_LOGIN) + ResteasyWebTarget webTarget + ) throws Exception { + final OwnerEditionData ownerData = new OwnerEditionData(newPasswordForExistentOwner()); + + final Response response = webTarget.request().put(json(ownerData)); + + assertThat(response, hasOkStatus()); + } + + @Test + @InSequence(32) + @ShouldMatchDataSet("owners-update-password.xml") + @CleanupUsingScript({ + "cleanup.sql", "cleanup-autoincrement.sql" + }) + public void afterUpdatePassword() {} + + @Test + @InSequence(40) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeDeleteWithoutPets() {} + + @Test + @InSequence(41) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testDeleteWithoutPets( + @ArquillianResteasyResource(BASE_PATH + OWNER_WITHOUT_PETS_LOGIN) + ResteasyWebTarget webTarget + ) throws Exception { + final Response response = webTarget.request().delete(); + + assertThat(response, hasOkStatus()); + } + + @Test + @InSequence(42) + @ShouldMatchDataSet("owners-remove-without-pets.xml") + @CleanupUsingScript({ + "cleanup.sql", "cleanup-autoincrement.sql" + }) + public void afterDeleteWithoutPets() {} + + @Test + @InSequence(43) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeDeleteWithPets() {} + + @Test + @InSequence(44) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testDeleteWithPets( + @ArquillianResteasyResource(BASE_PATH + OWNER_WITH_PETS_LOGIN) + ResteasyWebTarget webTarget + ) throws Exception { + final Response response = webTarget.request().delete(); + + assertThat(response, hasOkStatus()); + } + + @Test + @InSequence(45) + @ShouldMatchDataSet("owners-remove-with-pets.xml") + @CleanupUsingScript({ + "cleanup.sql", "cleanup-autoincrement.sql" + }) + public void afterDeleteWithPets() {} + + @Test + @InSequence(46) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeDeleteNoLogin() {} + + @Test + @InSequence(47) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testDeleteNoLogin( + @ArquillianResteasyResource(BASE_PATH) + ResteasyWebTarget webTarget + ) throws Exception { + final Response response = webTarget.request().delete(); + + assertThat(response, hasMethodNotAllowedStatus()); + } + + @Test + @InSequence(48) + @ShouldMatchDataSet("owners.xml") + @CleanupUsingScript({ + "cleanup.sql", "cleanup-autoincrement.sql" + }) + public void afterDeleteNoLogin() {} + + private static Response authorizedJsonRequestGet(String uri) { + return ClientBuilder.newClient().target(uri) + .request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", BASIC_AUTHORIZATION) + .get(); + } } diff --git a/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceUnitTest.java b/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceUnitTest.java index abfce26..446d177 100644 --- a/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceUnitTest.java +++ b/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceUnitTest.java @@ -3,17 +3,19 @@ package es.uvigo.esei.xcs.rest; import static es.uvigo.esei.xcs.domain.entities.IsEqualToOwner.containsOwnersInAnyOrder; import static es.uvigo.esei.xcs.domain.entities.IsEqualToOwner.equalToOwner; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.anyLogin; -import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.anyOwner; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentLogin; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentOwner; -import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithFreshPets; -import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithPersistentPets; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentPassword; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerLogin; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerPassword; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newPasswordForExistentOwner; import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.owners; import static es.uvigo.esei.xcs.http.util.HasHttpStatus.hasCreatedStatus; import static es.uvigo.esei.xcs.http.util.HasHttpStatus.hasOkStatus; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; +import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.expectLastCall; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; @@ -38,177 +40,185 @@ import org.junit.runner.RunWith; import es.uvigo.esei.xcs.domain.entities.Owner; import es.uvigo.esei.xcs.domain.entities.OwnersDataset; +import es.uvigo.esei.xcs.rest.entity.OwnerCreationData; +import es.uvigo.esei.xcs.rest.entity.OwnerEditionData; import es.uvigo.esei.xcs.service.OwnerService; @RunWith(EasyMockRunner.class) public class OwnerResourceUnitTest extends EasyMockSupport { - @TestSubject - private OwnerResource resource = new OwnerResource(); - - @Mock - private OwnerService facade; - - @Mock - private UriInfo uriInfo; - - @Mock - private UriBuilder uriBuilder; - - @After - public void tearDown() throws Exception { - verifyAll(); - } - - @Test - public void testGet() { - final Owner owner = OwnersDataset.anyOwner(); - - expect(facade.get(owner.getLogin())) - .andReturn(owner); - - replayAll(); - - final Response response = resource.get(owner.getLogin()); - - assertThat(response, hasOkStatus()); - assertThat(response.getEntity(), is(instanceOf(Owner.class))); - assertThat((Owner) response.getEntity(), is(equalToOwner(owner))); - } - - @Test(expected = IllegalArgumentException.class) - public void testGetNull() { - replayAll(); - - resource.get(null); - } - - @Test(expected = IllegalArgumentException.class) - public void testGetMissing() { - final String login = anyLogin(); - - expect(facade.get(login)) - .andReturn(null); - - replayAll(); - - resource.get(login); - } - - @Test - @SuppressWarnings("unchecked") - public void testList() { - final Owner[] owners = owners(); - - expect(facade.list()) - .andReturn(asList(owners)); - - replayAll(); - - final Response response = resource.list(); - - assertThat(response, hasOkStatus()); - assertThat(response.getEntity(), is(instanceOf(List.class))); - assertThat((List) response.getEntity(), containsOwnersInAnyOrder(owners)); - } - - @Test - @SuppressWarnings("unchecked") - public void testListEmpty() { - expect(facade.list()) - .andReturn(emptyList()); - - replayAll(); - - final Response response = resource.list(); - - assertThat(response, hasOkStatus()); - assertThat(response.getEntity(), is(instanceOf(List.class))); - assertThat((List) response.getEntity(), is(empty())); - } - - @Test - public void testCreate() throws Exception { - final Owner newOwner = newOwnerWithFreshPets(); - final Owner createdOwner = newOwnerWithPersistentPets(); - - final URI mockUri = new URI("http://host/api/owner/" + newOwner.getLogin()); - - expect(facade.create(newOwner)) - .andReturn(createdOwner); - - expect(uriInfo.getAbsolutePathBuilder()) - .andReturn(uriBuilder); - expect(uriBuilder.path(newOwner.getLogin())) - .andReturn(uriBuilder); - expect(uriBuilder.build()) - .andReturn(mockUri); - - replayAll(); - - final Response response = resource.create(newOwner); - - assertThat(response, hasCreatedStatus()); - assertThat(response.getHeaderString("Location"), is(equalTo(mockUri.toString()))); - } - - @Test(expected = IllegalArgumentException.class) - public void testCreateNull() { - replayAll(); - - resource.create(null); - } - - @Test(expected = IllegalArgumentException.class) - public void testCreateExistentOwner() { - final Owner existentOwner = existentOwner(); - - expect(facade.create(existentOwner)) - .andThrow(new EntityExistsException()); - - replayAll(); - - resource.create(existentOwner); - } - - @Test - public void testUpdate() { - final Owner owner = anyOwner(); - - facade.update(owner); - - expectLastCall().andReturn(owner); - - replayAll(); - - final Response response = resource.update(owner); - - assertThat(response, hasOkStatus()); - } - - @Test(expected = IllegalArgumentException.class) - public void testUpdateNull() { - replayAll(); - - resource.update(null); - } - - @Test - public void testDelete() { - final String login = anyLogin(); - - facade.remove(login); - - replayAll(); - - final Response response = resource.delete(login); - - assertThat(response, hasOkStatus()); - } - - @Test(expected = IllegalArgumentException.class) - public void testDeleteNull() { - replayAll(); - - resource.delete(null); - } + @TestSubject + private OwnerResource resource = new OwnerResource(); + + @Mock + private OwnerService facade; + + @Mock + private UriInfo uriInfo; + + @Mock + private UriBuilder uriBuilder; + + @After + public void tearDown() throws Exception { + verifyAll(); + } + + @Test + public void testGet() { + final Owner owner = OwnersDataset.anyOwner(); + + expect(facade.get(owner.getLogin())) + .andReturn(owner); + + replayAll(); + + final Response response = resource.get(owner.getLogin()); + + assertThat(response, hasOkStatus()); + assertThat(response.getEntity(), is(instanceOf(Owner.class))); + assertThat((Owner) response.getEntity(), is(equalToOwner(owner))); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetNull() { + replayAll(); + + resource.get(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetMissing() { + final String login = anyLogin(); + + expect(facade.get(login)) + .andReturn(null); + + replayAll(); + + resource.get(login); + } + + @Test + @SuppressWarnings("unchecked") + public void testList() { + final Owner[] owners = owners(); + + expect(facade.list()) + .andReturn(asList(owners)); + + replayAll(); + + final Response response = resource.list(); + + assertThat(response, hasOkStatus()); + assertThat(response.getEntity(), is(instanceOf(List.class))); + assertThat((List) response.getEntity(), containsOwnersInAnyOrder(owners)); + } + + @Test + @SuppressWarnings("unchecked") + public void testListEmpty() { + expect(facade.list()) + .andReturn(emptyList()); + + replayAll(); + + final Response response = resource.list(); + + assertThat(response, hasOkStatus()); + assertThat(response.getEntity(), is(instanceOf(List.class))); + assertThat((List) response.getEntity(), is(empty())); + } + + @Test + public void testCreate() throws Exception { + final OwnerCreationData newOwner = new OwnerCreationData(newOwnerLogin(), newOwnerPassword()); + final Owner createdOwner = OwnersDataset.newOwnerWithoutPets(); + + final URI mockUri = new URI("http://host/api/owner/" + newOwner.getLogin()); + + expect(facade.create(anyObject(Owner.class))) + .andReturn(createdOwner); + + expect(uriInfo.getAbsolutePathBuilder()) + .andReturn(uriBuilder); + expect(uriBuilder.path(newOwner.getLogin())) + .andReturn(uriBuilder); + expect(uriBuilder.build()) + .andReturn(mockUri); + + replayAll(); + + final Response response = resource.create(newOwner); + + assertThat(response, hasCreatedStatus()); + assertThat(response.getHeaderString("Location"), is(equalTo(mockUri.toString()))); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateNull() { + replayAll(); + + resource.create(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateExistentOwner() { + final OwnerCreationData existentOwner = new OwnerCreationData(existentLogin(), existentPassword()); + + expect(facade.create(anyObject(Owner.class))) + .andThrow(new EntityExistsException()); + + replayAll(); + + resource.create(existentOwner); + } + + @Test + public void testUpdate() { + final Owner owner = existentOwner(); + final Owner ownerWithChangedPassword = existentOwner(); + ownerWithChangedPassword.changePassword(newPasswordForExistentOwner()); + + final OwnerEditionData ownerData = new OwnerEditionData(newPasswordForExistentOwner()); + + expect(facade.get(owner.getLogin())) + .andReturn(owner); + + expect(facade.update(anyObject(Owner.class))) + .andReturn(owner); + + replayAll(); + + final Response response = resource.update(owner.getLogin(), ownerData); + + assertThat(response, hasOkStatus()); + } + + @Test(expected = IllegalArgumentException.class) + public void testUpdateNull() { + replayAll(); + + resource.update(null, null); + } + + @Test + public void testDelete() { + final String login = anyLogin(); + + facade.remove(login); + + replayAll(); + + final Response response = resource.delete(login); + + assertThat(response, hasOkStatus()); + } + + @Test(expected = IllegalArgumentException.class) + public void testDeleteNull() { + replayAll(); + + resource.delete(null); + } } diff --git a/service/src/main/java/es/uvigo/esei/xcs/service/UserService.java b/service/src/main/java/es/uvigo/esei/xcs/service/UserService.java new file mode 100644 index 0000000..d65592a --- /dev/null +++ b/service/src/main/java/es/uvigo/esei/xcs/service/UserService.java @@ -0,0 +1,30 @@ +package es.uvigo.esei.xcs.service; + +import java.security.Principal; + +import javax.annotation.security.RolesAllowed; +import javax.ejb.Stateless; +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import es.uvigo.esei.xcs.domain.entities.User; + +@Stateless +@RolesAllowed({"OWNER", "ADMIN"}) +public class UserService { + @PersistenceContext + private EntityManager em; + + @Inject + private Principal principal; + + /** + * Returns the current user entity. + * + * @return the entity with the information of the current user. + */ + public User getCurrentUser() { + return this.em.find(User.class, this.principal.getName()); + } +} diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIntegrationTest.java b/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIntegrationTest.java index d1ba538..45707e8 100644 --- a/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIntegrationTest.java +++ b/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIntegrationTest.java @@ -63,8 +63,8 @@ public class PetServiceIntegrationTest { .addPackage(Pet.class.getPackage()) .addAsResource("test-persistence.xml", "META-INF/persistence.xml") .addAsWebInfResource("jboss-web.xml") - .addAsResource("arquillian.extension.persistence.properties") - .addAsResource("arquillian.extension.persistence.dbunit.properties") + .addAsResource("arquillian.extension.persistence.properties") + .addAsResource("arquillian.extension.persistence.dbunit.properties") .addAsWebInfResource("beans.xml", "beans.xml"); } diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/ServiceIntegrationTestSuite.java b/service/src/test/java/es/uvigo/esei/xcs/service/ServiceIntegrationTestSuite.java index fe0cb61..d1ef4dd 100644 --- a/service/src/test/java/es/uvigo/esei/xcs/service/ServiceIntegrationTestSuite.java +++ b/service/src/test/java/es/uvigo/esei/xcs/service/ServiceIntegrationTestSuite.java @@ -9,7 +9,9 @@ import org.junit.runners.Suite.SuiteClasses; OwnerServiceIntegrationTest.class, OwnerServiceIllegalAccessIntegrationTest.class, PetServiceIntegrationTest.class, - PetServiceIllegalAccessIntegrationTest.class + PetServiceIllegalAccessIntegrationTest.class, + UserServiceIntegrationTest.class, + UserServiceIllegalAccessIntegrationTest.class }) public class ServiceIntegrationTestSuite { } diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/UserServiceIllegalAccessIntegrationTest.java b/service/src/test/java/es/uvigo/esei/xcs/service/UserServiceIllegalAccessIntegrationTest.java new file mode 100644 index 0000000..83bec3d --- /dev/null +++ b/service/src/test/java/es/uvigo/esei/xcs/service/UserServiceIllegalAccessIntegrationTest.java @@ -0,0 +1,85 @@ +package es.uvigo.esei.xcs.service; + +import static es.uvigo.esei.xcs.domain.entities.IsEqualToUser.equalToUser; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentOwner; +import static es.uvigo.esei.xcs.domain.entities.UsersDataset.existentAdmin; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import javax.ejb.EJB; +import javax.inject.Inject; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.persistence.CleanupUsingScript; +import org.jboss.arquillian.persistence.ShouldMatchDataSet; +import org.jboss.arquillian.persistence.UsingDataSet; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import es.uvigo.esei.xcs.domain.entities.Owner; +import es.uvigo.esei.xcs.domain.entities.OwnersDataset; +import es.uvigo.esei.xcs.domain.entities.Pet; +import es.uvigo.esei.xcs.domain.entities.User; +import es.uvigo.esei.xcs.domain.entities.UsersDataset; +import es.uvigo.esei.xcs.service.util.security.RoleCaller; +import es.uvigo.esei.xcs.service.util.security.TestPrincipal; + +@RunWith(Arquillian.class) +@UsingDataSet("owners.xml") +@CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) +public class UserServiceIllegalAccessIntegrationTest { + + @Inject + private UserService facade; + + @EJB(beanName = "owner-caller") + private RoleCaller asOwner; + + @EJB(beanName = "admin-caller") + private RoleCaller asAdmin; + + @Inject + private TestPrincipal principal; + + @Deployment + public static Archive createDeployment() { + return ShrinkWrap.create(WebArchive.class, "test.war") + .addClasses(UserService.class) + .addPackage(RoleCaller.class.getPackage()) + .addPackage(Pet.class.getPackage()) + .addAsResource("test-persistence.xml", "META-INF/persistence.xml") + .addAsWebInfResource("jboss-web.xml") + .addAsResource("arquillian.extension.persistence.properties") + .addAsResource("arquillian.extension.persistence.dbunit.properties") + .addAsWebInfResource("beans.xml", "beans.xml"); + } + + @Test + @ShouldMatchDataSet("owners.xml") + public void testGetOwnerCredentials() { + final Owner existentOwner = existentOwner(); + + principal.setName(existentOwner.getLogin()); + + final User actualUser = asOwner.call(() -> facade.getCurrentUser()); + + assertThat(actualUser, is(equalToUser(existentOwner))); + } + + @Test + @ShouldMatchDataSet("owners.xml") + public void testGetAdminCredentials() { + final User existentAdmin = existentAdmin(); + + principal.setName(existentAdmin.getLogin()); + + final User actualUser = asAdmin.call(() -> facade.getCurrentUser()); + + assertThat(actualUser, is(equalToUser(existentAdmin))); + } + +} diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/UserServiceIntegrationTest.java b/service/src/test/java/es/uvigo/esei/xcs/service/UserServiceIntegrationTest.java new file mode 100644 index 0000000..3db9c9c --- /dev/null +++ b/service/src/test/java/es/uvigo/esei/xcs/service/UserServiceIntegrationTest.java @@ -0,0 +1,46 @@ +package es.uvigo.esei.xcs.service; + +import javax.ejb.EJBAccessException; +import javax.inject.Inject; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.persistence.CleanupUsingScript; +import org.jboss.arquillian.persistence.ShouldMatchDataSet; +import org.jboss.arquillian.persistence.UsingDataSet; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import es.uvigo.esei.xcs.domain.entities.Pet; +import es.uvigo.esei.xcs.service.util.security.RoleCaller; + +@RunWith(Arquillian.class) +@UsingDataSet("owners.xml") +@CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) +public class UserServiceIntegrationTest { + + @Inject + private UserService facade; + + @Deployment + public static Archive createDeployment() { + return ShrinkWrap.create(WebArchive.class, "test.war") + .addClasses(UserService.class) + .addPackage(RoleCaller.class.getPackage()) + .addPackage(Pet.class.getPackage()) + .addAsResource("test-persistence.xml", "META-INF/persistence.xml") + .addAsWebInfResource("jboss-web.xml") + .addAsResource("arquillian.extension.persistence.properties") + .addAsResource("arquillian.extension.persistence.dbunit.properties") + .addAsWebInfResource("beans.xml", "beans.xml"); + } + + @Test(expected = EJBAccessException.class) + @ShouldMatchDataSet("owners.xml") + public void testGetCredentialsNoUser() { + facade.getCurrentUser(); + } +} diff --git a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToUser.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToUser.java new file mode 100644 index 0000000..7359d22 --- /dev/null +++ b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualToUser.java @@ -0,0 +1,38 @@ +package es.uvigo.esei.xcs.domain.entities; + +import org.hamcrest.Factory; +import org.hamcrest.Matcher; + +public class IsEqualToUser extends IsEqualToEntity { + public IsEqualToUser(User user) { + super(user); + } + + @Override + protected boolean matchesSafely(User actual) { + this.clearDescribeTo(); + + if (actual == null) { + this.addTemplatedDescription("actual", expected.toString()); + return false; + } else { + return checkAttribute("login", User::getLogin, actual) + && checkAttribute("role", User::getRole, actual); + } + } + + @Factory + public static IsEqualToUser equalToUser(User user) { + return new IsEqualToUser(user); + } + + @Factory + public static Matcher> containsUsersInAnyOrder(User ... users) { + return containsEntityInAnyOrder(IsEqualToUser::equalToUser, users); + } + + @Factory + public static Matcher> containsUsersInAnyOrder(Iterable users) { + return containsEntityInAnyOrder(IsEqualToUser::equalToUser, users); + } +} diff --git a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java index 337b250..560074e 100644 --- a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java +++ b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java @@ -34,9 +34,9 @@ public class OwnersDataset { public static Owner[] owners() { return new Owner[] { - new Owner(EXISTENT_LOGIN, "pepepass", + new Owner(EXISTENT_LOGIN, EXISTENT_LOGIN + "pass", new Pet(1, "Pepecat", AnimalType.CAT, new Date(946684861000L))), - new Owner(OWNER_WITH_PETS_LOGIN, "juanpass", + new Owner(OWNER_WITH_PETS_LOGIN, OWNER_WITH_PETS_LOGIN + "pass", new Pet(2, "Max", AnimalType.CAT, new Date(946684861000L)), new Pet(3, "Juandog", AnimalType.DOG, new Date(946684861000L)) ), @@ -45,7 +45,7 @@ public class OwnersDataset { new Pet(5, "Max", AnimalType.DOG, new Date(946684861000L)), new Pet(6, "Anabird", AnimalType.BIRD, new Date(946684861000L)) ), - new Owner(OWNER_WITHOUT_PETS_LOGIN, "lorenapass") + new Owner(OWNER_WITHOUT_PETS_LOGIN, OWNER_WITHOUT_PETS_LOGIN + "pass") }; } @@ -117,6 +117,22 @@ public class OwnersDataset { return new Owner(newOwnerLogin(), newOwnerPassword()); } + public static Owner newOwnerWithFreshPets() { + return new Owner(newOwnerLogin(), newOwnerPassword(), + new Pet("Jacintocat", AnimalType.CAT, new Date(946684861000L)), + new Pet("Jacintodo", AnimalType.DOG, new Date(946684861000L)), + new Pet("Jacintobird", AnimalType.BIRD, new Date(946684861000L)) + ); + } + + public static Owner newOwnerWithPersistentPets() { + return new Owner(newOwnerLogin(), newOwnerPassword(), + new Pet(7, "Jacintocat", AnimalType.CAT, new Date(946684861000L)), + new Pet(8, "Jacintodo", AnimalType.DOG, new Date(946684861000L)), + new Pet(9, "Jacintobird", AnimalType.BIRD, new Date(946684861000L)) + ); + } + public static String newOwnerLogin() { return "jacinto"; } @@ -125,22 +141,6 @@ public class OwnersDataset { return "jacintopass"; } - public static Owner newOwnerWithFreshPets() { - return new Owner(newOwnerLogin(), newOwnerPassword(), - new Pet("Jacintocat", AnimalType.CAT, new Date(946684861000L)), - new Pet("Jacintodo", AnimalType.DOG, new Date(946684861000L)), - new Pet("Jacintobird", AnimalType.BIRD, new Date(946684861000L)) - ); - } - - public static Owner newOwnerWithPersistentPets() { - return new Owner(newOwnerLogin(), newOwnerPassword(), - new Pet(7, "Jacintocat", AnimalType.CAT, new Date(946684861000L)), - new Pet(8, "Jacintodo", AnimalType.DOG, new Date(946684861000L)), - new Pet(9, "Jacintobird", AnimalType.BIRD, new Date(946684861000L)) - ); - } - public static String anyLogin() { return existentLogin(); } @@ -148,6 +148,10 @@ public class OwnersDataset { public static String existentLogin() { return EXISTENT_LOGIN; } + + public static String existentPassword() { + return EXISTENT_LOGIN + "pass"; + } public static String nonExistentLogin() { return NON_EXISTENT_LOGIN; @@ -156,6 +160,10 @@ public class OwnersDataset { public static Owner anyOwner() { return ownerWithLogin(anyLogin()); } + + public static String anyOwnerPassword() { + return anyOwner().getLogin() + "pass"; + } public static Owner existentOwner() { return ownerWithLogin(existentLogin()); diff --git a/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/UsersDataset.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/UsersDataset.java new file mode 100644 index 0000000..e1c3ac7 --- /dev/null +++ b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/UsersDataset.java @@ -0,0 +1,19 @@ +package es.uvigo.esei.xcs.domain.entities; + +public class UsersDataset { + public static final String EXISTENT_LOGIN = "jose"; + + public static User[] users() { + final Owner[] owners = OwnersDataset.owners(); + final User[] users = new User[owners.length + 1]; + + users[0] = new Administrator(EXISTENT_LOGIN, EXISTENT_LOGIN + "pass"); + System.arraycopy(owners, 0, users, 1, owners.length); + + return users; + } + + public static User existentAdmin() { + return users()[0]; + } +} -- 2.18.1