content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.ambari.server.controller.internal;
  
  import static org.easymock.EasyMock.capture;
  import static org.easymock.EasyMock.expect;
  import static org.easymock.EasyMock.expectLastCall;
  import static org.easymock.EasyMock.newCapture;
  
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.LinkedHashMap;
  import java.util.LinkedHashSet;
  import java.util.Map;
  import java.util.Set;
  
  import jakarta.persistence.EntityManager;
  
  import org.apache.ambari.server.actionmanager.ActionDBAccessor;
  import org.apache.ambari.server.actionmanager.ActionManager;
  import org.apache.ambari.server.actionmanager.HostRoleCommandFactory;
  import org.apache.ambari.server.actionmanager.HostRoleCommandFactoryImpl;
  import org.apache.ambari.server.actionmanager.StageFactory;
  import org.apache.ambari.server.api.services.AmbariMetaInfo;
  import org.apache.ambari.server.controller.AbstractRootServiceResponseFactory;
  import org.apache.ambari.server.controller.AmbariManagementController;
  import org.apache.ambari.server.controller.AmbariManagementControllerImpl;
  import org.apache.ambari.server.controller.KerberosHelper;
  import org.apache.ambari.server.controller.spi.Predicate;
  import org.apache.ambari.server.controller.spi.Request;
  import org.apache.ambari.server.controller.spi.Resource;
  import org.apache.ambari.server.controller.spi.ResourceProvider;
  import org.apache.ambari.server.controller.spi.SystemException;
  import org.apache.ambari.server.controller.utilities.PredicateBuilder;
  import org.apache.ambari.server.controller.utilities.PropertyHelper;
  import org.apache.ambari.server.hooks.HookContextFactory;
  import org.apache.ambari.server.hooks.HookService;
  import org.apache.ambari.server.metadata.CachedRoleCommandOrderProvider;
  import org.apache.ambari.server.metadata.RoleCommandOrderProvider;
  import org.apache.ambari.server.orm.DBAccessor;
  import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
  import org.apache.ambari.server.orm.dao.UserDAO;
  import org.apache.ambari.server.orm.dao.WidgetDAO;
  import org.apache.ambari.server.orm.dao.WidgetLayoutDAO;
  import org.apache.ambari.server.orm.entities.UserEntity;
  import org.apache.ambari.server.orm.entities.WidgetLayoutEntity;
  import org.apache.ambari.server.scheduler.ExecutionScheduler;
  import org.apache.ambari.server.security.TestAuthenticationFactory;
  import org.apache.ambari.server.security.authorization.AuthorizationException;
  import org.apache.ambari.server.security.authorization.Users;
  import org.apache.ambari.server.security.encryption.CredentialStoreService;
  import org.apache.ambari.server.security.encryption.CredentialStoreServiceImpl;
  import org.apache.ambari.server.stack.StackManagerFactory;
  import org.apache.ambari.server.stack.upgrade.orchestrate.UpgradeContextFactory;
  import org.apache.ambari.server.stageplanner.RoleGraphFactory;
  import org.apache.ambari.server.state.Cluster;
  import org.apache.ambari.server.state.Clusters;
  import org.apache.ambari.server.state.ConfigFactory;
  import org.apache.ambari.server.state.ServiceComponentFactory;
  import org.apache.ambari.server.state.ServiceComponentHostFactory;
  import org.apache.ambari.server.state.ServiceFactory;
  import org.apache.ambari.server.state.configgroup.ConfigGroupFactory;
  import org.apache.ambari.server.state.scheduler.RequestExecutionFactory;
  import org.apache.ambari.server.state.stack.OsFamily;
  import org.apache.ambari.server.topology.PersistedState;
  import org.apache.ambari.server.topology.PersistedStateImpl;
  import org.apache.ambari.server.topology.tasks.ConfigureClusterTaskFactory;
  import org.easymock.Capture;
  import org.easymock.EasyMockSupport;
  import org.junit.Assert;
  import org.junit.Before;
  import org.junit.Ignore;
  import org.junit.Test;
  import org.springframework.security.core.Authentication;
  import org.springframework.security.core.context.SecurityContextHolder;
  import org.springframework.security.crypto.password.PasswordEncoder;
  
  import com.google.gson.Gson;
  import com.google.inject.AbstractModule;
  import com.google.inject.Guice;
  import com.google.inject.Injector;
  import com.google.inject.assistedinject.FactoryModuleBuilder;
  
  /**
   * ActiveWidgetLayout tests
   */
  @Ignore // need to fix StackOverflowError
  public class ActiveWidgetLayoutResourceProviderTest extends EasyMockSupport {
  
    @Before
    public void before() {
      resetAll();
    }
  
  
    @Test
    public void testGetResources_Administrator() throws Exception {
      getResourcesTest(TestAuthenticationFactory.createAdministrator("admin"), "User1");
    }
  
    @Test
    public void testGetResources_NonAdministrator_Self() throws Exception {
      getResourcesTest(TestAuthenticationFactory.createClusterAdministrator("User1", 2L), "User1");
    }
  
    @Test(expected = AuthorizationException.class)
    public void testGetResources_NonAdministrator_Other() throws Exception {
      getResourcesTest(TestAuthenticationFactory.createClusterAdministrator("User1", 2L), "User10");
    }
  
    @Test(expected = SystemException.class)
    public void testCreateResources_Administrator() throws Exception {
      createResourcesTest(TestAuthenticationFactory.createAdministrator("admin"), "User1");
    }
  
    @Test(expected = SystemException.class)
    public void testCreateResources_NonAdministrator_Self() throws Exception {
      createResourcesTest(TestAuthenticationFactory.createClusterAdministrator("User1", 2L), "User1");
    }
  
    @Test(expected = SystemException.class)
    public void testCreateResources_NonAdministrator_Other() throws Exception {
      createResourcesTest(TestAuthenticationFactory.createClusterAdministrator("User1", 2L), "User10");
    }
  
    @Test
    public void testUpdateResources_Administrator() throws Exception {
      updateResourcesTest(TestAuthenticationFactory.createAdministrator("admin"), "User1");
    }
  
    @Test
    public void testUpdateResources_NonAdministrator_Self() throws Exception {
      updateResourcesTest(TestAuthenticationFactory.createClusterAdministrator("User1", 2L), "User1");
    }
  
    @Test
    public void testUpdateResources_NoUserName_Self() throws Exception {
      updateResourcesTest(TestAuthenticationFactory.createClusterAdministrator("User1", 2L), "User1", false);
    }
  
    @Test(expected = AuthorizationException.class)
    public void testUpdateResources_NonAdministrator_Other() throws Exception {
      updateResourcesTest(TestAuthenticationFactory.createClusterAdministrator("User1", 2L), "User10");
    }
  
    @Test(expected = SystemException.class)
    public void testDeleteResources_Administrator() throws Exception {
      deleteResourcesTest(TestAuthenticationFactory.createAdministrator("admin"), "User1");
    }
  
    @Test(expected = SystemException.class)
    public void testDeleteResources_NonAdministrator_Self() throws Exception {
      deleteResourcesTest(TestAuthenticationFactory.createClusterAdministrator("User1", 2L), "User1");
    }
  
    @Test(expected = SystemException.class)
    public void testDeleteResources_NonAdministrator_Other() throws Exception {
      deleteResourcesTest(TestAuthenticationFactory.createClusterAdministrator("User1", 2L), "User10");
    }
  
    private void getResourcesTest(Authentication authentication, String requestedUsername) throws Exception {
      Injector injector = createInjector();
  
      UserEntity userEntity = createMockUserEntity(requestedUsername);
  
      UserDAO userDAO = injector.getInstance(UserDAO.class);
      expect(userDAO.findUserByName(requestedUsername)).andReturn(userEntity).atLeastOnce();
  
      WidgetLayoutDAO widgetLayoutDAO = injector.getInstance(WidgetLayoutDAO.class);
      expect(widgetLayoutDAO.findById(1L)).andReturn(createMockWidgetLayout(1L, requestedUsername)).atLeastOnce();
      expect(widgetLayoutDAO.findById(2L)).andReturn(createMockWidgetLayout(2L, requestedUsername)).atLeastOnce();
  
      Cluster cluster = createNiceMock(Cluster.class);
      expect(cluster.getClusterName()).andReturn("c1").atLeastOnce();
      expect(cluster.getResourceId()).andReturn(4L).anyTimes();
  
      Clusters clusters = injector.getInstance(Clusters.class);
      expect(clusters.getClusterById(2L)).andReturn(cluster).atLeastOnce();
  
      replayAll();
  
      AmbariMetaInfo ambariMetaInfo = injector.getInstance(AmbariMetaInfo.class);
      ambariMetaInfo.init();
  
      SecurityContextHolder.getContext().setAuthentication(authentication);
  
      AmbariManagementController managementController = injector.getInstance(AmbariManagementController.class);
  
      ResourceProvider provider = getResourceProvider(injector, managementController);
  
      Set<String> propertyIds = PropertyHelper.getPropertyIds(Resource.Type.ActiveWidgetLayout);
  
      Request request = PropertyHelper.getReadRequest(propertyIds);
  
      Set<Resource> resources = provider.getResources(request, createPredicate(requestedUsername));
  
      Assert.assertEquals(2, resources.size());
      for (Resource resource : resources) {
  
        Long id = (Long) resource.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_ID_PROPERTY_ID);
  
        Assert.assertEquals("section" + id, resource.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_SECTION_NAME_PROPERTY_ID));
        Assert.assertEquals("CLUSTER", resource.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_SCOPE_PROPERTY_ID));
        Assert.assertEquals(requestedUsername, resource.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_USERNAME_PROPERTY_ID));
        Assert.assertEquals("display name" + id, resource.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_DISPLAY_NAME_PROPERTY_ID));
        Assert.assertEquals("layout name" + id, resource.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_LAYOUT_NAME_PROPERTY_ID));
  
        Assert.assertEquals("[]", resource.getPropertyValue(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_WIDGETS_PROPERTY_ID).toString());
      }
  
      verifyAll();
    }
  
    private void createResourcesTest(Authentication authentication, String requestedUsername) throws Exception {
      Injector injector = createInjector();
  
      replayAll();
  
      AmbariMetaInfo ambariMetaInfo = injector.getInstance(AmbariMetaInfo.class);
      ambariMetaInfo.init();
  
      SecurityContextHolder.getContext().setAuthentication(authentication);
  
      AmbariManagementController managementController = injector.getInstance(AmbariManagementController.class);
  
      ResourceProvider provider = getResourceProvider(injector, managementController);
  
      // add the property map to a set for the request.  add more maps for multiple creates
      Set<Map<String, Object>> propertySet = new LinkedHashSet<>();
  
      Map<String, Object> properties = new LinkedHashMap<>();
  
      // add properties to the request map
      properties.put(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_USERNAME_PROPERTY_ID, requestedUsername);
  
      propertySet.add(properties);
  
      // create the request
      Request request = PropertyHelper.getCreateRequest(propertySet, null);
  
      provider.createResources(request);
  
      verifyAll();
    }
  
    private void updateResourcesTest(Authentication authentication, String requestedUsername) throws Exception {
      updateResourcesTest(authentication, requestedUsername, true);
    }
  
    private void updateResourcesTest(Authentication authentication, String requestedUsername, boolean setUserName) throws Exception {
      Injector injector = createInjector();
  
      Capture<? extends String> widgetLayoutJsonCapture = newCapture();
  
      UserEntity userEntity = createMockUserEntity(requestedUsername);
      userEntity.setActiveWidgetLayouts(capture(widgetLayoutJsonCapture));
      expectLastCall().once();
  
      UserDAO userDAO = injector.getInstance(UserDAO.class);
      expect(userDAO.findUserByName(requestedUsername)).andReturn(userEntity).atLeastOnce();
      expect(userDAO.merge(userEntity)).andReturn(userEntity).atLeastOnce();
  
      WidgetLayoutDAO widgetLayoutDAO = injector.getInstance(WidgetLayoutDAO.class);
      expect(widgetLayoutDAO.findById(1L)).andReturn(createMockWidgetLayout(1L, requestedUsername)).atLeastOnce();
      expect(widgetLayoutDAO.findById(2L)).andReturn(createMockWidgetLayout(2L, requestedUsername)).atLeastOnce();
  
      replayAll();
  
      AmbariMetaInfo ambariMetaInfo = injector.getInstance(AmbariMetaInfo.class);
      ambariMetaInfo.init();
  
      SecurityContextHolder.getContext().setAuthentication(authentication);
  
      AmbariManagementController managementController = injector.getInstance(AmbariManagementController.class);
  
      Set<Map<String, String>> widgetLayouts = new HashSet<>();
      HashMap<String, String> layout;
  
      layout = new HashMap<>();
      layout.put("id", "1");
      widgetLayouts.add(layout);
  
      layout = new HashMap<>();
      layout.put("id", "2");
      widgetLayouts.add(layout);
  
      HashMap<String, Object> requestProps = new HashMap<>();
      requestProps.put(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT, widgetLayouts);
      if (setUserName) {
        requestProps.put(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_USERNAME_PROPERTY_ID, requestedUsername);
      }
  
      Request request = PropertyHelper.getUpdateRequest(requestProps, null);
  
      ResourceProvider provider = getResourceProvider(injector, managementController);
  
      provider.updateResources(request, createPredicate(requestedUsername));
  
      verifyAll();
  
      String json = widgetLayoutJsonCapture.getValue();
      Assert.assertNotNull(json);
  
      Set capturedWidgetLayouts = new Gson().fromJson(json, widgetLayouts.getClass());
      Assert.assertEquals(widgetLayouts, capturedWidgetLayouts);
    }
  
    private void deleteResourcesTest(Authentication authentication, String requestedUsername) throws Exception {
      Injector injector = createInjector();
  
      UserEntity userEntity = createMockUserEntity(requestedUsername);
  
      UserDAO userDAO = injector.getInstance(UserDAO.class);
      expect(userDAO.findUserByName(requestedUsername)).andReturn(userEntity).atLeastOnce();
  
      replayAll();
  
      AmbariMetaInfo ambariMetaInfo = injector.getInstance(AmbariMetaInfo.class);
      ambariMetaInfo.init();
  
      SecurityContextHolder.getContext().setAuthentication(authentication);
  
      AmbariManagementController managementController = injector.getInstance(AmbariManagementController.class);
  
      ResourceProvider provider = getResourceProvider(injector, managementController);
  
      provider.deleteResources(new RequestImpl(null, null, null, null), createPredicate(requestedUsername));
  
      verifyAll();
    }
  
    private ResourceProvider getResourceProvider(Injector injector, AmbariManagementController managementController) throws Exception {
      ActiveWidgetLayoutResourceProvider.init(injector.getInstance(UserDAO.class),
          injector.getInstance(WidgetDAO.class),
          injector.getInstance(WidgetLayoutDAO.class),
          new Gson());
  
      return AbstractControllerResourceProvider.getResourceProvider(
          Resource.Type.ActiveWidgetLayout,
          managementController);
    }
  
    private Predicate createPredicate(String requestedUsername) {
      return new PredicateBuilder()
          .property(ActiveWidgetLayoutResourceProvider.WIDGETLAYOUT_USERNAME_PROPERTY_ID)
          .equals(requestedUsername)
          .toPredicate();
    }
  
    private WidgetLayoutEntity createMockWidgetLayout(Long id, String username) {
      WidgetLayoutEntity widgetLayoutEntity = createMock(WidgetLayoutEntity.class);
      expect(widgetLayoutEntity.getId()).andReturn(id).anyTimes();
      expect(widgetLayoutEntity.getUserName()).andReturn(username).anyTimes();
      expect(widgetLayoutEntity.getLayoutName()).andReturn("layout name" + id).anyTimes();
      expect(widgetLayoutEntity.getSectionName()).andReturn("section" + id).anyTimes();
      expect(widgetLayoutEntity.getScope()).andReturn("CLUSTER").anyTimes();
      expect(widgetLayoutEntity.getDisplayName()).andReturn("display name" + id).anyTimes();
      expect(widgetLayoutEntity.getClusterId()).andReturn(2L).anyTimes();
      expect(widgetLayoutEntity.getListWidgetLayoutUserWidgetEntity()).andReturn(Collections.emptyList()).anyTimes();
      return widgetLayoutEntity;
    }
  
    private UserEntity createMockUserEntity(String username) {
      UserEntity userEntity = createMock(UserEntity.class);
      expect(userEntity.getUserId()).andReturn(username.hashCode()).anyTimes();
      expect(userEntity.getUserName()).andReturn(username).anyTimes();
      expect(userEntity.getActiveWidgetLayouts()).andReturn("[{\"id\":\"1\"},{\"id\":\"2\"}]").anyTimes();
  
      return userEntity;
    }
  
    private Injector createInjector() throws Exception {
      return Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          install(new FactoryModuleBuilder().build(UpgradeContextFactory.class));
          install(new FactoryModuleBuilder().build(RoleGraphFactory.class));
          install(new FactoryModuleBuilder().build(ConfigureClusterTaskFactory.class));
  
          bind(PersistedState.class).to(PersistedStateImpl.class);
          bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class));
          bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class));
          bind(ActionDBAccessor.class).toInstance(createNiceMock(ActionDBAccessor.class));
          bind(ExecutionScheduler.class).toInstance(createNiceMock(ExecutionScheduler.class));
          bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class));
          bind(AmbariMetaInfo.class).toInstance(createMock(AmbariMetaInfo.class));
          bind(ActionManager.class).toInstance(createNiceMock(ActionManager.class));
          bind(org.apache.ambari.server.actionmanager.RequestFactory.class).toInstance(createNiceMock(org.apache.ambari.server.actionmanager.RequestFactory.class));
          bind(RequestExecutionFactory.class).toInstance(createNiceMock(RequestExecutionFactory.class));
          bind(StageFactory.class).toInstance(createNiceMock(StageFactory.class));
          bind(Clusters.class).toInstance(createNiceMock(Clusters.class));
          bind(AbstractRootServiceResponseFactory.class).toInstance(createNiceMock(AbstractRootServiceResponseFactory.class));
          bind(StackManagerFactory.class).toInstance(createNiceMock(StackManagerFactory.class));
          bind(ConfigFactory.class).toInstance(createNiceMock(ConfigFactory.class));
          bind(ConfigGroupFactory.class).toInstance(createNiceMock(ConfigGroupFactory.class));
          bind(ServiceFactory.class).toInstance(createNiceMock(ServiceFactory.class));
          bind(ServiceComponentFactory.class).toInstance(createNiceMock(ServiceComponentFactory.class));
          bind(ServiceComponentHostFactory.class).toInstance(createNiceMock(ServiceComponentHostFactory.class));
          bind(PasswordEncoder.class).toInstance(createNiceMock(PasswordEncoder.class));
          bind(KerberosHelper.class).toInstance(createNiceMock(KerberosHelper.class));
          bind(Users.class).toInstance(createMock(Users.class));
          bind(AmbariManagementController.class).to(AmbariManagementControllerImpl.class);
          bind(RoleCommandOrderProvider.class).to(CachedRoleCommandOrderProvider.class);
          bind(CredentialStoreService.class).to(CredentialStoreServiceImpl.class);
          bind(UserDAO.class).toInstance(createMock(UserDAO.class));
          bind(WidgetLayoutDAO.class).toInstance(createMock(WidgetLayoutDAO.class));
          bind(HostRoleCommandDAO.class).toInstance(createMock(HostRoleCommandDAO.class));
          bind(HookContextFactory.class).toInstance(createMock(HookContextFactory.class));
          bind(HookService.class).toInstance(createMock(HookService.class));
          bind(HostRoleCommandFactory.class).to(HostRoleCommandFactoryImpl.class);
        }
      });
    }
  }
  