package com.sixsq.slipstream.user; /* * +=================================================================+ * SlipStream Server (WAR) * ===== * Copyright (C) 2013 SixSq Sarl (sixsq.com) * ===== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * -=================================================================- */ import com.sixsq.slipstream.connector.ExecutionControlUserParametersFactory; import com.sixsq.slipstream.connector.local.LocalConnector; import com.sixsq.slipstream.cookie.CookieUtils; import com.sixsq.slipstream.exceptions.ConfigurationException; import com.sixsq.slipstream.exceptions.SlipStreamClientException; import com.sixsq.slipstream.exceptions.ValidationException; import com.sixsq.slipstream.persistence.User; import com.sixsq.slipstream.persistence.User.State; import com.sixsq.slipstream.persistence.UserParameter; import com.sixsq.slipstream.persistence.UserTest; import com.sixsq.slipstream.util.ResourceTestBase; import com.sixsq.slipstream.util.SerializationUtil; import com.sixsq.slipstream.util.XmlUtil; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.restlet.Request; import org.restlet.Response; import org.restlet.data.Form; import org.restlet.data.Status; import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.security.NoSuchAlgorithmException; import java.util.Map; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; public class UserResourceTest extends ResourceTestBase { private static final String NEW_PASSWORD = "newPassword"; private static final String SUPER_PASSWORD = "passwordSuper"; private static User otherUser = UserTest.createUser("test2", "password2"); private static User superUser = UserTest .createUser("super", SUPER_PASSWORD); private static User user = null; @BeforeClass public static void setupBeforeClass() throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { resetAndLoadConnector(LocalConnector.class); } @Before public void setup() { user = UserTest.createUser("test"); user = UserTest.storeUser(user); UserTest.storeUser(otherUser); superUser.setSuper(true); superUser = UserTest.storeUser(superUser); } @After public void tearDown() throws ConfigurationException, ValidationException { user.remove(); otherUser.remove(); superUser.remove(); } @Test public void getUser() throws ConfigurationException, ValidationException { Request request = createGetRequest(user); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); } @Test public void normalUserCantAccessOthers() throws ConfigurationException, ValidationException { Request request = createGetRequest(user, otherUser.getName()); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.CLIENT_ERROR_FORBIDDEN)); } @Test public void getUserAsSuperUser() throws ConfigurationException, ValidationException { Request request = createGetRequest(superUser, otherUser.getName()); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); } @Test public void getInexistantUser() throws ConfigurationException, ValidationException { Request request = createGetRequest(user, "inexistant"); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.CLIENT_ERROR_NOT_FOUND)); } @Test public void changePasswordValidAsSuper() throws ConfigurationException, NoSuchAlgorithmException, UnsupportedEncodingException, ValidationException { user = user.store(); user.hashAndSetPassword("something old"); user = user.store(); assertThat(getPersistedPassword(user), is(not(Passwords.hash(NEW_PASSWORD)))); Passwords passwords = createValidPasswords(UserTest.PASSWORD); Request request = createPutRequest(user, superUser.getName(), passwords); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); User modifiedUser = User.load(user.getResourceUri()); assertThat(getPersistedPassword(modifiedUser), is(Passwords.hash(NEW_PASSWORD))); } @Test public void changePasswordValidAsItself() throws ConfigurationException, NoSuchAlgorithmException, UnsupportedEncodingException, ValidationException { user = user.store(); String oldPassword = "something old"; user.hashAndSetPassword(oldPassword); user = user.store(); assertThat(getPersistedPassword(user), is(not(NEW_PASSWORD))); Passwords passwords = createValidPasswords(oldPassword); Request request = createPutRequest(user, user.getName(), passwords); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); User modifiedUser = User.load(user.getResourceUri()); assertThat(getPersistedPassword(modifiedUser), is(Passwords.hash(NEW_PASSWORD))); } @Test public void cannotChangePasswordOfOtherUser() throws ConfigurationException, NoSuchAlgorithmException, UnsupportedEncodingException, ValidationException { String oldPassword = "old password"; user.hashAndSetPassword(oldPassword); user = (User) user.store(); assertThat(getPersistedPassword(user), is(not(NEW_PASSWORD))); Passwords passwords = createValidPasswords(oldPassword); Request request = createPutRequest(user, otherUser.getName(), passwords); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.CLIENT_ERROR_FORBIDDEN)); } @Test public void changePasswordMissingOldPassword() throws ConfigurationException, NoSuchAlgorithmException, UnsupportedEncodingException, ValidationException { Passwords passwords = createValidPasswords(UserTest.PASSWORD); passwords.oldPassword = null; Request request = createPutRequest(user, user.getName(), passwords); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.CLIENT_ERROR_CONFLICT)); } @Test public void superCanChangeOthersPasswordWithoutOldPassword() throws ConfigurationException, ValidationException, NoSuchAlgorithmException, UnsupportedEncodingException { user.hashAndSetPassword(UserTest.PASSWORD); Passwords passwords = createValidPasswords(UserTest.PASSWORD); passwords.oldPassword = null; Request request = createPutRequest(user, superUser.getName(), passwords); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); user = User.load(user.getResourceUri()); assertThat(user.getHashedPassword(), is(Passwords.hash(NEW_PASSWORD))); } @Test public void superMustProvideItsOwnOldPassowrdToChangeItsPassword() throws ConfigurationException, ValidationException, NoSuchAlgorithmException, UnsupportedEncodingException { Passwords passwords = createValidPasswords(SUPER_PASSWORD); passwords.oldPassword = null; Request request = createPutRequest(superUser, superUser.getName(), passwords); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.CLIENT_ERROR_CONFLICT)); } @Test public void passwordBlankedForNormalUser() throws SlipStreamClientException { Request request = createGetRequest(user, user.getName()); Response response = executeRequest(request); User user = (User) SerializationUtil.fromXml( response.getEntityAsText(), User.class); assertNull(user.getHashedPassword()); } @Test public void passwordSerializedForNormalUserAsSuper() throws SlipStreamClientException { Request request = createGetRequest(superUser, superUser.getName()); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); String xml = response.getEntityAsText(); User user = (User) SerializationUtil.fromXml(xml, User.class); assertNull(user.getHashedPassword()); } @Test public void passwordBlankedForSuperAsSuper() throws SlipStreamClientException { Request request = createGetRequest(superUser, superUser.getName()); Response response = executeRequest(request); User user = (User) SerializationUtil.fromXml( response.getEntityAsText(), User.class); assertNull(user.getHashedPassword()); } @Test public void deleteUser() throws ConfigurationException, ValidationException { User toBeDelete = new User("toBeDelete"); UserTest.storeUser(toBeDelete); Request request = createDeleteRequest(toBeDelete, toBeDelete); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_NO_CONTENT)); } @Test public void cantDeleteAnotherUser() throws ConfigurationException, ValidationException { User cantBeDeleted = new User("cantBeDeletedByAnotherUser"); UserTest.storeUser(cantBeDeleted); Request request = createDeleteRequest(user, cantBeDeleted); Response response = executeRequest(request); cantBeDeleted.remove(); assertThat(response.getStatus(), is(Status.CLIENT_ERROR_FORBIDDEN)); } @Test public void cantSelfAssignSuperUnlessAlreadySuper() throws ConfigurationException, ValidationException { User cantSelfAssignSuper = UserTest.createUser("cantSelfAssignSuper"); UserTest.storeUser(cantSelfAssignSuper); cantSelfAssignSuper.setSuper(true); Request request = createPutRequest(cantSelfAssignSuper, "cantSelfAssignSuper"); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); cantSelfAssignSuper = User.loadByName("cantSelfAssignSuper"); cantSelfAssignSuper.remove(); assertThat(cantSelfAssignSuper.isSuper(), is(false)); } @Test public void superCanAssignSuperToOthers() throws ConfigurationException, ValidationException { User superCanAssignSuperToOthers = UserTest.createUser( "superCanAssignSuperToOthers"); superCanAssignSuperToOthers.setSuper(true); UserTest.storeUser(superCanAssignSuperToOthers); superCanAssignSuperToOthers.setSuper(false); Request request = createPutRequest(superCanAssignSuperToOthers, superUser.getName()); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); superCanAssignSuperToOthers = User .loadByName("superCanAssignSuperToOthers"); superCanAssignSuperToOthers.remove(); assertThat(superCanAssignSuperToOthers.isSuper(), is(false)); } private String getPersistedPassword(User user) throws ConfigurationException, ValidationException { User restoredUser = User.load(user.getResourceUri()); return restoredUser.getHashedPassword(); } private Passwords createValidPasswords(String oldPassword) throws NoSuchAlgorithmException, UnsupportedEncodingException { Passwords passwords = new Passwords(oldPassword, NEW_PASSWORD, NEW_PASSWORD); return passwords; } @Test public void getNewToRetrieveTemplate() throws ConfigurationException, ValidationException { Request request = createGetRequest(user, "new"); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); } @Test public void editRedirectsToView() throws ConfigurationException, ValidationException { Passwords passwords = new Passwords(); Request request = createPutRequest(user, user.getName(), passwords); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); assertThat(response.getLocationRef().getPath(), is("/user/" + user.getName())); } @Test public void putWithParameter() throws ConfigurationException, ValidationException { user = user.store(); String paramName = ExecutionControlUserParametersFactory.CATEGORY + "." + ExecutionControlUserParametersFactory.DEFAULT_CLOUD_SERVICE_PARAMETER_NAME; UserParameter p = new UserParameter(paramName, LocalConnector.CLOUD_SERVICE_NAME, "description"); user.setParameter(p); Request request = createPutRequest(user, user.getName()); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); User updated = User.load(user.getResourceUri()); assertThat(updated.getParameter(paramName).getValue(), is(LocalConnector.CLOUD_SERVICE_NAME)); } @Test public void superCreatesInActiveState() throws ValidationException, ConfigurationException { User willBeActive = UserTest.createUser("superCreatesInActiveState"); Passwords passwords = new Passwords(null, UserTest.PASSWORD, UserTest.PASSWORD); Request request = createPutRequest(willBeActive, superUser.getName(), passwords); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_CREATED)); willBeActive = User.loadByName(willBeActive.getName()); assertThat(willBeActive.getState(), is(State.ACTIVE)); willBeActive.remove(); } @Test public void normalUserCreatedInNewState() throws ValidationException, ConfigurationException { User willBeNew = UserTest.createUser("normalUserCreatedInNewState"); Passwords passwords = new Passwords(null, UserTest.PASSWORD, UserTest.PASSWORD); Request request = createPutRequest(willBeNew, user.getName(), passwords); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_CREATED)); willBeNew = User.loadByName(willBeNew.getName()); assertThat(willBeNew.getState(), is(State.NEW)); willBeNew.remove(); } @Test public void createWithUserState() throws ValidationException, ConfigurationException { User withState = UserTest.createUser("createWithUserState"); withState.setState(State.SUSPENDED); Passwords passwords = new Passwords(null, UserTest.PASSWORD, UserTest.PASSWORD); Request request = createPutRequest(withState, superUser.getName(), passwords); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_CREATED)); withState = User.loadByName(withState.getName()); assertThat(withState.getState(), is(State.SUSPENDED)); withState.remove(); } @Test public void putWithUserState() throws ValidationException, ConfigurationException { User withState = UserTest.createUser("putWithUserState"); withState = withState.store(); withState.setState(State.SUSPENDED); Request request = createPutRequest(withState, superUser.getName()); Response response = executeRequest(request); assertThat(response.getStatus(), is(Status.SUCCESS_OK)); withState = User.loadByName(withState.getName()); assertThat(withState.getState(), is(State.SUSPENDED)); withState.remove(); } @Test @Ignore public void systemParameterMerge() throws SlipStreamClientException { Request request = createGetRequest(superUser, otherUser.getName()); // Pick a category that we know always exists String category = "SlipStream_Support"; CookieUtils.addAuthnCookie(request, otherUser.getName(), category); Response response = executeRequest(request); String denormalized = XmlUtil.denormalize(response.getEntityAsText()); User user = (User) SerializationUtil.fromXml(denormalized, User.class); UserParameter systemParameter = user .getParameter("slipstream.support.email"); assertNotNull(systemParameter); } private Request createDeleteRequest(User targetUser, User user) throws ConfigurationException, ValidationException { return createDeleteRequest(targetUser, user.getName()); } private Request createDeleteRequest(User user, String targetUsername) throws ConfigurationException, ValidationException { Map<String, Object> attributes = createUserAttributes(targetUsername); Request request = createDeleteRequest(attributes); addUserToRequest(user, request); return request; } private Request createPutRequest(User targetUser, String username) throws ConfigurationException, ValidationException { Passwords passwords = new Passwords(); return createPutRequest(targetUser, username, passwords); } private Request createPutRequest(User targetUser, String username, Passwords passwords) throws ConfigurationException, ValidationException { Form form = new Form(); form.add("name", targetUser.getName()); form.add("firstname", targetUser.getFirstName()); form.add("lastname", targetUser.getLastName()); form.add("email", targetUser.getEmail()); if (passwords.newPassword1 != null) { form.add("password1", passwords.newPassword1); } if (passwords.newPassword2 != null) { form.add("password2", passwords.newPassword2); } if (passwords.oldPassword != null) { form.add("oldPassword", passwords.oldPassword); } if (targetUser.isSuper()) { form.add("super", "on"); } form.add("state", targetUser.getState().toString()); for (UserParameter parameter : targetUser.getParameters().values()) { UserFormProcessorTest.fillForm(parameter, form); } Map<String, Object> attributes = createUserAttributes(targetUser .getName()); Request request = createPutRequest(attributes, form.getWebRepresentation(), targetUser.getResourceUri()); addUserToRequest(username, request); return request; } private Request createGetRequest(User user) throws ConfigurationException, ValidationException { return createGetRequest(user, user.getName()); } private Request createGetRequest(User user, String targetUsername) throws ConfigurationException, ValidationException { Map<String, Object> attributes = createUserAttributes(targetUsername); Request request = createGetRequest(attributes); addUserToRequest(user, request); return request; } private Map<String, Object> createUserAttributes(String targetUsername) { return createAttributes("user", targetUsername); } private Response executeRequest(Request request) { return executeRequest(request, new UserResource()); } }