Browse Source

AMBARI-7737. User in group with cluster operate permission have only read permission functionality.

Siddharth Wagle 10 years ago
parent
commit
4bbaf7f2a5
17 changed files with 695 additions and 16 deletions
  1. 5 1
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
  2. 5 3
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/UserResourceDefinition.java
  3. 79 0
      ambari-server/src/main/java/org/apache/ambari/server/api/services/UserPrivilegeService.java
  4. 4 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
  5. 2 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
  6. 8 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java
  7. 215 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java
  8. 3 1
      ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
  9. 13 2
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterDAO.java
  10. 17 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java
  11. 17 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java
  12. 27 6
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewInstanceDAO.java
  13. 5 1
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
  14. 11 2
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
  15. 48 0
      ambari-server/src/test/java/org/apache/ambari/server/api/resources/UserResourceDefinitionTest.java
  16. 111 0
      ambari-server/src/test/java/org/apache/ambari/server/api/services/UserPrivilegeServiceTest.java
  17. 125 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java

+ 5 - 1
ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java

@@ -140,7 +140,7 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
       case StackVersion:
         resourceDefinition = new StackVersionResourceDefinition();
         break;
-        
+
       case StackLevelConfiguration:
         resourceDefinition = new StackLevelConfigurationResourceDefinition();
         break;
@@ -278,6 +278,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         resourceDefinition = new PrivilegeResourceDefinition(Resource.Type.ViewPrivilege);
         break;
 
+      case UserPrivilege:
+        resourceDefinition = new PrivilegeResourceDefinition(Resource.Type.UserPrivilege);
+        break;
+
       case ViewPermission:
         resourceDefinition = new ViewPermissionResourceDefinition();
         break;

+ 5 - 3
ambari-server/src/main/java/org/apache/ambari/server/api/resources/UserResourceDefinition.java

@@ -17,7 +17,7 @@
  */
 package org.apache.ambari.server.api.resources;
 
-import java.util.Collections;
+import java.util.HashSet;
 import java.util.Set;
 
 import org.apache.ambari.server.controller.spi.Resource;
@@ -30,7 +30,7 @@ public class UserResourceDefinition extends BaseResourceDefinition {
   public UserResourceDefinition() {
     super(Resource.Type.User);
   }
-  
+
   @Override
   public String getPluralName() {
     return "users";
@@ -43,7 +43,9 @@ public class UserResourceDefinition extends BaseResourceDefinition {
 
   @Override
   public Set<SubResourceDefinition> getSubResourceDefinitions() {
-    return Collections.emptySet();
+    final Set<SubResourceDefinition> subResourceDefinitions = new HashSet<SubResourceDefinition>();
+    subResourceDefinitions.add(new SubResourceDefinition(Resource.Type.UserPrivilege));
+    return subResourceDefinitions;
   }
 
 }

+ 79 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/services/UserPrivilegeService.java

@@ -0,0 +1,79 @@
+/**
+ * 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 privileges and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.services;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ *  Service responsible for user privilege resource requests.
+ */
+public class UserPrivilegeService extends PrivilegeService {
+
+  private final String userName;
+
+  public UserPrivilegeService(String userName) {
+    this.userName = userName;
+  }
+
+  // ----- PrivilegeService --------------------------------------------------
+
+  @Override
+  public Response createPrivilege(String body, HttpHeaders headers, UriInfo ui) {
+    return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build();
+  }
+
+  @Override
+  public Response updatePrivilege(String body, HttpHeaders headers, UriInfo ui,
+      String privilegeId) {
+    return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build();
+  }
+
+  @Override
+  public Response updatePrivileges(String body, HttpHeaders headers, UriInfo ui) {
+    return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build();
+  }
+
+  @Override
+  public Response deletePrivilege(HttpHeaders headers, UriInfo ui,
+      String privilegeId) {
+    return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build();
+  }
+
+  @Override
+  public Response deletePrivileges(String body, HttpHeaders headers, UriInfo ui) {
+    return Response.status(HttpServletResponse.SC_NOT_IMPLEMENTED).build();
+  }
+
+  @Override
+  protected ResourceInstance createPrivilegeResource(String privilegeId) {
+    final Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.User, userName);
+    mapIds.put(Resource.Type.UserPrivilege, privilegeId);
+    return createResource(Resource.Type.UserPrivilege, mapIds);
+  }
+}

+ 4 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java

@@ -59,6 +59,7 @@ import org.apache.ambari.server.controller.internal.PrivilegeResourceProvider;
 import org.apache.ambari.server.controller.internal.StackAdvisorResourceProvider;
 import org.apache.ambari.server.controller.internal.StackDefinedPropertyProvider;
 import org.apache.ambari.server.controller.internal.StackDependencyResourceProvider;
+import org.apache.ambari.server.controller.internal.UserPrivilegeResourceProvider;
 import org.apache.ambari.server.controller.internal.ViewPermissionResourceProvider;
 import org.apache.ambari.server.controller.nagios.NagiosPropertyProvider;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
@@ -72,6 +73,7 @@ import org.apache.ambari.server.orm.dao.PrincipalDAO;
 import org.apache.ambari.server.orm.dao.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.ResourceDAO;
 import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.MetainfoEntity;
 import org.apache.ambari.server.resources.ResourceManager;
 import org.apache.ambari.server.resources.api.rest.GetResource;
@@ -583,6 +585,8 @@ public class AmbariServer {
     PrivilegeResourceProvider.init(injector.getInstance(PrivilegeDAO.class), injector.getInstance(UserDAO.class),
         injector.getInstance(GroupDAO.class), injector.getInstance(PrincipalDAO.class),
         injector.getInstance(PermissionDAO.class), injector.getInstance(ResourceDAO.class));
+    UserPrivilegeResourceProvider.init(injector.getInstance(UserDAO.class), injector.getInstance(ClusterDAO.class),
+        injector.getInstance(GroupDAO.class), injector.getInstance(ViewInstanceDAO.class));
     ClusterPrivilegeResourceProvider.init(injector.getInstance(ClusterDAO.class));
     AmbariPrivilegeResourceProvider.init(injector.getInstance(ClusterDAO.class));
   }

+ 2 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java

@@ -81,6 +81,8 @@ public class DefaultProviderModule extends AbstractProviderModule {
         return new ClusterPrivilegeResourceProvider();
       case LdapSyncEvent:
         return new LdapSyncEventResourceProvider(managementController);
+      case UserPrivilege:
+        return new UserPrivilegeResourceProvider();
       default:
         return AbstractControllerResourceProvider.getResourceProvider(type, propertyIds,
             keyPropertyIds, managementController);

+ 8 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java

@@ -385,6 +385,8 @@ public abstract class PrivilegeResourceProvider<T> extends AbstractResourceProvi
               " permission on a " + entity.getResource().getResourceType().getName() + " resource.");
         }
         privilegeDAO.create(entity);
+        entity.getPrincipal().getPrivileges().add(entity);
+        principalDAO.merge(entity.getPrincipal());
         return null;
       }
     };
@@ -406,6 +408,8 @@ public abstract class PrivilegeResourceProvider<T> extends AbstractResourceProvi
                 throw new AmbariException("Can't remove " + entity.getPermission().getResourceType().getName() +
                     " permission from a " + entity.getResource().getResourceType().getName() + " resource.");
               }
+              entity.getPrincipal().getPrivileges().remove(entity);
+              principalDAO.merge(entity.getPrincipal());
               privilegeDAO.remove(entity);
             }
           }
@@ -461,6 +465,8 @@ public abstract class PrivilegeResourceProvider<T> extends AbstractResourceProvi
             }
 
             privilegeDAO.create(requiredPrivilege);
+            requiredPrivilege.getPrincipal().getPrivileges().add(requiredPrivilege);
+            principalDAO.merge(requiredPrivilege.getPrincipal());
           }
         }
         for (PrivilegeEntity currentPrivilege: currentPrivileges) {
@@ -477,6 +483,8 @@ public abstract class PrivilegeResourceProvider<T> extends AbstractResourceProvi
               throw new AmbariException("Can't remove " + currentPrivilege.getPermission().getResourceType().getName() +
                   " permission from a " + currentPrivilege.getResource().getResourceType().getName() + " resource.");
             }
+            currentPrivilege.getPrincipal().getPrivileges().remove(currentPrivilege);
+            principalDAO.merge(currentPrivilege.getPrincipal());
             privilegeDAO.remove(currentPrivilege);
           }
         }

+ 215 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProvider.java

@@ -0,0 +1,215 @@
+/**
+ * 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 privileges and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.controller.internal;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+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.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.orm.dao.ClusterDAO;
+import org.apache.ambari.server.orm.dao.GroupDAO;
+import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
+import org.apache.ambari.server.orm.entities.ClusterEntity;
+import org.apache.ambari.server.orm.entities.GroupEntity;
+import org.apache.ambari.server.orm.entities.MemberEntity;
+import org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
+import org.apache.ambari.server.orm.entities.PrivilegeEntity;
+import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+
+/**
+ * Resource provider for user privilege resources.
+ */
+public class UserPrivilegeResourceProvider extends ReadOnlyResourceProvider {
+
+  protected static final String PRIVILEGE_PRIVILEGE_ID_PROPERTY_ID    = PrivilegeResourceProvider.PRIVILEGE_ID_PROPERTY_ID;
+  protected static final String PRIVILEGE_PERMISSION_NAME_PROPERTY_ID = PrivilegeResourceProvider.PERMISSION_NAME_PROPERTY_ID;
+  protected static final String PRIVILEGE_PRINCIPAL_NAME_PROPERTY_ID  = PrivilegeResourceProvider.PRINCIPAL_NAME_PROPERTY_ID;
+  protected static final String PRIVILEGE_PRINCIPAL_TYPE_PROPERTY_ID  = PrivilegeResourceProvider.PRINCIPAL_TYPE_PROPERTY_ID;
+  protected static final String PRIVILEGE_VIEW_NAME_PROPERTY_ID       = ViewPrivilegeResourceProvider.PRIVILEGE_VIEW_NAME_PROPERTY_ID;
+  protected static final String PRIVILEGE_VIEW_VERSION_PROPERTY_ID    = ViewPrivilegeResourceProvider.PRIVILEGE_VIEW_VERSION_PROPERTY_ID;
+  protected static final String PRIVILEGE_INSTANCE_NAME_PROPERTY_ID   = ViewPrivilegeResourceProvider.PRIVILEGE_INSTANCE_NAME_PROPERTY_ID;
+  protected static final String PRIVILEGE_CLUSTER_NAME_PROPERTY_ID    = ClusterPrivilegeResourceProvider.PRIVILEGE_CLUSTER_NAME_PROPERTY_ID;
+  protected static final String PRIVILEGE_TYPE_PROPERTY_ID            = AmbariPrivilegeResourceProvider.PRIVILEGE_TYPE_PROPERTY_ID;
+  protected static final String PRIVILEGE_USER_NAME_PROPERTY_ID       = "PrivilegeInfo/user_name";
+
+  /**
+   * Data access object used to obtain user entities.
+   */
+  protected static UserDAO userDAO;
+
+  /**
+   * Data access object used to obtain cluster entities.
+   */
+  protected static ClusterDAO clusterDAO;
+
+  /**
+   * Data access object used to obtain group entities.
+   */
+  protected static GroupDAO groupDAO;
+
+  /**
+   * Data access object used to obtain view instance entities.
+   */
+  protected static ViewInstanceDAO viewInstanceDAO;
+
+  /**
+   * The property ids for a privilege resource.
+   */
+  private static Set<String> propertyIds = new HashSet<String>();
+  static {
+    propertyIds.add(PRIVILEGE_PRIVILEGE_ID_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_PERMISSION_NAME_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_PRINCIPAL_NAME_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_PRINCIPAL_TYPE_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_VIEW_NAME_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_VIEW_VERSION_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_INSTANCE_NAME_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_CLUSTER_NAME_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_TYPE_PROPERTY_ID);
+    propertyIds.add(PRIVILEGE_USER_NAME_PROPERTY_ID);
+  }
+
+  /**
+   * Static initialization.
+   *
+   * @param userDAO         the user data access object
+   * @param clusterDAO      the cluster data access object
+   * @param groupDAO        the group data access object
+   * @param viewInstanceDAO the view instance data access object
+   */
+  public static void init(UserDAO userDAO, ClusterDAO clusterDAO, GroupDAO groupDAO,
+                          ViewInstanceDAO viewInstanceDAO) {
+    UserPrivilegeResourceProvider.userDAO         = userDAO;
+    UserPrivilegeResourceProvider.clusterDAO      = clusterDAO;
+    UserPrivilegeResourceProvider.groupDAO        = groupDAO;
+    UserPrivilegeResourceProvider.viewInstanceDAO = viewInstanceDAO;
+  }
+
+  @SuppressWarnings("serial")
+  private static Set<String> pkPropertyIds = new HashSet<String>() {
+    {
+      add(PRIVILEGE_PRIVILEGE_ID_PROPERTY_ID);
+    }
+  };
+
+  /**
+   * The key property ids for a privilege resource.
+   */
+  private static Map<Resource.Type, String> keyPropertyIds = new HashMap<Resource.Type, String>();
+  static {
+    keyPropertyIds.put(Resource.Type.User, PRIVILEGE_USER_NAME_PROPERTY_ID);
+    keyPropertyIds.put(Resource.Type.UserPrivilege, PRIVILEGE_PRIVILEGE_ID_PROPERTY_ID);
+  }
+
+
+  /**
+   * Constructor.
+   */
+  public UserPrivilegeResourceProvider() {
+    super(propertyIds, keyPropertyIds, null);
+  }
+
+  // ----- PrivilegeResourceProvider -----------------------------------------
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds;
+  }
+
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+    final Set<Resource> resources = new HashSet<Resource>();
+    final Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+
+    for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+      final String userName = (String) propertyMap.get(PRIVILEGE_USER_NAME_PROPERTY_ID);
+
+      if (userName != null) {
+        UserEntity userEntity = userDAO.findLocalUserByName(userName);
+        if (userEntity == null) {
+          userEntity = userDAO.findLdapUserByName(userName);
+        }
+        if (userEntity == null) {
+          throw new SystemException("User " + userName + " was not found");
+        }
+
+        final Set<PrivilegeEntity> privileges = userEntity.getPrincipal().getPrivileges();
+        for (MemberEntity membership : userEntity.getMemberEntities()) {
+          privileges.addAll(membership.getGroup().getPrincipal().getPrivileges());
+        }
+
+        for (PrivilegeEntity privilegeEntity : privileges) {
+          final ResourceImpl resource = new ResourceImpl(Resource.Type.UserPrivilege);
+
+          setResourceProperty(resource, PRIVILEGE_USER_NAME_PROPERTY_ID, userName, requestedIds);
+          setResourceProperty(resource, PRIVILEGE_PRIVILEGE_ID_PROPERTY_ID, privilegeEntity.getId(), requestedIds);
+          setResourceProperty(resource, PRIVILEGE_PERMISSION_NAME_PROPERTY_ID, privilegeEntity.getPermission().getPermissionName(), requestedIds);
+          setResourceProperty(resource, PRIVILEGE_PRINCIPAL_TYPE_PROPERTY_ID, privilegeEntity.getPrincipal().getPrincipalType().getName(), requestedIds);
+
+          final String principalTypeName = privilegeEntity.getPrincipal().getPrincipalType().getName();
+          if (principalTypeName.equals(PrincipalTypeEntity.USER_PRINCIPAL_TYPE_NAME)) {
+            final UserEntity user = userDAO.findUserByPrincipal(privilegeEntity.getPrincipal());
+            setResourceProperty(resource, PRIVILEGE_PRINCIPAL_NAME_PROPERTY_ID, user.getUserName(), requestedIds);
+          } else if (principalTypeName.equals(PrincipalTypeEntity.GROUP_PRINCIPAL_TYPE_NAME)) {
+            final GroupEntity groupEntity = groupDAO.findGroupByPrincipal(privilegeEntity.getPrincipal());
+            setResourceProperty(resource, PRIVILEGE_PRINCIPAL_NAME_PROPERTY_ID, groupEntity.getGroupName(), requestedIds);
+          }
+
+          String privilegeType;
+          switch (privilegeEntity.getResource().getResourceType().getId()) {
+          case ResourceTypeEntity.CLUSTER_RESOURCE_TYPE:
+            final ClusterEntity clusterEntity = clusterDAO.findByResourceId(privilegeEntity.getResource().getId());
+            privilegeType = ResourceTypeEntity.CLUSTER_RESOURCE_TYPE_NAME;
+            setResourceProperty(resource, PRIVILEGE_CLUSTER_NAME_PROPERTY_ID, clusterEntity.getClusterName(), requestedIds);
+            break;
+          case ResourceTypeEntity.AMBARI_RESOURCE_TYPE:
+            privilegeType = ResourceTypeEntity.AMBARI_RESOURCE_TYPE_NAME;
+            break;
+          default:
+            privilegeType = ResourceTypeEntity.VIEW_RESOURCE_TYPE_NAME;
+            final ViewInstanceEntity viewInstanceEntity = viewInstanceDAO.findByResourceId(privilegeEntity.getResource().getId());
+            final ViewEntity viewEntity = viewInstanceEntity.getViewEntity();
+
+            setResourceProperty(resource, PRIVILEGE_VIEW_NAME_PROPERTY_ID, viewEntity.getCommonName(), requestedIds);
+            setResourceProperty(resource, PRIVILEGE_VIEW_VERSION_PROPERTY_ID, viewEntity.getVersion(), requestedIds);
+            setResourceProperty(resource, PRIVILEGE_INSTANCE_NAME_PROPERTY_ID, viewInstanceEntity.getName(), requestedIds);
+            break;
+          }
+          setResourceProperty(resource, PRIVILEGE_TYPE_PROPERTY_ID, privilegeType, requestedIds);
+
+          resources.add(resource);
+        }
+      }
+    }
+    return resources;
+  }
+}

+ 3 - 1
ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java

@@ -124,7 +124,8 @@ public interface Resource {
     ViewPermission,
     ClientConfig,
     StackLevelConfiguration,
-    LdapSyncEvent;
+    LdapSyncEvent,
+    UserPrivilege;
 
     /**
      * Get the {@link Type} that corresponds to this InternalType.
@@ -210,6 +211,7 @@ public interface Resource {
     public static final Type ClientConfig = InternalType.ClientConfig.getType();
     public static final Type StackLevelConfiguration = InternalType.StackLevelConfiguration.getType();
     public static final Type LdapSyncEvent = InternalType.LdapSyncEvent.getType();
+    public static final Type UserPrivilege = InternalType.UserPrivilege.getType();
 
     /**
      * The type name.

+ 13 - 2
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterDAO.java

@@ -28,7 +28,6 @@ import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Root;
 
 import com.google.inject.Singleton;
-import org.apache.ambari.server.controller.ivory.Cluster;
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
@@ -66,6 +65,18 @@ public class ClusterDAO {
     }
   }
 
+
+  @RequiresSession
+  public ClusterEntity findByResourceId(long resourceId) {
+    TypedQuery<ClusterEntity> query = entityManagerProvider.get().createNamedQuery("clusterByResourceId", ClusterEntity.class);
+    query.setParameter("resourceId", resourceId);
+    try {
+      return query.getSingleResult();
+    } catch (NoResultException ignored) {
+      return null;
+    }
+  }
+
   @RequiresSession
   public List<ClusterEntity> findAll() {
     TypedQuery<ClusterEntity> query = entityManagerProvider.get().createNamedQuery("allClusters", ClusterEntity.class);
@@ -126,7 +137,7 @@ public class ClusterDAO {
   public void createConfig(ClusterConfigEntity entity) {
     entityManagerProvider.get().persist(entity);
   }
-  
+
   /**
    * Remove a cluster configuration in the DB.
    */

+ 17 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/GroupDAO.java

@@ -81,6 +81,23 @@ public class GroupDAO {
     return daoUtils.selectList(query);
   }
 
+  /**
+   * Find the group entity for the given admin principal entity.
+   *
+   * @param principal the principal entity
+   *
+   * @return the matching gropu entity
+   */
+  public GroupEntity findGroupByPrincipal(PrincipalEntity principal) {
+    if (principal == null) {
+      return null;
+    }
+    final TypedQuery<GroupEntity> query = entityManagerProvider.get().createQuery("SELECT group_entity FROM GroupEntity group_entity WHERE group_entity.principal.id=:principalId", GroupEntity.class);
+    query.setParameter("principalId", principal.getId());
+    return daoUtils.selectSingle(query);
+  }
+
+
   @Transactional
   public void create(GroupEntity group) {
     create(new HashSet<GroupEntity>(Arrays.asList(group)));

+ 17 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/UserDAO.java

@@ -104,6 +104,23 @@ public class UserDAO {
     return daoUtils.selectList(query);
   }
 
+  /**
+   * Find the user entity for the given admin principal entity.
+   *
+   * @param principal the principal entity
+   *
+   * @return the matching user entity
+   */
+  public UserEntity findUserByPrincipal(PrincipalEntity principal) {
+    if (principal == null) {
+      return null;
+    }
+    final TypedQuery<UserEntity> query = entityManagerProvider.get().createQuery("SELECT user_entity FROM UserEntity user_entity WHERE user_entity.principal.id=:principalId", UserEntity.class);
+    query.setParameter("principalId", principal.getId());
+    return daoUtils.selectSingle(query);
+  }
+
+
   @Transactional
   public void create(UserEntity user) {
     create(new HashSet<UserEntity>(Arrays.asList(user)));

+ 27 - 6
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ViewInstanceDAO.java

@@ -18,16 +18,20 @@
 
 package org.apache.ambari.server.orm.dao;
 
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.ViewInstanceDataEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import com.google.inject.persist.Transactional;
-import org.apache.ambari.server.orm.entities.ViewInstanceDataEntity;
-import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
-
-import javax.persistence.EntityManager;
-import javax.persistence.TypedQuery;
-import java.util.List;
 
 /**
  * View Instance Data Access Object.
@@ -57,6 +61,23 @@ public class ViewInstanceDAO {
     return daoUtils.selectSingle(query, viewName, instanceName);
   }
 
+  /**
+   * Find a view instance by given resource id.
+   *
+   * @param resourceId resource id
+   * @return a matching view instance or null
+   */
+  @RequiresSession
+  public ViewInstanceEntity findByResourceId(long resourceId) {
+    TypedQuery<ViewInstanceEntity> query = entityManagerProvider.get().createNamedQuery("viewInstanceByResourceId", ViewInstanceEntity.class);
+    query.setParameter("resourceId", resourceId);
+    try {
+      return query.getSingleResult();
+    } catch (NoResultException ignored) {
+      return null;
+    }
+  }
+
   /**
    * Find all view instances.
    *

+ 5 - 1
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java

@@ -52,7 +52,11 @@ import org.apache.ambari.server.state.State;
             "WHERE cluster.clusterName=:clusterName"),
     @NamedQuery(name = "allClusters", query =
         "SELECT clusters " +
-            "FROM ClusterEntity clusters")
+            "FROM ClusterEntity clusters"),
+    @NamedQuery(name = "clusterByResourceId", query =
+        "SELECT cluster " +
+            "FROM ClusterEntity cluster " +
+            "WHERE cluster.resource.id=:resourceId")
 })
 @Entity
 @TableGenerator(name = "cluster_id_generator",

+ 11 - 2
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java

@@ -23,6 +23,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+
 import javax.persistence.Basic;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
@@ -33,6 +34,7 @@ import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.JoinColumns;
 import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
@@ -58,8 +60,15 @@ import org.apache.ambari.view.ViewInstanceDefinition;
     name = "UQ_viewinstance_name", columnNames = {"view_name", "name"}
   )
 )
-@NamedQuery(name = "allViewInstances",
-  query = "SELECT viewInstance FROM ViewInstanceEntity viewInstance")
+@NamedQueries({
+  @NamedQuery(name = "allViewInstances",
+      query = "SELECT viewInstance FROM ViewInstanceEntity viewInstance"),
+  @NamedQuery(name = "viewInstanceByResourceId", query =
+      "SELECT viewInstance " +
+          "FROM ViewInstanceEntity viewInstance " +
+          "WHERE viewInstance.resource.id=:resourceId")
+})
+
 @TableGenerator(name = "view_instance_id_generator",
   table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value"
   , pkColumnValue = "view_instance_id_seq"

+ 48 - 0
ambari-server/src/test/java/org/apache/ambari/server/api/resources/UserResourceDefinitionTest.java

@@ -0,0 +1,48 @@
+/**
+ * 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.api.resources;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Set;
+
+/**
+ * UserResourceDefinition tests.
+ */
+public class UserResourceDefinitionTest {
+  @Test
+  public void testGetPluralName() throws Exception {
+    final UserResourceDefinition userResourceDefinition = new UserResourceDefinition();
+    Assert.assertEquals("users", userResourceDefinition.getPluralName());
+  }
+
+  @Test
+  public void testGetSingularName() throws Exception {
+    final UserResourceDefinition userResourceDefinition = new UserResourceDefinition();
+    Assert.assertEquals("user", userResourceDefinition.getSingularName());
+  }
+
+  @Test
+  public void testGetSubResourceDefinitions() throws Exception {
+    final UserResourceDefinition userResourceDefinition = new UserResourceDefinition();
+    Set<SubResourceDefinition> subResourceDefinitions = userResourceDefinition.getSubResourceDefinitions();
+    Assert.assertEquals(1, subResourceDefinitions.size());
+  }
+}

+ 111 - 0
ambari-server/src/test/java/org/apache/ambari/server/api/services/UserPrivilegeServiceTest.java

@@ -0,0 +1,111 @@
+/**
+ * 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.api.services;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import junit.framework.Assert;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.services.parsers.RequestBodyParser;
+import org.apache.ambari.server.api.services.serializers.ResultSerializer;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+/**
+ * Unit tests for GroupService.
+ */
+public class UserPrivilegeServiceTest extends BaseServiceTest {
+
+  public List<ServiceTestInvocation> getTestInvocations() throws Exception {
+    List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>();
+
+    UserPrivilegeService userPrivilegeService;
+    Method m;
+    Object[] args;
+
+    //getPrivilege
+    userPrivilegeService = new TestUserPrivilegeService();
+    m = userPrivilegeService.getClass().getMethod("getPrivilege", HttpHeaders.class, UriInfo.class, String.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo(), "id"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, userPrivilegeService, m, args, null));
+
+    //getPrivileges
+    userPrivilegeService = new TestUserPrivilegeService();
+    m = userPrivilegeService.getClass().getMethod("getPrivileges", HttpHeaders.class, UriInfo.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo()};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, userPrivilegeService, m, args, null));
+
+    return listInvocations;
+  }
+
+  @Test
+  public void testDisabledMethods() {
+    final HttpHeaders headers = EasyMock.createNiceMock(HttpHeaders.class);
+    final UriInfo uriInfo = EasyMock.createNiceMock(UriInfo.class);
+    final UserPrivilegeService service = new TestUserPrivilegeService();
+
+    final List<Response> disabledMethods = new ArrayList<Response>();
+    disabledMethods.add(service.createPrivilege("test", headers, uriInfo));
+    disabledMethods.add(service.updatePrivilege("test", headers, uriInfo, "test"));
+    disabledMethods.add(service.updatePrivileges("test", headers, uriInfo));
+    disabledMethods.add(service.deletePrivilege(headers, uriInfo, "test"));
+    disabledMethods.add(service.deletePrivileges("test", headers, uriInfo));
+
+    for (Response response: disabledMethods) {
+      Assert.assertEquals(HttpServletResponse.SC_NOT_IMPLEMENTED, response.getStatus());
+    }
+  }
+
+  private class TestUserPrivilegeService extends UserPrivilegeService {
+
+    public TestUserPrivilegeService() {
+      super("user");
+    }
+
+    @Override
+    protected ResourceInstance createResource(Type type, Map<Type, String> mapIds) {
+      return getTestResource();
+    }
+
+    @Override
+    RequestFactory getRequestFactory() {
+      return getTestRequestFactory();
+    }
+
+    @Override
+    protected RequestBodyParser getBodyParser() {
+      return getTestBodyParser();
+    }
+
+    @Override
+    protected ResultSerializer getResultSerializer() {
+      return getTestResultSerializer();
+    }
+  }
+}

+ 125 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UserPrivilegeResourceProviderTest.java

@@ -0,0 +1,125 @@
+/**
+ * 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 java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.Assert;
+
+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.SystemException;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.dao.ClusterDAO;
+import org.apache.ambari.server.orm.dao.GroupDAO;
+import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
+import org.apache.ambari.server.orm.entities.MemberEntity;
+import org.apache.ambari.server.orm.entities.PermissionEntity;
+import org.apache.ambari.server.orm.entities.PrincipalEntity;
+import org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
+import org.apache.ambari.server.orm.entities.PrivilegeEntity;
+import org.apache.ambari.server.orm.entities.ResourceEntity;
+import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+/**
+ * UserPrivilegeResourceProvider tests.
+ */
+public class UserPrivilegeResourceProviderTest {
+
+  @Test(expected = SystemException.class)
+  public void testCreateResources() throws Exception {
+    final UserPrivilegeResourceProvider resourceProvider = new UserPrivilegeResourceProvider();
+    resourceProvider.createResources(EasyMock.createNiceMock(Request.class));
+  }
+
+  @SuppressWarnings("serial")
+  @Test
+  public void testGetResources() throws Exception {
+    final UserPrivilegeResourceProvider resourceProvider = new UserPrivilegeResourceProvider();
+    final UserDAO userDAO = EasyMock.createNiceMock(UserDAO.class);
+    final GroupDAO groupDAO = EasyMock.createNiceMock(GroupDAO.class);
+    final ClusterDAO clusterDAO = EasyMock.createNiceMock(ClusterDAO.class);
+    final ViewInstanceDAO viewInstanceDAO = EasyMock.createNiceMock(ViewInstanceDAO.class);
+    final UserEntity userEntity = EasyMock.createNiceMock(UserEntity.class);
+    final PrincipalEntity principalEntity = EasyMock.createNiceMock(PrincipalEntity.class);
+    final PrivilegeEntity privilegeEntity = EasyMock.createNiceMock(PrivilegeEntity.class);
+    final PermissionEntity permissionEntity = EasyMock.createNiceMock(PermissionEntity.class);
+    final PrincipalTypeEntity principalTypeEntity = EasyMock.createNiceMock(PrincipalTypeEntity.class);
+    final ResourceEntity resourceEntity = EasyMock.createNiceMock(ResourceEntity.class);
+    final ResourceTypeEntity resourceTypeEntity = EasyMock.createNiceMock(ResourceTypeEntity.class);
+
+    EasyMock.expect(userDAO.findLocalUserByName("user")).andReturn(userEntity).anyTimes();
+    EasyMock.expect(userEntity.getPrincipal()).andReturn(principalEntity).anyTimes();
+    EasyMock.expect(userEntity.getMemberEntities()).andReturn(Collections.<MemberEntity> emptySet()).anyTimes();
+    EasyMock.expect(privilegeEntity.getPermission()).andReturn(permissionEntity).anyTimes();
+    EasyMock.expect(privilegeEntity.getPrincipal()).andReturn(principalEntity).anyTimes();
+    EasyMock.expect(principalEntity.getPrincipalType()).andReturn(principalTypeEntity).anyTimes();
+    EasyMock.expect(principalTypeEntity.getName()).andReturn(PrincipalTypeEntity.USER_PRINCIPAL_TYPE_NAME).anyTimes();
+    EasyMock.expect(principalEntity.getPrivileges()).andReturn(new HashSet<PrivilegeEntity>() {
+      {
+        add(privilegeEntity);
+      }
+    }).anyTimes();
+    EasyMock.expect(userDAO.findUserByPrincipal(EasyMock.<PrincipalEntity>anyObject())).andReturn(userEntity).anyTimes();
+    EasyMock.expect(userEntity.getUserName()).andReturn("user").anyTimes();
+    EasyMock.expect(privilegeEntity.getResource()).andReturn(resourceEntity).anyTimes();
+    EasyMock.expect(resourceEntity.getResourceType()).andReturn(resourceTypeEntity).anyTimes();
+    EasyMock.expect(resourceTypeEntity.getId()).andReturn(ResourceTypeEntity.AMBARI_RESOURCE_TYPE);
+
+    EasyMock.replay(userDAO, userEntity, principalEntity, privilegeEntity, permissionEntity, principalTypeEntity, resourceEntity, resourceTypeEntity);
+
+    UserPrivilegeResourceProvider.init(userDAO, clusterDAO, groupDAO, viewInstanceDAO);
+
+    final Set<String> propertyIds = new HashSet<String>();
+    propertyIds.add(UserPrivilegeResourceProvider.PRIVILEGE_USER_NAME_PROPERTY_ID);
+    //propertyIds.add(UserResourceProvider.USER_PASSWORD_PROPERTY_ID);
+
+    final Predicate predicate = new PredicateBuilder().property(UserPrivilegeResourceProvider.PRIVILEGE_USER_NAME_PROPERTY_ID).equals("user").toPredicate();
+    Request request = PropertyHelper.getReadRequest(propertyIds);
+    Set<Resource> resources = resourceProvider.getResources(request, predicate);
+
+    Assert.assertEquals(1, resources.size());
+    for (Resource resource : resources) {
+      String userName = (String) resource.getPropertyValue(UserPrivilegeResourceProvider.PRIVILEGE_USER_NAME_PROPERTY_ID);
+      Assert.assertEquals("user", userName);
+    }
+
+    EasyMock.verify(userDAO, userEntity, principalEntity, privilegeEntity, permissionEntity, principalTypeEntity, resourceEntity, resourceTypeEntity);
+  }
+
+  @Test(expected = SystemException.class)
+  public void testUpdateResources() throws Exception {
+    final UserPrivilegeResourceProvider resourceProvider = new UserPrivilegeResourceProvider();
+    resourceProvider.updateResources(EasyMock.createNiceMock(Request.class), EasyMock.createNiceMock(Predicate.class));
+  }
+
+  @Test(expected = SystemException.class)
+  public void testDeleteResources() throws Exception {
+    final UserPrivilegeResourceProvider resourceProvider = new UserPrivilegeResourceProvider();
+    resourceProvider.deleteResources(EasyMock.createNiceMock(Predicate.class));
+  }
+}