diff --git a/assembly/assembly-wsagent-war/src/main/java/org/eclipse/che/wsagent/server/WsAgentModule.java b/assembly/assembly-wsagent-war/src/main/java/org/eclipse/che/wsagent/server/WsAgentModule.java
index b8e7c88848..5d7edff736 100644
--- a/assembly/assembly-wsagent-war/src/main/java/org/eclipse/che/wsagent/server/WsAgentModule.java
+++ b/assembly/assembly-wsagent-war/src/main/java/org/eclipse/che/wsagent/server/WsAgentModule.java
@@ -29,7 +29,7 @@ import org.eclipse.che.api.git.GitUserResolver;
import org.eclipse.che.api.project.server.ProjectApiModule;
import org.eclipse.che.api.ssh.server.HttpSshServiceClient;
import org.eclipse.che.api.ssh.server.SshServiceClient;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
import org.eclipse.che.commons.lang.Pair;
import org.eclipse.che.everrest.CheAsynchronousJobPool;
import org.eclipse.che.api.git.LocalGitUserResolver;
diff --git a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java
index 072480ae51..acbe238904 100644
--- a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java
+++ b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java
@@ -15,6 +15,7 @@ import com.google.inject.multibindings.Multibinder;
import com.google.inject.name.Names;
import org.eclipse.che.api.machine.shared.Constants;
+import org.eclipse.che.api.user.server.ProfileService;
import org.eclipse.che.inject.DynaModule;
import org.everrest.guice.ServiceBindingHelper;
@@ -30,7 +31,8 @@ public class WsMasterModule extends AbstractModule {
bind(org.eclipse.che.api.ssh.server.SshService.class);
bind(org.eclipse.che.api.machine.server.recipe.RecipeService.class);
bind(org.eclipse.che.api.user.server.UserService.class);
- bind(org.eclipse.che.api.user.server.UserProfileService.class);
+ bind(org.eclipse.che.api.user.server.ProfileService.class);
+ bind(org.eclipse.che.api.user.server.PreferencesService.class);
bind(org.eclipse.che.api.workspace.server.stack.StackLoader.class);
bind(org.eclipse.che.api.workspace.server.stack.StackService.class);
bind(org.eclipse.che.api.workspace.server.WorkspaceService.class);
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/user/Profile.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/user/Profile.java
new file mode 100644
index 0000000000..d7a03e5a54
--- /dev/null
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/user/Profile.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.model.user;
+
+import java.util.Map;
+
+/**
+ * Defines the user's profile model.
+ *
+ *
User's profile describes an additional user information such as his
+ * job title or company name which is not related to application business logic.
+ * If it is necessary to manage business logic related attributes then
+ * user's preferences should be used instead.
+ *
+ * @author Yevhenii Voevodin
+ * @see User
+ */
+public interface Profile {
+
+ /**
+ * Returns the identifier of the user {@link User#getId()}
+ * whom this profile belongs to.
+ */
+ String getUserId();
+
+ /**
+ * Returns the user profile attributes (e.g. job title).
+ */
+ Map getAttributes();
+}
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/user/User.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/user/User.java
new file mode 100644
index 0000000000..1536ab541e
--- /dev/null
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/user/User.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.model.user;
+
+import org.eclipse.che.commons.annotation.Nullable;
+
+import java.util.List;
+
+/**
+ * Defines the user model.
+ *
+ * @author Yevhenii Voevodin
+ */
+public interface User {
+
+ /**
+ * Returns the identifier of the user (e.g. "user0x124567890").
+ * The identifier value is unique and mandatory.
+ */
+ String getId();
+
+ /**
+ * Returns the user's email (e.g. user@codenvy.com).
+ * The email is unique, mandatory and updatable.
+ */
+ String getEmail();
+
+ /**
+ * Returns the user's name (e.g. name_example).
+ * The name is unique, mandatory and updatable.
+ */
+ String getName();
+
+ /**
+ * Returns the list of the user's aliases, the aliases are the values
+ * which identify user in the system with third party ids (e.g. if user is registered
+ * within google oauth the aliases list may contain 'google:user_identifier' alias).
+ *
+ * Note that user's {@link #getEmail() email} and {@link #getName() name}
+ * are not a part of the result, and returned list never contains those values.
+ * Also note that returned aliases are unique, so there are no two users
+ * who have the alias in common.
+ */
+ List getAliases();
+
+ /**
+ * Returns the user's password.
+ * The returned value may be the password placeholder such as 'none' or
+ * even null, depends on the context.
+ */
+ @Nullable
+ String getPassword();
+}
diff --git a/core/che-core-api-model/src/main/resources/org/eclipse/che/api/core/model/Model.gwt.xml b/core/che-core-api-model/src/main/resources/org/eclipse/che/api/core/model/Model.gwt.xml
index ba274e4e70..dab00cbbdc 100644
--- a/core/che-core-api-model/src/main/resources/org/eclipse/che/api/core/model/Model.gwt.xml
+++ b/core/che-core-api-model/src/main/resources/org/eclipse/che/api/core/model/Model.gwt.xml
@@ -18,5 +18,6 @@
+
diff --git a/core/commons/che-core-commons-test/pom.xml b/core/commons/che-core-commons-test/pom.xml
index 64474bce88..9339b40210 100644
--- a/core/commons/che-core-commons-test/pom.xml
+++ b/core/commons/che-core-commons-test/pom.xml
@@ -21,10 +21,32 @@
che-core-commons-test
jar
Che Core :: Commons :: Utilities for tests
+
+ true
+
org.mockito
mockito-core
+
+ org.testng
+ testng
+
+
+ com.google.guava
+ guava
+ provided
+
+
+ com.google.inject
+ guice
+ provided
+
+
+ javax.inject
+ javax.inject
+ provided
+
diff --git a/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/TckModule.java b/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/TckModule.java
new file mode 100644
index 0000000000..26dcb8bbdb
--- /dev/null
+++ b/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/TckModule.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.commons.test.tck;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Module;
+
+import org.testng.IModuleFactory;
+import org.testng.ITestContext;
+
+import java.util.ServiceLoader;
+
+/**
+ * Abstract class for those Guice {@link Module modules} which provide
+ * TCK tests components, which will be injected directly into the test class.
+ *
+ * The {@link ServiceLoader} mechanism is used for loading such modules
+ * and for injecting them later. So each module which is TCK module must
+ * provide the implementations list(as described by {@code ServiceLoader} mechanism)
+ * in the file named org.eclipse.che.commons.test.tck.TckModule usually under
+ * test/resources/META-INF/services directory, then the {@link TckModuleFactory}
+ * will recognise and load it.
+ *
+ * @author Yevhenii Voevodin
+ * @see TckModuleFactory
+ */
+public abstract class TckModule extends AbstractModule {
+
+ /**
+ * It is guaranteed that this field is always present and
+ * can be reused by implementation, the value is equal to the
+ * {@link IModuleFactory#createModule(ITestContext, Class)} first
+ * parameter and will be set by {@link TckModuleFactory} immediately after module
+ * implementation is loaded by {@link ServiceLoader}.
+ */
+ private ITestContext testContext;
+
+ /** Returns the {@link ITestContext context} of currently executing test suite. */
+ protected ITestContext getTestContext() {
+ return testContext;
+ }
+
+ /**
+ * Sets the context of currently executing test suite.
+ * This method designed to be used by {@link TckModuleFactory} for setting
+ * the context before installing modules.
+ */
+ void setTestContext(ITestContext testContext) {
+ this.testContext = testContext;
+ }
+}
diff --git a/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/TckModuleFactory.java b/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/TckModuleFactory.java
new file mode 100644
index 0000000000..8802f12b25
--- /dev/null
+++ b/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/TckModuleFactory.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.commons.test.tck;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Module;
+
+import org.testng.IModuleFactory;
+import org.testng.ITestContext;
+
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+import static java.lang.String.format;
+
+/**
+ * The factory is designed to instantiate {@link TckModule tck modules}
+ * using {@link ServiceLoader} mechanism. The components
+ * provided by those modules will be injected into a test class
+ * whether it's necessary to do so.
+ *
+ *
The factory expects at least one implementation of {@code TckModule}
+ * to be configured, if it doesn't find any of the {@code TckModule}
+ * implementations then it will report an appropriate exception
+ * and TckTest will fail(as it requires components to be injected into it).
+ * If it finds more than one {@code TckModule} implementation it will
+ * use all of the found.
+ *
+ *
The usage example:
+ *
+ * package org.eclipse.mycomponent;
+ *
+ * @org.testng.annotations.Guice(moduleFactory = TckModuleFactory.class)
+ * // Good practice to define suiteName for TCK tests as it makes easier
+ * // to implement logic related to certain tests in ITestNGListener implementations
+ * @org.testng.annotations.Test(suiteName = "MySuite")
+ * class SubjectTest {
+ *
+ * @javax.inject.Inject
+ * private Component1 component1.
+ * @javax.inject.Inject
+ * private Component2 component2;
+ *
+ * @org.testng.annotations.Test
+ * public void test() {
+ * // use components
+ * }
+ * }
+ *
+ * class MyTckModule extends TckModule {
+ * public void configure() {
+ * bind(Component1.class).to(...);
+ * bind(Component2.class).toInstance(new Component2(() -> testContext.getAttribute("server_url").toString()));
+ * }
+ * }
+ *
+ * // Allows to add pre/post test actions like db server start/stop
+ * class DBServerListener implements ITestListener {
+ * // ...
+ * public void onStart(ITestContext context) {
+ * String url = dbServer.start();
+ * context.setAttribute("server_url", url)l
+ * }
+ *
+ * public void onFinish(ITestContext context) {
+ * dbServer.stop();
+ * }
+ * // ...
+ * }
+ *
+ *
+ * Configuring:
+ *
+ * META-INF/services/org.eclipse.che.commons.test.tck.TckModule
+ * org.eclipse.mycomponent.MyTckModule
+ *
+ * META-INF/services/org.testng.ITestNGListener
+ * org.eclipse.mycomponent.DBServerListener
+ *
+ *
+ * @author Yevhenii Voevodin
+ * @see org.testng.annotations.Guice
+ * @see IModuleFactory
+ */
+public class TckModuleFactory implements IModuleFactory {
+
+ @Override
+ public Module createModule(ITestContext context, Class> testClass) {
+ final Iterator moduleIterator = ServiceLoader.load(TckModule.class).iterator();
+ if (!moduleIterator.hasNext()) {
+ throw new IllegalStateException(format("Couldn't find a TckModule configuration. " +
+ "You probably forgot to configure resources/META-INF/services/%s, or even " +
+ "provide an implementation of the TckModule which is required by the tck test class %s",
+ TckModule.class.getName(),
+ testClass.getName()));
+ }
+ return new CompoundModule(context, moduleIterator);
+ }
+
+ private static class CompoundModule extends AbstractModule {
+ private final ITestContext testContext;
+ private final Iterator moduleIterator;
+
+ private CompoundModule(ITestContext testContext, Iterator moduleIterator) {
+ this.testContext = testContext;
+ this.moduleIterator = moduleIterator;
+ }
+
+ @Override
+ protected void configure() {
+ bind(ITestContext.class).toInstance(testContext);
+ while (moduleIterator.hasNext()) {
+ final TckModule module = moduleIterator.next();
+ module.setTestContext(testContext);
+ install(module);
+ }
+ }
+ }
+}
diff --git a/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/repository/TckRepository.java b/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/repository/TckRepository.java
new file mode 100644
index 0000000000..bfb2cd8ea0
--- /dev/null
+++ b/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/repository/TckRepository.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.commons.test.tck.repository;
+
+import java.util.Collection;
+
+/**
+ * The interface which allows to create TCK tests for DAO interfaces
+ * by providing operations for creating/removing batch of elements.
+ * The interface is designed to work with entities, which means
+ * that entity marshaling and unmarshalling to/from db objects must be
+ * tested by implementation separately.
+ *
+ * @param
+ * the type of the object managed by the repository
+ * @author Yevhenii Voevodin
+ */
+public interface TckRepository {
+
+ /**
+ * Creates all the given {@code entities} in the storage.
+ *
+ * Note that implementation must fail if it is impossible to
+ * create any of the given entities.
+ *
+ * @param entities
+ * elements to create
+ * @throws TckRepositoryException
+ * when any error occurs during the storing
+ */
+ void createAll(Collection extends T> entities) throws TckRepositoryException;
+
+ /**
+ * Clears the storage.
+ *
+ *
Note that implementation must fail if it is impossible to
+ * remove all the entities.
+ *
+ * @throws TckRepositoryException
+ * when any error occurs during the clearing
+ */
+ void removeAll() throws TckRepositoryException;
+}
diff --git a/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/repository/TckRepositoryException.java b/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/repository/TckRepositoryException.java
new file mode 100644
index 0000000000..33ce50511a
--- /dev/null
+++ b/core/commons/che-core-commons-test/src/main/java/org/eclipse/che/commons/test/tck/repository/TckRepositoryException.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.commons.test.tck.repository;
+
+import java.util.Collection;
+
+/**
+ * Thrown when any error occurs during {@link TckRepository#createAll(Collection)}
+ * or {@link TckRepository#removeAll()} invocation. Usually wraps exceptions
+ * occurred during the storing/removing.
+ *
+ * @author Yevhenii Voevodin
+ */
+public class TckRepositoryException extends Exception {
+
+ public TckRepositoryException(String message) {
+ super(message);
+ }
+
+ public TckRepositoryException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/DBServerListener.java b/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/DBServerListener.java
new file mode 100644
index 0000000000..fa4f585f74
--- /dev/null
+++ b/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/DBServerListener.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.commons.test.tck;
+
+import org.testng.ITestContext;
+import org.testng.ITestListener;
+import org.testng.ITestResult;
+
+/**
+ * Listener representing fake db server url injection for testing "attributes sharing"
+ * using {@link ITestContext} test suite instance.
+ *
+ * @author Yevhenii Voevodin
+ */
+public class DBServerListener implements ITestListener {
+
+ public static final String DB_SERVER_URL_ATTRIBUTE_NAME = "db_server_url";
+ public static final String DB_SERVER_URL = "localhost:12345";
+
+ @Override
+ public void onStart(ITestContext context) {
+ context.setAttribute(DB_SERVER_URL_ATTRIBUTE_NAME, DB_SERVER_URL);
+ }
+
+ @Override
+ public void onFinish(ITestContext context) {}
+
+ @Override
+ public void onTestStart(ITestResult result) {}
+
+ @Override
+ public void onTestSuccess(ITestResult result) {}
+
+ @Override
+ public void onTestFailure(ITestResult result) {}
+
+ @Override
+ public void onTestSkipped(ITestResult result) {}
+
+ @Override
+ public void onTestFailedButWithinSuccessPercentage(ITestResult result) {}
+}
diff --git a/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/TckComponentsTest.java b/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/TckComponentsTest.java
new file mode 100644
index 0000000000..706ac50b0e
--- /dev/null
+++ b/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/TckComponentsTest.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.commons.test.tck;
+
+import org.eclipse.che.commons.test.tck.repository.TckRepository;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import javax.inject.Inject;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+/**
+ * Tests for {@code org.eclipse.che.commons.test.tck.*} package.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Guice(moduleFactory = TckModuleFactory.class)
+public class TckComponentsTest {
+
+ @Inject
+ private TckRepository tckRepository;
+
+ @Inject
+ private DBUrlProvider dbUrlProvider;
+
+ @Test
+ public void testComponentsAreInjected() {
+ assertNotNull(tckRepository, "TckRepository is not injected");
+ assertNotNull(dbUrlProvider, "DBUrlProvider is not injected");
+ assertEquals(dbUrlProvider.getUrl(), DBServerListener.DB_SERVER_URL, "Value is set to ITestContext");
+ }
+
+ public interface Entity {}
+
+ public interface DBUrlProvider {
+ String getUrl();
+ }
+}
diff --git a/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/TestModule1.java b/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/TestModule1.java
new file mode 100644
index 0000000000..f7e26295c4
--- /dev/null
+++ b/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/TestModule1.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.commons.test.tck;
+
+import com.google.inject.TypeLiteral;
+
+import org.eclipse.che.commons.test.tck.TckComponentsTest.Entity;
+import org.eclipse.che.commons.test.tck.repository.TckRepository;
+import org.eclipse.che.commons.test.tck.repository.TckRepositoryException;
+
+import java.util.Collection;
+
+/**
+ * @author Yevhenii Voevodin
+ */
+public class TestModule1 extends TckModule {
+
+ @Override
+ public void configure() {
+ bind(new TypeLiteral>() {}).toInstance(new TckRepository() {
+ @Override
+ public void createAll(Collection extends Entity> entities) throws TckRepositoryException {}
+
+ @Override
+ public void removeAll() throws TckRepositoryException {}
+ });
+ }
+}
diff --git a/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/model/Membership.java b/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/TestModule2.java
similarity index 53%
rename from wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/model/Membership.java
rename to core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/TestModule2.java
index 4060dccd11..666867836c 100644
--- a/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/model/Membership.java
+++ b/core/commons/che-core-commons-test/src/test/java/org/eclipse/che/commons/test/tck/TestModule2.java
@@ -8,25 +8,19 @@
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
-package org.eclipse.che.api.user.shared.model;
+package org.eclipse.che.commons.test.tck;
-import java.util.List;
-import java.util.Map;
+import org.eclipse.che.commons.test.tck.TckComponentsTest.DBUrlProvider;
+
+import static org.eclipse.che.commons.test.tck.DBServerListener.DB_SERVER_URL_ATTRIBUTE_NAME;
/**
- * @author gazarenkov
+ * @author Yevhenii Voevodin
*/
-public interface Membership {
+public class TestModule2 extends TckModule {
- String getScope();
-
- List getRoles();
-
- String getUserId();
-
- String getUserName();
-
- String getSubjectId();
-
- Map getSubjectProperties();
+ @Override
+ public void configure() {
+ bind(DBUrlProvider.class).toInstance(() -> getTestContext().getAttribute(DB_SERVER_URL_ATTRIBUTE_NAME).toString());
+ }
}
diff --git a/core/commons/che-core-commons-test/src/test/resources/META-INF/services/org.eclipse.che.commons.test.tck.TckModule b/core/commons/che-core-commons-test/src/test/resources/META-INF/services/org.eclipse.che.commons.test.tck.TckModule
new file mode 100644
index 0000000000..5c9171f461
--- /dev/null
+++ b/core/commons/che-core-commons-test/src/test/resources/META-INF/services/org.eclipse.che.commons.test.tck.TckModule
@@ -0,0 +1,2 @@
+org.eclipse.che.commons.test.tck.TestModule1
+org.eclipse.che.commons.test.tck.TestModule2
diff --git a/core/commons/che-core-commons-test/src/test/resources/META-INF/services/org.testng.ITestNGListener b/core/commons/che-core-commons-test/src/test/resources/META-INF/services/org.testng.ITestNGListener
new file mode 100644
index 0000000000..3fea5967cb
--- /dev/null
+++ b/core/commons/che-core-commons-test/src/test/resources/META-INF/services/org.testng.ITestNGListener
@@ -0,0 +1 @@
+org.eclipse.che.commons.test.tck.DBServerListener
diff --git a/core/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/PreferencesServiceClient.java b/core/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/PreferencesServiceClient.java
new file mode 100644
index 0000000000..7176bd7057
--- /dev/null
+++ b/core/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/PreferencesServiceClient.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.ide.api.user;
+
+import org.eclipse.che.api.promises.client.Promise;
+import javax.validation.constraints.NotNull;
+import java.util.Map;
+
+/**
+ * GWT client for preferences service;
+ *
+ * @author Yevhenii Voevodin
+ */
+public interface PreferencesServiceClient {
+
+ /**
+ * Updates user's preferences using the merge strategy.
+ *
+ * @param prefsToUpdate
+ * preferences update
+ * @return a promise that resolves all the user's preferences, or rejects with an error
+ */
+ Promise> updatePreferences(@NotNull Map prefsToUpdate);
+
+ /**
+ * Gets user preferences.
+ *
+ * @return a promise that resolves preferences, or rejects with an error
+ */
+ Promise> getPreferences();
+}
diff --git a/core/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/PreferencesServiceClientImpl.java b/core/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/PreferencesServiceClientImpl.java
new file mode 100644
index 0000000000..30c44c3c02
--- /dev/null
+++ b/core/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/PreferencesServiceClientImpl.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.ide.api.user;
+
+import com.google.inject.Inject;
+
+import org.eclipse.che.api.promises.client.Promise;
+import org.eclipse.che.ide.json.JsonHelper;
+import org.eclipse.che.ide.rest.AsyncRequestFactory;
+import org.eclipse.che.ide.rest.RestContext;
+import org.eclipse.che.ide.rest.StringMapUnmarshaller;
+import org.eclipse.che.ide.ui.loaders.request.LoaderFactory;
+
+import java.util.Map;
+
+import static org.eclipse.che.ide.MimeType.APPLICATION_JSON;
+import static org.eclipse.che.ide.rest.HTTPHeader.ACCEPT;
+import static org.eclipse.che.ide.rest.HTTPHeader.CONTENT_TYPE;
+
+/**
+ * Default implementation of {@link PreferencesServiceClient}.
+ *
+ * @author Yevhenii Voevodin
+ */
+public class PreferencesServiceClientImpl implements PreferencesServiceClient {
+
+ private final String PREFERENCES_PATH;
+ private final LoaderFactory loaderFactory;
+ private final AsyncRequestFactory asyncRequestFactory;
+
+ @Inject
+ protected PreferencesServiceClientImpl(@RestContext String restContext,
+ LoaderFactory loaderFactory,
+ AsyncRequestFactory asyncRequestFactory) {
+ this.loaderFactory = loaderFactory;
+ this.asyncRequestFactory = asyncRequestFactory;
+ PREFERENCES_PATH = restContext + "/preferences";
+ }
+
+ @Override
+ public Promise> getPreferences() {
+ return asyncRequestFactory.createGetRequest(PREFERENCES_PATH)
+ .header(ACCEPT, APPLICATION_JSON)
+ .header(CONTENT_TYPE, APPLICATION_JSON)
+ .loader(loaderFactory.newLoader("Getting user's preferences..."))
+ .send(new StringMapUnmarshaller());
+ }
+
+ @Override
+ public Promise> updatePreferences(Map update) {
+ final String data = JsonHelper.toJson(update);
+ return asyncRequestFactory.createPutRequest(PREFERENCES_PATH, null)
+ .header(ACCEPT, APPLICATION_JSON)
+ .header(CONTENT_TYPE, APPLICATION_JSON)
+ .data(data)
+ .loader(loaderFactory.newLoader("Updating user's preferences..."))
+ .send(new StringMapUnmarshaller());
+ }
+}
diff --git a/dashboard/src/app/administration/docker-registry/docker-registry-list/add-registry/add-registry.controller.js b/dashboard/src/app/administration/docker-registry/docker-registry-list/add-registry/add-registry.controller.js
index dbc4892703..fd5debb495 100644
--- a/dashboard/src/app/administration/docker-registry/docker-registry-list/add-registry/add-registry.controller.js
+++ b/dashboard/src/app/administration/docker-registry/docker-registry-list/add-registry/add-registry.controller.js
@@ -20,9 +20,9 @@ export class AddRegistryController {
* Default constructor.
* @ngInject for Dependency injection
*/
- constructor($mdDialog, cheProfile, cheNotification) {
+ constructor($mdDialog, chePreferences, cheNotification) {
this.$mdDialog = $mdDialog;
- this.cheProfile = cheProfile;
+ this.chePreferences = chePreferences;
this.cheNotification = cheNotification;
}
@@ -41,7 +41,7 @@ export class AddRegistryController {
return;
}
- let promise = this.cheProfile.addRegistry(this.registryUrl, this.registryUserName, this.registryUserPassword);
+ let promise = this.chePreferences.addRegistry(this.registryUrl, this.registryUserName, this.registryUserPassword);
promise.then(() => {
this.$mdDialog.hide();
diff --git a/dashboard/src/app/administration/docker-registry/docker-registry-list/docker-registry-list.controller.js b/dashboard/src/app/administration/docker-registry/docker-registry-list/docker-registry-list.controller.js
index 14e598639f..f2ca629382 100644
--- a/dashboard/src/app/administration/docker-registry/docker-registry-list/docker-registry-list.controller.js
+++ b/dashboard/src/app/administration/docker-registry/docker-registry-list/docker-registry-list.controller.js
@@ -22,16 +22,16 @@ export class DockerRegistryListController {
* Default constructor that is using resource
* @ngInject for Dependency injection
*/
- constructor($mdDialog, $document, cheProfile, cheNotification) {
+ constructor($mdDialog, $document, chePreferences, cheNotification) {
this.$mdDialog = $mdDialog;
this.$document = $document;
- this.cheProfile = cheProfile;
+ this.chePreferences = chePreferences;
this.cheNotification = cheNotification;
- this.registries = cheProfile.getRegistries();
+ this.registries = chePreferences.getRegistries();
this.isLoading = true;
- let promise = cheProfile.fetchPreferences();
+ let promise = chePreferences.fetchPreferences();
promise.then(() => {
this.isLoading = false;
}, (error) => {
@@ -91,7 +91,7 @@ export class DockerRegistryListController {
.targetEvent(event);
this.$mdDialog.show(confirm).then(() => {
this.isLoading = true;
- let promise = this.cheProfile.removeRegistry(registry.url);
+ let promise = this.chePreferences.removeRegistry(registry.url);
promise.then(() => {
this.isLoading = false;
}, (error) => {
diff --git a/dashboard/src/app/index.module.js b/dashboard/src/app/index.module.js
index d94e145b67..a8fe0e9cfb 100644
--- a/dashboard/src/app/index.module.js
+++ b/dashboard/src/app/index.module.js
@@ -40,13 +40,13 @@ let initModule = angular.module('userDashboard', ['ngAnimate', 'ngCookies', 'ngT
initModule.config(['$routeProvider', ($routeProvider) => {
$routeProvider.accessWhen = (path, route) => {
route.resolve || (route.resolve = {});
- route.resolve.app = ['cheBranding', '$q', 'cheProfile', (cheBranding, $q, cheProfile) => {
+ route.resolve.app = ['cheBranding', '$q', 'chePreferences', (cheBranding, $q, chePreferences) => {
var deferred = $q.defer();
- let profilePreferences = cheProfile.getPreferences();
- if (profilePreferences && profilePreferences.$resolved) {
+ let preferences = chePreferences.getPreferences();
+ if (preferences && preferences.$resolved) {
deferred.resolve();
} else {
- profilePreferences.$promise.then(() => {
+ preferences.$promise.then(() => {
deferred.resolve();
}, (error) => {
deferred.reject(error);
@@ -61,13 +61,13 @@ initModule.config(['$routeProvider', ($routeProvider) => {
$routeProvider.accessOtherWise = (route) => {
route.resolve || (route.resolve = {});
- route.resolve.app = ['$q', 'cheProfile', ($q, cheProfile) => {
+ route.resolve.app = ['$q', 'chePreferences', ($q, chePreferences) => {
var deferred = $q.defer();
- let profilePreferences = cheProfile.getPreferences();
- if (profilePreferences && profilePreferences.$resolved) {
+ let preferences = chePreferences.getPreferences();
+ if (preferences && preferences.$resolved) {
deferred.resolve();
} else {
- profilePreferences.$promise.then(() => {
+ preferences.$promise.then(() => {
deferred.resolve();
}, (error) => {
deferred.reject(error);
diff --git a/dashboard/src/app/navbar/navbar.controller.js b/dashboard/src/app/navbar/navbar.controller.js
index a60aa4a4a6..e6a89f40de 100644
--- a/dashboard/src/app/navbar/navbar.controller.js
+++ b/dashboard/src/app/navbar/navbar.controller.js
@@ -26,11 +26,11 @@ export class CheNavBarCtrl {
this.links = [{href: '#/create-workspace', name: 'New Workspace'}];
this.profile = cheAPI.getProfile().getProfile();
- if (this.profile.attributes) {
- this.email = this.profile.attributes.email;
+ if (this.profile.email) {
+ this.email = this.profile.email;
} else {
this.profile.$promise.then(() => {
- this.email = this.profile.attributes.email ? this.profile.attributes.email : 'N/A ';
+ this.email = this.profile.email ? this.profile.email : 'N/A ';
}, () => {
this.email = 'N/A ';
});
diff --git a/dashboard/src/app/projects/list-projects/list-projects.controller.js b/dashboard/src/app/projects/list-projects/list-projects.controller.js
index 96defdd984..d9e1ddde0e 100644
--- a/dashboard/src/app/projects/list-projects/list-projects.controller.js
+++ b/dashboard/src/app/projects/list-projects/list-projects.controller.js
@@ -49,9 +49,9 @@ export class ListProjectsCtrl {
}
});
- let profilePreferences = cheAPI.getProfile().getPreferences();
+ let preferences = cheAPI.getPreferences().getPreferences();
- this.profileCreationDate = profilePreferences['che:created'];
+ this.profileCreationDate = preferences['che:created'];
this.menuOptions = [
{
diff --git a/dashboard/src/app/workspaces/workspace-details/workspace-projects/workspace-details-projects.controller.js b/dashboard/src/app/workspaces/workspace-details/workspace-projects/workspace-details-projects.controller.js
index 47419670ef..228666a2c8 100644
--- a/dashboard/src/app/workspaces/workspace-details/workspace-projects/workspace-details-projects.controller.js
+++ b/dashboard/src/app/workspaces/workspace-details/workspace-projects/workspace-details-projects.controller.js
@@ -28,9 +28,9 @@ export class WorkspaceDetailsProjectsCtrl {
this.namespace = $route.current.params.namespace;
this.workspaceName = $route.current.params.workspaceName;
- let profilePreferences = cheAPI.getProfile().getPreferences();
+ let preferences = cheAPI.getPreferences().getPreferences();
- this.profileCreationDate = profilePreferences['che:created'];
+ this.profileCreationDate = preferences['che:created'];
if (!this.cheWorkspace.getWorkspacesById().get(this.workspaceId)) {
let promise = this.cheWorkspace.fetchWorkspaceDetails(this.workspaceId);
diff --git a/dashboard/src/components/api/builder/che-profile-builder.js b/dashboard/src/components/api/builder/che-profile-builder.js
index dc07d28d84..41556b6219 100644
--- a/dashboard/src/components/api/builder/che-profile-builder.js
+++ b/dashboard/src/components/api/builder/che-profile-builder.js
@@ -32,7 +32,8 @@ export class CheProfileBuilder {
* @returns {CheProfileBuilder}
*/
withEmail(email) {
- return this.withAttribute('email', email);
+ this.profile.email = email;
+ return this;
}
/**
diff --git a/dashboard/src/components/api/che-api-config.js b/dashboard/src/components/api/che-api-config.js
index 65d212c717..974f3bb860 100644
--- a/dashboard/src/components/api/che-api-config.js
+++ b/dashboard/src/components/api/che-api-config.js
@@ -18,6 +18,7 @@ import {CheRecipeTemplate} from './che-recipe-template.factory';
import {CheStack} from './che-stack.factory';
import {CheWebsocket} from './che-websocket.factory';
import {CheProfile} from './che-profile.factory';
+import {ChePreferences} from './che-preferences.factory';
import {CheService} from './che-service.factory';
import {CheSvn} from './che-svn.factory';
import {CheHttpBackend} from './test/che-http-backend';
@@ -35,6 +36,7 @@ export class ApiConfig {
register.factory('cheWorkspace', CheWorkspace);
register.factory('cheProjectTemplate', CheProjectTemplate);
register.factory('cheProfile', CheProfile);
+ register.factory('chePreferences', ChePreferences);
register.factory('cheWebsocket', CheWebsocket);
register.factory('cheRecipe', CheRecipe);
register.factory('cheRecipeTemplate', CheRecipeTemplate);
diff --git a/dashboard/src/components/api/che-api.factory.js b/dashboard/src/components/api/che-api.factory.js
index bdf16639f5..c813d63536 100644
--- a/dashboard/src/components/api/che-api.factory.js
+++ b/dashboard/src/components/api/che-api.factory.js
@@ -22,10 +22,11 @@ export class CheAPI {
* Default constructor that is using resource
* @ngInject for Dependency injection
*/
- constructor(cheWorkspace, cheProfile, cheProjectTemplate, cheWebsocket, cheSvn, cheService,
+ constructor(cheWorkspace, cheProfile, chePreferences, cheProjectTemplate, cheWebsocket, cheSvn, cheService,
cheAdminPlugins, cheAdminService, cheRecipe, cheRecipeTemplate, cheStack, cheOAuthProvider) {
this.cheWorkspace = cheWorkspace;
this.cheProfile = cheProfile;
+ this.chePreferences = chePreferences;
this.cheProjectTemplate = cheProjectTemplate;
this.cheWebsocket = cheWebsocket;
this.cheSvn = cheSvn;
@@ -63,6 +64,14 @@ export class CheAPI {
return this.cheProfile;
}
+ /**
+ * The Che Preferences API
+ * @returns {ChePreferences|*}
+ */
+ getPreferences() {
+ return this.chePreferences;
+ }
+
/**
* The Che Project Template API
* @returns {CheProjectTemplate|*}
diff --git a/dashboard/src/components/api/che-preferences.factory.js b/dashboard/src/components/api/che-preferences.factory.js
new file mode 100644
index 0000000000..7196ce9130
--- /dev/null
+++ b/dashboard/src/components/api/che-preferences.factory.js
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2015-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ */
+'use strict';
+
+/**
+ * This class is handling the preferences API retrieval
+ * @author Yevhenii Voevodin
+ */
+export class ChePreferences {
+
+ /**
+ * Default constructor that is using resource
+ * @ngInject for Dependency injection
+ */
+ constructor($resource, $http, $window) {
+ this.$window = $window;
+
+ // keep resource
+ this.$resource = $resource;
+
+ // http is used for sending data with DELETE method (angular is not sending any data by default with DELETE)
+ this.$http = $http;
+
+ // remote call
+ this.remotePreferencesAPI = this.$resource('/api/preferences', {}, {
+ getPreferences: {method: 'GET', url: '/api/preferences'},
+ updatePreferences: {method: 'POST', url: '/api/preferences'}
+ });
+
+ // fetch the preferences when we're initialized
+ this.fetchPreferences();
+
+
+ //registry array
+ this.registries = [];
+ }
+
+ /**
+ * Gets the preferences
+ * @return preferences
+ */
+ getPreferences() {
+ return this.preferences;
+ }
+
+ /**
+ * Update the preferences
+ * @param properties
+ */
+ updatePreferences(properties) {
+ angular.extend(this.preferences, properties);
+ return this.preferences.$save();
+ }
+
+ /**
+ * Remove preferences properties
+ * @param properties (list of keys)
+ */
+ removePreferences(properties) {
+ // delete method doesn't send body when it is defined in $resources
+ // that's why direct $http call is used.
+ this.$http({
+ url: '/api/preferences',
+ method: 'DELETE',
+ headers: {'Content-Type': 'application/json;charset=utf-8'},
+ data: properties}).then(resp => {
+ this.fetchPreferences();
+ })
+ }
+
+ /**
+ * Gets the preferences data
+ */
+ fetchPreferences() {
+ let preferences = this.remotePreferencesAPI.getPreferences();
+ // if we don't yet have data
+ if (!this.preferences) {
+ // set preferences for using promise in controllers during first request
+ this.preferences = preferences;
+ }
+
+ let preferencesPromise = this.preferences.$promise;
+
+ preferencesPromise.then((preferences) => {
+ // update preferences data if we have new value
+ this.preferences = preferences;
+ });
+
+ return preferencesPromise;
+ }
+
+
+ /**
+ * Gets the registries
+ * @return registries
+ */
+ getRegistries() {
+ return this.registries;
+ }
+
+ /**
+ * Add a registry
+ * @param registryUrl
+ * @param userName
+ * @param userEmail
+ * @param userPassword
+ * @returns {*} the promise
+ */
+ addRegistry(registryUrl, userName, userPassword) {
+ let credentials = {};
+ credentials[registryUrl] = {
+ username: userName,
+ password: userPassword
+ };
+
+ if (this.preferences.dockerCredentials) {
+ let remoteCredentialsJson = this.$window.atob(this.preferences.dockerCredentials);
+ let remoteCredentials = angular.fromJson(remoteCredentialsJson);
+ if (remoteCredentials[registryUrl]) {
+ delete remoteCredentials[registryUrl];
+ }
+ angular.extend(credentials, remoteCredentials);
+ }
+
+ let credentialsBase64 = this.$window.btoa(angular.toJson(credentials));
+ let preferences = {dockerCredentials: credentialsBase64};
+ let promise = this.updatePreferences(preferences);
+
+ promise.then((preferences) => {
+ this.preferences = preferences;
+ this._updateRegistries(preferences);
+ });
+
+ return promise;
+ }
+
+
+ /**
+ * Remove the registry by its URL
+ * @param registryUrl
+ * @returns {*} the promise
+ */
+ removeRegistry(registryUrl) {
+ let credentialsJson = this.$window.atob(this.preferences.dockerCredentials);
+ let credentials = angular.fromJson(credentialsJson);
+
+ delete credentials[registryUrl];
+
+ let credentialsBase64 = this.$window.btoa(angular.toJson(credentials));
+ let preferences = {dockerCredentials: credentialsBase64};
+
+ let promise = this.updatePreferences(preferences);
+
+ promise.then((preferences) => {
+ this.preferences = preferences;
+ this._updateRegistries(preferences);
+ });
+
+ return promise;
+ }
+
+ /**
+ * Update registry array from preferences
+ * @param preferences
+ */
+ _updateRegistries(preferences) {
+ this.registries.length = 0;
+ if (preferences.dockerCredentials) {
+ let credentialsJson = this.$window.atob(preferences.dockerCredentials);
+ let credentials = angular.fromJson(credentialsJson);
+
+ for (var key in credentials) {
+ let credential = {
+ url: key,
+ username: credentials[key].username,
+ password: credentials[key].password
+ };
+ this.registries.push(credential);
+ }
+ }
+ }
+}
diff --git a/dashboard/src/components/api/che-preferences.spec.js b/dashboard/src/components/api/che-preferences.spec.js
new file mode 100644
index 0000000000..c578334ecd
--- /dev/null
+++ b/dashboard/src/components/api/che-preferences.spec.js
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2015-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ */
+'use strict';
+
+/**
+ * Test of the ChePreferences
+ */
+describe('ChePreferences', function () {
+
+ /**
+ * Preferences Factory for the test
+ */
+ var factory;
+
+ /**
+ * API builder.
+ */
+ var apiBuilder;
+
+ /**
+ * Backend for handling http operations
+ */
+ var httpBackend;
+
+ /**
+ * che backend
+ */
+ var cheBackend;
+
+ /**
+ * setup module
+ */
+ beforeEach(angular.mock.module('userDashboard'));
+
+ /**
+ * Inject factory and http backend
+ */
+ beforeEach(inject(function (chePreferences, cheAPIBuilder, cheHttpBackend) {
+ factory = chePreferences;
+ apiBuilder = cheAPIBuilder;
+ cheBackend = cheHttpBackend;
+ httpBackend = cheHttpBackend.getHttpBackend();
+ }));
+
+ /**
+ * Check assertion after the test
+ */
+ afterEach(function () {
+ httpBackend.verifyNoOutstandingExpectation();
+ httpBackend.verifyNoOutstandingRequest();
+ });
+
+ /**
+ * Check that we're able to fetch preferences
+ */
+ it('Fetch preferences', function () {
+ // providing request
+ // add default preferences on Http backend
+ let defaultPreferences = { pref1 : "value1", pref2 : "value2"};
+ cheBackend.addDefaultPreferences(defaultPreferences);
+
+ // setup backend
+ cheBackend.setup();
+
+ // fetch preferences
+ factory.fetchPreferences();
+
+ // expecting GETs
+ httpBackend.expectGET('/api/preferences');
+
+ // flush command
+ httpBackend.flush();
+
+ // now, check preferences
+ let preferences = factory.getPreferences();
+
+ expect(preferences["pref1"]).toEqual("value1");
+ expect(preferences["pref2"]).toEqual("value2");
+ }
+ );
+
+ /**
+ * Check that we're able to update preferences
+ */
+ it('Update preferences', function () {
+ let defaultPreferences = { pref1 : "value1" };
+
+ // setup backend
+ cheBackend.setup();
+ cheBackend.setPreferences(defaultPreferences);
+
+ // fetch preferences
+ factory.updatePreferences(defaultPreferences);
+
+ // expecting POST
+ httpBackend.expectPOST('/api/preferences');
+
+ // flush command
+ httpBackend.flush();
+
+ // now, check preferences
+ let preferences = factory.getPreferences();
+
+ expect(preferences["pref1"]).toEqual("value1");
+ }
+ );
+
+ /**
+ * Check that we're able to delete preferences
+ */
+ it('Remove preferences', function () {
+
+ let defaultPreferences = { pref1 : "value1", pref2 : "value2" };
+ cheBackend.addDefaultPreferences(defaultPreferences);
+
+ // setup backend
+ cheBackend.setup();
+
+ // r
+ factory.removePreferences(["pref1"]);
+
+ // expecting POST
+ httpBackend.expectDELETE('/api/preferences');
+
+ // flush command
+ httpBackend.flush();
+ }
+ );
+});
diff --git a/dashboard/src/components/api/che-profile.factory.js b/dashboard/src/components/api/che-profile.factory.js
index ea81b3f362..8113c9d57a 100644
--- a/dashboard/src/components/api/che-profile.factory.js
+++ b/dashboard/src/components/api/che-profile.factory.js
@@ -21,9 +21,8 @@ export class CheProfile {
* Default constructor that is using resource
* @ngInject for Dependency injection
*/
- constructor($resource, $http, $window) {
+ constructor($resource, $http) {
this.$resource = $resource;
- this.$window = $window;
// http is used for sending data with DELETE method (angular is not sending any data by default with DELETE)
this.$http = $http;
@@ -31,22 +30,13 @@ export class CheProfile {
// remote call
this.remoteProfileAPI = this.$resource('/api/profile', {}, {
getById: {method: 'GET', url: '/api/profile/:userId'},
- setAttributes: {method: 'POST', url: '/api/profile'}
+ setAttributes: {method: 'PUT', url: '/api/profile/attributes'}
});
- // remote call for preferences
- this.remoteProfilePreferencesAPI = this.$resource('/api/profile/prefs');
-
this.profileIdMap = new Map();
// fetch the profile when we're initialized
this.fetchProfile();
-
- // fetch the profilePreferences when we're initialized
- this.fetchPreferences();
-
- //registry array
- this.registries = [];
}
@@ -58,129 +48,6 @@ export class CheProfile {
return this.profile;
}
- /**
- * Gets the preferences
- * @return preferences
- */
- getPreferences() {
- return this.profilePreferences;
- }
-
-
- /**
- * Update the preferences
- * @param properties
- * @returns {*} the promise
- */
- updatePreferences(properties) {
- angular.extend(this.profilePreferences, properties);
- return this.profilePreferences.$save();
- }
-
- /**
- * Gets the registries
- * @return registries
- */
- getRegistries() {
- return this.registries;
- }
-
- /**
- * Add a registry
- * @param registryUrl
- * @param userName
- * @param userEmail
- * @param userPassword
- * @returns {*} the promise
- */
- addRegistry(registryUrl, userName, userPassword) {
- let credentials = {};
- credentials[registryUrl] = {
- username: userName,
- password: userPassword
- };
-
- if (this.profilePreferences.dockerCredentials) {
- let remoteCredentialsJson = this.$window.atob(this.profilePreferences.dockerCredentials);
- let remoteCredentials = angular.fromJson(remoteCredentialsJson);
- if (remoteCredentials[registryUrl]) {
- delete remoteCredentials[registryUrl];
- }
- angular.extend(credentials, remoteCredentials);
- }
-
- let credentialsBase64 = this.$window.btoa(angular.toJson(credentials));
- let preferences = {dockerCredentials: credentialsBase64};
- let promise = this.updatePreferences(preferences);
-
- promise.then((profilePreferences) => {
- this.profilePreferences = profilePreferences;
- this._updateRegistries(profilePreferences);
- });
-
- return promise;
- }
-
-
- /**
- * Remove the registry by its URL
- * @param registryUrl
- * @returns {*} the promise
- */
- removeRegistry(registryUrl) {
- let credentialsJson = this.$window.atob(this.profilePreferences.dockerCredentials);
- let credentials = angular.fromJson(credentialsJson);
-
- delete credentials[registryUrl];
-
- let credentialsBase64 = this.$window.btoa(angular.toJson(credentials));
- let preferences = {dockerCredentials: credentialsBase64};
-
- let promise = this.updatePreferences(preferences);
-
- promise.then((profilePreferences) => {
- this.profilePreferences = profilePreferences;
- this._updateRegistries(profilePreferences);
- });
-
- return promise;
- }
-
- /**
- * Update registry array from profile preferences
- * @param profilePreferences
- */
- _updateRegistries(profilePreferences) {
- this.registries.length = 0;
- if (profilePreferences.dockerCredentials) {
- let credentialsJson = this.$window.atob(profilePreferences.dockerCredentials);
- let credentials = angular.fromJson(credentialsJson);
-
- for (var key in credentials) {
- let credential = {
- url: key,
- username: credentials[key].username,
- password: credentials[key].password
- };
- this.registries.push(credential);
- }
- }
- }
-
- /**
- * Remove preferences properties
- * @param properties (list of keys)
- */
- removePreferences(properties) {
- this.$http({
- url: '/api/profile/prefs',
- method: 'DELETE',
- headers: {'Content-Type': 'application/json;charset=utf-8'},
- data: properties
- });
- this.fetchPreferences();
- }
-
/**
* Gets the full name if it possible
* @returns {string} full name
@@ -223,28 +90,6 @@ export class CheProfile {
return profilePromise;
}
- /**
- * Gets the preferences data
- */
- fetchPreferences() {
- let profilePreferences = this.remoteProfilePreferencesAPI.get();
- // if we don't yet have data
- if (!this.profilePreferences) {
- // set profilePreferences for using promise in controllers during first request
- this.profilePreferences = profilePreferences;
- }
-
- let profilePrefsPromise = this.profilePreferences.$promise;
-
- profilePrefsPromise.then((profilePreferences) => {
- // update profilePreferences data if we have new value
- this.profilePreferences = profilePreferences;
- this._updateRegistries(profilePreferences);
- });
-
- return profilePrefsPromise;
- }
-
/**
* Set the profile attributes data
* @param attributes
diff --git a/dashboard/src/components/api/che-profile.spec.js b/dashboard/src/components/api/che-profile.spec.js
index 9eee677255..7f185bdb80 100644
--- a/dashboard/src/components/api/che-profile.spec.js
+++ b/dashboard/src/components/api/che-profile.spec.js
@@ -82,8 +82,6 @@ describe('CheProfile', function () {
// expecting GETs
httpBackend.expectGET('/api/profile');
- httpBackend.expectGET('/api/profile/prefs');
-
// flush command
httpBackend.flush();
@@ -92,7 +90,7 @@ describe('CheProfile', function () {
// check id, email, firstName and lastName in profile attributes
expect(profile.id).toEqual(profileId);
- expect(profile.attributes.email).toEqual(email);
+ expect(profile.email).toEqual(email);
expect(profile.attributes.firstName).toEqual(firstName);
expect(profile.attributes.lastName).toEqual(lastName);
}
@@ -112,8 +110,8 @@ describe('CheProfile', function () {
// fetch profile
factory.setAttributes(testAttributes);
- // expecting a POST
- httpBackend.expectPOST('/api/profile');
+ // expecting a PUT
+ httpBackend.expectPUT('/api/profile/attributes');
// flush command
httpBackend.flush();
diff --git a/dashboard/src/components/api/test/che-http-backend.js b/dashboard/src/components/api/test/che-http-backend.js
index 66b211c310..c5a4779dce 100644
--- a/dashboard/src/components/api/test/che-http-backend.js
+++ b/dashboard/src/components/api/test/che-http-backend.js
@@ -61,12 +61,15 @@ export class CheHttpBackend {
//profiles
this.httpBackend.when('GET', '/api/profile').respond(this.defaultProfile);
- this.httpBackend.when('GET', '/api/profile/prefs').respond(this.defaultProfilePrefs);
var profileKeys = this.profilesMap.keys();
for (let key of profileKeys) {
this.httpBackend.when('GET', '/api/profile/' + key).respond(this.profilesMap.get(key));
}
+ //preferences
+ this.httpBackend.when('GET', '/api/preferences').respond(this.defaultPreferences);
+ this.httpBackend.when('DELETE', '/api/preferences').respond();
+
/// project details
var projectDetailsKeys = this.projectDetailsMap.keys();
for (let projectKey of projectDetailsKeys) {
@@ -177,6 +180,23 @@ export class CheHttpBackend {
this.defaultProfile = profile;
}
+ /**
+ * Add the given preferences
+ * @param preferences
+ */
+ addDefaultPreferences(preferences) {
+ this.defaultPreferences = preferences;
+ }
+
+ /**
+ * Add the given preferences
+ * @param preferences
+ */
+ setPreferences(preferences) {
+ this.httpBackend.when('POST', '/api/preferences').respond(preferences);
+ this.defaultPreferences = preferences;
+ }
+
/**
* Add the given profile
* @param profile
@@ -191,7 +211,7 @@ export class CheHttpBackend {
* @param attributes
*/
setAttributes(attributes) {
- this.httpBackend.when('POST', '/api/profile').respond(attributes);
+ this.httpBackend.when('PUT', '/api/profile/attributes').respond(attributes);
this.defaultProfile.attributes = attributes;
}
@@ -312,4 +332,3 @@ export class CheHttpBackend {
}
}
-
diff --git a/dashboard/src/components/widget/learn-more/che-learn-more.controller.js b/dashboard/src/components/widget/learn-more/che-learn-more.controller.js
index 403ca1da4a..e33524d506 100644
--- a/dashboard/src/components/widget/learn-more/che-learn-more.controller.js
+++ b/dashboard/src/components/widget/learn-more/che-learn-more.controller.js
@@ -23,18 +23,18 @@ export class CheLearnMoreCtrl {
* Default constructor that is using resource
* @ngInject for Dependency injection
*/
- constructor($scope, $element, $attrs, $compile, cheProfile) {
+ constructor($scope, $element, $attrs, $compile, chePreferences) {
this.items = [];
this.WIDGET_PREFERENCES_PREFIX = 'learn-widget-';
- this.cheProfile = cheProfile;
+ this.chePreferences = chePreferences;
// current index is first one
this.currentIndex = 0;
- let preferences = this.cheProfile.getPreferences();
+ let preferences = this.chePreferences.getPreferences();
let promise = preferences.$promise;
promise.then(() => {
@@ -87,7 +87,7 @@ export class CheLearnMoreCtrl {
let checkKey = this.WIDGET_PREFERENCES_PREFIX + key;
var properties = {};
properties[checkKey] = value;
- this.cheProfile.updatePreferences(properties);
+ this.chePreferences.updatePreferences(properties);
// also update icon state
this.stateIcons[key] = value;
@@ -104,7 +104,7 @@ export class CheLearnMoreCtrl {
// check if key is stored in preferences
// if there,
if (key) {
- let preferences = this.cheProfile.getPreferences();
+ let preferences = this.chePreferences.getPreferences();
let promise = preferences.$promise;
promise.then(() => {
diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/app/CurrentUser.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/app/CurrentUser.java
index 2f30fe534c..2dd2e95f57 100644
--- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/app/CurrentUser.java
+++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/app/CurrentUser.java
@@ -10,7 +10,8 @@
*******************************************************************************/
package org.eclipse.che.ide.api.app;
-import org.eclipse.che.api.user.shared.dto.ProfileDescriptor;
+import org.eclipse.che.api.user.shared.dto.ProfileDto;
+
import com.google.inject.Singleton;
import java.util.Map;
@@ -22,17 +23,17 @@ import java.util.Map;
@Singleton
public class CurrentUser {
- private ProfileDescriptor profileDescriptor;
+ private ProfileDto profileDescriptor;
private Map preferences;
public CurrentUser() {
}
- public CurrentUser(ProfileDescriptor profileDescriptor) {
+ public CurrentUser(ProfileDto profileDescriptor) {
this(profileDescriptor, null);
}
- public CurrentUser(ProfileDescriptor profileDescriptor, Map preferences) {
+ public CurrentUser(ProfileDto profileDescriptor, Map preferences) {
this.profileDescriptor = profileDescriptor;
this.preferences = preferences;
}
@@ -42,11 +43,11 @@ public class CurrentUser {
*
* @return
*/
- public ProfileDescriptor getProfile() {
+ public ProfileDto getProfile() {
return profileDescriptor;
}
- public void setProfile(ProfileDescriptor profileDescriptor) {
+ public void setProfile(ProfileDto profileDescriptor) {
this.profileDescriptor = profileDescriptor;
}
diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/PreferencesServiceClient.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/PreferencesServiceClient.java
new file mode 100644
index 0000000000..7176bd7057
--- /dev/null
+++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/PreferencesServiceClient.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.ide.api.user;
+
+import org.eclipse.che.api.promises.client.Promise;
+import javax.validation.constraints.NotNull;
+import java.util.Map;
+
+/**
+ * GWT client for preferences service;
+ *
+ * @author Yevhenii Voevodin
+ */
+public interface PreferencesServiceClient {
+
+ /**
+ * Updates user's preferences using the merge strategy.
+ *
+ * @param prefsToUpdate
+ * preferences update
+ * @return a promise that resolves all the user's preferences, or rejects with an error
+ */
+ Promise> updatePreferences(@NotNull Map prefsToUpdate);
+
+ /**
+ * Gets user preferences.
+ *
+ * @return a promise that resolves preferences, or rejects with an error
+ */
+ Promise> getPreferences();
+}
diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/PreferencesServiceClientImpl.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/PreferencesServiceClientImpl.java
new file mode 100644
index 0000000000..30c44c3c02
--- /dev/null
+++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/PreferencesServiceClientImpl.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.ide.api.user;
+
+import com.google.inject.Inject;
+
+import org.eclipse.che.api.promises.client.Promise;
+import org.eclipse.che.ide.json.JsonHelper;
+import org.eclipse.che.ide.rest.AsyncRequestFactory;
+import org.eclipse.che.ide.rest.RestContext;
+import org.eclipse.che.ide.rest.StringMapUnmarshaller;
+import org.eclipse.che.ide.ui.loaders.request.LoaderFactory;
+
+import java.util.Map;
+
+import static org.eclipse.che.ide.MimeType.APPLICATION_JSON;
+import static org.eclipse.che.ide.rest.HTTPHeader.ACCEPT;
+import static org.eclipse.che.ide.rest.HTTPHeader.CONTENT_TYPE;
+
+/**
+ * Default implementation of {@link PreferencesServiceClient}.
+ *
+ * @author Yevhenii Voevodin
+ */
+public class PreferencesServiceClientImpl implements PreferencesServiceClient {
+
+ private final String PREFERENCES_PATH;
+ private final LoaderFactory loaderFactory;
+ private final AsyncRequestFactory asyncRequestFactory;
+
+ @Inject
+ protected PreferencesServiceClientImpl(@RestContext String restContext,
+ LoaderFactory loaderFactory,
+ AsyncRequestFactory asyncRequestFactory) {
+ this.loaderFactory = loaderFactory;
+ this.asyncRequestFactory = asyncRequestFactory;
+ PREFERENCES_PATH = restContext + "/preferences";
+ }
+
+ @Override
+ public Promise> getPreferences() {
+ return asyncRequestFactory.createGetRequest(PREFERENCES_PATH)
+ .header(ACCEPT, APPLICATION_JSON)
+ .header(CONTENT_TYPE, APPLICATION_JSON)
+ .loader(loaderFactory.newLoader("Getting user's preferences..."))
+ .send(new StringMapUnmarshaller());
+ }
+
+ @Override
+ public Promise> updatePreferences(Map update) {
+ final String data = JsonHelper.toJson(update);
+ return asyncRequestFactory.createPutRequest(PREFERENCES_PATH, null)
+ .header(ACCEPT, APPLICATION_JSON)
+ .header(CONTENT_TYPE, APPLICATION_JSON)
+ .data(data)
+ .loader(loaderFactory.newLoader("Updating user's preferences..."))
+ .send(new StringMapUnmarshaller());
+ }
+}
diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserProfileServiceClient.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserProfileServiceClient.java
index f1bbad020b..8a331b38c2 100644
--- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserProfileServiceClient.java
+++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserProfileServiceClient.java
@@ -10,8 +10,7 @@
*******************************************************************************/
package org.eclipse.che.ide.api.user;
-import org.eclipse.che.api.promises.client.Promise;
-import org.eclipse.che.api.user.shared.dto.ProfileDescriptor;
+import org.eclipse.che.api.user.shared.dto.ProfileDto;
import org.eclipse.che.ide.rest.AsyncRequestCallback;
import javax.validation.constraints.NotNull;
@@ -29,7 +28,7 @@ public interface UserProfileServiceClient {
*
* @param callback
*/
- void getCurrentProfile(AsyncRequestCallback callback);
+ void getCurrentProfile(AsyncRequestCallback callback);
/**
* Update current user's profile.
@@ -38,7 +37,7 @@ public interface UserProfileServiceClient {
* attributes to update
* @param callback
*/
- void updateCurrentProfile(@NotNull Map updates, AsyncRequestCallback callback);
+ void updateCurrentProfile(@NotNull Map updates, AsyncRequestCallback callback);
/**
* Get profile by id.
@@ -47,26 +46,8 @@ public interface UserProfileServiceClient {
* profile's id
* @param callback
*/
- void getProfileById(@NotNull String id, AsyncRequestCallback callback);
+ void getProfileById(@NotNull String id, AsyncRequestCallback callback);
- /**
- * Get user preferences
- *
- * @param callback
- * which contains some action with user preferences
- * @deprecated use {@link #getPreferences()}
- */
- @Deprecated
- void getPreferences(AsyncRequestCallback> callback);
-
- /**
- * Get user preferences
- *
- * @return the promise which either uses preferences for some actions or rejects with an error
- */
- Promise> getPreferences();
-
- /**
/**
* Update profile.
@@ -77,25 +58,5 @@ public interface UserProfileServiceClient {
* attributes to update
* @param callback
*/
- void updateProfile(@NotNull String id, Map updates, AsyncRequestCallback callback);
-
- /**
- * Update preferences.
- *
- * @param prefsToUpdate
- * preferences to update
- * @param callback
- * which contains some action with user preferences
- * @deprecated use {@link #updatePreferences(Map)}
- */
- @Deprecated
- void updatePreferences(@NotNull Map prefsToUpdate, AsyncRequestCallback> callback);
-
- /**
- * Update preferences.
- *
- * @param prefsToUpdate
- * @return promise which either uses preferences for some actions or rejects with an error
- */
- Promise> updatePreferences(@NotNull Map prefsToUpdate);
+ void updateProfile(@NotNull String id, Map updates, AsyncRequestCallback callback);
}
diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserProfileServiceClientImpl.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserProfileServiceClientImpl.java
index c6d7b6d19b..264f9242b7 100644
--- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserProfileServiceClientImpl.java
+++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserProfileServiceClientImpl.java
@@ -13,7 +13,7 @@ package org.eclipse.che.ide.api.user;
import com.google.inject.Inject;
import org.eclipse.che.api.promises.client.Promise;
-import org.eclipse.che.api.user.shared.dto.ProfileDescriptor;
+import org.eclipse.che.api.user.shared.dto.ProfileDto;
import org.eclipse.che.ide.json.JsonHelper;
import org.eclipse.che.ide.rest.AsyncRequestCallback;
import org.eclipse.che.ide.rest.AsyncRequestFactory;
@@ -35,7 +35,6 @@ import static org.eclipse.che.ide.rest.HTTPHeader.CONTENT_TYPE;
*/
public class UserProfileServiceClientImpl implements UserProfileServiceClient {
private final String PROFILE;
- private final String PREFS;
private final LoaderFactory loaderFactory;
private final AsyncRequestFactory asyncRequestFactory;
@@ -46,12 +45,11 @@ public class UserProfileServiceClientImpl implements UserProfileServiceClient {
this.loaderFactory = loaderFactory;
this.asyncRequestFactory = asyncRequestFactory;
PROFILE = restContext + "/profile/";
- PREFS = PROFILE + "prefs";
}
/** {@inheritDoc} */
@Override
- public void getCurrentProfile(AsyncRequestCallback callback) {
+ public void getCurrentProfile(AsyncRequestCallback callback) {
asyncRequestFactory.createGetRequest(PROFILE)
.header(ACCEPT, APPLICATION_JSON)
.loader(loaderFactory.newLoader("Retrieving current user's profile..."))
@@ -60,7 +58,7 @@ public class UserProfileServiceClientImpl implements UserProfileServiceClient {
/** {@inheritDoc} */
@Override
- public void updateCurrentProfile(@NotNull Map updates, AsyncRequestCallback callback) {
+ public void updateCurrentProfile(@NotNull Map updates, AsyncRequestCallback callback) {
asyncRequestFactory.createPostRequest(PROFILE, null)
.header(ACCEPT, APPLICATION_JSON)
.header(CONTENT_TYPE, APPLICATION_JSON)
@@ -71,7 +69,7 @@ public class UserProfileServiceClientImpl implements UserProfileServiceClient {
/** {@inheritDoc} */
@Override
- public void getProfileById(@NotNull String id, AsyncRequestCallback callback) {
+ public void getProfileById(@NotNull String id, AsyncRequestCallback callback) {
String requestUrl = PROFILE + id;
asyncRequestFactory.createGetRequest(requestUrl)
@@ -80,27 +78,9 @@ public class UserProfileServiceClientImpl implements UserProfileServiceClient {
.send(callback);
}
- @Override
- public void getPreferences(AsyncRequestCallback> callback) {
- asyncRequestFactory.createGetRequest(PREFS)
- .header(ACCEPT, APPLICATION_JSON)
- .header(CONTENT_TYPE, APPLICATION_JSON)
- .loader(loaderFactory.newLoader("Getting user's preferences..."))
- .send(callback);
- }
-
- @Override
- public Promise> getPreferences() {
- return asyncRequestFactory.createGetRequest(PREFS)
- .header(ACCEPT, APPLICATION_JSON)
- .header(CONTENT_TYPE, APPLICATION_JSON)
- .loader(loaderFactory.newLoader("Getting user's preferences..."))
- .send(new StringMapUnmarshaller());
- }
-
/** {@inheritDoc} */
@Override
- public void updateProfile(@NotNull String id, Map updates, AsyncRequestCallback callback) {
+ public void updateProfile(@NotNull String id, Map updates, AsyncRequestCallback callback) {
String requestUrl = PROFILE + id;
asyncRequestFactory.createPostRequest(requestUrl, null)
@@ -110,28 +90,4 @@ public class UserProfileServiceClientImpl implements UserProfileServiceClient {
.loader(loaderFactory.newLoader("Updating user's profile..."))
.send(callback);
}
-
- /** {@inheritDoc} */
- @Override
- public void updatePreferences(@NotNull Map update, AsyncRequestCallback> callback) {
- final String data = JsonHelper.toJson(update);
- asyncRequestFactory.createPostRequest(PREFS, null)
- .header(ACCEPT, APPLICATION_JSON)
- .header(CONTENT_TYPE, APPLICATION_JSON)
- .data(data)
- .loader(loaderFactory.newLoader("Updating user's preferences..."))
- .send(callback);
- }
-
- /** {@inheritDoc} */
- @Override
- public Promise> updatePreferences(@NotNull Map update) {
- final String data = JsonHelper.toJson(update);
- return asyncRequestFactory.createPostRequest(PREFS, null)
- .header(ACCEPT, APPLICATION_JSON)
- .header(CONTENT_TYPE, APPLICATION_JSON)
- .data(data)
- .loader(loaderFactory.newLoader("Updating user's preferences..."))
- .send(new StringMapUnmarshaller());
- }
}
diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserServiceClient.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserServiceClient.java
index 5d84a46e81..19d612de8c 100644
--- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserServiceClient.java
+++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserServiceClient.java
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.eclipse.che.ide.api.user;
-import org.eclipse.che.api.user.shared.dto.UserDescriptor;
+import org.eclipse.che.api.user.shared.dto.UserDto;
import org.eclipse.che.ide.rest.AsyncRequestCallback;
import javax.validation.constraints.NotNull;
@@ -31,14 +31,14 @@ public interface UserServiceClient {
* if true - is temporary user
* @param callback
*/
- void createUser(@NotNull String token, boolean isTemporary, AsyncRequestCallback callback);
+ void createUser(@NotNull String token, boolean isTemporary, AsyncRequestCallback callback);
/**
* Get current user's information.
*
* @param callback
*/
- void getCurrentUser(AsyncRequestCallback callback);
+ void getCurrentUser(AsyncRequestCallback callback);
/**
* Update user's password.
@@ -56,7 +56,7 @@ public interface UserServiceClient {
* user's id
* @param callback
*/
- void getUserById(@NotNull String id, AsyncRequestCallback callback);
+ void getUserById(@NotNull String id, AsyncRequestCallback callback);
/**
* Get user's information by its alias.
@@ -65,7 +65,7 @@ public interface UserServiceClient {
* user's alias
* @param callback
*/
- void getUserByAlias(@NotNull String alias, AsyncRequestCallback callback);
+ void getUserByAlias(@NotNull String alias, AsyncRequestCallback callback);
/**
* Remove user.
diff --git a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserServiceClientImpl.java b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserServiceClientImpl.java
index 804b094055..b2b11f588f 100644
--- a/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserServiceClientImpl.java
+++ b/ide/che-core-ide-api/src/main/java/org/eclipse/che/ide/api/user/UserServiceClientImpl.java
@@ -12,7 +12,7 @@ package org.eclipse.che.ide.api.user;
import com.google.inject.Inject;
-import org.eclipse.che.api.user.shared.dto.UserDescriptor;
+import org.eclipse.che.api.user.shared.dto.UserDto;
import org.eclipse.che.ide.MimeType;
import org.eclipse.che.ide.rest.AsyncRequestCallback;
import org.eclipse.che.ide.rest.AsyncRequestFactory;
@@ -52,7 +52,7 @@ public class UserServiceClientImpl implements UserServiceClient {
/** {@inheritDoc} */
@Override
- public void createUser(@NotNull String token, boolean isTemporary, AsyncRequestCallback callback) {
+ public void createUser(@NotNull String token, boolean isTemporary, AsyncRequestCallback callback) {
StringBuilder requestUrl = new StringBuilder(CREATE);
requestUrl.append("?token=").append(token).append("&temporary=").append(isTemporary);
@@ -64,7 +64,7 @@ public class UserServiceClientImpl implements UserServiceClient {
/** {@inheritDoc} */
@Override
- public void getCurrentUser(AsyncRequestCallback callback) {
+ public void getCurrentUser(AsyncRequestCallback callback) {
asyncRequestFactory.createGetRequest(USER)
.header(ACCEPT, MimeType.APPLICATION_JSON)
@@ -86,7 +86,7 @@ public class UserServiceClientImpl implements UserServiceClient {
/** {@inheritDoc} */
@Override
- public void getUserById(@NotNull String id, AsyncRequestCallback callback) {
+ public void getUserById(@NotNull String id, AsyncRequestCallback callback) {
String requestUrl = USER + id;
asyncRequestFactory.createGetRequest(requestUrl)
@@ -97,7 +97,7 @@ public class UserServiceClientImpl implements UserServiceClient {
/** {@inheritDoc} */
@Override
- public void getUserByAlias(@NotNull String alias, AsyncRequestCallback callback) {
+ public void getUserByAlias(@NotNull String alias, AsyncRequestCallback callback) {
String requestUrl = FIND + "?alias=" + alias;
asyncRequestFactory.createGetRequest(requestUrl)
diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/core/CoreGinModule.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/core/CoreGinModule.java
index db7f11f6e8..903ed9fd20 100644
--- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/core/CoreGinModule.java
+++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/core/CoreGinModule.java
@@ -41,6 +41,8 @@ import org.eclipse.che.ide.api.project.ProjectTypeServiceClient;
import org.eclipse.che.ide.api.project.ProjectTypeServiceClientImpl;
import org.eclipse.che.ide.api.ssh.SshServiceClient;
import org.eclipse.che.ide.api.ssh.SshServiceClientImpl;
+import org.eclipse.che.ide.api.user.PreferencesServiceClient;
+import org.eclipse.che.ide.api.user.PreferencesServiceClientImpl;
import org.eclipse.che.ide.api.user.UserProfileServiceClient;
import org.eclipse.che.ide.api.user.UserProfileServiceClientImpl;
import org.eclipse.che.ide.api.user.UserServiceClient;
@@ -333,6 +335,7 @@ public class CoreGinModule extends AbstractGinModule {
private void configurePlatformApiGwtClients() {
bind(UserServiceClient.class).to(UserServiceClientImpl.class).in(Singleton.class);
bind(UserProfileServiceClient.class).to(UserProfileServiceClientImpl.class).in(Singleton.class);
+ bind(PreferencesServiceClient.class).to(PreferencesServiceClientImpl.class).in(Singleton.class);
bind(GitServiceClient.class).to(GitServiceClientImpl.class).in(Singleton.class);
bind(OAuthServiceClient.class).to(OAuthServiceClientImpl.class).in(Singleton.class);
bind(FactoryServiceClient.class).to(FactoryServiceClientImpl.class).in(Singleton.class);
diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/core/ProfileComponent.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/core/ProfileComponent.java
index c37127aff5..b55fd2c3d1 100644
--- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/core/ProfileComponent.java
+++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/core/ProfileComponent.java
@@ -10,8 +10,8 @@
*******************************************************************************/
package org.eclipse.che.ide.core;
+import org.eclipse.che.api.user.shared.dto.ProfileDto;
import org.eclipse.che.ide.api.user.UserProfileServiceClient;
-import org.eclipse.che.api.user.shared.dto.ProfileDescriptor;
import org.eclipse.che.ide.api.app.CurrentUser;
import org.eclipse.che.ide.api.component.Component;
import org.eclipse.che.ide.rest.AsyncRequestCallback;
@@ -40,10 +40,10 @@ public class ProfileComponent implements Component {
@Override
public void start(final Callback callback) {
- AsyncRequestCallback asyncRequestCallback = new AsyncRequestCallback(
- dtoUnmarshallerFactory.newUnmarshaller(ProfileDescriptor.class)) {
+ AsyncRequestCallback asyncRequestCallback = new AsyncRequestCallback(
+ dtoUnmarshallerFactory.newUnmarshaller(ProfileDto.class)) {
@Override
- protected void onSuccess(final ProfileDescriptor profile) {
+ protected void onSuccess(final ProfileDto profile) {
currentUser.setProfile(profile);
callback.onSuccess(ProfileComponent.this);
}
diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/preferences/PreferencesManagerImpl.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/preferences/PreferencesManagerImpl.java
index 5c73c8ee24..ebddb5b45b 100644
--- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/preferences/PreferencesManagerImpl.java
+++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/preferences/PreferencesManagerImpl.java
@@ -17,7 +17,7 @@ import org.eclipse.che.api.promises.client.Function;
import org.eclipse.che.api.promises.client.FunctionException;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.js.Promises;
-import org.eclipse.che.ide.api.user.UserProfileServiceClient;
+import org.eclipse.che.ide.api.user.PreferencesServiceClient;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.ide.api.preferences.PreferencesManager;
@@ -31,22 +31,22 @@ import java.util.Map;
*/
@Singleton
public class PreferencesManagerImpl implements PreferencesManager {
- private final UserProfileServiceClient userProfileService;
- private final Map changedPreferences;
+ private final Map changedPreferences;
+ private final PreferencesServiceClient preferencesService;
private Map persistedPreferences;
/**
* Create preferences manager
*
- * @param userProfileService
+ * @param preferencesService
* user preference service client
*/
@Inject
- protected PreferencesManagerImpl(UserProfileServiceClient userProfileService) {
+ protected PreferencesManagerImpl(PreferencesServiceClient preferencesService) {
this.persistedPreferences = new HashMap<>();
this.changedPreferences = new HashMap<>();
- this.userProfileService = userProfileService;
+ this.preferencesService = preferencesService;
}
/** {@inheritDoc} */
@@ -72,9 +72,9 @@ public class PreferencesManagerImpl implements PreferencesManager {
return Promises.resolve(null);
}
- return userProfileService.updatePreferences(changedPreferences).thenPromise(new Function, Promise>() {
+ return preferencesService.updatePreferences(changedPreferences).thenPromise(new Function, Promise>() {
@Override
- public Promise apply(Map result) throws FunctionException {
+ public Promise apply(Map result) throws FunctionException {
persistedPreferences.putAll(changedPreferences);
changedPreferences.clear();
return Promises.resolve(null);
@@ -85,7 +85,7 @@ public class PreferencesManagerImpl implements PreferencesManager {
/** {@inheritDoc} */
@Override
public Promise> loadPreferences() {
- return userProfileService.getPreferences().then(new Function, Map>() {
+ return preferencesService.getPreferences().then(new Function, Map>() {
@Override
public Map apply(Map preferences) throws FunctionException {
persistedPreferences = preferences;
diff --git a/plugins/plugin-docker/che-plugin-docker-client/src/main/java/org/eclipse/che/plugin/docker/client/UserSpecificDockerRegistryCredentialsProvider.java b/plugins/plugin-docker/che-plugin-docker-client/src/main/java/org/eclipse/che/plugin/docker/client/UserSpecificDockerRegistryCredentialsProvider.java
index 9ce739728f..42aaadbc08 100644
--- a/plugins/plugin-docker/che-plugin-docker-client/src/main/java/org/eclipse/che/plugin/docker/client/UserSpecificDockerRegistryCredentialsProvider.java
+++ b/plugins/plugin-docker/che-plugin-docker-client/src/main/java/org/eclipse/che/plugin/docker/client/UserSpecificDockerRegistryCredentialsProvider.java
@@ -13,7 +13,7 @@ package org.eclipse.che.plugin.docker.client;
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
+import org.eclipse.che.api.user.server.PreferenceManager;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.dto.server.DtoFactory;
@@ -35,11 +35,11 @@ public class UserSpecificDockerRegistryCredentialsProvider {
private static final Logger LOG = LoggerFactory.getLogger(UserSpecificDockerRegistryCredentialsProvider.class);
- private PreferenceDao preferenceDao;
+ private PreferenceManager preferenceManager;
@Inject
- public UserSpecificDockerRegistryCredentialsProvider(PreferenceDao preferenceDao) {
- this.preferenceDao = preferenceDao;
+ public UserSpecificDockerRegistryCredentialsProvider(PreferenceManager preferenceManager) {
+ this.preferenceManager = preferenceManager;
}
/**
@@ -52,11 +52,11 @@ public class UserSpecificDockerRegistryCredentialsProvider {
@Nullable
public AuthConfigs getCredentials() {
try {
- String encodedCredentials = preferenceDao.getPreferences(EnvironmentContext.getCurrent()
- .getSubject()
- .getUserId(),
- DOCKER_REGISTRY_CREDENTIALS_KEY)
- .get(DOCKER_REGISTRY_CREDENTIALS_KEY);
+ String encodedCredentials = preferenceManager.find(EnvironmentContext.getCurrent()
+ .getSubject()
+ .getUserId(),
+ DOCKER_REGISTRY_CREDENTIALS_KEY)
+ .get(DOCKER_REGISTRY_CREDENTIALS_KEY);
String credentials = encodedCredentials != null ? new String(Base64.getDecoder().decode(encodedCredentials), "UTF-8") : "{}";
return DtoFactory.newDto(AuthConfigs.class).withConfigs(
diff --git a/plugins/plugin-docker/che-plugin-docker-client/src/test/java/org/eclipse/che/plugin/docker/client/UserSpecificDockerRegistryCredentialsProviderTest.java b/plugins/plugin-docker/che-plugin-docker-client/src/test/java/org/eclipse/che/plugin/docker/client/UserSpecificDockerRegistryCredentialsProviderTest.java
index bd645ba019..8e5c7e1f5d 100644
--- a/plugins/plugin-docker/che-plugin-docker-client/src/test/java/org/eclipse/che/plugin/docker/client/UserSpecificDockerRegistryCredentialsProviderTest.java
+++ b/plugins/plugin-docker/che-plugin-docker-client/src/test/java/org/eclipse/che/plugin/docker/client/UserSpecificDockerRegistryCredentialsProviderTest.java
@@ -11,7 +11,7 @@
package org.eclipse.che.plugin.docker.client;
import org.eclipse.che.api.core.ServerException;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
+import org.eclipse.che.api.user.server.PreferenceManager;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.SubjectImpl;
import org.eclipse.che.dto.server.DtoFactory;
@@ -41,13 +41,13 @@ public class UserSpecificDockerRegistryCredentialsProviderTest {
private static final String DOCKER_REGISTRY_CREDENTIALS_KEY = "dockerCredentials";
@Mock
- private PreferenceDao preferenceDao;
+ private PreferenceManager preferenceManager;
private UserSpecificDockerRegistryCredentialsProvider dockerCredentials;
@BeforeClass
private void before() {
- dockerCredentials = new UserSpecificDockerRegistryCredentialsProvider(preferenceDao);
+ dockerCredentials = new UserSpecificDockerRegistryCredentialsProvider(preferenceManager);
}
@Test
@@ -101,7 +101,7 @@ public class UserSpecificDockerRegistryCredentialsProviderTest {
preferences.put(DOCKER_REGISTRY_CREDENTIALS_KEY, base64encodedCredentials);
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("name", "id", "token1234", false));
- when(preferenceDao.getPreferences(anyObject(), anyObject())).thenReturn(preferences);
+ when(preferenceManager.find(anyObject(), anyObject())).thenReturn(preferences);
}
}
diff --git a/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/integration/ServiceTest.java b/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/integration/ServiceTest.java
index f38d7ccd26..8a4ac374a2 100644
--- a/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/integration/ServiceTest.java
+++ b/plugins/plugin-docker/che-plugin-docker-machine/src/test/java/org/eclipse/che/plugin/docker/machine/integration/ServiceTest.java
@@ -19,7 +19,7 @@ import org.eclipse.che.api.machine.server.MachineInstanceProviders;
import org.eclipse.che.api.machine.server.MachineManager;
import org.eclipse.che.api.machine.server.MachineRegistry;
import org.eclipse.che.api.machine.server.MachineService;
-import org.eclipse.che.api.machine.server.dao.SnapshotDao;
+import org.eclipse.che.api.machine.server.spi.SnapshotDao;
import org.eclipse.che.api.machine.server.exception.MachineException;
import org.eclipse.che.api.machine.server.spi.impl.SnapshotImpl;
import org.eclipse.che.api.machine.server.model.impl.MachineImpl;
@@ -128,7 +128,7 @@ public class ServiceTest {
.withHostConfig(new HostConfig().withPortBindings(
singletonMap("5000/tcp", new PortBinding[]{new PortBinding().withHostPort("5000")})));
- registryContainerId = docker.createContainer(containerConfig, null).getId();
+ registryContainerId = docker.createContainer(containerConfig, null).getUserId();
docker.startContainer(registryContainerId, null);
}
@@ -192,7 +192,7 @@ public class ServiceTest {
}
@Override
- public String getId() {
+ public String getUserId() {
return USER;
}
@@ -208,7 +208,7 @@ public class ServiceTest {
@AfterMethod
public void tearDown() throws Exception {
for (MachineStateImpl machine : new ArrayList<>(machineManager.getMachinesStates())) {
- machineManager.destroy(machine.getId(), false);
+ machineManager.destroy(machine.getUserId(), false);
}
EnvironmentContext.reset();
}
@@ -224,7 +224,7 @@ public class ServiceTest {
.withType("Dockerfile")
.withScript("FROM ubuntu\nCMD tail -f /dev/null\n")));
- waitMachineIsRunning(machine.getId());
+ waitMachineIsRunning(machine.getUserId());
}
@Test(dependsOnMethods = "saveSnapshotTest", enabled = false)
@@ -242,27 +242,27 @@ public class ServiceTest {
final MachineStateDescriptor machine = machineService
.createMachineFromSnapshot(newDto(SnapshotMachineCreationMetadata.class).withSnapshotId(SNAPSHOT_ID));
- waitMachineIsRunning(machine.getId());
+ waitMachineIsRunning(machine.getUserId());
}
@Test
public void getMachineTest() throws Exception {
final MachineImpl machine = createMachineAndWaitRunningState();
- final MachineDescriptor machineById = machineService.getMachineById(machine.getId());
+ final MachineDescriptor machineById = machineService.getMachineById(machine.getUserId());
- assertEquals(machineById.getId(), machine.getId());
+ assertEquals(machineById.getUserId(), machine.getUserId());
}
@Test
public void getMachinesTest() throws Exception {
Set expected = new HashSet<>();
- expected.add(createMachineAndWaitRunningState().getId());
- expected.add(createMachineAndWaitRunningState().getId());
+ expected.add(createMachineAndWaitRunningState().getUserId());
+ expected.add(createMachineAndWaitRunningState().getUserId());
Set actual = machineManager.getMachinesStates()
.stream()
- .map(MachineImpl::getId)
+ .map(MachineImpl::getUserId)
.collect(Collectors.toSet());
assertEquals(actual, expected);
}
@@ -271,14 +271,14 @@ public class ServiceTest {
public void destroyMachineTest() throws Exception {
final MachineImpl machine = createMachineAndWaitRunningState();
- machineService.destroyMachine(machine.getId());
+ machineService.destroyMachine(machine.getUserId());
- assertEquals(machineService.getMachineStateById(machine.getId()).getStatus(), MachineStatus.DESTROYING);
+ assertEquals(machineService.getMachineStateById(machine.getUserId()).getStatus(), MachineStatus.DESTROYING);
int counter = 0;
while (++counter < 1000) {
try {
- machineManager.getMachine(machine.getId());
+ machineManager.getMachine(machine.getUserId());
} catch (NotFoundException e) {
return;
}
@@ -293,7 +293,7 @@ public class ServiceTest {
// use machine manager instead of machine service because it returns future with snapshot
// that allows check operation result
- final SnapshotImpl snapshot = machineManager.save(machine.getId(), USER, "test description");
+ final SnapshotImpl snapshot = machineManager.save(machine.getUserId(), USER, "test description");
for (int i = 0; snapshot.getInstanceKey() == null && i < 10; ++i) {
Thread.sleep(500);
@@ -337,13 +337,13 @@ public class ServiceTest {
final MachineImpl machine = createMachineAndWaitRunningState();
String commandInMachine = "echo \"command in machine\" && tail -f /dev/null";
- machineService.executeCommandInMachine(machine.getId(),
+ machineService.executeCommandInMachine(machine.getUserId(),
DtoFactory.newDto(CommandDto.class).withCommandLine(commandInMachine),
null);
Thread.sleep(500);
- final List processes = machineService.getProcesses(machine.getId());
+ final List processes = machineService.getProcesses(machine.getUserId());
assertEquals(processes.size(), 1);
assertEquals(processes.get(0).getCommandLine(), commandInMachine);
}
@@ -357,12 +357,12 @@ public class ServiceTest {
commands.add("sleep 10000");
for (String command : commands) {
- machineService.executeCommandInMachine(machine.getId(), DtoFactory.newDto(CommandDto.class).withCommandLine(command), null);
+ machineService.executeCommandInMachine(machine.getUserId(), DtoFactory.newDto(CommandDto.class).withCommandLine(command), null);
}
Thread.sleep(500);
- final List processes = machineService.getProcesses(machine.getId());
+ final List processes = machineService.getProcesses(machine.getUserId());
assertEquals(processes.size(), 2);
Set actualCommandLines = new HashSet<>(2);
for (MachineProcessDto process : processes) {
@@ -377,19 +377,19 @@ public class ServiceTest {
final MachineImpl machine = createMachineAndWaitRunningState();
String commandInMachine = "echo \"command in machine\" && tail -f /dev/null";
- machineService.executeCommandInMachine(machine.getId(),
+ machineService.executeCommandInMachine(machine.getUserId(),
DtoFactory.newDto(CommandDto.class).withCommandLine(commandInMachine),
null);
Thread.sleep(500);
- final List processes = machineService.getProcesses(machine.getId());
+ final List processes = machineService.getProcesses(machine.getUserId());
assertEquals(processes.size(), 1);
assertEquals(processes.get(0).getCommandLine(), commandInMachine);
- machineService.stopProcess(machine.getId(), processes.get(0).getPid());
+ machineService.stopProcess(machine.getUserId(), processes.get(0).getPid());
- assertTrue(machineService.getProcesses(machine.getId()).isEmpty());
+ assertTrue(machineService.getProcesses(machine.getUserId()).isEmpty());
}
@Test(expectedExceptions = NotFoundException.class, expectedExceptionsMessageRegExp = "Process with pid .* not found")
@@ -397,17 +397,17 @@ public class ServiceTest {
final MachineImpl machine = createMachineAndWaitRunningState();
String commandInMachine = "echo \"command in machine\" && tail -f /dev/null";
- machineService.executeCommandInMachine(machine.getId(),
+ machineService.executeCommandInMachine(machine.getUserId(),
DtoFactory.newDto(CommandDto.class).withCommandLine(commandInMachine),
null);
Thread.sleep(500);
- final List processes = machineService.getProcesses(machine.getId());
+ final List processes = machineService.getProcesses(machine.getUserId());
assertEquals(processes.size(), 1);
assertEquals(processes.get(0).getCommandLine(), commandInMachine);
- machineService.stopProcess(machine.getId(), processes.get(0).getPid() + 100);
+ machineService.stopProcess(machine.getUserId(), processes.get(0).getPid() + 100);
}
private MachineImpl createMachineAndWaitRunningState() throws Exception {
@@ -423,7 +423,7 @@ public class ServiceTest {
.withDev(false)
.withDisplayName("displayName" + System.currentTimeMillis())
, false);
- waitMachineIsRunning(machine.getId());
+ waitMachineIsRunning(machine.getUserId());
return machine;
}
diff --git a/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/authenticator/GitHubAuthenticatorImpl.java b/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/authenticator/GitHubAuthenticatorImpl.java
index 2fdbff90b6..9ff12bd033 100644
--- a/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/authenticator/GitHubAuthenticatorImpl.java
+++ b/plugins/plugin-github/che-plugin-github-ide/src/main/java/org/eclipse/che/plugin/github/ide/authenticator/GitHubAuthenticatorImpl.java
@@ -142,7 +142,7 @@ public class GitHubAuthenticatorImpl implements OAuth2Authenticator, OAuthCallba
private void generateSshKeys(final OAuthStatus authStatus) {
final SshKeyUploader githubKeyUploader = registry.getUploader(GITHUB_HOST);
if (githubKeyUploader != null) {
- String userId = appContext.getCurrentUser().getProfile().getId();
+ String userId = appContext.getCurrentUser().getProfile().getUserId();
githubKeyUploader.uploadKey(userId, new AsyncCallback() {
@Override
public void onSuccess(Void result) {
diff --git a/plugins/plugin-github/che-plugin-github-ide/src/test/java/org/eclipse/che/plugin/github/ide/authenticator/GitHubAuthenticatorImplTest.java b/plugins/plugin-github/che-plugin-github-ide/src/test/java/org/eclipse/che/plugin/github/ide/authenticator/GitHubAuthenticatorImplTest.java
index 06cc2fb719..690f4c370e 100644
--- a/plugins/plugin-github/che-plugin-github-ide/src/test/java/org/eclipse/che/plugin/github/ide/authenticator/GitHubAuthenticatorImplTest.java
+++ b/plugins/plugin-github/che-plugin-github-ide/src/test/java/org/eclipse/che/plugin/github/ide/authenticator/GitHubAuthenticatorImplTest.java
@@ -16,7 +16,8 @@ import com.google.gwtmockito.GwtMockitoTestRunner;
import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.ssh.shared.dto.SshPairDto;
-import org.eclipse.che.api.user.shared.dto.ProfileDescriptor;
+import org.eclipse.che.api.user.shared.dto.ProfileDto;
+import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.app.CurrentUser;
import org.eclipse.che.ide.api.dialogs.ConfirmCallback;
@@ -141,14 +142,14 @@ public class GitHubAuthenticatorImplTest {
SshKeyUploader sshKeyUploader = mock(SshKeyUploader.class);
CurrentUser user = mock(CurrentUser.class);
- ProfileDescriptor profile = mock(ProfileDescriptor.class);
+ ProfileDto profile = mock(ProfileDto.class);
when(view.isGenerateKeysSelected()).thenReturn(true);
when(registry.getUploader(GITHUB_HOST)).thenReturn(sshKeyUploader);
when(appContext.getCurrentUser()).thenReturn(user);
when(user.getProfile()).thenReturn(profile);
- when(profile.getId()).thenReturn(userId);
+ when(profile.getUserId()).thenReturn(userId);
gitHubAuthenticator.onAuthenticated(authStatus);
@@ -164,11 +165,11 @@ public class GitHubAuthenticatorImplTest {
OAuthStatus authStatus = mock(OAuthStatus.class);
CurrentUser user = mock(CurrentUser.class);
- ProfileDescriptor profile = mock(ProfileDescriptor.class);
+ ProfileDto profile = mock(ProfileDto.class);
when(view.isGenerateKeysSelected()).thenReturn(false);
when(appContext.getCurrentUser()).thenReturn(user);
when(user.getProfile()).thenReturn(profile);
- when(profile.getId()).thenReturn(userId);
+ when(profile.getUserId()).thenReturn(userId);
gitHubAuthenticator.authenticate(null, getCallBack());
gitHubAuthenticator.onAuthenticated(authStatus);
@@ -184,13 +185,13 @@ public class GitHubAuthenticatorImplTest {
SshKeyUploader keyProvider = mock(SshKeyUploader.class);
CurrentUser user = mock(CurrentUser.class);
- ProfileDescriptor profile = mock(ProfileDescriptor.class);
+ ProfileDto profile = mock(ProfileDto.class);
when(view.isGenerateKeysSelected()).thenReturn(true);
when(registry.getUploader(GITHUB_HOST)).thenReturn(keyProvider);
when(appContext.getCurrentUser()).thenReturn(user);
when(user.getProfile()).thenReturn(profile);
- when(profile.getId()).thenReturn(userId);
+ when(profile.getUserId()).thenReturn(userId);
gitHubAuthenticator.authenticate(null, getCallBack());
gitHubAuthenticator.onAuthenticated(authStatus);
@@ -213,14 +214,14 @@ public class GitHubAuthenticatorImplTest {
SshKeyUploader keyProvider = mock(SshKeyUploader.class);
CurrentUser user = mock(CurrentUser.class);
- ProfileDescriptor profile = mock(ProfileDescriptor.class);
+ ProfileDto profile = mock(ProfileDto.class);
MessageDialog messageDialog = mock(MessageDialog.class);
when(view.isGenerateKeysSelected()).thenReturn(true);
when(registry.getUploader(GITHUB_HOST)).thenReturn(keyProvider);
when(appContext.getCurrentUser()).thenReturn(user);
when(user.getProfile()).thenReturn(profile);
- when(profile.getId()).thenReturn(userId);
+ when(profile.getUserId()).thenReturn(userId);
when(dialogFactory.createMessageDialog(anyString(), anyString(), Matchers.anyObject())).thenReturn(messageDialog);
gitHubAuthenticator.authenticate(null, getCallBack());
@@ -248,14 +249,14 @@ public class GitHubAuthenticatorImplTest {
SshKeyUploader keyUploader = mock(SshKeyUploader.class);
CurrentUser user = mock(CurrentUser.class);
- ProfileDescriptor profile = mock(ProfileDescriptor.class);
+ ProfileDto profile = mock(ProfileDto.class);
MessageDialog messageDialog = mock(MessageDialog.class);
when(view.isGenerateKeysSelected()).thenReturn(true);
when(registry.getUploader(GITHUB_HOST)).thenReturn(keyUploader);
when(appContext.getCurrentUser()).thenReturn(user);
when(user.getProfile()).thenReturn(profile);
- when(profile.getId()).thenReturn(userId);
+ when(profile.getUserId()).thenReturn(userId);
when(dialogFactory.createMessageDialog(anyString(), anyString(), Matchers.anyObject())).thenReturn(messageDialog);
when(pair.getName()).thenReturn(GITHUB_HOST);
when(pair.getService()).thenReturn(SshKeyManagerPresenter.VCS_SSH_SERVICE);
diff --git a/plugins/plugin-github/che-plugin-github-ide/src/test/java/org/eclipse/che/plugin/github/ide/importer/page/GithubImporterPagePresenterTest.java b/plugins/plugin-github/che-plugin-github-ide/src/test/java/org/eclipse/che/plugin/github/ide/importer/page/GithubImporterPagePresenterTest.java
index 4d9aa2b651..807b13fb58 100644
--- a/plugins/plugin-github/che-plugin-github-ide/src/test/java/org/eclipse/che/plugin/github/ide/importer/page/GithubImporterPagePresenterTest.java
+++ b/plugins/plugin-github/che-plugin-github-ide/src/test/java/org/eclipse/che/plugin/github/ide/importer/page/GithubImporterPagePresenterTest.java
@@ -20,7 +20,9 @@ import org.eclipse.che.api.project.shared.dto.ProjectImporterDescriptor;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.PromiseError;
import org.eclipse.che.ide.api.user.UserServiceClient;
-import org.eclipse.che.api.user.shared.dto.ProfileDescriptor;
+import org.eclipse.che.api.user.shared.dto.ProfileDto;
+import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
+import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.app.CurrentUser;
import org.eclipse.che.ide.api.notification.NotificationManager;
@@ -500,11 +502,11 @@ public class GithubImporterPagePresenterTest {
public void onLoadRepoClickedWhenAuthorizeIsFailed() throws Exception {
String userId = "userId";
CurrentUser user = mock(CurrentUser.class);
- ProfileDescriptor profile = mock(ProfileDescriptor.class);
+ ProfileDto profile = mock(ProfileDto.class);
when(appContext.getCurrentUser()).thenReturn(user);
when(user.getProfile()).thenReturn(profile);
- when(profile.getId()).thenReturn(userId);
+ when(profile.getUserId()).thenReturn(userId);
final Throwable exception = mock(UnauthorizedException.class);
@@ -553,12 +555,12 @@ public class GithubImporterPagePresenterTest {
final Throwable exception = mock(UnauthorizedException.class);
String userId = "userId";
CurrentUser user = mock(CurrentUser.class);
- ProfileDescriptor profile = mock(ProfileDescriptor.class);
+ ProfileDto profile = mock(ProfileDto.class);
doReturn(exception).when(promiseError).getCause();
when(appContext.getCurrentUser()).thenReturn(user);
when(user.getProfile()).thenReturn(profile);
- when(profile.getId()).thenReturn(userId);
+ when(profile.getUserId()).thenReturn(userId);
presenter.onLoadRepoClicked();
diff --git a/plugins/plugin-java/che-plugin-java-ext-jdt/org-eclipse-ui-ide/src/main/java/org/eclipse/ui/IWorkingSet.java b/plugins/plugin-java/che-plugin-java-ext-jdt/org-eclipse-ui-ide/src/main/java/org/eclipse/ui/IWorkingSet.java
index 00b1556499..b0be467f4e 100644
--- a/plugins/plugin-java/che-plugin-java-ext-jdt/org-eclipse-ui-ide/src/main/java/org/eclipse/ui/IWorkingSet.java
+++ b/plugins/plugin-java/che-plugin-java-ext-jdt/org-eclipse-ui-ide/src/main/java/org/eclipse/ui/IWorkingSet.java
@@ -53,9 +53,9 @@ public interface IWorkingSet extends /*IPersistableElement,*/ IAdaptable {
* Currently, this is one of the icons specified in the extensions
* of the org.eclipse.ui.workingSets extension point.
* The extension is identified using the value returned by
- * getId().
+ * getUserId().
* Returns null if no icon has been specified in the
- * extension or if getId() returns null.
+ * extension or if getUserId() returns null.
*
* @return the working set icon or null.
* @since 2.1
@@ -69,9 +69,9 @@ public interface IWorkingSet extends /*IPersistableElement,*/ IAdaptable {
* Currently, this is one of the icons specified in the extensions
* of the org.eclipse.ui.workingSets extension point.
* The extension is identified using the value returned by
- * getId().
+ * getUserId().
* Returns null if no icon has been specified in the
- * extension or if getId() returns null.
+ * extension or if getUserId() returns null.
*
* @return the working set icon or null.
* @since 3.3
diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/perspective/widgets/machine/appliance/sufficientinfo/MachineInfoPresenter.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/perspective/widgets/machine/appliance/sufficientinfo/MachineInfoPresenter.java
index 287a373223..19b4a160b4 100644
--- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/perspective/widgets/machine/appliance/sufficientinfo/MachineInfoPresenter.java
+++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/main/java/org/eclipse/che/ide/extension/machine/client/perspective/widgets/machine/appliance/sufficientinfo/MachineInfoPresenter.java
@@ -17,8 +17,8 @@ import com.google.inject.Inject;
import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.OperationException;
import org.eclipse.che.api.promises.client.PromiseError;
+import org.eclipse.che.api.user.shared.dto.ProfileDto;
import org.eclipse.che.ide.api.user.UserProfileServiceClient;
-import org.eclipse.che.api.user.shared.dto.ProfileDescriptor;
import org.eclipse.che.ide.api.workspace.WorkspaceServiceClient;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto;
import org.eclipse.che.ide.extension.machine.client.machine.Machine;
@@ -66,11 +66,11 @@ public class MachineInfoPresenter implements TabPresenter {
*/
public void update(@NotNull Machine machine) {
- Unmarshallable profileUnMarshaller = unmarshallerFactory.newUnmarshaller(ProfileDescriptor.class);
+ Unmarshallable profileUnMarshaller = unmarshallerFactory.newUnmarshaller(ProfileDto.class);
- userProfile.getCurrentProfile(new AsyncRequestCallback(profileUnMarshaller) {
+ userProfile.getCurrentProfile(new AsyncRequestCallback(profileUnMarshaller) {
@Override
- protected void onSuccess(ProfileDescriptor result) {
+ protected void onSuccess(ProfileDto result) {
Map attributes = result.getAttributes();
String firstName = attributes.get(FIRST_NAME_KEY);
diff --git a/plugins/plugin-machine/che-plugin-machine-ext-client/src/test/java/org/eclipse/che/ide/extension/machine/client/perspective/widgets/machine/appliance/sufficientinfo/MachineInfoPresenterTest.java b/plugins/plugin-machine/che-plugin-machine-ext-client/src/test/java/org/eclipse/che/ide/extension/machine/client/perspective/widgets/machine/appliance/sufficientinfo/MachineInfoPresenterTest.java
index aa4bd503cd..40270ba6f6 100644
--- a/plugins/plugin-machine/che-plugin-machine-ext-client/src/test/java/org/eclipse/che/ide/extension/machine/client/perspective/widgets/machine/appliance/sufficientinfo/MachineInfoPresenterTest.java
+++ b/plugins/plugin-machine/che-plugin-machine-ext-client/src/test/java/org/eclipse/che/ide/extension/machine/client/perspective/widgets/machine/appliance/sufficientinfo/MachineInfoPresenterTest.java
@@ -13,8 +13,8 @@ package org.eclipse.che.ide.extension.machine.client.perspective.widgets.machine
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import org.eclipse.che.api.promises.client.Promise;
+import org.eclipse.che.api.user.shared.dto.ProfileDto;
import org.eclipse.che.ide.api.user.UserProfileServiceClient;
-import org.eclipse.che.api.user.shared.dto.ProfileDescriptor;
import org.eclipse.che.ide.api.workspace.WorkspaceServiceClient;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto;
@@ -62,22 +62,22 @@ public class MachineInfoPresenterTest {
//additional mocks
@Mock
- private Machine machine;
+ private Machine machine;
@Mock
- private AcceptsOneWidget container;
+ private AcceptsOneWidget container;
@Mock
- private Unmarshallable profileUnmarshaller;
+ private Unmarshallable profileUnmarshaller;
@Mock
- private Unmarshallable wsUnmarshaller;
+ private Unmarshallable wsUnmarshaller;
@Mock
- private ProfileDescriptor profileDescriptor;
+ private ProfileDto profileDescriptor;
@Mock
private WorkspaceDto wsDescriptor;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Promise promise;
@Captor
- private ArgumentCaptor> profileCaptor;
+ private ArgumentCaptor> profileCaptor;
@Captor
private ArgumentCaptor> wsCaptor;
@@ -88,7 +88,7 @@ public class MachineInfoPresenterTest {
public void setUp() {
when(machine.getWorkspaceId()).thenReturn(SOME_TEXT);
- when(unmarshallerFactory.newUnmarshaller(ProfileDescriptor.class)).thenReturn(profileUnmarshaller);
+ when(unmarshallerFactory.newUnmarshaller(ProfileDto.class)).thenReturn(profileUnmarshaller);
when(unmarshallerFactory.newUnmarshaller(WorkspaceDto.class)).thenReturn(wsUnmarshaller);
}
@@ -98,9 +98,9 @@ public class MachineInfoPresenterTest {
presenter.update(machine);
- verify(unmarshallerFactory).newUnmarshaller(ProfileDescriptor.class);
+ verify(unmarshallerFactory).newUnmarshaller(ProfileDto.class);
- verify(userProfile).getCurrentProfile(Matchers.>anyObject());
+ verify(userProfile).getCurrentProfile(Matchers.>anyObject());
verify(machine).getWorkspaceId();
verify(wsService).getWorkspace(eq(SOME_TEXT));
@@ -119,7 +119,7 @@ public class MachineInfoPresenterTest {
presenter.update(machine);
verify(userProfile).getCurrentProfile(profileCaptor.capture());
- AsyncRequestCallback callback = profileCaptor.getValue();
+ AsyncRequestCallback callback = profileCaptor.getValue();
//noinspection NonJREEmulationClassesInClientCode
Method method = callback.getClass().getDeclaredMethod("onSuccess", Object.class);
@@ -144,7 +144,7 @@ public class MachineInfoPresenterTest {
presenter.update(machine);
verify(userProfile).getCurrentProfile(profileCaptor.capture());
- AsyncRequestCallback callback = profileCaptor.getValue();
+ AsyncRequestCallback callback = profileCaptor.getValue();
//noinspection NonJREEmulationClassesInClientCode
Method method = callback.getClass().getDeclaredMethod("onSuccess", Object.class);
diff --git a/plugins/plugin-ssh-key/che-plugin-ssh-key-ide/src/main/java/org/eclipse/che/plugin/ssh/key/client/manage/SshKeyManagerPresenter.java b/plugins/plugin-ssh-key/che-plugin-ssh-key-ide/src/main/java/org/eclipse/che/plugin/ssh/key/client/manage/SshKeyManagerPresenter.java
index 3ca65b0e1b..dc90af0c2d 100644
--- a/plugins/plugin-ssh-key/che-plugin-ssh-key-ide/src/main/java/org/eclipse/che/plugin/ssh/key/client/manage/SshKeyManagerPresenter.java
+++ b/plugins/plugin-ssh-key/che-plugin-ssh-key-ide/src/main/java/org/eclipse/che/plugin/ssh/key/client/manage/SshKeyManagerPresenter.java
@@ -178,7 +178,7 @@ public class SshKeyManagerPresenter extends AbstractPreferencePagePresenter impl
CurrentUser user = appContext.getCurrentUser();
final SshKeyUploader githubUploader = registry.getUploaders().get(GITHUB_HOST);
if (user != null && githubUploader != null) {
- githubUploader.uploadKey(user.getProfile().getId(), new AsyncCallback() {
+ githubUploader.uploadKey(user.getProfile().getUserId(), new AsyncCallback() {
@Override
public void onSuccess(Void result) {
refreshKeys();
diff --git a/plugins/plugin-svn/che-plugin-svn-ext-server/src/main/java/org/eclipse/che/plugin/svn/server/credentials/CurrentUserPreferencesAccessImpl.java b/plugins/plugin-svn/che-plugin-svn-ext-server/src/main/java/org/eclipse/che/plugin/svn/server/credentials/CurrentUserPreferencesAccessImpl.java
index 43f3302c9c..71db6d5177 100644
--- a/plugins/plugin-svn/che-plugin-svn-ext-server/src/main/java/org/eclipse/che/plugin/svn/server/credentials/CurrentUserPreferencesAccessImpl.java
+++ b/plugins/plugin-svn/che-plugin-svn-ext-server/src/main/java/org/eclipse/che/plugin/svn/server/credentials/CurrentUserPreferencesAccessImpl.java
@@ -10,9 +10,8 @@
*******************************************************************************/
package org.eclipse.che.plugin.svn.server.credentials;
-import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
@@ -45,7 +44,7 @@ public class CurrentUserPreferencesAccessImpl implements CurrentUserPreferencesA
content.put(key, value);
try {
this.preferencesDao.setPreferences(currentSubject.getUserId(), content);
- } catch (final ServerException | NotFoundException e) {
+ } catch (final ServerException e) {
throw new PreferencesAccessException(e);
}
}
diff --git a/plugins/plugin-svn/che-plugin-svn-ext-server/src/test/java/org/eclipse/che/plugin/svn/server/SubversionProjectImporterTest.java b/plugins/plugin-svn/che-plugin-svn-ext-server/src/test/java/org/eclipse/che/plugin/svn/server/SubversionProjectImporterTest.java
index efca68365a..4b18ad594a 100644
--- a/plugins/plugin-svn/che-plugin-svn-ext-server/src/test/java/org/eclipse/che/plugin/svn/server/SubversionProjectImporterTest.java
+++ b/plugins/plugin-svn/che-plugin-svn-ext-server/src/test/java/org/eclipse/che/plugin/svn/server/SubversionProjectImporterTest.java
@@ -20,7 +20,7 @@ import org.eclipse.che.api.project.server.FolderEntry;
import org.eclipse.che.api.project.server.importer.ProjectImporter;
import org.eclipse.che.api.project.server.type.ProjectTypeDef;
import org.eclipse.che.api.project.server.type.ValueProviderFactory;
-import org.eclipse.che.api.user.server.dao.UserProfileDao;
+import org.eclipse.che.api.user.server.spi.ProfileDao;
import org.eclipse.che.api.vfs.VirtualFile;
import org.eclipse.che.api.vfs.VirtualFileSystem;
import org.eclipse.che.commons.lang.NameGenerator;
@@ -47,7 +47,8 @@ import static org.mockito.Mockito.when;
public class SubversionProjectImporterTest {
@Mock
- private UserProfileDao userProfileDao;
+ private ProfileDao userProfileDao;
+
@Mock
private CredentialsProvider credentialsProvider;
@Mock
@@ -73,7 +74,7 @@ public class SubversionProjectImporterTest {
.to(SubversionValueProviderFactory.class);
bind(SshKeyProvider.class).toInstance(sshKeyProvider);
- bind(UserProfileDao.class).toInstance(userProfileDao);
+ bind(ProfileDao.class).toInstance(userProfileDao);
bind(CredentialsProvider.class).toInstance(credentialsProvider);
bind(RepositoryUrlProvider.class).toInstance(repositoryUrlProvider);
}
diff --git a/plugins/plugin-svn/che-plugin-svn-ext-server/src/test/java/org/eclipse/che/plugin/svn/server/utils/TestUtils.java b/plugins/plugin-svn/che-plugin-svn-ext-server/src/test/java/org/eclipse/che/plugin/svn/server/utils/TestUtils.java
index 9cec8bc957..1eed582ac9 100644
--- a/plugins/plugin-svn/che-plugin-svn-ext-server/src/test/java/org/eclipse/che/plugin/svn/server/utils/TestUtils.java
+++ b/plugins/plugin-svn/che-plugin-svn-ext-server/src/test/java/org/eclipse/che/plugin/svn/server/utils/TestUtils.java
@@ -15,8 +15,8 @@ import com.google.common.io.Files;
import org.eclipse.che.api.core.util.LineConsumer;
import org.eclipse.che.api.core.util.LineConsumerFactory;
-import org.eclipse.che.api.user.server.dao.Profile;
-import org.eclipse.che.api.user.server.dao.UserProfileDao;
+import org.eclipse.che.api.user.server.model.impl.ProfileImpl;
+import org.eclipse.che.api.user.server.spi.ProfileDao;
import org.eclipse.che.api.vfs.VirtualFileSystem;
import org.eclipse.che.api.vfs.VirtualFileSystemProvider;
import org.eclipse.che.api.vfs.impl.file.LocalVirtualFileSystemProvider;
@@ -163,7 +163,7 @@ public class TestUtils {
* @throws Exception
* if anything goes wrong
*/
- public static void createTestUser(final UserProfileDao userProfileDao) throws Exception {
+ public static void createTestUser(final ProfileDao userProfileDao) throws Exception {
// set current user
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("codenvy", "codenvy", null, false));
@@ -175,7 +175,7 @@ public class TestUtils {
profileAttributes.put("email", "che@eclipse.org");
Mockito.when(userProfileDao.getById("codenvy"))
- .thenReturn(new Profile().withId("codenvy").withUserId("codenvy").withAttributes(profileAttributes));
+ .thenReturn(new ProfileImpl("codenvy", profileAttributes));
}
/**
diff --git a/pom.xml b/pom.xml
index 3b0149288e..e7570de986 100644
--- a/pom.xml
+++ b/pom.xml
@@ -186,6 +186,12 @@
che-core-api-ssh-shared
${che.version}
+
+ org.eclipse.che.core
+ che-core-api-user
+ ${project.version}
+ tests
+
org.eclipse.che.core
che-core-api-user
diff --git a/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/LocalGitUserResolver.java b/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/LocalGitUserResolver.java
index 62173c7bad..d4ab4dd4ee 100644
--- a/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/LocalGitUserResolver.java
+++ b/wsagent/che-core-api-git/src/main/java/org/eclipse/che/api/git/LocalGitUserResolver.java
@@ -12,7 +12,7 @@ package org.eclipse.che.api.git;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.git.shared.GitUser;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/wsagent/che-core-api-project/src/test/java/org/eclipse/che/api/project/server/ProjectServiceTest.java b/wsagent/che-core-api-project/src/test/java/org/eclipse/che/api/project/server/ProjectServiceTest.java
index a757539d9a..d2bb1e393f 100644
--- a/wsagent/che-core-api-project/src/test/java/org/eclipse/che/api/project/server/ProjectServiceTest.java
+++ b/wsagent/che-core-api-project/src/test/java/org/eclipse/che/api/project/server/ProjectServiceTest.java
@@ -40,7 +40,7 @@ import org.eclipse.che.api.project.shared.dto.ItemReference;
import org.eclipse.che.api.project.shared.dto.MoveOptions;
import org.eclipse.che.api.project.shared.dto.SourceEstimation;
import org.eclipse.che.api.project.shared.dto.TreeElement;
-import org.eclipse.che.api.user.server.dao.UserDao;
+import org.eclipse.che.api.user.server.spi.UserDao;
import org.eclipse.che.api.vfs.VirtualFile;
import org.eclipse.che.api.vfs.VirtualFileSystem;
import org.eclipse.che.api.vfs.impl.file.DefaultFileWatcherNotificationHandler;
diff --git a/wsagent/wsagent-local/src/main/java/org/eclipse/che/RemotePreferenceDao.java b/wsagent/wsagent-local/src/main/java/org/eclipse/che/RemotePreferenceDao.java
index 6817bb84fa..06762de4d4 100644
--- a/wsagent/wsagent-local/src/main/java/org/eclipse/che/RemotePreferenceDao.java
+++ b/wsagent/wsagent-local/src/main/java/org/eclipse/che/RemotePreferenceDao.java
@@ -17,8 +17,7 @@ import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
-import org.eclipse.che.api.user.server.UserProfileService;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
import org.eclipse.che.commons.env.EnvironmentContext;
import javax.inject.Inject;
@@ -44,12 +43,12 @@ public class RemotePreferenceDao implements PreferenceDao {
@Inject
public RemotePreferenceDao(@Named("api.endpoint") String apiUrl, HttpJsonRequestFactory requestFactory) {
- this.prefsUrl = apiUrl + "/profile/prefs";
+ this.prefsUrl = apiUrl + "/preferences";
this.requestFactory = requestFactory;
}
@Override
- public void setPreferences(String userId, Map preferences) throws ServerException, NotFoundException {
+ public void setPreferences(String userId, Map preferences) throws ServerException {
requireNonNull(preferences, "Required non-null preferences");
checkUserId(requireNonNull(userId, "Required non-null user id"));
try {
diff --git a/wsagent/wsagent-local/src/test/java/org/eclipse/che/RemotePreferenceDaoCompatibilityTest.java b/wsagent/wsagent-local/src/test/java/org/eclipse/che/RemotePreferenceDaoCompatibilityTest.java
index 3b7b29aaf0..592936d4f7 100644
--- a/wsagent/wsagent-local/src/test/java/org/eclipse/che/RemotePreferenceDaoCompatibilityTest.java
+++ b/wsagent/wsagent-local/src/test/java/org/eclipse/che/RemotePreferenceDaoCompatibilityTest.java
@@ -11,10 +11,9 @@
package org.eclipse.che;
import org.eclipse.che.api.core.rest.DefaultHttpJsonRequestFactory;
-import org.eclipse.che.api.user.server.UserProfileService;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
-import org.eclipse.che.api.user.server.dao.UserDao;
-import org.eclipse.che.api.user.server.dao.UserProfileDao;
+import org.eclipse.che.api.user.server.PreferenceManager;
+import org.eclipse.che.api.user.server.PreferencesService;
+import org.eclipse.che.api.user.server.ProfileService;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
import org.eclipse.che.commons.subject.SubjectImpl;
@@ -41,7 +40,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
- * Tests that {@link RemotePreferenceDao} uses correct methods of {@link UserProfileService}.
+ * Tests that {@link RemotePreferenceDao} uses correct methods of {@link ProfileService}.
*
* @author Yevhenii Voevodin
*/
@@ -53,16 +52,10 @@ public class RemotePreferenceDaoCompatibilityTest {
private static final Subject TEST_SUBJECT = new SubjectImpl("name", "id", "token", false);
@Mock
- private PreferenceDao preferenceDaoMock;
-
- @Mock
- private UserDao userDao;
-
- @Mock
- private UserProfileDao userProfileDao;
+ private PreferenceManager preferenceManager;
@InjectMocks
- private UserProfileService profileService;
+ private PreferencesService preferenceService;
@BeforeMethod
private void setUp() {
@@ -77,7 +70,7 @@ public class RemotePreferenceDaoCompatibilityTest {
remoteDao.getPreferences(TEST_SUBJECT.getUserId());
- verify(preferenceDaoMock).getPreferences(TEST_SUBJECT.getUserId());
+ verify(preferenceManager).find(TEST_SUBJECT.getUserId());
}
@Test
@@ -86,7 +79,7 @@ public class RemotePreferenceDaoCompatibilityTest {
remoteDao.getPreferences(TEST_SUBJECT.getUserId(), "filter");
- verify(preferenceDaoMock).getPreferences(TEST_SUBJECT.getUserId(), "filter");
+ verify(preferenceManager).find(TEST_SUBJECT.getUserId(), "filter");
}
@Test
@@ -96,7 +89,7 @@ public class RemotePreferenceDaoCompatibilityTest {
remoteDao.setPreferences(TEST_SUBJECT.getUserId(), prefs);
- verify(preferenceDaoMock).setPreferences(TEST_SUBJECT.getUserId(), prefs);
+ verify(preferenceManager).save(TEST_SUBJECT.getUserId(), prefs);
}
@Test
@@ -105,7 +98,7 @@ public class RemotePreferenceDaoCompatibilityTest {
remoteDao.remove(TEST_SUBJECT.getUserId());
- verify(preferenceDaoMock).remove(TEST_SUBJECT.getUserId());
+ verify(preferenceManager).remove(TEST_SUBJECT.getUserId());
}
@Filter
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryService.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryService.java
index d6a623ed1c..7a42236b7c 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryService.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/FactoryService.java
@@ -31,7 +31,7 @@ import org.eclipse.che.api.factory.server.builder.FactoryBuilder;
import org.eclipse.che.api.factory.server.snippet.SnippetGenerator;
import org.eclipse.che.api.factory.shared.dto.Author;
import org.eclipse.che.api.factory.shared.dto.Factory;
-import org.eclipse.che.api.user.server.dao.UserDao;
+import org.eclipse.che.api.user.server.spi.UserDao;
import org.eclipse.che.api.workspace.server.WorkspaceManager;
import org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryAcceptValidatorImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryAcceptValidatorImpl.java
index 69d52f3162..dacb658c6b 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryAcceptValidatorImpl.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryAcceptValidatorImpl.java
@@ -13,7 +13,7 @@ package org.eclipse.che.api.factory.server.impl;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.factory.server.FactoryAcceptValidator;
import org.eclipse.che.api.factory.shared.dto.Factory;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
import javax.inject.Inject;
import javax.inject.Singleton;
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryBaseValidator.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryBaseValidator.java
index cceb5cbbbf..73feb7a8ff 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryBaseValidator.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryBaseValidator.java
@@ -20,7 +20,7 @@ import org.eclipse.che.api.factory.shared.dto.Ide;
import org.eclipse.che.api.factory.shared.dto.OnAppLoaded;
import org.eclipse.che.api.factory.shared.dto.OnProjectsLoaded;
import org.eclipse.che.api.factory.shared.dto.Policies;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import java.io.UnsupportedEncodingException;
@@ -30,7 +30,6 @@ import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
-import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.Boolean.parseBoolean;
import static java.lang.String.format;
diff --git a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryCreateValidatorImpl.java b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryCreateValidatorImpl.java
index 999550fbc3..168e768fb6 100644
--- a/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryCreateValidatorImpl.java
+++ b/wsmaster/che-core-api-factory/src/main/java/org/eclipse/che/api/factory/server/impl/FactoryCreateValidatorImpl.java
@@ -15,7 +15,7 @@ import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.factory.server.FactoryCreateValidator;
import org.eclipse.che.api.factory.shared.dto.Factory;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
import org.eclipse.che.api.workspace.server.WorkspaceValidator;
import javax.inject.Inject;
diff --git a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/FactoryServiceTest.java b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/FactoryServiceTest.java
index 9891e0c01e..138aa8e238 100644
--- a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/FactoryServiceTest.java
+++ b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/FactoryServiceTest.java
@@ -26,8 +26,8 @@ import org.eclipse.che.api.factory.shared.dto.Button;
import org.eclipse.che.api.factory.shared.dto.ButtonAttributes;
import org.eclipse.che.api.factory.shared.dto.Factory;
import org.eclipse.che.api.machine.shared.dto.CommandDto;
-import org.eclipse.che.api.user.server.dao.User;
-import org.eclipse.che.api.user.server.dao.UserDao;
+import org.eclipse.che.api.user.server.model.impl.UserImpl;
+import org.eclipse.che.api.user.server.spi.UserDao;
import org.eclipse.che.api.workspace.server.WorkspaceManager;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
@@ -161,7 +161,11 @@ public class FactoryServiceTest {
factoryBuilder = spy(new FactoryBuilder(new SourceStorageParametersValidator()));
doNothing().when(factoryBuilder).checkValid(any(Factory.class));
when(factoryParametersResolverHolder.getFactoryParametersResolvers()).thenReturn(factoryParametersResolvers);
- when(userDao.getById(anyString())).thenReturn(new User().withName(JettyHttpServer.ADMIN_USER_NAME));
+ when(userDao.getById(anyString())).thenReturn(new UserImpl(null,
+ null,
+ JettyHttpServer.ADMIN_USER_NAME,
+ null,
+ null));
factoryService = new FactoryService(factoryStore,
createValidator,
acceptValidator,
diff --git a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/impl/FactoryBaseValidatorTest.java b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/impl/FactoryBaseValidatorTest.java
index d67d83bf3f..37dd3c3369 100644
--- a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/impl/FactoryBaseValidatorTest.java
+++ b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/impl/FactoryBaseValidatorTest.java
@@ -26,9 +26,9 @@ import org.eclipse.che.api.factory.shared.dto.OnAppClosed;
import org.eclipse.che.api.factory.shared.dto.OnAppLoaded;
import org.eclipse.che.api.factory.shared.dto.OnProjectsLoaded;
import org.eclipse.che.api.factory.shared.dto.Policies;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
-import org.eclipse.che.api.user.server.dao.User;
-import org.eclipse.che.api.user.server.dao.UserDao;
+import org.eclipse.che.api.user.server.model.impl.UserImpl;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
+import org.eclipse.che.api.user.server.spi.UserDao;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
@@ -86,7 +86,7 @@ public class FactoryBaseValidatorTest {
.withCreator(newDto(Author.class)
.withUserId("userid"));
- User user = new User().withId("userid");
+ UserImpl user = new UserImpl("userid");
when(userDao.getById("userid")).thenReturn(user);
validator = new TesterFactoryBaseValidator(preferenceDao);
diff --git a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/impl/FactoryCreateAndAcceptValidatorsImplsTest.java b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/impl/FactoryCreateAndAcceptValidatorsImplsTest.java
index a60644563a..0df79abda2 100644
--- a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/impl/FactoryCreateAndAcceptValidatorsImplsTest.java
+++ b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/impl/FactoryCreateAndAcceptValidatorsImplsTest.java
@@ -13,8 +13,8 @@ package org.eclipse.che.api.factory.server.impl;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
import org.eclipse.che.api.factory.shared.dto.Factory;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
-import org.eclipse.che.api.user.server.dao.UserDao;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
+import org.eclipse.che.api.user.server.spi.UserDao;
import org.eclipse.che.api.workspace.server.WorkspaceValidator;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
diff --git a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/impl/TesterFactoryBaseValidator.java b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/impl/TesterFactoryBaseValidator.java
index ecaac39056..5c5080b6df 100644
--- a/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/impl/TesterFactoryBaseValidator.java
+++ b/wsmaster/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/server/impl/TesterFactoryBaseValidator.java
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.eclipse.che.api.factory.server.impl;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
/**
* @author Sergii Kabashniuk
diff --git a/wsmaster/che-core-api-user-shared/pom.xml b/wsmaster/che-core-api-user-shared/pom.xml
index aa6e1404d6..239d2c61b2 100644
--- a/wsmaster/che-core-api-user-shared/pom.xml
+++ b/wsmaster/che-core-api-user-shared/pom.xml
@@ -41,6 +41,10 @@
org.eclipse.che.core
che-core-api-dto
+
+ org.eclipse.che.core
+ che-core-api-model
+
diff --git a/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/MembershipDto.java b/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/MembershipDto.java
deleted file mode 100644
index 7c754e2ed3..0000000000
--- a/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/MembershipDto.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012-2016 Codenvy, S.A.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Codenvy, S.A. - initial API and implementation
- *******************************************************************************/
-package org.eclipse.che.api.user.shared.dto;
-
-import org.eclipse.che.api.user.shared.model.Membership;
-import org.eclipse.che.dto.shared.DTO;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- *
- *
- * @author andrew00x
- */
-@DTO
-public interface MembershipDto extends Membership {
-
- @Override
- String getUserId();
-
- void setUserId(String id);
-
- MembershipDto withUserId(String id);
-
- @Override
- String getScope();
-
- @Override
- String getUserName();
-
- @Override
- String getSubjectId();
-
- @Override
- Map getSubjectProperties();
-
- @Override
- List getRoles();
-
- void setRoles(List roles);
-
- MembershipDto withRoles(List roles);
-}
diff --git a/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/ProfileDescriptor.java b/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/ProfileDto.java
similarity index 68%
rename from wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/ProfileDescriptor.java
rename to wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/ProfileDto.java
index 076c23f189..df91663179 100644
--- a/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/ProfileDescriptor.java
+++ b/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/ProfileDto.java
@@ -10,43 +10,47 @@
*******************************************************************************/
package org.eclipse.che.api.user.shared.dto;
+import org.eclipse.che.api.core.model.user.Profile;
import org.eclipse.che.api.core.rest.shared.dto.Link;
+import org.eclipse.che.dto.server.DtoFactory;
import org.eclipse.che.dto.shared.DTO;
+
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
import java.util.Map;
/**
- * @author andrew00x
+ * This object used for transporting profile data to/from client.
+ *
+ * @author Yevhenii Voevodin
+ * @see Profile
+ * @see DtoFactory
*/
@DTO
-public interface ProfileDescriptor {
-
- void setId(String id);
-
- @ApiModelProperty("Profile ID")
- String getId();
-
- ProfileDescriptor withId(String id);
-
- @ApiModelProperty("User ID")
- String getUserId();
+public interface ProfileDto extends Profile {
void setUserId(String id);
- ProfileDescriptor withUserId(String id);
+ @ApiModelProperty("Profile ID")
+ String getUserId();
+
+ ProfileDto withUserId(String id);
@ApiModelProperty("Profile attributes")
Map getAttributes();
void setAttributes(Map attributes);
- ProfileDescriptor withAttributes(Map attributes);
+ ProfileDto withAttributes(Map attributes);
List getLinks();
void setLinks(List links);
- ProfileDescriptor withLinks(List links);
+ ProfileDto withLinks(List links);
+
+ String getEmail();
+
+ ProfileDto withEmail(String email);
}
diff --git a/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/UserDescriptor.java b/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/UserDto.java
similarity index 72%
rename from wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/UserDescriptor.java
rename to wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/UserDto.java
index 09681e0af7..5013273967 100644
--- a/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/UserDescriptor.java
+++ b/wsmaster/che-core-api-user-shared/src/main/java/org/eclipse/che/api/user/shared/dto/UserDto.java
@@ -10,56 +10,62 @@
*******************************************************************************/
package org.eclipse.che.api.user.shared.dto;
+import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.core.rest.shared.dto.Link;
+import org.eclipse.che.dto.server.DtoFactory;
import org.eclipse.che.dto.shared.DTO;
+
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
/**
- * @author andrew00x
+ * This object used for transporting user data to/from client.
+ *
+ * @author Yevhenii Voevodin
+ * @see User
+ * @see DtoFactory
*/
@DTO
-public interface UserDescriptor {
+public interface UserDto extends User {
@ApiModelProperty("User ID")
String getId();
void setId(String id);
- UserDescriptor withId(String id);
-
+ UserDto withId(String id);
@ApiModelProperty("User alias which is used for oAuth")
List getAliases();
void setAliases(List aliases);
- UserDescriptor withAliases(List aliases);
+ UserDto withAliases(List aliases);
@ApiModelProperty("User email")
String getEmail();
void setEmail(String email);
- UserDescriptor withEmail(String email);
+ UserDto withEmail(String email);
@ApiModelProperty("User name")
String getName();
void setName(String name);
- UserDescriptor withName(String name);
+ UserDto withName(String name);
@ApiModelProperty("User password")
String getPassword();
void setPassword(String password);
- UserDescriptor withPassword(String password);
+ UserDto withPassword(String password);
List getLinks();
void setLinks(List links);
- UserDescriptor withLinks(List links);
+ UserDto withLinks(List links);
}
diff --git a/wsmaster/che-core-api-user/pom.xml b/wsmaster/che-core-api-user/pom.xml
index 11db5d149a..774fe5d09a 100644
--- a/wsmaster/che-core-api-user/pom.xml
+++ b/wsmaster/che-core-api-user/pom.xml
@@ -48,6 +48,10 @@
org.eclipse.che.core
che-core-api-dto
+
+ org.eclipse.che.core
+ che-core-api-model
+
org.eclipse.che.core
che-core-api-user-shared
@@ -56,10 +60,19 @@
org.eclipse.che.core
che-core-commons-lang
+
+ org.eclipse.che.core
+ che-core-commons-test
+
org.slf4j
slf4j-api
+
+ com.google.code.gson
+ gson
+ test
+
com.jayway.restassured
rest-assured
@@ -99,4 +112,35 @@
test
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ **/spi/tck/*.*
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ test-jar
+
+
+
+ **/spi/tck/*.*
+
+
+
+
+
+
+
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/Constants.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/Constants.java
index 3fb6d2501d..3181cce577 100644
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/Constants.java
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/Constants.java
@@ -11,30 +11,32 @@
package org.eclipse.che.api.user.server;
/**
- * Constants for User API and UserProfile API
+ * Constants for User/Profile/Preferences API.
*
- * @author Eugene Voevodin
+ * @author Yevhenii Voevodin
* @author Max Shaposhnik
*/
public final class Constants {
- public static final String LINK_REL_GET_CURRENT_USER_PROFILE = "current user profile";
- public static final String LINK_REL_UPDATE_CURRENT_USER_PROFILE = "update current user profile";
- public static final String LINK_REL_GET_USER_PROFILE_BY_ID = "user profile by id";
- public static final String LINK_REL_UPDATE_USER_PROFILE_BY_ID = "update user profile by id";
- public static final String LINK_REL_INROLE = "in role";
- public static final String LINK_REL_CREATE_USER = "create user";
- public static final String LINK_REL_GET_CURRENT_USER = "get current";
- public static final String LINK_REL_UPDATE_PASSWORD = "update password";
- public static final String LINK_REL_REMOVE_PREFERENCES = "remove preferences";
- public static final String LINK_REL_REMOVE_ATTRIBUTES = "remove attributes";
- public static final String LINK_REL_GET_USER_BY_ID = "get user by id";
- public static final String LINK_REL_GET_USER_BY_EMAIL = "get user by email";
- public static final String LINK_REL_REMOVE_USER_BY_ID = "remove user by id";
- public static final String LINK_REL_UPDATE_PREFERENCES = "update prefs";
- public static final int ID_LENGTH = 16;
- public static final int PASSWORD_LENGTH = 10;
+ /** Profile link relationships. */
+ public static final String LINK_REL_CURRENT_PROFILE = "current_profile";
+ public static final String LINK_REL_CURRENT_PROFILE_ATTRIBUTES = "current_profile.attributes";
+ public static final String LINK_REL_PROFILE = "profile";
+ public static final String LINK_REL_PROFILE_ATTRIBUTES = "profile.attributes";
- private Constants() {
- }
+ /** User links relationships. */
+ public static final String LINK_REL_USER = "user";
+ public static final String LINK_REL_CURRENT_USER = "current_user";
+ public static final String LINK_REL_CURRENT_USER_PASSWORD = "current_user.password";
+ public static final String LINK_REL_CURRENT_USER_SETTINGS = "current_user.settings";
+
+ /** Preferences links relationships. */
+ public static final String LINK_REL_PREFERENCES = "preferences";
+
+ public static final String LINK_REL_SELF = "self";
+
+ public static final int ID_LENGTH = 16;
+ public static final int PASSWORD_LENGTH = 10;
+
+ private Constants() {}
}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/DtoConverter.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/DtoConverter.java
index cd9a5806f0..c12a424387 100644
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/DtoConverter.java
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/DtoConverter.java
@@ -10,8 +10,8 @@
*******************************************************************************/
package org.eclipse.che.api.user.server;
-import org.eclipse.che.api.user.server.dao.User;
-import org.eclipse.che.api.user.shared.dto.UserDescriptor;
+import org.eclipse.che.api.core.model.user.User;
+import org.eclipse.che.api.user.shared.dto.UserDto;
import org.eclipse.che.dto.server.DtoFactory;
/**
@@ -22,10 +22,10 @@ import org.eclipse.che.dto.server.DtoFactory;
public final class DtoConverter {
/**
- * Converts {@link User} to {@link UserDescriptor}.
+ * Converts {@link User} to {@link UserDto}.
*/
- public static UserDescriptor toDescriptor(User user) {
- return DtoFactory.getInstance().createDto(UserDescriptor.class)
+ public static UserDto asDto(User user) {
+ return DtoFactory.getInstance().createDto(UserDto.class)
.withId(user.getId())
.withEmail(user.getEmail())
.withName(user.getName())
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/PreferenceManager.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/PreferenceManager.java
new file mode 100644
index 0000000000..2a97b1fca5
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/PreferenceManager.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server;
+
+import com.google.common.util.concurrent.Striped;
+
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Preferences manager layer, simplifies preferences service by
+ * taking all the business logic out from the service and making that logic easily
+ * reusable throughout the system.
+ *
+ * The manager doesn't perform any bean validations and it
+ * is expected that all the incoming objects are valid, nevertheless
+ * this exactly the right place for performing business validations.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Singleton
+public class PreferenceManager {
+
+ private static final Striped UPDATE_REENTRANT_LOCKS = Striped.lazyWeakLock(32);
+
+ @Inject
+ private PreferenceDao preferenceDao;
+
+ /**
+ * Associates the given {@code preferences} with the given {@code userId}.
+ *
+ * Note that this method will override all the existing properties
+ * for the user with id {@code userId}.
+ *
+ * @param userId
+ * the user id whom the {@code preferences} belong to
+ * @param preferences
+ * the preferences to associate with the {@code userId}
+ * @throws NullPointerException
+ * when either {@code userId} or {@code preferences} is null
+ * @throws ServerException
+ * when any error occurs
+ */
+ public void save(String userId, Map preferences) throws ServerException {
+ requireNonNull(userId, "Required non-null user id");
+ requireNonNull(preferences, "Required non-null preferences");
+ preferenceDao.setPreferences(userId, preferences);
+ }
+
+ /**
+ * Updates the preferences of the user by merging given {@code preferences}
+ * with the existing preferences. If user doesn't have any preferences
+ * then the given {@code preferences} will be associated with the user.
+ *
+ * @param userId
+ * the user whose preferences should be updated
+ * @param preferences
+ * preferences update
+ * @return all the user's preferences including the update
+ * @throws NullPointerException
+ * when either {@code userId} or {@code preferences} is null
+ * @throws ServerException
+ * when any error occurs
+ */
+ public Map update(String userId, Map preferences) throws ServerException {
+ requireNonNull(userId, "Required non-null user id");
+ requireNonNull(preferences, "Required non-null preferences");
+ // Holding reference to prevent garbage collection
+ // this reentrantLock helps to avoid race-conditions when parallel updates are applied
+ final Lock reentrantLock = UPDATE_REENTRANT_LOCKS.get(userId);
+ reentrantLock.lock();
+ try {
+ final Map found = preferenceDao.getPreferences(userId);
+ found.putAll(preferences);
+ preferenceDao.setPreferences(userId, found);
+ return found;
+ } finally {
+ reentrantLock.unlock();
+ }
+ }
+
+ /**
+ * Finds user's preferences.
+ *
+ * @param userId
+ * user id to find preferences
+ * @return found preferences or empty map, if there are no preferences related to user
+ * @throws NullPointerException
+ * when {@code userId} is null
+ * @throws ServerException
+ * when any error occurs
+ */
+ public Map find(String userId) throws ServerException {
+ requireNonNull(userId, "Required non-null user id");
+ return preferenceDao.getPreferences(userId);
+ }
+
+ /**
+ * Finds user's preferences.
+ *
+ * @param userId
+ * user id to find preferences
+ * @param keyFilter
+ * regex which is used to filter preferences by keys, so
+ * result contains only the user's preferences that match {@code keyFilter} regex
+ * @return found preferences filtered by {@code keyFilter} or an empty map
+ * if there are no preferences related to user
+ * @throws NullPointerException
+ * when {@code userId} is null
+ * @throws ServerException
+ * when any error occurs
+ */
+ public Map find(String userId, String keyFilter) throws ServerException {
+ requireNonNull(userId, "Required non-null user id");
+ return preferenceDao.getPreferences(userId, keyFilter);
+ }
+
+ /**
+ * Removes(clears) user's preferences.
+ *
+ * @param userId
+ * the id of the user to remove preferences
+ * @throws NullPointerException
+ * when {@code userId} is null
+ * @throws ServerException
+ * when any error occurs
+ */
+ public void remove(String userId) throws ServerException {
+ requireNonNull(userId, "Required non-null user id");
+ preferenceDao.remove(userId);
+ }
+
+ /**
+ * Removes the preferences with the given {@code names}.
+ *
+ * @param userId
+ * the id of the user to remove preferences
+ * @param names
+ * the names to remove
+ * @throws NullPointerException
+ * when either {@code userId} or {@code names} is null
+ * @throws ServerException
+ * when any error occurs
+ */
+ public void remove(String userId, List names) throws ServerException {
+ requireNonNull(userId, "Required non-null user id");
+ requireNonNull(names, "Required non-null preference names");
+ // Holding reference to prevent garbage collection
+ // this reentrantLock helps to avoid race-conditions when parallel updates are applied
+ final Lock reentrantLock = UPDATE_REENTRANT_LOCKS.get(userId);
+ reentrantLock.lock();
+ try {
+ final Map preferences = preferenceDao.getPreferences(userId);
+ names.forEach(preferences::remove);
+ preferenceDao.setPreferences(userId, preferences);
+ } finally {
+ reentrantLock.unlock();
+ }
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/PreferencesService.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/PreferencesService.java
new file mode 100644
index 0000000000..9ca9d74e30
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/PreferencesService.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+import org.eclipse.che.api.core.BadRequestException;
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.core.rest.Service;
+import org.eclipse.che.api.core.rest.annotations.GenerateLink;
+import org.eclipse.che.commons.env.EnvironmentContext;
+
+import javax.annotation.security.RolesAllowed;
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import java.util.List;
+import java.util.Map;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_PREFERENCES;
+
+/**
+ * Preferences REST API.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Path("/preferences")
+@Api(value = "/preferences", description = "Preferences REST API")
+public class PreferencesService extends Service {
+
+ @Inject
+ private PreferenceManager preferenceManager;
+
+ @GET
+ @Produces(APPLICATION_JSON)
+ @GenerateLink(rel = LINK_REL_PREFERENCES)
+ @ApiOperation(value = "Gets preferences of logged in user",
+ notes = "If not all the preferences needed then 'filter' may be used, " +
+ "basically it is regex for filtering preferences by names")
+ @ApiResponses({@ApiResponse(code = 200, message = "Preferences successfully fetched"),
+ @ApiResponse(code = 500, message = "Internal Server Error")})
+ public Map find(@ApiParam("Regex for filtering preferences by names, e.g. '.*github.*' " +
+ "will return all the preferences which name contains github")
+ @QueryParam("filter")
+ String filter) throws ServerException {
+ if (filter == null) {
+ return preferenceManager.find(userId());
+ }
+ return preferenceManager.find(userId(), filter);
+ }
+
+ @POST
+ @Consumes(APPLICATION_JSON)
+ @GenerateLink(rel = LINK_REL_PREFERENCES)
+ @ApiOperation(value = "Saves preferences of logged in user",
+ notes = "All the existing user's preferences will be override by this method")
+ @ApiResponses({@ApiResponse(code = 204, message = "Preferences successfully saved"),
+ @ApiResponse(code = 400, message = "Request doesn't contain new preferences"),
+ @ApiResponse(code = 500, message = "Couldn't save preferences due to internal server error")})
+ public void save(Map preferences) throws BadRequestException, ServerException {
+ if (preferences == null) {
+ throw new BadRequestException("Required non-null new preferences");
+ }
+ preferenceManager.save(userId(), preferences);
+ }
+
+ @PUT
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON)
+ @GenerateLink(rel = LINK_REL_PREFERENCES)
+ @ApiOperation(value = "Updates preferences of logged in user",
+ notes = "The merge strategy is used for update, which means that " +
+ "existing preferences with keys equal to update preference keys will " +
+ "be replaces with new values, and new preferences will be added")
+ @ApiResponses({@ApiResponse(code = 200, message = "Preferences successfully updated, response contains " +
+ "all the user preferences"),
+ @ApiResponse(code = 400, message = "Request doesn't contain preferences update"),
+ @ApiResponse(code = 500, message = "Couldn't update preferences due to internal server error")})
+ public Map update(Map preferences) throws ServerException, BadRequestException {
+ if (preferences == null) {
+ throw new BadRequestException("Required non-null preferences update");
+ }
+ return preferenceManager.update(userId(), preferences);
+ }
+
+ @DELETE
+ @Consumes(APPLICATION_JSON)
+ @GenerateLink(rel = LINK_REL_PREFERENCES)
+ @ApiOperation(value = "Remove preferences of logged in user.",
+ notes = "If names are not specified, then all the user's preferences will be removed, " +
+ "otherwise only the preferences which names are listed")
+ @ApiResponses({@ApiResponse(code = 204, message = "Preferences successfully removed"),
+ @ApiResponse(code = 500, message = "Couldn't remove preferences due to internal server error")})
+ public void removePreferences(@ApiParam("Preferences to remove") List names) throws ServerException {
+ if (names == null || names.isEmpty()) {
+ preferenceManager.remove(userId());
+ } else {
+ preferenceManager.remove(userId(), names);
+ }
+ }
+
+ private static String userId() {
+ return EnvironmentContext.getCurrent().getSubject().getUserId();
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/ProfileLinksInjector.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/ProfileLinksInjector.java
new file mode 100644
index 0000000000..752ce15556
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/ProfileLinksInjector.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server;
+
+import org.eclipse.che.api.core.rest.ServiceContext;
+import org.eclipse.che.api.core.rest.shared.dto.Link;
+import org.eclipse.che.api.user.shared.dto.ProfileDto;
+
+import javax.inject.Singleton;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.UriBuilder;
+import java.util.ArrayList;
+import java.util.List;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.eclipse.che.api.core.util.LinksHelper.createLink;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_CURRENT_PROFILE;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_CURRENT_PROFILE_ATTRIBUTES;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_PROFILE_ATTRIBUTES;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_SELF;
+
+/**
+ * Creates and injects links to the {@link ProfileDto} object.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Singleton
+public class ProfileLinksInjector {
+
+ public ProfileDto injectLinks(ProfileDto profileDto, ServiceContext serviceContext) {
+ final UriBuilder uriBuilder = serviceContext.getServiceUriBuilder();
+ final List links = new ArrayList<>(5);
+ links.add(createLink(HttpMethod.GET,
+ uriBuilder.clone()
+ .path(ProfileService.class, "getCurrent")
+ .build()
+ .toString(),
+ null,
+ APPLICATION_JSON,
+ LINK_REL_CURRENT_PROFILE));
+ links.add(createLink(HttpMethod.GET,
+ uriBuilder.clone()
+ .path(ProfileService.class, "getById")
+ .build(profileDto.getUserId())
+ .toString(),
+ null,
+ APPLICATION_JSON,
+ LINK_REL_SELF));
+ links.add(createLink(HttpMethod.PUT,
+ uriBuilder.clone()
+ .path(ProfileService.class, "updateAttributes")
+ .build()
+ .toString(),
+ APPLICATION_JSON,
+ APPLICATION_JSON,
+ LINK_REL_CURRENT_PROFILE_ATTRIBUTES));
+ links.add(createLink(HttpMethod.DELETE,
+ uriBuilder.clone()
+ .path(ProfileService.class, "removeAttributes")
+ .build(profileDto.getUserId())
+ .toString(),
+ APPLICATION_JSON,
+ APPLICATION_JSON,
+ LINK_REL_CURRENT_PROFILE_ATTRIBUTES));
+ links.add(createLink(HttpMethod.PUT,
+ uriBuilder.clone()
+ .path(ProfileService.class, "updateAttributesById")
+ .build(profileDto.getUserId())
+ .toString(),
+ APPLICATION_JSON,
+ APPLICATION_JSON,
+ LINK_REL_PROFILE_ATTRIBUTES));
+ return profileDto.withLinks(links);
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/ProfileManager.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/ProfileManager.java
new file mode 100644
index 0000000000..ba72708941
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/ProfileManager.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server;
+
+import org.eclipse.che.api.core.ConflictException;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.core.model.user.Profile;
+import org.eclipse.che.api.core.model.user.User;
+import org.eclipse.che.api.user.server.model.impl.ProfileImpl;
+import org.eclipse.che.api.user.server.spi.ProfileDao;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Preferences manager layer, simplifies prefernces service by
+ * taking all the business logic out from the service and making that logic
+ * easily reusable throughout the system.
+ *
+ * The manager doesn't perform any bean validations and it
+ * is expected that all the incoming objects are valid, nevertheless
+ * this exactly the right place for performing business validations.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Singleton
+public class ProfileManager {
+
+ @Inject
+ private ProfileDao profileDao;
+
+ /**
+ * Finds the profile related to the user with given {@code userId}.
+ *
+ * @param userId
+ * the id to search the user's profile
+ * @return found profile
+ * @throws NullPointerException
+ * when {@code userId} is null
+ * @throws NotFoundException
+ * when there is no profile for the user with the id {@code userId}
+ * @throws ServerException
+ * when any other error occurs
+ */
+ public Profile getById(String userId) throws NotFoundException, ServerException {
+ requireNonNull(userId, "Required non-null user id");
+ return profileDao.getById(userId);
+ }
+
+ /**
+ * Creates a new user's profile .
+ *
+ * @param profile
+ * new profile
+ * @throws NullPointerException
+ * when profile is null
+ * @throws ConflictException
+ * when profile for the user {@code profile.getUserId()} already exists
+ * @throws ServerException
+ * when any other error occurs
+ */
+ public void create(Profile profile) throws ServerException, ConflictException {
+ requireNonNull(profile, "Required non-null profile");
+ profileDao.create(new ProfileImpl(profile));
+ }
+
+ /**
+ * Updates current profile using replace strategy.
+ *
+ *
Note that {@link Profile#getEmail()} can't be updated using this method
+ * as it is mirrored from the {@link User#getEmail()}.
+ *
+ * @param profile
+ * profile update
+ * @throws NullPointerException
+ * when {@code profile} is null
+ * @throws NotFoundException
+ * when there is no profile for the user with the id {@code profile.getUserId()}
+ * @throws ServerException
+ * when any other error occurs
+ */
+ public void update(Profile profile) throws NotFoundException, ServerException {
+ requireNonNull(profile, "Required non-null profile");
+ profileDao.update(new ProfileImpl(profile));
+ }
+
+ /**
+ * Removes the user's profile.
+ *
+ *
Note that this method won't throw any exception when
+ * user doesn't have the corresponding profile.
+ *
+ * @param userId
+ * the id of the user, whose profile should be removed
+ * @throws NullPointerException
+ * when {@code id} is null
+ * @throws ServerException
+ * when any other error occurs
+ */
+ public void remove(String userId) throws ServerException {
+ requireNonNull(userId, "Required non-null user id");
+ profileDao.remove(userId);
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/ProfileService.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/ProfileService.java
new file mode 100644
index 0000000000..aef2115761
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/ProfileService.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server;
+
+import org.eclipse.che.api.core.BadRequestException;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.core.model.user.Profile;
+import org.eclipse.che.api.core.model.user.User;
+import org.eclipse.che.api.core.rest.Service;
+import org.eclipse.che.api.core.rest.annotations.GenerateLink;
+import org.eclipse.che.api.user.server.model.impl.ProfileImpl;
+import org.eclipse.che.api.user.shared.dto.ProfileDto;
+import org.eclipse.che.commons.env.EnvironmentContext;
+import org.eclipse.che.dto.server.DtoFactory;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+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.SecurityContext;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_CURRENT_PROFILE;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_CURRENT_PROFILE_ATTRIBUTES;
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+
+/**
+ * Profile REST API.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Api(value = "/profile", description = "Profile REST API")
+@Path("/profile")
+public class ProfileService extends Service {
+
+ @Inject
+ private ProfileManager profileManager;
+ @Inject
+ private UserManager userManager;
+ @Inject
+ private ProfileLinksInjector linksInjector;
+ @Context
+ private SecurityContext context;
+
+ @GET
+ @Produces(APPLICATION_JSON)
+ @GenerateLink(rel = LINK_REL_CURRENT_PROFILE)
+ @ApiOperation("Get profile of the logged in user")
+ @ApiResponses({@ApiResponse(code = 200, message = "The response contains requested profile entity"),
+ @ApiResponse(code = 404, message = "Currently logged in user doesn't have profile"),
+ @ApiResponse(code = 500, message = "Couldn't retrieve profile due to internal server error")})
+ public ProfileDto getCurrent() throws ServerException, NotFoundException {
+ final ProfileImpl profile = new ProfileImpl(profileManager.getById(userId()));
+ return linksInjector.injectLinks(asDto(profile, userManager.getById(profile.getUserId())), getServiceContext());
+ }
+
+ @GET
+ @Path("/{id}")
+ @Produces(APPLICATION_JSON)
+ @GenerateLink(rel = LINK_REL_CURRENT_PROFILE)
+ @ApiOperation("Get profile by user's id")
+ @ApiResponses({@ApiResponse(code = 200, message = "The response contains requested profile entity"),
+ @ApiResponse(code = 404, message = "Profile for the user with requested identifier doesn't exist"),
+ @ApiResponse(code = 500, message = "Couldn't retrieve profile due to internal server error")})
+ public ProfileDto getById(@ApiParam("User identifier")
+ @PathParam("id")
+ String userId) throws NotFoundException, ServerException {
+ return linksInjector.injectLinks(asDto(profileManager.getById(userId), userManager.getById(userId)), getServiceContext());
+ }
+
+ @PUT
+ @Path("/{id}/attributes")
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON)
+ @ApiOperation(value = "Update the profile attributes of the user with requested identifier",
+ notes = "The replace strategy is used for the update, so all the existing profile " +
+ "attributes will be override by the profile update")
+ @ApiResponses({@ApiResponse(code = 200, message = "The profile successfully updated and the response contains " +
+ "newly updated profile entity"),
+ @ApiResponse(code = 404, message = "When profile for the user with requested identifier doesn't exist"),
+ @ApiResponse(code = 500, message = "Couldn't retrieve profile due to internal server error")})
+ public ProfileDto updateAttributesById(@ApiParam("Id of the user")
+ @PathParam("id")
+ String userId,
+ @ApiParam("New profile attributes")
+ Map updates) throws NotFoundException,
+ ServerException,
+ BadRequestException {
+ if (updates == null) {
+ throw new BadRequestException("Update attributes required");
+ }
+ final ProfileImpl profile = new ProfileImpl(profileManager.getById(userId));
+ profile.setAttributes(updates);
+ profileManager.update(profile);
+ return linksInjector.injectLinks(asDto(profile, userManager.getById(userId)), getServiceContext());
+ }
+
+ @PUT
+ @Path("/attributes")
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON)
+ @GenerateLink(rel = LINK_REL_CURRENT_PROFILE_ATTRIBUTES)
+ @ApiOperation(value = "Update the profile attributes of the currently logged in user",
+ notes = "The replace strategy is used for the update, so all the existing profile " +
+ "attributes will be override with incoming values")
+ public ProfileDto updateAttributes(@ApiParam("New profile attributes")
+ Map updates) throws NotFoundException,
+ ServerException,
+ BadRequestException {
+ if (updates == null) {
+ throw new BadRequestException("Update attributes required");
+ }
+ final ProfileImpl profile = new ProfileImpl(profileManager.getById(userId()));
+ profile.setAttributes(updates);
+ profileManager.update(profile);
+ return linksInjector.injectLinks(asDto(profile, userManager.getById(profile.getUserId())), getServiceContext());
+ }
+
+ @DELETE
+ @Path("/attributes")
+ @GenerateLink(rel = LINK_REL_CURRENT_PROFILE_ATTRIBUTES)
+ @Consumes(APPLICATION_JSON)
+ @ApiOperation(value = "Remove profile attributes which names are equal to given",
+ notes = "If names list is not send, all the attributes will be removed, " +
+ "if there are no attributes which names equal to some of the given names, " +
+ "then those names are skipped.")
+ @ApiResponses({@ApiResponse(code = 204, message = "Attributes successfully removed"),
+ @ApiResponse(code = 500, message = "Couldn't remove attributes due to internal server error")})
+ public void removeAttributes(@ApiParam("The names of the profile attributes to remove")
+ List names) throws NotFoundException, ServerException {
+ final Profile profile = profileManager.getById(userId());
+ final Map attributes = profile.getAttributes();
+ if (names == null) {
+ attributes.clear();
+ } else {
+ names.forEach(attributes::remove);
+ }
+ profileManager.update(profile);
+ }
+
+ private static ProfileDto asDto(Profile profile, User user) {
+ return DtoFactory.newDto(ProfileDto.class)
+ .withUserId(profile.getUserId())
+ .withEmail(user.getEmail())
+ .withAttributes(profile.getAttributes());
+ }
+
+ private static String userId() {
+ return EnvironmentContext.getCurrent().getSubject().getUserId();
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/TokenValidator.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/TokenValidator.java
index e5be2caf94..cc890f7807 100644
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/TokenValidator.java
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/TokenValidator.java
@@ -11,7 +11,7 @@
package org.eclipse.che.api.user.server;
import org.eclipse.che.api.core.ConflictException;
-import org.eclipse.che.api.user.server.dao.User;
+import org.eclipse.che.api.core.model.user.User;
/**
* Validates token.
@@ -22,7 +22,7 @@ import org.eclipse.che.api.user.server.dao.User;
public interface TokenValidator {
/**
- * Validates {@param token}
+ * Validates {@code token}.
*
* @return user email
* @throws ConflictException
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/LinksInjector.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserLinksInjector.java
similarity index 54%
rename from wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/LinksInjector.java
rename to wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserLinksInjector.java
index 9eaa226df4..ba823c5d75 100644
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/LinksInjector.java
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserLinksInjector.java
@@ -13,96 +13,88 @@ package org.eclipse.che.api.user.server;
import org.eclipse.che.api.core.rest.ServiceContext;
import org.eclipse.che.api.core.rest.shared.dto.Link;
import org.eclipse.che.api.core.util.LinksHelper;
-import org.eclipse.che.api.user.shared.dto.UserDescriptor;
+import org.eclipse.che.api.user.shared.dto.UserDto;
+import javax.inject.Singleton;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.UriBuilder;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
import static javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_CURRENT_USER;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_CURRENT_USER_PROFILE;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_USER_BY_EMAIL;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_USER_BY_ID;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_USER_PROFILE_BY_ID;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_REMOVE_USER_BY_ID;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_UPDATE_PASSWORD;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_CURRENT_USER;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_CURRENT_USER_PASSWORD;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_CURRENT_USER_SETTINGS;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_PREFERENCES;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_PROFILE;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_SELF;
/**
* Helps to inject {@link UserService} related links.
*
* @author Anatoliy Bazko
+ * @author Yevhenii Voevodin
*/
-public final class LinksInjector {
+@Singleton
+public class UserLinksInjector {
- public static UserDescriptor injectLinks(UserDescriptor userDescriptor, ServiceContext serviceContext) {
+ public UserDto injectLinks(UserDto userDto, ServiceContext serviceContext) {
final UriBuilder uriBuilder = serviceContext.getBaseUriBuilder();
- final List links = new LinkedList<>();
+ final List links = new ArrayList<>(6);
links.add(LinksHelper.createLink(HttpMethod.GET,
- uriBuilder.clone().path(UserProfileService.class)
- .path(UserProfileService.class, "getCurrent")
- .build()
+ uriBuilder.clone()
+ .path(UserService.class)
+ .path(UserService.class, "getById")
+ .build(userDto.getId())
.toString(),
null,
APPLICATION_JSON,
- LINK_REL_GET_CURRENT_USER_PROFILE));
+ LINK_REL_SELF));
links.add(LinksHelper.createLink(HttpMethod.GET,
- uriBuilder.clone().path(UserService.class)
+ uriBuilder.clone()
+ .path(UserService.class)
.path(UserService.class, "getCurrent")
.build()
.toString(),
null,
APPLICATION_JSON,
- LINK_REL_GET_CURRENT_USER));
+ LINK_REL_CURRENT_USER));
links.add(LinksHelper.createLink(HttpMethod.POST,
- uriBuilder.clone().path(UserService.class)
+ uriBuilder.clone()
+ .path(UserService.class)
.path(UserService.class, "updatePassword")
.build()
.toString(),
APPLICATION_FORM_URLENCODED,
null,
- LINK_REL_UPDATE_PASSWORD));
-
+ LINK_REL_CURRENT_USER_PASSWORD));
links.add(LinksHelper.createLink(HttpMethod.GET,
- uriBuilder.clone().path(UserService.class)
- .path(UserService.class, "getById")
- .build(userDescriptor.getId())
+ uriBuilder.clone()
+ .path(ProfileService.class)
+ .path(ProfileService.class, "getById")
+ .build(userDto.getId())
.toString(),
null,
APPLICATION_JSON,
- LINK_REL_GET_USER_BY_ID));
+ LINK_REL_PROFILE));
links.add(LinksHelper.createLink(HttpMethod.GET,
- uriBuilder.clone().path(UserProfileService.class)
- .path(UserProfileService.class, "getById")
- .build(userDescriptor.getId())
+ uriBuilder.clone()
+ .path(UserService.class)
+ .path(UserService.class, "getSettings")
+ .build()
.toString(),
null,
APPLICATION_JSON,
- LINK_REL_GET_USER_PROFILE_BY_ID));
- if (userDescriptor.getEmail() != null) {
- links.add(LinksHelper.createLink(HttpMethod.GET,
- uriBuilder.clone().path(UserService.class)
- .path(UserService.class, "getByAlias")
- .queryParam("email", userDescriptor.getEmail())
- .build()
- .toString(),
- null,
- APPLICATION_JSON,
- LINK_REL_GET_USER_BY_EMAIL));
- }
- links.add(LinksHelper.createLink(HttpMethod.DELETE,
- uriBuilder.clone().path(UserService.class)
- .path(UserService.class, "remove")
- .build(userDescriptor.getId())
+ LINK_REL_CURRENT_USER_SETTINGS));
+ links.add(LinksHelper.createLink(HttpMethod.GET,
+ uriBuilder.clone().path(PreferencesService.class)
+ .path(PreferencesService.class, "find")
+ .build()
.toString(),
null,
- null,
- LINK_REL_REMOVE_USER_BY_ID));
-
- return userDescriptor.withLinks(links);
+ APPLICATION_JSON,
+ LINK_REL_PREFERENCES));
+ return userDto.withLinks(links);
}
-
- private LinksInjector() {}
}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserManager.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserManager.java
index 6f1da2d75b..3cd30c8ab9 100644
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserManager.java
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserManager.java
@@ -10,167 +10,218 @@
*******************************************************************************/
package org.eclipse.che.api.user.server;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
-import org.eclipse.che.api.user.server.dao.Profile;
-import org.eclipse.che.api.user.server.dao.User;
-import org.eclipse.che.api.user.server.dao.UserDao;
-import org.eclipse.che.api.user.server.dao.UserProfileDao;
+import org.eclipse.che.api.core.model.user.Profile;
+import org.eclipse.che.api.core.model.user.User;
+import org.eclipse.che.api.user.server.model.impl.ProfileImpl;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
+import org.eclipse.che.api.user.server.spi.ProfileDao;
+import org.eclipse.che.api.user.server.spi.UserDao;
+import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
+import javax.inject.Singleton;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Set;
import static com.google.common.base.MoreObjects.firstNonNull;
import static java.lang.String.format;
+import static java.lang.System.currentTimeMillis;
+import static java.util.Objects.requireNonNull;
import static org.eclipse.che.api.user.server.Constants.ID_LENGTH;
import static org.eclipse.che.api.user.server.Constants.PASSWORD_LENGTH;
import static org.eclipse.che.commons.lang.NameGenerator.generate;
/**
- * Facade for User related operations.
+ * Facade for {@link User} and {@link Profile} related operations.
*
* @author Max Shaposhnik (mshaposhnik@codenvy.com)
+ * @author Yevhenii Voevodin
*/
+@Singleton
public class UserManager {
-
private static final Logger LOG = LoggerFactory.getLogger(UserManager.class);
- private final UserDao userDao;
- private final UserProfileDao profileDao;
- private final PreferenceDao preferenceDao;
- private final Set reservedNames;
+ private final UserDao userDao;
+ private final ProfileDao profileDao;
+ private final PreferenceDao preferencesDao;
+ private final Set reservedNames;
@Inject
public UserManager(UserDao userDao,
- UserProfileDao profileDao,
- PreferenceDao preferenceDao,
+ ProfileDao profileDao,
+ PreferenceDao preferencesDao,
@Named("user.reserved_names") String[] reservedNames) {
this.userDao = userDao;
this.profileDao = profileDao;
- this.preferenceDao = preferenceDao;
+ this.preferencesDao = preferencesDao;
this.reservedNames = Sets.newHashSet(reservedNames);
}
-
/**
- * Creates new user.
+ * Creates new user and his profile.
*
- * @param user
- * POJO representation of user entity
+ * @param newUser
+ * created user
+ * @throws NullPointerException
+ * when {@code newUser} is null
* @throws ConflictException
- * when given user cannot be created
+ * when user with such name/email/alias already exists
* @throws ServerException
* when any other error occurs
*/
- public void create(User user, boolean isTemporary) throws ConflictException, ServerException {
- if (reservedNames.contains(user.getName().toLowerCase())) {
- throw new ConflictException(String.format("Username \"%s\" is reserved", user.getName()));
+ public User create(User newUser, boolean isTemporary) throws ConflictException, ServerException {
+ requireNonNull(newUser, "Required non-null user");
+ if (reservedNames.contains(newUser.getName().toLowerCase())) {
+ throw new ConflictException(String.format("Username '%s' is reserved", newUser.getName()));
}
- user.withId(generate("user", ID_LENGTH))
- .withPassword(firstNonNull(user.getPassword(), generate("", PASSWORD_LENGTH)));
- userDao.create(user);
-
- profileDao.create(new Profile(user.getId()));
-
- final Map preferences = new HashMap<>(4);
- preferences.put("temporary", Boolean.toString(isTemporary));
- preferences.put("codenvy:created", Long.toString(System.currentTimeMillis()));
+ final UserImpl user = new UserImpl(generate("user", ID_LENGTH),
+ newUser.getEmail(),
+ newUser.getName(),
+ firstNonNull(newUser.getPassword(), generate("", PASSWORD_LENGTH)),
+ newUser.getAliases());
try {
- preferenceDao.setPreferences(user.getId(), preferences);
- } catch (NotFoundException e) {
- LOG.warn(format("Cannot set creation time preferences for user %s.", user.getId()), e);
+ userDao.create(user);
+ profileDao.create(new ProfileImpl(user.getId()));
+ preferencesDao.setPreferences(user.getId(), ImmutableMap.of("temporary", Boolean.toString(isTemporary),
+ "codenvy:created", Long.toString(currentTimeMillis())));
+ } catch (ConflictException | ServerException x) {
+ // optimistic rollback(won't remove profile if userDao.remove failed)
+ // remove operation is not-found-safe so if any exception
+ // during the either user or profile creation occurs remove all entities
+ // NOTE: this logic must be replaced with transaction management
+ try {
+ userDao.remove(user.getId());
+ profileDao.remove(user.getId());
+ preferencesDao.remove(user.getId());
+ } catch (ConflictException | ServerException rollbackEx) {
+ LOG.error(format("An attempt to clean up resources due to user creation failure was unsuccessful." +
+ "Now the system may be in inconsistent state. " +
+ "User with id '%s' must not exist",
+ user.getId()),
+ rollbackEx);
+ }
+ throw x;
}
+ return user;
}
+ /**
+ * Updates user by replacing an existing user entity with a new one.
+ *
+ * @param user
+ * user update
+ * @throws NullPointerException
+ * when {@code user} is null
+ * @throws NotFoundException
+ * when user with id {@code user.getId()} is not found
+ * @throws ConflictException
+ * when user's new alias/email/name is not unique
+ * @throws ServerException
+ * when any other error occurs
+ */
+ public void update(User user) throws NotFoundException, ServerException, ConflictException {
+ requireNonNull(user, "Required non-null user");
+ userDao.update(new UserImpl(user));
+ }
/**
- * Gets user from persistent layer by his identifier
+ * Finds user by given {@code id}.
*
* @param id
* user identifier
- * @return user POJO
+ * @return user instance
+ * @throws NullPointerException
+ * when {@code id} is null
* @throws NotFoundException
* when user doesn't exist
* @throws ServerException
* when any other error occurs
*/
public User getById(String id) throws NotFoundException, ServerException {
+ requireNonNull(id, "Required non-null id");
return userDao.getById(id);
}
-
/**
- * Updates already present in persistent layer user.
- *
- * @param user
- * POJO representation of user entity
- * @throws NotFoundException
- * when user is not found
- * @throws ConflictException
- * when given user cannot be updated
- * @throws ServerException
- * when any other error occurs
- *
- */
- public void update(User user) throws NotFoundException, ServerException, ConflictException {
- userDao.update(user);
- }
-
-
- /**
- * Gets user from persistent layer by any of his aliases
+ * Finds user by given {@code alias}.
*
* @param alias
- * user name or alias
- * @return user POJO
+ * user alias
+ * @return user instance
+ * @throws NullPointerException
+ * when {@code alias} is null
* @throws NotFoundException
* when user doesn't exist
* @throws ServerException
* when any other error occurs
*/
public User getByAlias(String alias) throws NotFoundException, ServerException {
+ requireNonNull(alias, "Required non-null alias");
return userDao.getByAlias(alias);
}
-
/**
- * Gets user from persistent layer by his username
+ * Finds user by given {@code name}.
*
- * @param userName
+ * @param name
* user name
- * @return user POJO
+ * @return user instance
+ * @throws NullPointerException
+ * when {@code name} is null
* @throws NotFoundException
* when user doesn't exist
* @throws ServerException
* when any other error occurs
*/
- public User getByName(String userName) throws NotFoundException, ServerException {
- return userDao.getByName(userName);
+ public User getByName(String name) throws NotFoundException, ServerException {
+ requireNonNull(name, "Required non-null name");
+ return userDao.getByName(name);
}
+ /**
+ * Finds user by given {@code email}.
+ *
+ * @param email
+ * user email
+ * @return user instance
+ * @throws NullPointerException
+ * when {@code email} is null
+ * @throws NotFoundException
+ * when user doesn't exist
+ * @throws ServerException
+ * when any other error occurs
+ */
+ public User getByEmail(String email) throws NotFoundException, ServerException {
+ requireNonNull(email, "Required non-null email");
+ return userDao.getByEmail(email);
+ }
/**
- * Removes user from persistent layer by his identifier.
+ * Removes user and his dependencies by given {@code id}.
*
* @param id
* user identifier
+ * @throws NullPointerException
+ * when {@code id} is null
* @throws ConflictException
* when given user cannot be deleted
* @throws ServerException
* when any other error occurs
*/
- public void remove(String id) throws NotFoundException, ServerException, ConflictException {
+ public void remove(String id) throws ServerException, ConflictException {
+ requireNonNull(id, "Required non-null id");
+ profileDao.remove(id);
+ preferencesDao.remove(id);
userDao.remove(id);
}
}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserProfileService.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserProfileService.java
deleted file mode 100644
index 23d8ccd355..0000000000
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserProfileService.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012-2016 Codenvy, S.A.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Codenvy, S.A. - initial API and implementation
- *******************************************************************************/
-package org.eclipse.che.api.user.server;
-
-
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
-
-import com.google.common.util.concurrent.Striped;
-
-import org.eclipse.che.api.core.ConflictException;
-import org.eclipse.che.api.core.NotFoundException;
-import org.eclipse.che.api.core.ServerException;
-import org.eclipse.che.api.core.rest.Service;
-import org.eclipse.che.api.core.rest.annotations.Description;
-import org.eclipse.che.api.core.rest.annotations.GenerateLink;
-import org.eclipse.che.api.core.rest.annotations.Required;
-import org.eclipse.che.api.core.rest.shared.dto.Link;
-import org.eclipse.che.api.core.util.LinksHelper;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
-import org.eclipse.che.api.user.server.dao.Profile;
-import org.eclipse.che.api.user.server.dao.User;
-import org.eclipse.che.api.user.server.dao.UserDao;
-import org.eclipse.che.api.user.server.dao.UserProfileDao;
-import org.eclipse.che.api.user.shared.dto.ProfileDescriptor;
-import org.eclipse.che.commons.env.EnvironmentContext;
-import org.eclipse.che.commons.subject.Subject;
-import org.eclipse.che.dto.server.DtoFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.inject.Inject;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.UriBuilder;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.locks.Lock;
-
-import static com.google.common.base.Strings.nullToEmpty;
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_CURRENT_USER_PROFILE;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_USER_PROFILE_BY_ID;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_REMOVE_ATTRIBUTES;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_REMOVE_PREFERENCES;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_UPDATE_CURRENT_USER_PROFILE;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_UPDATE_PREFERENCES;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_UPDATE_USER_PROFILE_BY_ID;
-
-/**
- * User Profile API
- *
- * @author Eugene Voevodin
- * @author Max Shaposhnik
- */
-@Api(value = "/profile",
- description = "User profile manager")
-@Path("/profile")
-public class UserProfileService extends Service {
-
- private static final Logger LOG = LoggerFactory.getLogger(UserProfileService.class);
-
- // Assuming 1000 concurrent users at most trying to update their preferences (if more they will wait for another user to finish).
- // Using the lazy weak version of Striped so the locks will be created on demand and not eagerly, and garbage collected when not needed anymore.
- private static final Striped preferencesUpdateLocksByUser = Striped.lazyWeakLock(1000);
-
- private final UserProfileDao profileDao;
- private final UserDao userDao;
- private final PreferenceDao preferenceDao;
-
- @Inject
- public UserProfileService(UserProfileDao profileDao, PreferenceDao preferenceDao, UserDao userDao) {
- this.profileDao = profileDao;
- this.userDao = userDao;
- this.preferenceDao = preferenceDao;
- }
-
- /**
- * Returns {@link ProfileDescriptor} for current user profile.
- * By default user email will be added to attributes with key 'email' .
- *
- * @return descriptor of profile
- * @throws ServerException
- * when some error occurred while retrieving/updating profile
- * @see ProfileDescriptor
- * @see #updateCurrent(Map)
- */
- @ApiOperation(value = "Get user profile",
- notes = "Get user profile details.",
- response = ProfileDescriptor.class)
- @ApiResponses(value = {
- @ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 404, message = "Not Found"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
- @GET
- @GenerateLink(rel = LINK_REL_GET_CURRENT_USER_PROFILE)
- @Produces(APPLICATION_JSON)
- public ProfileDescriptor getCurrent() throws NotFoundException, ServerException {
- final User user = userDao.getById(currentUser().getUserId());
- final Profile profile = profileDao.getById(user.getId());
- profile.getAttributes().put("email", user.getEmail());
- return toDescriptor(profile);
- }
-
- /**
- * Returns preferences for current user
- */
- @ApiOperation(value = "Get user preferences",
- notes = "Get user preferences, like SSH keys, recently opened project and files. It is possible " +
- "to use a filter, e.g. CodenvyAppState or ssh.key.public.github.com to get the last opened project " +
- "or a public part of GitHub SSH key (if any)",
- response = ProfileDescriptor.class)
- @ApiResponses(value = {
- @ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
- @GET
- @Path("/prefs")
- @Produces(APPLICATION_JSON)
- public Map getPreferences(@ApiParam(value = "Filer")
- @QueryParam("filter") String filter) throws ServerException {
- if (filter != null) {
- return preferenceDao.getPreferences(currentUser().getUserId(), filter);
- }
- return preferenceDao.getPreferences(currentUser().getUserId());
- }
-
- /**
- * Updates attributes of current user profile.
- *
- * @param updates
- * attributes to update
- * @return descriptor of updated profile
- * @throws ServerException
- * when some error occurred while retrieving/persisting profile
- * @see ProfileDescriptor
- */
-
- @POST
- @GenerateLink(rel = LINK_REL_UPDATE_CURRENT_USER_PROFILE)
- @Consumes(APPLICATION_JSON)
- @Produces(APPLICATION_JSON)
- public ProfileDescriptor updateCurrent(@Description("attributes to update") Map updates)
- throws NotFoundException, ServerException, ConflictException {
- if (updates == null || updates.isEmpty()) {
- throw new ConflictException("Attributes to update required");
- }
- final User user = userDao.getById(currentUser().getUserId());
- final Profile profile = profileDao.getById(user.getId());
- profile.getAttributes().putAll(updates);
- profileDao.update(profile);
- logEventUserUpdateProfile(user, profile.getAttributes());
- return toDescriptor(profile);
- }
-
-
- /**
- * Updates attributes of certain profile.
- *
- * @param profileId
- * profile identifier
- * @param updates
- * attributes to update
- * @return descriptor of updated profile
- * @throws NotFoundException
- * when profile with given identifier doesn't exist
- * @throws ServerException
- * when some error occurred while retrieving/updating profile
- * @see ProfileDescriptor
- * @see #getById(String)
- */
-
- @POST
- @Path("/{id}")
- @Consumes(APPLICATION_JSON)
- @Produces(APPLICATION_JSON)
- public ProfileDescriptor update(@PathParam("id") String profileId,
- Map updates) throws NotFoundException, ServerException, ConflictException {
- if (updates == null || updates.isEmpty()) {
- throw new ConflictException("Attributes to update required");
- }
- final Profile profile = profileDao.getById(profileId);
- profile.getAttributes().putAll(updates);
- profileDao.update(profile);
- final User user = userDao.getById(profile.getUserId());
- logEventUserUpdateProfile(user, profile.getAttributes());
- return toDescriptor(profile);
- }
-
- /**
- * Searches for profile with given identifier and {@link ProfileDescriptor} if found.
- *
- * @param profileId
- * profile identifier
- * @return descriptor of found profile
- * @throws NotFoundException
- * when profile with given identifier doesn't exist
- * @throws ServerException
- * when some error occurred while retrieving user or profile
- * @see ProfileDescriptor
- * @see #getById(String)
- */
- @ApiOperation(value = "Get profile of a specific user",
- notes = "Get profile of a specific user",
- response = ProfileDescriptor.class)
- @ApiResponses(value = {
- @ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 404, message = "Not Found"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
- @GET
- @Path("/{id}")
- @Produces(APPLICATION_JSON)
- public ProfileDescriptor getById(@ApiParam(value = " ID")
- @PathParam("id")
- String profileId) throws NotFoundException, ServerException {
- final Profile profile = profileDao.getById(profileId);
- final User user = userDao.getById(profile.getUserId());
- profile.getAttributes().put("email", user.getEmail());
- return toDescriptor(profile);
- }
-
- /**
- * Updates preferences of current user profile.
- *
- * @param update
- * update preferences
- * @return descriptor of updated profile
- * @throws ServerException
- * when some error occurred while retrieving/updating profile
- * @throws ConflictException
- * when update is {@code null} or empty
- * @see ProfileDescriptor
- * @see #updateCurrent(Map)
- */
- @POST
- @Path("/prefs")
- @GenerateLink(rel = LINK_REL_UPDATE_PREFERENCES)
- @Consumes(APPLICATION_JSON)
- @Produces(APPLICATION_JSON)
- public Map updatePreferences(@Required Map update) throws NotFoundException,
- ServerException,
- ConflictException {
- if (update == null || update.isEmpty()) {
- throw new ConflictException("Preferences to update required");
- }
-
- String userId = currentUser().getUserId();
- // Keep the lock in a variable so it isn't garbage collected while in use
- Lock lock = preferencesUpdateLocksByUser.get(userId);
- lock.lock();
- try {
- final Map preferences = preferenceDao.getPreferences(userId);
- preferences.putAll(update);
- preferenceDao.setPreferences(currentUser().getUserId(), preferences);
- return preferences;
- } finally {
- lock.unlock();
- }
- }
-
- /**
- * Removes attributes with given names from current user profile.
- * If names are {@code null} - all attributes will be removed
- *
- * @param attrNames
- * attributes names to remove
- * @throws ConflictException
- * when given list of attributes names is {@code null}
- * @throws ServerException
- * when some error occurred while retrieving/updating profile
- */
- @ApiOperation(value = "Remove attributes of a current user",
- notes = "Remove attributes of a current user",
- position = 6)
- @ApiResponses(value = {
- @ApiResponse(code = 204, message = "OK"),
- @ApiResponse(code = 404, message = "Not Found"),
- @ApiResponse(code = 409, message = "Attributes names required"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
- @DELETE
- @Path("/attributes")
- @GenerateLink(rel = LINK_REL_REMOVE_ATTRIBUTES)
- @Consumes(APPLICATION_JSON)
- public void removeAttributes(@ApiParam(value = "Attributes", required = true)
- @Required
- @Description("Attributes names to remove")
- List attrNames) throws NotFoundException, ServerException, ConflictException {
- final Profile currentProfile = profileDao.getById(currentUser().getUserId());
- if (attrNames == null) {
- currentProfile.getAttributes().clear();
- } else {
- for (String attributeName : attrNames) {
- currentProfile.getAttributes().remove(attributeName);
- }
- }
- profileDao.update(currentProfile);
- }
-
- /**
- * Removes preferences with given name from current user profile.
- * If names are {@code null} - all preferences will be removed
- *
- * @param names
- * preferences names to remove
- * @throws ServerException
- * when some error occurred while retrieving/updating profile
- * @see #removeAttributes(List)
- */
- @ApiOperation(value = "Remove profile references of a current user",
- notes = "Remove profile references of a current user",
- position = 7)
- @ApiResponses(value = {
- @ApiResponse(code = 204, message = "OK"),
- @ApiResponse(code = 404, message = "Not Found"),
- @ApiResponse(code = 409, message = "Preferences names required"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
- @DELETE
- @Path("/prefs")
- @GenerateLink(rel = LINK_REL_REMOVE_PREFERENCES)
- @Consumes(APPLICATION_JSON)
- public void removePreferences(@ApiParam(value = "Preferences to remove", required = true)
- @Required
- List names) throws ServerException, NotFoundException {
- String userId = currentUser().getUserId();
- if (names == null) {
- preferenceDao.remove(userId);
- } else {
- // Keep the lock in a variable so it isn't garbage collected while in use
- Lock lock = preferencesUpdateLocksByUser.get(userId);
- lock.lock();
- try {
- final Map preferences = preferenceDao.getPreferences(userId);
- for (String name : names) {
- preferences.remove(name);
- }
- preferenceDao.setPreferences(userId, preferences);
- } finally {
- lock.unlock();
- }
- }
- }
-
- /**
- * Converts {@link Profile} to {@link ProfileDescriptor}
- */
- /* package-private used in tests*/ProfileDescriptor toDescriptor(Profile profile) {
- final UriBuilder uriBuilder = getServiceContext().getServiceUriBuilder();
- final List links = new LinkedList<>();
- links.add(LinksHelper.createLink(HttpMethod.GET,
- uriBuilder.clone()
- .path(getClass(), "getCurrent")
- .build()
- .toString(),
- null,
- APPLICATION_JSON,
- LINK_REL_GET_CURRENT_USER_PROFILE));
- links.add(LinksHelper.createLink(HttpMethod.GET,
- uriBuilder.clone()
- .path(getClass(), "getById")
- .build(profile.getId())
- .toString(),
- null,
- APPLICATION_JSON,
- LINK_REL_GET_USER_PROFILE_BY_ID));
- links.add(LinksHelper.createLink(HttpMethod.POST,
- uriBuilder.clone()
- .path(getClass(), "updateCurrent")
- .build()
- .toString(),
- APPLICATION_JSON,
- APPLICATION_JSON,
- LINK_REL_UPDATE_CURRENT_USER_PROFILE));
- links.add(LinksHelper.createLink(HttpMethod.POST,
- uriBuilder.clone()
- .path(getClass(), "updatePreferences")
- .build()
- .toString(),
- APPLICATION_JSON,
- APPLICATION_JSON,
- LINK_REL_UPDATE_PREFERENCES));
- links.add(LinksHelper.createLink(HttpMethod.GET,
- uriBuilder.clone()
- .path(getClass(), "getById")
- .build(profile.getId())
- .toString(),
- null,
- APPLICATION_JSON,
- LINK_REL_GET_USER_PROFILE_BY_ID));
- links.add(LinksHelper.createLink(HttpMethod.POST,
- uriBuilder.clone()
- .path(getClass(), "update")
- .build(profile.getId())
- .toString(),
- APPLICATION_JSON,
- APPLICATION_JSON,
- LINK_REL_UPDATE_USER_PROFILE_BY_ID));
- return DtoFactory.newDto(ProfileDescriptor.class)
- .withId(profile.getId())
- .withUserId(profile.getUserId())
- .withAttributes(profile.getAttributes())
- .withLinks(links);
- }
-
- private Subject currentUser() {
- return EnvironmentContext.getCurrent().getSubject();
- }
-
- private void logEventUserUpdateProfile(User user, Map attributes) {
- final Set emails = new HashSet<>(user.getAliases());
- emails.add(user.getEmail());
-
- LOG.info("EVENT#user-update-profile# USER#{}# FIRSTNAME#{}# LASTNAME#{}# COMPANY#{}# PHONE#{}# JOBTITLE#{}# EMAILS#{}# USER-ID#{}#",
- user.getEmail(),
- nullToEmpty(attributes.get("firstName")),
- nullToEmpty(attributes.get("lastName")),
- nullToEmpty(attributes.get("employer")),
- nullToEmpty(attributes.get("phone")),
- nullToEmpty(attributes.get("jobtitle")),
- user.getAliases(),
- user.getId());
- }
-}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserService.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserService.java
index 6ba7f67405..a47fff2dd7 100644
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserService.java
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserService.java
@@ -20,15 +20,14 @@ import com.google.common.collect.ImmutableMap;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ConflictException;
-import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.UnauthorizedException;
+import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.core.rest.Service;
import org.eclipse.che.api.core.rest.annotations.GenerateLink;
-import org.eclipse.che.api.core.rest.annotations.Required;
-import org.eclipse.che.api.user.server.dao.User;
-import org.eclipse.che.api.user.shared.dto.UserDescriptor;
+import org.eclipse.che.api.user.server.model.impl.UserImpl;
+import org.eclipse.che.api.user.shared.dto.UserDto;
import org.eclipse.che.commons.env.EnvironmentContext;
import javax.inject.Inject;
@@ -46,301 +45,162 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import java.util.Map;
-import static com.google.common.base.Strings.isNullOrEmpty;
import static javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.Response.Status.CREATED;
-import static javax.ws.rs.core.Response.status;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_CREATE_USER;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_CURRENT_USER;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_USER_BY_EMAIL;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_USER_BY_ID;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_REMOVE_USER_BY_ID;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_UPDATE_PASSWORD;
-import static org.eclipse.che.api.user.server.DtoConverter.toDescriptor;
-import static org.eclipse.che.api.user.server.LinksInjector.injectLinks;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_CURRENT_USER;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_CURRENT_USER_PASSWORD;
+import static org.eclipse.che.api.user.server.Constants.LINK_REL_USER;
+import static org.eclipse.che.api.user.server.DtoConverter.asDto;
/**
- * Provides REST API for user management
+ * User REST API.
*
- * @author Eugene Voevodin
+ * @author Yevhenii Voevodin
* @author Anton Korneta
*/
-@Api(value = "/user", description = "User manager")
@Path("/user")
+@Api(value = "/user", description = "User REST API")
public class UserService extends Service {
public static final String USER_SELF_CREATION_ALLOWED = "user.self.creation.allowed";
private final UserManager userManager;
private final TokenValidator tokenValidator;
- private final UserNameValidator userNameValidator;
+ private final UserLinksInjector linksInjector;
+ private final UserValidator userValidator;
private final boolean userSelfCreationAllowed;
@Inject
public UserService(UserManager userManager,
TokenValidator tokenValidator,
- UserNameValidator userNameValidator,
+ UserValidator userNameValidator,
+ UserLinksInjector linksInjector,
@Named(USER_SELF_CREATION_ALLOWED) boolean userSelfCreationAllowed) {
this.userManager = userManager;
+ this.linksInjector = linksInjector;
this.tokenValidator = tokenValidator;
- this.userNameValidator = userNameValidator;
+ this.userValidator = userNameValidator;
this.userSelfCreationAllowed = userSelfCreationAllowed;
}
- /**
- * Creates new user and profile.
- *
- * User will be created from {@code token} parameter or from {@code userDescriptor}
- * when {@code token} is null
- *
- * @param token
- * authentication token
- * @param isTemporary
- * if it is {@code true} creates temporary user
- * @return entity of created user
- * @throws ForbiddenException
- * when the user is not the system admin, or self creation is disabled
- * @throws BadRequestException
- * when {@code userDescriptor} is invalid
- * @throws UnauthorizedException
- * when token is null
- * @throws ConflictException
- * when token is not valid
- * @throws ServerException
- * when some error occurred while persisting user or user profile
- * @see UserDescriptor
- * @see #getCurrent()
- * @see #updatePassword(String)
- * @see #getById(String)
- * @see #getByAlias(String)
- * @see #remove(String)
- */
@POST
- @Path("/create")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
- @GenerateLink(rel = LINK_REL_CREATE_USER)
- @ApiOperation(value = "Create a new user",
- notes = "Create a new user in the system. There are two ways to create a user: " +
- "through a regular registration workflow when auth token is sent to user's mailbox" +
- "and directly with predefined name and password. ",
- response = UserDescriptor.class)
- @ApiResponses({@ApiResponse(code = 201, message = "Created"),
+ @GenerateLink(rel = LINK_REL_USER)
+ @ApiOperation(value = "Create a new user", response = UserDto.class)
+ @ApiResponses({@ApiResponse(code = 201, message = "User successfully created, response contains created entity"),
@ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
@ApiResponse(code = 401, message = "Missed token parameter"),
- @ApiResponse(code = 403, message = "Invalid or missing request parameters"),
- @ApiResponse(code = 409, message = "Invalid token"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
- public Response create(@ApiParam(value = "New user")
- UserDescriptor userDescriptor,
- @ApiParam(value = "Authentication token")
+ @ApiResponse(code = 500, message = "Couldn't create user due to internal server error")})
+ public Response create(@ApiParam("New user")
+ UserDto userDto,
+ @ApiParam("Authentication token")
@QueryParam("token")
String token,
- @ApiParam(value = "User type")
+ @ApiParam("User type")
@QueryParam("temporary")
@DefaultValue("false")
- Boolean isTemporary) throws ForbiddenException,
- BadRequestException,
+ Boolean isTemporary) throws BadRequestException,
UnauthorizedException,
ConflictException,
- ServerException,
- NotFoundException {
- final User user = isNullOrEmpty(token) ? fromEntity(userDescriptor) : fromToken(token);
- if (!userNameValidator.isValidUserName(user.getName())) {
- throw new BadRequestException("Username must contain only letters and digits");
- }
- userManager.create(user, isTemporary);
- return status(CREATED).entity(injectLinks(toDescriptor(user), getServiceContext())).build();
+ ServerException {
+ final User newUser = token == null ? userDto : tokenValidator.validateToken(token);
+ userValidator.checkUser(newUser);
+ return Response.status(CREATED)
+ .entity(linksInjector.injectLinks(asDto(userManager.create(newUser, isTemporary)), getServiceContext()))
+ .build();
}
- /**
- * Returns {@link UserDescriptor} of current user.
- *
- * @return entity of current user.
- * @throws NotFoundException
- * when current user not found
- * @throws ServerException
- * when some error occurred while retrieving current user
- */
@GET
- @GenerateLink(rel = LINK_REL_GET_CURRENT_USER)
@Produces(APPLICATION_JSON)
- @ApiOperation(value = "Get current user",
- notes = "Get user currently logged in the system",
- response = UserDescriptor.class,
- position = 2)
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 404, message = "Not Found"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
- public UserDescriptor getCurrent() throws NotFoundException, ServerException {
- final User user = userManager.getById(currentUserId());
- return injectLinks(toDescriptor(user), getServiceContext());
+ @GenerateLink(rel = LINK_REL_CURRENT_USER)
+ @ApiOperation("Get logged in user")
+ @ApiResponses({@ApiResponse(code = 200, message = "The response contains currently logged in user entity"),
+ @ApiResponse(code = 500, message = "Couldn't get user due to internal server error")})
+ public UserDto getCurrent() throws NotFoundException, ServerException {
+ final User user = userManager.getById(userId());
+ return linksInjector.injectLinks(asDto(user), getServiceContext());
}
- /**
- * Updates current user password.
- *
- * @param password
- * new user password
- * @throws NotFoundException
- * when current user not found
- * @throws BadRequestException
- * when given password is invalid
- * @throws ServerException
- * when some error occurred while updating profile
- * @see UserDescriptor
- */
@POST
@Path("/password")
- @GenerateLink(rel = LINK_REL_UPDATE_PASSWORD)
@Consumes(APPLICATION_FORM_URLENCODED)
- @ApiOperation(value = "Update password",
- notes = "Update current password")
- @ApiResponses({@ApiResponse(code = 204, message = "OK"),
- @ApiResponse(code = 400, message = "Invalid password"),
- @ApiResponse(code = 404, message = "Not Found"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
+ @GenerateLink(rel = LINK_REL_CURRENT_USER_PASSWORD)
+ @ApiOperation(value = "Update password of logged in user",
+ notes = "Password must contain at least 8 characters, " +
+ "passport must contain letters and digits")
+ @ApiResponses({@ApiResponse(code = 204, message = "Password successfully updated"),
+ @ApiResponse(code = 400, message = "Incoming password is invalid value." +
+ "Valid password must contain at least 8 character " +
+ "which are letters and digits"),
+ @ApiResponse(code = 500, message = "Couldn't update password due to internal server error")})
public void updatePassword(@ApiParam(value = "New password", required = true)
@FormParam("password")
String password) throws NotFoundException,
BadRequestException,
ServerException,
ConflictException {
+ userValidator.checkPassword(password);
- checkPassword(password);
-
- final User user = userManager.getById(currentUserId());
+ final UserImpl user = new UserImpl(userManager.getById(userId()));
user.setPassword(password);
userManager.update(user);
}
- /**
- * Returns status 200 and {@link UserDescriptor} built from user with given {@code id}
- * or status 404 when user with given {@code id} was not found.
- *
- * @param id
- * identifier to search user
- * @return entity of found user
- * @throws NotFoundException
- * when user with given identifier doesn't exist
- * @throws ServerException
- * when some error occurred while retrieving user
- * @see UserDescriptor
- * @see #getByAlias(String)
- */
@GET
@Path("/{id}")
- @GenerateLink(rel = LINK_REL_GET_USER_BY_ID)
@Produces(APPLICATION_JSON)
- @ApiOperation(value = "Get user by ID",
- notes = "Get user by its ID in the system",
- response = UserDescriptor.class)
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 404, message = "Not Found"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
- public UserDescriptor getById(@ApiParam(value = "User ID") @PathParam("id") String id) throws NotFoundException,
- ServerException {
+ @GenerateLink(rel = LINK_REL_USER)
+ @ApiOperation("Get user by identifier")
+ @ApiResponses({@ApiResponse(code = 200, message = "The response contains requested user entity"),
+ @ApiResponse(code = 404, message = "User with requested identifier not found"),
+ @ApiResponse(code = 500, message = "Impossible to get user due to internal server error")})
+ public UserDto getById(@ApiParam("User identifier")
+ @PathParam("id")
+ String id) throws NotFoundException, ServerException {
final User user = userManager.getById(id);
- return injectLinks(toDescriptor(user), getServiceContext());
+ return linksInjector.injectLinks(asDto(user), getServiceContext());
}
- /**
- * Returns status 200 and {@link UserDescriptor} built from user with given {@code alias}
- * or status 404 when user with given {@code alias} was not found.
- *
- * @param alias
- * alias to search user
- * @return entity of found user
- * @throws NotFoundException
- * when user with given alias doesn't exist
- * @throws ServerException
- * when some error occurred while retrieving user
- * @throws BadRequestException
- * when alias parameter is missing
- * @see UserDescriptor
- * @see #getById(String)
- * @see #remove(String)
- */
@GET
@Path("/find")
- @GenerateLink(rel = LINK_REL_GET_USER_BY_EMAIL)
@Produces(APPLICATION_JSON)
- @ApiOperation(value = "Get user by alias",
- notes = "Get user by alias",
- response = UserDescriptor.class)
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 400, message = "Missed alias parameter"),
- @ApiResponse(code = 404, message = "Not Found"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
- public UserDescriptor getByAlias(@ApiParam(value = "User alias", required = true)
- @QueryParam("alias")
- @Required String alias) throws NotFoundException,
- ServerException,
- BadRequestException {
- if (alias == null) {
- throw new BadRequestException("Missed parameter alias");
+ @GenerateLink(rel = LINK_REL_USER)
+ @ApiOperation("Get user by email or name")
+ @ApiResponses({@ApiResponse(code = 200, message = "The response contains requested user entity"),
+ @ApiResponse(code = 404, message = "User with requested email/name not found"),
+ @ApiResponse(code = 500, message = "Impossible to get user due to internal server error")})
+ public UserDto find(@ApiParam("User email, if it is set then name shouldn't be")
+ @QueryParam("email")
+ String email,
+ @ApiParam("User name, if is is set then email shouldn't be")
+ @QueryParam("name")
+ String name) throws NotFoundException,
+ ServerException,
+ BadRequestException {
+ if (email == null && name == null) {
+ throw new BadRequestException("Missed user's email or name");
}
- final User user = userManager.getByAlias(alias);
- return injectLinks(toDescriptor(user), getServiceContext());
+ if (email != null && name != null) {
+ throw new BadRequestException("Expected either user's email or name, while both values received");
+ }
+ final User user = name == null ? userManager.getByEmail(email) : userManager.getByName(name);
+ return linksInjector.injectLinks(asDto(user), getServiceContext());
}
- /**
- * Removes user with given identifier.
- *
- * @param id
- * identifier to remove user
- * @throws NotFoundException
- * when user with given identifier doesn't exist
- * @throws ServerException
- * when some error occurred while removing user
- * @throws ConflictException
- * when some error occurred while removing user
- */
@DELETE
@Path("/{id}")
- @GenerateLink(rel = LINK_REL_REMOVE_USER_BY_ID)
- @ApiOperation(value = "Delete user",
- notes = "Delete a user from the system")
- @ApiResponses({@ApiResponse(code = 204, message = "Deleted"),
- @ApiResponse(code = 404, message = "Not Found"),
- @ApiResponse(code = 409, message = "Impossible to remove user"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
- public void remove(@ApiParam(value = "User ID") @PathParam("id") String id) throws NotFoundException,
- ServerException,
- ConflictException {
+ @GenerateLink(rel = LINK_REL_USER)
+ @ApiOperation("Delete user")
+ @ApiResponses({@ApiResponse(code = 204, message = "User successfully removed"),
+ @ApiResponse(code = 409, message = "Couldn't remove user due to conflict(e.g. it has related entities)"),
+ @ApiResponse(code = 500, message = "Couldn't remove user due to internal server error")})
+ public void remove(@ApiParam("User identifier")
+ @PathParam("id")
+ String id) throws ServerException, ConflictException {
userManager.remove(id);
}
- /**
- * Get user by name.
- *
- * @param name
- * user name
- * @return found user
- * @throws NotFoundException
- * when user with given name doesn't exist
- * @throws ServerException
- * when some error occurred while retrieving user
- */
- @GET
- @Path("/name/{name}")
- @GenerateLink(rel = "get user by name")
- @Produces(APPLICATION_JSON)
- @ApiOperation(value = "Get user by name",
- notes = "Get user by its name in the system")
- @ApiResponses({@ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 404, message = "Not Found"),
- @ApiResponse(code = 500, message = "Internal Server Error")})
- public UserDescriptor getByName(@ApiParam(value = "User email")
- @PathParam("name")
- String name) throws NotFoundException, ServerException {
- final User user = userManager.getByName(name);
- return injectLinks(toDescriptor(user), getServiceContext());
- }
-
- /**
- * Get setting of user service
- */
@GET
@Path("/settings")
@Produces(APPLICATION_JSON)
@@ -348,64 +208,7 @@ public class UserService extends Service {
return ImmutableMap.of(USER_SELF_CREATION_ALLOWED, Boolean.toString(userSelfCreationAllowed));
}
- private User fromEntity(UserDescriptor userDescriptor) throws BadRequestException {
- if (userDescriptor == null) {
- throw new BadRequestException("User Descriptor required");
- }
- if (isNullOrEmpty(userDescriptor.getName())) {
- throw new BadRequestException("User name required");
- }
- if (isNullOrEmpty(userDescriptor.getEmail())) {
- throw new BadRequestException("User email required");
- }
- final User user = new User().withName(userDescriptor.getName())
- .withEmail(userDescriptor.getEmail());
- if (userDescriptor.getPassword() != null) {
- checkPassword(userDescriptor.getPassword());
- user.setPassword(userDescriptor.getPassword());
- }
- return user;
- }
-
- private User fromToken(String token) throws UnauthorizedException, ConflictException {
- return tokenValidator.validateToken(token);
- }
-
- /**
- * Checks user password conforms some rules:
- *
- * Not null
- * Must be at least 8 character length
- * Must contain at least one letter and one digit
- *
- *
- * @param password
- * user's password
- * @throws BadRequestException
- * when password violates any rule
- */
- private void checkPassword(String password) throws BadRequestException {
- if (password == null) {
- throw new BadRequestException("Password required");
- }
- if (password.length() < 8) {
- throw new BadRequestException("Password should contain at least 8 characters");
- }
- int numOfLetters = 0;
- int numOfDigits = 0;
- for (char passwordChar : password.toCharArray()) {
- if (Character.isDigit(passwordChar)) {
- numOfDigits++;
- } else if (Character.isLetter(passwordChar)) {
- numOfLetters++;
- }
- }
- if (numOfDigits == 0 || numOfLetters == 0) {
- throw new BadRequestException("Password should contain letters and digits");
- }
- }
-
- private String currentUserId() {
+ private static String userId() {
return EnvironmentContext.getCurrent().getSubject().getUserId();
}
}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserNameValidator.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserValidator.java
similarity index 51%
rename from wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserNameValidator.java
rename to wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserValidator.java
index 871ed552a4..45c132f0f1 100644
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserNameValidator.java
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/UserValidator.java
@@ -10,8 +10,10 @@
*******************************************************************************/
package org.eclipse.che.api.user.server;
+import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.commons.lang.NameGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -19,13 +21,17 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.util.regex.Pattern;
+import static com.google.common.base.Strings.isNullOrEmpty;
+
+// TODO extract normalization code from the validator as it is not related to the validation at all
/**
* Utils for username validation and normalization.
*
* @author Mihail Kuznyetsov
+ * @author Yevhenii Voevodin
*/
-public class UserNameValidator {
- private static final Logger LOG = LoggerFactory.getLogger(UserNameValidator.class);
+public class UserValidator {
+ private static final Logger LOG = LoggerFactory.getLogger(UserValidator.class);
private static final Pattern ILLEGAL_USERNAME_CHARACTERS = Pattern.compile("[^a-zA-Z0-9]");
private static final Pattern VALID_USERNAME = Pattern.compile("^[a-zA-Z0-9]*");
@@ -33,19 +39,74 @@ public class UserNameValidator {
private final UserManager userManager;
@Inject
- public UserNameValidator (UserManager userManager) {
+ public UserValidator(UserManager userManager) {
this.userManager = userManager;
}
+ /**
+ * Checks whether given user is valid.
+ *
+ * @param user
+ * user to check
+ * @throws BadRequestException
+ * when user is not valid
+ */
+ public void checkUser(User user) throws BadRequestException {
+ if (user == null) {
+ throw new BadRequestException("User required");
+ }
+ if (isNullOrEmpty(user.getName())) {
+ throw new BadRequestException("User name required");
+ }
+ if (!isValidName(user.getName())) {
+ throw new BadRequestException("Username must contain only letters and digits");
+ }
+ if (isNullOrEmpty(user.getEmail())) {
+ throw new BadRequestException("User email required");
+ }
+ if (user.getPassword() != null) {
+ checkPassword(user.getPassword());
+ }
+ }
+
+ /**
+ * Checks whether password is ok.
+ *
+ * @param password
+ * password to check
+ * @throws BadRequestException
+ * when password is not valid
+ */
+ public void checkPassword(String password) throws BadRequestException {
+ if (password == null) {
+ throw new BadRequestException("Password required");
+ }
+ if (password.length() < 8) {
+ throw new BadRequestException("Password should contain at least 8 characters");
+ }
+ int numOfLetters = 0;
+ int numOfDigits = 0;
+ for (char passwordChar : password.toCharArray()) {
+ if (Character.isDigit(passwordChar)) {
+ numOfDigits++;
+ } else if (Character.isLetter(passwordChar)) {
+ numOfLetters++;
+ }
+ }
+ if (numOfDigits == 0 || numOfLetters == 0) {
+ throw new BadRequestException("Password should contain letters and digits");
+ }
+ }
+
/**
* Validate name, if it doesn't contain illegal characters
*
* @param name
- * username
+ * username
* @return true if valid name, false otherwise
*/
- public boolean isValidUserName(String name) {
- return VALID_USERNAME.matcher(name).matches();
+ public boolean isValidName(String name) {
+ return name != null && VALID_USERNAME.matcher(name).matches();
}
/**
@@ -54,7 +115,7 @@ public class UserNameValidator {
* Also ensures username is unique, if not, adds digits to it's end.
*
* @param name
- * username
+ * username
* @return username without illegal characters
*/
public String normalizeUserName(String name) throws ServerException {
@@ -67,7 +128,7 @@ public class UserNameValidator {
candidate = normalized.isEmpty() ? NameGenerator.generate("username", 4) : normalized + String.valueOf(i++);
}
} catch (ServerException e) {
- LOG.warn("Error occured during username normalization", e);
+ LOG.warn("Error occurred during username normalization", e);
throw e;
}
return candidate;
@@ -78,8 +139,6 @@ public class UserNameValidator {
userManager.getByName(username);
} catch (NotFoundException e) {
return false;
- } catch (ServerException e) {
- throw e;
}
return true;
}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/UserDao.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/UserDao.java
deleted file mode 100644
index 19eeea893a..0000000000
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/UserDao.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012-2016 Codenvy, S.A.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Codenvy, S.A. - initial API and implementation
- *******************************************************************************/
-package org.eclipse.che.api.user.server.dao;
-
-import org.eclipse.che.api.core.ConflictException;
-import org.eclipse.che.api.core.NotFoundException;
-import org.eclipse.che.api.core.ServerException;
-import org.eclipse.che.api.core.UnauthorizedException;
-
-/**
- * DAO interface offers means to perform CRUD operations with {@link User} data. The implementation is not
- * required to be responsible for persistent layer data dto integrity. It simply transfers data from one layer to another, so if
- * you're going to call any of implemented methods it is considered that all needed verifications are already done.
- * Note: This particularly does not mean that method call will not make any inconsistency, but this
- * mean that such kind of inconsistencies are expected by design and may be treated further.
- */
-public interface UserDao {
-
- /**
- * Authenticate user.
- *
- * @param alias
- * user name or alias
- * @param password
- * password
- * @return user id when authentication success
- * @throws UnauthorizedException
- * when authentication failed or no such user exists
- * @throws ServerException
- * when any other error occurs
- *
- */
- String authenticate(String alias, String password) throws UnauthorizedException, ServerException;
-
- /**
- * Adds user to persistent layer.
- *
- * @param user
- * - POJO representation of user entity
- * @throws ConflictException
- * when given user cannot be created
- * @throws ServerException
- * when any other error occurs
- */
- void create(User user) throws ConflictException, ServerException;
-
- /**
- * Updates already present in persistent layer user.
- *
- * @param user
- * POJO representation of user entity
- * @throws NotFoundException
- * when user is not found
- * @throws ConflictException
- * when given user cannot be updated
- * @throws ServerException
- * when any other error occurs
- *
- */
- void update(User user) throws NotFoundException, ServerException, ConflictException;
-
- /**
- * Removes user from persistent layer by his identifier.
- *
- * @param id
- * user identifier
- * @throws ConflictException
- * when given user cannot be deleted
- * @throws ServerException
- * when any other error occurs
- */
- void remove(String id) throws NotFoundException, ServerException, ConflictException;
-
- /**
- * Gets user from persistent layer by any of his aliases
- *
- * @param alias
- * user name or alias
- * @return user POJO
- * @throws NotFoundException
- * when user doesn't exist
- * @throws ServerException
- * when any other error occurs
- */
- User getByAlias(String alias) throws NotFoundException, ServerException;
-
- /**
- * Gets user from persistent layer by his identifier
- *
- * @param id
- * user identifier
- * @return user POJO
- * @throws NotFoundException
- * when user doesn't exist
- * @throws ServerException
- * when any other error occurs
- */
- User getById(String id) throws NotFoundException, ServerException;
-
- /**
- * Gets user from persistent layer by his username
- *
- * @param userName
- * user name
- * @return user POJO
- * @throws NotFoundException
- * when user doesn't exist
- * @throws ServerException
- * when any other error occurs
- */
- User getByName(String userName) throws NotFoundException, ServerException;
-}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/UserProfileDao.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/UserProfileDao.java
deleted file mode 100644
index 2f75d2e571..0000000000
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/UserProfileDao.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012-2016 Codenvy, S.A.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Codenvy, S.A. - initial API and implementation
- *******************************************************************************/
-package org.eclipse.che.api.user.server.dao;
-
-
-import org.eclipse.che.api.core.ConflictException;
-import org.eclipse.che.api.core.NotFoundException;
-import org.eclipse.che.api.core.ServerException;
-
-/**
- * DAO interface offers means to perform CRUD operations with {@link Profile} data.
- *
- * @author Eugene Voevodin
- * @author Max Shaposhnik
- */
-public interface UserProfileDao {
-
- /**
- * Adds profile to persistent layer.
- *
- * @param profile
- * profile to setPreferences
- */
- void create(Profile profile) throws ConflictException, ServerException;
-
- /**
- * Updates already present in persistent layer profile.
- *
- * @param profile
- * profile to update
- */
- void update(Profile profile) throws NotFoundException, ServerException;
-
- /**
- * Removes profile from persistent layer.
- *
- * @param id
- * profile identifier
- */
- void remove(String id) throws NotFoundException, ServerException;
-
- /**
- * Gets profile from persistent layer.
- *
- * @param id
- * profile identifier
- * @return profile with given {@code id}
- * @throws org.eclipse.che.api.core.NotFoundException
- * when profile doesn't exist
- */
- Profile getById(String id) throws NotFoundException, ServerException;
-}
\ No newline at end of file
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/Profile.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/model/impl/ProfileImpl.java
similarity index 55%
rename from wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/Profile.java
rename to wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/model/impl/ProfileImpl.java
index 428eee8741..a8d5dbd412 100644
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/Profile.java
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/model/impl/ProfileImpl.java
@@ -8,57 +8,48 @@
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
-package org.eclipse.che.api.user.server.dao;
+package org.eclipse.che.api.user.server.model.impl;
+
+import org.eclipse.che.api.core.model.user.Profile;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
- * @author Eugene Voevodin
+ * Data object for the {@link Profile}.
+ *
+ * @author Yevhenii Voevodin
*/
-public class Profile {
+public class ProfileImpl implements Profile {
private String id;
- private String userId;
private Map attributes;
- public Profile() {}
-
- public Profile(String id) {
+ public ProfileImpl(String id) {
this.id = id;
- this.userId = id;
}
- public String getId() {
+ public ProfileImpl(String id, Map attributes) {
+ this.id = id;
+ if (attributes != null) {
+ this.attributes = new HashMap<>(attributes);
+ }
+ }
+
+ public ProfileImpl(Profile profile) {
+ this(profile.getUserId(), profile.getAttributes());
+ }
+
+ @Override
+ public String getUserId() {
return id;
}
- public void setId(String id) {
- this.id = id;
- }
-
- public Profile withId(String id) {
- this.id = id;
- return this;
- }
-
- public String getUserId() {
- return userId;
- }
-
- public void setUserId(String userId) {
- this.userId = userId;
- }
-
- public Profile withUserId(String userId) {
- this.userId = userId;
- return this;
- }
-
+ @Override
public Map getAttributes() {
if (attributes == null) {
- attributes = new HashMap<>();
+ this.attributes = new HashMap<>();
}
return attributes;
}
@@ -67,31 +58,31 @@ public class Profile {
this.attributes = attributes;
}
- public Profile withAttributes(Map attributes) {
- this.attributes = attributes;
- return this;
- }
-
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
- if (!(obj instanceof Profile)) {
+ if (!(obj instanceof ProfileImpl)) {
return false;
}
- final Profile other = (Profile)obj;
- return Objects.equals(id, other.id) &&
- Objects.equals(userId, other.userId) &&
- Objects.equals(getAttributes(), other.getAttributes());
+ final ProfileImpl that = (ProfileImpl)obj;
+ return Objects.equals(id, that.id) && getAttributes().equals(that.getAttributes());
}
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + Objects.hashCode(id);
- hash = 31 * hash + Objects.hashCode(userId);
- hash = 31 * hash + Objects.hashCode(attributes);
+ hash = 31 * hash + getAttributes().hashCode();
return hash;
}
+
+ @Override
+ public String toString() {
+ return "ProfileImpl{" +
+ "id='" + id + '\'' +
+ ", attributes=" + attributes +
+ '}';
+ }
}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/User.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/model/impl/UserImpl.java
similarity index 58%
rename from wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/User.java
rename to wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/model/impl/UserImpl.java
index bb2f59b7b9..951a822e60 100644
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/User.java
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/model/impl/UserImpl.java
@@ -8,16 +8,21 @@
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
-package org.eclipse.che.api.user.server.dao;
+package org.eclipse.che.api.user.server.model.impl;
+
+import org.eclipse.che.api.core.model.user.User;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.Objects;
/**
- * @author Eugene Voevodin
+ * Data object for the {@link User}.
+ *
+ * @author Yevhenii Voevodin
*/
-public class User {
+public class UserImpl implements User {
private String id;
private String email;
@@ -25,19 +30,69 @@ public class User {
private String password;
private List aliases;
+ public UserImpl(String id) {
+ this.id = id;
+ }
+
+ public UserImpl(String id, String email, String name) {
+ this.id = id;
+ this.email = email;
+ this.name = name;
+ }
+
+ public UserImpl(String id,
+ String email,
+ String name,
+ String password,
+ Collection aliases) {
+ this(id, email, name);
+ this.password = password;
+ if (aliases != null) {
+ this.aliases = new ArrayList<>(aliases);
+ }
+ }
+
+ public UserImpl(User user) {
+ this(user.getId(),
+ user.getEmail(),
+ user.getName(),
+ user.getPassword(),
+ user.getAliases());
+ }
+
+ @Override
public String getId() {
return id;
}
- public void setId(String id) {
- this.id = id;
+ @Override
+ public String getEmail() {
+ return email;
}
- public User withId(String id) {
- this.id = id;
- return this;
+ public void setEmail(String email) {
+ this.email = email;
}
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ @Override
public List getAliases() {
if (aliases == null) {
aliases = new ArrayList<>();
@@ -49,64 +104,20 @@ public class User {
this.aliases = aliases;
}
- public User withAliases(List aliases) {
- this.aliases = aliases;
- return this;
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
-
- public User withEmail(String email) {
- this.email = email;
- return this;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- public User withPassword(String password) {
- this.password = password;
- return this;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public User withName(String name) {
- this.name = name;
- return this;
- }
-
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
- if (!(obj instanceof User)) {
+ if (!(obj instanceof UserImpl)) {
return false;
}
- final User other = (User)obj;
- return Objects.equals(id, other.id) &&
- Objects.equals(email, other.email) &&
- Objects.equals(password, other.password) &&
- Objects.equals(name, other.name) &&
- getAliases().equals(other.getAliases());
+ final UserImpl that = (UserImpl)obj;
+ return Objects.equals(id, that.id)
+ && Objects.equals(email, that.email)
+ && Objects.equals(name, that.name)
+ && Objects.equals(password, that.password)
+ && getAliases().equals(that.getAliases());
}
@Override
@@ -114,9 +125,20 @@ public class User {
int hash = 7;
hash = 31 * hash + Objects.hashCode(id);
hash = 31 * hash + Objects.hashCode(email);
- hash = 31 * hash + Objects.hashCode(password);
hash = 31 * hash + Objects.hashCode(name);
+ hash = 31 * hash + Objects.hashCode(password);
hash = 31 * hash + getAliases().hashCode();
return hash;
}
+
+ @Override
+ public String toString() {
+ return "UserImpl{" +
+ "id='" + id + '\'' +
+ ", email='" + email + '\'' +
+ ", name='" + name + '\'' +
+ ", password='" + password + '\'' +
+ ", aliases=" + aliases +
+ '}';
+ }
}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/PreferenceDao.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/spi/PreferenceDao.java
similarity index 89%
rename from wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/PreferenceDao.java
rename to wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/spi/PreferenceDao.java
index ea1b39258b..409f9993e5 100644
--- a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/dao/PreferenceDao.java
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/spi/PreferenceDao.java
@@ -8,9 +8,8 @@
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
-package org.eclipse.che.api.user.server.dao;
+package org.eclipse.che.api.user.server.spi;
-import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import java.util.Map;
@@ -31,12 +30,10 @@ public interface PreferenceDao {
* new preferences, if preferences are empty - removes user preferences
* @throws NullPointerException
* when preferences or userId is null
- * @throws NotFoundException
- * when user with given identifier doesn't exist
* @throws ServerException
* when any other error occurs
*/
- void setPreferences(String userId, Map preferences) throws ServerException, NotFoundException;
+ void setPreferences(String userId, Map preferences) throws ServerException;
/**
* Gets user preferences.
@@ -45,7 +42,7 @@ public interface PreferenceDao {
* {@code
* Map prefs = dao.getPreferences("user123");
* prefs.put("key", "secret");
- * dao.setPreferences("user123", prefs);
+ * spi.setPreferences("user123", prefs);
* }
*
* @param userId
@@ -63,7 +60,7 @@ public interface PreferenceDao {
*
* Note that this method must always return upgradable map, thus it may be used as:
*
{@code
- * Map prefs = dao.getPreferences("user123", ".*key.*");
+ * Map prefs = spi.getPreferences("user123", ".*key.*");
* prefs.put("new-key", "secret");
* prefs.setPreferences("user123", prefs);
* }
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/spi/ProfileDao.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/spi/ProfileDao.java
new file mode 100644
index 0000000000..17b7fb4b7e
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/spi/ProfileDao.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server.spi;
+
+import org.eclipse.che.api.core.ConflictException;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.core.model.user.Profile;
+import org.eclipse.che.api.core.model.user.User;
+import org.eclipse.che.api.user.server.model.impl.ProfileImpl;
+
+/**
+ * Data access object contract for {@link Profile}.
+ *
+ * @author Yevhenii Voevodin
+ */
+public interface ProfileDao {
+
+ /**
+ * Creates user profile.
+ *
+ * @param profile
+ * new profile
+ * @throws NullPointerException
+ * when {@code profile} is null
+ * @throws ServerException
+ * when any error occurs
+ * @throws ConflictException
+ * when profile for user {@code profile.getUserId()} already exists
+ */
+ void create(ProfileImpl profile) throws ServerException, ConflictException;
+
+ /**
+ * Updates profile by replacing an existing entity with a new one.
+ *
+ * @param profile
+ * profile update
+ * @throws NullPointerException
+ * when {@code profile} is null
+ * @throws NotFoundException
+ * when profile with such id doesn't exist
+ * @throws ServerException
+ * when any other error occurs
+ */
+ void update(ProfileImpl profile) throws NotFoundException, ServerException;
+
+ /**
+ * Removes profile.
+ *
+ * @param id
+ * profile identifier
+ * @throws NullPointerException
+ * when {@code id} is null
+ * @throws ServerException
+ * when any other error occurs
+ */
+ void remove(String id) throws ServerException;
+
+ /**
+ * Finds profile by its id.
+ *
+ * Due to {@link Profile#getEmail()} and {@link Profile#getUserId()} definition
+ * returned profile must contain profile owner's {@link User#getEmail() email}
+ * and {@link User#getId()} identifier.
+ *
+ * @param id
+ * profile identifier
+ * @return profile with given {@code id}
+ * @throws NullPointerException
+ * when {@code id} is null
+ * @throws NotFoundException
+ * when profile with such {@code id} doesn't exist
+ * @throws ServerException
+ * when any other error occurs
+ */
+ ProfileImpl getById(String id) throws NotFoundException, ServerException;
+}
diff --git a/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/spi/UserDao.java b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/spi/UserDao.java
new file mode 100644
index 0000000000..949371d452
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/main/java/org/eclipse/che/api/user/server/spi/UserDao.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server.spi;
+
+import org.eclipse.che.api.core.ConflictException;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.core.UnauthorizedException;
+import org.eclipse.che.api.user.server.model.impl.UserImpl;
+
+/**
+ * Defines data access object contract for {@link UserImpl}.
+ *
+ *
The implementation is not required to be responsible for persistent layer
+ * data dto integrity. It simply transfers data from one layer to another,
+ * so if you're going to call any of implemented methods it is considered
+ * that all needed verifications are already done.
+ *
+ *
Note: This particularly does not mean that
+ * method call will not make any inconsistency, but this mean that
+ * such kind of inconsistencies are expected by design and may be treated further.
+ *
+ * @author Yevhenii Voevodin
+ */
+public interface UserDao {
+
+ /**
+ * // TODO remove this method from spi
+ * Authenticates user.
+ *
+ * @param emailOrAliasOrName
+ * one of the user identifiers such as email/name/alias
+ * @param password
+ * password
+ * @return user identifier
+ * @throws NullPointerException
+ * when either {@code emailOrAliasOrName} or {@code password} is null
+ * @throws UnauthorizedException
+ * when user with such {@code aliasOrName} and {@code password} doesn't exist
+ * @throws ServerException
+ * when any other error occurs
+ */
+ String authenticate(String emailOrAliasOrName, String password) throws UnauthorizedException, ServerException;
+
+ /**
+ * Creates a new user.
+ *
+ * @param user
+ * user to create
+ * @throws NullPointerException
+ * when {@code user} is null
+ * @throws ConflictException
+ * when user with such id/alias/email/name already exists
+ * @throws ServerException
+ * when any other error occurs
+ */
+ void create(UserImpl user) throws ConflictException, ServerException;
+
+ /**
+ * Updates user by replacing an existing entity with a new one.
+ *
+ * @param user
+ * user to update
+ * @throws NullPointerException
+ * when {@code user} is null
+ * @throws NotFoundException
+ * when user with id {@code user.getId()} doesn't exist
+ * @throws ConflictException
+ * when any of the id/alias/email/name updated with a value
+ * which is not unique
+ * @throws ServerException
+ * when any other error occurs
+ */
+ void update(UserImpl user) throws NotFoundException, ServerException, ConflictException;
+
+ /**
+ * Removes user.
+ *
+ *
It is up to implementation to do cascade removing of dependent data or
+ * to forbid removing at all.
+ *
+ *
Note that this method doesn't throw any exception when
+ * user doesn't exist.
+ *
+ * @param id
+ * user identifier
+ * @throws NullPointerException
+ * when {@code id} is null
+ * @throws ConflictException
+ * when given user cannot be deleted
+ * @throws ServerException
+ * when any other error occurs
+ */
+ void remove(String id) throws ServerException, ConflictException;
+
+ /**
+ * Finds user by his alias.
+ *
+ *
This method doesn't work for user's email or name.
+ * If it is necessary to get user by name use {@link #getByName(String)} method instead.
+ *
+ * @param alias
+ * user name or alias
+ * @return user instance, never null
+ * @throws NullPointerException
+ * when {@code alias} is null
+ * @throws NotFoundException
+ * when user with given {@code alias} doesn't exist
+ * @throws ServerException
+ * when any other error occurs
+ */
+ UserImpl getByAlias(String alias) throws NotFoundException, ServerException;
+
+ /**
+ * Finds user by his identifier.
+ *
+ * @param id
+ * user identifier
+ * @return user instance, never null
+ * @throws NullPointerException
+ * when {@code id} is null
+ * @throws NotFoundException
+ * when user with given {@code id} doesn't exist
+ * @throws ServerException
+ * when any other error occurs
+ */
+ UserImpl getById(String id) throws NotFoundException, ServerException;
+
+ /**
+ * Finds user by his name.
+ *
+ * @param name
+ * user name
+ * @return user instance, never null
+ * @throws NullPointerException
+ * when {@code name} is null
+ * @throws NotFoundException
+ * when user with such {@code name} doesn't exist
+ * @throws ServerException
+ * when any other error occurs
+ */
+ UserImpl getByName(String name) throws NotFoundException, ServerException;
+
+ /**
+ * Finds user by his email.
+ *
+ * @param email
+ * user email
+ * @return user instance, never null
+ * @throws NullPointerException
+ * when {@code email} is null
+ * @throws NotFoundException
+ * when user with such {@code email} doesn't exist
+ * @throws ServerException
+ * when any other error occurs
+ */
+ UserImpl getByEmail(String email) throws NotFoundException, ServerException;
+}
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/PreferenceManagerTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/PreferenceManagerTest.java
new file mode 100644
index 0000000000..97792de800
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/PreferenceManagerTest.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server;
+
+import com.google.common.collect.ImmutableMap;
+
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.testng.MockitoTestNGListener;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.util.Arrays.asList;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests for {@link PreferenceManager}.
+ *
+ * @author Yevhenii Voevodin.
+ */
+@Listeners(MockitoTestNGListener.class)
+public class PreferenceManagerTest {
+
+ @Mock
+ private PreferenceDao preferenceDao;
+
+ @InjectMocks
+ private PreferenceManager preferenceManager;
+
+ @Captor
+ private ArgumentCaptor> preferencesCaptor;
+
+ @Test
+ public void shouldUseMergeStrategyForPreferencesUpdate() throws Exception {
+ // Preparing preferences
+ final Map existingPreferences = new HashMap<>();
+ existingPreferences.put("pKey1", "pValue1");
+ existingPreferences.put("pKey2", "pValue2");
+ existingPreferences.put("pKey3", "pValue3");
+ existingPreferences.put("pKey4", "pValue4");
+ when(preferenceDao.getPreferences(any())).thenReturn(existingPreferences);
+
+ // Updating preferences
+ final Map newPreferences = new HashMap<>();
+ newPreferences.put("pKey5", "pValue5");
+ newPreferences.put("pKey1", "new-value");
+ preferenceManager.update("user123", newPreferences);
+
+ // Checking
+ verify(preferenceDao).setPreferences(anyString(), preferencesCaptor.capture());
+ assertEquals(preferencesCaptor.getValue(), ImmutableMap.of("pKey1", "new-value",
+ "pKey2", "pValue2",
+ "pKey3", "pValue3",
+ "pKey4", "pValue4",
+ "pKey5", "pValue5"));
+
+ }
+
+ @Test
+ public void shouldRemoveSpecifiedPreferences() throws Exception {
+ // Preparing preferences
+ final Map existingPreferences = new HashMap<>();
+ existingPreferences.put("pKey1", "pValue1");
+ existingPreferences.put("pKey2", "pValue2");
+ existingPreferences.put("pKey3", "pValue3");
+ existingPreferences.put("pKey4", "pValue4");
+ when(preferenceDao.getPreferences(any())).thenReturn(existingPreferences);
+
+ // Removing
+ preferenceManager.remove("user123", asList("pKey1", "pKey5", "odd-pref-name"));
+
+ // Checking
+ verify(preferenceDao).setPreferences(anyString(), preferencesCaptor.capture());
+ assertEquals(preferencesCaptor.getValue(), ImmutableMap.of("pKey2", "pValue2",
+ "pKey3", "pValue3",
+ "pKey4", "pValue4"));
+ }
+
+ @Test
+ public void shouldGetPreferencesByUser() throws Exception {
+ final Map preferences = ImmutableMap.of("name", "value");
+ when(preferenceDao.getPreferences("user123")).thenReturn(preferences);
+
+ assertEquals(preferenceManager.find("user123"), preferences);
+ }
+
+ @Test
+ public void shouldGetPreferencesByUserAndFilter() throws Exception {
+ final Map preferences = ImmutableMap.of("name", "value");
+ when(preferenceDao.getPreferences("user123", "name.*")).thenReturn(preferences);
+
+ assertEquals(preferenceManager.find("user123", "name.*"), preferences);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void getPreferencesShouldThrowNpeWhenUserIdIsNull() throws Exception {
+ preferenceManager.find(null);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void getPreferencesByUserAndFilterShouldThrowNpeWhenUserIdIsNull() throws Exception {
+ preferenceManager.find(null, "name.*");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenRemovingPreferencesAndUserIdIsNull() throws Exception {
+ preferenceManager.remove(null);
+ }
+
+ @Test
+ public void shouldRemoveUserPreferences() throws Exception {
+ preferenceManager.remove("user123");
+
+ verify(preferenceDao).remove("user123");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenSavePreferencesWithNullUser() throws Exception {
+ preferenceManager.save(null, Collections.emptyMap());
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenSavePreferencesWithNullPreferences() throws Exception {
+ preferenceManager.save("user123", null);
+ }
+
+ @Test
+ public void shouldSavePreferences() throws Exception {
+ preferenceManager.save("user123", Collections.emptyMap());
+
+ verify(preferenceDao).setPreferences("user123", Collections.emptyMap());
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/PreferencesServiceTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/PreferencesServiceTest.java
new file mode 100644
index 0000000000..ffa09a5d69
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/PreferencesServiceTest.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server;
+
+import com.google.common.collect.ImmutableMap;
+import com.jayway.restassured.response.Response;
+
+import org.eclipse.che.api.core.rest.ApiExceptionMapper;
+import org.eclipse.che.commons.env.EnvironmentContext;
+import org.eclipse.che.commons.subject.Subject;
+import org.eclipse.che.commons.subject.SubjectImpl;
+import org.everrest.assured.EverrestJetty;
+import org.everrest.core.Filter;
+import org.everrest.core.GenericContainerRequest;
+import org.everrest.core.RequestFilter;
+import org.mockito.Answers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.testng.MockitoTestNGListener;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+import java.util.Map;
+
+import static com.jayway.restassured.RestAssured.given;
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static org.everrest.assured.JettyHttpServer.ADMIN_USER_NAME;
+import static org.everrest.assured.JettyHttpServer.ADMIN_USER_PASSWORD;
+import static org.everrest.assured.JettyHttpServer.SECURE_PATH;
+import static org.mockito.Mockito.verify;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests for {@link PreferencesService}.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Listeners({EverrestJetty.class, MockitoTestNGListener.class})
+public class PreferencesServiceTest {
+
+ @SuppressWarnings("unused")
+ private static final ApiExceptionMapper MAPPER = new ApiExceptionMapper();
+ @SuppressWarnings("unused")
+ private static final EnvironmentFilter FILTER = new EnvironmentFilter();
+ private static final Subject SUBJECT = new SubjectImpl("user", "user123", "token", false);
+
+ @Mock(answer = Answers.RETURNS_MOCKS)
+ private PreferenceManager preferenceManager;
+
+ @InjectMocks
+ private PreferencesService preferencesService;
+
+ @Test
+ public void shouldFindPreferences() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .get(SECURE_PATH + "/preferences");
+
+ assertEquals(response.getStatusCode(), 200);
+ verify(preferenceManager).find(SUBJECT.getUserId());
+ }
+
+ @Test
+ public void shouldFindPreferencesAndFilter() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .get(SECURE_PATH + "/preferences?filter=.*github.*");
+
+ assertEquals(response.getStatusCode(), 200);
+ verify(preferenceManager).find(SUBJECT.getUserId(), ".*github.*");
+ }
+
+ @Test
+ public void shouldSavePreferences() throws Exception {
+ final Map preferences = ImmutableMap.of("pref1", "value1",
+ "pref2", "value2",
+ "pref3", "value3");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType("application/json")
+ .body(preferences)
+ .when()
+ .post(SECURE_PATH + "/preferences");
+
+ assertEquals(response.getStatusCode(), 204);
+ verify(preferenceManager).save(SUBJECT.getUserId(), preferences);
+ }
+
+ @Test
+ public void shouldNotSavePreferencesWhenNothingSent() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType("application/json")
+ .when()
+ .post(SECURE_PATH + "/preferences");
+
+ assertEquals(response.getStatusCode(), 400);
+ }
+
+ @Test
+ public void shouldUpdatePreferences() throws Exception {
+ final Map preferences = ImmutableMap.of("pref1", "value1",
+ "pref2", "value2",
+ "pref3", "value3");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType("application/json")
+ .body(preferences)
+ .when()
+ .put(SECURE_PATH + "/preferences");
+
+ assertEquals(response.getStatusCode(), 200);
+ verify(preferenceManager).update(SUBJECT.getUserId(), preferences);
+ }
+
+ @Test
+ public void shouldNotUpdatePreferencesWhenNothingSent() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType("application/json")
+ .when()
+ .put(SECURE_PATH + "/preferences");
+
+ assertEquals(response.getStatusCode(), 400);
+ }
+
+ @Test
+ public void shouldRemoveSpecifiedPreferences() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType("application/json")
+ .body(asList("pref1", "pref2"))
+ .when()
+ .delete(SECURE_PATH + "/preferences");
+
+ assertEquals(response.getStatusCode(), 204);
+ verify(preferenceManager).remove(SUBJECT.getUserId(), asList("pref1", "pref2"));
+ }
+
+ @Test
+ public void shouldRemoveAllPreferencesIfNothingSent() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType("application/json")
+ .when()
+ .delete(SECURE_PATH + "/preferences");
+
+ assertEquals(response.getStatusCode(), 204);
+ verify(preferenceManager).remove(SUBJECT.getUserId());
+ }
+
+ @Filter
+ public static class EnvironmentFilter implements RequestFilter {
+ public void doFilter(GenericContainerRequest request) {
+ EnvironmentContext.getCurrent().setSubject(SUBJECT);
+ }
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/ProfileLinksInjectorTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/ProfileLinksInjectorTest.java
new file mode 100644
index 0000000000..bf536afa56
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/ProfileLinksInjectorTest.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server;
+
+import com.google.common.collect.Sets;
+
+import org.eclipse.che.api.core.rest.ServiceContext;
+import org.eclipse.che.api.user.shared.dto.ProfileDto;
+import org.eclipse.che.commons.lang.Pair;
+import org.eclipse.che.dto.server.DtoFactory;
+import org.everrest.core.impl.uri.UriBuilderImpl;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.testng.MockitoTestNGListener;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static java.util.Arrays.asList;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests for {@link ProfileLinksInjector}.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Listeners(MockitoTestNGListener.class)
+public class ProfileLinksInjectorTest {
+
+ @Mock
+ private ServiceContext serviceContext;
+
+ @InjectMocks
+ private ProfileLinksInjector linksInjector;
+
+ @BeforeMethod
+ public void setUpContext() {
+ final UriBuilderImpl uriBuilder = new UriBuilderImpl();
+ uriBuilder.uri("http://localhost:8080");
+ when(serviceContext.getServiceUriBuilder()).thenReturn(uriBuilder);
+ when(serviceContext.getBaseUriBuilder()).thenReturn(uriBuilder);
+ }
+
+ @Test
+ public void shouldInjectProfileLinks() throws Exception {
+ final ProfileDto profileDto = DtoFactory.newDto(ProfileDto.class)
+ .withUserId("user123")
+ .withEmail("user@codenvy.com");
+
+ linksInjector.injectLinks(profileDto, serviceContext);
+
+ // [rel, method] pairs links
+ final Set> links = profileDto.getLinks()
+ .stream()
+ .map(link -> Pair.of(link.getMethod(), link.getRel()))
+ .collect(Collectors.toSet());
+ final Set> expectedLinks
+ = new HashSet<>(asList(Pair.of("GET", Constants.LINK_REL_SELF),
+ Pair.of("GET", Constants.LINK_REL_CURRENT_PROFILE),
+ Pair.of("PUT", Constants.LINK_REL_PROFILE_ATTRIBUTES),
+ Pair.of("PUT", Constants.LINK_REL_CURRENT_PROFILE_ATTRIBUTES),
+ Pair.of("DELETE", Constants.LINK_REL_CURRENT_PROFILE_ATTRIBUTES)));
+
+ assertEquals(links, expectedLinks, "Difference " + Sets.symmetricDifference(links, expectedLinks) + "\n");
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/ProfileManagerTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/ProfileManagerTest.java
new file mode 100644
index 0000000000..5587c25ae1
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/ProfileManagerTest.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server;
+
+import org.eclipse.che.api.user.server.model.impl.ProfileImpl;
+import org.eclipse.che.api.user.server.spi.ProfileDao;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.testng.MockitoTestNGListener;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests for {@link ProfileManager}.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Listeners(MockitoTestNGListener.class)
+public class ProfileManagerTest {
+
+ @Mock
+ private ProfileDao profileDao;
+
+ @InjectMocks
+ private ProfileManager profileManager;
+
+ @Test
+ public void shouldGetProfileById() throws Exception {
+ final ProfileImpl profile = new ProfileImpl("user123");
+ when(profileDao.getById(profile.getUserId())).thenReturn(profile);
+
+ assertEquals(profile, profileManager.getById(profile.getUserId()));
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenGettingProfileByNullId() throws Exception {
+ profileManager.getById(null);
+ }
+
+ @Test
+ public void shouldCreateProfile() throws Exception {
+ final ProfileImpl profile = new ProfileImpl("user123");
+
+ profileManager.create(profile);
+
+ final ArgumentCaptor captor = ArgumentCaptor.forClass(ProfileImpl.class);
+ verify(profileDao).create(captor.capture());
+ assertEquals(captor.getValue(), profile);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenCreatingNullProfile() throws Exception {
+ profileManager.create(null);
+ }
+
+ @Test
+ public void shouldUpdateProfile() throws Exception {
+ final ProfileImpl profile = new ProfileImpl("user123");
+
+ profileManager.update(profile);
+
+ final ArgumentCaptor captor = ArgumentCaptor.forClass(ProfileImpl.class);
+ verify(profileDao).update(captor.capture());
+ assertEquals(captor.getValue(), profile);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenUpdatingNull() throws Exception {
+ profileManager.update(null);
+ }
+
+ @Test
+ public void shouldRemoveProfile() throws Exception {
+ profileManager.remove("user123");
+
+ verify(profileDao).remove("user123");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenRemovingNull() throws Exception {
+ profileManager.remove(null);
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/ProfileServiceTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/ProfileServiceTest.java
new file mode 100644
index 0000000000..9e3a6f0ab2
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/ProfileServiceTest.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server;
+
+import com.google.common.collect.ImmutableMap;
+import com.jayway.restassured.response.Response;
+
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.core.model.user.Profile;
+import org.eclipse.che.api.core.rest.ApiExceptionMapper;
+import org.eclipse.che.api.user.server.model.impl.ProfileImpl;
+import org.eclipse.che.api.user.shared.dto.ProfileDto;
+import org.eclipse.che.commons.env.EnvironmentContext;
+import org.eclipse.che.commons.subject.Subject;
+import org.eclipse.che.commons.subject.SubjectImpl;
+import org.eclipse.che.dto.server.DtoFactory;
+import org.everrest.assured.EverrestJetty;
+import org.everrest.core.Filter;
+import org.everrest.core.GenericContainerRequest;
+import org.everrest.core.RequestFilter;
+import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.testng.MockitoTestNGListener;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+import static com.jayway.restassured.RestAssured.given;
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static org.everrest.assured.JettyHttpServer.ADMIN_USER_NAME;
+import static org.everrest.assured.JettyHttpServer.ADMIN_USER_PASSWORD;
+import static org.everrest.assured.JettyHttpServer.SECURE_PATH;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Tests for {@link ProfileService}.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Listeners({EverrestJetty.class, MockitoTestNGListener.class})
+public class ProfileServiceTest {
+
+ @SuppressWarnings("unused")
+ private static final ApiExceptionMapper MAPPER = new ApiExceptionMapper();
+ @SuppressWarnings("unused")
+ private static final EnvironmentFilter FILTER = new EnvironmentFilter();
+ private static final Subject SUBJECT = new SubjectImpl("user", "user123", "token", false);
+
+ @Mock(answer = Answers.RETURNS_MOCKS)
+ private ProfileManager profileManager;
+
+ @Mock
+ private ProfileLinksInjector linksInjector;
+
+ @Mock(answer = Answers.RETURNS_MOCKS)
+ private UserManager userManager;
+
+ @Captor
+ private ArgumentCaptor profileCaptor;
+
+ @InjectMocks
+ private ProfileService profileService;
+
+ @BeforeMethod
+ public void setUp() throws NotFoundException, ServerException {
+ when(linksInjector.injectLinks(any(), any())).thenAnswer(inv -> inv.getArguments()[0]);
+
+ when(profileManager.getById(SUBJECT.getUserId())).thenReturn(new ProfileImpl(SUBJECT.getUserId()));
+ }
+
+ @Test
+ public void shouldGetCurrentProfile() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .get(SECURE_PATH + "/profile");
+
+ assertEquals(response.getStatusCode(), 200);
+ final ProfileDto profileDto = unwrapDto(response, ProfileDto.class);
+ assertEquals(profileDto.getUserId(), SUBJECT.getUserId());
+ }
+
+ @Test
+ public void shouldGetProfileById() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .get(SECURE_PATH + "/profile/" + SUBJECT.getUserId());
+
+ assertEquals(response.getStatusCode(), 200);
+ final ProfileDto profileDto = unwrapDto(response, ProfileDto.class);
+ assertEquals(profileDto.getUserId(), SUBJECT.getUserId());
+ }
+
+ @Test
+ public void shouldBeAbleToUpdateCurrentProfileAttributes() throws Exception {
+ final ImmutableMap attributes = ImmutableMap.of("attr1", "value1",
+ "attr2", "value2",
+ "attr3", "value3");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .contentType("application/json")
+ .body(attributes)
+ .put(SECURE_PATH + "/profile/attributes");
+
+ assertEquals(response.getStatusCode(), 200);
+ verify(profileManager).update(profileCaptor.capture());
+ final Profile profile = profileCaptor.getValue();
+ assertEquals(profile.getAttributes(), attributes);
+ }
+
+ @Test
+ public void shouldNotUpdateCurrentProfileAttributesIfNothingSent() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .contentType("application/json")
+ .put(SECURE_PATH + "/profile/attributes");
+
+ assertEquals(response.getStatusCode(), 400);
+ }
+
+ @Test
+ public void shouldBeAbleToUpdateAttributesOfSpecifiedProfile() throws Exception {
+ final ImmutableMap attributes = ImmutableMap.of("attr1", "value1",
+ "attr2", "value2",
+ "attr3", "value3");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .contentType("application/json")
+ .body(attributes)
+ .put(SECURE_PATH + "/profile/" + SUBJECT.getUserId() + "/attributes/");
+
+ assertEquals(response.getStatusCode(), 200);
+ verify(profileManager).update(profileCaptor.capture());
+ final Profile profile = profileCaptor.getValue();
+ assertEquals(profile.getAttributes(), attributes);
+ }
+
+ @Test
+ public void shouldNotUpdateSpecifiedProfileAttributesIfNothingSent() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .contentType("application/json")
+ .put(SECURE_PATH + "/profile/" + SUBJECT.getUserId() + "/attributes/");
+
+ assertEquals(response.getStatusCode(), 400);
+ }
+
+ @Test
+ public void shouldBeAbleToRemoveSpecifiedAttributes() throws Exception {
+ when(profileManager.getById(SUBJECT.getUserId()))
+ .thenReturn(new ProfileImpl(SUBJECT.getUserId(),
+ ImmutableMap.of("attr1", "value1",
+ "attr2", "value2",
+ "attr3", "value3")));
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .contentType("application/json")
+ .body(asList("attr1", "attr3"))
+ .delete(SECURE_PATH + "/profile/attributes");
+
+ assertEquals(response.getStatusCode(), 204);
+ verify(profileManager).update(profileCaptor.capture());
+ final Profile profile = profileCaptor.getValue();
+ assertEquals(profile.getAttributes(), ImmutableMap.of("attr2", "value2"));
+ }
+
+ @Test
+ public void shouldRemoveAllAttributeIfNoSpecified() throws Exception {
+ when(profileManager.getById(SUBJECT.getUserId()))
+ .thenReturn(new ProfileImpl(SUBJECT.getUserId(),
+ ImmutableMap.of("attr1", "value1",
+ "attr2", "value2",
+ "attr3", "value3")));
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .contentType("application/json")
+ .delete(SECURE_PATH + "/profile/attributes");
+
+ assertEquals(response.getStatusCode(), 204);
+ verify(profileManager).update(profileCaptor.capture());
+ final Profile profile = profileCaptor.getValue();
+ assertTrue(profile.getAttributes().isEmpty());
+ }
+
+ @Filter
+ public static class EnvironmentFilter implements RequestFilter {
+ public void doFilter(GenericContainerRequest request) {
+ EnvironmentContext.getCurrent().setSubject(SUBJECT);
+ }
+ }
+
+ private static T unwrapDto(Response response, Class dtoClass) {
+ return DtoFactory.getInstance().createDtoFromJson(response.body().print(), dtoClass);
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserLinksInjectorTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserLinksInjectorTest.java
new file mode 100644
index 0000000000..ad14853c9d
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserLinksInjectorTest.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server;
+
+import com.google.common.collect.Sets;
+
+import org.eclipse.che.api.core.rest.ServiceContext;
+import org.eclipse.che.api.user.shared.dto.UserDto;
+import org.eclipse.che.commons.lang.Pair;
+import org.eclipse.che.dto.server.DtoFactory;
+import org.everrest.core.impl.uri.UriBuilderImpl;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.testng.MockitoTestNGListener;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static java.util.Arrays.asList;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests for {@link UserLinksInjector}.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Listeners(MockitoTestNGListener.class)
+public class UserLinksInjectorTest {
+
+ @Mock
+ private ServiceContext serviceContext;
+
+ @InjectMocks
+ private UserLinksInjector linksInjector;
+
+ @BeforeMethod
+ public void setUpContext() {
+ final UriBuilderImpl uriBuilder = new UriBuilderImpl();
+ uriBuilder.uri("http://localhost:8080");
+ when(serviceContext.getServiceUriBuilder()).thenReturn(uriBuilder);
+ when(serviceContext.getBaseUriBuilder()).thenReturn(uriBuilder);
+ }
+
+ @Test
+ public void shouldInjectLinks() throws Exception {
+ final UserDto userDto = DtoFactory.newDto(UserDto.class)
+ .withId("user123")
+ .withEmail("user@codenvy.com")
+ .withName("user");
+
+ linksInjector.injectLinks(userDto, serviceContext);
+
+ // [rel, method] pairs links
+ final Set> links = userDto.getLinks()
+ .stream()
+ .map(link -> Pair.of(link.getMethod(), link.getRel()))
+ .collect(Collectors.toSet());
+ final Set> expectedLinks
+ = new HashSet<>(asList(Pair.of("GET", Constants.LINK_REL_SELF),
+ Pair.of("GET", Constants.LINK_REL_CURRENT_USER),
+ Pair.of("GET", Constants.LINK_REL_PROFILE),
+ Pair.of("GET", Constants.LINK_REL_CURRENT_USER_SETTINGS),
+ Pair.of("GET", Constants.LINK_REL_PREFERENCES),
+ Pair.of("POST", Constants.LINK_REL_CURRENT_USER_PASSWORD)));
+
+ assertEquals(links, expectedLinks, "Difference " + Sets.symmetricDifference(links, expectedLinks) + "\n");
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserManagerTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserManagerTest.java
index a6769e8880..d590abfcea 100644
--- a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserManagerTest.java
+++ b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserManagerTest.java
@@ -11,69 +11,234 @@
package org.eclipse.che.api.user.server;
import org.eclipse.che.api.core.ConflictException;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
-import org.eclipse.che.api.user.server.dao.Profile;
-import org.eclipse.che.api.user.server.dao.User;
-import org.eclipse.che.api.user.server.dao.UserDao;
-import org.eclipse.che.api.user.server.dao.UserProfileDao;
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.core.model.user.User;
+import org.eclipse.che.api.user.server.model.impl.ProfileImpl;
+import org.eclipse.che.api.user.server.spi.PreferenceDao;
+import org.eclipse.che.api.user.server.spi.ProfileDao;
+import org.eclipse.che.api.user.server.spi.UserDao;
+import org.eclipse.che.api.user.server.model.impl.UserImpl;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
+import java.util.Collections;
+import java.util.concurrent.Callable;
+
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyMapOf;
import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
/**
- * Tests for {@link UserManager}
+ * Tests for {@link UserManager}.
*
* @author Max Shaposhnik (mshaposhnik@codenvy.com)
+ * @author Yevhenii Voevodin
*/
-
-@Listeners(value = {MockitoTestNGListener.class})
+@Listeners(MockitoTestNGListener.class)
public class UserManagerTest {
@Mock
- UserDao userDao;
+ private UserDao userDao;
@Mock
- UserProfileDao profileDao;
+ private ProfileDao profileDao;
@Mock
- PreferenceDao preferenceDao;
+ private PreferenceDao preferencesDao;
- UserManager manager;
+ private UserManager manager;
@BeforeMethod
public void setUp() {
- manager = new UserManager(userDao, profileDao, preferenceDao, new String[0]);
+ initMocks(this);
+
+ manager = new UserManager(userDao, profileDao, preferencesDao, new String[] {"reserved"});
}
@Test
public void shouldCreateProfileAndPreferencesOnUserCreation() throws Exception {
- final User user = new User().withEmail("test@email.com").withName("testName");
+ final UserImpl user = new UserImpl(null, "test@email.com", "testName", null, null);
manager.create(user, false);
- verify(profileDao).create(any(Profile.class));
- verify(preferenceDao).setPreferences(anyString(), anyMapOf(String.class, String.class));
+ verify(userDao).create(any(UserImpl.class));
+ verify(profileDao).create(any(ProfileImpl.class));
+ verify(preferencesDao).setPreferences(anyString(), anyMapOf(String.class, String.class));
+ }
+
+ @Test(dataProvider = "rollback")
+ public void shouldTryToRollbackWhenEntityCreationFailed(Callable preAction) throws Exception {
+ preAction.call();
+
+ // Creating new user
+ try {
+ manager.create(new UserImpl(null, "test@email.com", "testName", null, null), false);
+ fail("Had to throw Exception");
+ } catch (Exception x) {
+ // defined by userDao mock
+ }
+
+ // Capturing identifier
+ final ArgumentCaptor captor = ArgumentCaptor.forClass(UserImpl.class);
+ verify(userDao).create(captor.capture());
+ final String userId = captor.getValue().getId();
+
+ // Verifying rollback
+ verify(userDao).remove(userId);
+ verify(preferencesDao).remove(userId);
+ verify(profileDao).remove(userId);
}
@Test
- public void shouldGeneratedPasswordWhenCreatingUserAndItIsMissing() throws Exception {
- final User user = new User().withEmail("test@email.com").withName("testName");
+ public void shouldGeneratePasswordWhenCreatingUserAndItIsMissing() throws Exception {
+ final User user = new UserImpl(null, "test@email.com", "testName", null, null);
manager.create(user, false);
- verify(userDao).create(eq(user.withPassword("")));
+ final ArgumentCaptor userCaptor = ArgumentCaptor.forClass(UserImpl.class);
+ verify(userDao).create(userCaptor.capture());
+ assertNotNull(userCaptor.getValue().getPassword());
+ }
+
+ @Test
+ public void shouldGenerateIdentifierWhenCreatingUser() throws Exception {
+ final User user = new UserImpl("identifier", "test@email.com", "testName", null, null);
+
+ manager.create(user, false);
+
+ final ArgumentCaptor userCaptor = ArgumentCaptor.forClass(UserImpl.class);
+ verify(userDao).create(userCaptor.capture());
+ final String id = userCaptor.getValue().getId();
+ assertNotNull(id);
+ assertNotEquals(id, "identifier");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenUpdatingUserWithNullEntity() throws Exception {
+ manager.update(null);
+ }
+
+ @Test
+ public void shouldUpdateUser() throws Exception {
+ final User user = new UserImpl("identifier", "test@email.com", "testName", "password", Collections.emptyList());
+
+ manager.update(user);
+
+ verify(userDao).update(new UserImpl(user));
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrownNpeWhenTryingToGetUserByNullId() throws Exception {
+ manager.getById(null);
+ }
+
+ @Test
+ public void shouldGetUserById() throws Exception {
+ final User user = new UserImpl("identifier", "test@email.com", "testName", "password", Collections.singletonList("alias"));
+ when(manager.getById(user.getId())).thenReturn(user);
+
+ assertEquals(manager.getById(user.getId()), user);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrownNpeWhenTryingToGetUserByNullAlias() throws Exception {
+ manager.getByAlias(null);
+ }
+
+ @Test
+ public void shouldGetUserByAlias() throws Exception {
+ final User user = new UserImpl("identifier", "test@email.com", "testName", "password", Collections.singletonList("alias"));
+ when(manager.getByAlias("alias")).thenReturn(user);
+
+ assertEquals(manager.getByAlias("alias"), user);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrownNpeWhenTryingToGetUserByNullName() throws Exception {
+ manager.getByName(null);
+ }
+
+ @Test
+ public void shouldGetUserByName() throws Exception {
+ final User user = new UserImpl("identifier", "test@email.com", "testName", "password", Collections.singletonList("alias"));
+ when(manager.getByName(user.getName())).thenReturn(user);
+
+ assertEquals(manager.getByName(user.getName()), user);
+ }
+
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrownNpeWhenTryingToGetUserWithNullEmail() throws Exception {
+ manager.getByEmail(null);
+ }
+
+ @Test
+ public void shouldGetUserByEmail() throws Exception {
+ final User user = new UserImpl("identifier", "test@email.com", "testName", "password", Collections.singletonList("alias"));
+ when(manager.getByEmail(user.getEmail())).thenReturn(user);
+
+ assertEquals(manager.getByEmail(user.getEmail()), user);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenRemovingUserByNullId() throws Exception {
+ manager.remove(null);
+ }
+
+ @Test
+ public void shouldRemoveUser() throws Exception {
+ manager.remove("user123");
+
+ verify(userDao).remove("user123");
+ verify(preferencesDao).remove("user123");
+ verify(profileDao).remove("user123");
}
@Test(expectedExceptions = ConflictException.class)
public void shouldThrowConflictExceptionOnCreationIfUserNameIsReserved() throws Exception {
- final User user = new User().withEmail("test@email.com").withName("reserved");
+ final User user = new UserImpl("id", "test@email.com", "reserved");
- new UserManager(userDao, profileDao, preferenceDao, new String[] {"reserved"}).create(user, false);
+ manager.create(user, false);
+ }
+
+ @DataProvider(name = "rollback")
+ public Object[][] rollbackTestPreActions() throws Exception {
+ return new Callable[][] {
+
+ // User creation mocking
+ {() -> {
+ doThrow(new ServerException("error"))
+ .when(userDao)
+ .create(any());
+ return null;
+ }},
+
+ // Preferences creation mocking
+ {() -> {
+ doThrow(new ServerException("error"))
+ .when(preferencesDao)
+ .setPreferences(anyString(), any());
+ return null;
+ }},
+
+ // Profile creation mocking
+ {() -> {
+ doThrow(new ServerException("error"))
+ .when(profileDao)
+ .create(any());
+ return null;
+ }}
+ };
}
}
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserProfileServiceTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserProfileServiceTest.java
deleted file mode 100644
index 16eee6c815..0000000000
--- a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserProfileServiceTest.java
+++ /dev/null
@@ -1,390 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012-2016 Codenvy, S.A.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Codenvy, S.A. - initial API and implementation
- *******************************************************************************/
-package org.eclipse.che.api.user.server;
-
-import sun.security.acl.PrincipalImpl;
-
-import org.eclipse.che.api.core.ForbiddenException;
-import org.eclipse.che.api.core.rest.ApiExceptionMapper;
-import org.eclipse.che.api.core.rest.shared.dto.Link;
-import org.eclipse.che.api.user.server.dao.PreferenceDao;
-import org.eclipse.che.api.user.server.dao.Profile;
-import org.eclipse.che.api.user.server.dao.User;
-import org.eclipse.che.api.user.server.dao.UserDao;
-import org.eclipse.che.api.user.server.dao.UserProfileDao;
-import org.eclipse.che.api.user.shared.dto.ProfileDescriptor;
-import org.eclipse.che.commons.json.JsonHelper;
-import org.eclipse.che.commons.subject.Subject;
-import org.everrest.core.impl.ApplicationContextImpl;
-import org.everrest.core.impl.ApplicationProviderBinder;
-import org.everrest.core.impl.ContainerRequest;
-import org.everrest.core.impl.ContainerResponse;
-import org.everrest.core.impl.EnvironmentContext;
-import org.everrest.core.impl.EverrestConfiguration;
-import org.everrest.core.impl.EverrestProcessor;
-import org.everrest.core.impl.ProviderBinder;
-import org.everrest.core.impl.ResourceBinderImpl;
-import org.everrest.core.tools.DependencySupplierImpl;
-import org.everrest.core.tools.ResourceLauncher;
-import org.mockito.Mock;
-import org.mockito.testng.MockitoTestNGListener;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Listeners;
-import org.testng.annotations.Test;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.SecurityContext;
-import javax.ws.rs.core.UriInfo;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyMap;
-import static java.util.Collections.singletonList;
-import static java.util.Collections.singletonMap;
-import static javax.ws.rs.core.Response.Status.NO_CONTENT;
-import static javax.ws.rs.core.Response.Status.OK;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_CURRENT_USER_PROFILE;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_USER_PROFILE_BY_ID;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_UPDATE_CURRENT_USER_PROFILE;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_UPDATE_PREFERENCES;
-import static org.eclipse.che.api.user.server.Constants.LINK_REL_UPDATE_USER_PROFILE_BY_ID;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
-/**
- * Tests for {@link UserProfileService}
- *
- * @author Max Shaposhnik
- * @author Eugene Voevodin
- */
-@Listeners(value = {MockitoTestNGListener.class})
-public class UserProfileServiceTest {
-
- private static final String BASE_URI = "http://localhost/service";
- private static final String SERVICE_PATH = BASE_URI + "/profile";
-
- @Mock
- private UserProfileDao profileDao;
- @Mock
- private UserDao userDao;
- @Mock
- private PreferenceDao preferenceDao;
- @Mock
- private User testUser;
- @Mock
- private UriInfo uriInfo;
- @Mock
- private EnvironmentContext environmentContext;
- @Mock
- private SecurityContext securityContext;
- private ResourceLauncher launcher;
- private UserProfileService service;
-
- @BeforeMethod
- public void setUp() throws Exception {
- final ResourceBinderImpl resources = new ResourceBinderImpl();
- resources.addResource(UserProfileService.class, null);
- final DependencySupplierImpl dependencies = new DependencySupplierImpl();
- dependencies.addComponent(UserDao.class, userDao);
- dependencies.addComponent(UserProfileDao.class, profileDao);
- dependencies.addComponent(PreferenceDao.class, preferenceDao);
- final URI uri = new URI(BASE_URI);
- final ContainerRequest req = new ContainerRequest(null, uri, uri, null, null, securityContext);
- final ApplicationContextImpl contextImpl = new ApplicationContextImpl(req, null, ProviderBinder.getInstance());
- contextImpl.setDependencySupplier(dependencies);
- ApplicationContextImpl.setCurrent(contextImpl);
- final ApplicationProviderBinder binder = new ApplicationProviderBinder();
- binder.addExceptionMapper(ApiExceptionMapper.class);
- final EverrestProcessor processor = new EverrestProcessor(resources,
- binder,
- dependencies,
- new EverrestConfiguration(),
- null);
- launcher = new ResourceLauncher(processor);
- service = (UserProfileService)resources.getMatchedResource("/profile", new ArrayList())
- .getInstance(ApplicationContextImpl.getCurrent());
- //setup testUser
- final String id = "user123abc456def";
- final String email = "user@testuser.com";
- when(testUser.getEmail()).thenReturn(email);
- when(testUser.getId()).thenReturn(id);
- when(environmentContext.get(SecurityContext.class)).thenReturn(securityContext);
- when(securityContext.getUserPrincipal()).thenReturn(new PrincipalImpl(email));
- when(userDao.getByAlias(email)).thenReturn(testUser);
- when(userDao.getById(id)).thenReturn(testUser);
- org.eclipse.che.commons.env.EnvironmentContext.getCurrent().setSubject(new Subject() {
- @Override
- public String getUserName() {
- return testUser.getEmail();
- }
-
- @Override
- public boolean hasPermission(String domain, String instance, String action) {
- return false;
- }
-
- @Override
- public void checkPermission(String domain, String instance, String action) throws ForbiddenException {
- }
-
- @Override
- public String getToken() {
- return null;
- }
-
- @Override
- public String getUserId() {
- return testUser.getId();
- }
-
- @Override
- public boolean isTemporary() {
- return false;
- }
- });
- }
-
- @Test
- public void shouldBeAbleToGetCurrentProfile() throws Exception {
- final Profile current = new Profile().withId(testUser.getId()).withUserId(testUser.getId());
- when(profileDao.getById(current.getId())).thenReturn(current);
-
- final ContainerResponse response = makeRequest(HttpMethod.GET, SERVICE_PATH, null);
-
- assertEquals(response.getStatus(), OK.getStatusCode());
- final ProfileDescriptor descriptor = (ProfileDescriptor)response.getEntity();
- assertEquals(descriptor.getId(), current.getId());
- assertEquals(descriptor.getUserId(), current.getUserId());
- assertEquals(descriptor.getAttributes().get("email"), testUser.getEmail());
- }
-
- @Test
- public void shouldBeAbleToGetPreferences() throws Exception {
- final Map preferences = new HashMap<>(8);
- preferences.put("test1", "test1");
- preferences.put("test2", "test2");
- preferences.put("test3", "test3");
- when(preferenceDao.getPreferences(testUser.getId())).thenReturn(preferences);
-
- final ContainerResponse response = makeRequest(HttpMethod.GET, SERVICE_PATH + "/prefs", null);
-
- assertEquals(response.getStatus(), OK.getStatusCode());
- assertEquals(response.getEntity(), preferences);
- }
-
- @Test
- public void shouldBeAbleToRemoveAttributes() throws Exception {
- final Map attributes = new HashMap<>(8);
- attributes.put("test", "test");
- attributes.put("test1", "test");
- attributes.put("test2", "test");
- final Profile profile = new Profile().withId(testUser.getId()).withAttributes(attributes);
- when(profileDao.getById(profile.getId())).thenReturn(profile);
-
- final ContainerResponse response = makeRequest(HttpMethod.DELETE, SERVICE_PATH + "/attributes", asList("test", "test2"));
-
- assertEquals(response.getStatus(), NO_CONTENT.getStatusCode());
- verify(profileDao, times(1)).update(profile);
- assertEquals(attributes.size(), 1);
- assertNotNull(attributes.get("test1"));
- }
-
- @Test
- public void shouldRemoveAllAttributesIfNullWasSent() throws Exception {
- final Map attributes = new HashMap<>(8);
- attributes.put("test", "test");
- attributes.put("test1", "test");
- attributes.put("test2", "test");
- final Profile profile = new Profile().withId(testUser.getId()).withAttributes(attributes);
- when(profileDao.getById(profile.getId())).thenReturn(profile);
-
- final ContainerResponse response = makeRequest(HttpMethod.DELETE, SERVICE_PATH + "/attributes", null);
-
- assertEquals(response.getStatus(), NO_CONTENT.getStatusCode());
- verify(profileDao, times(1)).update(profile);
- assertTrue(attributes.isEmpty());
- }
-
- @Test
- public void shouldBeAbleToUpdatePreferences() throws Exception {
- final Map preferences = new HashMap<>(8);
- preferences.put("test1", "test1");
- preferences.put("test2", "test2");
- preferences.put("test3", "test3");
- when(preferenceDao.getPreferences(testUser.getId())).thenReturn(preferences);
- final Map update = singletonMap("test1", "new_value");
-
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/prefs", update);
-
- preferences.putAll(update);
- assertEquals(response.getStatus(), OK.getStatusCode());
- assertEquals(response.getEntity(), preferences);
- verify(preferenceDao).setPreferences(testUser.getId(), preferences);
- }
-
- @Test
- public void shouldThrowExceptionIfPreferencesUpdateIsNull() throws Exception {
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/prefs", null);
-
- assertEquals(response.getStatus(), 409);
- }
-
- @Test
- public void shouldThrowExceptionIfPreferencesUpdateIsEmpty() throws Exception {
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/prefs", emptyMap());
-
- assertEquals(response.getStatus(), 409);
- }
-
- @Test
- public void shouldBeAbleToRemovePreferences() throws Exception {
- final Map preferences = new HashMap<>(8);
- preferences.put("test1", "test1");
- preferences.put("test2", "test2");
- preferences.put("test3", "test3");
- when(preferenceDao.getPreferences(testUser.getId())).thenReturn(preferences);
-
- final ContainerResponse response = makeRequest(HttpMethod.DELETE, SERVICE_PATH + "/prefs", singletonList("test1"));
-
- assertEquals(response.getStatus(), NO_CONTENT.getStatusCode());
- assertNull(preferences.get("test1"));
- verify(preferenceDao).setPreferences(testUser.getId(), preferences);
- }
-
- @Test
- public void shouldRemoveAllPreferencesIfNullWasSend() throws Exception {
- final ContainerResponse response = makeRequest(HttpMethod.DELETE, SERVICE_PATH + "/prefs", null);
-
- assertEquals(response.getStatus(), NO_CONTENT.getStatusCode());
- verify(preferenceDao).remove(testUser.getId());
- }
-
- @Test
- public void shouldBeAbleToGetProfileById() throws Exception {
- final Profile profile = new Profile().withId(testUser.getId())
- .withUserId(testUser.getId());
- when(profileDao.getById(profile.getId())).thenReturn(profile);
-
- final ContainerResponse response = makeRequest(HttpMethod.GET, SERVICE_PATH + "/" + profile.getId(), null);
-
- assertEquals(response.getStatus(), OK.getStatusCode());
- final ProfileDescriptor descriptor = (ProfileDescriptor)response.getEntity();
- assertEquals(descriptor.getUserId(), profile.getId());
- assertEquals(descriptor.getId(), profile.getId());
- assertEquals(descriptor.getAttributes().get("email"), testUser.getEmail());
- }
-
- @Test
- public void shouldBeAbleToUpdateCurrentProfileAttributes() throws Exception {
- final Profile profile = new Profile().withId(testUser.getId())
- .withAttributes(new HashMap<>(singletonMap("existed", "old")));
- when(profileDao.getById(profile.getId())).thenReturn(profile);
- final Map attributes = new HashMap<>(4);
- attributes.put("existed", "new");
- attributes.put("new", "value");
-
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH, attributes);
-
- assertEquals(response.getStatus(), OK.getStatusCode());
- verify(profileDao, times(1)).update(profile);
- assertEquals(((ProfileDescriptor)response.getEntity()).getAttributes(), attributes);
- }
-
- @Test
- public void shouldThrowExceptionIfAttributesUpdateForCurrentProfileIsNull() throws Exception {
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH, null);
-
- assertEquals(response.getStatus(), 409);
- }
-
- @Test
- public void shouldThrowExceptionIfAttributesUpdateForCurrentProfileIsEmpty() throws Exception {
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH, emptyMap());
-
- assertEquals(response.getStatus(), 409);
- }
-
- @Test
- public void shouldThrowExceptionIfAttributesUpdateForSpecificProfileIsNull() throws Exception {
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/any_profile_id", null);
-
- assertEquals(response.getStatus(), 409);
- }
-
- @Test
- public void shouldThrowExceptionIfAttributesUpdateForSpecificProfileIsEmpty() throws Exception {
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/any_profile_id", emptyMap());
-
- assertEquals(response.getStatus(), 409);
- }
-
- @Test
- public void shouldBeAbleToUpdateProfileById() throws Exception {
- final Profile profile = new Profile().withId(testUser.getId())
- .withUserId(testUser.getId())
- .withAttributes(new HashMap<>(singletonMap("existed", "old")));
- when(profileDao.getById(testUser.getId())).thenReturn(profile);
- final Map attributes = new HashMap<>(4);
- attributes.put("existed", "new");
- attributes.put("new", "value");
-
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/" + profile.getId(), attributes);
-
- assertEquals(response.getStatus(), OK.getStatusCode());
- assertEquals(((ProfileDescriptor)response.getEntity()).getAttributes(), attributes);
- verify(profileDao, times(1)).update(profile);
- }
-
- @Test
- public void testLinks() {
- final Profile profile = new Profile().withId(testUser.getId());
-
- final Set expectedRels = new HashSet<>(asList(LINK_REL_GET_CURRENT_USER_PROFILE,
- LINK_REL_UPDATE_CURRENT_USER_PROFILE,
- LINK_REL_GET_USER_PROFILE_BY_ID,
- LINK_REL_UPDATE_PREFERENCES,
- LINK_REL_UPDATE_USER_PROFILE_BY_ID));
-
- assertEquals(asRels(service.toDescriptor(profile).getLinks()), expectedRels);
- }
-
- private Set asRels(List links) {
- final Set rels = new HashSet<>();
- for (Link link : links) {
- rels.add(link.getRel());
- }
- return rels;
- }
-
- private ContainerResponse makeRequest(String method, String path, Object entity) throws Exception {
- Map> headers = null;
- byte[] data = null;
- if (entity != null) {
- headers = new HashMap<>();
- headers.put(HttpHeaders.CONTENT_TYPE, singletonList(MediaType.APPLICATION_JSON));
- data = JsonHelper.toJson(entity).getBytes();
- }
- return launcher.service(method, path, BASE_URI, headers, data, null, environmentContext);
- }
-}
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserServiceTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserServiceTest.java
index a24938e5ff..36a1742c13 100644
--- a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserServiceTest.java
+++ b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserServiceTest.java
@@ -10,52 +10,47 @@
*******************************************************************************/
package org.eclipse.che.api.user.server;
-import org.eclipse.che.api.core.ForbiddenException;
-import org.eclipse.che.api.core.NotFoundException;
-import org.eclipse.che.api.core.ServerException;
+import com.google.common.collect.ImmutableMap;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.jayway.restassured.response.Response;
+
+import org.eclipse.che.api.core.ConflictException;
+import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.core.rest.ApiExceptionMapper;
-import org.eclipse.che.api.user.server.dao.User;
-import org.eclipse.che.api.user.shared.dto.UserDescriptor;
-import org.eclipse.che.commons.json.JsonHelper;
+import org.eclipse.che.api.core.rest.shared.dto.ServiceError;
+import org.eclipse.che.api.user.server.model.impl.UserImpl;
+import org.eclipse.che.api.user.shared.dto.UserDto;
+import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
+import org.eclipse.che.commons.subject.SubjectImpl;
import org.eclipse.che.dto.server.DtoFactory;
-import org.everrest.core.impl.ApplicationContextImpl;
-import org.everrest.core.impl.ApplicationProviderBinder;
-import org.everrest.core.impl.ContainerResponse;
-import org.everrest.core.impl.EnvironmentContext;
-import org.everrest.core.impl.EverrestConfiguration;
-import org.everrest.core.impl.EverrestProcessor;
-import org.everrest.core.impl.ProviderBinder;
-import org.everrest.core.impl.ResourceBinderImpl;
-import org.everrest.core.impl.uri.UriBuilderImpl;
-import org.everrest.core.tools.DependencySupplierImpl;
-import org.everrest.core.tools.ResourceLauncher;
+import org.everrest.assured.EverrestJetty;
+import org.everrest.core.Filter;
+import org.everrest.core.GenericContainerRequest;
+import org.everrest.core.RequestFilter;
+import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.UriInfo;
-import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.List;
import java.util.Map;
-import static java.util.Collections.singletonList;
-import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
-import static javax.ws.rs.core.Response.Status.CREATED;
-import static javax.ws.rs.core.Response.Status.NO_CONTENT;
-import static javax.ws.rs.core.Response.Status.OK;
+import static com.jayway.restassured.RestAssured.given;
+import static java.util.Collections.emptyList;
+import static org.eclipse.che.dto.server.DtoFactory.newDto;
+import static org.everrest.assured.JettyHttpServer.ADMIN_USER_NAME;
+import static org.everrest.assured.JettyHttpServer.ADMIN_USER_PASSWORD;
+import static org.everrest.assured.JettyHttpServer.SECURE_PATH;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
import static org.testng.Assert.assertEquals;
/**
@@ -64,354 +59,364 @@ import static org.testng.Assert.assertEquals;
* @author Eugene Veovodin
* @author Max Shaposhnik
*/
-@Listeners(value = {MockitoTestNGListener.class})
+@Listeners({EverrestJetty.class, MockitoTestNGListener.class})
public class UserServiceTest {
+ @SuppressWarnings("unused")
+ private static final ApiExceptionMapper MAPPER = new ApiExceptionMapper();
+ @SuppressWarnings("unused")
+ private static final EnvironmentFilter FILTER = new EnvironmentFilter();
+ private static final Subject SUBJECT = new SubjectImpl("user", "user123", "token", false);
- private final String BASE_URI = "http://localhost/service";
- private final String SERVICE_PATH = BASE_URI + "/user";
-
+ @Mock(answer = Answers.RETURNS_MOCKS)
+ private UserManager userManager;
@Mock
- TokenValidator tokenValidator;
+ private TokenValidator tokenValidator;
@Mock
- UserNameValidator userNameValidator;
- @Mock
- UriInfo uriInfo;
- @Mock
- EnvironmentContext environmentContext;
- @Mock
- UserManager userManager;
-
- UserService userService;
-
- ResourceLauncher launcher;
+ private UserLinksInjector linksInjector;
+ private UserValidator userValidator;
+ @Captor
+ private ArgumentCaptor userCaptor;
+ private UserService userService;
@BeforeMethod
- public void setUp() throws Exception {
- ResourceBinderImpl resources = new ResourceBinderImpl();
- DependencySupplierImpl dependencies = new DependencySupplierImpl();
- dependencies.addComponent(UserManager.class, userManager);
- dependencies.addComponent(TokenValidator.class, tokenValidator);
+ public void initService() {
+ initMocks(this);
- userService = new UserService(userManager, tokenValidator, userNameValidator, true);
- final Field uriField = userService.getClass()
- .getSuperclass()
- .getDeclaredField("uriInfo");
- uriField.setAccessible(true);
- uriField.set(userService, uriInfo);
+ userValidator = new UserValidator(userManager);
- resources.addResource(userService, null);
+ // Return the incoming instance when injectLinks is called
+ when(linksInjector.injectLinks(any(), any())).thenAnswer(inv -> inv.getArguments()[0]);
- EverrestProcessor processor = new EverrestProcessor(resources,
- new ApplicationProviderBinder(),
- dependencies,
- new EverrestConfiguration(),
- null);
- launcher = new ResourceLauncher(processor);
- ProviderBinder providerBinder = ProviderBinder.getInstance();
- providerBinder.addExceptionMapper(ApiExceptionMapper.class);
- ApplicationContextImpl.setCurrent(new ApplicationContextImpl(null, null, providerBinder));
- //set up user
- final User user = createUser();
-
- when(uriInfo.getBaseUriBuilder()).thenReturn(new UriBuilderImpl());
-
- org.eclipse.che.commons.env.EnvironmentContext.getCurrent().setSubject(new Subject() {
-
- @Override
- public String getUserName() {
- return user.getEmail();
- }
-
- @Override
- public boolean hasPermission(String domain, String instance, String action) {
- return false;
- }
-
- @Override
- public void checkPermission(String domain, String instance, String action) throws ForbiddenException {
- }
-
- @Override
- public String getToken() {
- return null;
- }
-
- @Override
- public String getUserId() {
- return user.getId();
- }
-
- @Override
- public boolean isTemporary() {
- return false;
- }
- });
- }
-
- @Test(enabled = false)
- //TODO Should be fixed within https://jira.codenvycorp.com/browse/CHE-1078
- public void shouldBeAbleToCreateNewUser() throws Exception {
- final User userByToken = new User().withEmail("test@email.com").withName("test");
- final String userEmail = "test@email.com";
- final String userName = "test";
- final String token = "test_token";
- when(tokenValidator.validateToken(token)).thenReturn(userByToken);
-
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/create?token=" + token, null);
-
- assertEquals(response.getStatus(), CREATED.getStatusCode());
- final UserDescriptor user = (UserDescriptor)response.getEntity();
- assertEquals(user.getEmail(), userEmail);
- assertEquals(user.getName(), userName);
- assertEquals(user.getPassword(), "");
- verify(userManager).create(any(User.class), eq(false));
- }
-
- @Test(enabled = false)
- //TODO Should be fixed within https://jira.codenvycorp.com/browse/CHE-1078
- public void shouldBeAbleToCreateNewUserWithEmail() throws Exception {
- final String name = "name";
- final String email = "test_user@email.com";
- final UserDescriptor newUser = DtoFactory.getInstance()
- .createDto(UserDescriptor.class)
- .withName(name)
- .withEmail(email);
-
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/create", newUser);
-
- assertEquals(response.getStatus(), CREATED.getStatusCode());
- final UserDescriptor descriptor = (UserDescriptor)response.getEntity();
- assertEquals(descriptor.getName(), name);
- assertEquals(descriptor.getEmail(), email);
- }
-
- @Test(enabled = false)
- //TODO Should be fixed within https://jira.codenvycorp.com/browse/CHE-1078
- public void shouldBeAbleToCreateNewUserWithUserDto() throws Exception {
- final UserDescriptor newUser = DtoFactory.getInstance()
- .createDto(UserDescriptor.class)
- .withName("test")
- .withPassword("password123")
- .withEmail("test@mail.com");
-
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/create", newUser);
-
- assertEquals(response.getStatus(), CREATED.getStatusCode());
- final UserDescriptor descriptor = (UserDescriptor)response.getEntity();
- assertEquals(descriptor.getName(), newUser.getName());
- assertEquals(descriptor.getPassword(), "");
- verify(userManager).create(any(User.class), eq(false));
+ userService = new UserService(userManager, tokenValidator, userValidator, linksInjector, true);
}
@Test
- public void shouldThrowBadRequestExceptionWhenCreatingUserWithInvalidUsername() throws Exception {
- final UserDescriptor newUser = DtoFactory.getInstance()
- .createDto(UserDescriptor.class)
- .withName("test-123@gmail.com")
- .withPassword("password");
+ public void shouldCreateUserFromToken() throws Exception {
+ when(tokenValidator.validateToken("token_value")).thenReturn(new UserImpl("id", "test@eclipse.org", "test"));
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/create", newUser);
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .contentType("application/json")
+ .post(SECURE_PATH + "/user?token=token_value");
- assertEquals(response.getStatus(), BAD_REQUEST.getStatusCode());
- verify(userManager, never()).create(any(User.class), anyBoolean());
+ assertEquals(response.statusCode(), 201);
+ verify(userManager).create(userCaptor.capture(), anyBoolean());
+ final User user = userCaptor.getValue();
+ assertEquals(user.getEmail(), "test@eclipse.org");
+ assertEquals(user.getName(), "test");
}
@Test
- public void shouldThrowForbiddenExceptionWhenCreatingUserWithInvalidPassword() throws Exception {
- final UserDescriptor newUser = DtoFactory.getInstance()
- .createDto(UserDescriptor.class)
- .withName("test")
- .withPassword("password");
+ public void shouldCreateUserFromEntity() throws Exception {
+ final UserDto newUser = newDto(UserDto.class).withName("test")
+ .withEmail("test@codenvy.com")
+ .withPassword("password12345");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .body(newUser)
+ .contentType("application/json")
+ .post(SECURE_PATH + "/user");
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/create", newUser);
-
- assertEquals(response.getStatus(), BAD_REQUEST.getStatusCode());
- verify(userManager, never()).create(any(User.class), anyBoolean());
+ assertEquals(response.statusCode(), 201);
+ verify(userManager).create(userCaptor.capture(), anyBoolean());
+ final User user = userCaptor.getValue();
+ assertEquals(user.getEmail(), "test@codenvy.com");
+ assertEquals(user.getName(), "test");
+ assertEquals(user.getPassword(), "password12345");
}
@Test
- public void shouldThrowForbiddenExceptionWhenCreatingUserBasedOnEntityWhichIsNull() throws Exception {
+ public void shouldNotCreateUserFromEntityWhenPasswordIsNotValid() throws Exception {
+ final UserDto newUser = newDto(UserDto.class).withName("test")
+ .withEmail("test@codenvy.com")
+ .withPassword("1");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .body(newUser)
+ .contentType("application/json")
+ .post(SECURE_PATH + "/user");
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/create", null);
-
- assertEquals(response.getStatus(), BAD_REQUEST.getStatusCode());
- verify(userManager, never()).create(any(User.class), anyBoolean());
+ assertEquals(response.statusCode(), 400);
+ assertEquals(unwrapError(response), "Password should contain at least 8 characters");
}
@Test
- public void shouldThrowForbiddenExceptionWhenCreatingUserBasedOnEntityWhichContainsNullEmail() throws Exception {
- final UserDescriptor newUser = DtoFactory.getInstance().createDto(UserDescriptor.class);
+ public void shouldNotCreateUserIfTokenIsNotValid() throws Exception {
+ when(tokenValidator.validateToken("token_value")).thenThrow(new ConflictException("error"));
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/create", newUser);
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .contentType("application/json")
+ .post(SECURE_PATH + "/user?token=token_value");
- assertEquals(response.getStatus(), BAD_REQUEST.getStatusCode());
- verify(userManager, never()).create(any(User.class), anyBoolean());
+ assertEquals(response.statusCode(), 409);
+ assertEquals(unwrapError(response), "error");
+ }
+
+ @Test
+ public void shouldNotCreateUserFromEntityIfEntityIsNull() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .contentType("application/json")
+ .post(SECURE_PATH + "/user");
+
+ assertEquals(response.statusCode(), 400);
+ assertEquals(unwrapError(response), "User required");
+ }
+
+ @Test
+ public void shouldNotCreateUserFromEntityIfEmailIsNull() throws Exception {
+ final UserDto newUser = newDto(UserDto.class).withName("test")
+ .withPassword("password12345");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .body(newUser)
+ .contentType("application/json")
+ .post(SECURE_PATH + "/user");
+
+ assertEquals(response.statusCode(), 400);
+ assertEquals(unwrapError(response), "User email required");
+ }
+
+ @Test
+ public void shouldNotCreateUserFromEntityIfNameIsNull() throws Exception {
+ final UserDto newUser = newDto(UserDto.class).withEmail("test@codenvy.com")
+ .withPassword("password12345");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .body(newUser)
+ .contentType("application/json")
+ .post(SECURE_PATH + "/user");
+
+ assertEquals(response.statusCode(), 400);
+ assertEquals(unwrapError(response), "User name required");
+ }
+
+ @Test
+ public void shouldNotCreateUserFromEntityIfPasswordIsNotValid() throws Exception {
+ final UserDto newUser = newDto(UserDto.class).withEmail("test@codenvy.com")
+ .withName("test")
+ .withPassword("1");
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .body(newUser)
+ .contentType("application/json")
+ .post(SECURE_PATH + "/user");
+
+ assertEquals(response.statusCode(), 400);
+ assertEquals(unwrapError(response), "Password should contain at least 8 characters");
}
@Test
public void shouldBeAbleToGetCurrentUser() throws Exception {
- final User user = createUser();
+ when(userManager.getById(SUBJECT.getUserId())).thenReturn(copySubject());
- final ContainerResponse response = makeRequest(HttpMethod.GET, SERVICE_PATH, null);
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .get(SECURE_PATH + "/user");
- assertEquals(response.getStatus(), OK.getStatusCode());
- final UserDescriptor descriptor = (UserDescriptor)response.getEntity();
- assertEquals(descriptor.getId(), user.getId());
- assertEquals(descriptor.getEmail(), user.getEmail());
- assertEquals(descriptor.getAliases(), user.getAliases());
+ assertEquals(response.getStatusCode(), 200);
}
@Test
public void shouldBeAbleToGetUserById() throws Exception {
- final User user = createUser();
+ final UserImpl testUser = copySubject();
+ when(userManager.getById(SUBJECT.getUserId())).thenReturn(testUser);
- final ContainerResponse response = makeRequest(HttpMethod.GET, SERVICE_PATH + "/" + user.getId(), null);
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .get(SECURE_PATH + "/user/" + SUBJECT.getUserId());
- assertEquals(response.getStatus(), OK.getStatusCode());
- final UserDescriptor descriptor = (UserDescriptor)response.getEntity();
- assertEquals(descriptor.getId(), user.getId());
- assertEquals(descriptor.getEmail(), user.getEmail());
- assertEquals(descriptor.getAliases(), user.getAliases());
+ assertEquals(response.getStatusCode(), 200);
+ final UserDto fetchedUser = unwrapDto(response, UserDto.class);
+ assertEquals(fetchedUser.getId(), testUser.getId());
+ assertEquals(fetchedUser.getName(), testUser.getName());
+ assertEquals(fetchedUser.getEmail(), testUser.getEmail());
}
@Test
- public void shouldBeAbleToGetUserByEmail() throws Exception {
- final User user = createUser();
+ public void shouldBeAbleToFindUserByEmail() throws Exception {
+ final UserImpl testUser = copySubject();
+ when(userManager.getByEmail(testUser.getEmail())).thenReturn(testUser);
- final ContainerResponse response = makeRequest(HttpMethod.GET, SERVICE_PATH + "?alias=" + user.getEmail(), null);
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .get(SECURE_PATH + "/user/find?email=" + testUser.getEmail());
- assertEquals(response.getStatus(), OK.getStatusCode());
- final UserDescriptor descriptor = (UserDescriptor)response.getEntity();
- assertEquals(descriptor.getId(), user.getId());
- assertEquals(descriptor.getEmail(), user.getEmail());
- assertEquals(descriptor.getAliases(), user.getAliases());
+ assertEquals(response.getStatusCode(), 200);
+ final UserDto fetchedUser = unwrapDto(response, UserDto.class);
+ assertEquals(fetchedUser.getId(), testUser.getId());
+ assertEquals(fetchedUser.getName(), testUser.getName());
+ assertEquals(fetchedUser.getEmail(), testUser.getEmail());
}
@Test
- public void shouldBeAbleToUpdateUserPassword() throws Exception {
- final User user = createUser();
- final String newPassword = "validPass123";
- final Map> headers = new HashMap<>();
- headers.put(HttpHeaders.CONTENT_TYPE, singletonList(MediaType.APPLICATION_FORM_URLENCODED));
+ public void shouldBeAbleToFindUserByName() throws Exception {
+ final UserImpl testUser = copySubject();
+ when(userManager.getByName(testUser.getName())).thenReturn(testUser);
- final ContainerResponse response = launcher.service(HttpMethod.POST,
- SERVICE_PATH + "/password",
- BASE_URI,
- headers,
- ("password=" + newPassword).getBytes(),
- null,
- environmentContext);
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .get(SECURE_PATH + "/user/find?name=" + testUser.getName());
- assertEquals(response.getStatus(), NO_CONTENT.getStatusCode());
- verify(userManager).update(user.withPassword(newPassword));
+ assertEquals(response.getStatusCode(), 200);
+ final UserDto fetchedUser = unwrapDto(response, UserDto.class);
+ assertEquals(fetchedUser.getId(), testUser.getId());
+ assertEquals(fetchedUser.getName(), testUser.getName());
+ assertEquals(fetchedUser.getEmail(), testUser.getEmail());
}
@Test
- public void shouldFailUpdatePasswordContainsOnlyLetters() throws Exception {
- final User user = createUser();
- final String newPassword = "password";
- final Map> headers = new HashMap<>();
- headers.put(HttpHeaders.CONTENT_TYPE, singletonList(MediaType.APPLICATION_FORM_URLENCODED));
+ public void shouldNotFindUserByNameOrEmailWhenBothSpecified() throws Exception {
+ final UserImpl testUser = copySubject();
+ when(userManager.getByName(testUser.getName())).thenReturn(testUser);
- final ContainerResponse response = launcher.service(HttpMethod.POST,
- SERVICE_PATH + "/password",
- BASE_URI,
- headers,
- ("password=" + newPassword).getBytes(),
- null,
- environmentContext);
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .get(SECURE_PATH + "/user/find?" +
+ "name=" + testUser.getName() +
+ "&email=" + testUser.getEmail());
- assertEquals(response.getStatus(), BAD_REQUEST.getStatusCode());
- verify(userManager, never()).update(user.withPassword(newPassword));
+ assertEquals(response.getStatusCode(), 400);
+ assertEquals(unwrapError(response), "Expected either user's email or name, while both values received");
}
@Test
- public void shouldFailUpdatePasswordContainsOnlyDigits() throws Exception {
- final User user = createUser();
- final String newPassword = "12345678";
- final Map> headers = new HashMap<>();
- headers.put(HttpHeaders.CONTENT_TYPE, singletonList(MediaType.APPLICATION_FORM_URLENCODED));
+ public void shouldNotFindUserByNameOrEmailWhenBothAreEmpty() throws Exception {
+ final UserImpl testUser = copySubject();
+ when(userManager.getByName(testUser.getName())).thenReturn(testUser);
- final ContainerResponse response = launcher.service(HttpMethod.POST,
- SERVICE_PATH + "/password",
- BASE_URI,
- headers,
- ("password=" + newPassword).getBytes(),
- null,
- environmentContext);
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .get(SECURE_PATH + "/user/find");
- assertEquals(response.getStatus(), BAD_REQUEST.getStatusCode());
- verify(userManager, never()).update(user.withPassword(newPassword));
+ assertEquals(response.getStatusCode(), 400);
+ assertEquals(unwrapError(response), "Missed user's email or name");
}
@Test
- public void shouldFailUpdatePasswordWhichLessEightChar() throws Exception {
- final User user = createUser();
- final String newPassword = "abc123";
- final Map> headers = new HashMap<>();
- headers.put(HttpHeaders.CONTENT_TYPE, singletonList(MediaType.APPLICATION_FORM_URLENCODED));
-
- final ContainerResponse response = launcher.service(HttpMethod.POST,
- SERVICE_PATH + "/password",
- BASE_URI,
- headers,
- ("password=" + newPassword).getBytes(),
- null,
- environmentContext);
-
- assertEquals(response.getStatus(), BAD_REQUEST.getStatusCode());
- verify(userManager, never()).update(user.withPassword(newPassword));
- }
-
- @Test
- public void shouldBeAbleToRemoveUser() throws Exception {
- final User testUser = createUser();
-
- final ContainerResponse response = makeRequest(HttpMethod.DELETE, SERVICE_PATH + "/" + testUser.getId(), null);
-
- assertEquals(response.getStatus(), NO_CONTENT.getStatusCode());
- verify(userManager).remove(testUser.getId());
- }
-
- @Test
- public void shouldNotBeAbleToCreateUserWithoutEmailBySystemAdmin() throws Exception {
- final UserDescriptor newUser = DtoFactory.getInstance()
- .createDto(UserDescriptor.class)
- .withName("user")
- .withPassword("password");
-
- final ContainerResponse response = makeRequest(HttpMethod.POST, SERVICE_PATH + "/create", newUser);
-
- assertEquals(response.getStatus(), BAD_REQUEST.getStatusCode());
- }
-
- @Test
- public void shouldBeAbleToGetSettingOfUserService() throws Exception {
- final ContainerResponse response = makeRequest(HttpMethod.GET, SERVICE_PATH + "/settings", null);
-
- assertEquals(response.getStatus(), OK.getStatusCode());
- @SuppressWarnings("unchecked")
- final Map settings = (Map)response.getEntity();
- assertEquals(settings.size(), 1);
- assertEquals(settings.get(UserService.USER_SELF_CREATION_ALLOWED), "true");
- }
-
- private User createUser() throws NotFoundException, ServerException {
- final User testUser = new User().withId("test_id")
- .withEmail("test@email");
+ public void shouldUpdatePassword() throws Exception {
+ final UserImpl testUser = copySubject();
when(userManager.getById(testUser.getId())).thenReturn(testUser);
- when(userManager.getByAlias(testUser.getEmail())).thenReturn(testUser);
- return testUser;
+
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType("application/x-www-form-urlencoded")
+ .body("password=password12345")
+ .when()
+ .post(SECURE_PATH + "/user/password");
+
+ verify(userManager).update(userCaptor.capture());
+ final User fetchedUser = userCaptor.getValue();
+ assertEquals(fetchedUser.getPassword(), "password12345");
}
- private ContainerResponse makeRequest(String method, String path, Object entity) throws Exception {
- Map> headers = null;
- byte[] data = null;
- if (entity != null) {
- headers = new HashMap<>();
- headers.put(HttpHeaders.CONTENT_TYPE, singletonList(MediaType.APPLICATION_JSON));
- data = JsonHelper.toJson(entity).getBytes();
+ @Test
+ public void shouldNotUpdatePasswordIfPasswordContainsOnlyDigits() throws Exception {
+ final UserImpl testUser = copySubject();
+ when(userManager.getById(testUser.getId())).thenReturn(testUser);
+
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType("application/x-www-form-urlencoded")
+ .body("password=1234567890")
+ .when()
+ .post(SECURE_PATH + "/user/password");
+
+ assertEquals(response.getStatusCode(), 400);
+ assertEquals(unwrapError(response), "Password should contain letters and digits");
+ }
+
+ @Test
+ public void shouldNotUpdatePasswordIfPasswordContainsLessThan8Chars() throws Exception {
+ final UserImpl testUser = copySubject();
+ when(userManager.getById(testUser.getId())).thenReturn(testUser);
+
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType("application/x-www-form-urlencoded")
+ .body("password=0xf")
+ .when()
+ .post(SECURE_PATH + "/user/password");
+
+ assertEquals(response.getStatusCode(), 400);
+ assertEquals(unwrapError(response), "Password should contain at least 8 characters");
+ }
+
+ @Test
+ public void shouldNotUpdatePasswordIfPasswordIsNull() throws Exception {
+ final UserImpl testUser = copySubject();
+ when(userManager.getById(testUser.getId())).thenReturn(testUser);
+
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .contentType("application/x-www-form-urlencoded")
+ .when()
+ .post(SECURE_PATH + "/user/password");
+
+ assertEquals(response.getStatusCode(), 400);
+ assertEquals(unwrapError(response), "Password required");
+ }
+
+ @Test
+ public void shouldRemoveUser() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .delete(SECURE_PATH + "/user/" + SUBJECT.getUserId());
+
+ assertEquals(response.getStatusCode(), 204);
+ verify(userManager).remove(SUBJECT.getUserId());
+ }
+
+ @Test
+ public void shouldBeAbleToGetSettings() throws Exception {
+ final Response response = given().auth()
+ .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
+ .when()
+ .get(SECURE_PATH + "/user/settings");
+
+ assertEquals(response.getStatusCode(), 200);
+ final Map settings = new Gson().fromJson(response.print(),
+ new TypeToken>() {}.getType());
+ assertEquals(settings, ImmutableMap.of("user.self.creation.allowed", "true"));
+ }
+
+ @Filter
+ public static class EnvironmentFilter implements RequestFilter {
+
+ public void doFilter(GenericContainerRequest request) {
+ EnvironmentContext.getCurrent().setSubject(SUBJECT);
}
- return launcher.service(method, path, BASE_URI, headers, data, null, environmentContext);
+ }
+
+ private static T unwrapDto(Response response, Class dtoClass) {
+ return DtoFactory.getInstance().createDtoFromJson(response.body().print(), dtoClass);
+ }
+
+ private static String unwrapError(Response response) {
+ return unwrapDto(response, ServiceError.class).getMessage();
+ }
+
+ private static UserImpl copySubject() {
+ return new UserImpl(SUBJECT.getUserId(),
+ SUBJECT.getUserName() + "@codenvy.com",
+ SUBJECT.getUserName(),
+ null,
+ emptyList());
}
}
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserNameValidatorTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserValidatorTest.java
similarity index 92%
rename from wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserNameValidatorTest.java
rename to wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserValidatorTest.java
index cf72910845..c3d486b3e7 100644
--- a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserNameValidatorTest.java
+++ b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/UserValidatorTest.java
@@ -15,7 +15,6 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
@@ -24,16 +23,19 @@ import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doThrow;
/**
+ * Tests of {@link UserValidator}.
+ *
* @author Mihail Kuznyetsov
+ * @author Yevhenii Voevodin
*/
@Listeners(MockitoTestNGListener.class)
-public class UserNameValidatorTest {
+public class UserValidatorTest {
@Mock
private UserManager userManager;
@InjectMocks
- private UserNameValidator userNameValidator;
+ private UserValidator userNameValidator;
@Test(dataProvider = "normalizeNames")
public void testNormalizeUserName(String input, String expected) throws Exception {
@@ -47,7 +49,7 @@ public class UserNameValidatorTest {
public void testValidUserName(String input, boolean expected) throws Exception {
doThrow(NotFoundException.class).when(userManager).getByName(anyString());
- Assert.assertEquals(userNameValidator.isValidUserName(input), expected);
+ Assert.assertEquals(userNameValidator.isValidName(input), expected);
}
@DataProvider(name = "normalizeNames")
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/model/impl/DataObjectsTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/model/impl/DataObjectsTest.java
new file mode 100644
index 0000000000..4dafc5f7f0
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/model/impl/DataObjectsTest.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server.model.impl;
+
+import com.google.common.collect.ImmutableMap;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import static java.util.Collections.singletonList;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Tests for {@link UserImpl} and {@link ProfileImpl}.
+ *
+ * @author Yevhenii Voevodin
+ */
+public class DataObjectsTest {
+
+ @Test
+ public void testUserCreation() {
+ final UserImpl user = new UserImpl("user123",
+ "user@company.com",
+ "user_name",
+ "password",
+ singletonList("google:id"));
+
+ assertEquals(user.getId(), "user123");
+ assertEquals(user.getEmail(), "user@company.com");
+ assertEquals(user.getName(), "user_name");
+ assertEquals(user.getPassword(), "password");
+ assertEquals(user.getAliases(), singletonList("google:id"));
+ }
+
+ @Test
+ public void testUserModification() throws Exception {
+ final UserImpl user = new UserImpl("user123",
+ "user@company.com",
+ "user_name",
+ "password",
+ singletonList("google:id"));
+
+ user.setName("new_name");
+ user.setEmail("new_email@company.com");
+ user.setPassword("new-password");
+ user.setAliases(singletonList("new-alias"));
+
+ assertEquals(user.getName(), "new_name");
+ assertEquals(user.getEmail(), "new_email@company.com");
+ assertEquals(user.getPassword(), "new-password");
+ assertEquals(user.getAliases(), singletonList("new-alias"));
+ }
+
+ @Test
+ public void testUserCopyConstructor() throws Exception {
+ final UserImpl user = new UserImpl("user123",
+ "user@company.com",
+ "user_name",
+ "password",
+ new ArrayList<>(singletonList("google:id")));
+ final UserImpl copy = new UserImpl(user);
+
+ user.getAliases().add("new-alias");
+
+ assertEquals(copy.getName(), "user_name");
+ assertEquals(copy.getEmail(), "user@company.com");
+ assertEquals(copy.getPassword(), "password");
+ assertEquals(copy.getAliases(), singletonList("google:id"));
+ assertFalse(copy.getAliases().contains("new-alias"));
+ }
+
+ @Test
+ public void testProfileCreation() {
+ final ProfileImpl profile = new ProfileImpl("user123",
+ ImmutableMap.of("attribute1", "value1",
+ "attribute2", "value2",
+ "attribute3", "value3"));
+
+ assertEquals(profile.getUserId(), "user123");
+ assertEquals(profile.getAttributes(), ImmutableMap.of("attribute1", "value1",
+ "attribute2", "value2",
+ "attribute3", "value3"));
+ }
+
+ @Test
+ public void testProfileModification() throws Exception {
+ final ProfileImpl profile = new ProfileImpl("user123",
+ ImmutableMap.of("attribute1", "value1",
+ "attribute2", "value2",
+ "attribute3", "value3"));
+
+ profile.setAttributes(ImmutableMap.of("attribute1", "value1"));
+
+ assertEquals(profile.getAttributes(), ImmutableMap.of("attribute1", "value1"));
+ }
+
+ @Test
+ public void testProfileCopyConstructor() throws Exception {
+ final ProfileImpl profile = new ProfileImpl("user123",
+ new HashMap<>(ImmutableMap.of("attribute1", "value1",
+ "attribute2", "value2",
+ "attribute3", "value3")));
+
+ final ProfileImpl copy = new ProfileImpl(profile);
+ profile.getAttributes().put("new-attribute", "new-value");
+
+ assertEquals(copy.getUserId(), "user123");
+ assertEquals(copy.getAttributes(), ImmutableMap.of("attribute1", "value1",
+ "attribute2", "value2",
+ "attribute3", "value3"));
+ assertFalse(copy.getAttributes().containsKey("new-attribute"));
+ }
+
+ @Test(dataProvider = "singleObjectProvider")
+ @SuppressWarnings("all")
+ public void testReflexiveness(Object obj) throws Exception {
+ assertTrue(obj.equals(obj));
+ }
+
+ @Test(dataProvider = "symmetryDataProvider")
+ public void testSymmetry(Object object1, Object object2) throws Exception {
+ assertTrue(object1.equals(object2));
+ assertTrue(object2.equals(object1));
+ }
+
+ @Test(dataProvider = "transitivityDataProvider")
+ public void testTransitivity(Object object1, Object object2, Object object3) {
+ assertTrue(object1.equals(object2));
+ assertTrue(object2.equals(object3));
+ assertTrue(object3.equals(object1));
+ }
+
+ @Test(dataProvider = "consistencyDataProvider")
+ public void testConsistency(Object object1, Object object2) {
+ assertTrue(object1.equals(object2));
+ }
+
+ @Test(dataProvider = "singleObjectProvider")
+ @SuppressWarnings("all")
+ public void testNotEqualityToNull(Object object) throws Exception {
+ assertFalse(object.equals(null));
+ }
+
+ @Test(dependsOnMethods = {"testReflexiveness", "testSymmetry", "testTransitivity", "testConsistency", "testNotEqualityToNull"})
+ public void testHashCodeContract() throws Exception {
+ final UserImpl user1 = new UserImpl("user123",
+ "user@company.com",
+ "user_name",
+ "password",
+ null);
+ final UserImpl user2 = new UserImpl("user123",
+ "user@company.com",
+ "user_name",
+ "password",
+ new ArrayList<>());
+
+ assertEquals(user1.hashCode(), user2.hashCode());
+ }
+
+ @DataProvider(name = "reflexivenessProvider")
+ public Object[][] singleObjectProvider() {
+ return new Object[][] {
+ {
+ new UserImpl("user123", "user@company.com", "user_name", "password", singletonList("google:id"))
+ },
+ {
+ new ProfileImpl("user123", ImmutableMap.of("attribute1", "value1",
+ "attribute2", "value2",
+ "attribute3", "value3"))
+ }
+ };
+ }
+
+ @DataProvider(name = "symmetryDataProvider")
+ public Object[][] symmetryDataProvider() {
+ return new Object[][] {
+ {
+ new UserImpl("user123", "user@company.com", "user_name", "password", singletonList("google:id")),
+ new UserImpl("user123", "user@company.com", "user_name", "password", singletonList("google:id"))
+ },
+ {
+ new ProfileImpl("user123", ImmutableMap.of("attribute1", "value1")),
+ new ProfileImpl("user123", ImmutableMap.of("attribute1", "value1"))
+ }
+ };
+ }
+
+ @DataProvider(name = "transitivityDataProvider")
+ public Object[][] transitivityDataProvider() {
+ return new Object[][] {
+ {
+ new UserImpl("user123", "user@company.com", "user_name", "password", null),
+ new UserImpl("user123", "user@company.com", "user_name", "password", new ArrayList<>()),
+ new UserImpl("user123", "user@company.com", "user_name", "password", null)
+ },
+ {
+ new ProfileImpl("user123", ImmutableMap.of("attribute1", "value1")),
+ new ProfileImpl("user123", ImmutableMap.of("attribute1", "value1")),
+ new ProfileImpl("user123", ImmutableMap.of("attribute1", "value1"))
+ }
+ };
+ }
+
+ @DataProvider(name = "consistencyDataProvider")
+ public Object[][] consistencyDatProvider() {
+ return new Object[][] {
+ {
+ new UserImpl("user123", "user@company.com", "user_name", "password", null),
+ new UserImpl("user123", "user@company.com", "user_name", "password", new ArrayList<>())
+ },
+ {
+ new ProfileImpl("user123", null),
+ new ProfileImpl("user123", new HashMap<>())
+ }
+ };
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/spi/tck/ProfileDaoTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/spi/tck/ProfileDaoTest.java
new file mode 100644
index 0000000000..e634ef40ab
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/spi/tck/ProfileDaoTest.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server.spi.tck;
+
+import com.google.common.collect.ImmutableMap;
+
+import org.eclipse.che.api.core.ConflictException;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.user.server.Constants;
+import org.eclipse.che.api.user.server.model.impl.ProfileImpl;
+import org.eclipse.che.api.user.server.spi.ProfileDao;
+import org.eclipse.che.commons.lang.NameGenerator;
+import org.eclipse.che.commons.test.tck.TckModuleFactory;
+import org.eclipse.che.commons.test.tck.repository.TckRepository;
+import org.eclipse.che.commons.test.tck.repository.TckRepositoryException;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import javax.inject.Inject;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests {@link ProfileDao} contract.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Guice(moduleFactory = TckModuleFactory.class)
+@Test(suiteName = ProfileDaoTest.SUITE_NAME)
+public class ProfileDaoTest {
+
+ public static final String SUITE_NAME = "ProfileDaoTck";
+
+ private static final int COUNT_OF_PROFILES = 5;
+
+ private ProfileImpl[] profiles;
+
+ @Inject
+ private ProfileDao profileDao;
+
+ @Inject
+ private TckRepository tckRepository;
+
+ @BeforeMethod
+ private void setUp() throws TckRepositoryException {
+ profiles = new ProfileImpl[COUNT_OF_PROFILES];
+
+ for (int i = 0; i < COUNT_OF_PROFILES; i++) {
+ final String userId = NameGenerator.generate("user", Constants.ID_LENGTH);
+ final Map attributes = new HashMap<>();
+ attributes.put("firstName", "first-name-" + i);
+ attributes.put("lastName", "last-name-" + i);
+ attributes.put("company", "company-" + i);
+ profiles[i] = new ProfileImpl(userId, attributes);
+ }
+
+ tckRepository.createAll(Arrays.asList(profiles));
+ }
+
+ @AfterMethod
+ private void cleanup() throws TckRepositoryException {
+ tckRepository.removeAll();
+ }
+
+ @Test
+ public void shouldGetProfileById() throws Exception {
+ final ProfileImpl profile = profiles[0];
+
+ assertEquals(profileDao.getById(profile.getUserId()), profile);
+ }
+
+ @Test(expectedExceptions = NotFoundException.class)
+ public void shouldThrowNotFoundExceptionWhenGettingNonExistingProfileById() throws Exception {
+ profileDao.getById("non-existing-user-id");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenGettingProfileByNullId() throws Exception {
+ profileDao.getById(null);
+ }
+
+ @Test(dependsOnMethods = "shouldGetProfileById")
+ public void shouldCreateProfile() throws Exception {
+ final ProfileImpl newProfile = new ProfileImpl("user123",
+ ImmutableMap.of("attribute1", "value1",
+ "attribute2", "value2",
+ "attribute3", "value3"));
+
+ profileDao.create(newProfile);
+
+ assertEquals(profileDao.getById(newProfile.getUserId()), newProfile);
+ }
+
+ @Test(expectedExceptions = ConflictException.class)
+ public void shouldThrowConflictExceptionWhenCreatingProfileThatAlreadyExistsForUserWithGivenId() throws Exception {
+ final ProfileImpl newProfile = new ProfileImpl(profiles[0].getUserId(),
+ ImmutableMap.of("attribute1", "value1",
+ "attribute2", "value2",
+ "attribute3", "value3"));
+
+ profileDao.create(newProfile);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenCreatingNull() throws Exception {
+ profileDao.create(null);
+ }
+
+ @Test(dependsOnMethods = "shouldGetProfileById")
+ public void shouldUpdateProfile() throws Exception {
+ final ProfileImpl profile = profiles[0];
+
+ profileDao.update(new ProfileImpl(profile.getUserId(),
+ ImmutableMap.of("firstName", "new-first-name",
+ "lastName", "new-second-name",
+ "company", "new-company")));
+
+ final ProfileImpl updated = profileDao.getById(profile.getUserId());
+ assertEquals(updated.getUserId(), profile.getUserId());
+ assertEquals(updated.getAttributes(), ImmutableMap.of("firstName", "new-first-name",
+ "lastName", "new-second-name",
+ "company", "new-company"));
+ }
+
+ @Test(expectedExceptions = NotFoundException.class)
+ public void shouldThrowNotFoundExceptionWhenUpdatingProfileOfNonExistingUser() throws Exception {
+ final ProfileImpl profile = profiles[0];
+
+ profileDao.update(new ProfileImpl("non-existing-user-id", profile.getAttributes()));
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenUpdatingNull() throws Exception {
+ profileDao.update(null);
+ }
+
+ @Test(expectedExceptions = NotFoundException.class,
+ dependsOnMethods = "shouldThrowNotFoundExceptionWhenGettingNonExistingProfileById")
+ public void shouldRemoveProfile() throws Exception {
+ final ProfileImpl profile = profiles[0];
+
+ profileDao.remove(profile.getUserId());
+ profileDao.getById(profile.getUserId());
+ }
+
+ @Test
+ public void shouldNotThrowAnyExceptionWhenRemovingNonExistingUser() throws Exception {
+ profileDao.remove("non-existing-id");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void shouldThrowNpeWhenRemovingNull() throws Exception {
+ profileDao.remove(null);
+ }
+}
diff --git a/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/spi/tck/UserDaoTest.java b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/spi/tck/UserDaoTest.java
new file mode 100644
index 0000000000..8094d9ae1b
--- /dev/null
+++ b/wsmaster/che-core-api-user/src/test/java/org/eclipse/che/api/user/server/spi/tck/UserDaoTest.java
@@ -0,0 +1,337 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.user.server.spi.tck;
+
+import org.eclipse.che.api.core.ConflictException;
+import org.eclipse.che.api.core.NotFoundException;
+import org.eclipse.che.api.core.UnauthorizedException;
+import org.eclipse.che.api.core.model.user.User;
+import org.eclipse.che.api.user.server.Constants;
+import org.eclipse.che.api.user.server.model.impl.UserImpl;
+import org.eclipse.che.api.user.server.spi.UserDao;
+import org.eclipse.che.commons.lang.NameGenerator;
+import org.eclipse.che.commons.test.tck.TckModuleFactory;
+import org.eclipse.che.commons.test.tck.repository.TckRepository;
+import org.eclipse.che.commons.test.tck.repository.TckRepositoryException;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests {@link UserDao} contract.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Guice(moduleFactory = TckModuleFactory.class)
+@Test(suiteName = UserDaoTest.SUITE_NAME)
+public class UserDaoTest {
+
+ public static final String SUITE_NAME = "UserDaoTck";
+
+ private static final int COUNT_OF_USERS = 5;
+
+ private UserImpl[] users;
+
+ @Inject
+ private UserDao userDao;
+
+ @Inject
+ private TckRepository