From 053ddd0f40bf579d919f9aba516d007b8ed92d15 Mon Sep 17 00:00:00 2001 From: Miguel Reboiro-Jato Date: Tue, 19 Apr 2016 19:29:10 +0200 Subject: [PATCH] Adds support for retrieving the data of an user This commit adds the new resource UsersResource (/users) with a simple functionality: retrieving the data of an user. This functionality requires knowing the login of the user that is performing the request. In this regard, this commit is an example of how this information can be retrieved and how to test a resource that requires knowing the login of an user. --- db/mysql-with-inserts.sql | 4 +- .../uvigo/esei/daa/DAAExampleApplication.java | 8 +- .../java/es/uvigo/esei/daa/LoginFilter.java | 66 ++++--- .../java/es/uvigo/esei/daa/dao/UsersDAO.java | 60 +++++-- .../java/es/uvigo/esei/daa/entities/User.java | 68 ++++++++ .../es/uvigo/esei/daa/rest/UsersResource.java | 98 +++++++++++ .../uvigo/esei/daa/dataset/UsersDataset.java | 38 +++++ .../esei/daa/matchers/HasHttpStatus.java | 10 ++ .../esei/daa/matchers/IsEqualToUser.java | 56 ++++++ .../esei/daa/rest/UsersResourceTest.java | 161 ++++++++++++++++++ .../esei/daa/suites/IntegrationTestSuite.java | 4 +- src/test/resources/datasets/dataset-add.xml | 3 +- .../resources/datasets/dataset-delete.xml | 3 +- .../resources/datasets/dataset-modify.xml | 3 +- src/test/resources/datasets/dataset.xml | 3 +- 15 files changed, 539 insertions(+), 46 deletions(-) create mode 100644 src/main/java/es/uvigo/esei/daa/entities/User.java create mode 100644 src/main/java/es/uvigo/esei/daa/rest/UsersResource.java create mode 100644 src/test/java/es/uvigo/esei/daa/dataset/UsersDataset.java create mode 100644 src/test/java/es/uvigo/esei/daa/matchers/IsEqualToUser.java create mode 100644 src/test/java/es/uvigo/esei/daa/rest/UsersResourceTest.java diff --git a/db/mysql-with-inserts.sql b/db/mysql-with-inserts.sql index 088d807..9f4e773 100644 --- a/db/mysql-with-inserts.sql +++ b/db/mysql-with-inserts.sql @@ -24,4 +24,6 @@ INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'María','Nu INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'Alba','Fernández'); INSERT INTO `daaexample`.`people` (`id`,`name`,`surname`) VALUES (0,'Asunción','Jiménez'); -INSERT INTO `daaexample`.`users` (`login`,`password`) VALUES ('admin', '0b893644f3b2097d004c58d585e784ac92dd1356d25158a298573ad54ab2d15d'); +-- The password for each user is its login suffixed with "pass". For example, user "admin" has the password "adminpass". +INSERT INTO `daaexample`.`users` (`login`,`password`) VALUES ('admin', '43f413b773f7d0cfad0e8e6529ec1249ce71e8697919eab30d82d800a3986b70'); +INSERT INTO `daaexample`.`users` (`login`,`password`) VALUES ('normal', '688f21dd2d65970f174e2c9d35159250a8a23e27585452683db8c5d10b586336'); diff --git a/src/main/java/es/uvigo/esei/daa/DAAExampleApplication.java b/src/main/java/es/uvigo/esei/daa/DAAExampleApplication.java index 9ee0e9e..1857d92 100644 --- a/src/main/java/es/uvigo/esei/daa/DAAExampleApplication.java +++ b/src/main/java/es/uvigo/esei/daa/DAAExampleApplication.java @@ -1,15 +1,17 @@ package es.uvigo.esei.daa; +import static java.util.stream.Collectors.toSet; + import java.util.Collections; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import java.util.stream.Stream; import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; import es.uvigo.esei.daa.rest.PeopleResource; +import es.uvigo.esei.daa.rest.UsersResource; /** * Configuration of the REST application. This class includes the resources and @@ -22,8 +24,8 @@ import es.uvigo.esei.daa.rest.PeopleResource; public class DAAExampleApplication extends Application { @Override public Set> getClasses() { - return Stream.of(PeopleResource.class) - .collect(Collectors.toSet()); + return Stream.of(PeopleResource.class, UsersResource.class) + .collect(toSet()); } @Override diff --git a/src/main/java/es/uvigo/esei/daa/LoginFilter.java b/src/main/java/es/uvigo/esei/daa/LoginFilter.java index b62919b..6dd8ad2 100644 --- a/src/main/java/es/uvigo/esei/daa/LoginFilter.java +++ b/src/main/java/es/uvigo/esei/daa/LoginFilter.java @@ -30,11 +30,13 @@ import es.uvigo.esei.daa.dao.UsersDAO; * @author Miguel Reboiro Jato * */ -@WebFilter(urlPatterns = { "/*", "/logout" }) +@WebFilter(urlPatterns = "/*") public class LoginFilter implements Filter { - private static final String REST_PATH = "/rest"; - private static final String INDEX_PATH = "/index.html"; private static final String LOGOUT_PATH = "/logout"; + private static final String REST_PATH = "/rest"; + private static final String[] PUBLIC_PATHS = new String[] { + "/index.html" // Add the paths that can be publicly accessed (e.g. /js, /css...) + }; @Override public void doFilter( @@ -48,15 +50,15 @@ public class LoginFilter implements Filter { try { if (isLogoutPath(httpRequest)) { destroySession(httpRequest); - removeTokenCookie(httpResponse); + removeTokenCookie(httpRequest, httpResponse); redirectToIndex(httpRequest, httpResponse); - } else if (isIndexPath(httpRequest) || checkToken(httpRequest)) { + } else if (isPublicPath(httpRequest) || checkToken(httpRequest)) { chain.doFilter(request, response); } else if (checkLogin(httpRequest, httpResponse)) { continueWithRedirect(httpRequest, httpResponse); } else if (isRestPath(httpRequest)) { destroySession(httpRequest); - httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN); + httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN); } else { destroySession(httpRequest); redirectToIndex(httpRequest, httpResponse); @@ -80,8 +82,13 @@ public class LoginFilter implements Filter { return request.getServletPath().equals(LOGOUT_PATH); } - private boolean isIndexPath(HttpServletRequest request) { - return request.getServletPath().equals(INDEX_PATH); + private boolean isPublicPath(HttpServletRequest request) { + for (String path : PUBLIC_PATHS) { + if (request.getServletPath().startsWith(path)) + return true; + } + + return false; } private boolean isRestPath(HttpServletRequest request) { @@ -106,10 +113,15 @@ public class LoginFilter implements Filter { response.sendRedirect(redirectPath); } - private void removeTokenCookie(HttpServletResponse response) { - final Cookie cookie = new Cookie("token", ""); - cookie.setMaxAge(0); - response.addCookie(cookie); + private void removeTokenCookie( + HttpServletRequest request, + HttpServletResponse response + ) { + final Cookie cookie = getTokenCookie(request); + if (cookie != null) { + cookie.setMaxAge(0); + response.addCookie(cookie); + } } private void destroySession(HttpServletRequest request) { @@ -125,6 +137,7 @@ public class LoginFilter implements Filter { if (login != null && password != null) { final UsersDAO dao = new UsersDAO(); + if (dao.checkLogin(login, password)) { final Credentials credentials = new Credentials(login, password); @@ -140,18 +153,33 @@ public class LoginFilter implements Filter { } } - private boolean checkToken(HttpServletRequest request) - throws DAOException, IllegalArgumentException { + private Cookie getTokenCookie(HttpServletRequest request) { final Cookie[] cookies = Optional.ofNullable(request.getCookies()) .orElse(new Cookie[0]); for (Cookie cookie : cookies) { if ("token".equals(cookie.getName())) { - final Credentials credentials = new Credentials(cookie.getValue()); - - final UsersDAO dao = new UsersDAO(); - - return dao.checkLogin(credentials.getLogin(), credentials.getPassword()); + return cookie; + } + } + + return null; + } + + private boolean checkToken(HttpServletRequest request) + throws DAOException, IllegalArgumentException { + final Cookie cookie = getTokenCookie(request); + + if (cookie != null) { + final Credentials credentials = new Credentials(cookie.getValue()); + + final UsersDAO dao = new UsersDAO(); + + if (dao.checkLogin(credentials.getLogin(), credentials.getPassword())) { + request.getSession().setAttribute("login", credentials.getLogin()); + return true; + } else { + return false; } } diff --git a/src/main/java/es/uvigo/esei/daa/dao/UsersDAO.java b/src/main/java/es/uvigo/esei/daa/dao/UsersDAO.java index 61ea846..8c17b7e 100644 --- a/src/main/java/es/uvigo/esei/daa/dao/UsersDAO.java +++ b/src/main/java/es/uvigo/esei/daa/dao/UsersDAO.java @@ -9,6 +9,8 @@ import java.sql.SQLException; import java.util.logging.Level; import java.util.logging.Logger; +import es.uvigo.esei.daa.entities.User; + /** * DAO class for managing the users of the system. * @@ -18,35 +20,28 @@ public class UsersDAO extends DAO { private final static Logger LOG = Logger.getLogger(UsersDAO.class.getName()); private final static String SALT = "daaexample-"; - + /** - * Checks if the provided credentials (login and password) correspond with a - * valid user registered in the system. + * Returns a user stored persisted in the system. * - *

The password is stored in the system "salted" and encoded with the - * SHA-256 algorithm.

- * - * @param login the login of the user. - * @param password the password of the user. - * @return {@code true} if the credentials are valid. {@code false} - * otherwise. - * @throws DAOException if an error happens while checking the credentials. + * @param login the login of the user to be retrieved. + * @return a user with the provided login. + * @throws DAOException if an error happens while retrieving the user. + * @throws IllegalArgumentException if the provided login does not + * corresponds with any persisted user. */ - public boolean checkLogin(String login, String password) throws DAOException { + public User get(String login) throws DAOException { try (final Connection conn = this.getConnection()) { - final String query = "SELECT password FROM users WHERE login=?"; + final String query = "SELECT * FROM users WHERE login=?"; try (final PreparedStatement statement = conn.prepareStatement(query)) { statement.setString(1, login); try (final ResultSet result = statement.executeQuery()) { if (result.next()) { - final String dbPassword = result.getString("password"); - final String shaPassword = encodeSha256(SALT + password); - - return shaPassword.equals(dbPassword); + return rowToEntity(result); } else { - return false; + throw new IllegalArgumentException("Invalid id"); } } } @@ -55,6 +50,28 @@ public class UsersDAO extends DAO { throw new DAOException(e); } } + + /** + * Checks if the provided credentials (login and password) correspond with a + * valid user registered in the system. + * + *

The password is stored in the system "salted" and encoded with the + * SHA-256 algorithm.

+ * + * @param login the login of the user. + * @param password the password of the user. + * @return {@code true} if the credentials are valid. {@code false} + * otherwise. + * @throws DAOException if an error happens while checking the credentials. + */ + public boolean checkLogin(String login, String password) throws DAOException { + final User user = this.get(login); + + final String dbPassword = user.getPassword(); + final String shaPassword = encodeSha256(SALT + password); + + return shaPassword.equals(dbPassword); + } private final static String encodeSha256(String text) { try { @@ -77,4 +94,11 @@ public class UsersDAO extends DAO { return sb.toString(); } + + private User rowToEntity(ResultSet result) throws SQLException { + return new User( + result.getString("login"), + result.getString("password") + ); + } } diff --git a/src/main/java/es/uvigo/esei/daa/entities/User.java b/src/main/java/es/uvigo/esei/daa/entities/User.java new file mode 100644 index 0000000..ade776c --- /dev/null +++ b/src/main/java/es/uvigo/esei/daa/entities/User.java @@ -0,0 +1,68 @@ +package es.uvigo.esei.daa.entities; + +import static java.util.Objects.requireNonNull; + +/** + * An entity that represents a user. + * + * @author Miguel Reboiro Jato + */ +public class User { + private String login; + private String password; + + // Constructor needed for the JSON conversion + User() {} + + /** + * Constructs a new instance of {@link User}. + * + * @param login login that identifies the user in the system. + * @param password password of the user encoded using SHA-256 and with the + * "salt" prefix added. + */ + public User(String login, String password) { + this.setLogin(login); + this.setPassword(password); + } + + /** + * Returns the login of the user. + * + * @return the login of the user. + */ + public String getLogin() { + return login; + } + + /** + * Sets the login of the user. + * + * @param login the login that identifies the user in the system. + */ + public void setLogin(String login) { + this.login = requireNonNull(login, "Login can't be null"); + } + + /** + * Returns the password of the user. + * + * @return the password of the user. + */ + public String getPassword() { + return password; + } + + /** + * Sets the users password. + * @param password the password of the user encoded using SHA-256 and with + * the "salt" prefix added. + */ + public void setPassword(String password) { + requireNonNull(password, "Password can't be null"); + if (!password.matches("[a-zA-Z0-9]{64}")) + throw new IllegalArgumentException("Password must be a valid SHA-256"); + + this.password = password; + } +} diff --git a/src/main/java/es/uvigo/esei/daa/rest/UsersResource.java b/src/main/java/es/uvigo/esei/daa/rest/UsersResource.java new file mode 100644 index 0000000..7693f5b --- /dev/null +++ b/src/main/java/es/uvigo/esei/daa/rest/UsersResource.java @@ -0,0 +1,98 @@ +package es.uvigo.esei.daa.rest; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import es.uvigo.esei.daa.dao.DAOException; +import es.uvigo.esei.daa.dao.UsersDAO; +/** + * REST resource for managing users. + * + * @author Miguel Reboiro Jato. + */ +@Path("/users") +@Produces(MediaType.APPLICATION_JSON) +public class UsersResource { + private final static Logger LOG = Logger.getLogger(UsersResource.class.getName()); + + private final UsersDAO dao; + + // The HttpServletRequest can be also injected as a parameter in the REST + // methods. + private @Context HttpServletRequest request; + + /** + * Constructs a new instance of {@link UsersResource}. + */ + public UsersResource() { + this(new UsersDAO()); + } + + // Needed for testing purposes + UsersResource(UsersDAO dao) { + this(dao, null); + } + + // Needed for testing purposes + UsersResource(UsersDAO dao, HttpServletRequest request) { + this.dao = dao; + this.request = request; + } + + /** + * Returns a user with the provided login. + * + * @param login the identifier of the user to retrieve. + * @return a 200 OK response with an user that has the provided login. + * If the request is done without providing the login credentials or using + * invalid credentials a 401 Unauthorized response will be returned. If the + * credentials are provided and a regular user (i.e. non admin user) tries + * to access the data of other user, a 403 Forbidden response will be + * returned. If the credentials are OK, but the login does not corresponds + * with any user, a 400 Bad Request response with an error message will be + * returned. If an error happens while retrieving the list, a 500 Internal + * Server Error response with an error message will be returned. + */ + @GET + @Path("/{login}") + public Response get( + @PathParam("login") String login + ) { + final String loggedUser = getLogin(); + + // Each user can only access his or her own data. Only the admin user + // can access the data of any user. + if (loggedUser.equals(login) || loggedUser.equals("admin")) { + try { + return Response.ok(dao.get(login)).build(); + } catch (IllegalArgumentException iae) { + LOG.log(Level.FINE, "Invalid user login in get method", iae); + + return Response.status(Response.Status.BAD_REQUEST) + .entity(iae.getMessage()) + .build(); + } catch (DAOException e) { + LOG.log(Level.SEVERE, "Error getting an user", e); + + return Response.serverError() + .entity(e.getMessage()) + .build(); + } + } else { + return Response.status(Response.Status.UNAUTHORIZED).build(); + } + } + + private String getLogin() { + return (String) request.getSession().getAttribute("login"); + } +} diff --git a/src/test/java/es/uvigo/esei/daa/dataset/UsersDataset.java b/src/test/java/es/uvigo/esei/daa/dataset/UsersDataset.java new file mode 100644 index 0000000..44082c7 --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/dataset/UsersDataset.java @@ -0,0 +1,38 @@ +package es.uvigo.esei.daa.dataset; + +import java.util.Arrays; +import java.util.Base64; + +import es.uvigo.esei.daa.entities.User; + +public final class UsersDataset { + private UsersDataset() {} + + public static User[] users() { + return new User[] { + new User(adminLogin(), "43f413b773f7d0cfad0e8e6529ec1249ce71e8697919eab30d82d800a3986b70"), + new User(normalLogin(), "688f21dd2d65970f174e2c9d35159250a8a23e27585452683db8c5d10b586336") + }; + } + + public static User user(String login) { + return Arrays.stream(users()) + .filter(user -> user.getLogin().equals(login)) + .findAny() + .orElseThrow(IllegalArgumentException::new); + } + + public static String adminLogin() { + return "admin"; + } + + public static String normalLogin() { + return "normal"; + } + + public static String userToken(String login) { + final String chain = login + ":" + login + "pass"; + + return Base64.getEncoder().encodeToString(chain.getBytes()); + } +} diff --git a/src/test/java/es/uvigo/esei/daa/matchers/HasHttpStatus.java b/src/test/java/es/uvigo/esei/daa/matchers/HasHttpStatus.java index 03bc3e3..e5e7111 100644 --- a/src/test/java/es/uvigo/esei/daa/matchers/HasHttpStatus.java +++ b/src/test/java/es/uvigo/esei/daa/matchers/HasHttpStatus.java @@ -77,4 +77,14 @@ public class HasHttpStatus extends TypeSafeMatcher { public static Matcher hasInternalServerErrorStatus() { return new HasHttpStatus(Response.Status.INTERNAL_SERVER_ERROR); } + + @Factory + public static Matcher hasUnauthorized() { + return new HasHttpStatus(Response.Status.UNAUTHORIZED); + } + + @Factory + public static Matcher hasForbidden() { + return new HasHttpStatus(Response.Status.FORBIDDEN); + } } diff --git a/src/test/java/es/uvigo/esei/daa/matchers/IsEqualToUser.java b/src/test/java/es/uvigo/esei/daa/matchers/IsEqualToUser.java new file mode 100644 index 0000000..689674e --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/matchers/IsEqualToUser.java @@ -0,0 +1,56 @@ +package es.uvigo.esei.daa.matchers; + +import org.hamcrest.Factory; +import org.hamcrest.Matcher; + +import es.uvigo.esei.daa.entities.Person; +import es.uvigo.esei.daa.entities.User; + +public class IsEqualToUser extends IsEqualToEntity { + public IsEqualToUser(User entity) { + super(entity); + } + + @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("password", User::getPassword, actual); + } + } + + /** + * Factory method that creates a new {@link IsEqualToEntity} matcher with + * the provided {@link Person} as the expected value. + * + * @param user the expected person. + * @return a new {@link IsEqualToEntity} matcher with the provided + * {@link Person} as the expected value. + */ + @Factory + public static IsEqualToUser equalsToUser(User user) { + return new IsEqualToUser(user); + } + + /** + * Factory method that returns a new {@link Matcher} that includes several + * {@link IsEqualToUser} matchers, each one using an {@link Person} of the + * provided ones as the expected value. + * + * @param users the persons to be used as the expected values. + * @return a new {@link Matcher} that includes several + * {@link IsEqualToUser} matchers, each one using an {@link Person} of the + * provided ones as the expected value. + * @see IsEqualToEntity#containsEntityInAnyOrder(java.util.function.Function, Object...) + */ + @Factory + public static Matcher> containsPeopleInAnyOrder(User ... users) { + return containsEntityInAnyOrder(IsEqualToUser::equalsToUser, users); + } + +} diff --git a/src/test/java/es/uvigo/esei/daa/rest/UsersResourceTest.java b/src/test/java/es/uvigo/esei/daa/rest/UsersResourceTest.java new file mode 100644 index 0000000..042faec --- /dev/null +++ b/src/test/java/es/uvigo/esei/daa/rest/UsersResourceTest.java @@ -0,0 +1,161 @@ +package es.uvigo.esei.daa.rest; + +import static es.uvigo.esei.daa.dataset.UsersDataset.adminLogin; +import static es.uvigo.esei.daa.dataset.UsersDataset.normalLogin; +import static es.uvigo.esei.daa.dataset.UsersDataset.user; +import static es.uvigo.esei.daa.dataset.UsersDataset.userToken; +import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasForbidden; +import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasOkStatus; +import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasUnauthorized; +import static es.uvigo.esei.daa.matchers.IsEqualToUser.equalsToUser; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.io.IOException; + +import javax.sql.DataSource; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Response; + +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.servlet.ServletContainer; +import org.glassfish.jersey.test.DeploymentContext; +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.test.ServletDeploymentContext; +import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory; +import org.glassfish.jersey.test.spi.TestContainerFactory; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; +import com.github.springtestdbunit.DbUnitTestExecutionListener; +import com.github.springtestdbunit.annotation.DatabaseSetup; +import com.github.springtestdbunit.annotation.ExpectedDatabase; + +import es.uvigo.esei.daa.DAAExampleApplication; +import es.uvigo.esei.daa.LoginFilter; +import es.uvigo.esei.daa.entities.User; +import es.uvigo.esei.daa.listeners.ApplicationContextBinding; +import es.uvigo.esei.daa.listeners.ApplicationContextJndiBindingTestExecutionListener; +import es.uvigo.esei.daa.listeners.DbManagement; +import es.uvigo.esei.daa.listeners.DbManagementTestExecutionListener; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:contexts/mem-context.xml") +@TestExecutionListeners({ + DbUnitTestExecutionListener.class, + DbManagementTestExecutionListener.class, + ApplicationContextJndiBindingTestExecutionListener.class +}) +@ApplicationContextBinding( + jndiUrl = "java:/comp/env/jdbc/daaexample", + type = DataSource.class +) +@DbManagement( + create = "classpath:db/hsqldb.sql", + drop = "classpath:db/hsqldb-drop.sql" +) +@DatabaseSetup("/datasets/dataset.xml") +@ExpectedDatabase("/datasets/dataset.xml") +public class UsersResourceTest extends JerseyTest { + @Override + protected Application configure() { + return new DAAExampleApplication(); + } + + @Override + protected void configureClient(ClientConfig config) { + super.configureClient(config); + + // Enables JSON transformation in client + config.register(JacksonJsonProvider.class); + config.property("com.sun.jersey.api.json.POJOMappingFeature", Boolean.TRUE); + } + + @Override + protected TestContainerFactory getTestContainerFactory() { + return new GrizzlyWebTestContainerFactory(); + } + + @Override + protected DeploymentContext configureDeployment() { + return ServletDeploymentContext.forServlet( + new ServletContainer(ResourceConfig.forApplication(configure())) + ) + .servletPath("/rest") + .addFilter(LoginFilter.class, "login-filter") + .build(); + } + + @Test + public void testGetAdminOwnUser() throws IOException { + final String admin = adminLogin(); + + final Response response = target("users/" + admin).request() + .cookie("token", userToken(admin)) + .get(); + assertThat(response, hasOkStatus()); + + final User user = response.readEntity(User.class); + + assertThat(user, is(equalsToUser(user(admin)))); + } + + @Test + public void testGetAdminOtherUser() throws IOException { + final String admin = adminLogin(); + final String otherUser = normalLogin(); + + final Response response = target("users/" + otherUser).request() + .cookie("token", userToken(admin)) + .get(); + assertThat(response, hasOkStatus()); + + final User user = response.readEntity(User.class); + + assertThat(user, is(equalsToUser(user(otherUser)))); + } + + @Test + public void testGetNormalOwnUser() throws IOException { + final String login = normalLogin(); + + final Response response = target("users/" + login).request() + .cookie("token", userToken(login)) + .get(); + assertThat(response, hasOkStatus()); + + final User user = response.readEntity(User.class); + + assertThat(user, is(equalsToUser(user(login)))); + } + + @Test + public void testGetNoCredentials() throws IOException { + final Response response = target("users/" + normalLogin()).request().get(); + + assertThat(response, hasForbidden()); + } + + @Test + public void testGetBadCredentials() throws IOException { + final Response response = target("users/" + adminLogin()).request() + .cookie("token", "YmFkOmNyZWRlbnRpYWxz") + .get(); + + assertThat(response, hasForbidden()); + } + + @Test + public void testGetIllegalAccess() throws IOException { + final Response response = target("users/" + adminLogin()).request() + .cookie("token", userToken(normalLogin())) + .get(); + + assertThat(response, hasUnauthorized()); + } +} diff --git a/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java b/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java index 35ad0bf..822c83f 100644 --- a/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java +++ b/src/test/java/es/uvigo/esei/daa/suites/IntegrationTestSuite.java @@ -6,10 +6,12 @@ import org.junit.runners.Suite.SuiteClasses; import es.uvigo.esei.daa.dao.PeopleDAOTest; import es.uvigo.esei.daa.rest.PeopleResourceTest; +import es.uvigo.esei.daa.rest.UsersResourceTest; @SuiteClasses({ PeopleDAOTest.class, - PeopleResourceTest.class + PeopleResourceTest.class, + UsersResourceTest.class }) @RunWith(Suite.class) public class IntegrationTestSuite { diff --git a/src/test/resources/datasets/dataset-add.xml b/src/test/resources/datasets/dataset-add.xml index 7ec50ae..832a4a1 100644 --- a/src/test/resources/datasets/dataset-add.xml +++ b/src/test/resources/datasets/dataset-add.xml @@ -14,5 +14,6 @@ - + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset-delete.xml b/src/test/resources/datasets/dataset-delete.xml index 51b0b21..7480a41 100644 --- a/src/test/resources/datasets/dataset-delete.xml +++ b/src/test/resources/datasets/dataset-delete.xml @@ -12,5 +12,6 @@ - + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset-modify.xml b/src/test/resources/datasets/dataset-modify.xml index 8b0811f..f840fb5 100644 --- a/src/test/resources/datasets/dataset-modify.xml +++ b/src/test/resources/datasets/dataset-modify.xml @@ -13,5 +13,6 @@ - + + \ No newline at end of file diff --git a/src/test/resources/datasets/dataset.xml b/src/test/resources/datasets/dataset.xml index 9aed589..2a7eff1 100644 --- a/src/test/resources/datasets/dataset.xml +++ b/src/test/resources/datasets/dataset.xml @@ -13,5 +13,6 @@ - + + \ No newline at end of file -- 2.18.1