/* * Copyright 2002 - 2014 Webdetails, a Pentaho company. All rights reserved. * * This software was developed by Webdetails and is provided under the terms * of the Mozilla Public License, Version 2.0, or any later version. You may not use * this file except in compliance with the license. If you need a copy of the license, * please go to http://mozilla.org/MPL/2.0/. The Initial Developer is Webdetails. * * Software distributed under the Mozilla Public License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to * the license for the specific language governing your rights and limitations. */ package org.pentaho.marketplace.domain.services; import static org.junit.Assert.assertThat; import static org.hamcrest.CoreMatchers.*; import org.apache.karaf.features.Feature; import org.apache.karaf.features.FeaturesService; import org.apache.karaf.features.Repository; import org.apache.karaf.kar.KarService; import org.junit.Test; import org.junit.Before; import static org.mockito.Mockito.*; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.osgi.framework.Bundle; import org.osgi.service.cm.ConfigurationAdmin; import org.pentaho.marketplace.domain.model.entities.MarketEntryType; import org.pentaho.marketplace.domain.model.entities.interfaces.IDomainStatusMessage; import org.pentaho.marketplace.domain.model.entities.interfaces.IPlugin; import org.pentaho.marketplace.domain.model.entities.interfaces.IPluginVersion; import org.pentaho.marketplace.domain.model.entities.serialization.MarketplaceXmlSerializer; import org.pentaho.marketplace.domain.model.factories.DomainStatusMessageFactory; import org.pentaho.marketplace.domain.model.factories.PluginFactory; import org.pentaho.marketplace.domain.model.factories.PluginVersionFactory; import org.pentaho.marketplace.domain.model.factories.VersionDataFactory; import org.pentaho.marketplace.domain.model.factories.interfaces.IDomainStatusMessageFactory; import org.pentaho.marketplace.domain.model.factories.interfaces.IPluginFactory; import org.pentaho.marketplace.domain.model.factories.interfaces.IPluginVersionFactory; import org.pentaho.marketplace.domain.model.factories.interfaces.IVersionDataFactory; import org.pentaho.marketplace.domain.services.interfaces.IPluginProvider; import org.pentaho.marketplace.domain.services.interfaces.IRemotePluginProvider; import org.pentaho.platform.api.engine.IApplicationContext; import org.pentaho.platform.api.engine.IPentahoSession; import org.pentaho.platform.api.engine.ISecurityHelper; import org.pentaho.telemetry.ITelemetryService; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import java.util.List; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; public class BaPluginServiceTest { private String getSolutionPath() { return System.getProperty( "user.dir" ) + "/target/test-classes/pentaho-solutions/"; } IDomainStatusMessageFactory domainStatusMessageFactory; IVersionDataFactory versionDataFactory; IPluginFactory pluginFactory = new PluginFactory(); IPluginVersionFactory pluginVersionFactory = new PluginVersionFactory(); //region auxiliary methods /** * Creates a new plugin service. * Solution folder is set to "test-res/pentaho-solutions/" * @return a new test plugin service */ private BaPluginService createPluginService() { IDomainStatusMessageFactory domainStatusMessageFactory = this.domainStatusMessageFactory; IVersionDataFactory versionDataFactory = this.versionDataFactory; IPluginVersionFactory pluginVersionFactory = this.pluginVersionFactory; IRemotePluginProvider pluginProvider = mock( IRemotePluginProvider.class ); MarketplaceXmlSerializer serializer = mock( MarketplaceXmlSerializer.class ); ISecurityHelper securityHelper = mock( ISecurityHelper.class ); ITelemetryService telemetryService = mock( ITelemetryService.class ); KarService karService = mock( KarService.class ); FeaturesService featuresService = mock( FeaturesService.class ); Feature[] emtptyFeatures = {}; when( featuresService.listInstalledFeatures() ).thenReturn( emtptyFeatures ); try { when( featuresService.listFeatures() ).thenReturn( emtptyFeatures ); } catch ( Exception e ) {} when( featuresService.listRepositories() ).thenReturn( new Repository[0] ); Bundle bundle = mock( Bundle.class ); ConfigurationAdmin configurationAdmin = mock( ConfigurationAdmin.class ); BaPluginService service = new BaPluginService( pluginProvider, versionDataFactory, pluginVersionFactory, karService, featuresService, configurationAdmin, telemetryService, domainStatusMessageFactory, serializer, securityHelper, bundle ); IApplicationContext applicationContext = mock( IApplicationContext.class ); final String solutionPath = this.getSolutionPath(); when( applicationContext.getSolutionPath( anyString() ) ).thenAnswer( new Answer<String>() { @Override public String answer( InvocationOnMock invocation ) throws Throwable { String path = (String) invocation.getArguments()[ 0 ]; return solutionPath + path; } } ); service.setApplicationContext( applicationContext ); return service; } private Authentication createMockUserAuthentication( String role, String userName ) { GrantedAuthority userAuthority = mock( GrantedAuthority.class ); when( userAuthority.getAuthority() ).thenReturn( role ); Authentication userAuthentication = mock( Authentication.class ); List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(); authList.add( userAuthority ); doReturn( authList ).when( userAuthentication ).getAuthorities(); when( userAuthentication.getName() ).thenReturn( userName ); return userAuthentication; } // endregion @Before public void setup() { this.domainStatusMessageFactory = new DomainStatusMessageFactory(); this.versionDataFactory = new VersionDataFactory(); } // region Tests /** * Tests that when no allowed roles are defined and the user trying to install is not an administrator * then the installation is denied. */ @Test public void testInstallDeniedNoRolesAndNonAdminUser( ) { // arrange BaPluginService service = this.createPluginService(); // setup no roles service.setAuthorizedRoles( Collections.<String>emptyList() ); // setup security helper for non admin user ISecurityHelper securityHelper = service.getSecurityHelper(); when( securityHelper.isPentahoAdministrator( Mockito.any( IPentahoSession.class ) ) ).thenReturn( false ); // act IDomainStatusMessage result = service.installPlugin( "doesNotMatter", "doesNotMatter" ); // assert assertThat( result.getCode(), is( equalTo( BasePluginService.UNAUTHORIZED_ACCESS_ERROR_CODE ) ) ); } /** * Tests that when no allowed roles are defined and the user trying to uninstall is not an administrator * then the uninstall is denied. */ @Test public void testUninstallDeniedNoRolesAndNonAdminUser( ) { // arrange BaPluginService service = this.createPluginService(); // setup no roles service.setAuthorizedRoles( Collections.<String>emptyList() ); // setup security helper for non admin user ISecurityHelper securityHelper = service.getSecurityHelper(); when( securityHelper.isPentahoAdministrator( Mockito.any( IPentahoSession.class ) ) ).thenReturn( false ); // act IDomainStatusMessage result = service.uninstallPlugin( "doesNotMatter" ); // assert assertThat( result.getCode(), is( equalTo( BasePluginService.UNAUTHORIZED_ACCESS_ERROR_CODE ) ) ); } /** * Tests that when allowed roles are defined and the user trying to install does not have one of them * then the installation is denied. */ @Test public void testInstallDeniedUserNotInRoles( ) { // region arrange BaPluginService service = this.createPluginService(); // this is the role of the user which will be in the authorized roles String userRole = "peasant"; Collection<String> authorizedRoles = Arrays.asList( "manager", "lackey" ); // setup roles service.setAuthorizedRoles( authorizedRoles ); Authentication userAuthentication = this.createMockUserAuthentication( userRole, null ); // setup security helper ISecurityHelper securityHelper = service.getSecurityHelper(); when( securityHelper.getAuthentication( Mockito.any( IPentahoSession.class ), eq( true ) ) ).thenReturn( userAuthentication ); // endregion // act IDomainStatusMessage result = service.installPlugin( "doesNotMatter", "doesNotMatter" ); // assert assertThat( result.getCode(), is( equalTo( BasePluginService.UNAUTHORIZED_ACCESS_ERROR_CODE ) ) ); } /** * Tests that when allowed roles are defined and the user trying to uninstall does not have one of them * then the uninstall is denied. */ @Test public void testUninstallDeniedUserNotInRoles( ) { // region arrange BaPluginService service = this.createPluginService(); // this is the role of the user which will be in the authorized roles String userRole = "peasant"; Collection<String> authorizedRoles = Arrays.asList( "manager", "lackey" ); // setup roles service.setAuthorizedRoles( authorizedRoles ); Authentication userAuthentication = this.createMockUserAuthentication( userRole, null ); // setup security helper ISecurityHelper securityHelper = service.getSecurityHelper(); when( securityHelper.getAuthentication( Mockito.any( IPentahoSession.class ), eq( true ) ) ).thenReturn( userAuthentication ); // endregion // act IDomainStatusMessage result = service.uninstallPlugin( "doesNotMatter" ); // assert assertThat( result.getCode(), is( equalTo( BasePluginService.UNAUTHORIZED_ACCESS_ERROR_CODE ) ) ); } /** * Tests that when allowed users are defined and the user trying to install is not one of them * then the installation is denied. */ @Test public void testInstallDeniedUserNotInUsers( ) { // arrange String userName = "Dennis"; Collection<String> authorizedUsers = Arrays.asList( "Joseph", "David" ); Collection<String> authorizedRoles = Collections.emptyList(); BaPluginService service = this.createPluginService(); service.setAuthorizedUsernames( authorizedUsers ); service.setAuthorizedRoles( authorizedRoles ); Authentication userAuthentication = this.createMockUserAuthentication( null, userName ); ISecurityHelper securityHelper = service.getSecurityHelper(); when( securityHelper.getAuthentication( Mockito.any( IPentahoSession.class ), eq( true ) ) ).thenReturn( userAuthentication ); // act IDomainStatusMessage result = service.installPlugin( "doesNotMatter", "doesNotMatter" ); // assert assertThat( result.getCode(), is( equalTo( BasePluginService.UNAUTHORIZED_ACCESS_ERROR_CODE ) ) ); } /** * Tests that when allowed users are defined and the user trying to uninstall is not one of them * then the uninstall is denied. */ @Test public void testUninstallDeniedUserNotInUsers( ) { // arrange String userName = "Dennis"; Collection<String> authorizedUsers = Arrays.asList( "Joseph" , "David" ); Collection<String> authorizedRoles = Collections.emptyList(); BaPluginService service = this.createPluginService(); service.setAuthorizedUsernames( authorizedUsers ); service.setAuthorizedRoles( authorizedRoles ); Authentication userAuthentication = this.createMockUserAuthentication( null, userName ); ISecurityHelper securityHelper = service.getSecurityHelper(); when( securityHelper.getAuthentication( Mockito.any( IPentahoSession.class ), eq( true ) ) ).thenReturn( userAuthentication ); // act IDomainStatusMessage result = service.uninstallPlugin( "doesNotMatter" ); // assert assertThat( result.getCode(), is( equalTo( BasePluginService.UNAUTHORIZED_ACCESS_ERROR_CODE ) ) ); } //TODO: "(un)install allowed" test cases /** * Tests that only compatible versions (with ba server) of plugins are returned */ @Test public void testGetPluginsOnlyCompatibleVersions( ) { // arrange BaPluginService service = this.createPluginService(); service.setServerVersion( "5.2" ); IPluginVersion compatibleVersion = this.pluginVersionFactory.create(); compatibleVersion.setMinParentVersion( "1.0" ); compatibleVersion.setMaxParentVersion( "6.9.99" ); IPluginVersion notCompatibleVersion = this.pluginVersionFactory.create(); notCompatibleVersion.setMaxParentVersion( "1.0" ); notCompatibleVersion.setMinParentVersion( "1.0" ); Collection<IPluginVersion> versions = new ArrayList<>(); versions.add( compatibleVersion ); versions.add( notCompatibleVersion ); Map<String, IPlugin> plugins = new HashMap<>(); IPlugin plugin = this.pluginFactory.create(); String pluginId = "myPlugin"; plugin.setId( pluginId ); plugin.setVersions( versions ); plugin.setType( MarketEntryType.Platform ); plugins.put(plugin.getId(), plugin ); IPluginProvider pluginProvider = service.getMetadataPluginsProvider(); when( pluginProvider.getPlugins() ).thenReturn( plugins ); // act Map<String, IPlugin> actualPlugins = service.getPlugins(); // assert IPlugin actualPlugin = actualPlugins.get( pluginId ); Collection<IPluginVersion> actualVersions = actualPlugin.getVersions(); assertThat( actualPlugin, is( equalTo( plugin ) ) ); assertThat( actualVersions, hasItem( compatibleVersion ) ); assertThat( actualVersions, not( hasItem( notCompatibleVersion ) ) ); } /** * Tests that plugins which are installed (in the system folder) are marked as installed */ @Test public void testGetPluginsInstalledPluginsAreIdentified() { // arrange BaPluginService service = this.createPluginService(); service.setServerVersion( "5.2" ); IPluginVersion compatibleVersion = this.pluginVersionFactory.create(); compatibleVersion.setMinParentVersion( "1.0" ); compatibleVersion.setMaxParentVersion( "6.9.99" ); IPlugin installedPlugin = this.pluginFactory.create(); // plugin name is the same as the plugin folder inside "test-res/pentaho-solutions/system" String installedPluginId = "installedPlugin"; installedPlugin.setId( installedPluginId ); installedPlugin.setInstalled( false ); installedPlugin.setType( MarketEntryType.Platform ); // have at least one compatible version so its not filtered out installedPlugin.getVersions().add( compatibleVersion ); IPlugin notInstalledPlugin = this.pluginFactory.create(); String notInstalledPluginId = "notInstalledPlugin"; notInstalledPlugin.setId( notInstalledPluginId ); notInstalledPlugin.setInstalled( false ); notInstalledPlugin.setType( MarketEntryType.Platform ); // have at least one compatible version so its not filtered out notInstalledPlugin.getVersions().add( compatibleVersion ); Map<String, IPlugin> plugins = new HashMap<>(); plugins.put( installedPlugin.getId(), installedPlugin ); plugins.put( notInstalledPlugin.getId(), notInstalledPlugin ); IPluginProvider pluginProvider = service.getMetadataPluginsProvider(); when( pluginProvider.getPlugins() ).thenReturn( plugins ); // act Map<String, IPlugin> actualPlugins = service.getPlugins(); // assert IPlugin actualInstalledPlugin = actualPlugins.get( installedPluginId ); IPlugin actualNotInstalledPlugin = actualPlugins.get( notInstalledPluginId ); assertThat( actualInstalledPlugin, is( notNullValue() ) ); assertThat( actualNotInstalledPlugin, is( notNullValue() ) ); assertThat( actualInstalledPlugin.isInstalled(), is( true ) ); assertThat( actualNotInstalledPlugin.isInstalled(), is( false ) ); } // endregion }