Remove Stack service (#14078)

* Remove Che6 Stack concept

Signed-off-by: Sergii Kabashniuk <skabashniuk@redhat.com>
7.20.x
Mykhailo Kuznietsov 2019-09-03 09:00:12 +03:00 committed by Sergii Kabashniuk
parent 3da8646eaf
commit 40ee503a05
93 changed files with 186 additions and 6930 deletions

View File

@ -73,7 +73,6 @@ import org.eclipse.che.api.workspace.server.spi.provision.env.WorkspaceAgentJava
import org.eclipse.che.api.workspace.server.spi.provision.env.WorkspaceIdEnvVarProvider;
import org.eclipse.che.api.workspace.server.spi.provision.env.WorkspaceNameEnvVarProvider;
import org.eclipse.che.api.workspace.server.spi.provision.env.WorkspaceNamespaceNameEnvVarProvider;
import org.eclipse.che.api.workspace.server.stack.StackLoader;
import org.eclipse.che.api.workspace.server.token.MachineTokenProvider;
import org.eclipse.che.api.workspace.server.wsplugins.ChePluginsApplier;
import org.eclipse.che.commons.auth.token.ChainedTokenExtractor;
@ -156,12 +155,6 @@ public class WsMasterModule extends AbstractModule {
install(new DevfileModule());
MapBinder<String, String> stacks =
MapBinder.newMapBinder(
binder(), String.class, String.class, Names.named(StackLoader.CHE_PREDEFINED_STACKS));
stacks.addBinding("stacks.json").toInstance("stacks-images");
stacks.addBinding("che-in-che.json").toInstance("");
bind(org.eclipse.che.api.workspace.server.stack.StackService.class);
bind(org.eclipse.che.api.workspace.server.TemporaryWorkspaceRemover.class);
bind(org.eclipse.che.api.workspace.server.WorkspaceService.class);
install(new FactoryModuleBuilder().build(ServersCheckerFactory.class));
@ -310,7 +303,6 @@ public class WsMasterModule extends AbstractModule {
bind(TokenValidator.class).to(org.eclipse.che.api.local.DummyTokenValidator.class);
bind(MachineTokenProvider.class).to(MachineTokenProvider.EmptyMachineTokenProvider.class);
bind(org.eclipse.che.api.workspace.server.stack.StackLoader.class);
bind(DataSource.class).toProvider(org.eclipse.che.core.db.h2.H2DataSourceProvider.class);
install(new org.eclipse.che.api.user.server.jpa.UserJpaModule());

View File

@ -32,7 +32,6 @@
<class>org.eclipse.che.api.workspace.server.model.impl.SourceStorageImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.VolumeImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.CommandImpl</class>
@ -68,8 +67,7 @@
<class>org.eclipse.che.multiuser.api.permission.server.model.impl.SystemPermissionsImpl</class>
<class>org.eclipse.che.multiuser.api.permission.server.model.impl.AbstractPermissions</class>
<class>org.eclipse.che.multiuser.permission.workspace.server.model.impl.WorkerImpl</class>
<class>org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl</class>
<class>org.eclipse.che.multiuser.resource.spi.impl.FreeResourcesLimitImpl</class>
<class>org.eclipse.che.multiuser.resource.spi.impl.ResourceImpl</class>

View File

@ -1,160 +0,0 @@
[
{
"id": "che-in-che",
"creator": "ide",
"name": "Eclipse Che",
"description": "Utilities to build Che in Che with JDK 8 and Maven.",
"scope": "general",
"tags": [
"Java",
"JDK",
"Maven",
"Git",
"SDK"
],
"components": [
{
"name": "JDK",
"version": "1.8.0_92"
},
{
"name": "Maven",
"version": "3.3.9"
}
],
"workspaceConfig": {
"environments": {
"default": {
"machines": {
"dev-machine": {
"volumes": {
"m2": {
"path": "/home/user/.m2/"
}
},
"installers": [
"org.eclipse.che.exec",
"org.eclipse.che.terminal",
"org.eclipse.che.ws-agent",
"org.eclipse.che.ls.js-ts",
"org.eclipse.che.ls.java"
],
"servers": {
"dev-wsagent/wsagent": {
"path": "wsagent",
"protocol": "ws",
"port": "8087"
},
"GWT-CodeServer": {
"protocol": "http",
"port": "9876"
},
"IDE-agent-server": {
"protocol": "http",
"port": "8085"
},
"dev-wsagent/http": {
"path": "api",
"protocol": "http",
"port": "8087"
},
"tomcat8" : {
"port" : "8080",
"protocol" : "http"
}
},
"attributes": {
"memoryLimitBytes": "7516192768"
}
}
},
"recipe": {
"content": "eclipse/che-dev:nightly",
"type": "dockerimage"
}
}
},
"name": "default",
"defaultEnv": "default",
"description": null,
"commands": [
{
"commandLine": "cd ${current.project.path} && mvn clean install -Pnative",
"name": "Build project",
"type": "custom",
"attributes": {
"goal": "Run",
"previewUrl": ""
}
},
{
"commandLine": "cd ${current.project.eldest.parent.path} && mvn gwt:codeserver -pl :assembly-ide-war -am -Psdm-in-che -Dskip-enforce -Dskip-validate-sources -Dche.dto.skip -Dmaven.main.skip -Dmaven.resources.skip -Dmaven.buildNumber.skip",
"name": "GWT SDM",
"type": "gwt_sdm_che",
"attributes": {
"goal": "Run",
"previewUrl": "${server.GWT-CodeServer}"
}
},
{
"commandLine": "cd /home/user/tomcat8/bin && export SERVER_PORT=8080 && export JPDA_ADDRESS=9000 && ./catalina.sh jpda run",
"name": "Tomcat8-IDE Start",
"type": "custom",
"attributes": {
"goal": "Run",
"previewUrl": ""
}
},
{
"commandLine": "cd /home/user/traefik && ./traefik",
"name": "Traefik Start",
"type": "custom",
"attributes": {
"goal": "Run",
"previewUrl": ""
}
},
{
"commandLine": "cd ${current.project.eldest.parent.path} && mvn clean install -pl :assembly-wsagent-war -am && cp ${current.project.eldest.parent.path}/assembly/assembly-wsagent-war/target/*.war /home/user/tomcat8/webapps/ROOT.war",
"name": "Deploy Workspace Agent",
"type": "custom",
"attributes": {
"goal": "Run",
"previewUrl": "${server.IDE-agent-server}/${workspace.namespace}/${workspace.name}?wsagent-ref-prefix=dev-"
}
},
{
"commandLine": "cd ${current.project.eldest.parent.path} && mvn clean install -pl :assembly-ide-war -am && cp ${current.project.eldest.parent.path}/assembly/assembly-ide-war/target/*.war /home/user/tomcat8/webapps/ide.war",
"name": "Deploy IDE",
"type": "custom",
"attributes": {
"goal": "Run",
"previewUrl": "${server.IDE-agent-server}/${workspace.namespace}/${workspace.name}?wsagent-ref-prefix=dev-"
}
},
{
"commandLine": "cp ${current.project.path}/target/*.jar /home/user/tomcat8/webapps/ROOT/WEB-INF/lib/ && echo \"Artifact copied. It takes a few seconds for Tomcat to hot deploy it.\"",
"name": "Hot Deploy Workspace Agent",
"type": "custom",
"attributes": {
"goal": "Run",
"previewUrl": ""
}
},
{
"commandLine": "cd ${current.project.eldest.parent.path} && mvn sortpom:sort fmt:format",
"name": "Sort POM & Do Format",
"type": "custom",
"attributes": {
"goal": "Run",
"previewUrl": ""
}
}
]
},
"stackIcon": {
"name": "type-che.svg",
"mediaType": "image/svg+xml"
}
}
]

View File

@ -352,15 +352,6 @@ db.schema.flyway.scripts.suffix=.sql
db.schema.flyway.scripts.version_separator=__
db.schema.flyway.scripts.locations=classpath:che-schema
# Defines whether stacks loaded once or each time server starts.
# If value is 'false' stacks will be loaded once after database is initialized,
# otherwise stacks will be loaded each time server starts.
# Stacks loading overrides existing predefined stacks with new data
# defined in stacks.json.
# - 'default' : false
# Note that this property is needed for backward compatibility and will be removed soon.
che.predefined.stacks.reload_on_start=false
### Kubernetes Infra parameters
# Configuration of Kubernetes client that Infra will use

View File

@ -64,7 +64,6 @@ data:
CHE_MULTIUSER: {{ .Values.global.multiuser | quote }}
CHE_OAUTH_GITHUB_CLIENTID: {{ .Values.global.gitHubClientID | quote}}
CHE_OAUTH_GITHUB_CLIENTSECRET: {{ .Values.global.gitHubClientSecret | quote}}
CHE_PREDEFINED_STACKS_RELOAD__ON__START: "false"
JAVA_OPTS: "-XX:MaxRAMFraction=2 -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Dsun.zip.disableMemoryMapping=true -Xms20m "
CHE_WORKSPACE_AUTO_START: "false"
{{- if .Values.global.tls.enabled }}

View File

@ -138,8 +138,6 @@ objects:
value: "${CHE_OAUTH_GITHUB_CLIENTID}"
- name: CHE_OAUTH_GITHUB_CLIENTSECRET
value: "${CHE_OAUTH_GITHUB_CLIENTSECRET}"
- name: CHE_PREDEFINED_STACKS_RELOAD__ON__START
value: 'true'
- name: JAVA_OPTS
value: "-XX:MaxRAMFraction=2 -XX:+UseParallelGC -XX:MinHeapFreeRatio=10
-XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90

View File

@ -11,7 +11,6 @@
*/
package org.eclipse.che.multiuser.integration.jpa.cascaderemoval;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.eclipse.che.multiuser.api.permission.server.AbstractPermissionsDomain.SET_PERMISSIONS;
@ -22,7 +21,6 @@ import static org.eclipse.che.multiuser.integration.jpa.cascaderemoval.TestObjec
import static org.eclipse.che.multiuser.integration.jpa.cascaderemoval.TestObjectsFactory.createProfile;
import static org.eclipse.che.multiuser.integration.jpa.cascaderemoval.TestObjectsFactory.createSignatureKeyPair;
import static org.eclipse.che.multiuser.integration.jpa.cascaderemoval.TestObjectsFactory.createSshPair;
import static org.eclipse.che.multiuser.integration.jpa.cascaderemoval.TestObjectsFactory.createStack;
import static org.eclipse.che.multiuser.integration.jpa.cascaderemoval.TestObjectsFactory.createUser;
import static org.eclipse.che.multiuser.integration.jpa.cascaderemoval.TestObjectsFactory.createWorker;
import static org.eclipse.che.multiuser.integration.jpa.cascaderemoval.TestObjectsFactory.createWorkspace;
@ -38,16 +36,13 @@ import static org.testng.Assert.fail;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.multibindings.MapBinder;
import com.google.inject.multibindings.Multibinder;
import com.google.inject.name.Names;
import com.google.inject.persist.jpa.JpaPersistModule;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import javax.annotation.PostConstruct;
import javax.inject.Singleton;
@ -81,9 +76,7 @@ import org.eclipse.che.api.workspace.server.WorkspaceSharedPool;
import org.eclipse.che.api.workspace.server.WorkspaceStatusCache;
import org.eclipse.che.api.workspace.server.devfile.DevfileModule;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.RuntimeInfrastructure;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.spi.WorkspaceDao;
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironmentFactory;
import org.eclipse.che.api.workspace.server.wsplugins.ChePluginsApplier;
@ -100,8 +93,6 @@ import org.eclipse.che.inject.lifecycle.InitModule;
import org.eclipse.che.multiuser.api.permission.server.PermissionChecker;
import org.eclipse.che.multiuser.api.permission.server.PermissionCheckerImpl;
import org.eclipse.che.multiuser.api.permission.server.PermissionsManager;
import org.eclipse.che.multiuser.api.permission.server.model.impl.AbstractPermissions;
import org.eclipse.che.multiuser.api.permission.server.spi.PermissionsDao;
import org.eclipse.che.multiuser.machine.authentication.server.MachineAuthModule;
import org.eclipse.che.multiuser.machine.authentication.server.signature.spi.SignatureKeyDao;
import org.eclipse.che.multiuser.organization.api.OrganizationJpaModule;
@ -113,11 +104,7 @@ import org.eclipse.che.multiuser.organization.spi.MemberDao;
import org.eclipse.che.multiuser.organization.spi.impl.MemberImpl;
import org.eclipse.che.multiuser.organization.spi.impl.OrganizationImpl;
import org.eclipse.che.multiuser.permission.workspace.server.jpa.MultiuserWorkspaceJpaModule;
import org.eclipse.che.multiuser.permission.workspace.server.jpa.listener.RemoveStackOnLastUserRemovedEventSubscriber;
import org.eclipse.che.multiuser.permission.workspace.server.spi.WorkerDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaStackPermissionsDao;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
import org.eclipse.che.multiuser.resource.api.AvailableResourcesProvider;
import org.eclipse.che.multiuser.resource.api.ResourceLockKeyProvider;
import org.eclipse.che.multiuser.resource.api.ResourceUsageTracker;
@ -152,10 +139,8 @@ public class JpaEntitiesCascadeRemovalTest {
private WorkspaceDao workspaceDao;
private SshDao sshDao;
private FactoryDao factoryDao;
private StackDao stackDao;
private WorkerDao workerDao;
private SignatureKeyDao signatureKeyDao;
private JpaStackPermissionsDao stackPermissionsDao;
private FreeResourcesLimitDao freeResourcesLimitDao;
private OrganizationManager organizationManager;
private MemberDao memberDao;
@ -196,12 +181,6 @@ public class JpaEntitiesCascadeRemovalTest {
private FactoryImpl factory2;
/** Stack depend on user via permissions */
private StackImpl stack1;
private StackImpl stack2;
private StackImpl stack3;
/** Organization depends on user via permissions */
private Organization organization;
@ -314,7 +293,6 @@ public class JpaEntitiesCascadeRemovalTest {
sshDao = injector.getInstance(SshDao.class);
workspaceDao = injector.getInstance(WorkspaceDao.class);
factoryDao = injector.getInstance(FactoryDao.class);
stackDao = injector.getInstance(StackDao.class);
workerDao = injector.getInstance(WorkerDao.class);
signatureKeyDao = injector.getInstance(SignatureKeyDao.class);
freeResourcesLimitDao = injector.getInstance(FreeResourcesLimitDao.class);
@ -322,15 +300,6 @@ public class JpaEntitiesCascadeRemovalTest {
memberDao = injector.getInstance(MemberDao.class);
organizationResourcesDistributor = injector.getInstance(OrganizationResourcesDistributor.class);
TypeLiteral<Set<PermissionsDao<? extends AbstractPermissions>>> lit =
new TypeLiteral<Set<PermissionsDao<? extends AbstractPermissions>>>() {};
Key<Set<PermissionsDao<? extends AbstractPermissions>>> key = Key.get(lit);
for (PermissionsDao<? extends AbstractPermissions> dao : injector.getInstance(key)) {
if (dao.getDomain().getId().equals(StackDomain.DOMAIN_ID)) {
stackPermissionsDao = (JpaStackPermissionsDao) dao;
}
}
h2JpaCleaner = injector.getInstance(H2JpaCleaner.class);
}
@ -358,14 +327,8 @@ public class JpaEntitiesCascadeRemovalTest {
// Check workers and parent entity is removed
assertTrue(workspaceDao.getByNamespace(user2.getId(), 30, 0).isEmpty());
assertEquals(workerDao.getWorkers(workspace3.getId(), 1, 0).getTotalItemsCount(), 0);
// Check stack and recipes are removed
assertNull(notFoundToNull(() -> stackDao.getById(stack1.getId())));
assertNull(notFoundToNull(() -> stackDao.getById(stack2.getId())));
// Permissions are removed
assertTrue(stackPermissionsDao.getByUser(user2.getId()).isEmpty());
// Non-removed user permissions and stack are present
assertNotNull(notFoundToNull(() -> stackDao.getById(stack3.getId())));
assertFalse(stackPermissionsDao.getByUser(user3.getId()).isEmpty());
// Check existence of organizations
assertNull(notFoundToNull(() -> organizationManager.getById(organization.getId())));
assertEquals(memberDao.getMembers(organization.getId(), 1, 0).getTotalItemsCount(), 0);
@ -391,7 +354,6 @@ public class JpaEntitiesCascadeRemovalTest {
notFoundToNull(() -> organizationResourcesDistributor.get(childOrganization.getId())));
// cleanup
stackDao.remove(stack3.getId());
memberDao.remove(organization2.getId(), user3.getId());
organizationManager.remove(organization2.getId());
userDao.remove(user3.getId());
@ -413,9 +375,6 @@ public class JpaEntitiesCascadeRemovalTest {
// Check all the data rolled back
assertNotNull(userDao.getById(user2.getId()));
assertFalse(stackPermissionsDao.getByUser(user2.getId()).isEmpty());
assertNotNull(notFoundToNull(() -> stackDao.getById(stack1.getId())));
assertNotNull(notFoundToNull(() -> stackDao.getById(stack2.getId())));
assertNotNull(notFoundToNull(() -> freeResourcesLimitDao.get(account.getId())));
assertNotNull(notFoundToNull(() -> organizationManager.getById(organization.getId())));
assertNotNull(notFoundToNull(() -> organizationManager.getById(childOrganization.getId())));
@ -429,7 +388,6 @@ public class JpaEntitiesCascadeRemovalTest {
@DataProvider(name = "beforeRemoveRollbackActions")
public Object[][] beforeRemoveActions() {
return new Class[][] {
{RemoveStackOnLastUserRemovedEventSubscriber.class, BeforeUserRemovedEvent.class},
{RemoveOrganizationOnLastUserRemovedEventSubscriber.class, BeforeUserRemovedEvent.class}
};
}
@ -456,29 +414,11 @@ public class JpaEntitiesCascadeRemovalTest {
factoryDao.create(factory1 = createFactory("factory1", user.getId()));
factoryDao.create(factory2 = createFactory("factory2", user.getId()));
stackDao.create(stack1 = createStack("stack1", "st1"));
stackDao.create(stack2 = createStack("stack2", "st2"));
stackDao.create(stack3 = createStack("stack3", "st3"));
workerDao.store(createWorker(user2.getId(), workspace3.getId()));
signatureKeyDao.create(createSignatureKeyPair(workspace1.getId()));
signatureKeyDao.create(createSignatureKeyPair(workspace2.getId()));
stackPermissionsDao.store(
new StackPermissionsImpl(
user2.getId(), stack1.getId(), asList(SET_PERMISSIONS, "read", "write")));
stackPermissionsDao.store(
new StackPermissionsImpl(
user2.getId(), stack2.getId(), asList(SET_PERMISSIONS, "read", "execute")));
// To test removal only permissions if more users with setPermissions are present
stackPermissionsDao.store(
new StackPermissionsImpl(
user2.getId(), stack3.getId(), asList(SET_PERMISSIONS, "read", "write")));
stackPermissionsDao.store(
new StackPermissionsImpl(
user3.getId(), stack3.getId(), asList(SET_PERMISSIONS, "read", "write", "execute")));
// creator will have all permissions for newly created organization
prepareCreator(user.getId());
organization = organizationManager.create(new OrganizationImpl(null, "testOrg", null));
@ -524,15 +464,6 @@ public class JpaEntitiesCascadeRemovalTest {
organizationManager.remove(organization.getId());
organizationManager.remove(organization2.getId());
stackPermissionsDao.remove(user2.getId(), stack1.getId());
stackPermissionsDao.remove(user2.getId(), stack2.getId());
stackPermissionsDao.remove(user2.getId(), stack3.getId());
stackPermissionsDao.remove(user3.getId(), stack3.getId());
stackDao.remove(stack1.getId());
stackDao.remove(stack2.getId());
stackDao.remove(stack3.getId());
workerDao.removeWorker(workspace3.getId(), user2.getId());
factoryDao.remove(factory1.getId());

View File

@ -29,9 +29,6 @@ import org.eclipse.che.api.user.server.model.impl.ProfileImpl;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackComponentImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.stack.image.StackIcon;
import org.eclipse.che.multiuser.machine.authentication.server.signature.model.impl.SignatureKeyPairImpl;
import org.eclipse.che.multiuser.permission.workspace.server.model.impl.WorkerImpl;
import org.eclipse.che.multiuser.resource.spi.impl.FreeResourcesLimitImpl;
@ -96,24 +93,6 @@ public final class TestObjectsFactory {
null);
}
public static StackImpl createStack(String id, String name) {
return StackImpl.builder()
.setId(id)
.setName(name)
.setCreator("user123")
.setDescription(id + "-description")
.setScope(id + "-scope")
.setWorkspaceConfig(createWorkspaceConfig(id + "test"))
.setTags(asList(id + "-tag1", id + "-tag2"))
.setComponents(
asList(
new StackComponentImpl(id + "-component1", id + "-component1-version"),
new StackComponentImpl(id + "-component2", id + "-component2-version")))
.setStackIcon(
new StackIcon(id + "-icon", id + "-media-type", "0x1234567890abcdef".getBytes()))
.build();
}
public static WorkerImpl createWorker(String userId, String workspaceId) {
return new WorkerImpl(workspaceId, userId, Arrays.asList("read", "write", "run"));
}

View File

@ -31,7 +31,6 @@
<class>org.eclipse.che.api.workspace.server.model.impl.SourceStorageImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.VolumeImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.devfile.DevfileImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.devfile.ProjectImpl</class>
@ -64,7 +63,6 @@
<class>org.eclipse.che.multiuser.api.permission.server.model.impl.SystemPermissionsImpl</class>
<class>org.eclipse.che.multiuser.api.permission.server.model.impl.AbstractPermissions</class>
<class>org.eclipse.che.multiuser.permission.workspace.server.model.impl.WorkerImpl</class>
<class>org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl</class>
<class>org.eclipse.che.api.ssh.server.model.impl.SshPairImpl</class>
<class>org.eclipse.che.multiuser.organization.spi.impl.OrganizationImpl</class>

View File

@ -252,11 +252,7 @@
<port>jdbc.port:3306</port>
</ports>
<wait>
<tcp>
<ports>
<port>3306</port>
</ports>
</tcp>
<log>ready for connections</log>
<time>60000</time>
</wait>
<restartPolicy>

View File

@ -40,7 +40,6 @@ import javax.persistence.spi.PersistenceUnitTransactionType;
import org.eclipse.che.account.spi.AccountImpl;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.commons.test.tck.JpaCleaner;
import org.eclipse.che.commons.test.tck.TckModule;
import org.eclipse.che.commons.test.tck.TckResourcesCleaner;
@ -71,11 +70,8 @@ import org.eclipse.che.multiuser.organization.spi.jpa.JpaOrganizationDao;
import org.eclipse.che.multiuser.organization.spi.jpa.JpaOrganizationDistributedResourcesDao;
import org.eclipse.che.multiuser.permission.workspace.server.model.impl.WorkerImpl;
import org.eclipse.che.multiuser.permission.workspace.server.spi.WorkerDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaStackPermissionsDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaWorkerDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.tck.StackPermissionsDaoTest;
import org.eclipse.che.multiuser.permission.workspace.server.spi.tck.WorkerDaoTest;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
import org.eclipse.che.multiuser.resource.spi.FreeResourcesLimitDao;
import org.eclipse.che.multiuser.resource.spi.impl.FreeResourcesLimitImpl;
import org.eclipse.che.multiuser.resource.spi.jpa.JpaFreeResourcesLimitDao;
@ -132,24 +128,16 @@ public class MultiuserMySqlTckModule extends TckModule {
// api-workspace
bind(new TypeLiteral<TckRepository<WorkspaceImpl>>() {})
.toInstance(new JpaTckRepository<>(WorkspaceImpl.class));
bind(new TypeLiteral<TckRepository<StackImpl>>() {})
.toInstance(new JpaTckRepository<>(StackImpl.class));
bind(new TypeLiteral<TckRepository<WorkerImpl>>() {})
.toInstance(new JpaTckRepository<>(WorkerImpl.class));
// api permission
bind(new TypeLiteral<TckRepository<StackPermissionsImpl>>() {})
.toInstance(new JpaTckRepository<>(StackPermissionsImpl.class));
bind(new TypeLiteral<TckRepository<SystemPermissionsImpl>>() {})
.toInstance(new JpaTckRepository<>(SystemPermissionsImpl.class));
bind(new TypeLiteral<PermissionsDao<StackPermissionsImpl>>() {})
.to(JpaStackPermissionsDao.class);
bind(new TypeLiteral<PermissionsDao<SystemPermissionsImpl>>() {})
.to(JpaSystemPermissionsDao.class);
bind(new TypeLiteral<AbstractPermissionsDomain<StackPermissionsImpl>>() {})
.to(StackPermissionsDaoTest.TestDomain.class);
bind(new TypeLiteral<AbstractPermissionsDomain<WorkerImpl>>() {})
.to(WorkerDaoTest.TestDomain.class);
bind(new TypeLiteral<AbstractPermissionsDomain<SystemPermissionsImpl>>() {})

View File

@ -30,7 +30,6 @@
<class>org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl$Attribute</class>
<class>org.eclipse.che.api.workspace.server.model.impl.SourceStorageImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.VolumeImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.devfile.DevfileImpl</class>
@ -57,7 +56,6 @@
<class>org.eclipse.che.multiuser.api.permission.server.model.impl.SystemPermissionsImpl</class>
<class>org.eclipse.che.multiuser.api.permission.server.model.impl.AbstractPermissions</class>
<class>org.eclipse.che.multiuser.permission.workspace.server.model.impl.WorkerImpl</class>
<class>org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl</class>
<class>org.eclipse.che.multiuser.resource.spi.impl.FreeResourcesLimitImpl</class>
<class>org.eclipse.che.multiuser.resource.spi.impl.ResourceImpl</class>

View File

@ -40,7 +40,6 @@ import javax.persistence.spi.PersistenceUnitTransactionType;
import org.eclipse.che.account.spi.AccountImpl;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.commons.test.tck.JpaCleaner;
import org.eclipse.che.commons.test.tck.TckModule;
import org.eclipse.che.commons.test.tck.TckResourcesCleaner;
@ -71,11 +70,8 @@ import org.eclipse.che.multiuser.organization.spi.jpa.JpaOrganizationDao;
import org.eclipse.che.multiuser.organization.spi.jpa.JpaOrganizationDistributedResourcesDao;
import org.eclipse.che.multiuser.permission.workspace.server.model.impl.WorkerImpl;
import org.eclipse.che.multiuser.permission.workspace.server.spi.WorkerDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaStackPermissionsDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaWorkerDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.tck.StackPermissionsDaoTest;
import org.eclipse.che.multiuser.permission.workspace.server.spi.tck.WorkerDaoTest;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
import org.eclipse.che.multiuser.resource.spi.FreeResourcesLimitDao;
import org.eclipse.che.multiuser.resource.spi.impl.FreeResourcesLimitImpl;
import org.eclipse.che.multiuser.resource.spi.jpa.JpaFreeResourcesLimitDao;
@ -131,24 +127,16 @@ public class MultiuserPostgresqlTckModule extends TckModule {
// api-workspace
bind(new TypeLiteral<TckRepository<WorkspaceImpl>>() {})
.toInstance(new JpaTckRepository<>(WorkspaceImpl.class));
bind(new TypeLiteral<TckRepository<StackImpl>>() {})
.toInstance(new JpaTckRepository<>(StackImpl.class));
bind(new TypeLiteral<TckRepository<WorkerImpl>>() {})
.toInstance(new JpaTckRepository<>(WorkerImpl.class));
// api permission
bind(new TypeLiteral<TckRepository<StackPermissionsImpl>>() {})
.toInstance(new JpaTckRepository<>(StackPermissionsImpl.class));
bind(new TypeLiteral<TckRepository<SystemPermissionsImpl>>() {})
.toInstance(new JpaTckRepository<>(SystemPermissionsImpl.class));
bind(new TypeLiteral<PermissionsDao<StackPermissionsImpl>>() {})
.to(JpaStackPermissionsDao.class);
bind(new TypeLiteral<PermissionsDao<SystemPermissionsImpl>>() {})
.to(JpaSystemPermissionsDao.class);
bind(new TypeLiteral<AbstractPermissionsDomain<StackPermissionsImpl>>() {})
.to(StackPermissionsDaoTest.TestDomain.class);
bind(new TypeLiteral<AbstractPermissionsDomain<WorkerImpl>>() {})
.to(WorkerDaoTest.TestDomain.class);
bind(new TypeLiteral<AbstractPermissionsDomain<SystemPermissionsImpl>>() {})

View File

@ -30,7 +30,6 @@
<class>org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl$Attribute</class>
<class>org.eclipse.che.api.workspace.server.model.impl.SourceStorageImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.VolumeImpl</class>
<class>org.eclipse.che.api.workspace.server.model.impl.devfile.DevfileImpl</class>
@ -57,7 +56,6 @@
<class>org.eclipse.che.multiuser.api.permission.server.model.impl.SystemPermissionsImpl</class>
<class>org.eclipse.che.multiuser.api.permission.server.model.impl.AbstractPermissions</class>
<class>org.eclipse.che.multiuser.permission.workspace.server.model.impl.WorkerImpl</class>
<class>org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl</class>
<class>org.eclipse.che.multiuser.resource.spi.impl.FreeResourcesLimitImpl</class>
<class>org.eclipse.che.multiuser.resource.spi.impl.ResourceImpl</class>

View File

@ -34,7 +34,6 @@ import org.eclipse.che.api.workspace.server.model.impl.devfile.EntrypointImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.EnvImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.ProjectImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.SourceImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.commons.test.db.H2DBTestServer;
import org.eclipse.che.commons.test.db.H2JpaCleaner;
import org.eclipse.che.commons.test.db.PersistTestModuleBuilder;
@ -73,7 +72,6 @@ public class SignatureKeyTckModule extends TckModule {
MachineConfigImpl.class,
SourceStorageImpl.class,
ServerConfigImpl.class,
StackImpl.class,
CommandImpl.class,
RecipeImpl.class,
VolumeImpl.class,

View File

@ -12,23 +12,13 @@
package org.eclipse.che.multiuser.permission.workspace.server;
import com.google.inject.AbstractModule;
import com.google.inject.multibindings.MapBinder;
import com.google.inject.multibindings.Multibinder;
import com.google.inject.name.Names;
import org.eclipse.che.api.workspace.server.stack.StackLoader;
import org.eclipse.che.multiuser.api.permission.server.SuperPrivilegesChecker;
import org.eclipse.che.multiuser.api.permission.server.filter.check.RemovePermissionsChecker;
import org.eclipse.che.multiuser.api.permission.server.filter.check.SetPermissionsChecker;
import org.eclipse.che.multiuser.api.permission.shared.model.PermissionsDomain;
import org.eclipse.che.multiuser.permission.workspace.server.filters.InstallerServicePermissionFilter;
import org.eclipse.che.multiuser.permission.workspace.server.filters.PublicPermissionsRemoveChecker;
import org.eclipse.che.multiuser.permission.workspace.server.filters.StackDomainSetPermissionsChecker;
import org.eclipse.che.multiuser.permission.workspace.server.filters.StackPermissionsFilter;
import org.eclipse.che.multiuser.permission.workspace.server.filters.WorkspacePermissionsFilter;
import org.eclipse.che.multiuser.permission.workspace.server.filters.WorkspaceRemoteSubscriptionPermissionFilter;
import org.eclipse.che.multiuser.permission.workspace.server.stack.MultiuserStackLoader;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackCreatorPermissionsProvider;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain;
/** @author Sergii Leschenko */
public class WorkspaceApiPermissionsModule extends AbstractModule {
@ -36,13 +26,10 @@ public class WorkspaceApiPermissionsModule extends AbstractModule {
@Override
protected void configure() {
bind(WorkspacePermissionsFilter.class);
bind(StackPermissionsFilter.class);
bind(InstallerServicePermissionFilter.class).asEagerSingleton();
bind(WorkspaceRemoteSubscriptionPermissionFilter.class).asEagerSingleton();
bind(WorkspaceCreatorPermissionsProvider.class).asEagerSingleton();
bind(StackCreatorPermissionsProvider.class).asEagerSingleton();
bind(StackLoader.class).to(MultiuserStackLoader.class);
Multibinder.newSetBinder(
binder(),
@ -50,13 +37,5 @@ public class WorkspaceApiPermissionsModule extends AbstractModule {
Names.named(SuperPrivilegesChecker.SUPER_PRIVILEGED_DOMAINS))
.addBinding()
.to(WorkspaceDomain.class);
MapBinder.newMapBinder(binder(), String.class, SetPermissionsChecker.class)
.addBinding(StackDomain.DOMAIN_ID)
.to(StackDomainSetPermissionsChecker.class);
MapBinder.newMapBinder(binder(), String.class, RemovePermissionsChecker.class)
.addBinding(StackDomain.DOMAIN_ID)
.to(PublicPermissionsRemoveChecker.class);
}
}

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.filters;
import static org.eclipse.che.multiuser.api.permission.server.SystemDomain.DOMAIN_ID;
import static org.eclipse.che.multiuser.api.permission.server.SystemDomain.MANAGE_SYSTEM_ACTION;
import java.util.HashSet;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.multiuser.api.permission.server.PermissionsManager;
import org.eclipse.che.multiuser.api.permission.server.filter.check.DefaultRemovePermissionsChecker;
import org.eclipse.che.multiuser.api.permission.server.filter.check.RemovePermissionsChecker;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain;
/**
* Recipe and Stack domains remove permissions checker.
*
* @author Anton Korneta
*/
@Singleton
public class PublicPermissionsRemoveChecker implements RemovePermissionsChecker {
private final DefaultRemovePermissionsChecker defaultChecker;
private final PermissionsManager permissionsManager;
@Inject
public PublicPermissionsRemoveChecker(
DefaultRemovePermissionsChecker defaultChecker, PermissionsManager permissionsManager) {
this.defaultChecker = defaultChecker;
this.permissionsManager = permissionsManager;
}
@Override
public void check(String user, String domain, String instance) throws ForbiddenException {
if (!"*".equals(user)
|| !EnvironmentContext.getCurrent()
.getSubject()
.hasPermission(DOMAIN_ID, null, MANAGE_SYSTEM_ACTION)) {
defaultChecker.check(user, domain, instance);
return;
}
final Set<String> actions = new HashSet<>();
try {
actions.addAll(permissionsManager.get(user, domain, instance).getActions());
} catch (ApiException ignored) {
}
// perform default check if no search action found or its not admin user
if (!actions.contains(StackDomain.SEARCH)) {
defaultChecker.check(user, domain, instance);
}
}
}

View File

@ -1,73 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.filters;
import static java.util.stream.Collectors.toList;
import static org.eclipse.che.multiuser.api.permission.server.SystemDomain.MANAGE_SYSTEM_ACTION;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.READ;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.SEARCH;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.getActions;
import java.util.HashSet;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.multiuser.api.permission.server.SystemDomain;
import org.eclipse.che.multiuser.api.permission.server.filter.check.DefaultSetPermissionsChecker;
import org.eclipse.che.multiuser.api.permission.server.filter.check.SetPermissionsChecker;
import org.eclipse.che.multiuser.api.permission.shared.model.Permissions;
/**
* Stack domain specific set permission checker.
*
* @author Anton Korneta
*/
@Singleton
public class StackDomainSetPermissionsChecker implements SetPermissionsChecker {
private final DefaultSetPermissionsChecker defaultChecker;
@Inject
public StackDomainSetPermissionsChecker(DefaultSetPermissionsChecker defaultChecker) {
this.defaultChecker = defaultChecker;
}
@Override
public void check(Permissions permissions) throws ForbiddenException {
if (!"*".equals(permissions.getUserId())) {
defaultChecker.check(permissions);
return;
}
final Set<String> unsupportedPublicActions = new HashSet<>(permissions.getActions());
unsupportedPublicActions.remove(READ);
// public search is supported only for admins
if (EnvironmentContext.getCurrent()
.getSubject()
.hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION)) {
unsupportedPublicActions.remove(SEARCH);
} else {
defaultChecker.check(permissions);
}
if (!unsupportedPublicActions.isEmpty()) {
throw new ForbiddenException(
"Following actions are not supported for setting as public:"
+ getActions()
.stream()
.filter(a -> !(a.equals(READ) || a.equals(SEARCH)))
.collect(toList()));
}
}
}

View File

@ -1,162 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.filters;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.DELETE;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.DOMAIN_ID;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.READ;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.SEARCH;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.UPDATE;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import javax.ws.rs.Path;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.Page;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.workspace.server.stack.StackService;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
import org.eclipse.che.everrest.CheMethodInvokerFilter;
import org.eclipse.che.multiuser.api.permission.server.PermissionsManager;
import org.eclipse.che.multiuser.api.permission.server.SystemDomain;
import org.eclipse.che.multiuser.api.permission.server.model.impl.AbstractPermissions;
import org.everrest.core.Filter;
import org.everrest.core.resource.GenericResourceMethod;
/**
* Restricts access to methods of {@link StackService} by users' permissions
*
* <p>Filter should contain rules for protecting of all methods of {@link StackService}.<br>
* In case when requested method is unknown filter throws {@link ForbiddenException}
*
* @author Sergii Leschenko
* @author Mykola Morhun
*/
@Filter
@Path("/stack{path:(/.*)?}")
public class StackPermissionsFilter extends CheMethodInvokerFilter {
private final PermissionsManager permissionsManager;
@Inject
public StackPermissionsFilter(PermissionsManager permissionsManager) {
this.permissionsManager = permissionsManager;
}
@Override
public void filter(GenericResourceMethod genericResourceMethod, Object[] arguments)
throws ForbiddenException, ServerException {
final String methodName = genericResourceMethod.getMethod().getName();
final Subject currentSubject = EnvironmentContext.getCurrent().getSubject();
String action;
String stackId;
switch (methodName) {
case "getStack":
case "getIcon":
stackId = ((String) arguments[0]);
action = READ;
if (currentSubject.hasPermission(DOMAIN_ID, stackId, SEARCH)) {
// allow to read stack if user has 'search' permission
return;
}
break;
case "updateStack":
case "uploadIcon":
stackId = ((String) arguments[1]);
action = UPDATE;
break;
case "removeIcon":
stackId = ((String) arguments[0]);
action = UPDATE;
break;
case "removeStack":
stackId = ((String) arguments[0]);
action = DELETE;
break;
case "createStack":
case "searchStacks":
// available for all
return;
default:
throw new ForbiddenException("The user does not have permission to perform this operation");
}
if (currentSubject.hasPermission(
SystemDomain.DOMAIN_ID, null, SystemDomain.MANAGE_SYSTEM_ACTION)
&& isStackPredefined(stackId)) {
// allow any operation with predefined stack if user has 'manageSystem' permission
return;
}
if (!currentSubject.hasPermission(DOMAIN_ID, stackId, action)) {
throw new ForbiddenException(
"The user does not have permission to " + action + " stack with id '" + stackId + "'");
}
}
/**
* Determines whether stack is predefined. Note, that 'predefined' means public for all users (not
* necessary provided with system from the box).
*
* @param stackId id of stack to test
* @return true if stack is predefined, false otherwise
* @throws ServerException when any error occurs during permissions fetching
*/
@VisibleForTesting
boolean isStackPredefined(String stackId) throws ServerException {
try {
Page<AbstractPermissions> permissionsPage =
permissionsManager.getByInstance(DOMAIN_ID, stackId, 25, 0);
do {
for (AbstractPermissions stackPermission : permissionsPage.getItems()) {
if ("*".equals(stackPermission.getUserId())) {
return true;
}
}
} while ((permissionsPage = getNextPermissionsPage(stackId, permissionsPage)) != null);
} catch (NotFoundException e) {
// should never happen
throw new ServerException(e);
}
return false;
}
/**
* Retrieves next permissions page for given stack.
*
* @param stackId id of stack to which permissions will be obtained
* @param permissionsPage previous permissions page
* @return next permissions page for given stack or null if next page doesn't exist
* @throws ServerException when any error occurs during permissions fetching
*/
@VisibleForTesting
Page<AbstractPermissions> getNextPermissionsPage(
String stackId, Page<AbstractPermissions> permissionsPage)
throws NotFoundException, ServerException {
if (!permissionsPage.hasNextPage()) {
return null;
}
final Page.PageRef nextPageRef = permissionsPage.getNextPageRef();
return permissionsManager.getByInstance(
DOMAIN_ID, stackId, nextPageRef.getPageSize(), nextPageRef.getItemsBefore());
}
}

View File

@ -15,29 +15,21 @@ import com.google.inject.AbstractModule;
import com.google.inject.TypeLiteral;
import com.google.inject.multibindings.Multibinder;
import org.eclipse.che.api.workspace.server.jpa.JpaWorkspaceDao.RemoveWorkspaceBeforeAccountRemovedEventSubscriber;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.spi.WorkspaceDao;
import org.eclipse.che.multiuser.api.permission.server.AbstractPermissionsDomain;
import org.eclipse.che.multiuser.api.permission.server.jpa.listener.RemovePermissionsOnLastUserRemovedEventSubscriber;
import org.eclipse.che.multiuser.api.permission.server.model.impl.AbstractPermissions;
import org.eclipse.che.multiuser.api.permission.server.spi.PermissionsDao;
import org.eclipse.che.multiuser.permission.workspace.server.WorkspaceDomain;
import org.eclipse.che.multiuser.permission.workspace.server.jpa.listener.RemoveStackOnLastUserRemovedEventSubscriber;
import org.eclipse.che.multiuser.permission.workspace.server.model.impl.WorkerImpl;
import org.eclipse.che.multiuser.permission.workspace.server.spi.WorkerDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaStackPermissionsDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaWorkerDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.MultiuserJpaStackDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.MultiuserJpaWorkspaceDao;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
/** @author Yevhenii Voevodin */
public class MultiuserWorkspaceJpaModule extends AbstractModule {
@Override
protected void configure() {
bind(StackDao.class).to(MultiuserJpaStackDao.class);
bind(WorkerDao.class).to(JpaWorkerDao.class);
bind(WorkspaceDao.class).to(MultiuserJpaWorkspaceDao.class);
bind(RemoveWorkspaceBeforeAccountRemovedEventSubscriber.class).asEagerSingleton();
@ -45,20 +37,11 @@ public class MultiuserWorkspaceJpaModule extends AbstractModule {
bind(JpaWorkerDao.RemoveWorkersBeforeWorkspaceRemovedEventSubscriber.class).asEagerSingleton();
bind(JpaWorkerDao.RemoveWorkersBeforeUserRemovedEventSubscriber.class).asEagerSingleton();
bind(new TypeLiteral<
RemovePermissionsOnLastUserRemovedEventSubscriber<JpaStackPermissionsDao>>() {})
.to(RemoveStackOnLastUserRemovedEventSubscriber.class);
bind(JpaStackPermissionsDao.RemovePermissionsBeforeStackRemovedEventSubscriber.class)
.asEagerSingleton();
bind(new TypeLiteral<AbstractPermissionsDomain<StackPermissionsImpl>>() {})
.to(StackDomain.class);
bind(new TypeLiteral<AbstractPermissionsDomain<WorkerImpl>>() {}).to(WorkspaceDomain.class);
Multibinder<PermissionsDao<? extends AbstractPermissions>> daos =
Multibinder.newSetBinder(
binder(), new TypeLiteral<PermissionsDao<? extends AbstractPermissions>>() {});
daos.addBinding().to(JpaWorkerDao.class);
daos.addBinding().to(JpaStackPermissionsDao.class);
}
}

View File

@ -1,38 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.jpa.listener;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.api.workspace.server.jpa.JpaStackDao;
import org.eclipse.che.multiuser.api.permission.server.jpa.listener.RemovePermissionsOnLastUserRemovedEventSubscriber;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaStackPermissionsDao;
/**
* Listens for {@link UserImpl} removal events, and checks if the removing user is the last who have
* "setPermissions" role to particular stack, and if it is, then removes stack itself.
*
* @author Max Shaposhnik
*/
@Singleton
public class RemoveStackOnLastUserRemovedEventSubscriber
extends RemovePermissionsOnLastUserRemovedEventSubscriber<JpaStackPermissionsDao> {
@Inject private JpaStackDao stackDao;
@Override
public void remove(String instanceId) throws ServerException {
stackDao.remove(instanceId);
}
}

View File

@ -1,186 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.spi.jpa;
import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.persist.Transactional;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.Page;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.workspace.server.event.BeforeStackRemovedEvent;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.core.db.cascade.CascadeEventSubscriber;
import org.eclipse.che.multiuser.api.permission.server.AbstractPermissionsDomain;
import org.eclipse.che.multiuser.api.permission.server.jpa.AbstractJpaPermissionsDao;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
/**
* JPA based implementation of stack permissions DAO.
*
* @author Max Shaposhnik
*/
@Singleton
public class JpaStackPermissionsDao extends AbstractJpaPermissionsDao<StackPermissionsImpl> {
@Inject
public JpaStackPermissionsDao(AbstractPermissionsDomain<StackPermissionsImpl> domain) {
super(domain);
}
@Override
public StackPermissionsImpl get(String userId, String instanceId)
throws ServerException, NotFoundException {
requireNonNull(instanceId, "Stack identifier required");
requireNonNull(userId, "User identifier required");
try {
return new StackPermissionsImpl(getEntity(wildcardToNull(userId), instanceId));
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Override
public List<StackPermissionsImpl> getByUser(String userId) throws ServerException {
requireNonNull(userId, "User identifier required");
return doGetByUser(wildcardToNull(userId))
.stream()
.map(StackPermissionsImpl::new)
.collect(toList());
}
@Override
@Transactional
public Page<StackPermissionsImpl> getByInstance(String instanceId, int maxItems, long skipCount)
throws ServerException {
requireNonNull(instanceId, "Stack identifier required");
checkArgument(
skipCount <= Integer.MAX_VALUE,
"The number of items to skip can't be greater than " + Integer.MAX_VALUE);
try {
final EntityManager entityManager = managerProvider.get();
final List<StackPermissionsImpl> stacks =
entityManager
.createNamedQuery("StackPermissions.getByStackId", StackPermissionsImpl.class)
.setFirstResult((int) skipCount)
.setMaxResults(maxItems)
.setParameter("stackId", instanceId)
.getResultList()
.stream()
.map(StackPermissionsImpl::new)
.collect(toList());
final Long permissionsCount =
entityManager
.createNamedQuery("StackPermissions.getCountByStackId", Long.class)
.setParameter("stackId", instanceId)
.getSingleResult();
return new Page<>(stacks, skipCount, maxItems, permissionsCount);
} catch (RuntimeException e) {
throw new ServerException(e.getLocalizedMessage(), e);
}
}
@Override
protected StackPermissionsImpl getEntity(String userId, String instanceId)
throws NotFoundException, ServerException {
try {
return doGet(userId, instanceId);
} catch (NoResultException e) {
throw new NotFoundException(
format("Permissions on stack '%s' of user '%s' was not found.", instanceId, userId));
} catch (RuntimeException e) {
throw new ServerException(e.getMessage(), e);
}
}
@Transactional
protected StackPermissionsImpl doGet(String userId, String instanceId) {
if (userId == null) {
return managerProvider
.get()
.createNamedQuery("StackPermissions.getByStackIdPublic", StackPermissionsImpl.class)
.setParameter("stackId", instanceId)
.getSingleResult();
} else {
return managerProvider
.get()
.createNamedQuery("StackPermissions.getByUserAndStackId", StackPermissionsImpl.class)
.setParameter("stackId", instanceId)
.setParameter("userId", userId)
.getSingleResult();
}
}
@Transactional
protected List<StackPermissionsImpl> doGetByUser(@Nullable String userId) throws ServerException {
try {
return managerProvider
.get()
.createNamedQuery("StackPermissions.getByUserId", StackPermissionsImpl.class)
.setParameter("userId", userId)
.getResultList();
} catch (RuntimeException e) {
throw new ServerException(e.getLocalizedMessage(), e);
}
}
@Singleton
public static class RemovePermissionsBeforeStackRemovedEventSubscriber
extends CascadeEventSubscriber<BeforeStackRemovedEvent> {
private static final int PAGE_SIZE = 100;
@Inject private EventService eventService;
@Inject private JpaStackPermissionsDao dao;
@PostConstruct
public void subscribe() {
eventService.subscribe(this, BeforeStackRemovedEvent.class);
}
@PreDestroy
public void unsubscribe() {
eventService.unsubscribe(this, BeforeStackRemovedEvent.class);
}
@Override
public void onCascadeEvent(BeforeStackRemovedEvent event) throws Exception {
removeStackPermissions(event.getStack().getId(), PAGE_SIZE);
}
@VisibleForTesting
void removeStackPermissions(String stackId, int pageSize)
throws ServerException, NotFoundException {
Page<StackPermissionsImpl> stacksPage;
do {
// skip count always equals to 0 because elements will be shifted after removing previous
// items
stacksPage = dao.getByInstance(stackId, pageSize, 0);
for (StackPermissionsImpl stackPermissions : stacksPage.getItems()) {
dao.remove(stackPermissions.getUserId(), stackPermissions.getInstanceId());
}
} while (stacksPage.hasNextPage());
}
}
}

View File

@ -1,182 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.spi.jpa;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import com.google.inject.persist.Transactional;
import java.util.List;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import org.eclipse.che.api.core.ApiException;
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.notification.EventService;
import org.eclipse.che.api.workspace.server.event.BeforeStackRemovedEvent;
import org.eclipse.che.api.workspace.server.event.StackPersistedEvent;
import org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.core.db.jpa.DuplicateKeyException;
/**
* JPA based implementation of {@link StackDao}.
*
* @author Yevhenii Voevodin
*/
@Singleton
public class MultiuserJpaStackDao implements StackDao {
@Inject private Provider<EntityManager> managerProvider;
@Inject private EventService eventService;
private static final String findByPermissionsQuery =
" SELECT stack FROM StackPermissions perm "
+ " LEFT JOIN perm.stack stack "
+ " WHERE (perm.userId IS NULL OR perm.userId = :userId) "
+ " AND 'search' MEMBER OF perm.actions"
+ " GROUP BY stack.id";
private static final String findByPermissionsAndTagsQuery =
" SELECT stack FROM StackPermissions perm "
+ " LEFT JOIN perm.stack stack "
+ " LEFT JOIN stack.tags tag "
+ " WHERE (perm.userId IS NULL OR perm.userId = :userId) "
+ " AND 'search' MEMBER OF perm.actions"
+ " AND tag IN :tags "
+ " GROUP BY stack.id HAVING COUNT(tag) = :tagsSize";
@Override
public void create(StackImpl stack) throws ConflictException, ServerException {
requireNonNull(stack, "Required non-null stack");
try {
doCreate(stack);
} catch (DuplicateKeyException x) {
throw new ConflictException(
format("Stack with id '%s' or name '%s' already exists", stack.getId(), stack.getName()));
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Override
@Transactional
public StackImpl getById(String id) throws NotFoundException, ServerException {
requireNonNull(id, "Required non-null id");
try {
final StackImpl stack = managerProvider.get().find(StackImpl.class, id);
if (stack == null) {
throw new NotFoundException(format("Stack with id '%s' doesn't exist", id));
}
return new StackImpl(stack);
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Override
public void remove(String id) throws ServerException {
requireNonNull(id, "Required non-null id");
try {
doRemove(id);
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Override
public StackImpl update(StackImpl update)
throws NotFoundException, ServerException, ConflictException {
requireNonNull(update, "Required non-null update");
try {
return new StackImpl(doUpdate(update));
} catch (DuplicateKeyException x) {
throw new ConflictException(format("Stack with name '%s' already exists", update.getName()));
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Override
@Transactional
public List<StackImpl> searchStacks(
@Nullable String userId, @Nullable List<String> tags, int skipCount, int maxItems)
throws ServerException {
final TypedQuery<StackImpl> query;
if (tags == null || tags.isEmpty()) {
query = managerProvider.get().createQuery(findByPermissionsQuery, StackImpl.class);
} else {
query =
managerProvider
.get()
.createQuery(findByPermissionsAndTagsQuery, StackImpl.class)
.setParameter("tags", tags)
.setParameter("tagsSize", tags.size());
}
try {
return query
.setParameter("userId", userId)
.setMaxResults(maxItems)
.setFirstResult(skipCount)
.getResultList()
.stream()
.map(StackImpl::new)
.collect(Collectors.toList());
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Transactional(rollbackOn = {RuntimeException.class, ApiException.class})
protected void doCreate(StackImpl stack) throws ConflictException, ServerException {
if (stack.getWorkspaceConfig() != null) {
stack.getWorkspaceConfig().getProjects().forEach(ProjectConfigImpl::prePersistAttributes);
}
EntityManager manager = managerProvider.get();
manager.persist(stack);
manager.flush();
eventService.publish(new StackPersistedEvent(stack)).propagateException();
}
@Transactional(rollbackOn = {RuntimeException.class, ServerException.class})
protected void doRemove(String id) throws ServerException {
final EntityManager manager = managerProvider.get();
final StackImpl stack = manager.find(StackImpl.class, id);
if (stack != null) {
eventService.publish(new BeforeStackRemovedEvent(new StackImpl(stack))).propagateException();
manager.remove(stack);
manager.flush();
}
}
@Transactional
protected StackImpl doUpdate(StackImpl update) throws NotFoundException {
final EntityManager manager = managerProvider.get();
if (manager.find(StackImpl.class, update.getId()) == null) {
throw new NotFoundException(format("Workspace with id '%s' doesn't exist", update.getId()));
}
if (update.getWorkspaceConfig() != null) {
update.getWorkspaceConfig().getProjects().forEach(ProjectConfigImpl::prePersistAttributes);
}
StackImpl merged = manager.merge(update);
manager.flush();
return merged;
}
}

View File

@ -1,78 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.stack;
import static java.lang.String.format;
import static java.util.Collections.singletonList;
import java.nio.file.Path;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
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.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.stack.StackLoader;
import org.eclipse.che.api.workspace.server.stack.image.StackIcon;
import org.eclipse.che.api.workspace.shared.stack.Stack;
import org.eclipse.che.core.db.DBInitializer;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaStackPermissionsDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class for loading list predefined {@link Stack} to the {@link StackDao} and set {@link StackIcon}
* to the predefined stack.
*
* @author Alexander Andrienko
* @author Sergii Leshchenko
* @author Anton Korneta
*/
@Singleton
public class MultiuserStackLoader extends StackLoader {
public static final String CHE_PREDEFINED_STACKS = "che.predefined.stacks";
private static final Logger LOG = LoggerFactory.getLogger(MultiuserStackLoader.class);
private final JpaStackPermissionsDao permissionsDao;
@Inject
@SuppressWarnings("unused")
public MultiuserStackLoader(
@Named("che.predefined.stacks.reload_on_start") boolean reloadStacksOnStart,
@Named(CHE_PREDEFINED_STACKS) Map<String, String> stacks2images,
StackDao stackDao,
JpaStackPermissionsDao permissionsDao,
DBInitializer dbInitializer) {
super(reloadStacksOnStart, stacks2images, stackDao, dbInitializer);
this.permissionsDao = permissionsDao;
}
protected void loadStack(StackImpl stack, Path imagePath) {
setIconData(stack, imagePath);
try {
try {
stackDao.update(stack);
} catch (NotFoundException ignored) {
stackDao.create(stack);
}
permissionsDao.store(
new StackPermissionsImpl("*", stack.getId(), singletonList(StackDomain.SEARCH)));
} catch (ServerException | ConflictException ex) {
LOG.warn(format("Failed to load stack with id '%s' ", stack.getId()), ex.getMessage());
}
}
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.stack;
import com.google.inject.Inject;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Singleton;
import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.workspace.server.event.StackPersistedEvent;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
import org.eclipse.che.core.db.cascade.CascadeEventSubscriber;
import org.eclipse.che.multiuser.api.permission.server.PermissionsManager;
/**
* Grants access to stack which is created by user who is {@link EnvironmentContext#getSubject()
* subject}, if there is no subject present in {@link EnvironmentContext#getCurrent() current}
* context then no permissions will be added.
*
* @author Yevhenii Voevodin
*/
@Singleton
public class StackCreatorPermissionsProvider extends CascadeEventSubscriber<StackPersistedEvent> {
@Inject private PermissionsManager permissionsManager;
@Inject private EventService eventService;
@Override
public void onCascadeEvent(StackPersistedEvent event) throws Exception {
final Subject subject = EnvironmentContext.getCurrent().getSubject();
if (!subject.isAnonymous()) {
permissionsManager.storePermission(
new StackPermissionsImpl(
subject.getUserId(), event.getStack().getId(), StackDomain.getActions()));
}
}
@PostConstruct
public void subscribe() {
eventService.subscribe(this, StackPersistedEvent.class);
}
@PreDestroy
public void unsubscribe() {
eventService.unsubscribe(this, StackPersistedEvent.class);
}
}

View File

@ -1,49 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.stack;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.eclipse.che.multiuser.api.permission.server.AbstractPermissionsDomain;
/**
* Domain for storing stacks' permissions
*
* @author Sergii Leschenko
* @author Yevhenii Voevodin
*/
public class StackDomain extends AbstractPermissionsDomain<StackPermissionsImpl> {
public static final String DOMAIN_ID = "stack";
public static final String READ = "read";
public static final String SEARCH = "search";
public static final String UPDATE = "update";
public static final String DELETE = "delete";
private static final List<String> ACTIONS =
ImmutableList.of(SET_PERMISSIONS, READ, SEARCH, UPDATE, DELETE);
/** Returns all the available actions for {@link StackDomain}. */
public static List<String> getActions() {
return ACTIONS;
}
public StackDomain() {
super(DOMAIN_ID, ACTIONS);
}
@Override
public StackPermissionsImpl doCreateInstance(
String userId, String instanceId, List<String> allowedActions) {
return new StackPermissionsImpl(userId, instanceId, allowedActions);
}
}

View File

@ -1,123 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.stack;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.multiuser.api.permission.server.model.impl.AbstractPermissions;
import org.eclipse.che.multiuser.api.permission.shared.model.Permissions;
/**
* Stack permissions data object.
*
* @author Max Shaposhnik
*/
@Entity(name = "StackPermissions")
@NamedQueries({
@NamedQuery(
name = "StackPermissions.getByStackId",
query = "SELECT stack " + "FROM StackPermissions stack " + "WHERE stack.stackId = :stackId "),
@NamedQuery(
name = "StackPermissions.getCountByStackId",
query =
"SELECT COUNT(stack) "
+ "FROM StackPermissions stack "
+ "WHERE stack.stackId = :stackId "),
@NamedQuery(
name = "StackPermissions.getByUserId",
query = "SELECT stack " + "FROM StackPermissions stack " + "WHERE stack.userId = :userId "),
@NamedQuery(
name = "StackPermissions.getByUserAndStackId",
query =
"SELECT stack "
+ "FROM StackPermissions stack "
+ "WHERE stack.stackId = :stackId "
+ "AND stack.userId = :userId "),
@NamedQuery(
name = "StackPermissions.getByStackIdPublic",
query =
"SELECT stack "
+ "FROM StackPermissions stack "
+ "WHERE stack.stackId = :stackId "
+ "AND stack.userId IS NULL ")
})
@Table(name = "che_stack_permissions")
public class StackPermissionsImpl extends AbstractPermissions {
@Column(name = "stack_id")
private String stackId;
@ManyToOne
@JoinColumn(name = "stack_id", insertable = false, updatable = false)
private StackImpl stack;
@ElementCollection(fetch = FetchType.EAGER)
@Column(name = "actions")
@CollectionTable(
name = "che_stack_permissions_actions",
joinColumns = @JoinColumn(name = "stack_permissions_id"))
protected List<String> actions;
public StackPermissionsImpl() {}
public StackPermissionsImpl(Permissions permissions) {
this(permissions.getUserId(), permissions.getInstanceId(), permissions.getActions());
}
public StackPermissionsImpl(String userId, String instanceId, List<String> allowedActions) {
super(userId);
this.stackId = instanceId;
if (allowedActions != null) {
this.actions = new ArrayList<>(allowedActions);
}
}
@Override
public String getInstanceId() {
return stackId;
}
@Override
public String getDomainId() {
return StackDomain.DOMAIN_ID;
}
@Override
public List<String> getActions() {
return actions;
}
@Override
public String toString() {
return "StackPermissionsImpl{"
+ "userId='"
+ getUserId()
+ '\''
+ ", stackId='"
+ stackId
+ '\''
+ ", actions="
+ actions
+ '}';
}
}

View File

@ -1,116 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.filters;
import static java.util.Collections.singletonList;
import static org.eclipse.che.multiuser.api.permission.server.SystemDomain.MANAGE_SYSTEM_ACTION;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
import org.eclipse.che.multiuser.api.permission.server.PermissionsManager;
import org.eclipse.che.multiuser.api.permission.server.SystemDomain;
import org.eclipse.che.multiuser.api.permission.server.filter.check.DefaultRemovePermissionsChecker;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* Tests {@link PublicPermissionsRemoveChecker}.
*
* @author Anton Korneta
*/
@Listeners(MockitoTestNGListener.class)
public class PublicPermissionsRemoveCheckerTest {
private static final String USER = "user123";
private static final String INSTANCE = "instance123";
@Mock private Subject subj;
@Mock private PermissionsManager manager;
@Mock private DefaultRemovePermissionsChecker defaultChecker;
private PublicPermissionsRemoveChecker publicPermissionsRemoveChecker;
@BeforeMethod
public void setup() throws Exception {
publicPermissionsRemoveChecker = new PublicPermissionsRemoveChecker(defaultChecker, manager);
final EnvironmentContext ctx = new EnvironmentContext();
ctx.setSubject(subj);
EnvironmentContext.setCurrent(ctx);
}
@AfterMethod
public void tearDown() throws Exception {
EnvironmentContext.reset();
}
@Test
public void permitsRemoveNonPublicPermissionsWhenDefaultCheckPassed() throws Exception {
doNothing().when(defaultChecker).check(USER, StackDomain.DOMAIN_ID, INSTANCE);
publicPermissionsRemoveChecker.check(USER, StackDomain.DOMAIN_ID, INSTANCE);
verify(defaultChecker, times(1)).check(USER, StackDomain.DOMAIN_ID, INSTANCE);
verify(manager, never()).get(USER, StackDomain.DOMAIN_ID, INSTANCE);
}
@Test(expectedExceptions = ForbiddenException.class)
public void throwsForbiddenExceptionWhenRemoveNonPublicPermissionsAndDefaultCheckFailed()
throws Exception {
doThrow(ForbiddenException.class)
.when(defaultChecker)
.check(USER, StackDomain.DOMAIN_ID, INSTANCE);
publicPermissionsRemoveChecker.check(USER, StackDomain.DOMAIN_ID, INSTANCE);
verify(defaultChecker, times(1)).check(USER, StackDomain.DOMAIN_ID, INSTANCE);
verify(manager, never()).get(USER, StackDomain.DOMAIN_ID, INSTANCE);
}
@Test(expectedExceptions = ForbiddenException.class)
public void throwsForbiddenExceptionWhenFailedToGetActionRemovingPermissionByAdmin()
throws Exception {
doThrow(ServerException.class).when(manager).get("*", StackDomain.DOMAIN_ID, INSTANCE);
doThrow(ForbiddenException.class)
.when(defaultChecker)
.check("*", StackDomain.DOMAIN_ID, INSTANCE);
when(subj.hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION)).thenReturn(true);
publicPermissionsRemoveChecker.check("*", StackDomain.DOMAIN_ID, INSTANCE);
}
@Test
public void permitsRemoveStackPermissionsWhenAdminUserPassedDefaultCheck() throws Exception {
when(manager.get("*", StackDomain.DOMAIN_ID, INSTANCE))
.thenReturn(new StackPermissionsImpl("*", INSTANCE, singletonList(StackDomain.SEARCH)));
when(subj.hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION)).thenReturn(true);
publicPermissionsRemoveChecker.check("*", StackDomain.DOMAIN_ID, INSTANCE);
verify(manager, times(1)).get("*", StackDomain.DOMAIN_ID, INSTANCE);
verify(subj, times(1)).hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION);
verify(defaultChecker, never()).check("*", StackDomain.DOMAIN_ID, INSTANCE);
}
}

View File

@ -1,172 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.filters;
import static java.util.Collections.singletonList;
import static org.eclipse.che.multiuser.api.permission.server.SystemDomain.MANAGE_SYSTEM_ACTION;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.DELETE;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.READ;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.SEARCH;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableList;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
import org.eclipse.che.multiuser.api.permission.server.SystemDomain;
import org.eclipse.che.multiuser.api.permission.server.filter.check.DefaultSetPermissionsChecker;
import org.eclipse.che.multiuser.api.permission.shared.model.Permissions;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* Tests {@link StackDomainSetPermissionsChecker}.
*
* @author Anton Korneta
*/
@Listeners(MockitoTestNGListener.class)
public class StackDomainSetPermissionsCheckerTest {
@Mock private Subject subj;
@Mock private DefaultSetPermissionsChecker defaultChecker;
private StackDomainSetPermissionsChecker stackSetPermChecker;
@BeforeMethod
public void setup() throws Exception {
stackSetPermChecker = new StackDomainSetPermissionsChecker(defaultChecker);
final EnvironmentContext ctx = new EnvironmentContext();
ctx.setSubject(subj);
EnvironmentContext.setCurrent(ctx);
}
@AfterMethod
public void tearDown() throws Exception {
EnvironmentContext.reset();
}
@Test
public void permitsToSetNonPublicPermissionsWhenDefaultCheckPassed() throws Exception {
final Permissions permissions =
new StackPermissionsImpl("user73", "stack73", singletonList(DELETE));
doNothing().when(defaultChecker).check(permissions);
stackSetPermChecker.check(permissions);
verify(defaultChecker).check(permissions);
}
@Test(expectedExceptions = ForbiddenException.class)
public void throwsForbiddenExceptionOnSetNonPublicPermissionsWhenDefaultCheckFailed()
throws Exception {
final Permissions permissions =
new StackPermissionsImpl("user73", "stack73", singletonList(DELETE));
doThrow(ForbiddenException.class).when(defaultChecker).check(permissions);
stackSetPermChecker.check(permissions);
}
@Test
public void permitsToSetPublicPermissionsWithSearchActionForAdmin() throws Exception {
final Permissions permissions = new StackPermissionsImpl("*", "stack73", singletonList(SEARCH));
when(subj.hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION)).thenReturn(true);
stackSetPermChecker.check(permissions);
verify(subj).hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION);
verify(defaultChecker, never()).check(permissions);
}
@Test(
expectedExceptions = ForbiddenException.class,
expectedExceptionsMessageRegExp =
"Following actions are not supported for setting as public:.*")
public void throwsForbiddenExceptionWhenSetPublicPermissionsWithUnsupportedActionByAdmin()
throws Exception {
final Permissions permissions =
new StackPermissionsImpl("*", "stack73", ImmutableList.of(SEARCH, DELETE));
when(subj.hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION)).thenReturn(true);
stackSetPermChecker.check(permissions);
verify(subj).hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION);
verify(defaultChecker, never()).check(permissions);
}
@Test
public void permitsToSetPublicPermissionsWithReadActionForNonAdminUser() throws Exception {
final Permissions permissions = new StackPermissionsImpl("*", "stack73", singletonList(READ));
when(subj.hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION)).thenReturn(false);
doNothing().when(defaultChecker).check(permissions);
stackSetPermChecker.check(permissions);
verify(subj).hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION);
verify(defaultChecker).check(permissions);
}
@Test(
expectedExceptions = ForbiddenException.class,
expectedExceptionsMessageRegExp =
"Following actions are not supported for setting as public:.*")
public void throwsForbiddenExceptionWhenSetPublicPermissionsWithUnsupportedActionByNonAdminUser()
throws Exception {
final Permissions permissions = new StackPermissionsImpl("*", "stack73", singletonList(DELETE));
when(subj.hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION)).thenReturn(false);
doNothing().when(defaultChecker).check(permissions);
stackSetPermChecker.check(permissions);
verify(subj).hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION);
verify(defaultChecker).check(permissions);
}
@Test(expectedExceptions = ForbiddenException.class)
public void throwsForbiddenExceptionWhenSetPublicPermissionsByNonAdminUserFailedOnDefaultCheck()
throws Exception {
final Permissions permissions = new StackPermissionsImpl("*", "stack73", singletonList(READ));
when(subj.hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION)).thenReturn(false);
doThrow(ForbiddenException.class).when(defaultChecker).check(permissions);
stackSetPermChecker.check(permissions);
verify(subj).hasPermission(SystemDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION);
verify(defaultChecker).check(permissions);
}
@Test(expectedExceptions = ForbiddenException.class)
public void throwsExceptionWhenChecksAdminPermissionsWithWrongDomainOnSetPermission()
throws Exception {
final Permissions permissions = new StackPermissionsImpl("*", "stack73", singletonList(SEARCH));
lenient()
.when(subj.hasPermission(StackDomain.DOMAIN_ID, null, MANAGE_SYSTEM_ACTION))
.thenReturn(false);
stackSetPermChecker.check(permissions);
verify(subj).hasPermission(any(), any(), MANAGE_SYSTEM_ACTION);
verify(defaultChecker).check(permissions);
}
}

View File

@ -1,454 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.filters;
import static com.jayway.restassured.RestAssured.given;
import static java.util.Arrays.asList;
import static org.eclipse.che.multiuser.api.permission.server.SystemDomain.MANAGE_SYSTEM_ACTION;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.DELETE;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.DOMAIN_ID;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.READ;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.SEARCH;
import static org.eclipse.che.multiuser.permission.workspace.server.stack.StackDomain.UPDATE;
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.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import com.jayway.restassured.response.Response;
import com.jayway.restassured.specification.RequestSpecification;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.Page;
import org.eclipse.che.api.core.rest.ApiExceptionMapper;
import org.eclipse.che.api.core.rest.shared.dto.ServiceError;
import org.eclipse.che.api.workspace.server.WorkspaceService;
import org.eclipse.che.api.workspace.server.stack.StackService;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
import org.eclipse.che.dto.server.DtoFactory;
import org.eclipse.che.multiuser.api.permission.server.PermissionsManager;
import org.eclipse.che.multiuser.api.permission.server.SystemDomain;
import org.eclipse.che.multiuser.api.permission.server.model.impl.AbstractPermissions;
import org.everrest.assured.EverrestJetty;
import org.everrest.core.Filter;
import org.everrest.core.GenericContainerRequest;
import org.everrest.core.RequestFilter;
import org.everrest.core.resource.GenericResourceMethod;
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;
/**
* Tests for {@link StackPermissionsFilter}
*
* @author Sergii Leschenko
* @author Mykola Morhun
*/
@Listeners(value = {EverrestJetty.class, MockitoTestNGListener.class})
public class StackPermissionsFilterTest {
@SuppressWarnings("unused")
private static final ApiExceptionMapper MAPPER = new ApiExceptionMapper();
@SuppressWarnings("unused")
private static final EnvironmentFilter FILTER = new EnvironmentFilter();
@SuppressWarnings("unused")
@InjectMocks
StackPermissionsFilter permissionsFilter;
@Mock private static Subject subject;
@Mock private StackService service;
@Mock private PermissionsManager permissionsManager;
@BeforeMethod
public void beforeMethod() throws Exception {
permissionsFilter = spy(new StackPermissionsFilter(permissionsManager));
lenient().doReturn(false).when(subject).hasPermission("stack", "stack123", SEARCH);
lenient().doReturn(false).when(subject).hasPermission("system", null, MANAGE_SYSTEM_ACTION);
}
@Test
public void shouldNotCheckPermissionsOnStackCreating() throws Exception {
final Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType("application/json")
.when()
.post(SECURE_PATH + "/stack");
assertEquals(response.getStatusCode(), 204);
verify(service).createStack(any());
verifyZeroInteractions(subject);
}
@Test
public void shouldCheckPermissionsOnStackReading() throws Exception {
when(subject.hasPermission("stack", "stack123", READ)).thenReturn(true);
final Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType("application/json")
.when()
.get(SECURE_PATH + "/stack/stack123");
assertEquals(response.getStatusCode(), 204);
verify(service).getStack("stack123");
verify(subject).hasPermission(eq("stack"), eq("stack123"), eq(READ));
}
@Test
public void shouldCheckPermissionsOnStackUpdating() throws Exception {
when(subject.hasPermission("stack", "stack123", UPDATE)).thenReturn(true);
final Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType("application/json")
.when()
.put(SECURE_PATH + "/stack/stack123");
assertEquals(response.getStatusCode(), 204);
verify(service).updateStack(any(), eq("stack123"));
verify(subject).hasPermission(eq("stack"), eq("stack123"), eq(UPDATE));
}
@Test
public void shouldCheckPermissionsOnStackRemoving() throws Exception {
when(subject.hasPermission("stack", "stack123", DELETE)).thenReturn(true);
final Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType("application/json")
.when()
.delete(SECURE_PATH + "/stack/stack123");
assertEquals(response.getStatusCode(), 204);
verify(service).removeStack(eq("stack123"));
verify(subject).hasPermission(eq("stack"), eq("stack123"), eq(DELETE));
}
@Test
public void shouldNotCheckPermissionsOnStacksSearching() throws Exception {
final Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType("application/json")
.when()
.get(SECURE_PATH + "/stack");
assertEquals(response.getStatusCode(), 200);
verify(service).searchStacks(nullable(List.class), anyInt(), anyInt());
verifyZeroInteractions(subject);
}
@Test
public void shouldCheckPermissionsOnIconReading() throws Exception {
when(subject.hasPermission("stack", "stack123", READ)).thenReturn(true);
final Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType("application/json")
.when()
.get(SECURE_PATH + "/stack/stack123/icon");
assertEquals(response.getStatusCode(), 204);
verify(service).getIcon(eq("stack123"));
verify(subject).hasPermission(eq("stack"), eq("stack123"), eq(READ));
}
@Test
public void shouldCheckPermissionsOnIconUploading() throws Exception {
when(subject.hasPermission("stack", "stack123", UPDATE)).thenReturn(true);
final Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType("multipart/form-data")
.multiPart("icon", "content", "image/png")
.when()
.post(SECURE_PATH + "/stack/stack123/icon");
assertEquals(response.getStatusCode(), 204);
verify(service).uploadIcon(any(), eq("stack123"));
verify(subject).hasPermission(eq("stack"), eq("stack123"), eq(UPDATE));
}
@Test
public void shouldThrowForbiddenExceptionWhenUserDoesNotHavePermissionsForIconUpdating() {
when(subject.hasPermission("stack", "stack123", UPDATE)).thenReturn(false);
final Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType("multipart/form-data")
.multiPart("icon", "content", "image/png")
.when()
.post(SECURE_PATH + "/stack/stack123/icon");
assertEquals(response.getStatusCode(), 403);
Assert.assertEquals(
unwrapError(response),
"The user does not have permission to " + UPDATE + " stack with id 'stack123'");
verifyZeroInteractions(service);
}
@Test
public void shouldCheckPermissionsOnIconRemoving() throws Exception {
when(subject.hasPermission("stack", "stack123", UPDATE)).thenReturn(true);
final Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType("multipart/form-data")
.when()
.delete(SECURE_PATH + "/stack/stack123/icon");
assertEquals(response.getStatusCode(), 204);
verify(service).removeIcon(eq("stack123"));
verify(subject).hasPermission(eq("stack"), eq("stack123"), eq(UPDATE));
}
@Test(
expectedExceptions = ForbiddenException.class,
expectedExceptionsMessageRegExp =
"The user does not have permission to perform this operation")
public void shouldThrowForbiddenExceptionWhenRequestedUnknownMethod() throws Exception {
final GenericResourceMethod mock = mock(GenericResourceMethod.class);
Method injectLinks = WorkspaceService.class.getMethod("getServiceDescriptor");
when(mock.getMethod()).thenReturn(injectLinks);
permissionsFilter.filter(mock, new Object[] {});
}
@Test(dataProvider = "coveredPaths")
public void shouldThrowForbiddenExceptionWhenUserDoesNotHavePermissionsForPerformOperation(
String path, String method, String action) throws Exception {
when(subject.hasPermission(
nullable(String.class), nullable(String.class), nullable(String.class)))
.thenReturn(false);
Response response =
request(
given().auth().basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD).when(),
SECURE_PATH + path,
method);
assertEquals(response.getStatusCode(), 403);
assertEquals(
unwrapError(response),
"The user does not have permission to " + action + " stack with id 'stack123'");
verifyZeroInteractions(service);
}
@Test(dataProvider = "coveredPaths")
public void shouldAllowToAdminPerformAnyActionWithPredefinedStack(
String path, String method, String action) throws Exception {
doReturn(false)
.when(subject)
.hasPermission(eq(DOMAIN_ID), nullable(String.class), nullable(String.class));
doReturn(true)
.when(subject)
.hasPermission(eq(SystemDomain.DOMAIN_ID), nullable(String.class), nullable(String.class));
doReturn(true).when(permissionsFilter).isStackPredefined(nullable(String.class));
Response response =
request(
given().auth().basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD).when(),
SECURE_PATH + path,
method);
assertEquals(response.getStatusCode() / 100, 2);
verify(subject).hasPermission(eq(SystemDomain.DOMAIN_ID), eq(null), eq(MANAGE_SYSTEM_ACTION));
}
@Test(dataProvider = "coveredPaths")
public void shouldNotAllowToAdminPerformAnyActionWithNonPredefinedStack(
String path, String method, String action) throws Exception {
doReturn(false)
.when(subject)
.hasPermission(eq(DOMAIN_ID), nullable(String.class), nullable(String.class));
doReturn(true)
.when(subject)
.hasPermission(eq(SystemDomain.DOMAIN_ID), nullable(String.class), nullable(String.class));
doReturn(false).when(permissionsFilter).isStackPredefined(nullable(String.class));
Response response =
request(
given().auth().basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD).when(),
SECURE_PATH + path,
method);
assertEquals(response.getStatusCode(), 403);
verify(subject).hasPermission(eq(SystemDomain.DOMAIN_ID), eq(null), eq(MANAGE_SYSTEM_ACTION));
}
@DataProvider(name = "coveredPaths")
public Object[][] pathsProvider() {
return new Object[][] {
{"/stack/stack123", "get", READ},
{"/stack/stack123", "put", UPDATE},
{"/stack/stack123", "delete", DELETE},
{"/stack/stack123/icon", "get", READ},
{"/stack/stack123/icon", "delete", UPDATE}
};
}
@Test
public void shouldRecognizePredefinedStack() throws Exception {
final AbstractPermissions stackPermission = mock(AbstractPermissions.class);
when(stackPermission.getUserId()).thenReturn("*");
final Page<AbstractPermissions> permissionsPage = mock(Page.class);
when(permissionsPage.getItems()).thenReturn(Collections.singletonList(stackPermission));
when(permissionsManager.getByInstance(
nullable(String.class), nullable(String.class), anyInt(), anyLong()))
.thenReturn(permissionsPage);
assertTrue(permissionsFilter.isStackPredefined("stack123"));
}
@Test
public void shouldRecognizeNonPredefinedStack() throws Exception {
final AbstractPermissions stackPermission = mock(AbstractPermissions.class);
when(stackPermission.getUserId()).thenReturn("userId");
final Page<AbstractPermissions> permissionsPage = mock(Page.class);
when(permissionsPage.getItems()).thenReturn(Collections.singletonList(stackPermission));
when(permissionsManager.getByInstance(
nullable(String.class), nullable(String.class), anyInt(), anyLong()))
.thenReturn(permissionsPage);
assertFalse(permissionsFilter.isStackPredefined("stack123"));
}
@Test
public void shouldRecognizePredefinedStackWhenAFewPermissionsPagesIsRetrieved() throws Exception {
final String stackId = "stack123";
final AbstractPermissions privateStackPermission = mock(AbstractPermissions.class);
when(privateStackPermission.getUserId()).thenReturn("userId");
final AbstractPermissions publicStackPermission = mock(AbstractPermissions.class);
when(publicStackPermission.getUserId()).thenReturn("*");
final Page<AbstractPermissions> permissionsPage1 = mock(Page.class);
when(permissionsPage1.getItems())
.thenReturn(asList(privateStackPermission, privateStackPermission, privateStackPermission));
when(permissionsPage1.hasNextPage()).thenReturn(true);
final Page<AbstractPermissions> permissionsPage2 = mock(Page.class);
when(permissionsPage2.getItems())
.thenReturn(asList(privateStackPermission, publicStackPermission, privateStackPermission));
when(permissionsPage2.hasNextPage()).thenReturn(false);
doReturn(permissionsPage2)
.when(permissionsFilter)
.getNextPermissionsPage(stackId, permissionsPage1);
doReturn(null).when(permissionsFilter).getNextPermissionsPage(stackId, permissionsPage2);
when(permissionsManager.getByInstance(
nullable(String.class), nullable(String.class), anyInt(), anyLong()))
.thenReturn(permissionsPage1);
assertTrue(permissionsFilter.isStackPredefined(stackId));
}
@Test
public void shouldBeAbleToRetrieveNextPermissionPage() throws Exception {
final String stackId = "stack123";
final Page<AbstractPermissions> currentPage = mock(Page.class);
when(currentPage.hasNextPage()).thenReturn(true);
when(currentPage.getNextPageRef()).thenReturn(mock(Page.PageRef.class));
final Page<AbstractPermissions> nextPage = mock(Page.class);
when(permissionsManager.getByInstance(eq(DOMAIN_ID), eq(stackId), anyInt(), anyLong()))
.thenReturn(nextPage);
assertEquals(permissionsFilter.getNextPermissionsPage(stackId, currentPage), nextPage);
}
@Test
public void shouldReturnNullIfNoNextPermissionPage() throws Exception {
final Page<AbstractPermissions> currentPage = mock(Page.class);
when(currentPage.hasNextPage()).thenReturn(false);
assertNull(permissionsFilter.getNextPermissionsPage("stack123", currentPage));
}
private Response request(RequestSpecification request, String path, String method) {
switch (method) {
case "post":
return request.post(path);
case "get":
return request.get(path);
case "delete":
return request.delete(path);
case "put":
return request.put(path);
}
throw new RuntimeException("Unsupported method");
}
private static String unwrapError(Response response) {
return unwrapDto(response, ServiceError.class).getMessage();
}
private static <T> T unwrapDto(Response response, Class<T> dtoClass) {
return DtoFactory.getInstance().createDtoFromJson(response.body().print(), dtoClass);
}
@Filter
public static class EnvironmentFilter implements RequestFilter {
public void doFilter(GenericContainerRequest request) {
EnvironmentContext.getCurrent().setSubject(subject);
}
}
}

View File

@ -1,180 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.jpa;
import static java.util.Arrays.asList;
import static org.testng.Assert.assertTrue;
import com.google.inject.Guice;
import com.google.inject.Injector;
import java.util.List;
import javax.persistence.EntityManager;
import org.eclipse.che.api.core.Page;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.api.workspace.server.event.BeforeStackRemovedEvent;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.commons.test.tck.TckResourcesCleaner;
import org.eclipse.che.multiuser.api.permission.server.AbstractPermissionsDomain;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaStackPermissionsDao;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/** @author Max Shaposhnik */
public class JpaStackPermissionsDaoTest {
private TckResourcesCleaner tckResourcesCleaner;
private EntityManager manager;
private JpaStackPermissionsDao dao;
private JpaStackPermissionsDao.RemovePermissionsBeforeStackRemovedEventSubscriber
removePermissionsSubscriber;
private StackPermissionsImpl[] permissions;
private UserImpl[] users;
private StackImpl[] stacks;
@BeforeClass
public void setupEntities() throws Exception {
permissions =
new StackPermissionsImpl[] {
new StackPermissionsImpl("user1", "stack1", asList("read", "use", "run")),
new StackPermissionsImpl("user2", "stack1", asList("read", "use")),
new StackPermissionsImpl("user1", "stack2", asList("read", "run")),
new StackPermissionsImpl("user2", "stack2", asList("read", "use", "run", "configure"))
};
users =
new UserImpl[] {
new UserImpl("user1", "user1@com.com", "usr1"),
new UserImpl("user2", "user2@com.com", "usr2")
};
stacks =
new StackImpl[] {
new StackImpl("stack1", "st1", null, null, null, null, null, null, null),
new StackImpl("stack2", "st2", null, null, null, null, null, null, null)
};
Injector injector = Guice.createInjector(new WorkspaceTckModule());
manager = injector.getInstance(EntityManager.class);
dao = injector.getInstance(JpaStackPermissionsDao.class);
removePermissionsSubscriber =
injector.getInstance(
JpaStackPermissionsDao.RemovePermissionsBeforeStackRemovedEventSubscriber.class);
tckResourcesCleaner = injector.getInstance(TckResourcesCleaner.class);
}
@BeforeMethod
public void setUp() throws Exception {
manager.getTransaction().begin();
for (UserImpl user : users) {
manager.persist(user);
}
for (StackImpl stack : stacks) {
manager.persist(stack);
}
for (StackPermissionsImpl stackPermissions : permissions) {
manager.persist(stackPermissions);
}
manager.getTransaction().commit();
manager.clear();
}
@AfterMethod
public void cleanup() {
manager.getTransaction().begin();
manager
.createQuery("SELECT p FROM StackPermissions p", StackPermissionsImpl.class)
.getResultList()
.forEach(manager::remove);
manager
.createQuery("SELECT r FROM Stack r", StackImpl.class)
.getResultList()
.forEach(manager::remove);
manager
.createQuery("SELECT u FROM Usr u", UserImpl.class)
.getResultList()
.forEach(manager::remove);
manager.getTransaction().commit();
}
@AfterClass
public void shutdown() throws Exception {
tckResourcesCleaner.clean();
}
@Test
public void shouldRemoveStackPermissionsWhenStackIsRemoved() throws Exception {
BeforeStackRemovedEvent event = new BeforeStackRemovedEvent(stacks[0]);
removePermissionsSubscriber.onEvent(event);
assertTrue(dao.getByInstance("stack1", 30, 0).isEmpty());
}
@Test
public void shouldStoreStackPublicPermission() throws Exception {
final StackPermissionsImpl publicPermission =
new StackPermissionsImpl("*", "stack1", asList("read", "use", "run"));
dao.store(publicPermission);
assertTrue(
dao.getByInstance(publicPermission.getInstanceId(), 30, 0)
.getItems()
.contains(new StackPermissionsImpl(publicPermission)));
}
@Test
public void shouldUpdateExistingStackPublicPermissions() throws Exception {
final StackPermissionsImpl publicPermission =
new StackPermissionsImpl("*", "stack1", asList("read", "use", "run"));
dao.store(publicPermission);
dao.store(publicPermission);
final Page<StackPermissionsImpl> permissions =
dao.getByInstance(publicPermission.getInstanceId(), 30, 0);
assertTrue(permissions.getItems().contains(new StackPermissionsImpl(publicPermission)));
assertTrue(permissions.getItems().stream().filter(p -> "*".equals(p.getUserId())).count() == 1);
}
@Test
public void shouldRemoveStackPublicPermission() throws Exception {
final StackPermissionsImpl publicPermission =
new StackPermissionsImpl("*", "stack1", asList("read", "use", "run"));
dao.store(publicPermission);
dao.remove(publicPermission.getUserId(), publicPermission.getInstanceId());
Page<StackPermissionsImpl> byInstance =
dao.getByInstance(publicPermission.getInstanceId(), 30, 0);
assertTrue(byInstance.getItems().stream().filter(p -> "*".equals(p.getUserId())).count() == 0);
}
public static class TestDomain extends AbstractPermissionsDomain<StackPermissionsImpl> {
public TestDomain() {
super("stack", asList("read", "write", "use", "delete"));
}
@Override
protected StackPermissionsImpl doCreateInstance(
String userId, String instanceId, List<String> allowedActions) {
return new StackPermissionsImpl(userId, instanceId, allowedActions);
}
}
}

View File

@ -1,195 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.jpa;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import com.google.inject.Guice;
import com.google.inject.Injector;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.persistence.EntityManager;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.commons.test.tck.TckResourcesCleaner;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.MultiuserJpaStackDao;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/** @author Max Shaposhnik (mshaposhnik@codenvy.com) */
public class MultiuserJpaStackDaoTest {
private TckResourcesCleaner tckResourcesCleaner;
private EntityManager manager;
private MultiuserJpaStackDao dao;
private UserImpl[] users;
private StackImpl[] stacks;
@BeforeClass
public void setupEntities() throws Exception {
users =
new UserImpl[] {
new UserImpl("user1", "user1@com.com", "usr1"),
new UserImpl("user2", "user2@com.com", "usr2")
};
stacks =
new StackImpl[] {
new StackImpl(
"stack1", "st1", null, null, null, Arrays.asList("tag1", "tag2"), null, null, null),
new StackImpl("stack2", "st2", null, null, null, null, null, null, null),
new StackImpl(
"stack3", "st3", null, null, null, Arrays.asList("tag1", "tag2"), null, null, null),
new StackImpl("stack4", "st4", null, null, null, null, null, null, null)
};
Injector injector = Guice.createInjector(new WorkspaceTckModule());
manager = injector.getInstance(EntityManager.class);
dao = injector.getInstance(MultiuserJpaStackDao.class);
tckResourcesCleaner = injector.getInstance(TckResourcesCleaner.class);
}
@BeforeMethod
public void setUp() throws Exception {
manager.getTransaction().begin();
for (UserImpl user : users) {
manager.persist(user);
}
for (StackImpl recipe : stacks) {
manager.persist(recipe);
}
manager.getTransaction().commit();
manager.clear();
}
@AfterMethod
public void cleanup() {
manager.getTransaction().begin();
manager
.createQuery("SELECT p FROM StackPermissions p", StackPermissionsImpl.class)
.getResultList()
.forEach(manager::remove);
manager
.createQuery("SELECT r FROM Stack r", StackImpl.class)
.getResultList()
.forEach(manager::remove);
manager
.createQuery("SELECT u FROM Usr u", UserImpl.class)
.getResultList()
.forEach(manager::remove);
manager.getTransaction().commit();
}
@AfterClass
public void shutdown() throws Exception {
tckResourcesCleaner.clean();
}
@Test
public void shouldFindStackByDirectPermissions() throws Exception {
manager.persist(
new StackPermissionsImpl(
users[0].getId(), stacks[0].getId(), Arrays.asList("read", "use", "search")));
manager.persist(
new StackPermissionsImpl(
users[0].getId(), stacks[1].getId(), Arrays.asList("read", "search")));
manager.persist(
new StackPermissionsImpl(
users[0].getId(), stacks[2].getId(), Arrays.asList("read", "search")));
List<StackImpl> results = dao.searchStacks(users[0].getId(), null, 0, 0);
assertEquals(results.size(), 3);
assertTrue(results.contains(stacks[0]));
assertTrue(results.contains(stacks[1]));
assertTrue(results.contains(stacks[2]));
}
@Test
public void shouldFindStackByPublicPermissions() throws Exception {
manager.persist(
new StackPermissionsImpl("*", stacks[0].getId(), Arrays.asList("read", "use", "search")));
List<StackImpl> results = dao.searchStacks(users[0].getId(), null, 0, 0);
assertEquals(results.size(), 1);
assertTrue(results.contains(stacks[0]));
}
@Test
public void shouldFindStackByPublicAndDirectPermissions() throws Exception {
manager.persist(
new StackPermissionsImpl("*", stacks[0].getId(), Arrays.asList("read", "search")));
manager.persist(
new StackPermissionsImpl(
users[0].getId(), stacks[0].getId(), Arrays.asList("read", "search")));
List<StackImpl> results = dao.searchStacks(users[0].getId(), null, 0, 0);
assertEquals(results.size(), 1);
assertTrue(results.contains(stacks[0]));
}
@Test
public void shouldFindRecipeByPermissionsAndTags() throws Exception {
manager.persist(
new StackPermissionsImpl(
users[0].getId(), stacks[0].getId(), Arrays.asList("read", "use", "search")));
manager.persist(
new StackPermissionsImpl(
users[0].getId(), stacks[1].getId(), Arrays.asList("read", "search")));
manager.persist(
new StackPermissionsImpl(
users[0].getId(), stacks[2].getId(), Arrays.asList("read", "search")));
manager.persist(
new StackPermissionsImpl(
users[0].getId(), stacks[3].getId(), Arrays.asList("read", "search")));
List<StackImpl> results =
dao.searchStacks(users[0].getId(), Collections.singletonList("tag2"), 0, 0);
assertEquals(results.size(), 2);
assertTrue(results.contains(stacks[0]));
assertTrue(results.contains(stacks[2]));
}
@Test
public void shouldNotFindRecipeByNonexistentTags() throws Exception {
manager.persist(
new StackPermissionsImpl(
users[0].getId(), stacks[0].getId(), Arrays.asList("read", "use", "search")));
manager.persist(
new StackPermissionsImpl(
users[0].getId(), stacks[1].getId(), Arrays.asList("read", "search")));
manager.persist(
new StackPermissionsImpl(
users[0].getId(), stacks[2].getId(), Arrays.asList("read", "search")));
manager.persist(
new StackPermissionsImpl(
users[0].getId(), stacks[3].getId(), Arrays.asList("read", "search")));
List<StackImpl> results =
dao.searchStacks(users[0].getId(), Collections.singletonList("unexisted_tag2"), 0, 0);
assertTrue(results.isEmpty());
}
}

View File

@ -16,7 +16,6 @@ import java.util.Collection;
import org.eclipse.che.account.spi.AccountImpl;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.api.workspace.server.devfile.SerializableConverter;
import org.eclipse.che.api.workspace.server.jpa.JpaStackDao;
import org.eclipse.che.api.workspace.server.jpa.JpaWorkspaceDao;
import org.eclipse.che.api.workspace.server.model.impl.CommandImpl;
import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
@ -36,8 +35,6 @@ import org.eclipse.che.api.workspace.server.model.impl.devfile.EntrypointImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.EnvImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.ProjectImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.SourceImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.spi.WorkspaceDao;
import org.eclipse.che.commons.test.db.H2DBTestServer;
import org.eclipse.che.commons.test.db.H2JpaCleaner;
@ -52,14 +49,10 @@ import org.eclipse.che.core.db.h2.jpa.eclipselink.H2ExceptionHandler;
import org.eclipse.che.core.db.schema.SchemaInitializer;
import org.eclipse.che.core.db.schema.impl.flyway.FlywaySchemaInitializer;
import org.eclipse.che.multiuser.api.permission.server.AbstractPermissionsDomain;
import org.eclipse.che.multiuser.api.permission.server.spi.PermissionsDao;
import org.eclipse.che.multiuser.permission.workspace.server.model.impl.WorkerImpl;
import org.eclipse.che.multiuser.permission.workspace.server.spi.WorkerDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaStackPermissionsDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaWorkerDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.tck.StackPermissionsDaoTest;
import org.eclipse.che.multiuser.permission.workspace.server.spi.tck.WorkerDaoTest;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
import org.h2.Driver;
/** @author Yevhenii Voevodin */
@ -79,12 +72,10 @@ public class WorkspaceTckModule extends TckModule {
WorkspaceConfigImpl.class,
ProjectConfigImpl.class,
EnvironmentImpl.class,
StackPermissionsImpl.class,
WorkerImpl.class,
MachineConfigImpl.class,
SourceStorageImpl.class,
ServerConfigImpl.class,
StackImpl.class,
CommandImpl.class,
RecipeImpl.class,
VolumeImpl.class,
@ -112,25 +103,16 @@ public class WorkspaceTckModule extends TckModule {
bind(new TypeLiteral<TckRepository<AccountImpl>>() {})
.toInstance(new JpaTckRepository<>(AccountImpl.class));
bind(new TypeLiteral<TckRepository<WorkspaceImpl>>() {}).toInstance(new WorkspaceRepository());
bind(new TypeLiteral<TckRepository<StackImpl>>() {}).toInstance(new StackRepository());
bind(new TypeLiteral<TckRepository<UserImpl>>() {})
.toInstance(new JpaTckRepository<>(UserImpl.class));
bind(new TypeLiteral<TckRepository<WorkerImpl>>() {})
.toInstance(new JpaTckRepository<>(WorkerImpl.class));
bind(new TypeLiteral<TckRepository<StackPermissionsImpl>>() {})
.toInstance(new JpaTckRepository<>(StackPermissionsImpl.class));
bind(new TypeLiteral<PermissionsDao<StackPermissionsImpl>>() {})
.to(JpaStackPermissionsDao.class);
bind(new TypeLiteral<AbstractPermissionsDomain<WorkerImpl>>() {})
.to(WorkerDaoTest.TestDomain.class);
bind(new TypeLiteral<AbstractPermissionsDomain<StackPermissionsImpl>>() {})
.to(StackPermissionsDaoTest.TestDomain.class);
bind(WorkerDao.class).to(JpaWorkerDao.class);
bind(WorkspaceDao.class).to(JpaWorkspaceDao.class);
bind(StackDao.class).to(JpaStackDao.class);
}
private static class WorkspaceRepository extends JpaTckRepository<WorkspaceImpl> {
@ -147,18 +129,4 @@ public class WorkspaceTckModule extends TckModule {
super.createAll(entities);
}
}
private static class StackRepository extends JpaTckRepository<StackImpl> {
public StackRepository() {
super(StackImpl.class);
}
@Override
public void createAll(Collection<? extends StackImpl> entities) throws TckRepositoryException {
for (StackImpl stack : entities) {
stack.getWorkspaceConfig().getProjects().forEach(ProjectConfigImpl::prePersistAttributes);
}
super.createAll(entities);
}
}
}

View File

@ -33,7 +33,6 @@ import org.eclipse.che.api.workspace.server.model.impl.devfile.EntrypointImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.EnvImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.ProjectImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.SourceImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.commons.test.db.H2DBTestServer;
import org.eclipse.che.commons.test.db.H2JpaCleaner;
import org.eclipse.che.commons.test.db.PersistTestModuleBuilder;
@ -46,12 +45,9 @@ import org.eclipse.che.core.db.h2.jpa.eclipselink.H2ExceptionHandler;
import org.eclipse.che.core.db.schema.SchemaInitializer;
import org.eclipse.che.core.db.schema.impl.flyway.FlywaySchemaInitializer;
import org.eclipse.che.multiuser.api.permission.server.AbstractPermissionsDomain;
import org.eclipse.che.multiuser.api.permission.server.spi.PermissionsDao;
import org.eclipse.che.multiuser.permission.workspace.server.model.impl.WorkerImpl;
import org.eclipse.che.multiuser.permission.workspace.server.spi.WorkerDao;
import org.eclipse.che.multiuser.permission.workspace.server.spi.tck.StackPermissionsDaoTest;
import org.eclipse.che.multiuser.permission.workspace.server.spi.tck.WorkerDaoTest;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
import org.h2.Driver;
/** @author Yevhenii Voevodin */
@ -71,12 +67,10 @@ public class JpaTckModule extends TckModule {
WorkspaceConfigImpl.class,
ProjectConfigImpl.class,
EnvironmentImpl.class,
StackPermissionsImpl.class,
WorkerImpl.class,
MachineConfigImpl.class,
SourceStorageImpl.class,
ServerConfigImpl.class,
StackImpl.class,
CommandImpl.class,
RecipeImpl.class,
VolumeImpl.class,
@ -97,15 +91,6 @@ public class JpaTckModule extends TckModule {
.setExceptionHandler(H2ExceptionHandler.class)
.build());
bind(new TypeLiteral<AbstractPermissionsDomain<StackPermissionsImpl>>() {})
.to(StackPermissionsDaoTest.TestDomain.class);
bind(new TypeLiteral<PermissionsDao<StackPermissionsImpl>>() {})
.to(JpaStackPermissionsDao.class);
bind(new TypeLiteral<TckRepository<StackPermissionsImpl>>() {})
.toInstance(new JpaTckRepository<>(StackPermissionsImpl.class));
bind(new TypeLiteral<TckRepository<StackImpl>>() {})
.toInstance(new JpaTckRepository<>(StackImpl.class));
bind(new TypeLiteral<AbstractPermissionsDomain<WorkerImpl>>() {})
.to(WorkerDaoTest.TestDomain.class);

View File

@ -1,126 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.spi.jpa;
import static java.util.Arrays.asList;
import static org.testng.AssertJUnit.assertEquals;
import com.google.inject.Guice;
import com.google.inject.Injector;
import java.util.List;
import java.util.stream.Stream;
import javax.persistence.EntityManager;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.api.workspace.server.jpa.JpaStackDao;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.commons.test.tck.TckResourcesCleaner;
import org.eclipse.che.multiuser.api.permission.server.AbstractPermissionsDomain;
import org.eclipse.che.multiuser.permission.workspace.server.spi.jpa.JpaStackPermissionsDao.RemovePermissionsBeforeStackRemovedEventSubscriber;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* Tests for {@link RemovePermissionsBeforeStackRemovedEventSubscriber}
*
* @author Sergii Leschenko
*/
public class RemovePermissionsBeforeStackRemovedEventSubscriberTest {
private TckResourcesCleaner tckResourcesCleaner;
private EntityManager manager;
private JpaStackDao stackDao;
private JpaStackPermissionsDao stackPermissionsDao;
private RemovePermissionsBeforeStackRemovedEventSubscriber subscriber;
private StackImpl stack;
private UserImpl[] users;
private StackPermissionsImpl[] stackPermissions;
@BeforeClass
public void setupEntities() throws Exception {
stack = StackImpl.builder().setId("stack123").setName("defaultStack").build();
users = new UserImpl[3];
for (int i = 0; i < 3; i++) {
users[i] = new UserImpl("user" + i, "user" + i + "@test.com", "username" + i);
}
stackPermissions = new StackPermissionsImpl[3];
for (int i = 0; i < 3; i++) {
stackPermissions[i] =
new StackPermissionsImpl(users[i].getId(), stack.getId(), asList("read", "update"));
}
Injector injector = Guice.createInjector(new JpaTckModule());
manager = injector.getInstance(EntityManager.class);
stackDao = injector.getInstance(JpaStackDao.class);
stackPermissionsDao = injector.getInstance(JpaStackPermissionsDao.class);
tckResourcesCleaner = injector.getInstance(TckResourcesCleaner.class);
subscriber = injector.getInstance(RemovePermissionsBeforeStackRemovedEventSubscriber.class);
subscriber.subscribe();
}
@BeforeMethod
public void setUp() throws Exception {
manager.getTransaction().begin();
manager.persist(stack);
Stream.of(users).forEach(manager::persist);
Stream.of(stackPermissions).forEach(manager::persist);
manager.getTransaction().commit();
}
@AfterMethod
public void cleanup() {
manager.getTransaction().begin();
manager
.createQuery("SELECT usr FROM Usr usr", UserImpl.class)
.getResultList()
.forEach(manager::remove);
manager.getTransaction().commit();
}
@AfterClass
public void shutdown() throws Exception {
subscriber.unsubscribe();
tckResourcesCleaner.clean();
}
@Test
public void shouldRemoveAllRecipePermissionsWhenRecipeIsRemoved() throws Exception {
stackDao.remove(stack.getId());
assertEquals(stackPermissionsDao.getByInstance(stack.getId(), 1, 0).getTotalItemsCount(), 0);
}
@Test
public void shouldRemoveAllRecipePermissionsWhenPageSizeEqualsToOne() throws Exception {
subscriber.removeStackPermissions(stack.getId(), 1);
assertEquals(stackPermissionsDao.getByInstance(stack.getId(), 1, 0).getTotalItemsCount(), 0);
}
public static class TestDomain extends AbstractPermissionsDomain<StackPermissionsImpl> {
public TestDomain() {
super("stack", asList("read", "write", "use", "delete"));
}
@Override
protected StackPermissionsImpl doCreateInstance(
String userId, String instanceId, List<String> allowedActions) {
return new StackPermissionsImpl(userId, instanceId, allowedActions);
}
}
}

View File

@ -1,255 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.spi.tck;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.AssertJUnit.assertEquals;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.inject.Inject;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.Page;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.commons.test.tck.TckListener;
import org.eclipse.che.commons.test.tck.repository.TckRepository;
import org.eclipse.che.commons.test.tck.repository.TckRepositoryException;
import org.eclipse.che.multiuser.api.permission.server.AbstractPermissionsDomain;
import org.eclipse.che.multiuser.api.permission.server.spi.PermissionsDao;
import org.eclipse.che.multiuser.api.permission.shared.model.Permissions;
import org.eclipse.che.multiuser.permission.workspace.server.stack.StackPermissionsImpl;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/** @author Max Shaposhnik */
@Listeners(TckListener.class)
@Test(suiteName = "StackPermissionsDaoTck")
public class StackPermissionsDaoTest {
@Inject private PermissionsDao<StackPermissionsImpl> dao;
@Inject private TckRepository<StackPermissionsImpl> permissionsRepository;
@Inject private TckRepository<UserImpl> userRepository;
@Inject private TckRepository<StackImpl> stackRepository;
private StackPermissionsImpl[] permissions;
@BeforeMethod
public void setUp() throws TckRepositoryException {
permissions =
new StackPermissionsImpl[] {
new StackPermissionsImpl("user1", "stack1", asList("read", "use", "run")),
new StackPermissionsImpl("user2", "stack1", asList("read", "use")),
new StackPermissionsImpl("user1", "stack2", asList("read", "run")),
new StackPermissionsImpl("user2", "stack2", asList("read", "use", "run", "configure")),
new StackPermissionsImpl("user", "stack2", asList("read", "use", "run", "configure"))
};
final UserImpl[] users =
new UserImpl[] {
new UserImpl("user", "user@com.com", "usr"),
new UserImpl("user1", "user1@com.com", "usr1"),
new UserImpl("user2", "user2@com.com", "usr2")
};
userRepository.createAll(asList(users));
// Workspace configuration
final WorkspaceConfigImpl wCfg = new WorkspaceConfigImpl();
wCfg.setDefaultEnv("env1");
wCfg.setName("ws1");
wCfg.setDescription("description");
stackRepository.createAll(
asList(
new StackImpl("stack1", "st1", null, null, null, null, wCfg, null, null),
new StackImpl("stack2", "st2", null, null, null, null, wCfg, null, null)));
permissionsRepository.createAll(
Stream.of(permissions).map(StackPermissionsImpl::new).collect(Collectors.toList()));
}
@AfterMethod
public void cleanUp() throws TckRepositoryException {
permissionsRepository.removeAll();
stackRepository.removeAll();
userRepository.removeAll();
}
/* StackPermissionsDao.store() tests */
@Test
public void shouldStorePermissions() throws Exception {
final StackPermissionsImpl permissions =
new StackPermissionsImpl("user", "stack1", asList("read", "use"));
dao.store(permissions);
final Permissions result = dao.get(permissions.getUserId(), permissions.getInstanceId());
assertEquals(result, new StackPermissionsImpl(permissions));
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowExceptionWhenStoringArgumentIsNull() throws Exception {
dao.store(null);
}
@Test
public void shouldReplacePermissionsOnStoringWhenItHasAlreadyExisted() throws Exception {
StackPermissionsImpl oldPermissions = permissions[0];
StackPermissionsImpl newPermissions =
new StackPermissionsImpl(
oldPermissions.getUserId(), oldPermissions.getInstanceId(), singletonList("read"));
dao.store(newPermissions);
final Permissions result = dao.get(oldPermissions.getUserId(), oldPermissions.getInstanceId());
assertEquals(newPermissions, result);
}
@Test
public void shouldReturnsSupportedDomainsIds() {
assertEquals(dao.getDomain(), new TestDomain());
}
/* StackPermissionsDao.remove() tests */
@Test
public void shouldRemovePermissions() throws Exception {
StackPermissionsImpl testPermission = permissions[3];
dao.remove(testPermission.getUserId(), testPermission.getInstanceId());
assertFalse(
dao.exists(
testPermission.getUserId(),
testPermission.getInstanceId(),
testPermission.getActions().get(0)));
}
@Test(
expectedExceptions = NotFoundException.class,
expectedExceptionsMessageRegExp =
"Permissions on stack 'instance' of user 'user' was not found.")
public void shouldThrowNotFoundExceptionWhenPermissionsWasNotFoundOnRemove() throws Exception {
dao.remove("user", "instance");
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowExceptionWhenRemovePermissionsUserIdArgumentIsNull() throws Exception {
dao.remove(null, "instance");
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowExceptionWhenRemovePermissionsInstanceIdArgumentIsNull() throws Exception {
dao.remove("user", null);
}
/* StackPermissionsDao.getByInstance() tests */
@Test
public void shouldGetPermissionsByInstance() throws Exception {
final Page<StackPermissionsImpl> permissionsPage =
dao.getByInstance(permissions[2].getInstanceId(), 1, 1);
final List<StackPermissionsImpl> fetchedPermissions = permissionsPage.getItems();
assertEquals(3, permissionsPage.getTotalItemsCount());
assertEquals(1, permissionsPage.getItemsCount());
assertTrue(
fetchedPermissions.contains(permissions[2])
^ fetchedPermissions.contains(this.permissions[3])
^ fetchedPermissions.contains(this.permissions[4]));
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowExceptionWhenGetByInstanceInstanceIdArgumentIsNull() throws Exception {
dao.getByInstance(null, 1, 0);
}
/* StackPermissionsDao.get() tests */
@Test
public void shouldBeAbleToGetPermissions() throws Exception {
final StackPermissionsImpl result1 =
dao.get(permissions[0].getUserId(), permissions[0].getInstanceId());
final StackPermissionsImpl result2 =
dao.get(permissions[2].getUserId(), permissions[2].getInstanceId());
assertEquals(result1, permissions[0]);
assertEquals(result2, permissions[2]);
}
@Test(
expectedExceptions = NotFoundException.class,
expectedExceptionsMessageRegExp =
"Permissions on stack 'instance' of user 'user' was not found.")
public void
shouldThrowNotFoundExceptionWhenThereIsNotAnyPermissionsForGivenUserAndDomainAndInstance()
throws Exception {
dao.get("user", "instance");
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowExceptionWhenGetPermissionsUserIdArgumentIsNull() throws Exception {
dao.get(null, "instance");
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowExceptionWhenGetPermissionsInstanceIdArgumentIsNull() throws Exception {
dao.get("user", null);
}
/* StackPermissionsDao.exists() tests */
@Test
public void shouldBeAbleToCheckPermissionExistence() throws Exception {
StackPermissionsImpl testPermission = permissions[0];
final boolean readPermissionExisted =
dao.exists(testPermission.getUserId(), testPermission.getInstanceId(), "read");
final boolean fakePermissionExisted =
dao.exists(testPermission.getUserId(), testPermission.getInstanceId(), "fake");
assertEquals(readPermissionExisted, testPermission.getActions().contains("read"));
assertEquals(fakePermissionExisted, testPermission.getActions().contains("fake"));
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowExceptionWhenPermissionsExistsUserIdArgumentIsNull() throws Exception {
dao.exists(null, "instance", "action");
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowExceptionWhenPermissionsExistsInstanceIdArgumentIsNull() throws Exception {
dao.exists("user", null, "action");
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowExceptionWhenPermissionsExistsActionArgumentIsNull() throws Exception {
dao.exists("user", "instance", null);
}
public static class TestDomain extends AbstractPermissionsDomain<StackPermissionsImpl> {
public TestDomain() {
super("stack", asList("read", "write", "use", "delete"));
}
@Override
protected StackPermissionsImpl doCreateInstance(
String userId, String instanceId, List<String> allowedActions) {
return new StackPermissionsImpl(userId, instanceId, allowedActions);
}
}
}

View File

@ -1,95 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.multiuser.permission.workspace.server.stack;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.testng.Assert.assertEquals;
import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.workspace.server.event.StackPersistedEvent;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.SubjectImpl;
import org.eclipse.che.multiuser.api.permission.server.PermissionsManager;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* Tests {@link StackCreatorPermissionsProvider}.
*
* @author Yevhenii Voevodin
*/
@Listeners(MockitoTestNGListener.class)
public class StackCreatorPermissionsProviderTest {
@Mock private EventService eventService;
@Mock private PermissionsManager permManager;
@InjectMocks private StackCreatorPermissionsProvider permProvider;
@AfterMethod
public void resetContext() {
EnvironmentContext.reset();
}
@Test
public void shouldAddPermissions() throws Exception {
final EnvironmentContext ctx = new EnvironmentContext();
ctx.setSubject(new SubjectImpl("test-user-name", "test-user-id", "test-token", false));
EnvironmentContext.setCurrent(ctx);
final StackImpl stack = createStack();
permProvider.onEvent(new StackPersistedEvent(stack));
final ArgumentCaptor<StackPermissionsImpl> captor =
ArgumentCaptor.forClass(StackPermissionsImpl.class);
verify(permManager).storePermission(captor.capture());
final StackPermissionsImpl perm = captor.getValue();
assertEquals(perm.getInstanceId(), stack.getId());
assertEquals(perm.getUserId(), "test-user-id");
assertEquals(perm.getDomainId(), StackDomain.DOMAIN_ID);
assertEquals(perm.getActions(), StackDomain.getActions());
}
@Test
public void shouldNotAddPermissionsIfThereIsNoUserInEnvironmentContext() throws Exception {
permProvider.onEvent(new StackPersistedEvent(createStack()));
verify(permManager, never()).storePermission(any());
}
@Test
public void shouldSubscribe() {
permProvider.subscribe();
verify(eventService).subscribe(permProvider, StackPersistedEvent.class);
}
@Test
public void shouldUnsubscribe() {
permProvider.unsubscribe();
verify(eventService).unsubscribe(permProvider, StackPersistedEvent.class);
}
private static StackImpl createStack() {
return StackImpl.builder().setId("test").setName("test").setCreator("test").build();
}
}

View File

@ -0,0 +1,14 @@
--
-- Copyright (c) 2012-2019 Red Hat, Inc.
-- This program and the accompanying materials are made
-- available under the terms of the Eclipse Public License 2.0
-- which is available at https://www.eclipse.org/legal/epl-2.0/
--
-- SPDX-License-Identifier: EPL-2.0
--
-- Contributors:
-- Red Hat, Inc. - initial API and implementation
--
DROP TABLE che_stack_permissions_actions;
DROP TABLE che_stack_permissions;

View File

@ -1,50 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.constant;
/** @author Ann Shumilova */
public enum TestStacksConstants {
ANDROID("android-default", "Android"),
JAVA("java-default", "Java"),
JAVA_MYSQL("java-mysql", "Java-MySQL"),
BLANK("blank-default", "Blank"),
BITNAMI_CODEIGNITER("bitnami-codeigniter", "Bitnami Codeigniter"),
BITNAMI_SYMFONY("bitnami-symfony", "Bitnami Symfony"),
BITNAMI_PLAY_FOR_JAVA("bitnami-java-play", "Bitnami Play for Java"),
BITNAMI_RAILS("bitnami-rails", "Bitnami Rails"),
BITNAMI_EXPRESS("bitnami-express", "Bitnami Express"),
BITNAMI_LARAVEL("bitnami-laravel", "Bitnami Laravel"),
BITNAMI_SWIFT("bitnami-swift", "Bitnami Swift"),
CPP("cpp-default", "C++"),
DOTNET("dotnet-default", ".NET"),
ECLIPSE_CHE("che-in-che", "Eclipse Che"),
NODE("node-default", "Node"),
PHP("php-default", "PHP"),
PYTHON("python-default", "Python"),
RAILS("rails-default", "Rails");
private final String id;
private final String name;
TestStacksConstants(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return this.id;
}
public String getName() {
return name;
}
}

View File

@ -19,6 +19,7 @@ import java.util.List;
import org.eclipse.che.selenium.core.user.DefaultTestUser;
import org.eclipse.che.selenium.core.workspace.TestWorkspace;
import org.eclipse.che.selenium.core.workspace.TestWorkspaceProvider;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.Workspaces;
/**
@ -36,27 +37,24 @@ public class CreateWorkspaceHelper {
@Inject private DefaultTestUser defaultTestUser;
@Inject private TestWorkspaceProvider testWorkspaceProvider;
public TestWorkspace createWorkspaceFromStackWithProject(
NewWorkspace.Stack stack, String workspaceName, String projectName) {
return createWorkspaceFromStack(stack, workspaceName, ImmutableList.of(projectName), null);
public TestWorkspace createWorkspaceFromDevfileWithProject(
Devfile devfile, String workspaceName, String projectName) {
return createWorkspaceFromStack(devfile, workspaceName, ImmutableList.of(projectName), null);
}
public TestWorkspace createWorkspaceFromStackWithoutProject(
NewWorkspace.Stack stack, String workspaceName) {
return createWorkspaceFromStack(stack, workspaceName, Collections.emptyList(), null);
public TestWorkspace createWorkspaceFromDevfileWithoutProject(
Devfile devfile, String workspaceName) {
return createWorkspaceFromStack(devfile, workspaceName, Collections.emptyList(), null);
}
public TestWorkspace createWorkspaceFromStackWithProjects(
NewWorkspace.Stack stack, String workspaceName, List<String> projectNames) {
return createWorkspaceFromStack(stack, workspaceName, projectNames, null);
Devfile devfile, String workspaceName, List<String> projectNames) {
return createWorkspaceFromStack(devfile, workspaceName, projectNames, null);
}
public TestWorkspace createWorkspaceFromStack(
NewWorkspace.Stack stack,
String workspaceName,
List<String> projectNames,
Double machineRam) {
prepareWorkspace(stack, workspaceName, machineRam);
Devfile devfile, String workspaceName, List<String> projectNames, Double machineRam) {
prepareWorkspace(devfile, workspaceName, machineRam);
projectSourcePage.clickOnAddOrImportProjectButton();
projectNames.forEach(projectSourcePage::selectSample);
@ -67,14 +65,14 @@ public class CreateWorkspaceHelper {
return testWorkspaceProvider.getWorkspace(workspaceName, defaultTestUser);
}
private void prepareWorkspace(NewWorkspace.Stack stack, String workspaceName, Double machineRam) {
private void prepareWorkspace(Devfile devfile, String workspaceName, Double machineRam) {
dashboard.waitDashboardToolbarTitle();
dashboard.selectWorkspacesItemOnDashboard();
workspaces.clickOnAddWorkspaceBtn();
newWorkspace.waitToolbar();
newWorkspace.selectStack(stack);
newWorkspace.selectDevfile(devfile);
newWorkspace.typeWorkspaceName(workspaceName);
}
}

View File

@ -16,9 +16,9 @@ import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static org.eclipse.che.selenium.core.constant.TestTimeoutsConstants.WIDGET_TIMEOUT_SEC;
import static org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Locators.BOTTOM_CREATE_BUTTON_XPATH;
import static org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Locators.DEVFILE_ROW_XPATH;
import static org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Locators.ERROR_MESSAGE;
import static org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Locators.ORGANIZATIONS_LIST_ID;
import static org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Locators.STACK_ROW_XPATH;
import static org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Locators.TOOLBAR_TITLE_ID;
import static org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Locators.TOP_CREATE_BUTTON_XPATH;
import static org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Locators.TOP_DROPDOWN_BUTTON_XPATH;
@ -73,7 +73,7 @@ public class NewWorkspace {
String WORKSPACE_NAME_INPUT = "workspace-name-input";
String ERROR_MESSAGE = "new-workspace-error-message";
String TOOLBAR_TITLE_ID = "New_Workspace";
String STACK_ROW_XPATH = "//div[@data-devfile-id='%s']";
String DEVFILE_ROW_XPATH = "//div[@data-devfile-id='%s']";
String MACHINE_NAME =
"//span[contains(@class,'ram-settings-machine-item-item-name') and text()='%s']";
String ORGANIZATIONS_LIST_ID = "namespace-selector";
@ -85,7 +85,7 @@ public class NewWorkspace {
String BOTTOM_CREATE_BUTTON_XPATH = "//che-button-save-flat/button[@name='saveButton']";
}
public enum Stack {
public enum Devfile {
APACHE_CAMEL("Apache Camel based projects on Che 7"),
DOT_NET(".NET Core with Theia IDE"),
GO("Go with Theia IDE"),
@ -96,15 +96,15 @@ public class NewWorkspace {
// wsnext-helloworld-openshift
private final String id;
Stack(String id) {
Devfile(String id) {
this.id = id;
}
public static Stack getById(String id) {
Optional<Stack> first =
asList(values()).stream().filter(stack -> stack.getId().equals(id)).findFirst();
public static Devfile getById(String id) {
Optional<Devfile> first =
asList(values()).stream().filter(devfile -> devfile.getId().equals(id)).findFirst();
first.orElseThrow(
() -> new RuntimeException(String.format("Stack with id '%s' not found.", id)));
() -> new RuntimeException(String.format("Devfile with id '%s' not found.", id)));
return first.get();
}
@ -176,14 +176,16 @@ public class NewWorkspace {
seleniumWebDriverHelper.waitVisibility(By.id(TOOLBAR_TITLE_ID), timeout);
}
public boolean isStackVisible(Stack stack) {
return seleniumWebDriver.findElements(By.xpath(format(STACK_ROW_XPATH, stack.getId()))).size()
public boolean isDevfileVisible(Devfile devfile) {
return seleniumWebDriver
.findElements(By.xpath(format(DEVFILE_ROW_XPATH, devfile.getId())))
.size()
> 0;
}
public void selectStack(Stack stack) {
waitStacks(asList(stack));
seleniumWebDriverHelper.waitAndClick(By.xpath(format(STACK_ROW_XPATH, stack.getId())));
public void selectDevfile(Devfile devfile) {
waitDevfiles(asList(devfile));
seleniumWebDriverHelper.waitAndClick(By.xpath(format(DEVFILE_ROW_XPATH, devfile.getId())));
}
public boolean isCreateWorkspaceButtonEnabled() {
@ -287,69 +289,70 @@ public class NewWorkspace {
waitPageLoad(DEFAULT_TIMEOUT);
}
public List<Stack> getAvailableStacks() {
public List<Devfile> getAvailableDevfiles() {
return seleniumWebDriverHelper
.waitPresenceOfAllElements(By.xpath("//div[@data-devfile-id]"))
.stream()
.map(webElement -> Stack.getById(webElement.getAttribute("data-devfile-id")))
.map(webElement -> Devfile.getById(webElement.getAttribute("data-devfile-id")))
.collect(toList());
}
public void waitStackSelected(Stack stack) {
String selectedStackXpath =
public void waitDevfileSelected(Devfile devfile) {
String selectedDevfileXpath =
format(
"//div[@data-devfile-id='%s' and contains(@class, 'devfile-selector-item-selected')]",
stack.getId());
seleniumWebDriverHelper.waitVisibility(By.xpath(selectedStackXpath));
devfile.getId());
seleniumWebDriverHelper.waitVisibility(By.xpath(selectedDevfileXpath));
}
public List<Stack> getVisibleStacks() {
public List<Devfile> getVisibleDevfiles() {
return seleniumWebDriverHelper
.waitPresenceOfAllElements(By.xpath("//div[@data-devfile-id]"))
.stream()
.filter(seleniumWebDriverHelper::isVisible)
.map(webElement -> Stack.getById(webElement.getAttribute("data-devfile-id")))
.map(webElement -> Devfile.getById(webElement.getAttribute("data-devfile-id")))
.collect(Collectors.toList());
}
public void waitVisibleStacks(List<Stack> expectedVisibleStacks) {
public void waitVisibleDevfiles(List<Devfile> expectedVisibleDevfiles) {
webDriverWaitFactory
.get()
.until(
(ExpectedCondition<Boolean>)
driver -> getVisibleStacks().equals(expectedVisibleStacks));
driver -> getVisibleDevfiles().equals(expectedVisibleDevfiles));
}
public void waitStacks(List<Stack> expectedStacks) {
expectedStacks.forEach(
stack ->
public void waitDevfiles(List<Devfile> expectedDevfiles) {
expectedDevfiles.forEach(
devfile ->
seleniumWebDriverHelper.waitPresence(
By.xpath(format("//div[@data-devfile-id='%s']", stack.getId()))));
By.xpath(format("//div[@data-devfile-id='%s']", devfile.getId()))));
}
public void waitStacksCount(int expectedCount) {
public void waitDevfilesCount(int expectedCount) {
webDriverWaitFactory
.get()
.until((ExpectedCondition<Boolean>) driver -> expectedCount == getAvailableStacksCount());
.until((ExpectedCondition<Boolean>) driver -> expectedCount == getAvailableDevfilesCount());
}
public int getAvailableStacksCount() {
return getAvailableStacks().size();
public int getAvailableDevfilesCount() {
return getAvailableDevfiles().size();
}
public void waitStacksNotPresent(List<Stack> stacksIdForChecking) {
stacksIdForChecking.forEach(
stack ->
public void waitDevfilesNotPresent(List<Devfile> devfilesIdForChecking) {
devfilesIdForChecking.forEach(
devfile ->
webDriverWaitFactory
.get()
.until(
(ExpectedCondition<Boolean>) driver -> !getAvailableStacks().contains(stack)));
(ExpectedCondition<Boolean>)
driver -> !getAvailableDevfiles().contains(devfile)));
}
public void waitStacksOrder(List<Stack> expectedOrder) {
public void waitDevfilesOrder(List<Devfile> expectedOrder) {
webDriverWaitFactory
.get()
.until((ExpectedCondition<Boolean>) driver -> expectedOrder.equals(getAvailableStacks()));
.until((ExpectedCondition<Boolean>) driver -> expectedOrder.equals(getAvailableDevfiles()));
}
public void clickNameButton() {

View File

@ -1,68 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.pageobject.dashboard.stacks;
import static java.lang.String.format;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.webdriver.SeleniumWebDriverHelper;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
@Singleton
public class StackDetails {
private final SeleniumWebDriverHelper seleniumWebDriverHelper;
@Inject
public StackDetails(
SeleniumWebDriver seleniumWebDriver, SeleniumWebDriverHelper seleniumWebDriverHelper) {
this.seleniumWebDriverHelper = seleniumWebDriverHelper;
PageFactory.initElements(seleniumWebDriver, this);
}
private interface Locators {
String TOOLBAR_XPATH = "//*[@name='stackForm']";
String TOOLBAR_WITH_STACK_NAME_XPATH_PATTERN = "//div[@che-title='%s']";
String NEW_STACK_NAME = "deskname";
String SAVE_CHANGES_BUTTON_NAME = "saveButton";
String ALL_STACKS_BUTTON_XPATH = "//a[@title='All stacks']";
}
@FindBy(name = Locators.NEW_STACK_NAME)
WebElement stackNameField;
public void waitToolbar() {
seleniumWebDriverHelper.waitVisibility(By.xpath(Locators.TOOLBAR_XPATH));
}
public void waitToolbarWithStackName(String stackName) {
seleniumWebDriverHelper.waitVisibility(
By.xpath(format(Locators.TOOLBAR_WITH_STACK_NAME_XPATH_PATTERN, stackName)));
}
public void setStackName(String stackName) {
seleniumWebDriverHelper.waitAndClick(stackNameField);
seleniumWebDriverHelper.setValue(stackNameField, stackName);
}
public void clickOnSaveChangesButton() {
seleniumWebDriverHelper.waitAndClick(By.name(Locators.SAVE_CHANGES_BUTTON_NAME));
}
public void clickOnAllStacksButton() {
seleniumWebDriverHelper.waitAndClick(By.xpath(Locators.ALL_STACKS_BUTTON_XPATH));
}
}

View File

@ -1,226 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.pageobject.dashboard.stacks;
import static java.lang.String.format;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.utils.WaitUtils;
import org.eclipse.che.selenium.core.webdriver.SeleniumWebDriverHelper;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
@Singleton
public class Stacks {
private final SeleniumWebDriver seleniumWebDriver;
private final SeleniumWebDriverHelper seleniumWebDriverHelper;
@Inject
public Stacks(
SeleniumWebDriver seleniumWebDriver, SeleniumWebDriverHelper seleniumWebDriverHelper) {
this.seleniumWebDriver = seleniumWebDriver;
this.seleniumWebDriverHelper = seleniumWebDriverHelper;
PageFactory.initElements(seleniumWebDriver, this);
}
private interface Locators {
String TOOLBAR_ID = "Stacks";
String DOCUMENTATION_LINK_XPATH = "//div[@che-link-title='Learn more.']/a";
String ADD_STACK_BUTTON_ID = "import-item-button";
String BUILD_STACK_FROM_RECIPE_BUTTON_ID = "import-item-button";
String DELETE_STACK_BUTTON_ID = "delete-item-button";
String DELETE_DIALOG_BUTTON_ID = "ok-dialog-button";
String SEARCH_STACK_FIELD_XPATH = "//input[@ng-placeholder='Search']";
String STACKS_LIST_HEADERS_XPATH = "//div[@che-column-title]";
String SORT_STACKS_BY_NAME_ID = "sort-stacks-by-name";
String BULK_CHECKBOX_XPATH = "//md-checkbox[@aria-label='Stack list']";
String NO_STACKS_FOUND_XPATH = "//span[text()='No stacks found.']";
String STACK_ITEM_XPATH = "//div[contains(@class, 'stack-item-name')]";
String STACK_ITEM_CHECKBOX_XPATH_PATTERN = "//div[@id='stack-name-%s']//md-checkbox";
String STACK_ITEM_NAME_XPATH_PATTERN = "//div[@id='stack-name-%s']";
String STACK_ITEM_NAME_CONTAINS_XPATH_PATTERN = "//div[contains(@id,'stack-name-%s')]";
String STACK_ITEM_COMPONENTS_XPATH_PATTERN =
"//div[@id='stack-name-%s']//div[contains(@class,'stack-item-components')]";
String STACK_ITEM_DESCRIPTION_XPATH_PATTERN =
"//div[@id='stack-name-%s']//div[contains(@class,'stack-item-description')]";
String STACK_ITEM_DELETE_BUTTON_XPATH_PATTERN =
"//div[@id='stack-name-%s']//a[@uib-tooltip='Delete Stack']";
String DUPLICATE_STACK_BUTTON_XPATH_PATTERN =
"//div[@id='stack-name-%s']//a[@uib-tooltip='Duplicate stack']";
String BUILD_STACK_FROM_RECIPE_DIALOG_XPATH = "//*[@title='Build stack from recipe']";
}
@FindBy(id = Locators.TOOLBAR_ID)
WebElement toolbar;
@FindBy(id = Locators.ADD_STACK_BUTTON_ID)
WebElement addWorkspaceBtn;
@FindBy(id = Locators.DELETE_STACK_BUTTON_ID)
WebElement deleteStackButton;
@FindBy(xpath = Locators.BULK_CHECKBOX_XPATH)
WebElement bulkCheckbox;
@FindBy(id = Locators.BUILD_STACK_FROM_RECIPE_BUTTON_ID)
WebElement buildStackFromRecipeButton;
@FindBy(id = Locators.DELETE_DIALOG_BUTTON_ID)
WebElement deleteDialogBtn;
@FindBy(xpath = Locators.SEARCH_STACK_FIELD_XPATH)
WebElement searchStackField;
public void waitToolbarTitleName() {
seleniumWebDriverHelper.waitVisibility(toolbar);
}
public void waitAddStackButton() {
seleniumWebDriverHelper.waitVisibility(addWorkspaceBtn);
}
public void clickOnAddStackButton() {
seleniumWebDriverHelper.waitAndClick(addWorkspaceBtn);
}
public void waitBuildStackFromRecipeButton() {
seleniumWebDriverHelper.waitVisibility(buildStackFromRecipeButton);
}
public void clickOnBuildStackFromRecipeButton() {
seleniumWebDriverHelper.waitAndClick(buildStackFromRecipeButton);
}
public void waitBuildStackFromRecipeDialog() {
seleniumWebDriverHelper.waitVisibility(By.xpath(Locators.BUILD_STACK_FROM_RECIPE_DIALOG_XPATH));
}
public void selectAllStacksByBulk() {
seleniumWebDriverHelper.waitAndClick(bulkCheckbox);
}
public void selectStackByCheckbox(String stackName) {
seleniumWebDriverHelper.waitAndClick(
By.xpath(String.format(Locators.STACK_ITEM_CHECKBOX_XPATH_PATTERN, stackName)));
}
public boolean isStackChecked(String workspaceName) {
String attrValue =
seleniumWebDriverHelper.waitVisibilityAndGetAttribute(
By.xpath(format(Locators.STACK_ITEM_CHECKBOX_XPATH_PATTERN, workspaceName)),
"aria-checked");
return Boolean.parseBoolean(attrValue);
}
public void openStackDetails(String stackName) {
seleniumWebDriverHelper.waitAndClick(
By.xpath(String.format(Locators.STACK_ITEM_NAME_XPATH_PATTERN, stackName)));
}
public void waitStackItem(String stackName) {
seleniumWebDriverHelper.waitVisibility(
By.xpath(format(Locators.STACK_ITEM_NAME_XPATH_PATTERN, stackName)));
}
public Boolean isStackItemExisted(String stackName) {
return seleniumWebDriverHelper.isVisible(
By.xpath(format(Locators.STACK_ITEM_NAME_XPATH_PATTERN, stackName)));
}
public Boolean isDuplicatedStackExisted(String stackName) {
return seleniumWebDriverHelper.isVisible(
By.xpath(format(Locators.STACK_ITEM_NAME_CONTAINS_XPATH_PATTERN, stackName)));
}
public String getStackDescription(String stackName) {
return seleniumWebDriverHelper.waitVisibilityAndGetText(
By.xpath(format(Locators.STACK_ITEM_DESCRIPTION_XPATH_PATTERN, stackName)));
}
public String getStackComponents(String stackName) {
return seleniumWebDriverHelper.waitVisibilityAndGetText(
By.xpath(format(Locators.STACK_ITEM_COMPONENTS_XPATH_PATTERN, stackName)));
}
public void clickOnDeleteActionButton(String stackName) {
seleniumWebDriverHelper.waitAndClick(
By.xpath(format(Locators.STACK_ITEM_DELETE_BUTTON_XPATH_PATTERN, stackName)));
}
public void clickOnDuplicateStackButton(String stackName) {
seleniumWebDriverHelper.waitAndClick(
By.xpath(format(Locators.DUPLICATE_STACK_BUTTON_XPATH_PATTERN, stackName)));
WaitUtils.sleepQuietly(1);
}
public Boolean isDeleteStackButtonEnabled() {
return seleniumWebDriverHelper.isVisible(deleteStackButton);
}
public void clickOnDeleteStackButton() {
seleniumWebDriverHelper.waitAndClick(deleteStackButton);
}
public void clickOnDeleteDialogButton() {
seleniumWebDriverHelper.waitAndClick(deleteDialogBtn);
}
public void waitFilterStacksField() {
seleniumWebDriverHelper.waitVisibility(searchStackField);
}
public void typeToSearchInput(String value) {
seleniumWebDriverHelper.setValue(searchStackField, value);
}
public void waitNoStacksFound() {
seleniumWebDriverHelper.waitVisibility(By.xpath(Locators.NO_STACKS_FOUND_XPATH));
}
public ArrayList<String> getStacksListHeaders() {
ArrayList<String> titles = new ArrayList<>();
List<WebElement> headers =
seleniumWebDriver.findElements(By.xpath(Locators.STACKS_LIST_HEADERS_XPATH));
headers.forEach(
header -> {
titles.add(header.getText());
});
return titles;
}
public ArrayList<String> getStacksNamesList() {
ArrayList<String> stacksNames = new ArrayList<>();
List<WebElement> names = seleniumWebDriver.findElements(By.xpath(Locators.STACK_ITEM_XPATH));
names.forEach(
name -> {
stacksNames.add(name.getText());
});
return stacksNames;
}
public void clickOnSortStacksByNameButton() {
seleniumWebDriverHelper.waitAndClick(By.id(Locators.SORT_STACKS_BY_NAME_ID));
}
public void waitDocumentationLink() {
seleniumWebDriverHelper.waitVisibility(By.xpath(Locators.DOCUMENTATION_LINK_XPATH));
}
}

View File

@ -302,7 +302,7 @@ public class Workspaces {
}
public void clickOnStackButton() {
seleniumWebDriverHelper.waitAndClick(By.xpath("//div[@che-column-title='Stack']/div"));
seleniumWebDriverHelper.waitAndClick(By.xpath("//div[@che-column-title='Devfile']/div"));
}
public void clickOnWorkspaceStopStartButton(String workspaceName) {

View File

@ -24,7 +24,7 @@ import org.eclipse.che.selenium.core.workspace.TestWorkspaceProvider;
import org.eclipse.che.selenium.pageobject.dashboard.Dashboard;
import org.eclipse.che.selenium.pageobject.dashboard.NavigationBar;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.ProjectSourcePage;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.WorkspaceDetails;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.WorkspaceProjects;
@ -78,8 +78,8 @@ public class CreateAndDeleteProjectsTest {
newWorkspace.waitToolbar();
dashboardWindow = seleniumWebDriver.getWindowHandle();
// we are selecting 'Java' stack from the 'All Stack' tab for compatibility with OSIO
newWorkspace.selectStack(Stack.JAVA_MAVEN);
// we are selecting 'Java' stack from the 'All Devfile' tab for compatibility with OSIO
newWorkspace.selectDevfile(Devfile.JAVA_MAVEN);
newWorkspace.typeWorkspaceName(WORKSPACE);
projectSourcePage.waitCreatedProjectButton(CONSOLE_JAVA_SIMPLE);

View File

@ -41,7 +41,7 @@ import org.eclipse.che.selenium.pageobject.Loader;
import org.eclipse.che.selenium.pageobject.dashboard.Dashboard;
import org.eclipse.che.selenium.pageobject.dashboard.DashboardFactories;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.ProjectSourcePage;
import org.eclipse.che.selenium.pageobject.dashboard.factories.CreateFactoryPage;
import org.eclipse.che.selenium.pageobject.dashboard.factories.FactoryDetails;
@ -377,8 +377,8 @@ public class CreateFactoryTest {
newWorkspace.waitToolbar();
loader.waitOnClosed();
// we are selecting 'Java' stack from the 'All Stack' tab for compatibility with OSIO
newWorkspace.selectStack(Stack.JAVA_MAVEN);
// we are selecting 'Java' stack from the 'All Devfile' tab for compatibility with OSIO
newWorkspace.selectDevfile(Devfile.JAVA_MAVEN);
newWorkspace.typeWorkspaceName(workspaceName);
projectSourcePage.clickOnAddOrImportProjectButton();
@ -403,8 +403,8 @@ public class CreateFactoryTest {
newWorkspace.waitToolbar();
loader.waitOnClosed();
// we are selecting 'Java' stack from the 'All Stack' tab for compatibility with OSIO
newWorkspace.selectStack(Stack.JAVA_MAVEN);
// we are selecting 'Java' stack from the 'All Devfile' tab for compatibility with OSIO
newWorkspace.selectDevfile(Devfile.JAVA_MAVEN);
newWorkspace.typeWorkspaceName(workspaceName);
newWorkspace.clickOnCreateButtonAndEditWorkspace();

View File

@ -19,7 +19,7 @@ import com.google.inject.Inject;
import org.eclipse.che.commons.lang.NameGenerator;
import org.eclipse.che.selenium.pageobject.dashboard.Dashboard;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.ProjectSourcePage;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.Workspaces;
import org.testng.annotations.BeforeClass;
@ -80,7 +80,7 @@ public class CreateWorkspaceTest {
@Test
public void checkProjectSourcePage() {
// add a project from the 'console-java-simple' sample
newWorkspace.selectStack(Stack.JAVA_MAVEN);
newWorkspace.selectDevfile(Devfile.JAVA_MAVEN);
projectSourcePage.waitOpened();
projectSourcePage.waitCreatedProjectButton(projectName);

View File

@ -25,7 +25,7 @@ import org.eclipse.che.selenium.core.workspace.TestWorkspace;
import org.eclipse.che.selenium.core.workspace.TestWorkspaceProvider;
import org.eclipse.che.selenium.pageobject.dashboard.Dashboard;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.ProjectSourcePage;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.Workspaces;
import org.eclipse.che.selenium.pageobject.theia.TheiaIde;
@ -77,8 +77,8 @@ public class ImportMavenProjectFromGitTest {
workspaces.clickOnAddWorkspaceBtn();
newWorkspace.waitToolbar();
// we are selecting 'Java' stack from the 'All Stack' tab for compatibility with OSIO
newWorkspace.selectStack(Stack.JAVA_MAVEN);
// we are selecting 'Java' stack from the 'All Devfile' tab for compatibility with OSIO
newWorkspace.selectDevfile(Devfile.JAVA_MAVEN);
newWorkspace.typeWorkspaceName(WORKSPACE);
projectSourcePage.clickOnAddOrImportProjectButton();

View File

@ -31,7 +31,7 @@ import org.eclipse.che.selenium.core.workspace.TestWorkspaceProvider;
import org.eclipse.che.selenium.pageobject.Ide;
import org.eclipse.che.selenium.pageobject.dashboard.Dashboard;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.ProjectSourcePage;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.Workspaces;
import org.eclipse.che.selenium.pageobject.theia.TheiaIde;
@ -97,8 +97,8 @@ public class ImportProjectFromGitHubTest {
dashboard.selectWorkspacesItemOnDashboard();
workspaces.clickOnAddWorkspaceBtn();
newWorkspace.waitToolbar();
// we are selecting 'Java' stack from the 'All Stack' tab for compatibility with OSIO
newWorkspace.selectStack(Stack.JAVA_MAVEN);
// we are selecting 'Java' stack from the 'All Devfile' tab for compatibility with OSIO
newWorkspace.selectDevfile(Devfile.JAVA_MAVEN);
newWorkspace.typeWorkspaceName(WORKSPACE);
projectSourcePage.clickOnAddOrImportProjectButton();

View File

@ -25,7 +25,7 @@ import org.eclipse.che.selenium.core.user.TestUser;
import org.eclipse.che.selenium.pageobject.dashboard.CheMultiuserAdminDashboard;
import org.eclipse.che.selenium.pageobject.dashboard.NavigationBar;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.organization.OrganizationListPage;
import org.eclipse.che.selenium.pageobject.dashboard.organization.OrganizationPage;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.WorkspaceDetails;
@ -173,7 +173,7 @@ public class AddWorkspaceToOrganizationTest {
newWorkspace.waitToolbar();
newWorkspace.openOrganizationsList();
newWorkspace.selectOrganizationFromList(organizationName);
newWorkspace.selectStack(Stack.JAVA_MAVEN);
newWorkspace.selectDevfile(Devfile.JAVA_MAVEN);
newWorkspace.typeWorkspaceName(workspaceName);
newWorkspace.clickOnCreateButtonAndEditWorkspace();
workspaceDetails.waitToolbarTitleName(workspaceName);

View File

@ -37,7 +37,7 @@ import org.eclipse.che.selenium.pageobject.ProjectExplorer;
import org.eclipse.che.selenium.pageobject.dashboard.CheMultiuserAdminDashboard;
import org.eclipse.che.selenium.pageobject.dashboard.CreateWorkspaceHelper;
import org.eclipse.che.selenium.pageobject.dashboard.NavigationBar;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.WorkspaceDetails;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.WorkspaceDetails.StateWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.WorkspaceOverview;
@ -179,8 +179,8 @@ public class ShareWorkspaceMemberTest {
}
private void createWorkspace(String workspaceName) {
createWorkspaceHelper.createWorkspaceFromStackWithProject(
Stack.JAVA_MAVEN, workspaceName, PROJECT_NAME);
createWorkspaceHelper.createWorkspaceFromDevfileWithProject(
Devfile.JAVA_MAVEN, workspaceName, PROJECT_NAME);
ide.switchToIdeAndWaitWorkspaceIsReadyToUse();

View File

@ -28,7 +28,7 @@ import org.eclipse.che.selenium.core.user.TestUser;
import org.eclipse.che.selenium.pageobject.dashboard.CheMultiuserAdminDashboard;
import org.eclipse.che.selenium.pageobject.dashboard.NavigationBar;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.WorkspaceDetails;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.WorkspaceShare;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.Workspaces;
@ -157,7 +157,7 @@ public class ShareWorkspaceOwnerTest {
newWorkspace.waitToolbar();
newWorkspace.openOrganizationsList();
newWorkspace.selectOrganizationFromList(organizationName);
newWorkspace.selectStack(Stack.JAVA_MAVEN);
newWorkspace.selectDevfile(Devfile.JAVA_MAVEN);
newWorkspace.typeWorkspaceName(workspaceName);
newWorkspace.clickOnCreateButtonAndEditWorkspace();
workspaceDetails.waitToolbarTitleName(workspaceName);

View File

@ -33,7 +33,7 @@ import org.eclipse.che.selenium.core.workspace.TestWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.Dashboard;
import org.eclipse.che.selenium.pageobject.dashboard.DocumentationPage;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.WorkspaceConfig;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.WorkspaceOverview;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.WorkspaceProjects;
@ -341,7 +341,7 @@ public class WorkspacesListTest {
workspaces.clickOnAddWorkspaceBtn();
newWorkspace.waitToolbar();
newWorkspace.typeWorkspaceName(NEWEST_CREATED_WORKSPACE_NAME);
newWorkspace.selectStack(Stack.JAVA_MAVEN);
newWorkspace.selectDevfile(Devfile.JAVA_MAVEN);
newWorkspace.clickOnCreateButtonAndEditWorkspace();
workspaceOverview.checkNameWorkspace(NEWEST_CREATED_WORKSPACE_NAME);

View File

@ -22,7 +22,7 @@ import org.eclipse.che.selenium.core.webdriver.SeleniumWebDriverHelper;
import org.eclipse.che.selenium.pageobject.dashboard.AddOrImportForm;
import org.eclipse.che.selenium.pageobject.dashboard.Dashboard;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.WorkspaceOverview;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.Workspaces;
import org.testng.annotations.Test;
@ -115,9 +115,9 @@ public class WorkspaceDetailsOverviewTest {
newWorkspace.waitPageLoad();
newWorkspace.typeWorkspaceName(WORKSPACE_NAME);
selectStackAndCheckWorkspaceName(Stack.APACHE_CAMEL);
selectDevfileAndCheckWorkspaceName(Devfile.APACHE_CAMEL);
selectStackAndCheckWorkspaceName(Stack.JAVA_GRADLE);
selectDevfileAndCheckWorkspaceName(Devfile.JAVA_GRADLE);
// create workspace
addOrImportForm.clickOnAddOrImportProjectButton();
@ -176,9 +176,9 @@ public class WorkspaceDetailsOverviewTest {
workspaceOverview.waitExportWorkspaceFormClosed();
}
private void selectStackAndCheckWorkspaceName(NewWorkspace.Stack stack) {
newWorkspace.selectStack(stack);
newWorkspace.waitStackSelected(stack);
private void selectDevfileAndCheckWorkspaceName(Devfile devfile) {
newWorkspace.selectDevfile(devfile);
newWorkspace.waitDevfileSelected(devfile);
newWorkspace.waitWorkspaceNameFieldValue(WORKSPACE_NAME);
}

View File

@ -25,7 +25,7 @@ import org.eclipse.che.selenium.core.user.DefaultTestUser;
import org.eclipse.che.selenium.core.workspace.TestWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.Dashboard;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.Workspaces;
import org.eclipse.che.selenium.pageobject.ocp.AuthorizeOpenShiftAccessPage;
import org.eclipse.che.selenium.pageobject.ocp.OpenShiftLoginPage;
@ -135,7 +135,7 @@ public class LoginExistedUserWithOpenShiftOAuthTest {
workspaces.clickOnAddWorkspaceBtn();
newWorkspace.waitToolbar();
newWorkspace.typeWorkspaceName(WORKSPACE_NAME);
newWorkspace.selectStack(Stack.JAVA_MAVEN);
newWorkspace.selectDevfile(Devfile.JAVA_MAVEN);
newWorkspace.clickOnCreateButtonAndOpenInIDE();
// switch to the IDE and wait for workspace is ready to use

View File

@ -26,7 +26,7 @@ import org.eclipse.che.selenium.core.user.TestUser;
import org.eclipse.che.selenium.core.workspace.TestWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.Dashboard;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.Workspaces;
import org.eclipse.che.selenium.pageobject.ocp.AuthorizeOpenShiftAccessPage;
import org.eclipse.che.selenium.pageobject.ocp.OpenShiftLoginPage;
@ -121,7 +121,7 @@ public class LoginNewUserWithOpenShiftOAuthTest {
workspaces.clickOnAddWorkspaceBtn();
newWorkspace.waitToolbar();
newWorkspace.typeWorkspaceName(WORKSPACE_NAME);
newWorkspace.selectStack(Stack.JAVA_MAVEN);
newWorkspace.selectDevfile(Devfile.JAVA_MAVEN);
newWorkspace.clickOnCreateButtonAndOpenInIDE();
// switch to the IDE and wait for workspace is ready to use

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.theia;
import static org.eclipse.che.selenium.core.TestGroup.OPENSHIFT;
import com.google.inject.Inject;
import org.eclipse.che.commons.lang.NameGenerator;
import org.eclipse.che.selenium.core.client.TestWorkspaceServiceClient;
import org.eclipse.che.selenium.core.user.DefaultTestUser;
import org.eclipse.che.selenium.pageobject.dashboard.CreateWorkspaceHelper;
import org.eclipse.che.selenium.pageobject.dashboard.Dashboard;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.theia.TheiaIde;
import org.eclipse.che.selenium.pageobject.theia.TheiaProjectTree;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
public class Che7PreviewDevfileStartTest {
private static final String WORKSPACE_NAME = NameGenerator.generate("wksp-", 5);
@Inject private Dashboard dashboard;
@Inject private TheiaIde theiaIde;
@Inject private DefaultTestUser defaultTestUser;
@Inject private CreateWorkspaceHelper createWorkspaceHelper;
@Inject private TestWorkspaceServiceClient workspaceServiceClient;
@Inject private TheiaProjectTree theiaProjectTree;
@AfterClass
public void tearDown() throws Exception {
workspaceServiceClient.delete(WORKSPACE_NAME, defaultTestUser.getName());
}
@Test(groups = {OPENSHIFT})
public void workspaceShouldBeStarted() {
dashboard.open();
createWorkspaceHelper.createWorkspaceFromDevfileWithoutProject(Devfile.GO, WORKSPACE_NAME);
theiaIde.switchToIdeFrame();
theiaIde.waitTheiaIde();
theiaIde.waitLoaderInvisibility();
theiaIde.waitTheiaIde();
theiaIde.waitTheiaIdeTopPanel();
theiaProjectTree.waitFilesTab();
}
}

View File

@ -26,7 +26,7 @@ import org.eclipse.che.selenium.core.webdriver.SeleniumWebDriverHelper;
import org.eclipse.che.selenium.pageobject.dashboard.CreateWorkspaceHelper;
import org.eclipse.che.selenium.pageobject.dashboard.Dashboard;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Stack;
import org.eclipse.che.selenium.pageobject.dashboard.NewWorkspace.Devfile;
import org.eclipse.che.selenium.pageobject.dashboard.workspaces.Workspaces;
import org.eclipse.che.selenium.pageobject.theia.TheiaEditor;
import org.eclipse.che.selenium.pageobject.theia.TheiaHostedPluginSelectPathForm;
@ -66,7 +66,7 @@ public class TheiaBuildPluginTest {
@BeforeClass
public void prepare() {
dashboard.open();
createWorkspaceHelper.createWorkspaceFromStackWithoutProject(Stack.GO, WORKSPACE_NAME);
createWorkspaceHelper.createWorkspaceFromDevfileWithoutProject(Devfile.GO, WORKSPACE_NAME);
theiaIde.switchToIdeFrame();
theiaIde.waitTheiaIde();

View File

@ -31,12 +31,6 @@ public final class Constants {
public static final String WORKSPACE_STOPPED_BY = "stopped_by";
public static final String WORKSPACE_STOP_REASON = "stop_reason";
public static final String LINK_REL_CREATE_STACK = "create stack";
public static final String LINK_REL_UPDATE_STACK = "update stack";
public static final String LINK_REL_REMOVE_STACK = "remove stack";
public static final String LINK_REL_GET_STACK_BY_ID = "get stack by id";
public static final String LINK_REL_SEARCH_STACKS = "search stacks";
public static final String LINK_REL_GET_ICON = "get icon link";
public static final String LINK_REL_UPLOAD_ICON = "upload icon link";
public static final String LINK_REL_DELETE_ICON = "delete icon link";

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.shared.dto.stack;
import org.eclipse.che.api.workspace.shared.stack.StackComponent;
import org.eclipse.che.dto.shared.DTO;
/** @author Alexander Andrienko */
@DTO
public interface StackComponentDto extends StackComponent {
void setName(String name);
StackComponentDto withName(String name);
void setVersion(String version);
StackComponentDto withVersion(String version);
}

View File

@ -1,64 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.shared.dto.stack;
import java.util.List;
import org.eclipse.che.api.core.rest.shared.dto.Hyperlinks;
import org.eclipse.che.api.core.rest.shared.dto.Link;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
import org.eclipse.che.api.workspace.shared.stack.Stack;
import org.eclipse.che.dto.shared.DTO;
/** @author Alexander Andrienko */
@DTO
public interface StackDto extends Stack, Hyperlinks {
void setId(String id);
StackDto withId(String id);
void setName(String name);
StackDto withName(String name);
void setDescription(String description);
StackDto withDescription(String description);
void setScope(String scope);
StackDto withScope(String scope);
void setCreator(String creator);
StackDto withCreator(String creator);
void setTags(List<String> tags);
StackDto withTags(List<String> tags);
@Override
WorkspaceConfigDto getWorkspaceConfig();
void setWorkspaceConfig(WorkspaceConfigDto workspaceConfigDto);
StackDto withWorkspaceConfig(WorkspaceConfigDto workspaceConfigDto);
@Override
List<StackComponentDto> getComponents();
void setComponents(List<StackComponentDto> components);
StackDto withComponents(List<StackComponentDto> components);
StackDto withLinks(List<Link> links);
}

View File

@ -1,72 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.shared.stack;
import java.util.List;
import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
import org.eclipse.che.commons.annotation.Nullable;
/**
* Defines the interface for managing stack of technologies.
*
* <p>Stack is the recipe/image/snapshot which declares workspace environment with certain
* components (technologies) and provides additional meta information for it.
*
* @author Alexander Andrienko
*/
public interface Stack {
/** Return the unique stack identifier. (e.g. "stack123"). */
String getId();
/** Return the unique stack name. (e.g. "Ruby on Rails"). */
String getName();
/** Return identifier of user who is the stack creator. */
String getCreator();
/** Returns the stack description, short information about the stack. */
@Nullable
String getDescription();
/**
* Return the scope of the stack.
*
* <p>There are two types of the scope:
*
* <ul>
* <li>"general" - when the stack defines common technology (e.g.: the stack "Java")
* <li>"advanced" - when the stack defines detailed(concrete) technology implementation (e.g:
* the stack "Java only with JRE")
* </ul>
*/
String getScope();
/** Return list technology tags. Tag links the stack with list Project Templates. */
List<String> getTags();
/**
* Return the {@link WorkspaceConfig} for creation workspace. This workspaceConfig can be used for
* store machine source, list predefined commands, projects etc.
*/
@Nullable
WorkspaceConfig getWorkspaceConfig();
/**
* Return the list of the components that stack consist of.
*
* @see StackComponent
* <p>Example: [{"name": "java", "version" : "1.8.45"}, {"name" : "maven", "version" :
* "3.3.1"}]
*/
List<? extends StackComponent> getComponents();
}

View File

@ -1,26 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.shared.stack;
/**
* Defines the interface that describes the stack component. It is a part of the {@link Stack}.
*
* @author Alexander Andrienko
*/
public interface StackComponent {
/** Returns the name of the component. The name is unique per stack. (e.g. "jdk"). */
String getName();
/** Returns the version of the component. (e.g. "1.8") */
String getVersion();
}

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.shared.stack;
/**
* Defines the interface that describes the stack source. It is a part of the {@link Stack}
*
* <p>Example: "source" : { "type":"image", "origin":"codenvy/ubuntu_jdk8" }
*
* @author Alexander Andrienko
*/
public interface StackSource {
/**
* Returns type for the StackSource.
*
* <p>There are three available types of the StackSource:
*
* <ul>
* <li>"recipe"
* <li>"image"
* <li>"location"
* </ul>
*/
String getType();
/**
* Returns origin data for the Stack Source. Origin data can be:
*
* <ul>
* <li>text/plain - when the type is "recipe" (e.g. "FROM codenvy/ubuntu_jdk8"})
* <li>image tag - when the type is "image" (e.g. "codenvy/ubuntu_jdk8")
* <li>url - when the type is "location" (e.g.
* "https://raw.githubusercontent.com/codenvy/dockerfiles/master/php/debian/Dockerfile")
* </ul>
*/
String getOrigin();
}

View File

@ -58,14 +58,6 @@
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-assistedinject</artifactId>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>io.opentracing</groupId>
<artifactId>opentracing-api</artifactId>

View File

@ -40,7 +40,6 @@ import org.eclipse.che.api.core.model.workspace.devfile.Source;
import org.eclipse.che.api.core.model.workspace.runtime.Machine;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
import org.eclipse.che.api.core.model.workspace.runtime.Server;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.shared.dto.CommandDto;
import org.eclipse.che.api.workspace.shared.dto.EnvironmentDto;
import org.eclipse.che.api.workspace.shared.dto.MachineConfigDto;
@ -67,9 +66,6 @@ import org.eclipse.che.api.workspace.shared.dto.devfile.EnvDto;
import org.eclipse.che.api.workspace.shared.dto.devfile.MetadataDto;
import org.eclipse.che.api.workspace.shared.dto.devfile.ProjectDto;
import org.eclipse.che.api.workspace.shared.dto.devfile.SourceDto;
import org.eclipse.che.api.workspace.shared.dto.stack.StackComponentDto;
import org.eclipse.che.api.workspace.shared.dto.stack.StackDto;
import org.eclipse.che.api.workspace.shared.stack.Stack;
/**
* Helps to convert to/from DTOs related to workspace.
@ -239,38 +235,6 @@ public final class DtoConverter {
.withAttributes(command.getAttributes());
}
/** Convert {@link StackImpl} to {@link StackDto}. */
public static StackDto asDto(Stack stack) {
WorkspaceConfigDto workspaceConfigDto = null;
if (stack.getWorkspaceConfig() != null) {
workspaceConfigDto = asDto(stack.getWorkspaceConfig());
}
List<StackComponentDto> componentsDto = null;
if (stack.getComponents() != null) {
componentsDto =
stack
.getComponents()
.stream()
.map(
component ->
newDto(StackComponentDto.class)
.withName(component.getName())
.withVersion(component.getVersion()))
.collect(toList());
}
return newDto(StackDto.class)
.withId(stack.getId())
.withName(stack.getName())
.withDescription(stack.getDescription())
.withCreator(stack.getCreator())
.withScope(stack.getScope())
.withTags(stack.getTags())
.withComponents(componentsDto)
.withWorkspaceConfig(workspaceConfigDto);
}
/** Converts {@link ProjectConfig} to {@link ProjectConfigDto}. */
public static ProjectConfigDto asDto(ProjectConfig projectCfg) {
final ProjectConfigDto projectConfigDto =

View File

@ -117,8 +117,6 @@ public class WorkspaceManager {
public WorkspaceImpl createWorkspace(
WorkspaceConfig config, String namespace, Map<String, String> attributes)
throws ServerException, NotFoundException, ConflictException, ValidationException {
TracingTags.STACK_ID.set(() -> attributes.getOrDefault("stackId", "no stack"));
requireNonNull(config, "Required non-null config");
requireNonNull(namespace, "Required non-null namespace");
validator.validateConfig(config);
@ -157,8 +155,6 @@ public class WorkspaceManager {
Map<String, String> attributes,
FileContentProvider contentProvider)
throws ServerException, NotFoundException, ConflictException, ValidationException {
TracingTags.STACK_ID.set(() -> attributes.getOrDefault("stackId", "no stack"));
requireNonNull(devfile, "Required non-null devfile");
requireNonNull(namespace, "Required non-null namespace");
validator.validateAttributes(attributes);
@ -347,10 +343,6 @@ public class WorkspaceManager {
}
Optional<WorkspaceImpl> workspaceOpt = workspaceDao.remove(workspaceId);
workspaceOpt.ifPresent(
workspace ->
TracingTags.STACK_ID.set(
workspace.getAttributes().getOrDefault("stackId", "no stack")));
LOG.info("Workspace '{}' removed by user '{}'", workspaceId, sessionUserNameOrUndefined());
}

View File

@ -389,7 +389,6 @@ public class WorkspaceRuntimes {
WorkspaceImpl workspace, @Nullable String envName, Map<String, String> options)
throws ConflictException, NotFoundException, ServerException {
TracingTags.WORKSPACE_ID.set(workspace.getId());
TracingTags.STACK_ID.set(() -> workspace.getAttributes().getOrDefault("stackId", "no stack"));
final String workspaceId = workspace.getId();
if (isStartRefused.get()) {
@ -469,7 +468,6 @@ public class WorkspaceRuntimes {
throws NotFoundException, ConflictException {
TracingTags.WORKSPACE_ID.set(workspace.getId());
TracingTags.STOPPED_BY.set(getStoppedBy(workspace));
TracingTags.STACK_ID.set(() -> workspace.getAttributes().getOrDefault("stackId", "no stack"));
String workspaceId = workspace.getId();
WorkspaceStatus status = statuses.get(workspaceId);

View File

@ -163,11 +163,7 @@ public class WorkspaceService extends Service {
value =
"Workspace attribute defined in 'attrName:attrValue' format. "
+ "The first ':' is considered as attribute name and value separator",
examples =
@Example({
@ExampleProperty("stackId:stack123"),
@ExampleProperty("attrName:value-with:colon")
}))
examples = @Example({@ExampleProperty("attrName:value-with:colon")}))
@QueryParam("attribute")
List<String> attrsList,
@ApiParam(
@ -231,11 +227,7 @@ public class WorkspaceService extends Service {
value =
"Workspace attribute defined in 'attrName:attrValue' format. "
+ "The first ':' is considered as attribute name and value separator",
examples =
@Example({
@ExampleProperty("stackId:stack123"),
@ExampleProperty("attrName:value-with:colon")
}))
examples = @Example({@ExampleProperty("attrName:value-with:colon")}))
@QueryParam("attribute")
List<String> attrsList,
@ApiParam(

View File

@ -1,33 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.event;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.core.db.cascade.event.RemoveEvent;
/**
* Pre-removal event of {@link StackImpl}.
*
* @author Max Shaposhnik
*/
public class BeforeStackRemovedEvent extends RemoveEvent {
private final StackImpl stack;
public BeforeStackRemovedEvent(StackImpl stack) {
this.stack = stack;
}
public StackImpl getStack() {
return stack;
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.event;
import org.eclipse.che.api.core.notification.EventOrigin;
import org.eclipse.che.api.workspace.shared.stack.Stack;
import org.eclipse.che.core.db.cascade.event.PersistEvent;
/**
* Published after stack instance is persisted.
*
* @author Yevhenii Voevodin
*/
@EventOrigin("stack")
public class StackPersistedEvent extends PersistEvent {
private final Stack stack;
public StackPersistedEvent(Stack stack) {
this.stack = stack;
}
public Stack getStack() {
return stack;
}
}

View File

@ -1,165 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.jpa;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import com.google.inject.persist.Transactional;
import java.util.List;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import org.eclipse.che.api.core.ApiException;
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.notification.EventService;
import org.eclipse.che.api.workspace.server.event.BeforeStackRemovedEvent;
import org.eclipse.che.api.workspace.server.event.StackPersistedEvent;
import org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.core.db.jpa.DuplicateKeyException;
/**
* JPA based implementation of {@link StackDao}.
*
* @author Yevhenii Voevodin
*/
@Singleton
public class JpaStackDao implements StackDao {
@Inject private Provider<EntityManager> managerProvider;
@Inject private EventService eventService;
@Override
public void create(StackImpl stack) throws ConflictException, ServerException {
requireNonNull(stack, "Required non-null stack");
try {
doCreate(stack);
} catch (DuplicateKeyException x) {
throw new ConflictException(
format("Stack with id '%s' or name '%s' already exists", stack.getId(), stack.getName()));
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Override
@Transactional
public StackImpl getById(String id) throws NotFoundException, ServerException {
requireNonNull(id, "Required non-null id");
try {
final StackImpl stack = managerProvider.get().find(StackImpl.class, id);
if (stack == null) {
throw new NotFoundException(format("Stack with id '%s' doesn't exist", id));
}
return new StackImpl(stack);
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Override
public void remove(String id) throws ServerException {
requireNonNull(id, "Required non-null id");
try {
doRemove(id);
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Override
public StackImpl update(StackImpl update)
throws NotFoundException, ServerException, ConflictException {
requireNonNull(update, "Required non-null update");
try {
return new StackImpl(doUpdate(update));
} catch (DuplicateKeyException x) {
throw new ConflictException(format("Stack with name '%s' already exists", update.getName()));
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Override
@Transactional
public List<StackImpl> searchStacks(
@Nullable String user, @Nullable List<String> tags, int skipCount, int maxItems)
throws ServerException {
final TypedQuery<StackImpl> query;
if (tags == null || tags.isEmpty()) {
query = managerProvider.get().createNamedQuery("Stack.getAll", StackImpl.class);
} else {
query =
managerProvider
.get()
.createNamedQuery("Stack.getByTags", StackImpl.class)
.setParameter("tags", tags)
.setParameter("tagsSize", tags.size());
}
try {
return query
.setMaxResults(maxItems)
.setFirstResult(skipCount)
.getResultList()
.stream()
.map(StackImpl::new)
.collect(Collectors.toList());
} catch (RuntimeException x) {
throw new ServerException(x.getLocalizedMessage(), x);
}
}
@Transactional(rollbackOn = {RuntimeException.class, ApiException.class})
protected void doCreate(StackImpl stack) throws ConflictException, ServerException {
if (stack.getWorkspaceConfig() != null) {
stack.getWorkspaceConfig().getProjects().forEach(ProjectConfigImpl::prePersistAttributes);
}
EntityManager manager = managerProvider.get();
manager.persist(stack);
manager.flush();
eventService.publish(new StackPersistedEvent(stack)).propagateException();
}
@Transactional(rollbackOn = {RuntimeException.class, ServerException.class})
protected void doRemove(String id) throws ServerException {
final EntityManager manager = managerProvider.get();
final StackImpl stack = manager.find(StackImpl.class, id);
if (stack != null) {
eventService.publish(new BeforeStackRemovedEvent(new StackImpl(stack))).propagateException();
manager.remove(stack);
manager.flush();
}
}
@Transactional
protected StackImpl doUpdate(StackImpl update) throws NotFoundException {
final EntityManager manager = managerProvider.get();
if (manager.find(StackImpl.class, update.getId()) == null) {
throw new NotFoundException(format("Workspace with id '%s' doesn't exist", update.getId()));
}
if (update.getWorkspaceConfig() != null) {
update.getWorkspaceConfig().getProjects().forEach(ProjectConfigImpl::prePersistAttributes);
}
StackImpl merged = manager.merge(update);
manager.flush();
return merged;
}
}

View File

@ -13,7 +13,6 @@ package org.eclipse.che.api.workspace.server.jpa;
import com.google.inject.AbstractModule;
import org.eclipse.che.api.workspace.server.jpa.JpaWorkspaceDao.RemoveWorkspaceBeforeAccountRemovedEventSubscriber;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.spi.WorkspaceDao;
/** @author Yevhenii Voevodin */
@ -21,7 +20,6 @@ public class WorkspaceJpaModule extends AbstractModule {
@Override
protected void configure() {
bind(StackDao.class).to(JpaStackDao.class);
bind(WorkspaceDao.class).to(JpaWorkspaceDao.class);
bind(RemoveWorkspaceBeforeAccountRemovedEventSubscriber.class).asEagerSingleton();
}

View File

@ -1,86 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.model.impl.stack;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import org.eclipse.che.api.workspace.shared.stack.StackComponent;
/**
* OldServer implementation of {@link StackComponent}
*
* @author Alexander Andrienko
*/
@Embeddable
public class StackComponentImpl implements StackComponent {
@Column(name = "name")
private String name;
@Column(name = "version")
private String version;
public StackComponentImpl() {}
public StackComponentImpl(StackComponent stackComponent) {
this(stackComponent.getName(), stackComponent.getVersion());
}
public StackComponentImpl(String name, String version) {
this.name = name;
this.version = version;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof StackComponentImpl)) {
return false;
}
StackComponentImpl another = (StackComponentImpl) obj;
return Objects.equals(name, another.name) && Objects.equals(version, another.version);
}
@Override
public int hashCode() {
int hash = 7;
hash = hash * 31 + Objects.hashCode(name);
hash = hash * 31 + Objects.hashCode(version);
return hash;
}
@Override
public String toString() {
return "StackComponentImpl{" + "name='" + name + '\'' + ", version='" + version + '\'' + '}';
}
}

View File

@ -1,375 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.model.impl.stack;
import static java.util.stream.Collectors.toList;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.api.workspace.server.stack.image.StackIcon;
import org.eclipse.che.api.workspace.shared.stack.Stack;
import org.eclipse.che.api.workspace.shared.stack.StackComponent;
import org.eclipse.che.api.workspace.shared.stack.StackSource;
import org.eclipse.che.commons.lang.NameGenerator;
/**
* Data object for {@link Stack}.
*
* @author Alexander Andrienko
* @author Yevhenii Voevodin
*/
@Entity(name = "Stack")
@NamedQueries({
@NamedQuery(
name = "Stack.getByTags",
query =
"SELECT stack "
+ "FROM Stack stack, stack.tags tag "
+ "WHERE tag IN :tags "
+ "GROUP BY stack.id "
+ "HAVING COUNT(tag) = :tagsSize"),
@NamedQuery(name = "Stack.getAll", query = "SELECT stack FROM Stack stack")
})
@Table(name = "stack")
public class StackImpl implements Stack {
public static StackBuilder builder() {
return new StackBuilder();
}
@Id
@Column(name = "id")
private String id;
@Column(name = "name", unique = true, nullable = false)
private String name;
@Column(name = "description", columnDefinition = "TEXT")
private String description;
@Column(name = "scope")
private String scope;
@Column(name = "creator")
private String creator;
@ElementCollection
@Column(name = "tag")
@CollectionTable(name = "stack_tags", joinColumns = @JoinColumn(name = "stack_id"))
private List<String> tags;
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "workspaceconfig_id")
private WorkspaceConfigImpl workspaceConfig;
@ElementCollection
@CollectionTable(name = "stack_components", joinColumns = @JoinColumn(name = "stack_id"))
private List<StackComponentImpl> components;
@Embedded private StackIcon stackIcon;
public StackImpl() {}
public StackImpl(StackImpl stack) {
this(
stack.getId(),
stack.getName(),
stack.getDescription(),
stack.getScope(),
stack.getCreator(),
stack.getTags(),
stack.getWorkspaceConfig(),
stack.getComponents(),
stack.getStackIcon());
}
public StackImpl(Stack stack) {
this(
stack.getId(),
stack.getName(),
stack.getDescription(),
stack.getScope(),
stack.getCreator(),
stack.getTags(),
stack.getWorkspaceConfig(),
stack.getComponents(),
null);
}
public StackImpl(
String id,
String name,
String description,
String scope,
String creator,
List<String> tags,
WorkspaceConfig workspaceConfig,
List<? extends StackComponent> components,
StackIcon stackIcon) {
this.id = id;
this.creator = creator;
this.name = name;
this.scope = scope;
this.description = description;
if (stackIcon != null) {
this.stackIcon = new StackIcon(stackIcon);
}
if (tags != null) {
this.tags = new ArrayList<>(tags);
}
if (workspaceConfig != null) {
this.workspaceConfig = new WorkspaceConfigImpl(workspaceConfig);
}
if (components != null) {
this.components = components.stream().map(StackComponentImpl::new).collect(toList());
}
}
@Override
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
@Override
public String getCreator() {
return creator;
}
public void setCreator(String creator) {
this.creator = creator;
}
@Override
public List<String> getTags() {
if (tags == null) {
tags = new ArrayList<>();
}
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
@Override
public WorkspaceConfigImpl getWorkspaceConfig() {
return workspaceConfig;
}
public void setWorkspaceConfig(WorkspaceConfigImpl workspaceConfig) {
this.workspaceConfig = workspaceConfig;
}
@Override
public List<StackComponentImpl> getComponents() {
if (components == null) {
components = new ArrayList<>();
}
return components;
}
public void setComponents(List<StackComponentImpl> components) {
this.components = components;
}
public StackIcon getStackIcon() {
return stackIcon;
}
public void setStackIcon(StackIcon stackIcon) {
this.stackIcon = stackIcon;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof StackImpl)) {
return false;
}
final StackImpl that = (StackImpl) obj;
return Objects.equals(id, that.id)
&& Objects.equals(name, that.name)
&& Objects.equals(description, that.description)
&& Objects.equals(scope, that.scope)
&& Objects.equals(creator, that.creator)
&& getTags().equals(that.getTags())
&& Objects.equals(workspaceConfig, that.workspaceConfig)
&& getComponents().equals(that.getComponents())
&& Objects.equals(stackIcon, that.stackIcon);
}
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + Objects.hashCode(id);
hash = 31 * hash + Objects.hashCode(name);
hash = 31 * hash + Objects.hashCode(description);
hash = 31 * hash + Objects.hashCode(scope);
hash = 31 * hash + Objects.hashCode(creator);
hash = 31 * hash + getTags().hashCode();
hash = 31 * hash + Objects.hashCode(workspaceConfig);
hash = 31 * hash + getComponents().hashCode();
hash = 31 * hash + Objects.hashCode(stackIcon);
return hash;
}
@Override
public String toString() {
return "StackImpl{"
+ "id='"
+ id
+ '\''
+ ", name='"
+ name
+ '\''
+ ", description='"
+ description
+ '\''
+ ", scope='"
+ scope
+ '\''
+ ", creator='"
+ creator
+ '\''
+ ", tags="
+ tags
+ ", workspaceConfig="
+ workspaceConfig
+ ", components="
+ components
+ ", stackIcon="
+ stackIcon
+ '}';
}
public static class StackBuilder {
private String id;
private String name;
private String description;
private String scope;
private String creator;
private List<String> tags;
private WorkspaceConfig workspaceConfig;
private StackSource source;
private List<? extends StackComponent> components;
private StackIcon stackIcon;
public StackBuilder generateId() {
id = NameGenerator.generate("stack", 16);
return this;
}
public StackBuilder setId(String id) {
this.id = id;
return this;
}
public StackBuilder setName(String name) {
this.name = name;
return this;
}
public StackBuilder setDescription(String description) {
this.description = description;
return this;
}
public StackBuilder setScope(String scope) {
this.scope = scope;
return this;
}
public StackBuilder setCreator(String creator) {
this.creator = creator;
return this;
}
public StackBuilder setTags(List<String> tags) {
this.tags = (tags == null) ? new ArrayList<>() : tags;
return this;
}
public StackBuilder setWorkspaceConfig(WorkspaceConfig workspaceConfig) {
this.workspaceConfig = workspaceConfig;
return this;
}
public StackBuilder setSource(StackSource source) {
this.source = source;
return this;
}
public StackBuilder setComponents(List<? extends StackComponent> components) {
this.components = (components == null) ? new ArrayList<>() : components;
return this;
}
public StackBuilder setStackIcon(StackIcon stackIcon) {
this.stackIcon = stackIcon;
return this;
}
public StackImpl build() {
return new StackImpl(
id, name, description, scope, creator, tags, workspaceConfig, components, stackIcon);
}
}
}

View File

@ -1,107 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.spi;
import java.util.List;
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.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.commons.annotation.Nullable;
/**
* Defines data access object for {@link StackImpl}
*
* @author Alexander Andrienko
*/
public interface StackDao {
/**
* Create new Stack.
*
* @param stack stack to create
* @throws NullPointerException when {@code stack} is null
* @throws ConflictException when stack with id equal to {@code stack.getId()} is already exist
* @throws ServerException when any error occurs
*/
void create(StackImpl stack) throws ConflictException, ServerException;
/**
* Return existing stack by specified {@code id} or throws {@link NotFoundException} when stack
* with such identifier doesn't exist.
*
* @param id the stack id
* @throws NullPointerException when {@code id} is null
* @throws NotFoundException if stack with {@code id} was not found
* @throws ServerException when any error occurs
*/
StackImpl getById(String id) throws NotFoundException, ServerException;
/**
* Remove the stack by specified {@code id}.
*
* @param id stack identifier to remove stack
* @throws NullPointerException when {@code id} is null
* @throws ServerException when any error occurs
*/
void remove(String id) throws ServerException;
/**
* Update stack with new entity, actually replaces(not merges) existed stack.
*
* <p>Existed stack will be fully updated(replaced), all data which wos present before update will
* not be accessible with {@code update} anymore Expected update usage:
*
* <pre>
* StackImpl stack = stackDao.getById("stack111");
* ...
* stack.setDescription("Java stack);
* ...
* stackDao.update(stack);
* </pre>
*
* @param update the stack for update
* @throws NullPointerException when {@code update} is null
* @throws NotFoundException when stack with {@code update.getId()} doesn't exist
* @throws ConflictException when stack with such name already exists
* @throws ServerException when any error occurs
*/
StackImpl update(StackImpl update) throws NotFoundException, ConflictException, ServerException;
/**
* Returns those stacks which match the following statements:
*
* <ul>
* <li>If neither {@code user} no {@code tags} are specified(null values passed to the method)
* then all the stacks which contain 'search' action in {@link StackImpl#getPublicActions()
* public actions} are returned
* <li>If {@code user} is specified then all the stacks which contain 'search' action in stack
* public actions(like defined by previous list item) or those which specify 'search' action
* in access control entry for given {@code user} are returned
* <li>Finally, if {@code tags} are specified then the stacks which match 2 rules above, will be
* filtered by the {@code tags}, stack should contain all of the {@code tags} to be in a
* result list.
* </ul>
*
* @param user user id for permission checking
* @param tags stack tags to search stacks, may be {@code null}
* @param skipCount count of items which should be skipped, if found items contain fewer than
* {@code skipCount} items then return empty list items
* @param maxItems max count of items to fetch
* @return list stacks which contains all of specified {@code tags}
* @throws ServerException when any error occurs
* @throws IllegalArgumentException when {@code skipCount} or {@code maxItems} is negative
*/
List<StackImpl> searchStacks(
@Nullable String user, @Nullable List<String> tags, int skipCount, int maxItems)
throws ServerException;
}

View File

@ -1,148 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.stack;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.commons.io.IOUtils;
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.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.stack.image.StackIcon;
import org.eclipse.che.api.workspace.shared.stack.Stack;
import org.eclipse.che.commons.lang.IoUtil;
import org.eclipse.che.core.db.DBInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class for loading list predefined {@link Stack} to the {@link StackDao} and set {@link StackIcon}
* to the predefined stack.
*
* @author Alexander Andrienko
* @author Sergii Leshchenko
* @author Anton Korneta
*/
@Singleton
public class StackLoader {
public static final String CHE_PREDEFINED_STACKS = "che.predefined.stacks";
private static final Logger LOG = LoggerFactory.getLogger(StackLoader.class);
protected final StackDao stackDao;
private final Gson GSON;
private final Map<String, String> stacks2images;
private final DBInitializer dbInitializer;
private final Boolean reloadStacksOnStart;
@Inject
@SuppressWarnings("unused")
public StackLoader(
@Named("che.predefined.stacks.reload_on_start") boolean reloadStacksOnStart,
@Named(CHE_PREDEFINED_STACKS) Map<String, String> stacks2images,
StackDao stackDao,
DBInitializer dbInitializer) {
this.reloadStacksOnStart = reloadStacksOnStart;
this.stacks2images = stacks2images;
this.stackDao = stackDao;
this.dbInitializer = dbInitializer;
GSON = new GsonBuilder().create();
}
/** Load predefined stacks with their icons to the {@link StackDao}. */
@PostConstruct
public void start() {
final boolean override;
if (reloadStacksOnStart) {
LOG.warn("Reload stacks on start is deprecated policy, and it will be removed soon");
override = true;
} else {
override = dbInitializer.isBareInit();
}
if (override) {
for (Map.Entry<String, String> stack2image : stacks2images.entrySet()) {
final String stackFile = stack2image.getKey();
final String imagesDir = stack2image.getValue();
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(IoUtil.getResource(stackFile)))) {
List<StackImpl> stacks =
GSON.fromJson(reader, new TypeToken<List<StackImpl>>() {}.getType());
final Path imagesDirPath = !isNullOrEmpty(imagesDir) ? Paths.get(imagesDir) : null;
stacks.forEach(stack -> loadStack(stack, imagesDirPath));
} catch (Exception ex) {
LOG.error("Failed to store stacks from '{}'", stackFile);
}
}
LOG.info("Stacks initialization finished");
}
}
protected void loadStack(StackImpl stack, Path imagePath) {
setIconData(stack, imagePath);
try {
try {
stackDao.update(stack);
} catch (NotFoundException ex) {
stackDao.create(stack);
}
} catch (ServerException | ConflictException ex) {
LOG.warn(format("Failed to load stack with id '%s' ", stack.getId()), ex.getMessage());
}
}
/**
* Searches for stack icon and set image data into given stack.
*
* @param stack stack for icon setup
* @param stackIconFolderPath path to icon folder
*/
protected void setIconData(StackImpl stack, Path stackIconFolderPath) {
StackIcon stackIcon = stack.getStackIcon();
if (stackIcon == null) {
return;
}
if (stackIconFolderPath == null) {
stack.setStackIcon(null);
LOG.warn("No configured image found for stack {}", stack.getId());
return;
}
try {
final Path stackIconPath = stackIconFolderPath.resolve(stackIcon.getName());
final byte[] imageData = IOUtils.toByteArray(IoUtil.getResource(stackIconPath.toString()));
stackIcon = new StackIcon(stackIcon.getName(), stackIcon.getMediaType(), imageData);
stack.setStackIcon(stackIcon);
} catch (IOException ex) {
stack.setStackIcon(null);
LOG.error(
format("Failed to load stack icon data for the stack with id '%s'", stack.getId()), ex);
}
}
}

View File

@ -1,364 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.stack;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.MediaType.MULTIPART_FORM_DATA;
import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
import static javax.ws.rs.core.Response.Status.CREATED;
import static org.eclipse.che.api.workspace.server.DtoConverter.asDto;
import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_CREATE_STACK;
import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_DELETE_ICON;
import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_GET_ICON;
import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_GET_STACK_BY_ID;
import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_REMOVE_STACK;
import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_SEARCH_STACKS;
import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_UPDATE_STACK;
import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_UPLOAD_ICON;
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 java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
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.Response;
import javax.ws.rs.core.UriBuilder;
import org.apache.commons.fileupload.FileItem;
import org.eclipse.che.api.core.ApiException;
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.rest.Service;
import org.eclipse.che.api.core.rest.annotations.GenerateLink;
import org.eclipse.che.api.core.rest.shared.dto.Link;
import org.eclipse.che.api.core.util.LinksHelper;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.stack.image.StackIcon;
import org.eclipse.che.api.workspace.shared.dto.stack.StackDto;
import org.eclipse.che.commons.env.EnvironmentContext;
/**
* Defines Stack REST API
*
* @author Alexander Andrienko
*/
@Api(value = "/stack", description = "Stack REST API")
@Path("/stack")
public class StackService extends Service {
private final StackDao stackDao;
private final StackValidator stackValidator;
@Inject
public StackService(StackDao stackDao, StackValidator stackValidator) {
this.stackDao = stackDao;
this.stackValidator = stackValidator;
}
@POST
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
@GenerateLink(rel = LINK_REL_CREATE_STACK)
@ApiOperation(
value = "Create a new stack",
notes = "This operation can be performed only by authorized user",
response = StackDto.class)
@ApiResponses({
@ApiResponse(code = 201, message = "The stack successfully created"),
@ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
@ApiResponse(code = 403, message = "The user does not have access to create a new stack"),
@ApiResponse(
code = 409,
message =
"Conflict error occurred during the stack creation"
+ "(e.g. The stack with such name already exists)"),
@ApiResponse(code = 500, message = "Internal server error occurred")
})
public Response createStack(@ApiParam("The new stack") final StackDto stackDto)
throws ApiException {
stackValidator.check(stackDto);
final String userId = EnvironmentContext.getCurrent().getSubject().getUserId();
final StackImpl newStack =
StackImpl.builder()
.generateId()
.setName(stackDto.getName())
.setDescription(stackDto.getDescription())
.setScope(stackDto.getScope())
.setCreator(userId)
.setTags(stackDto.getTags())
.setWorkspaceConfig(stackDto.getWorkspaceConfig())
.setComponents(stackDto.getComponents())
.build();
stackDao.create(newStack);
return Response.status(CREATED).entity(asStackDto(newStack)).build();
}
@GET
@Path("/{id}")
@Produces(APPLICATION_JSON)
@GenerateLink(rel = LINK_REL_GET_STACK_BY_ID)
@ApiOperation(
value = "Get the stack by id",
notes = "This operation can be performed for stack owner, or for predefined stacks")
@ApiResponses({
@ApiResponse(code = 200, message = "The response contains requested stack entity"),
@ApiResponse(code = 404, message = "The requested stack was not found"),
@ApiResponse(code = 403, message = "The user has not permission get requested stack"),
@ApiResponse(code = 500, message = "Internal server error occurred")
})
public StackDto getStack(@ApiParam("The stack id") @PathParam("id") final String id)
throws ApiException {
return asStackDto(stackDao.getById(id));
}
@PUT
@Path("/{id}")
@Produces(APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
@GenerateLink(rel = LINK_REL_UPDATE_STACK)
@ApiOperation(
value =
"Update the stack by replacing all the existing data (exclude field \"creator\") with update")
@ApiResponses({
@ApiResponse(code = 200, message = "The stack successfully updated"),
@ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
@ApiResponse(code = 403, message = "The user does not have access to update the stack"),
@ApiResponse(
code = 409,
message =
"Conflict error occurred during stack update"
+ "(e.g. Stack with such name already exists)"),
@ApiResponse(code = 500, message = "Internal server error occurred")
})
public StackDto updateStack(
@ApiParam(value = "The stack update", required = true) final StackDto updateDto,
@ApiParam(value = "The stack id", required = true) @PathParam("id") final String id)
throws ApiException {
stackValidator.check(updateDto);
final StackImpl stack = stackDao.getById(id);
StackImpl stackForUpdate =
StackImpl.builder()
.setId(id)
.setName(updateDto.getName())
.setDescription(updateDto.getDescription())
.setScope(updateDto.getScope())
// user can't edit creator
.setCreator(stack.getCreator())
.setTags(updateDto.getTags())
.setWorkspaceConfig(updateDto.getWorkspaceConfig())
.setComponents(updateDto.getComponents())
.build();
return asStackDto(stackDao.update(stackForUpdate));
}
@DELETE
@Path("/{id}")
@GenerateLink(rel = LINK_REL_REMOVE_STACK)
@ApiOperation(value = "Removes the stack")
@ApiResponses({
@ApiResponse(code = 204, message = "The stack successfully removed"),
@ApiResponse(code = 403, message = "The user does not have access to remove the stack"),
@ApiResponse(code = 404, message = "The stack doesn't exist"),
@ApiResponse(code = 500, message = "Internal server error occurred")
})
public void removeStack(@ApiParam("The stack id") @PathParam("id") final String id)
throws ApiException {
stackDao.remove(id);
}
@GET
@Produces(APPLICATION_JSON)
@GenerateLink(rel = LINK_REL_SEARCH_STACKS)
@ApiOperation(
value = "Get the list stacks with required tags",
notes = "This operation can be performed only by authorized user",
response = StackDto.class,
responseContainer = "List")
@ApiResponses({
@ApiResponse(
code = 200,
message = "The response contains requested list stack entity with required tags"),
@ApiResponse(
code = 403,
message = "The user does not have access to get stack entity list with required tags"),
@ApiResponse(code = 500, message = "Internal server error occurred")
})
public List<StackDto> searchStacks(
@ApiParam("List tags for search") @QueryParam("tags") final List<String> tags,
@ApiParam(value = "The number of the items to skip")
@DefaultValue("0")
@QueryParam("skipCount")
final Integer skipCount,
@ApiParam("The limit of the items in the response, default is 30")
@DefaultValue("30")
@QueryParam("maxItems")
final Integer maxItems)
throws ServerException {
final String currentUser = EnvironmentContext.getCurrent().getSubject().getUserId();
return stackDao
.searchStacks(currentUser, tags, skipCount, maxItems)
.stream()
.map(this::asStackDto)
.collect(Collectors.toList());
}
@GET
@Path("/{id}/icon")
@Produces("image/*")
@GenerateLink(rel = LINK_REL_GET_ICON)
@ApiOperation(
value = "Get icon by stack id",
notes = "This operation can be performed only by authorized user",
response = byte[].class)
@ApiResponses({
@ApiResponse(code = 200, message = "The response contains requested image entity"),
@ApiResponse(code = 403, message = "The user does not have access to get image entity"),
@ApiResponse(code = 500, message = "Internal server error occurred")
})
public Response getIcon(@ApiParam("The stack id") @PathParam("id") final String id)
throws NotFoundException, ServerException, BadRequestException {
StackImpl stack = stackDao.getById(id);
if (stack == null) {
throw new NotFoundException("Stack with id '" + id + "' was not found.");
}
StackIcon image = stack.getStackIcon();
if (image == null) {
throw new NotFoundException("Image for stack with id '" + id + "' was not found.");
}
return Response.ok(image.getData(), image.getMediaType()).build();
}
@POST
@Path("/{id}/icon")
@Consumes(MULTIPART_FORM_DATA)
@Produces(TEXT_PLAIN)
@GenerateLink(rel = LINK_REL_UPLOAD_ICON)
@ApiOperation(
value = "Upload icon for required stack",
notes = "This operation can be performed only by authorized stack owner")
@ApiResponses({
@ApiResponse(code = 200, message = "Image was successfully uploaded"),
@ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
@ApiResponse(
code = 403,
message = "The user does not have access upload image for stack with required id"),
@ApiResponse(code = 404, message = "The stack doesn't exist"),
@ApiResponse(code = 500, message = "Internal server error occurred")
})
public Response uploadIcon(
@ApiParam("The image for stack") final Iterator<FileItem> formData,
@ApiParam("The stack id") @PathParam("id") final String id)
throws NotFoundException, ServerException, BadRequestException, ForbiddenException,
ConflictException {
if (formData.hasNext()) {
FileItem fileItem = formData.next();
StackIcon stackIcon =
new StackIcon(fileItem.getName(), fileItem.getContentType(), fileItem.get());
StackImpl stack = stackDao.getById(id);
stack.setStackIcon(stackIcon);
stackDao.update(stack);
}
return Response.ok().build();
}
@DELETE
@Path("/{id}/icon")
@GenerateLink(rel = LINK_REL_DELETE_ICON)
@ApiOperation(
value = "Delete icon for required stack",
notes = "This operation can be performed only by authorized stack owner")
@ApiResponses({
@ApiResponse(code = 204, message = "Icon was successfully removed"),
@ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
@ApiResponse(
code = 403,
message = "The user does not have access upload image for stack with required id"),
@ApiResponse(code = 404, message = "The stack or icon doesn't exist"),
@ApiResponse(
code = 409,
message =
"Conflict error occurred during stack update"
+ "(e.g. Stack with such name already exists)"),
@ApiResponse(code = 500, message = "Internal server error occurred")
})
public void removeIcon(@ApiParam("The stack Id") @PathParam("id") final String id)
throws NotFoundException, ServerException, ConflictException, ForbiddenException,
BadRequestException {
StackImpl stack = stackDao.getById(id);
stack.setStackIcon(null);
stackDao.update(stack);
}
private StackDto asStackDto(StackImpl stack) {
final UriBuilder builder = getServiceContext().getServiceUriBuilder();
List<Link> links = new ArrayList<>();
final Link removeLink =
LinksHelper.createLink(
"DELETE",
builder.clone().path(getClass(), "removeStack").build(stack.getId()).toString(),
LINK_REL_REMOVE_STACK);
final Link getLink =
LinksHelper.createLink(
"GET",
builder.clone().path(getClass(), "getStack").build(stack.getId()).toString(),
APPLICATION_JSON,
LINK_REL_GET_STACK_BY_ID);
links.add(removeLink);
links.add(getLink);
StackIcon stackIcon = stack.getStackIcon();
if (stackIcon != null) {
Link deleteIcon =
LinksHelper.createLink(
"DELETE",
builder.clone().path(getClass(), "removeIcon").build(stack.getId()).toString(),
stackIcon.getMediaType(),
LINK_REL_DELETE_ICON);
Link getIconLink =
LinksHelper.createLink(
"GET",
builder.clone().path(getClass(), "getIcon").build(stack.getId()).toString(),
stackIcon.getMediaType(),
LINK_REL_GET_ICON);
links.add(deleteIcon);
links.add(getIconLink);
}
return asDto(stack).withLinks(links);
}
}

View File

@ -1,59 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.stack;
import javax.inject.Inject;
import javax.inject.Singleton;
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.ValidationException;
import org.eclipse.che.api.workspace.server.WorkspaceValidator;
import org.eclipse.che.api.workspace.shared.stack.Stack;
/**
* Validator for {@link Stack} objects
*
* @author Mihail Kuznyetsov
*/
@Singleton
public class StackValidator {
@Inject private WorkspaceValidator wsValidator;
/**
* Validate stack object
*
* @param stack stack to validate
* @throws BadRequestException if stack is not valid
*/
public void check(Stack stack) throws BadRequestException, ServerException, NotFoundException {
if (stack == null) {
throw new BadRequestException("Required non-null stack");
}
if (stack.getName() == null || stack.getName().isEmpty()) {
throw new BadRequestException("Required non-null and non-empty stack name");
}
if (stack.getScope() == null
|| !stack.getScope().equals("general") && !stack.getScope().equals("advanced")) {
throw new BadRequestException("Required non-null scope value: 'general' or 'advanced'");
}
if (stack.getWorkspaceConfig() == null) {
throw new BadRequestException("Workspace config required");
}
try {
wsValidator.validateConfig(stack.getWorkspaceConfig());
} catch (ValidationException x) {
throw new BadRequestException(x.getMessage());
}
}
}

View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.stack.image;
import com.google.common.base.Objects;
import java.util.Arrays;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import org.eclipse.che.commons.annotation.Nullable;
/**
* Class for storing {@link org.eclipse.che.api.workspace.shared.stack.Stack} icon data
*
* @author Alexander Andrienko
*/
@Embeddable
public class StackIcon {
@Column(name = "icon_name")
private String name;
@Column(name = "mediatype")
private String mediaType;
@Column(name = "data")
private byte[] data;
public StackIcon() {}
public StackIcon(String name, String mediaType, @Nullable byte[] data) {
this.data = data;
this.mediaType = mediaType;
this.name = name;
}
public StackIcon(StackIcon icon) {
this(icon.name, icon.mediaType, Arrays.copyOf(icon.data, icon.data.length));
}
public String getName() {
return name;
}
public String getMediaType() {
return mediaType;
}
public byte[] getData() {
return data;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof StackIcon)) {
return false;
}
StackIcon another = (StackIcon) obj;
return Objects.equal(name, another.name)
&& Objects.equal(mediaType, another.mediaType)
&& Arrays.equals(data, another.data);
}
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + Objects.hashCode(name);
hash = 31 * hash + Objects.hashCode(mediaType);
hash = 31 * hash + Arrays.hashCode(data);
return hash;
}
@Override
public String toString() {
return "StackIcon{"
+ "name='"
+ name
+ '\''
+ ", mediaType='"
+ mediaType
+ '\''
+ ", data=[byte array]"
+ '}';
}
}

View File

@ -167,7 +167,6 @@ public class WorkspaceServiceTest {
SECURE_PATH
+ "/workspace"
+ "?namespace=test"
+ "&attribute=stackId:stack123"
+ "&attribute=factoryId:factory123"
+ "&attribute=custom:custom:value");
@ -180,7 +179,6 @@ public class WorkspaceServiceTest {
eq("test"),
eq(
ImmutableMap.of(
"stackId", "stack123",
"factoryId", "factory123",
"custom", "custom:value")));
}
@ -206,7 +204,6 @@ public class WorkspaceServiceTest {
SECURE_PATH
+ "/workspace/devfile"
+ "?namespace=test"
+ "&attribute=stackId:stack123"
+ "&attribute=factoryId:factory123"
+ "&attribute=custom:custom:value");
@ -219,7 +216,6 @@ public class WorkspaceServiceTest {
eq("test"),
eq(
ImmutableMap.of(
"stackId", "stack123",
"factoryId", "factory123",
"custom", "custom:value")),
any());
@ -245,7 +241,6 @@ public class WorkspaceServiceTest {
SECURE_PATH
+ "/workspace/devfile"
+ "?namespace=test"
+ "&attribute=stackId:stack123"
+ "&attribute=factoryId:factory123"
+ "&attribute=custom:custom:value");
@ -258,7 +253,6 @@ public class WorkspaceServiceTest {
eq("test"),
eq(
ImmutableMap.of(
"stackId", "stack123",
"factoryId", "factory123",
"custom", "custom:value")),
any());
@ -285,7 +279,6 @@ public class WorkspaceServiceTest {
SECURE_PATH
+ "/workspace/devfile"
+ "?namespace=test"
+ "&attribute=stackId:stack123"
+ "&attribute=factoryId:factory123"
+ "&attribute=custom:custom:value");
@ -314,8 +307,7 @@ public class WorkspaceServiceTest {
.post(
SECURE_PATH
+ "/workspace"
+ "?attribute=stackId:stack123"
+ "&attribute=factoryId:factory123"
+ "?attribute=factoryId:factory123"
+ "&attribute=custom:custom:value");
assertEquals(response.getStatusCode(), 201);
@ -327,7 +319,6 @@ public class WorkspaceServiceTest {
eq(NAMESPACE),
eq(
ImmutableMap.of(
"stackId", "stack123",
"factoryId", "factory123",
"custom", "custom:value")));
}
@ -348,8 +339,7 @@ public class WorkspaceServiceTest {
.post(
SECURE_PATH
+ "/workspace"
+ "?attribute=stackId:stack123"
+ "&attribute=factoryId:factory123"
+ "?attribute=factoryId:factory123"
+ "&attribute=custom:custom:value"
+ "&start-after-create=true");
@ -360,7 +350,6 @@ public class WorkspaceServiceTest {
anyString(),
eq(
ImmutableMap.of(
"stackId", "stack123",
"factoryId", "factory123",
"custom", "custom:value")));
}
@ -374,12 +363,12 @@ public class WorkspaceServiceTest {
.contentType("application/json")
.body(createConfigDto())
.when()
.post(SECURE_PATH + "/workspace?attribute=stackId=stack123");
.post(SECURE_PATH + "/workspace?attribute=factoryId=factoryId123");
assertEquals(response.getStatusCode(), 400);
assertEquals(
unwrapError(response),
"Attribute 'stackId=stack123' is not valid, "
"Attribute 'factoryId=factoryId123' is not valid, "
+ "it should contain name and value separated "
+ "with colon. For example: attributeName:attributeValue");
}
@ -407,11 +396,7 @@ public class WorkspaceServiceTest {
.body(configDto)
.when()
.post(
SECURE_PATH
+ "/workspace"
+ "?namespace=test"
+ "&attribute=stackId:stack123"
+ "&attribute=custom:custom:value");
SECURE_PATH + "/workspace" + "?namespace=test" + "&attribute=custom:custom:value");
assertEquals(response.getStatusCode(), 201);
String savedLocation =
@ -433,7 +418,7 @@ public class WorkspaceServiceTest {
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType("application/json")
.when()
.post(SECURE_PATH + "/workspace?attribute=stackId=stack123");
.post(SECURE_PATH + "/workspace");
assertEquals(response.getStatusCode(), 400);
assertEquals(unwrapError(response), "Workspace configuration required");

View File

@ -33,8 +33,6 @@ import org.eclipse.che.api.workspace.server.model.impl.devfile.EntrypointImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.EnvImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.ProjectImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.SourceImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.spi.WorkspaceDao;
import org.eclipse.che.commons.test.db.H2DBTestServer;
import org.eclipse.che.commons.test.db.H2JpaCleaner;
@ -70,7 +68,6 @@ public class WorkspaceTckModule extends TckModule {
MachineConfigImpl.class,
SourceStorageImpl.class,
ServerConfigImpl.class,
StackImpl.class,
CommandImpl.class,
RecipeImpl.class,
VolumeImpl.class,
@ -97,10 +94,8 @@ public class WorkspaceTckModule extends TckModule {
bind(new TypeLiteral<TckRepository<AccountImpl>>() {})
.toInstance(new JpaTckRepository<>(AccountImpl.class));
bind(new TypeLiteral<TckRepository<WorkspaceImpl>>() {}).toInstance(new WorkspaceRepository());
bind(new TypeLiteral<TckRepository<StackImpl>>() {}).toInstance(new StackRepository());
bind(WorkspaceDao.class).to(JpaWorkspaceDao.class);
bind(StackDao.class).to(JpaStackDao.class);
}
private static class WorkspaceRepository extends JpaTckRepository<WorkspaceImpl> {
@ -119,18 +114,4 @@ public class WorkspaceTckModule extends TckModule {
super.createAll(entities);
}
}
private static class StackRepository extends JpaTckRepository<StackImpl> {
public StackRepository() {
super(StackImpl.class);
}
@Override
public void createAll(Collection<? extends StackImpl> entities) throws TckRepositoryException {
for (StackImpl stack : entities) {
stack.getWorkspaceConfig().getProjects().forEach(ProjectConfigImpl::prePersistAttributes);
}
super.createAll(entities);
}
}
}

View File

@ -1,312 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.spi.tck;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static org.eclipse.che.api.workspace.server.spi.tck.WorkspaceDaoTest.createWorkspaceConfig;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import com.google.inject.Inject;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Stream;
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.notification.EventService;
import org.eclipse.che.api.workspace.server.event.BeforeStackRemovedEvent;
import org.eclipse.che.api.workspace.server.event.StackPersistedEvent;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackComponentImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.stack.image.StackIcon;
import org.eclipse.che.commons.test.tck.TckListener;
import org.eclipse.che.commons.test.tck.repository.TckRepository;
import org.eclipse.che.commons.test.tck.repository.TckRepositoryException;
import org.eclipse.che.core.db.cascade.CascadeEventSubscriber;
import org.eclipse.che.core.db.cascade.event.CascadeEvent;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* Tests {@link StackDao} contract.
*
* @author Yevhenii Voevodin
*/
@Listeners(TckListener.class)
@Test(suiteName = StackDaoTest.SUITE_NAME)
public class StackDaoTest {
public static final String SUITE_NAME = "StackDaoTck";
private static final int STACKS_SIZE = 5;
private StackImpl[] stacks;
@Inject private TckRepository<StackImpl> stackRepo;
@Inject private StackDao stackDao;
@Inject private EventService eventService;
@BeforeMethod
private void createStacks() throws TckRepositoryException {
stacks = new StackImpl[STACKS_SIZE];
for (int i = 0; i < STACKS_SIZE; i++) {
stacks[i] = createStack("stack-" + i, "name-" + i);
}
stackRepo.createAll(Stream.of(stacks).map(StackImpl::new).collect(toList()));
}
@AfterMethod
private void removeStacks() throws TckRepositoryException {
stackRepo.removeAll();
}
@Test
public void shouldGetById() throws Exception {
final StackImpl stack = stacks[0];
assertEquals(stackDao.getById(stack.getId()), stack);
}
@Test(expectedExceptions = NotFoundException.class)
public void shouldThrowNotFoundExceptionWhenGettingNonExistingStack() throws Exception {
stackDao.getById("non-existing-stack");
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowNpeWhenGettingStackByNullKey() throws Exception {
stackDao.getById(null);
}
@Test(dependsOnMethods = "shouldGetById")
public void shouldCreateStack() throws Exception {
final StackImpl stack = createStack("new-stack", "new-stack-name");
stackDao.create(stack);
assertEquals(stackDao.getById(stack.getId()), new StackImpl(stack));
}
@Test(
dependsOnMethods = "shouldThrowNotFoundExceptionWhenGettingNonExistingStack",
expectedExceptions = NotFoundException.class)
public void shouldNotCreateStackWhenSubscriberThrowsExceptionOnStackStoring() throws Exception {
final StackImpl stack = createStack("new-stack", "new-stack-name");
CascadeEventSubscriber<StackPersistedEvent> subscriber = mockCascadeEventSubscriber();
doThrow(new ConflictException("error")).when(subscriber).onCascadeEvent(any());
eventService.subscribe(subscriber, StackPersistedEvent.class);
try {
stackDao.create(stack);
fail("StackDao#create had to throw conflict exception");
} catch (ConflictException ignored) {
}
eventService.unsubscribe(subscriber, StackPersistedEvent.class);
stackDao.getById(stack.getId());
}
@Test(expectedExceptions = ConflictException.class)
public void shouldThrowConflictExceptionWhenCreatingStackWithIdThatAlreadyExists()
throws Exception {
final StackImpl stack = createStack(stacks[0].getId(), "new-name");
stackDao.create(stack);
}
@Test(expectedExceptions = ConflictException.class)
public void shouldThrowConflictExceptionWhenCreatingStackWithNameThatAlreadyExists()
throws Exception {
final StackImpl stack = createStack("new-stack-id", stacks[0].getName());
stackDao.create(stack);
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowNpeWhenCreatingNullStack() throws Exception {
stackDao.create(null);
}
@Test(
expectedExceptions = NotFoundException.class,
dependsOnMethods = "shouldThrowNotFoundExceptionWhenGettingNonExistingStack")
public void shouldRemoveStack() throws Exception {
final StackImpl stack = stacks[0];
stackDao.remove(stack.getId());
// Should throw an exception
stackDao.getById(stack.getId());
}
@Test(dependsOnMethods = "shouldGetById")
public void shouldNotRemoveStackWhenSubscriberThrowsExceptionOnStackRemoving() throws Exception {
final StackImpl stack = stacks[0];
CascadeEventSubscriber<BeforeStackRemovedEvent> subscriber = mockCascadeEventSubscriber();
doThrow(new ServerException("error")).when(subscriber).onCascadeEvent(any());
eventService.subscribe(subscriber, BeforeStackRemovedEvent.class);
try {
stackDao.remove(stack.getId());
fail("StackDao#remove had to throw server exception");
} catch (ServerException ignored) {
}
assertEquals(stackDao.getById(stack.getId()), stack);
eventService.unsubscribe(subscriber, BeforeStackRemovedEvent.class);
}
@Test
public void shouldNotThrowAnyExceptionWhenRemovingNonExistingStack() throws Exception {
stackDao.remove("non-existing");
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowNpeWhenRemovingNull() throws Exception {
stackDao.remove(null);
}
@Test(dependsOnMethods = "shouldGetById")
public void shouldUpdateStack() throws Exception {
final StackImpl stack = stacks[0];
stack.setName("new-name");
stack.setCreator("new-creator");
stack.setDescription("new-description");
stack.setScope("new-scope");
stack.getTags().clear();
stack.getTags().add("new-tag");
// Remove an existing component
stack.getComponents().remove(1);
// Add a new component
stack.getComponents().add(new StackComponentImpl("component3", "component3-version"));
// Update an existing component
final StackComponentImpl component = stack.getComponents().get(0);
component.setName("new-name");
component.setVersion("new-version");
// Set a new icon
stack.setStackIcon(new StackIcon("new-name", "new-media", "new-data".getBytes()));
stackDao.update(stack);
assertEquals(stackDao.getById(stack.getId()), new StackImpl(stack));
}
@Test(expectedExceptions = ConflictException.class)
public void shouldNotUpdateStackIfNewNameIsReserved() throws Exception {
final StackImpl stack = stacks[0];
stack.setName(stacks[1].getName());
stackDao.update(stack);
}
@Test(expectedExceptions = NotFoundException.class)
public void shouldThrowNotFoundExceptionWhenUpdatingNonExistingStack() throws Exception {
stackDao.update(createStack("new-stack", "new-stack-name"));
}
@Test(expectedExceptions = NullPointerException.class)
public void shouldThrowNpeWhenUpdatingNullStack() throws Exception {
stackDao.update(null);
}
@Test(dependsOnMethods = "shouldUpdateStack")
public void shouldFindStacksWithSpecifiedTags() throws Exception {
stacks[0].getTags().addAll(asList("search-tag1", "search-tag2"));
stacks[1].getTags().addAll(asList("search-tag1", "non-search-tag"));
stacks[2].getTags().addAll(asList("non-search-tag", "search-tag2"));
stacks[3].getTags().addAll(asList("search-tag1", "search-tag2", "another-tag"));
updateAll();
final List<StackImpl> found =
stackDao.searchStacks(null, asList("search-tag1", "search-tag2"), 0, 0);
found.forEach(s -> Collections.sort(s.getTags()));
for (StackImpl stack : stacks) {
Collections.sort(stack.getTags());
}
assertEquals(new HashSet<>(found), new HashSet<>(asList(stacks[0], stacks[3])));
}
@Test
public void shouldReturnAllStacksWhenSearchingWithoutTags() throws Exception {
final List<StackImpl> found = stackDao.searchStacks(null, null, 0, 0);
found.forEach(s -> Collections.sort(s.getTags()));
for (StackImpl stack : stacks) {
Collections.sort(stack.getTags());
}
assertEquals(new HashSet<>(found), new HashSet<>(asList(stacks)));
}
@Test
public void shouldPublishStackPersistedEventAfterStackIsPersisted() throws Exception {
final boolean[] isNotified = new boolean[] {false};
eventService.subscribe(event -> isNotified[0] = true, StackPersistedEvent.class);
stackDao.create(createStack("test", "test"));
assertTrue(isNotified[0], "Event subscriber notified");
}
private void updateAll() throws ConflictException, NotFoundException, ServerException {
for (StackImpl stack : stacks) {
stackDao.update(stack);
}
}
private static StackImpl createStack(String id, String name) {
final StackImpl stack =
StackImpl.builder()
.setId(id)
.setName(name)
.setCreator("user123")
.setDescription(id + "-description")
.setScope(id + "-scope")
.setTags(asList(id + "-tag1", id + "-tag2"))
.setComponents(
asList(
new StackComponentImpl(id + "-component1", id + "-component1-version"),
new StackComponentImpl(id + "-component2", id + "-component2-version")))
.setStackIcon(
new StackIcon(id + "-icon", id + "-media-type", "0x1234567890abcdef".getBytes()))
.build();
final WorkspaceConfigImpl config = createWorkspaceConfig("test");
stack.setWorkspaceConfig(config);
return stack;
}
private <T extends CascadeEvent> CascadeEventSubscriber<T> mockCascadeEventSubscriber() {
@SuppressWarnings("unchecked")
CascadeEventSubscriber<T> subscriber = mock(CascadeEventSubscriber.class);
doCallRealMethod().when(subscriber).onEvent(any());
return subscriber;
}
}

View File

@ -1,229 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.stack;
import static java.util.Collections.singletonMap;
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
import static org.eclipse.che.dto.server.DtoFactory.newDto;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.rest.shared.dto.Link;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.shared.dto.CommandDto;
import org.eclipse.che.api.workspace.shared.dto.EnvironmentDto;
import org.eclipse.che.api.workspace.shared.dto.MachineConfigDto;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.ProjectProblemDto;
import org.eclipse.che.api.workspace.shared.dto.RecipeDto;
import org.eclipse.che.api.workspace.shared.dto.ServerConfigDto;
import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
import org.eclipse.che.api.workspace.shared.dto.stack.StackComponentDto;
import org.eclipse.che.api.workspace.shared.dto.stack.StackDto;
import org.eclipse.che.core.db.DBInitializer;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* Tests for {@link StackLoader}
*
* @author Alexander Andrienko
* @author Anton Korneta
*/
@Listeners(MockitoTestNGListener.class)
public class StackLoaderTest {
@Mock private StackDao stackDao;
@Mock private DBInitializer dbInitializer;
private StackLoader stackLoader;
@BeforeMethod
public void startup() throws Exception {
when(dbInitializer.isBareInit()).thenReturn(true);
stackLoader =
new StackLoader(
false, ImmutableMap.of("stacks.json", "stack_img"), stackDao, dbInitializer);
}
@Test
public void predefinedStackWithValidJsonShouldBeUpdated() throws Exception {
stackLoader.start();
verify(stackDao, times(5)).update(any());
verify(stackDao, never()).create(any());
}
@Test
public void predefinedStackWithValidJsonShouldBeCreated() throws Exception {
doThrow(new NotFoundException("Stack is already exist")).when(stackDao).update(any());
stackLoader.start();
verify(stackDao, times(5)).update(any());
verify(stackDao, times(5)).create(any());
}
@Test
public void doNotThrowExceptionWhenUpdateFailed() throws Exception {
doThrow(new ServerException("Internal server error")).when(stackDao).update(any());
stackLoader.start();
verify(stackDao, times(5)).update(any());
verify(stackDao, never()).create(any());
}
@Test
public void doNotThrowExceptionWhenCreationFailed() throws Exception {
doThrow(new NotFoundException("Not found")).when(stackDao).update(any());
doThrow(new ServerException("Internal server error")).when(stackDao).create(any());
stackLoader.start();
verify(stackDao, times(5)).update(any());
verify(stackDao, times(5)).create(any());
}
@Test
public void testOverrideStacksWithoutImages() throws Exception {
final Map<String, String> map = new HashMap<>();
map.put("stacks.json", null);
stackLoader = new StackLoader(true, map, stackDao, dbInitializer);
stackLoader.start();
verify(stackDao, times(5)).update(any());
verify(stackDao, never()).create(any());
}
@Test
public void shouldNotLoadStackWhenDBAlreadyInitialized() throws Exception {
when(dbInitializer.isBareInit()).thenReturn(false);
stackLoader.start();
verify(stackDao, never()).update(any());
verify(stackDao, never()).create(any());
}
@Test
public void dtoShouldBeSerialized() throws Exception {
StackDto stackDtoDescriptor = newDto(StackDto.class).withName("nameWorkspaceConfig");
StackComponentDto stackComponentDto =
newDto(StackComponentDto.class).withName("java").withVersion("1.8");
stackDtoDescriptor.setComponents(Collections.singletonList(stackComponentDto));
stackDtoDescriptor.setTags(Arrays.asList("some teg1", "some teg2"));
stackDtoDescriptor.setDescription("description");
stackDtoDescriptor.setId("someId");
stackDtoDescriptor.setScope("scope");
stackDtoDescriptor.setCreator("Created in Codenvy");
Map<String, String> attributes = new HashMap<>();
attributes.put("attribute1", "valute attribute1");
Link link =
newDto(Link.class)
.withHref("some url")
.withMethod("get")
.withRel("someRel")
.withConsumes("consumes")
.withProduces("produces");
HashMap<String, List<String>> projectMap = new HashMap<>();
projectMap.put("test", Arrays.asList("test", "test2"));
ProjectProblemDto projectProblem =
newDto(ProjectProblemDto.class).withCode(100).withMessage("message");
SourceStorageDto sourceStorageDto =
newDto(SourceStorageDto.class)
.withType("some type")
.withParameters(attributes)
.withLocation("location");
ProjectConfigDto projectConfigDto =
newDto(ProjectConfigDto.class)
.withName("project")
.withPath("somePath")
.withAttributes(projectMap)
.withType("maven type")
.withDescription("some project description")
.withLinks(Collections.singletonList(link))
.withMixins(Collections.singletonList("mixin time"))
.withProblems(Collections.singletonList(projectProblem))
.withSource(sourceStorageDto);
RecipeDto environmentRecipe =
newDto(RecipeDto.class)
.withContent("some content")
.withContentType("some content type")
.withType("someType");
Map<String, ServerConfigDto> servers = new HashMap<>();
servers.put(
"server1Ref",
newDto(ServerConfigDto.class)
.withPort("8080/tcp")
.withProtocol("http")
.withAttributes(singletonMap("key", "value")));
Map<String, MachineConfigDto> machines = new HashMap<>();
machines.put(
"someMachineName",
newDto(MachineConfigDto.class)
.withInstallers(Arrays.asList("agent1", "agent2"))
.withServers(servers)
.withAttributes(singletonMap(MEMORY_LIMIT_ATTRIBUTE, "" + 512L * 1024L * 1024L)));
EnvironmentDto environmentDto =
newDto(EnvironmentDto.class).withRecipe(environmentRecipe).withMachines(machines);
CommandDto commandDto =
newDto(CommandDto.class)
.withType("command type")
.withName("command name")
.withCommandLine("command line");
WorkspaceConfigDto workspaceConfigDto =
newDto(WorkspaceConfigDto.class)
.withName("SomeWorkspaceConfig")
.withDescription("some workspace")
.withLinks(Collections.singletonList(link))
.withDefaultEnv("some Default Env name")
.withProjects(Collections.singletonList(projectConfigDto))
.withEnvironments(singletonMap("name", environmentDto))
.withCommands(Collections.singletonList(commandDto));
stackDtoDescriptor.setWorkspaceConfig(workspaceConfigDto);
Gson GSON = new GsonBuilder().create();
GSON.fromJson(stackDtoDescriptor.toString(), StackImpl.class);
}
}

View File

@ -1,573 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.stack;
import static com.jayway.restassured.RestAssured.given;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.MediaType.MULTIPART_FORM_DATA;
import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_GET_STACK_BY_ID;
import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_REMOVE_STACK;
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.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import com.jayway.restassured.response.Response;
import java.lang.reflect.Field;
import java.net.URISyntaxException;
import java.util.List;
import javax.ws.rs.core.UriInfo;
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.ApiExceptionMapper;
import org.eclipse.che.api.core.rest.shared.dto.ServiceError;
import org.eclipse.che.api.workspace.server.model.impl.CommandImpl;
import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackComponentImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.stack.image.StackIcon;
import org.eclipse.che.api.workspace.shared.dto.stack.StackComponentDto;
import org.eclipse.che.api.workspace.shared.dto.stack.StackDto;
import org.eclipse.che.api.workspace.shared.stack.Stack;
import org.eclipse.che.api.workspace.shared.stack.StackComponent;
import org.eclipse.che.commons.env.EnvironmentContext;
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.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;
/**
* Test for {@link @StackService}
*
* @author Alexander Andrienko
*/
@Listeners(value = {EverrestJetty.class, MockitoTestNGListener.class})
public class StackServiceTest {
private static final String STACK_ID = "java-default";
private static final String NAME = "Java";
private static final String DESCRIPTION = "Default Java Stack with JDK 8, Maven and Tomcat.";
private static final String USER_ID = "che";
private static final String CREATOR = USER_ID;
private static final String FOREIGN_CREATOR = "foreign_creator";
private static final String SCOPE = "general";
private static final String SOURCE_TYPE = "image";
private static final String SOURCE_ORIGIN = "codenvy/ubuntu_jdk8";
private static final String COMPONENT_NAME = "Java";
private static final String COMPONENT_VERSION = "1.8.0_45";
private static final String WORKSPACE_CONFIG_NAME = "default";
private static final String DEF_ENVIRONMENT_NAME = "default";
private static final String COMMAND_NAME = "newMaven";
private static final String COMMAND_TYPE = "mvn";
private static final String COMMAND_LINE = "mvn clean install -f ${current.project.path}";
private static final String ENVIRONMENT_NAME = "default";
private static final String ICON_MEDIA_TYPE = "image/svg+xml";
private static final String SVG_ICON =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
+ "<svg viewBox=\"0 0 200 200\" xmlns=\"http://www.w3.org/2000/svg\">\n"
+ " <circle cx=\"100\" cy=\"100\" r=\"100\" fill=\"red\"/>\n"
+ "</svg>";
@SuppressWarnings("unused")
static final EnvironmentFilter FILTER = new EnvironmentFilter();
@SuppressWarnings("unused")
static final ApiExceptionMapper MAPPER = new ApiExceptionMapper();
private List<String> tags = asList("java", "maven");
private StackDto stackDto;
private StackImpl stackImpl;
private StackImpl foreignStack;
private List<StackComponent> componentsImpl;
private StackIcon stackIcon;
private List<StackComponentDto> componentsDto;
@Mock StackDao stackDao;
@Mock UriInfo uriInfo;
@Mock StackComponentImpl stackComponent;
@Mock StackValidator validator;
@InjectMocks StackService service;
@BeforeMethod
public void setUp() throws NoSuchFieldException, IllegalAccessException {
byte[] fileContent = STACK_ID.getBytes();
stackIcon = new StackIcon(ICON_MEDIA_TYPE, "image/svg+xml", fileContent);
componentsImpl = singletonList(new StackComponentImpl(COMPONENT_NAME, COMPONENT_VERSION));
CommandImpl command = new CommandImpl(COMMAND_NAME, COMMAND_LINE, COMMAND_TYPE);
EnvironmentImpl environment = new EnvironmentImpl(null, null);
WorkspaceConfigImpl workspaceConfig =
WorkspaceConfigImpl.builder()
.setName(WORKSPACE_CONFIG_NAME)
.setDefaultEnv(DEF_ENVIRONMENT_NAME)
.setCommands(singletonList(command))
.setEnvironments(singletonMap(ENVIRONMENT_NAME, environment))
.build();
StackComponentDto stackComponentDto =
newDto(StackComponentDto.class).withName(COMPONENT_NAME).withVersion(COMPONENT_VERSION);
componentsDto = singletonList(stackComponentDto);
stackDto =
DtoFactory.getInstance()
.createDto(StackDto.class)
.withId(STACK_ID)
.withName(NAME)
.withDescription(DESCRIPTION)
.withScope(SCOPE)
.withCreator(CREATOR)
.withTags(tags)
.withComponents(componentsDto);
stackImpl =
StackImpl.builder()
.setId(STACK_ID)
.setName(NAME)
.setDescription(DESCRIPTION)
.setScope(SCOPE)
.setCreator(CREATOR)
.setTags(tags)
.setComponents(componentsImpl)
.setWorkspaceConfig(workspaceConfig)
.setStackIcon(stackIcon)
.build();
foreignStack =
StackImpl.builder()
.setId(STACK_ID)
.setName(NAME)
.setDescription(DESCRIPTION)
.setScope(SCOPE)
.setCreator(FOREIGN_CREATOR)
.setTags(tags)
.setComponents(componentsImpl)
.setWorkspaceConfig(workspaceConfig)
.setStackIcon(stackIcon)
.build();
lenient().when(uriInfo.getBaseUriBuilder()).thenReturn(new UriBuilderImpl());
final Field uriField = service.getClass().getSuperclass().getDeclaredField("uriInfo");
uriField.setAccessible(true);
uriField.set(service, uriInfo);
}
/** Create stack */
@Test
public void newStackShouldBeCreatedForUser() throws ConflictException, ServerException {
final Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType(APPLICATION_JSON)
.body(stackDto)
.when()
.post(SECURE_PATH + "/stack");
assertEquals(response.getStatusCode(), 201);
verify(stackDao).create(any(StackImpl.class));
final StackDto stackDtoDescriptor = unwrapDto(response, StackDto.class);
assertEquals(stackDtoDescriptor.getName(), stackDto.getName());
assertEquals(stackDtoDescriptor.getCreator(), USER_ID);
assertEquals(stackDtoDescriptor.getDescription(), stackDto.getDescription());
assertEquals(stackDtoDescriptor.getTags(), stackDto.getTags());
assertEquals(stackDtoDescriptor.getComponents(), stackDto.getComponents());
assertEquals(stackDtoDescriptor.getScope(), stackDto.getScope());
assertEquals(stackDtoDescriptor.getLinks().size(), 2);
assertEquals(stackDtoDescriptor.getLinks().get(0).getRel(), LINK_REL_REMOVE_STACK);
assertEquals(stackDtoDescriptor.getLinks().get(1).getRel(), LINK_REL_GET_STACK_BY_ID);
}
// @Test
// public void shouldThrowBadRequestExceptionOnCreateStackWithEmptyBody() {
// final Response response = given().auth()
// .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
// .contentType(APPLICATION_JSON)
// .when()
// .post(SECURE_PATH + "/stack");
//
// assertEquals(response.getStatusCode(), 400);
// assertEquals(unwrapDto(response, ServiceError.class).getMessage(), "Stack required");
// }
// @Test
// public void shouldThrowBadRequestExceptionOnCreateStackWithEmptyName() {
// StackComponentDto stackComponentDto =
// newDto(StackComponentDto.class).withName("Java").withVersion("1.8.45");
// StackDto stackDto = newDto(StackDto.class).withId(USER_ID)
// .withDescription("")
// .withScope("Simple java stack for generation
// java projects")
// .withTags(asList("java", "maven"))
// .withCreator("che")
//
// .withComponents(singletonList(stackComponentDto))
//
// Response response = given().auth()
// .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
// .contentType(APPLICATION_JSON)
// .body(stackDto)
// .when()
// .post(SECURE_PATH + "/stack");
//
// assertEquals(response.getStatusCode(), 400);
// assertEquals(unwrapDto(response, ServiceError.class).getMessage(), "Stack name
// required");
// }
/** Get stack by id */
@Test
public void stackByIdShouldBeReturned() throws NotFoundException, ServerException {
when(stackDao.getById(STACK_ID)).thenReturn(stackImpl);
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
.get(SECURE_PATH + "/stack/" + STACK_ID);
assertEquals(response.getStatusCode(), 200);
StackDto result = unwrapDto(response, StackDto.class);
assertEquals(result.getId(), stackImpl.getId());
assertEquals(result.getName(), stackImpl.getName());
assertEquals(result.getDescription(), stackImpl.getDescription());
assertEquals(result.getScope(), stackImpl.getScope());
assertEquals(result.getTags().get(0), stackImpl.getTags().get(0));
assertEquals(result.getTags().get(1), stackImpl.getTags().get(1));
assertEquals(
result.getComponents().get(0).getName(), stackImpl.getComponents().get(0).getName());
assertEquals(
result.getComponents().get(0).getVersion(), stackImpl.getComponents().get(0).getVersion());
assertEquals(result.getCreator(), stackImpl.getCreator());
}
@Test
public void stackShouldBeUpdated() throws NotFoundException, ServerException, ConflictException {
final String updatedDescription = "some description";
final String updatedScope = "advanced";
StackDto updatedStackDto =
DtoFactory.getInstance()
.createDto(StackDto.class)
.withId(STACK_ID)
.withName(NAME)
.withDescription(updatedDescription)
.withScope(updatedScope)
.withCreator(CREATOR)
.withTags(tags)
.withComponents(componentsDto);
StackImpl updateStack = new StackImpl(stackImpl);
updateStack.setDescription(updatedDescription);
updateStack.setScope(updatedScope);
when(stackDao.getById(STACK_ID)).thenReturn(stackImpl).thenReturn(updateStack);
when(stackDao.update(any())).thenReturn(updateStack).thenReturn(updateStack);
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType(APPLICATION_JSON)
.content(updatedStackDto)
.when()
.put(SECURE_PATH + "/stack/" + STACK_ID);
assertEquals(response.getStatusCode(), 200);
StackDto result = unwrapDto(response, StackDto.class);
assertEquals(result.getId(), updatedStackDto.getId());
assertEquals(result.getName(), updatedStackDto.getName());
assertEquals(result.getDescription(), updatedStackDto.getDescription());
assertEquals(result.getScope(), updatedStackDto.getScope());
assertEquals(result.getTags().get(0), updatedStackDto.getTags().get(0));
assertEquals(result.getTags().get(1), updatedStackDto.getTags().get(1));
assertEquals(
result.getComponents().get(0).getName(), updatedStackDto.getComponents().get(0).getName());
assertEquals(
result.getComponents().get(0).getVersion(),
updatedStackDto.getComponents().get(0).getVersion());
assertEquals(result.getCreator(), updatedStackDto.getCreator());
verify(stackDao).update(any());
verify(stackDao).getById(STACK_ID);
}
@Test
public void creatorShouldNotBeUpdated()
throws ServerException, NotFoundException, ConflictException {
StackDto updatedStackDto =
DtoFactory.getInstance()
.createDto(StackDto.class)
.withId(STACK_ID)
.withName(NAME)
.withDescription(DESCRIPTION)
.withScope(SCOPE)
.withCreator("creator changed")
.withTags(tags)
.withComponents(componentsDto);
when(stackDao.getById(anyString())).thenReturn(foreignStack);
when(stackDao.update(any())).thenReturn(foreignStack);
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.contentType(APPLICATION_JSON)
.content(updatedStackDto)
.when()
.put(SECURE_PATH + "/stack/" + STACK_ID);
assertEquals(response.getStatusCode(), 200);
StackDto result = unwrapDto(response, StackDto.class);
assertEquals(result.getId(), updatedStackDto.getId());
assertEquals(result.getName(), updatedStackDto.getName());
assertEquals(result.getDescription(), updatedStackDto.getDescription());
assertEquals(result.getScope(), updatedStackDto.getScope());
assertEquals(result.getTags().get(0), updatedStackDto.getTags().get(0));
assertEquals(result.getTags().get(1), updatedStackDto.getTags().get(1));
assertEquals(
result.getComponents().get(0).getName(), updatedStackDto.getComponents().get(0).getName());
assertEquals(
result.getComponents().get(0).getVersion(),
updatedStackDto.getComponents().get(0).getVersion());
assertEquals(result.getCreator(), FOREIGN_CREATOR);
verify(stackDao).update(any());
verify(stackDao).getById(STACK_ID);
}
/** Delete stack */
@Test
public void stackShouldBeDeleted() throws ServerException, NotFoundException {
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
.delete(SECURE_PATH + "/stack/" + STACK_ID);
verify(stackDao).remove(eq(STACK_ID));
assertEquals(response.getStatusCode(), 204);
}
/** Search stack by tags */
@Test
public void shouldReturnsAllStacksWhenListTagsIsEmpty() throws ServerException {
StackImpl stack2 = new StackImpl(stackImpl);
stack2.setTags(singletonList("subversion"));
List<StackImpl> stacks = asList(stackImpl, stack2);
when(stackDao.searchStacks(anyString(), nullable(List.class), anyInt(), anyInt()))
.thenReturn(stacks);
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
.get(SECURE_PATH + "/stack");
assertEquals(response.getStatusCode(), 200);
verify(stackDao).searchStacks(anyString(), nullable(List.class), anyInt(), anyInt());
List<StackDto> result = unwrapListDto(response, StackDto.class);
assertEquals(result.size(), 2);
assertEquals(result.get(0).getName(), stackImpl.getName());
assertEquals(result.get(1).getName(), stack2.getName());
}
@Test
public void shouldReturnsStackByTagList() throws ServerException {
StackImpl stack2 = new StackImpl(stackImpl);
stack2.setTags(singletonList("Subversion"));
when(stackDao.searchStacks(anyString(), eq(singletonList("Subversion")), anyInt(), anyInt()))
.thenReturn(singletonList(stack2));
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
.get(SECURE_PATH + "/stack?tags=Subversion");
assertEquals(response.getStatusCode(), 200);
verify(stackDao).searchStacks(anyString(), eq(singletonList("Subversion")), anyInt(), anyInt());
List<StackDto> result = unwrapListDto(response, StackDto.class);
assertEquals(result.size(), 1);
assertEquals(result.get(0).getName(), stack2.getName());
}
/** Get icon by stack id */
@Test
public void shouldReturnIconByStackId() throws NotFoundException, ServerException {
when(stackDao.getById(stackImpl.getId())).thenReturn(stackImpl);
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
.get(SECURE_PATH + "/stack/" + stackImpl.getId() + "/icon");
assertEquals(response.getStatusCode(), 200);
verify(stackDao).getById(stackImpl.getId());
}
@Test
public void shouldThrowNotFoundExceptionWhenIconStackWasNotFound()
throws NotFoundException, ServerException {
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
.get(SECURE_PATH + "/stack/" + stackImpl.getId() + "/icon");
assertEquals(response.getStatusCode(), 404);
String expectedErrorMessage = format("Stack with id '%s' was not found.", STACK_ID);
assertEquals(unwrapDto(response, ServiceError.class).getMessage(), expectedErrorMessage);
verify(stackDao).getById(stackImpl.getId());
}
@Test
public void shouldThrowNotFoundExceptionWhenIconWasNotFound()
throws NotFoundException, ServerException {
StackImpl test = new StackImpl(stackImpl);
test.setStackIcon(null);
when(stackDao.getById(test.getId())).thenReturn(test);
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
.get(SECURE_PATH + "/stack/" + stackImpl.getId() + "/icon");
assertEquals(response.getStatusCode(), 404);
String expectedErrorMessage = format("Image for stack with id '%s' was not found.", STACK_ID);
assertEquals(unwrapDto(response, ServiceError.class).getMessage(), expectedErrorMessage);
verify(stackDao).getById(test.getId());
}
/** Delete icon by stack id */
@Test
public void stackIconShouldBeDeletedForUserOwner()
throws NotFoundException, ConflictException, ServerException {
when(stackDao.getById(stackImpl.getId())).thenReturn(stackImpl);
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
.delete(SECURE_PATH + "/stack/" + stackImpl.getId() + "/icon");
assertEquals(response.getStatusCode(), 204);
verify(stackDao).getById(stackImpl.getId());
verify(stackDao).update(stackImpl);
}
/** Update stack icon */
@Test
public void stackIconShouldBeUploadedForUserOwner()
throws NotFoundException, ConflictException, ServerException, URISyntaxException {
when(stackDao.getById(stackImpl.getId())).thenReturn(stackImpl);
checkUploadIcon(stackImpl);
}
@Test
public void foreignStackIconShouldBeUploadedForUser()
throws NotFoundException, ConflictException, ServerException {
when(stackDao.getById(foreignStack.getId())).thenReturn(foreignStack);
checkUploadIcon(foreignStack);
}
private void checkUploadIcon(Stack stack)
throws NotFoundException, ServerException, ConflictException {
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
.multiPart("type-java.svg", SVG_ICON, "image/svg+xml")
.contentType(MULTIPART_FORM_DATA)
.post(SECURE_PATH + "/stack/" + stackImpl.getId() + "/icon");
assertEquals(response.getStatusCode(), 200);
verify(stackDao).getById(foreignStack.getId());
verify(stackDao).update(any());
}
private static <T> T unwrapDto(Response response, Class<T> dtoClass) {
return DtoFactory.getInstance().createDtoFromJson(response.body().print(), dtoClass);
}
private static <T> List<T> unwrapListDto(Response response, Class<T> dtoClass) {
return DtoFactory.getInstance().createListDtoFromJson(response.body().print(), dtoClass);
}
@Filter
public static class EnvironmentFilter implements RequestFilter {
@Override
public void doFilter(GenericContainerRequest request) {
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("user", USER_ID, "token", false));
}
}
}

View File

@ -1,125 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.workspace.server.stack;
import static org.eclipse.che.dto.server.DtoFactory.newDto;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import java.util.ArrayList;
import java.util.Collections;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.workspace.server.WorkspaceValidator;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
import org.eclipse.che.api.workspace.shared.dto.stack.StackComponentDto;
import org.eclipse.che.api.workspace.shared.dto.stack.StackDto;
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;
/**
* Test for {@link StackValidator}
*
* @author Mihail Kuznyetsov
*/
@Listeners(MockitoTestNGListener.class)
public class StackValidatorTest {
@InjectMocks private StackValidator validator;
@Mock private WorkspaceValidator wsValidator;
@BeforeMethod
public void setUp() throws Exception {
doNothing().when(wsValidator).validateConfig(any(WorkspaceConfigDto.class));
}
@Test
public void shouldcheck() throws Exception {
validator.check(createStack());
}
@Test(
expectedExceptions = BadRequestException.class,
expectedExceptionsMessageRegExp = "Required non-null stack")
public void shouldNotValidateIfStackIsNull() throws Exception {
validator.check(null);
}
@Test(
expectedExceptions = BadRequestException.class,
expectedExceptionsMessageRegExp = "Required non-null and non-empty stack name")
public void shouldNotValidateIfStackNameIsNull() throws Exception {
validator.check(createStack().withName(null));
}
@Test(
expectedExceptions = BadRequestException.class,
expectedExceptionsMessageRegExp = "Required non-null and non-empty stack name")
public void shouldNotValidateIfStackNameIsEmpty() throws Exception {
validator.check(createStack().withName(""));
}
@Test
public void shouldValidateIfStackScopeIsGeneral() throws Exception {
validator.check(createStack().withScope("general"));
}
@Test
public void shouldValidateIfStackScopeIsAdvanced() throws Exception {
validator.check(createStack().withScope("advanced"));
}
@Test(
expectedExceptions = BadRequestException.class,
expectedExceptionsMessageRegExp = "Required non-null scope value: 'general' or 'advanced'")
public void shouldNotValidateIfStackScopeIsNull() throws Exception {
validator.check(createStack().withScope(null));
}
@Test(
expectedExceptions = BadRequestException.class,
expectedExceptionsMessageRegExp = "Required non-null scope value: 'general' or 'advanced'")
public void shouldNotValidateIfStackScopeIsNotGeneralOrAdvanced() throws Exception {
validator.check(createStack().withScope("not-valid"));
}
@Test(
expectedExceptions = BadRequestException.class,
expectedExceptionsMessageRegExp = "Workspace config required")
public void shouldValidateIfSourceIsStackSourceAndWorkspaceConfigIsNull() throws Exception {
validator.check(createStack().withWorkspaceConfig(null));
}
@Test
public void shouldNotcheck() throws Exception {
validator.check(createStack());
}
private static StackDto createStack() {
return newDto(StackDto.class)
.withId("stack123")
.withName("Name")
.withDescription("Description")
.withScope("general")
.withCreator("user123")
.withTags(new ArrayList<>(Collections.singletonList("latest")))
.withWorkspaceConfig(newDto(WorkspaceConfigDto.class))
.withComponents(
new ArrayList<>(
Collections.singletonList(
newDto(StackComponentDto.class).withName("maven").withVersion("3.3.1"))));
}
}

View File

@ -1,367 +0,0 @@
[
{
"id": "java-default",
"creator": "ide",
"name": "Java",
"description": "Default Java Stack with JDK 8, Maven and Tomcat.",
"scope": "general",
"tags": [
"Java",
"JDK",
"Maven",
"Tomcat",
"Subversion",
"Ubuntu",
"Git"
],
"components": [
{
"name": "JDK",
"version": "1.8.0_45"
},
{
"name": "Maven",
"version": "3.2.2"
},
{
"name": "Tomcat",
"version": "8.0.24"
}
],
"workspaceConfig": {
"environments": {
"default" : {
"machines": {
"devmachine": {
"installers": [
"org.eclipse.che.ws-agent"
],
"attributes" : {
"memoryLimitBytes": "2147483648"
}
}
},
"recipe": {
"location": "codenvy/ubuntu_jdk8",
"type": "dockerimage"
}
}
},
"name": "default",
"defaultEnv": "default",
"description": null,
"commands": [
{
"commandLine": "mvn clean install -f ${current.project.path}",
"name": "newMaven",
"type": "mvn"
}
]
},
"stackIcon" : {
"name": "type-java.svg",
"mediaType": "image/svg+xml"
}
},
{
"id": "node-default",
"creator": "ide",
"name": "Node",
"description": "Default Node Stack with Node 0.12.",
"scope": "general",
"tags": [
"Ubuntu",
"Git",
"Node.JS",
"NPM",
"Gulp",
"Bower",
"Grunt",
"Yeoman",
"Angular",
"Karma"
],
"components": [
{
"name": "Node.JS",
"version": "0.12.9"
},
{
"name": "NPM",
"version": "---"
},
{
"name": "Gulp",
"version": "---"
},
{
"name": "Bower",
"version": "---"
},
{
"name": "Grunt",
"version": "---"
},
{
"name": "Yeoman",
"version": "---"
}
],
"workspaceConfig": {
"environments": {
"default" : {
"machines": {
"devmachine": {
"installers": [
"org.eclipse.che.ws-agent"
],
"attributes" : {
"memoryLimitBytes": "2147483648"
}
}
},
"recipe": {
"location": "https://raw.githubusercontent.com/eclipse/che/master/Dockerfile",
"type": "dockerfile",
"contentType": "text/x-dockerfile"
}
}
},
"name": "default",
"defaultEnv": "default",
"description": null,
"commands": [
{
"commandLine": "mvn clean install -f ${current.project.path}",
"name": "newMaven",
"type": "mvn"
}
]
}
},
{
"id": "node-default",
"creator": "ide",
"name": "Node",
"description": "Default Node Stack with Node 0.12.",
"scope": "general",
"tags": [
"Ubuntu",
"Git",
"Node.JS",
"NPM",
"Gulp",
"Bower",
"Grunt",
"Yeoman",
"Angular",
"Karma"
],
"components": [
{
"name": "Node.JS",
"version": "0.12.9"
},
{
"name": "NPM",
"version": "---"
},
{
"name": "Gulp",
"version": "---"
},
{
"name": "Bower",
"version": "---"
},
{
"name": "Grunt",
"version": "---"
},
{
"name": "Yeoman",
"version": "---"
}
],
"workspaceConfig": {
"environments": {
"default" : {
"machines": {
"devmachine": {
"installers": [
"org.eclipse.che.ws-agent"
],
"attributes" : {
"memoryLimitBytes": "2147483648"
}
}
},
"recipe": {
"content": "FROM codenvy/ubuntu_jdk8",
"type": "dockerfile",
"contentType": "text/x-dockerfile"
}
}
},
"name": "default",
"defaultEnv": "default",
"description": null,
"commands": [
{
"commandLine": "mvn clean install -f ${current.project.path}",
"name": "newMaven",
"type": "mvn"
}
]
}
},
{
"id": "compose-location",
"creator": "ide",
"name": "Node",
"description": "Default Node Stack with Node 0.12.",
"scope": "general",
"tags": [
"Ubuntu",
"Git",
"Node.JS",
"NPM",
"Gulp",
"Bower",
"Grunt",
"Yeoman",
"Angular",
"Karma"
],
"components": [
{
"name": "Node.JS",
"version": "0.12.9"
},
{
"name": "NPM",
"version": "---"
},
{
"name": "Gulp",
"version": "---"
},
{
"name": "Bower",
"version": "---"
},
{
"name": "Grunt",
"version": "---"
},
{
"name": "Yeoman",
"version": "---"
}
],
"workspaceConfig": {
"environments": {
"default" : {
"machines": {
"devmachine": {
"installers": [
"org.eclipse.che.ws-agent"
],
"attributes" : {
"memoryLimitBytes": "2147483648"
}
}
},
"recipe": {
"location": "https://raw.githubusercontent.com/eclipse/che/master/Dockerfile",
"type": "compose",
"contentType": "application/x-yaml"
}
}
},
"name": "default",
"defaultEnv": "default",
"description": null,
"commands": [
{
"commandLine": "mvn clean install -f ${current.project.path}",
"name": "newMaven",
"type": "mvn"
}
]
}
},
{
"id": "compose-content",
"creator": "ide",
"name": "Node",
"description": "Default Node Stack with Node 0.12.",
"scope": "general",
"tags": [
"Ubuntu",
"Git",
"Node.JS",
"NPM",
"Gulp",
"Bower",
"Grunt",
"Yeoman",
"Angular",
"Karma"
],
"components": [
{
"name": "Node.JS",
"version": "0.12.9"
},
{
"name": "NPM",
"version": "---"
},
{
"name": "Gulp",
"version": "---"
},
{
"name": "Bower",
"version": "---"
},
{
"name": "Grunt",
"version": "---"
},
{
"name": "Yeoman",
"version": "---"
}
],
"workspaceConfig": {
"environments": {
"default" : {
"machines": {
"devmachine": {
"installers": [
"org.eclipse.che.ws-agent"
]
}
},
"recipe": {
"content": "service:\n devmachine:\n image: codenvy/ubuntu_jdk8\n mem_limit: 2147483648",
"type": "compose",
"contentType": "application/x-yaml"
}
}
},
"name": "default",
"defaultEnv": "default",
"description": null,
"commands": [
{
"commandLine": "mvn clean install -f ${current.project.path}",
"name": "newMaven",
"type": "mvn"
}
]
}
}
]

View File

@ -0,0 +1,15 @@
--
-- Copyright (c) 2012-2019 Red Hat, Inc.
-- This program and the accompanying materials are made
-- available under the terms of the Eclipse Public License 2.0
-- which is available at https://www.eclipse.org/legal/epl-2.0/
--
-- SPDX-License-Identifier: EPL-2.0
--
-- Contributors:
-- Red Hat, Inc. - initial API and implementation
--
DROP TABLE stack_components;
DROP TABLE stack_tags;
DROP TABLE stack;

View File

@ -95,7 +95,6 @@ import org.eclipse.che.api.workspace.server.model.impl.devfile.EntrypointImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.EnvImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.ProjectImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.SourceImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.RuntimeInfrastructure;
import org.eclipse.che.api.workspace.server.spi.WorkspaceDao;
import org.eclipse.che.commons.test.db.H2DBTestServer;
@ -193,7 +192,6 @@ public class CascadeRemovalTest {
MachineConfigImpl.class,
SourceStorageImpl.class,
ServerConfigImpl.class,
StackImpl.class,
CommandImpl.class,
RecipeImpl.class,
SshPairImpl.class,

View File

@ -47,9 +47,6 @@ import org.eclipse.che.api.workspace.server.model.impl.devfile.EntrypointImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.MetadataImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.ProjectImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.SourceImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackComponentImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.stack.image.StackIcon;
import org.eclipse.che.commons.lang.NameGenerator;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesMachineImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState;
@ -223,24 +220,6 @@ public final class TestObjectsFactory {
return new SshPairImpl(owner, service, name, "public-key", "private-key");
}
public static StackImpl createStack(String id, String name) {
return StackImpl.builder()
.setId(id)
.setName(name)
.setCreator("user123")
.setDescription(id + "-description")
.setScope(id + "-scope")
.setWorkspaceConfig(createWorkspaceConfig("test"))
.setTags(asList(id + "-tag1", id + "-tag2"))
.setComponents(
asList(
new StackComponentImpl(id + "-component1", id + "-component1-version"),
new StackComponentImpl(id + "-component2", id + "-component2-version")))
.setStackIcon(
new StackIcon(id + "-icon", id + "-media-type", "0x1234567890abcdef".getBytes()))
.build();
}
public static KubernetesRuntimeState createK8sRuntimeState(String workspaceId) {
return new KubernetesRuntimeState(
new RuntimeIdentityImpl(workspaceId, "envName", "ownerId"),

View File

@ -303,11 +303,7 @@
<port>jdbc.port:3306</port>
</ports>
<wait>
<tcp>
<ports>
<port>3306</port>
</ports>
</tcp>
<log>ready for connections</log>
<time>60000</time>
</wait>
<restartPolicy>

View File

@ -45,7 +45,6 @@ import org.eclipse.che.api.workspace.activity.WorkspaceActivity;
import org.eclipse.che.api.workspace.activity.WorkspaceActivityDao;
import org.eclipse.che.api.workspace.activity.WorkspaceExpiration;
import org.eclipse.che.api.workspace.server.devfile.SerializableConverter;
import org.eclipse.che.api.workspace.server.jpa.JpaStackDao;
import org.eclipse.che.api.workspace.server.jpa.JpaWorkspaceDao;
import org.eclipse.che.api.workspace.server.model.impl.CommandImpl;
import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
@ -65,8 +64,6 @@ import org.eclipse.che.api.workspace.server.model.impl.devfile.EntrypointImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.EnvImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.ProjectImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.SourceImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.spi.WorkspaceDao;
import org.eclipse.che.commons.lang.Pair;
import org.eclipse.che.commons.test.db.PersistTestModuleBuilder;
@ -136,7 +133,6 @@ public class MySqlTckModule extends TckModule {
MachineConfigImpl.class,
SourceStorageImpl.class,
ServerConfigImpl.class,
StackImpl.class,
CommandImpl.class,
SshPairImpl.class,
InstallerImpl.class,
@ -204,10 +200,8 @@ public class MySqlTckModule extends TckModule {
// workspace
bind(WorkspaceDao.class).to(JpaWorkspaceDao.class);
bind(StackDao.class).to(JpaStackDao.class);
bind(WorkspaceActivityDao.class).to(JpaWorkspaceActivityDao.class);
bind(new TypeLiteral<TckRepository<WorkspaceImpl>>() {}).toInstance(new WorkspaceRepository());
bind(new TypeLiteral<TckRepository<StackImpl>>() {}).toInstance(new StackRepository());
bind(new TypeLiteral<TckRepository<WorkspaceExpiration>>() {})
.toInstance(new JpaTckRepository<>(WorkspaceExpiration.class));
@ -331,18 +325,4 @@ public class MySqlTckModule extends TckModule {
super.createAll(entities);
}
}
private static class StackRepository extends JpaTckRepository<StackImpl> {
public StackRepository() {
super(StackImpl.class);
}
@Override
public void createAll(Collection<? extends StackImpl> entities) throws TckRepositoryException {
for (StackImpl stack : entities) {
stack.getWorkspaceConfig().getProjects().forEach(ProjectConfigImpl::prePersistAttributes);
}
super.createAll(entities);
}
}
}

View File

@ -45,7 +45,6 @@ import org.eclipse.che.api.workspace.activity.WorkspaceActivity;
import org.eclipse.che.api.workspace.activity.WorkspaceActivityDao;
import org.eclipse.che.api.workspace.activity.WorkspaceExpiration;
import org.eclipse.che.api.workspace.server.devfile.SerializableConverter;
import org.eclipse.che.api.workspace.server.jpa.JpaStackDao;
import org.eclipse.che.api.workspace.server.jpa.JpaWorkspaceDao;
import org.eclipse.che.api.workspace.server.model.impl.CommandImpl;
import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
@ -65,8 +64,6 @@ import org.eclipse.che.api.workspace.server.model.impl.devfile.EntrypointImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.EnvImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.ProjectImpl;
import org.eclipse.che.api.workspace.server.model.impl.devfile.SourceImpl;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.spi.WorkspaceDao;
import org.eclipse.che.commons.lang.Pair;
import org.eclipse.che.commons.test.db.PersistTestModuleBuilder;
@ -133,7 +130,6 @@ public class PostgreSqlTckModule extends TckModule {
MachineConfigImpl.class,
SourceStorageImpl.class,
ServerConfigImpl.class,
StackImpl.class,
CommandImpl.class,
SshPairImpl.class,
InstallerImpl.class,
@ -199,10 +195,8 @@ public class PostgreSqlTckModule extends TckModule {
// workspace
bind(WorkspaceDao.class).to(JpaWorkspaceDao.class);
bind(StackDao.class).to(JpaStackDao.class);
bind(WorkspaceActivityDao.class).to(JpaWorkspaceActivityDao.class);
bind(new TypeLiteral<TckRepository<WorkspaceImpl>>() {}).toInstance(new WorkspaceRepository());
bind(new TypeLiteral<TckRepository<StackImpl>>() {}).toInstance(new StackRepository());
bind(new TypeLiteral<TckRepository<WorkspaceExpiration>>() {})
.toInstance(new JpaTckRepository<>(WorkspaceExpiration.class));
@ -321,19 +315,4 @@ public class PostgreSqlTckModule extends TckModule {
super.createAll(entities);
}
}
private static class StackRepository extends JpaTckRepository<StackImpl> {
public StackRepository() {
super(StackImpl.class);
}
@Override
public void createAll(Collection<? extends StackImpl> entities) throws TckRepositoryException {
for (StackImpl stack : entities) {
stack.getWorkspaceConfig().getProjects().forEach(ProjectConfigImpl::prePersistAttributes);
}
super.createAll(entities);
}
}
}