You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by tb...@apache.org on 2014/07/29 14:04:32 UTC

[2/2] git commit: AMBARI-6627 - Views : Admin - Add custom permissions

AMBARI-6627 - Views : Admin - Add custom permissions


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/11336361
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/11336361
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/11336361

Branch: refs/heads/trunk
Commit: 11336361fa4b0e180961f29b95802bb51090c196
Parents: 8536204
Author: tbeerbower <tb...@hortonworks.com>
Authored: Sun Jul 27 09:33:45 2014 -0400
Committer: tbeerbower <tb...@hortonworks.com>
Committed: Tue Jul 29 08:01:54 2014 -0400

----------------------------------------------------------------------
 .../resources/ResourceInstanceFactoryImpl.java  |   4 +
 .../ViewPermissionResourceDefinition.java       |  58 +++++
 .../ViewVersionResourceDefinition.java          |   7 +-
 .../api/services/ViewPermissionService.java     | 185 +++++++++++++
 .../server/api/services/ViewVersionService.java |  13 +
 .../ambari/server/controller/AmbariServer.java  |   7 +-
 .../internal/DefaultProviderModule.java         |   2 +
 .../internal/PrivilegeResourceProvider.java     |  23 +-
 .../ViewPermissionResourceProvider.java         | 178 +++++++++++++
 .../ambari/server/controller/spi/Resource.java  |   4 +-
 .../apache/ambari/server/orm/dao/MemberDAO.java |   9 +-
 .../ambari/server/orm/dao/PermissionDAO.java    |  20 +-
 .../ambari/server/orm/dao/PrivilegeDAO.java     |  25 +-
 .../server/orm/entities/PermissionEntity.java   |  15 +-
 .../server/orm/entities/ResourceTypeEntity.java |  21 ++
 .../ambari/server/orm/entities/ViewEntity.java  |  47 ++++
 .../ambari/server/view/ViewContextImpl.java     |  43 ++-
 .../apache/ambari/server/view/ViewRegistry.java | 172 +++++++++---
 .../view/configuration/PermissionConfig.java    |  39 +++
 .../server/view/configuration/ViewConfig.java   |  15 ++
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   1 +
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   1 +
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   1 +
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |   1 +
 .../ViewPermissionResourceDefinitionTest.java   |  49 ++++
 .../ViewVersionResourceDefinitionTest.java      |   7 +-
 .../api/services/ViewPermissionServiceTest.java | 100 +++++++
 .../ambari/server/view/ViewRegistryTest.java    |  70 +++--
 .../configuration/PermissionConfigTest.java     |  69 +++++
 ambari-views/examples/pom.xml                   |   1 +
 .../examples/restricted-view/docs/index.md      | 261 +++++++++++++++++++
 ambari-views/examples/restricted-view/pom.xml   |  89 +++++++
 .../view/restricted/RestrictedResource.java     |  57 ++++
 .../view/restricted/UnrestrictedResource.java   |  49 ++++
 .../restricted-view/src/main/resources/view.xml |  38 +++
 .../apache/ambari/view/SecurityException.java   |  44 ++++
 .../org/apache/ambari/view/ViewContext.java     |  12 +
 37 files changed, 1638 insertions(+), 99 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index 892ac22..5399404 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -254,6 +254,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         resourceDefinition = new PrivilegeResourceDefinition(Resource.Type.ViewPrivilege);
         break;
 
+      case ViewPermission:
+        resourceDefinition = new ViewPermissionResourceDefinition();
+        break;
+
       default:
         throw new IllegalArgumentException("Unsupported resource type: " + type);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewPermissionResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewPermissionResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewPermissionResourceDefinition.java
new file mode 100644
index 0000000..1ff360d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewPermissionResourceDefinition.java
@@ -0,0 +1,58 @@
+/**
+ * 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.apache.ambari.server.controller.spi.Resource;
+
+import java.util.Collections;
+import java.util.Set;
+
+
+/**
+ * Permission resource definition.
+ */
+public class ViewPermissionResourceDefinition extends BaseResourceDefinition {
+
+  // ----- Constructors ------------------------------------------------------
+
+  /**
+   * Construct a permission resource definition.
+   */
+  public ViewPermissionResourceDefinition() {
+    super(Resource.Type.ViewPermission);
+  }
+
+
+  // ----- ResourceDefinition ------------------------------------------------
+
+  @Override
+  public String getPluralName() {
+    return "permissions";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "permission";
+  }
+
+  @Override
+  public Set<SubResourceDefinition> getSubResourceDefinitions() {
+    return Collections.emptySet();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewVersionResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewVersionResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewVersionResourceDefinition.java
index e67a50b..be21d1b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewVersionResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ViewVersionResourceDefinition.java
@@ -20,7 +20,7 @@ package org.apache.ambari.server.api.resources;
 
 import org.apache.ambari.server.controller.spi.Resource;
 
-import java.util.Collections;
+import java.util.HashSet;
 import java.util.Set;
 
 
@@ -53,6 +53,9 @@ public class ViewVersionResourceDefinition extends BaseResourceDefinition {
 
   @Override
   public Set<SubResourceDefinition> getSubResourceDefinitions() {
-    return Collections.singleton(new SubResourceDefinition(Resource.Type.ViewInstance));
+    Set<SubResourceDefinition> subResourceDefinitions = new HashSet<SubResourceDefinition>();
+    subResourceDefinitions.add(new SubResourceDefinition(Resource.Type.ViewInstance));
+    subResourceDefinitions.add(new SubResourceDefinition(Resource.Type.ViewPermission));
+    return subResourceDefinitions;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewPermissionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewPermissionService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewPermissionService.java
new file mode 100644
index 0000000..711e85b
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewPermissionService.java
@@ -0,0 +1,185 @@
+/**
+ * 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 org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * Service responsible for custom view permission resource requests.
+ */
+public class ViewPermissionService extends BaseService {
+
+  /**
+   * Parent view name.
+   */
+  private final String viewName;
+
+  /**
+   * The view version.
+   */
+  private final String version;
+
+
+  // ----- Constructors ------------------------------------------------------
+
+  /**
+   * Construct a view permission service.
+   *
+   * @param viewName  the view id
+   * @param version   the version
+   */
+  public ViewPermissionService(String viewName, String version) {
+    this.viewName = viewName;
+    this.version  = version;
+  }
+
+
+  // ----- ViewPermissionService -----------------------------------------------
+
+  /**
+   * Handles: GET /permissions/{permissionID}
+   * Get a specific permission.
+   *
+   * @param headers        http headers
+   * @param ui             uri info
+   * @param permissionId   permission id
+   *
+   * @return permission instance representation
+   */
+  @GET
+  @Path("{permissionId}")
+  @Produces("text/plain")
+  public Response getPermission(@Context HttpHeaders headers, @Context UriInfo ui,
+                                @PathParam("permissionId") String permissionId) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET, createPermissionResource(
+        viewName, version, permissionId));
+  }
+
+  /**
+   * Handles: GET  /permissions
+   * Get all permissions.
+   *
+   * @param headers  http headers
+   * @param ui       uri info
+   *
+   * @return permission collection resource representation
+   */
+  @GET
+  @Produces("text/plain")
+  public Response getPermissions(@Context HttpHeaders headers, @Context UriInfo ui) {
+    return handleRequest(headers, null, ui, Request.Type.GET, createPermissionResource(
+        viewName, version, null));
+  }
+
+  /**
+   * Handles: POST /permissions/{permissionID}
+   * Create a specific permission.
+   *
+   * @param headers    http headers
+   * @param ui         uri info
+   * @param permissionId   permission id
+   *
+   * @return information regarding the created permission
+   */
+  @POST
+  @Path("{permissionId}")
+  @Produces("text/plain")
+  public Response createPermission(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                   @PathParam("permissionId") String permissionId) {
+
+    return handleRequest(headers, body, ui, Request.Type.POST, createPermissionResource(
+        viewName, version, permissionId));
+  }
+
+  /**
+   * Handles: PUT /permissions/{permissionID}
+   * Update a specific permission.
+   *
+   * @param headers   http headers
+   * @param ui        uri info
+   * @param permissionId  permission id
+   *
+   * @return information regarding the updated permission
+   */
+  @PUT
+  @Path("{permissionId}")
+  @Produces("text/plain")
+  public Response updatePermission(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                   @PathParam("permissionId") String permissionId) {
+
+    return handleRequest(headers, body, ui, Request.Type.PUT, createPermissionResource(
+        viewName, version, permissionId));
+  }
+
+  /**
+   * Handles: DELETE /permissions/{permissionID}
+   * Delete a specific permission.
+   *
+   * @param headers   http headers
+   * @param ui        uri info
+   * @param permissionId  permission id
+   *
+   * @return information regarding the deleted permission
+   */
+  @DELETE
+  @Path("{permissionId}")
+  @Produces("text/plain")
+  public Response deletePermission(@Context HttpHeaders headers, @Context UriInfo ui,
+                                   @PathParam("permissionId") String permissionId) {
+
+    return handleRequest(headers, null, ui, Request.Type.DELETE, createPermissionResource(
+        viewName, version, permissionId));
+  }
+
+
+  // ----- helper methods ----------------------------------------------------
+
+  /**
+   * Create a permission resource.
+   *
+   * @param permissionId permission name
+   *
+   * @return a permission resource instance
+   */
+  protected ResourceInstance createPermissionResource(String viewName, String viewVersion, String permissionId) {
+    Map<Resource.Type,String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.View, viewName);
+    mapIds.put(Resource.Type.ViewVersion, viewVersion);
+    mapIds.put(Resource.Type.ViewPermission, permissionId);
+
+    return createResource(Resource.Type.ViewPermission, mapIds);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewVersionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewVersionService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewVersionService.java
index 0dac300..8152ae6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewVersionService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ViewVersionService.java
@@ -166,6 +166,19 @@ public class ViewVersionService extends BaseService {
     return new ViewInstanceService(viewName, version);
   }
 
+  /**
+   * Get the permissions sub-resource
+   *
+   * @param version  the version
+   *
+   * @return the permission service
+   */
+  @Path("{version}/permissions")
+  public ViewPermissionService getPermissionHandler(@PathParam("version") String version) {
+
+    return new ViewPermissionService(viewName, version);
+  }
+
 
   // ----- helper methods ----------------------------------------------------
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 6803a01..eb34a77 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -53,12 +53,14 @@ import org.apache.ambari.server.controller.internal.PrivilegeResourceProvider;
 import org.apache.ambari.server.controller.internal.RecommendationResourceProvider;
 import org.apache.ambari.server.controller.internal.StackDefinedPropertyProvider;
 import org.apache.ambari.server.controller.internal.StackDependencyResourceProvider;
+import org.apache.ambari.server.controller.internal.ViewPermissionResourceProvider;
 import org.apache.ambari.server.controller.nagios.NagiosPropertyProvider;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.PersistenceType;
 import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
 import org.apache.ambari.server.orm.dao.BlueprintDAO;
 import org.apache.ambari.server.orm.dao.GroupDAO;
+import org.apache.ambari.server.orm.dao.MemberDAO;
 import org.apache.ambari.server.orm.dao.MetainfoDAO;
 import org.apache.ambari.server.orm.dao.PermissionDAO;
 import org.apache.ambari.server.orm.dao.PrincipalDAO;
@@ -541,11 +543,14 @@ public class AmbariServer {
     ClusterResourceProvider.init(injector.getInstance(BlueprintDAO.class), ambariMetaInfo);
     AlertDefinitionResourceProvider.init(injector.getInstance(AlertDefinitionDAO.class));
     PermissionResourceProvider.init(injector.getInstance(PermissionDAO.class));
+    ViewPermissionResourceProvider.init(injector.getInstance(PermissionDAO.class));
     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));
     ViewRegistry.init(injector.getInstance(ViewDAO.class), injector.getInstance(ViewInstanceDAO.class),
-        injector.getInstance(ResourceDAO.class), injector.getInstance(ResourceTypeDAO.class));
+        injector.getInstance(ResourceDAO.class), injector.getInstance(ResourceTypeDAO.class),
+        injector.getInstance(UserDAO.class), injector.getInstance(MemberDAO.class),
+        injector.getInstance(PrivilegeDAO.class));
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
index 1d20075..88e4296 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
@@ -75,6 +75,8 @@ public class DefaultProviderModule extends AbstractProviderModule {
         return new AmbariPrivilegeResourceProvider();
       case ViewPrivilege:
         return new ViewPrivilegeResourceProvider();
+      case ViewPermission:
+        return new ViewPermissionResourceProvider();
       default:
         return AbstractControllerResourceProvider.getResourceProvider(type, propertyIds,
             keyPropertyIds, managementController);

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java
index c7476e5..d04345b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/PrivilegeResourceProvider.java
@@ -40,6 +40,7 @@ import org.apache.ambari.server.orm.entities.GroupEntity;
 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.UserEntity;
 
 import java.util.Collections;
@@ -303,22 +304,26 @@ public abstract class PrivilegeResourceProvider<T> extends AbstractResourceProvi
    * @return the new privilege entity
    */
   protected PrivilegeEntity toEntity(Map<String, Object> properties, Long resourceId) {
-    PrivilegeEntity entity = new PrivilegeEntity();
+    PrivilegeEntity entity         = new PrivilegeEntity();
+    String          permissionName = (String) properties.get(PERMISSION_NAME_PROPERTY_ID);
+    ResourceEntity  resourceEntity = resourceDAO.findById(resourceId);
 
-    String permissionName = (String) properties.get(PERMISSION_NAME_PROPERTY_ID);
-
-    entity.setPermission(permissionDAO.findPermissionByName(permissionName));
-    entity.setResource(resourceDAO.findById(resourceId));
+    entity.setResource(resourceEntity);
+    entity.setPermission(permissionDAO.findPermissionByNameAndType(permissionName, resourceEntity.getResourceType()));
 
     String principalName = (String) properties.get(PRINCIPAL_NAME_PROPERTY_ID);
     String principalType = (String) properties.get(PRINCIPAL_TYPE_PROPERTY_ID);
 
     if (PrincipalTypeEntity.GROUP_PRINCIPAL_TYPE_NAME.equalsIgnoreCase(principalType)) {
       GroupEntity groupEntity = groupDAO.findGroupByName(principalName);
-      entity.setPrincipal(principalDAO.findById(groupEntity.getPrincipal().getId()));
+      if (groupEntity != null) {
+        entity.setPrincipal(principalDAO.findById(groupEntity.getPrincipal().getId()));
+      }
     } else if (PrincipalTypeEntity.USER_PRINCIPAL_TYPE_NAME.equalsIgnoreCase(principalType)) {
       UserEntity userEntity = userDAO.findLocalUserByName(principalName);
-      entity.setPrincipal(principalDAO.findById(userEntity.getPrincipal().getId()));
+      if (userEntity != null) {
+        entity.setPrincipal(principalDAO.findById(userEntity.getPrincipal().getId()));
+      }
     }
     return entity;
   }
@@ -335,6 +340,10 @@ public abstract class PrivilegeResourceProvider<T> extends AbstractResourceProvi
 
         PrivilegeEntity entity = toEntity(properties, resourceId);
 
+        if (entity.getPrincipal() == null) {
+          throw new AmbariException("Can't find principal " + properties.get(PRINCIPAL_TYPE_PROPERTY_ID) +
+              " " + properties.get(PRINCIPAL_NAME_PROPERTY_ID) + " for privilege.");
+        }
         if (privilegeDAO.exists(entity)) {
             throw new DuplicateResourceException("The privilege already exists.");
         }

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewPermissionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewPermissionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewPermissionResourceProvider.java
new file mode 100644
index 0000000..547692d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewPermissionResourceProvider.java
@@ -0,0 +1,178 @@
+/**
+ * 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 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.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.orm.dao.PermissionDAO;
+import org.apache.ambari.server.orm.entities.PermissionEntity;
+import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.view.ViewRegistry;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Resource provider for custom view permissions.
+ */
+public class ViewPermissionResourceProvider extends AbstractResourceProvider {
+
+  /**
+   * Data access object used to obtain permission entities.
+   */
+  protected static PermissionDAO permissionDAO;
+
+  /**
+   * Permission property id constants.
+   */
+  public static final String VIEW_NAME_PROPERTY_ID       = "PermissionInfo/view_name";
+  public static final String VIEW_VERSION_PROPERTY_ID    = "PermissionInfo/version";
+  public static final String PERMISSION_ID_PROPERTY_ID   = "PermissionInfo/permission_id";
+  public static final String PERMISSION_NAME_PROPERTY_ID = "PermissionInfo/permission_name";
+  public static final String RESOURCE_NAME_PROPERTY_ID   = "PermissionInfo/resource_name";
+
+
+  /**
+   * The key property ids for a permission resource.
+   */
+  private static Map<Resource.Type, String> keyPropertyIds = new HashMap<Resource.Type, String>();
+  static {
+    keyPropertyIds.put(Resource.Type.View, VIEW_NAME_PROPERTY_ID);
+    keyPropertyIds.put(Resource.Type.ViewVersion, VIEW_VERSION_PROPERTY_ID);
+    keyPropertyIds.put(Resource.Type.ViewPermission, PERMISSION_ID_PROPERTY_ID);
+  }
+
+  /**
+   * The property ids for a permission resource.
+   */
+  private static Set<String> propertyIds = new HashSet<String>();
+  static {
+    propertyIds.add(VIEW_NAME_PROPERTY_ID);
+    propertyIds.add(VIEW_VERSION_PROPERTY_ID);
+    propertyIds.add(PERMISSION_ID_PROPERTY_ID);
+    propertyIds.add(PERMISSION_NAME_PROPERTY_ID);
+    propertyIds.add(RESOURCE_NAME_PROPERTY_ID);
+  }
+
+
+  // ----- Constructors ------------------------------------------------------
+
+  /**
+   * Construct a permission resource provider.
+   */
+  public ViewPermissionResourceProvider() {
+    super(propertyIds, keyPropertyIds);
+  }
+
+
+  // ----- PermissionResourceProvider ----------------------------------------
+
+  /**
+   * Static initialization.
+   *
+   * @param dao  permission data access object
+   */
+  public static void init(PermissionDAO dao) {
+    permissionDAO = dao;
+  }
+
+
+  // ----- ResourceProvider --------------------------------------------------
+
+  @Override
+  public RequestStatus createResources(Request request)
+      throws SystemException, UnsupportedPropertyException,
+      ResourceAlreadyExistsException, NoSuchParentResourceException {
+    throw new UnsupportedOperationException("Not supported.");
+  }
+
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    ViewRegistry  viewRegistry = ViewRegistry.getInstance();
+    Set<Resource> resources    = new HashSet<Resource>();
+    Set<String>   requestedIds = getRequestPropertyIds(request, predicate);
+
+    for(PermissionEntity permissionEntity : permissionDAO.findAll()){
+      ResourceTypeEntity resourceType = permissionEntity.getResourceType();
+
+      ViewEntity viewEntity = viewRegistry.getDefinition(resourceType);
+
+      if (viewEntity != null) {
+        resources.add(toResource(permissionEntity, resourceType, viewEntity, requestedIds));
+      }
+    }
+
+    return resources;
+  }
+
+  @Override
+  public RequestStatus updateResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    throw new UnsupportedOperationException("Not supported.");
+  }
+
+  @Override
+  public RequestStatus deleteResources(Predicate predicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    throw new UnsupportedOperationException("Not supported.");
+  }
+
+  @Override
+  public Map<Resource.Type, String> getKeyPropertyIds() {
+    return keyPropertyIds;
+  }
+
+
+  // ----- AbstractResourceProvider ------------------------------------------
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return new HashSet<String>(keyPropertyIds.values());
+  }
+
+
+  // ----- helper methods ----------------------------------------------------
+
+  // convert the given permission entity to a resource
+  private Resource toResource(PermissionEntity entity, ResourceTypeEntity resourceType,
+                              ViewEntity viewEntity, Set<String> requestedIds) {
+
+    Resource resource = new ResourceImpl(Resource.Type.ViewPermission);
+
+    setResourceProperty(resource, VIEW_NAME_PROPERTY_ID, viewEntity.getCommonName(), requestedIds);
+    setResourceProperty(resource, VIEW_VERSION_PROPERTY_ID, viewEntity.getVersion(), requestedIds);
+
+    setResourceProperty(resource, PERMISSION_ID_PROPERTY_ID, entity.getId(), requestedIds);
+    setResourceProperty(resource, PERMISSION_NAME_PROPERTY_ID, entity.getPermissionName(), requestedIds);
+    setResourceProperty(resource, RESOURCE_NAME_PROPERTY_ID, resourceType.getName(), requestedIds);
+
+    return resource;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
index 50519cc..c6cc95b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
@@ -115,7 +115,8 @@ public interface Resource {
     AlertDefinition,
     AmbariPrivilege,
     ClusterPrivilege,
-    ViewPrivilege;
+    ViewPrivilege,
+    ViewPermission;
 
     /**
      * Get the {@link Type} that corresponds to this InternalType.
@@ -192,6 +193,7 @@ public interface Resource {
     public static final Type AmbariPrivilege = InternalType.AmbariPrivilege.getType();
     public static final Type ClusterPrivilege = InternalType.ClusterPrivilege.getType();
     public static final Type ViewPrivilege = InternalType.ViewPrivilege.getType();
+    public static final Type ViewPermission = InternalType.ViewPermission.getType();
 
     /**
      * The type name.

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MemberDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MemberDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MemberDAO.java
index b4e015d..5788b81 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MemberDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/MemberDAO.java
@@ -29,6 +29,7 @@ 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.UserEntity;
 
 @Singleton
 public class MemberDAO {
@@ -44,7 +45,13 @@ public class MemberDAO {
 
   @RequiresSession
   public List<MemberEntity> findAll() {
-    final TypedQuery<MemberEntity> query = entityManagerProvider.get().createQuery("SELECT member FROM MemberEntity member", MemberEntity.class);
+    final TypedQuery<MemberEntity> query = entityManagerProvider.get().createQuery("SELECT m FROM MemberEntity m", MemberEntity.class);
+    return daoUtils.selectList(query);
+  }
+
+  public List<MemberEntity> findAllMembersByUser(UserEntity userEntity) {
+    TypedQuery<MemberEntity> query = entityManagerProvider.get().createQuery("SELECT m FROM MemberEntity m WHERE m.user = :userEntity", MemberEntity.class);
+    query.setParameter("userEntity", userEntity);
     return daoUtils.selectList(query);
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PermissionDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PermissionDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PermissionDAO.java
index c00b47a..0ab5af8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PermissionDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PermissionDAO.java
@@ -22,9 +22,9 @@ import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import org.apache.ambari.server.orm.entities.PermissionEntity;
+import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
 
 import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
 import javax.persistence.TypedQuery;
 import java.util.List;
 
@@ -58,24 +58,22 @@ public class PermissionDAO {
    * @return all entities or an empty List
    */
   public List<PermissionEntity> findAll() {
-    TypedQuery<PermissionEntity> query = entityManagerProvider.get().createQuery("SELECT resource FROM PermissionEntity resource", PermissionEntity.class);
+    TypedQuery<PermissionEntity> query = entityManagerProvider.get().createQuery("SELECT p FROM PermissionEntity p", PermissionEntity.class);
     return daoUtils.selectList(query);
   }
 
   /**
-   * Find a permission entity by name.
+   * Find a permission entity by name and type.
    *
-   * @param name  the permission name
+   * @param name         the permission name
+   * @param resourceType the resource type
    *
    * @return  a matching permission entity or null
    */
-  public PermissionEntity findPermissionByName(String name) {
-    final TypedQuery<PermissionEntity> query = entityManagerProvider.get().createNamedQuery("permissionByName", PermissionEntity.class);
+  public PermissionEntity findPermissionByNameAndType(String name, ResourceTypeEntity resourceType) {
+    TypedQuery<PermissionEntity> query = entityManagerProvider.get().createQuery("SELECT p FROM PermissionEntity p WHERE p.permissionName=:permissionname AND p.resourceType=:resourcetype", PermissionEntity.class);
     query.setParameter("permissionname", name);
-    try {
-      return query.getSingleResult();
-    } catch (NoResultException e) {
-      return null;
-    }
+    query.setParameter("resourcetype", resourceType);
+    return daoUtils.selectSingle(query);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PrivilegeDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PrivilegeDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PrivilegeDAO.java
index de18031..7fed17b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PrivilegeDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/PrivilegeDAO.java
@@ -22,7 +22,10 @@ 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.PermissionEntity;
+import org.apache.ambari.server.orm.entities.PrincipalEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
+import org.apache.ambari.server.orm.entities.ResourceEntity;
 
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
@@ -63,19 +66,33 @@ public class PrivilegeDAO {
   }
 
   /**
-   * Determine whether or not the given privilege entity already exists.
+   * Determine whether or not the given privilege entity exists.
    *
    * @param entity  the privilege entity
    *
    * @return true if the given privilege entity already exists
    */
   public boolean exists(PrivilegeEntity entity) {
+    return exists(entity.getPrincipal(), entity.getResource(), entity.getPermission());
+  }
+
+  /**
+   * Determine whether or not the privilege entity exists defined by the given principal, resource and
+   * permission exists.
+   *
+   * @param principalEntity   the principal entity
+   * @param resourceEntity    the resource entity
+   * @param permissionEntity  the permission entity
+   *
+   * @return true if the privilege entity already exists
+   */
+  public boolean exists(PrincipalEntity principalEntity, ResourceEntity resourceEntity, PermissionEntity permissionEntity) {
     TypedQuery<PrivilegeEntity> query = entityManagerProvider.get().createQuery(
         "SELECT privilege FROM PrivilegeEntity privilege WHERE privilege.principal = :principal AND privilege.resource = :resource AND privilege.permission = :permission", PrivilegeEntity.class);
 
-    query.setParameter("principal", entity.getPrincipal());
-    query.setParameter("resource", entity.getResource());
-    query.setParameter("permission", entity.getPermission());
+    query.setParameter("principal", principalEntity);
+    query.setParameter("resource", resourceEntity);
+    query.setParameter("permission", permissionEntity);
 
     List<PrivilegeEntity> privilegeEntities = daoUtils.selectList(query);
     return !(privilegeEntities == null || privilegeEntities.isEmpty());

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PermissionEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PermissionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PermissionEntity.java
index a770f1d..8889bde 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PermissionEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/PermissionEntity.java
@@ -43,10 +43,6 @@ import javax.persistence.TableGenerator;
     , initialValue = 5
     , allocationSize = 1
 )
-
-@NamedQueries({
-    @NamedQuery(name = "permissionByName", query = "SELECT permission_entity FROM PermissionEntity permission_entity where permission_entity.permissionName=:permissionname")
-})
 public class PermissionEntity {
 
   /**
@@ -137,17 +133,14 @@ public class PermissionEntity {
 
     PermissionEntity that = (PermissionEntity) o;
 
-    if (!id.equals(that.id)) return false;
-    if (permissionName != null ? !permissionName.equals(that.permissionName) : that.permissionName != null)
-      return false;
-    if (resourceType != null ? !resourceType.equals(that.resourceType) : that.resourceType != null) return false;
-
-    return true;
+    return !(id != null ? !id.equals(that.id) : that.id != null) &&
+        !(permissionName != null ? !permissionName.equals(that.permissionName) : that.permissionName != null) &&
+        !(resourceType != null ? !resourceType.equals(that.resourceType) : that.resourceType != null);
   }
 
   @Override
   public int hashCode() {
-    int result = id.hashCode();
+    int result = id != null ? id.hashCode() : 0;
     result = 31 * result + (permissionName != null ? permissionName.hashCode() : 0);
     result = 31 * result + (resourceType != null ? resourceType.hashCode() : 0);
     return result;

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ResourceTypeEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ResourceTypeEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ResourceTypeEntity.java
index 9842a6a..1fdb737 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ResourceTypeEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ResourceTypeEntity.java
@@ -99,5 +99,26 @@ public class ResourceTypeEntity {
   public void setName(String name) {
     this.name = name;
   }
+
+
+  // ----- Object overrides --------------------------------------------------
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ResourceTypeEntity that = (ResourceTypeEntity) o;
+
+    return !(id != null ? !id.equals(that.id) : that.id != null) && !(name != null ?
+        !name.equals(that.name) : that.name != null);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = id != null ? id.hashCode() : 0;
+    result = 31 * result + (name != null ? name.hashCode() : 0);
+    return result;
+  }
 }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java
index 59d87aa..da6e2d2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java
@@ -121,6 +121,18 @@ public class ViewEntity implements ViewDefinition {
   @OneToMany(cascade = CascadeType.ALL, mappedBy = "view")
   private Collection<ViewInstanceEntity> instances = new HashSet<ViewInstanceEntity>();
 
+  /**
+   * The list of view permissions.
+   */
+  @OneToMany(cascade = CascadeType.ALL)
+  @JoinColumns({
+      @JoinColumn(name = "resource_type_id", referencedColumnName = "resource_type_id", nullable = false),
+  })
+  private Collection<PermissionEntity> permissions = new HashSet<PermissionEntity>();
+
+  /**
+   * The resource type.
+   */
   @ManyToOne
   @JoinColumns({
       @JoinColumn(name = "resource_type_id", referencedColumnName = "resource_type_id", nullable = false),
@@ -352,6 +364,41 @@ public class ViewEntity implements ViewDefinition {
   }
 
   /**
+   * Get the view custom permissions.
+   *
+   * @return the view permissions
+   */
+  public Collection<PermissionEntity> getPermissions() {
+    return permissions;
+  }
+
+  /**
+   * Set the custom view permissions.
+   *
+   * @param permissions  the permissions
+   */
+  public void setPermissions(Collection<PermissionEntity> permissions) {
+    this.permissions = permissions;
+  }
+
+  /**
+   * Get the permission entity for the given permission name.
+   *
+   * @param permissionName  the permission name
+   *
+   * @return the matching permission entity or null
+   */
+  public PermissionEntity getPermission(String permissionName) {
+
+    for (PermissionEntity permissionEntity : permissions) {
+      if (permissionEntity.getPermissionName().equals(permissionName)) {
+        return permissionEntity;
+      }
+    }
+    return null;
+  }
+
+  /**
    * Get the view resources.
    *
    * @return the view resources

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java
index 6426575..d36ad6e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java
@@ -21,13 +21,19 @@ package org.apache.ambari.server.view;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import org.apache.ambari.server.configuration.ComponentSSLConfiguration;
+import org.apache.ambari.server.orm.entities.PermissionEntity;
 import org.apache.ambari.server.orm.entities.ViewEntity;
 import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.server.view.configuration.ParameterConfig;
+import org.apache.ambari.server.view.configuration.ViewConfig;
 import org.apache.ambari.server.view.events.EventImpl;
 import org.apache.ambari.server.view.persistence.DataStoreImpl;
 import org.apache.ambari.server.view.persistence.DataStoreModule;
 import org.apache.ambari.view.DataStore;
+import org.apache.ambari.view.MaskException;
+import org.apache.ambari.view.Masker;
 import org.apache.ambari.view.ResourceProvider;
+import org.apache.ambari.view.SecurityException;
 import org.apache.ambari.view.URLStreamProvider;
 import org.apache.ambari.view.ViewContext;
 import org.apache.ambari.view.ViewController;
@@ -35,6 +41,9 @@ import org.apache.ambari.view.ViewDefinition;
 import org.apache.ambari.view.ViewInstanceDefinition;
 import org.apache.ambari.view.events.Event;
 import org.apache.ambari.view.events.Listener;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.Velocity;
 import org.apache.velocity.exception.ParseErrorException;
@@ -51,14 +60,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.apache.ambari.server.view.configuration.ParameterConfig;
-import org.apache.ambari.server.view.configuration.ViewConfig;
-import org.apache.ambari.view.MaskException;
-import org.apache.ambari.view.Masker;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
 /**
  * View context implementation.
  */
@@ -239,6 +240,32 @@ public class ViewContextImpl implements ViewContext, ViewController {
   }
 
   @Override
+  public void hasPermission(String userName, String permissionName) throws org.apache.ambari.view.SecurityException {
+
+    if (userName == null || userName.length() == 0) {
+      throw new SecurityException("No user name specified.");
+    }
+
+    if (permissionName == null || permissionName.length() == 0) {
+      throw new SecurityException("No permission name specified.");
+    }
+
+    if (viewInstanceEntity == null) {
+      throw new SecurityException("There is no instance associated with the view context");
+    }
+
+    PermissionEntity permissionEntity = viewEntity.getPermission(permissionName);
+
+    if (permissionEntity == null) {
+      throw new SecurityException("The permission " + permissionName + " is not defined for " + viewEntity.getName());
+    }
+
+    if (!viewRegistry.hasPermission(permissionEntity, viewInstanceEntity.getResource(), userName)) {
+      throw new SecurityException("The user " + userName + " has not been granted permission " + permissionName);
+    }
+  }
+
+  @Override
   public URLStreamProvider getURLStreamProvider() {
     return streamProvider;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
index 4859836..7b7d9a4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
@@ -29,12 +29,19 @@ import org.apache.ambari.server.api.services.ViewExternalSubResourceService;
 import org.apache.ambari.server.api.services.ViewSubResourceService;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.orm.dao.MemberDAO;
+import org.apache.ambari.server.orm.dao.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.ResourceDAO;
 import org.apache.ambari.server.orm.dao.ResourceTypeDAO;
+import org.apache.ambari.server.orm.dao.UserDAO;
 import org.apache.ambari.server.orm.dao.ViewDAO;
 import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
+import org.apache.ambari.server.orm.entities.GroupEntity;
+import org.apache.ambari.server.orm.entities.MemberEntity;
+import org.apache.ambari.server.orm.entities.PermissionEntity;
 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.apache.ambari.server.orm.entities.ViewEntity;
 import org.apache.ambari.server.orm.entities.ViewEntityEntity;
 import org.apache.ambari.server.orm.entities.ViewInstanceDataEntity;
@@ -44,6 +51,7 @@ import org.apache.ambari.server.orm.entities.ViewResourceEntity;
 import org.apache.ambari.server.view.configuration.EntityConfig;
 import org.apache.ambari.server.view.configuration.InstanceConfig;
 import org.apache.ambari.server.view.configuration.ParameterConfig;
+import org.apache.ambari.server.view.configuration.PermissionConfig;
 import org.apache.ambari.server.view.configuration.PersistenceConfig;
 import org.apache.ambari.server.view.configuration.PropertyConfig;
 import org.apache.ambari.server.view.configuration.ResourceConfig;
@@ -164,6 +172,21 @@ public class ViewRegistry {
    */
   private static ResourceTypeDAO resourceTypeDAO;
 
+  /**
+   * User data access object.
+   */
+  private static UserDAO userDAO;
+
+  /**
+   * Group member data access object.
+   */
+  private static MemberDAO memberDAO;
+
+  /**
+   * Privilege data access object.
+   */
+  private static PrivilegeDAO privilegeDAO;
+
 
   // ----- Constructors ------------------------------------------------------
 
@@ -198,6 +221,23 @@ public class ViewRegistry {
   }
 
   /**
+   * Get the view definition for the given resource type.
+   *
+   * @param resourceTypeEntity  the resource type
+   *
+   * @return the view definition for the given resource type or null
+   */
+  public ViewEntity getDefinition(ResourceTypeEntity resourceTypeEntity) {
+
+    for (ViewEntity viewEntity : viewDefinitions.values()) {
+      if (viewEntity.getResourceType().equals(resourceTypeEntity)) {
+        return viewEntity;
+      }
+    }
+    return null;
+  }
+
+  /**
    * Add a view definition to the registry.
    *
    * @param definition  the definition
@@ -605,6 +645,43 @@ public class ViewRegistry {
     listeners.add(listener);
   }
 
+  /**
+   * Determine whether or not the access specified by the given permission
+   * is permitted for the given user on the view instance identified by
+   * the given resource.
+   *
+   * @param permissionEntity  the permission entity
+   * @param resourceEntity    the resource entity
+   * @param userName          the user name
+   *
+   * @return true if the access specified by the given permission
+   *         is permitted for the given user.
+   */
+  public boolean hasPermission(PermissionEntity permissionEntity, ResourceEntity resourceEntity, String userName) {
+
+    UserEntity userEntity = userDAO.findLocalUserByName(userName);
+
+    if (userEntity == null) {
+      return false;
+    }
+
+    if (privilegeDAO.exists(userEntity.getPrincipal(), resourceEntity, permissionEntity)) {
+      return true;
+    }
+
+    List<MemberEntity> memberEntities = memberDAO.findAllMembersByUser(userEntity);
+
+    for (MemberEntity memberEntity : memberEntities) {
+
+      GroupEntity groupEntity = memberEntity.getGroup();
+
+      if (privilegeDAO.exists(groupEntity.getPrincipal(), resourceEntity, permissionEntity)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
 
   // ----- helper methods ----------------------------------------------------
 
@@ -700,6 +777,24 @@ public class ViewRegistry {
       }
       viewDefinition.setResources(resources);
     }
+
+    ResourceTypeEntity resourceTypeEntity = new ResourceTypeEntity();
+    resourceTypeEntity.setName(viewDefinition.getName());
+
+    viewDefinition.setResourceType(resourceTypeEntity);
+
+    List<PermissionConfig> permissionConfigurations = viewConfig.getPermissions();
+
+    Collection<PermissionEntity> permissions = new HashSet<PermissionEntity>();
+    for (PermissionConfig permissionConfiguration : permissionConfigurations) {
+      PermissionEntity permissionEntity =  new PermissionEntity();
+
+      permissionEntity.setPermissionName(permissionConfiguration.getName());
+      permissionEntity.setResourceType(resourceTypeEntity);
+      permissions.add(permissionEntity);
+    }
+    viewDefinition.setPermissions(permissions);
+
     View view = null;
     if (viewConfig.getView() != null) {
       view = getView(viewConfig.getViewClass(cl), new ViewContextImpl(viewDefinition, this));
@@ -774,6 +869,10 @@ public class ViewRegistry {
 
     setPersistenceEntities(viewInstanceDefinition);
 
+    ResourceEntity resourceEntity = new ResourceEntity();
+    resourceEntity.setResourceType(viewDefinition.getResourceType());
+    viewInstanceDefinition.setResource(resourceEntity);
+
     viewDefinition.addInstanceDefinition(viewInstanceDefinition);
   }
 
@@ -885,35 +984,8 @@ public class ViewRegistry {
       if (LOG.isDebugEnabled()) {
         LOG.debug("Creating View " + viewName + ".");
       }
-      // get or create an admin resource type to represent this view
-      ResourceTypeEntity resourceTypeEntity = resourceTypeDAO.findByName(viewName);
-      if (resourceTypeEntity == null) {
-        resourceTypeEntity = new ResourceTypeEntity();
-        resourceTypeEntity.setName(view.getName());
-        resourceTypeDAO.create(resourceTypeEntity);
-      }
-
-      view.setResourceType(resourceTypeEntity);
-
-      for( ViewInstanceEntity instance : view.getInstances()) {
-
-        // create an admin resource to represent this view instance
-        ResourceEntity resourceEntity = new ResourceEntity();
-        resourceEntity.setResourceType(resourceTypeEntity);
-        resourceDAO.create(resourceEntity);
-
-        instance.setResource(resourceEntity);
-      }
       // ... merge it
-      viewDAO.merge(view);
-
-      persistedView = viewDAO.findByName(viewName);
-      if (persistedView == null) {
-        String message = "View  " + persistedView.getViewName() + " can not be found.";
-
-        LOG.error(message);
-        throw new IllegalStateException(message);
-      }
+      persistedView = viewDAO.merge(view);
     }
 
     Map<String, ViewInstanceEntity> instanceEntityMap = new HashMap<String, ViewInstanceEntity>();
@@ -921,6 +993,9 @@ public class ViewRegistry {
       instanceEntityMap.put(instance.getName(), instance);
     }
 
+    view.setResourceType(persistedView.getResourceType());
+    view.setPermissions(persistedView.getPermissions());
+
     // make sure that each instance of the view in the db is reflected in the given view
     for (ViewInstanceEntity persistedInstance : persistedView.getInstances()){
       String instanceName = persistedInstance.getName();
@@ -947,9 +1022,7 @@ public class ViewRegistry {
       instance.setProperties(persistedInstance.getProperties());
       instance.setEntities(persistedInstance.getEntities());
 
-      if (instance.getResource() == null) {
-        instance.setResource(persistedInstance.getResource());
-      }
+      instance.setResource(persistedInstance.getResource());
     }
 
     // these instances appear in the archive but have been deleted
@@ -1078,12 +1151,20 @@ public class ViewRegistry {
    * @param instanceDAO      view instance data access object
    * @param resourceDAO      resource data access object
    * @param resourceTypeDAO  resource type data access object
+   * @param userDAO          user data access object
+   * @param memberDAO        group member data access object
+   * @param privilegeDAO     the privilege data access object
    */
-  public static void init(ViewDAO viewDAO, ViewInstanceDAO instanceDAO, ResourceDAO resourceDAO, ResourceTypeDAO resourceTypeDAO) {
+  public static void init(ViewDAO viewDAO, ViewInstanceDAO instanceDAO, ResourceDAO resourceDAO,
+                          ResourceTypeDAO resourceTypeDAO, UserDAO userDAO, MemberDAO memberDAO,
+                          PrivilegeDAO privilegeDAO) {
     setViewDAO(viewDAO);
     setInstanceDAO(instanceDAO);
     setResourceDAO(resourceDAO);
     setResourceTypeDAO(resourceTypeDAO);
+    setUserDAO(userDAO);
+    setMemberDAO(memberDAO);
+    setPrivilegeDAO(privilegeDAO);
   }
 
   /**
@@ -1122,6 +1203,33 @@ public class ViewRegistry {
     ViewRegistry.resourceTypeDAO = resourceTypeDAO;
   }
 
+  /**
+   * Set the user DAO.
+   *
+   * @param userDAO  the user DAO
+   */
+  protected static void setUserDAO(UserDAO userDAO) {
+    ViewRegistry.userDAO = userDAO;
+  }
+
+  /**
+   * Set the group member DAO.
+   *
+   * @param memberDAO  the group member DAO
+   */
+  protected static void setMemberDAO(MemberDAO memberDAO) {
+    ViewRegistry.memberDAO = memberDAO;
+  }
+
+  /**
+   * Set the privilege DAO.
+   *
+   * @param privilegeDAO  the privilege DAO
+   */
+  protected static void setPrivilegeDAO(PrivilegeDAO privilegeDAO) {
+    ViewRegistry.privilegeDAO = privilegeDAO;
+  }
+
 
   // ----- inner class : ViewRegistryHelper ----------------------------------
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/PermissionConfig.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/PermissionConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/PermissionConfig.java
new file mode 100644
index 0000000..07d1b53
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/PermissionConfig.java
@@ -0,0 +1,39 @@
+/**
+ * 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.view.configuration;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+
+/**
+ * View custom permission configuration.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+public class PermissionConfig {
+  private String name;
+  private String description;
+
+  public String getName() {
+    return name;
+  }
+
+  public String getDescription() {
+    return description;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
index e084918..ddca446 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
@@ -109,6 +109,12 @@ public class ViewConfig {
   private PersistenceConfig persistence;
 
   /**
+   * The list of view parameters.
+   */
+  @XmlElement(name="permission")
+  private List<PermissionConfig> permissions;
+
+  /**
    * Get the unique name.
    *
    * @return the view name
@@ -241,4 +247,13 @@ public class ViewConfig {
   public PersistenceConfig getPersistence() {
     return persistence;
   }
+
+  /**
+   * Get the list of custom permissions defined for the view.
+   *
+   * @return the list of custom permissions
+   */
+  public List<PermissionConfig> getPermissions() {
+    return permissions == null ? Collections.<PermissionConfig>emptyList() : permissions;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index f3cac2e..cf51a49 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -129,6 +129,7 @@ ALTER TABLE viewentity ADD CONSTRAINT FK_viewentity_view_name FOREIGN KEY (view_
 ALTER TABLE adminresource ADD CONSTRAINT FK_resource_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id);
 ALTER TABLE adminprincipal ADD CONSTRAINT FK_principal_principal_type_id FOREIGN KEY (principal_type_id) REFERENCES adminprincipaltype(principal_type_id);
 ALTER TABLE adminpermission ADD CONSTRAINT FK_permission_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id);
+ALTER TABLE adminpermission ADD CONSTRAINT UQ_permission_name_resource_type_id UNIQUE (permission_name, resource_type_id);
 ALTER TABLE adminprivilege ADD CONSTRAINT FK_privilege_permission_id FOREIGN KEY (permission_id) REFERENCES adminpermission(permission_id);
 ALTER TABLE adminprivilege ADD CONSTRAINT FK_privilege_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id);
 ALTER TABLE viewmain ADD CONSTRAINT FK_view_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id);

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index 2328ffc..c05affd 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -119,6 +119,7 @@ ALTER TABLE viewentity ADD CONSTRAINT FK_viewentity_view_name FOREIGN KEY (view_
 ALTER TABLE adminresource ADD CONSTRAINT FK_resource_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id);
 ALTER TABLE adminprincipal ADD CONSTRAINT FK_principal_principal_type_id FOREIGN KEY (principal_type_id) REFERENCES adminprincipaltype(principal_type_id);
 ALTER TABLE adminpermission ADD CONSTRAINT FK_permission_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id);
+ALTER TABLE adminpermission ADD CONSTRAINT UQ_permission_name_resource_type_id UNIQUE (permission_name, resource_type_id);
 ALTER TABLE adminprivilege ADD CONSTRAINT FK_privilege_permission_id FOREIGN KEY (permission_id) REFERENCES adminpermission(permission_id);
 ALTER TABLE adminprivilege ADD CONSTRAINT FK_privilege_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id);
 ALTER TABLE viewmain ADD CONSTRAINT FK_view_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id);

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 43addca..82335e3 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -152,6 +152,7 @@ ALTER TABLE viewentity ADD CONSTRAINT FK_viewentity_view_name FOREIGN KEY (view_
 ALTER TABLE adminresource ADD CONSTRAINT FK_resource_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id);
 ALTER TABLE adminprincipal ADD CONSTRAINT FK_principal_principal_type_id FOREIGN KEY (principal_type_id) REFERENCES adminprincipaltype(principal_type_id);
 ALTER TABLE adminpermission ADD CONSTRAINT FK_permission_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id);
+ALTER TABLE adminpermission ADD CONSTRAINT UQ_permission_name_resource_type_id UNIQUE (permission_name, resource_type_id);
 ALTER TABLE adminprivilege ADD CONSTRAINT FK_privilege_permission_id FOREIGN KEY (permission_id) REFERENCES adminpermission(permission_id);
 ALTER TABLE adminprivilege ADD CONSTRAINT FK_privilege_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id);
 ALTER TABLE viewmain ADD CONSTRAINT FK_view_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id);

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index 2fc99be..b5fcd94 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -215,6 +215,7 @@ ALTER TABLE ambari.viewentity ADD CONSTRAINT FK_viewentity_view_name FOREIGN KEY
 ALTER TABLE ambari.adminresource ADD CONSTRAINT FK_resource_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id);
 ALTER TABLE ambari.adminprincipal ADD CONSTRAINT FK_principal_principal_type_id FOREIGN KEY (principal_type_id) REFERENCES adminprincipaltype(principal_type_id);
 ALTER TABLE ambari.adminpermission ADD CONSTRAINT FK_permission_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id);
+ALTER TABLE ambari.adminpermission ADD CONSTRAINT UQ_permission_name_resource_type_id UNIQUE (permission_name, resource_type_id);
 ALTER TABLE ambari.adminprivilege ADD CONSTRAINT FK_privilege_permission_id FOREIGN KEY (permission_id) REFERENCES adminpermission(permission_id);
 ALTER TABLE ambari.adminprivilege ADD CONSTRAINT FK_privilege_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id);
 ALTER TABLE viewmain ADD CONSTRAINT FK_view_resource_type_id FOREIGN KEY (resource_type_id) REFERENCES adminresourcetype(resource_type_id);

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ViewPermissionResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ViewPermissionResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ViewPermissionResourceDefinitionTest.java
new file mode 100644
index 0000000..fbb20f2
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ViewPermissionResourceDefinitionTest.java
@@ -0,0 +1,49 @@
+/**
+ * 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;
+
+/**
+ * ViewPermissionResourceDefinition tests.
+ */
+public class ViewPermissionResourceDefinitionTest {
+  @Test
+  public void testGetPluralName() throws Exception {
+    ViewPermissionResourceDefinition ViewPermissionResourceDefinition = new ViewPermissionResourceDefinition();
+    Assert.assertEquals("permissions", ViewPermissionResourceDefinition.getPluralName());
+  }
+
+  @Test
+  public void testGetSingularName() throws Exception {
+    ViewPermissionResourceDefinition ViewPermissionResourceDefinition = new ViewPermissionResourceDefinition();
+    Assert.assertEquals("permission", ViewPermissionResourceDefinition.getSingularName());
+  }
+
+  @Test
+  public void testGetSubResourceDefinitions() throws Exception {
+    ViewPermissionResourceDefinition ViewPermissionResourceDefinition = new ViewPermissionResourceDefinition();
+    Set<SubResourceDefinition> subResourceDefinitions = ViewPermissionResourceDefinition.getSubResourceDefinitions ();
+
+    Assert.assertTrue(subResourceDefinitions.isEmpty());
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ViewVersionResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ViewVersionResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ViewVersionResourceDefinitionTest.java
index 32c13b3..d83c902 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ViewVersionResourceDefinitionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ViewVersionResourceDefinitionTest.java
@@ -44,8 +44,11 @@ public class ViewVersionResourceDefinitionTest {
     ViewVersionResourceDefinition viewVersionResourceDefinition = new ViewVersionResourceDefinition();
     Set<SubResourceDefinition> subResourceDefinitions = viewVersionResourceDefinition.getSubResourceDefinitions ();
 
-    Assert.assertEquals(1, subResourceDefinitions.size());
+    Assert.assertEquals(2, subResourceDefinitions.size());
 
-    Assert.assertEquals("ViewInstance", subResourceDefinitions.iterator().next().getType().name());
+    for (SubResourceDefinition subResourceDefinition : subResourceDefinitions) {
+      String name = subResourceDefinition.getType().name();
+      Assert.assertTrue(name.equals("ViewInstance") || name.equals("ViewPermission"));
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/test/java/org/apache/ambari/server/api/services/ViewPermissionServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/ViewPermissionServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ViewPermissionServiceTest.java
new file mode 100644
index 0000000..f841be9
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ViewPermissionServiceTest.java
@@ -0,0 +1,100 @@
+/**
+ * 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 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 javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Unit tests for ViewPermissionService.
+ */
+public class ViewPermissionServiceTest extends BaseServiceTest {
+
+
+  public List<ServiceTestInvocation> getTestInvocations() throws Exception {
+    List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>();
+
+    //getPermission
+    ViewPermissionService permissionService = new TestViewPermissionService("MY_VIEW", "1.0", "permissionName");
+    Method m = permissionService.getClass().getMethod("getPermission", HttpHeaders.class, UriInfo.class, String.class);
+    Object[] args = new Object[] {getHttpHeaders(), getUriInfo(), "permissionName"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, permissionService, m, args, null));
+
+    //getPermissions
+    permissionService = new TestViewPermissionService("MY_VIEW", "1.0",null);
+    m = permissionService.getClass().getMethod("getPermissions", HttpHeaders.class, UriInfo.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo()};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, permissionService, m, args, null));
+
+    //createPermission
+    permissionService = new TestViewPermissionService("MY_VIEW", "1.0","permissionName");
+    m = permissionService.getClass().getMethod("createPermission", String.class, HttpHeaders.class, UriInfo.class, String.class);
+    args = new Object[] {"body", getHttpHeaders(), getUriInfo(), "permissionName"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.POST, permissionService, m, args, "body"));
+
+    //deletePermission
+    permissionService = new TestViewPermissionService("MY_VIEW", "1.0","permissionName");
+    m = permissionService.getClass().getMethod("deletePermission", HttpHeaders.class, UriInfo.class, String.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo(), "permissionName"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.DELETE, permissionService, m, args, null));
+
+    return listInvocations;
+  }
+
+
+  private class TestViewPermissionService extends ViewPermissionService {
+    private String permissionId;
+
+    private TestViewPermissionService(String viewName, String version, String permissionId) {
+
+      super(viewName, version);
+      this.permissionId = permissionId;
+    }
+
+    @Override
+    protected ResourceInstance createPermissionResource(String viewName, String viewVersion, String permissionId) {
+      assertEquals(this.permissionId, permissionId);
+      return getTestResource();
+    }
+
+    @Override
+    RequestFactory getRequestFactory() {
+      return getTestRequestFactory();
+    }
+
+    @Override
+    protected RequestBodyParser getBodyParser() {
+      return getTestBodyParser();
+    }
+
+    @Override
+    protected ResultSerializer getResultSerializer() {
+      return getTestResultSerializer();
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
index 5bd5c38..fbe1c90 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
@@ -22,8 +22,11 @@ import org.apache.ambari.server.api.resources.SubResourceDefinition;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.orm.dao.MemberDAO;
+import org.apache.ambari.server.orm.dao.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.ResourceDAO;
 import org.apache.ambari.server.orm.dao.ResourceTypeDAO;
+import org.apache.ambari.server.orm.dao.UserDAO;
 import org.apache.ambari.server.orm.dao.ViewDAO;
 import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
 import org.apache.ambari.server.orm.entities.ResourceEntity;
@@ -175,12 +178,22 @@ public class ViewRegistryTest {
     ViewRegistry.setViewDAO(vDAO);
 
     ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    viewDefinition.setResourceType(resourceTypeEntity);
 
-    viewDefinition.setInstances(ViewInstanceEntityTest.getViewInstanceEntities(viewDefinition));
+    Set<ViewInstanceEntity> viewInstanceEntities = ViewInstanceEntityTest.getViewInstanceEntities(viewDefinition);
+    viewDefinition.setInstances(viewInstanceEntities);
 
     Map<File, ViewConfig> viewConfigs =
         Collections.singletonMap(viewArchive, viewDefinition.getConfiguration());
 
+    long resourceId = 99L;
+    for (ViewInstanceEntity viewInstanceEntity : viewInstanceEntities) {
+      ResourceEntity resourceEntity = new ResourceEntity();
+      resourceEntity.setId(resourceId);
+      resourceEntity.setResourceType(resourceTypeEntity);
+      viewInstanceEntity.setResource(resourceEntity);
+    }
+
     Map<String, File> files = new HashMap<String, File>();
 
     files.put("/var/lib/ambari-server/resources/views/work", extractedArchiveDir);
@@ -242,17 +255,10 @@ public class ViewRegistryTest {
     Capture<ViewEntity> captureViewEntity = new Capture<ViewEntity>();
 
     expect(vDAO.findByName("MY_VIEW{1.0.0}")).andReturn(null);
-    expect(vDAO.merge(capture(captureViewEntity))).andReturn(null);
-    expect(vDAO.findByName("MY_VIEW{1.0.0}")).andReturn(viewDefinition);
+    expect(vDAO.merge(capture(captureViewEntity))).andReturn(viewDefinition);
 
     expect(vDAO.findAll()).andReturn(Collections.<ViewEntity>emptyList());
 
-    expect(rtDAO.findByName("MY_VIEW{1.0.0}")).andReturn(resourceTypeEntity);
-
-    Capture<ResourceEntity> resourceEntityCapture = new Capture<ResourceEntity>();
-    rDAO.create(capture(resourceEntityCapture));
-    rDAO.create(capture(resourceEntityCapture));
-
     // replay mocks
     replay(configuration, viewDir, extractedArchiveDir, viewArchive, archiveDir, entryFile, classesDir,
         libDir, fileEntry, viewJarFile, enumeration, jarEntry, is, fos, vDAO, rtDAO, rDAO);
@@ -305,10 +311,22 @@ public class ViewRegistryTest {
     ViewRegistry.setViewDAO(vDAO);
 
     ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    viewDefinition.setResourceType(resourceTypeEntity);
+
+    Set<ViewInstanceEntity> viewInstanceEntities = ViewInstanceEntityTest.getViewInstanceEntities(viewDefinition);
+    viewDefinition.setInstances(viewInstanceEntities);
 
     Map<File, ViewConfig> viewConfigs =
         Collections.singletonMap(viewArchive, viewDefinition.getConfiguration());
 
+    long resourceId = 99L;
+    for (ViewInstanceEntity viewInstanceEntity : viewInstanceEntities) {
+      ResourceEntity resourceEntity = new ResourceEntity();
+      resourceEntity.setId(resourceId);
+      resourceEntity.setResourceType(resourceTypeEntity);
+      viewInstanceEntity.setResource(resourceEntity);
+    }
+
     Map<String, File> files = new HashMap<String, File>();
 
     files.put("/var/lib/ambari-server/resources/views/work", extractedArchiveDir);
@@ -374,11 +392,7 @@ public class ViewRegistryTest {
 
     expect(vDAO.findAll()).andReturn(Collections.<ViewEntity>emptyList());
 
-    expect(rtDAO.findByName("MY_VIEW{1.0.0}")).andReturn(resourceTypeEntity);
-
     Capture<ResourceEntity> resourceEntityCapture = new Capture<ResourceEntity>();
-    rDAO.create(capture(resourceEntityCapture));
-    rDAO.create(capture(resourceEntityCapture));
 
     // replay mocks
     replay(configuration, viewDir, extractedArchiveDir, viewArchive, archiveDir, entryFile, classesDir,
@@ -511,8 +525,11 @@ public class ViewRegistryTest {
     ViewInstanceDAO viewInstanceDAO = createNiceMock(ViewInstanceDAO.class);
     ResourceDAO resourceDAO = createNiceMock(ResourceDAO.class);
     ResourceTypeDAO resourceTypeDAO = createNiceMock(ResourceTypeDAO.class);
+    UserDAO userDAO = createNiceMock(UserDAO.class);
+    MemberDAO memberDAO = createNiceMock(MemberDAO.class);
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
 
-    ViewRegistry.init(viewDAO, viewInstanceDAO, resourceDAO, resourceTypeDAO);
+    ViewRegistry.init(viewDAO, viewInstanceDAO, resourceDAO, resourceTypeDAO, userDAO, memberDAO, privilegeDAO);
 
     ViewRegistry registry = ViewRegistry.getInstance();
 
@@ -549,8 +566,11 @@ public class ViewRegistryTest {
     ViewInstanceDAO viewInstanceDAO = createNiceMock(ViewInstanceDAO.class);
     ResourceDAO resourceDAO = createNiceMock(ResourceDAO.class);
     ResourceTypeDAO resourceTypeDAO = createNiceMock(ResourceTypeDAO.class);
+    UserDAO userDAO = createNiceMock(UserDAO.class);
+    MemberDAO memberDAO = createNiceMock(MemberDAO.class);
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
 
-    ViewRegistry.init(viewDAO, viewInstanceDAO, resourceDAO, resourceTypeDAO);
+    ViewRegistry.init(viewDAO, viewInstanceDAO, resourceDAO, resourceTypeDAO, userDAO, memberDAO, privilegeDAO);
 
     ViewRegistry registry = ViewRegistry.getInstance();
 
@@ -582,8 +602,11 @@ public class ViewRegistryTest {
     ViewInstanceDAO viewInstanceDAO = createNiceMock(ViewInstanceDAO.class);
     ResourceDAO resourceDAO = createNiceMock(ResourceDAO.class);
     ResourceTypeDAO resourceTypeDAO = createNiceMock(ResourceTypeDAO.class);
+    UserDAO userDAO = createNiceMock(UserDAO.class);
+    MemberDAO memberDAO = createNiceMock(MemberDAO.class);
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
 
-    ViewRegistry.init(viewDAO, viewInstanceDAO, resourceDAO, resourceTypeDAO);
+    ViewRegistry.init(viewDAO, viewInstanceDAO, resourceDAO, resourceTypeDAO, userDAO, memberDAO, privilegeDAO);
 
     ViewRegistry registry = ViewRegistry.getInstance();
 
@@ -616,8 +639,11 @@ public class ViewRegistryTest {
     ViewInstanceDAO viewInstanceDAO = createNiceMock(ViewInstanceDAO.class);
     ResourceDAO resourceDAO = createNiceMock(ResourceDAO.class);
     ResourceTypeDAO resourceTypeDAO = createNiceMock(ResourceTypeDAO.class);
+    UserDAO userDAO = createNiceMock(UserDAO.class);
+    MemberDAO memberDAO = createNiceMock(MemberDAO.class);
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
 
-    ViewRegistry.init(viewDAO, viewInstanceDAO, resourceDAO, resourceTypeDAO);
+    ViewRegistry.init(viewDAO, viewInstanceDAO, resourceDAO, resourceTypeDAO, userDAO, memberDAO, privilegeDAO);
 
     ViewRegistry registry = ViewRegistry.getInstance();
 
@@ -658,8 +684,11 @@ public class ViewRegistryTest {
     ViewInstanceDAO viewInstanceDAO = createNiceMock(ViewInstanceDAO.class);
     ResourceDAO resourceDAO = createNiceMock(ResourceDAO.class);
     ResourceTypeDAO resourceTypeDAO = createNiceMock(ResourceTypeDAO.class);
+    UserDAO userDAO = createNiceMock(UserDAO.class);
+    MemberDAO memberDAO = createNiceMock(MemberDAO.class);
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
 
-    ViewRegistry.init(viewDAO, viewInstanceDAO, resourceDAO, resourceTypeDAO);
+    ViewRegistry.init(viewDAO, viewInstanceDAO, resourceDAO, resourceTypeDAO, userDAO, memberDAO, privilegeDAO);
 
     ViewRegistry registry = ViewRegistry.getInstance();
 
@@ -698,8 +727,11 @@ public class ViewRegistryTest {
     ViewInstanceDAO viewInstanceDAO = createNiceMock(ViewInstanceDAO.class);
     ResourceDAO resourceDAO = createNiceMock(ResourceDAO.class);
     ResourceTypeDAO resourceTypeDAO = createNiceMock(ResourceTypeDAO.class);
+    UserDAO userDAO = createNiceMock(UserDAO.class);
+    MemberDAO memberDAO = createNiceMock(MemberDAO.class);
+    PrivilegeDAO privilegeDAO = createNiceMock(PrivilegeDAO.class);
 
-    ViewRegistry.init(viewDAO, viewInstanceDAO, resourceDAO, resourceTypeDAO);
+    ViewRegistry.init(viewDAO, viewInstanceDAO, resourceDAO, resourceTypeDAO, userDAO, memberDAO, privilegeDAO);
 
     ViewRegistry registry = ViewRegistry.getInstance();
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/11336361/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/PermissionConfigTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/PermissionConfigTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/PermissionConfigTest.java
new file mode 100644
index 0000000..2600f17
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/PermissionConfigTest.java
@@ -0,0 +1,69 @@
+/**
+ * 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.view.configuration;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.xml.bind.JAXBException;
+import java.util.List;
+
+/**
+ * EntityConfig tests.
+ */
+public class PermissionConfigTest {
+
+  private final static String xml = "<view>\n" +
+      "    <name>MY_VIEW</name>\n" +
+      "    <label>My View!</label>\n" +
+      "    <version>1.0.0</version>\n" +
+      "    <instance>\n" +
+      "        <name>INSTANCE1</name>\n" +
+      "    </instance>\n" +
+      "  <permission>\n" +
+      "    <name>RESTRICTED</name>\n" +
+      "    <description>Access permission for a restricted view resource.</description>\n" +
+      "  </permission>" +
+      "</view>";
+
+
+  @Test
+  public void testGetName() throws Exception {
+    List<PermissionConfig> permissions = getPremissionConfig();
+
+    Assert.assertEquals(1, permissions.size());
+
+    Assert.assertEquals("RESTRICTED", permissions.get(0).getName());
+  }
+
+  @Test
+  public void testGetDescription() throws Exception {
+    List<PermissionConfig> permissions = getPremissionConfig();
+
+    Assert.assertEquals(1, permissions.size());
+
+    Assert.assertEquals("Access permission for a restricted view resource.", permissions.get(0).getDescription());
+  }
+
+  public static List<PermissionConfig> getPremissionConfig() throws JAXBException {
+    ViewConfig config = ViewConfigTest.getConfig(xml);
+
+    return config.getPermissions();
+  }
+}