Browse Source

HPCC-15732 Update ESP web services to support column level security

Signed-off-by: Suk Hwan Hong <suk.hong@gatech.edu>
Suk Hwan Hong 9 years ago
parent
commit
4454b18f7e

+ 160 - 1
esp/scm/ws_access.ecm

@@ -572,6 +572,153 @@ ESPresponse ResourcePermissionsResponse
     ESParray<ESPstruct ResourcePermission, Permission> Permissions;
 };
 
+
+ESPstruct View
+{
+    string viewname;
+    string description;
+};
+
+ESPrequest QueryViewsRequest
+{
+};
+
+ESPresponse QueryViewsResponse
+{
+    ESParray<ESPstruct View> views;
+};
+
+ESPrequest AddViewRequest
+{
+    string viewname;
+    string description;
+};
+
+ESPresponse AddViewResponse
+{
+    string viewname;
+    string description;
+};
+
+ESPrequest DeleteViewRequest
+{
+    string viewname;
+};
+
+Espresponse DeleteViewResponse
+{
+    string viewname;
+};
+
+ESPstruct ViewColumn
+{
+    string viewname;
+    string filename;
+    string columnname;
+};
+
+ESPrequest QueryViewColumnsRequest
+{
+    string viewname;
+};
+
+ESPresponse QueryViewColumnsResponse
+{
+    string viewname;
+    ESParray<ESPstruct ViewColumn> viewcolumns;
+};
+
+ESPrequest AddViewColumnRequest
+{
+    string viewname;
+    string filename;
+    string columnname;
+};
+
+ESPresponse AddViewColumnResponse
+{
+    string viewname;
+    string filename;
+    string columnname;
+};
+
+ESPrequest DeleteViewColumnRequest
+{
+    string viewname;
+    string filename;
+    string columnname;
+};
+
+ESPresponse DeleteViewColumnResponse
+{
+    string viewname;
+    string filename;
+    string columnname;
+};
+
+ESPenum ViewMemberType : string
+{
+    User("User"),
+    Group("Group"),
+};
+
+ESPstruct ViewMember
+{
+    string viewname;
+    string name;
+    ESPenum ViewMemberType membertype;
+};
+
+ESPrequest QueryViewMembersRequest
+{
+    string viewname;
+};
+
+ESPresponse QueryViewMembersResponse
+{
+    string viewname;
+    ESParray<ESPstruct ViewMember> viewmembers;
+};
+
+ESPrequest AddViewMemberRequest
+{
+    string viewname;
+    string membername;
+    ESPenum ViewMemberType membertype;
+};
+
+ESPresponse AddViewMemberResponse
+{
+    string viewname;
+    string membername;
+    ESPenum ViewMemberType membertype;
+};
+
+ESPrequest DeleteViewMemberRequest
+{
+    string viewname;
+    string membername;
+    ESPenum ViewMemberType membertype;
+};
+
+ESPresponse DeleteViewMemberResponse
+{
+    string viewname;
+    string membername;
+    ESPenum ViewMemberType membertype;
+};
+
+ESPrequest QueryUserViewColumnsRequest
+{
+    string username;
+};
+
+ESPresponse QueryUserViewColumnsResponse
+{
+    string username;
+    ESParray<ESPstruct ViewColumn> viewcolumns;
+};
+
 ESPrequest PermissionAddRequest
 {
     string basedn;
@@ -788,7 +935,7 @@ ESPresponse [nil_remove] UserAccountExportResponse
 };
 
 
-ESPservice [version("1.09"), exceptions_inline("./smc_xslt/exceptions.xslt")] ws_access
+ESPservice [version("1.10"), exceptions_inline("./smc_xslt/exceptions.xslt")] ws_access
 {
     ESPmethod [client_xslt("/esp/xslt/access_users.xslt")] Users(UserRequest, UserResponse);
     ESPmethod [client_xslt("/esp/xslt/access_useredit.xslt")] UserEdit(UserEditRequest, UserEditResponse);
@@ -815,6 +962,18 @@ ESPservice [version("1.09"), exceptions_inline("./smc_xslt/exceptions.xslt")] ws
     ESPmethod [client_xslt("/esp/xslt/access_resourceadd.xslt")] ResourceAdd(ResourceAddRequest, ResourceAddResponse);
     ESPmethod [client_xslt("/esp/xslt/access_resourcedelete.xslt")] ResourceDelete(ResourceDeleteRequest, ResourceDeleteResponse);
     ESPmethod [client_xslt("/esp/xslt/access_resourceaddinput.xslt")] ResourceAddInput(ResourceAddInputRequest, ResourceAddInputResponse);
+
+    ESPmethod [min_ver("1.10")] QueryViews(QueryViewsRequest, QueryViewsResponse);
+    ESPmethod [min_ver("1.10")] AddView(AddViewRequest, AddViewResponse);
+    ESPmethod [min_ver("1.10")] DeleteView(DeleteViewRequest, DeleteViewResponse);
+    ESPmethod [min_ver("1.10")] QueryViewColumns(QueryViewColumnsRequest, QueryViewColumnsResponse);
+    ESPmethod [min_ver("1.10")] AddViewColumn(AddViewColumnRequest, AddViewColumnResponse);
+    ESPmethod [min_ver("1.10")] DeleteViewColumn(DeleteViewColumnRequest, DeleteViewColumnResponse);
+    ESPmethod [min_ver("1.10")] QueryViewMembers(QueryViewMembersRequest, QueryViewMembersResponse);
+    ESPmethod [min_ver("1.10")] AddViewMember(AddViewMemberRequest, AddViewMemberResponse);
+    ESPmethod [min_ver("1.10")] DeleteViewMember(DeleteViewMemberRequest, DeleteViewMemberResponse);
+    ESPmethod [min_ver("1.10")] QueryUserViewColumns(QueryUserViewColumnsRequest, QueryUserViewColumnsResponse);
+
     ESPmethod [client_xslt("/esp/xslt/access_permissions.xslt")] ResourcePermissions(ResourcePermissionsRequest, ResourcePermissionsResponse);
     ESPmethod [client_xslt("/esp/xslt/access_permissionaddinput.xslt")] PermissionAddInput(PermissionAddRequest, PermissionAddResponse);
     ESPmethod [client_xslt("/esp/xslt/access_permissionchange.xslt")] PermissionAction(PermissionActionRequest, PermissionActionResponse);

+ 381 - 0
esp/services/ws_access/ws_accessService.cpp

@@ -2163,6 +2163,387 @@ bool Cws_accessEx::onResourcePermissions(IEspContext &context, IEspResourcePermi
     return true;
 }
 
+bool Cws_accessEx::onQueryViews(IEspContext &context, IEspQueryViewsRequest &req, IEspQueryViewsResponse &resp)
+{
+    try
+    {
+        CLdapSecManager* secmgr = queryLDAPSecurityManager(context);
+        
+        if(secmgr == NULL)
+            throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, MSG_SEC_MANAGER_IS_NULL);
+
+        checkUser(context);
+        
+        IArrayOf<IEspView> views;
+        StringArray names, descriptions, viewManagedBy;
+
+        secmgr->queryAllViews(names, descriptions, viewManagedBy);
+
+        ForEachItemIn(i, names)
+        {
+            Owned<IEspView> oneView = createView();
+            oneView->setViewname(names.item(i));
+            oneView->setDescription(descriptions.item(i));
+            views.append(*oneView.getLink());
+        }
+
+        resp.setViews(views);
+    }
+    catch (IException* e)
+    {
+        FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
+    }
+
+    return true;
+}
+
+bool Cws_accessEx::onAddView(IEspContext &context, IEspAddViewRequest &req, IEspAddViewResponse &resp)
+{
+    try
+    {
+        CLdapSecManager* secmgr = queryLDAPSecurityManager(context);
+        
+        if(secmgr == NULL)
+            throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, MSG_SEC_MANAGER_IS_NULL);
+
+        checkUser(context);
+
+        const char* viewname = req.getViewname();
+        const char* description = req.getDescription();
+
+        secmgr->createView(viewname, description);
+        resp.setViewname(viewname);
+        resp.setDescription(description);
+    }
+    catch (IException* e)
+    {
+        FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
+    }
+        
+    return true;
+}
+
+bool Cws_accessEx::onDeleteView(IEspContext &context, IEspDeleteViewRequest &req, IEspDeleteViewResponse &resp)
+{
+    try
+    {
+        CLdapSecManager* secmgr = queryLDAPSecurityManager(context);
+        
+        if(secmgr == NULL)
+            throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, MSG_SEC_MANAGER_IS_NULL);
+
+        checkUser(context);
+
+        const char* viewname = req.getViewname();
+        secmgr->deleteView(req.getViewname());
+
+        resp.setViewname(viewname);
+    }
+    catch (IException* e)
+    {
+        FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
+    }
+
+    return true;
+}
+
+bool Cws_accessEx::onQueryViewColumns(IEspContext &context, IEspQueryViewColumnsRequest &req, IEspQueryViewColumnsResponse &resp)
+{
+    try
+    {
+        CLdapSecManager* secmgr = queryLDAPSecurityManager(context);
+        
+        if(secmgr == NULL)
+            throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, MSG_SEC_MANAGER_IS_NULL);
+
+        checkUser(context);
+        
+        IArrayOf<IEspViewColumn> viewColumns;
+        StringArray files, columns;
+
+        const char* viewname = req.getViewname();
+
+        secmgr->queryViewColumns(viewname, files, columns);
+
+        ForEachItemIn(i, files)
+        {
+            Owned<IEspViewColumn> oneViewColumn = createViewColumn();
+            oneViewColumn->setViewname(req.getViewname());
+            oneViewColumn->setFilename(files.item(i));
+            oneViewColumn->setColumnname(columns.item(i));
+            viewColumns.append(*oneViewColumn.getLink());
+        }
+
+        resp.setViewname(viewname);
+        resp.setViewcolumns(viewColumns);
+    }
+    catch (IException* e)
+    {
+        FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
+    }
+
+    return true;
+}
+
+bool Cws_accessEx::onAddViewColumn(IEspContext &context, IEspAddViewColumnRequest &req, IEspAddViewColumnResponse &resp)
+{
+    try
+    {
+        CLdapSecManager* secmgr = queryLDAPSecurityManager(context);
+        
+        if(secmgr == NULL)
+            throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, MSG_SEC_MANAGER_IS_NULL);
+
+        checkUser(context);
+
+        const char* filename = req.getFilename();
+        const char* columnname = req.getColumnname();
+
+        if (!filename || *filename == '\0')
+            throw MakeStringException(ECLWATCH_INVALID_INPUT, "Filename cannot be empty.");
+
+        if (!columnname || *columnname == '\0')
+            throw MakeStringException(ECLWATCH_INVALID_INPUT, "Columnname cannot be empty.");
+
+        // View column filename MUST be a full path including the scope, with a leading tilde (~)
+        if (filename[0] != '~')
+            throw MakeStringException(ECLWATCH_INVALID_INPUT, "Filename must include a scope name, with a leading tilde (~)");
+        
+        StringArray files, columns;
+        const char* viewname = req.getViewname();
+
+        files.append(filename);
+        columns.append(columnname);
+
+        secmgr->addViewColumns(viewname, files, columns);
+
+        resp.setViewname(viewname);
+        resp.setFilename(filename);
+        resp.setColumnname(columnname);
+    }
+    catch (IException* e)
+    {
+        FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
+    }
+
+    return true;
+}
+
+bool Cws_accessEx::onDeleteViewColumn(IEspContext &context, IEspDeleteViewColumnRequest &req, IEspDeleteViewColumnResponse &resp)
+{
+    try
+    {
+        CLdapSecManager* secmgr = queryLDAPSecurityManager(context);
+        
+        if(secmgr == NULL)
+            throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, MSG_SEC_MANAGER_IS_NULL);
+
+        checkUser(context);
+
+        StringArray files, columns;
+
+        const char* viewname = req.getViewname();
+        const char* filename = req.getFilename();
+        const char* columnname = req.getColumnname();
+
+        files.append(filename);
+        columns.append(columnname);
+
+        secmgr->removeViewColumns(req.getViewname(), files, columns);
+
+        resp.setViewname(viewname);
+        resp.setFilename(filename);
+        resp.setColumnname(columnname);
+    }
+    catch (IException* e)
+    {
+        FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
+    }
+
+    return true;
+}
+
+bool Cws_accessEx::onQueryViewMembers(IEspContext &context, IEspQueryViewMembersRequest &req, IEspQueryViewMembersResponse &resp)
+{
+    try
+    {
+        CLdapSecManager* secmgr = queryLDAPSecurityManager(context);
+        
+        if(secmgr == NULL)
+            throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, MSG_SEC_MANAGER_IS_NULL);
+
+        checkUser(context);
+        
+        const char* reqViewname = req.getViewname();
+        StringArray users, groups;
+        IArrayOf<IEspViewMember> viewMembers;
+
+        secmgr->queryViewMembers(reqViewname, users, groups);
+        
+        ForEachItemIn(i, users)
+        {
+            Owned<IEspViewMember> oneViewMember = createViewMember();
+            oneViewMember->setViewname(reqViewname);
+            oneViewMember->setName(users.item(i));
+            oneViewMember->setMembertype(CViewMemberType_User);
+            viewMembers.append(*oneViewMember.getLink());
+        }
+
+        ForEachItemIn(j, groups)
+        {
+            Owned<IEspViewMember> oneViewMember = createViewMember();
+            oneViewMember->setViewname(reqViewname);
+            oneViewMember->setName(groups.item(j));
+            oneViewMember->setMembertype(CViewMemberType_Group);
+            viewMembers.append(*oneViewMember.getLink());
+        }
+
+        resp.setViewname(reqViewname);
+        resp.setViewmembers(viewMembers);
+    }
+    catch (IException* e)
+    {
+        FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
+    }
+
+    return true;
+}
+
+bool Cws_accessEx::onAddViewMember(IEspContext &context, IEspAddViewMemberRequest &req, IEspAddViewMemberResponse &resp)
+{
+    try
+    {
+        CLdapSecManager* secmgr = queryLDAPSecurityManager(context);
+        
+        if(secmgr == NULL)
+            throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, MSG_SEC_MANAGER_IS_NULL);
+
+        checkUser(context);
+
+        StringArray users, groups;
+        const char* viewname = req.getViewname();
+        const char* membername = req.getMembername();
+        CViewMemberType membertype = req.getMembertype();
+
+        if (membertype == CViewMemberType_User)
+        {
+            users.append(membername);
+        }
+        else if (membertype == CViewMemberType_Group)
+        {
+            groups.append(membername);
+        }
+        else
+        {            
+            throw MakeStringException(ECLWATCH_INVALID_INPUT, "Unknown view member type specified (Must be User or Group)");
+        }
+
+        secmgr->addViewMembers(viewname, users, groups);
+
+        resp.setViewname(viewname);
+        resp.setMembername(membername);
+        resp.setMembertype(membertype);
+    }
+    catch (IException* e)
+    {
+        FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
+    }
+
+    return true;
+}
+
+bool Cws_accessEx::onDeleteViewMember(IEspContext &context, IEspDeleteViewMemberRequest &req, IEspDeleteViewMemberResponse &resp)
+{
+    try
+    {
+        CLdapSecManager* secmgr = queryLDAPSecurityManager(context);
+        
+        if(secmgr == NULL)
+            throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, MSG_SEC_MANAGER_IS_NULL);
+
+        checkUser(context);
+
+        StringArray users, groups;
+        const char* viewname = req.getViewname();
+        const char* membername = req.getMembername();
+        CViewMemberType membertype = req.getMembertype();
+
+        if (membertype == CViewMemberType_User)
+        {
+            users.append(membername);
+        }
+        else if (membertype == CViewMemberType_Group)
+        {
+            groups.append(membername);
+        }
+        else
+        {
+            throw MakeStringException(ECLWATCH_INVALID_INPUT, "Unknown view member type specified (Must be User' or Group)");
+        }
+
+        secmgr->removeViewMembers(req.getViewname(), users, groups);
+
+        resp.setViewname(viewname);
+        resp.setMembername(membername);
+        resp.setMembertype(membertype);
+    }
+    catch (IException* e)
+    {
+        FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
+    }
+
+    return true;
+}
+
+bool Cws_accessEx::onQueryUserViewColumns(IEspContext &context, IEspQueryUserViewColumnsRequest &req, IEspQueryUserViewColumnsResponse &resp)
+{
+    try
+    {
+        CLdapSecManager* secmgr = queryLDAPSecurityManager(context);
+        
+        if(secmgr == NULL)
+            throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, MSG_SEC_MANAGER_IS_NULL);
+
+        checkUser(context);
+        
+        const char* username = req.getUsername();
+
+        IArrayOf<IEspViewColumn> viewColumns;
+
+        StringArray viewnames, viewdescriptions, viewManagedBy;
+        secmgr->queryAllViews(viewnames, viewdescriptions, viewManagedBy);
+
+        ForEachItemIn(i, viewnames)
+        {
+            const char* viewname = viewnames.item(i);
+            
+            if (secmgr->userInView(username, viewname))
+            {
+                StringArray files, columns;
+                secmgr->queryViewColumns(viewname, files, columns);
+        
+                ForEachItemIn(j, files)
+                {
+                    Owned<IEspViewColumn> oneViewColumn = createViewColumn();
+                    oneViewColumn->setViewname(viewname);
+                    oneViewColumn->setFilename(files.item(j));
+                    oneViewColumn->setColumnname(columns.item(j));
+                    viewColumns.append(*oneViewColumn.getLink());
+                }
+            }
+        }
+
+        resp.setUsername(username);
+        resp.setViewcolumns(viewColumns);
+    }
+    catch (IException* e)
+    {
+        FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
+    }
+
+    return true;
+}
+
 bool Cws_accessEx::onPermissionAddInput(IEspContext &context, IEspPermissionAddRequest &req, IEspPermissionAddResponse &resp)
 {
     try

+ 12 - 0
esp/services/ws_access/ws_accessService.hpp

@@ -101,6 +101,18 @@ public:
     virtual bool onResourceAdd(IEspContext &context, IEspResourceAddRequest &req, IEspResourceAddResponse &resp);
     virtual bool onResourceAddInput(IEspContext &context, IEspResourceAddInputRequest &req, IEspResourceAddInputResponse &resp);
     virtual bool onResourcePermissions(IEspContext &context, IEspResourcePermissionsRequest &req, IEspResourcePermissionsResponse &resp);
+
+    virtual bool onQueryViews(IEspContext &context, IEspQueryViewsRequest &req, IEspQueryViewsResponse &resp);
+    virtual bool onAddView(IEspContext &context, IEspAddViewRequest &req, IEspAddViewResponse &resp);
+    virtual bool onDeleteView(IEspContext &context, IEspDeleteViewRequest &req, IEspDeleteViewResponse &resp);
+    virtual bool onQueryViewColumns(IEspContext &context, IEspQueryViewColumnsRequest &req, IEspQueryViewColumnsResponse &resp);
+    virtual bool onAddViewColumn(IEspContext &context, IEspAddViewColumnRequest &req, IEspAddViewColumnResponse &resp);
+    virtual bool onDeleteViewColumn(IEspContext &context, IEspDeleteViewColumnRequest &req, IEspDeleteViewColumnResponse &resp);
+    virtual bool onQueryViewMembers(IEspContext &context, IEspQueryViewMembersRequest &req, IEspQueryViewMembersResponse &resp);
+    virtual bool onAddViewMember(IEspContext &context, IEspAddViewMemberRequest &req, IEspAddViewMemberResponse &resp);
+    virtual bool onDeleteViewMember(IEspContext &context, IEspDeleteViewMemberRequest &req, IEspDeleteViewMemberResponse &resp);
+    virtual bool onQueryUserViewColumns(IEspContext &context, IEspQueryUserViewColumnsRequest &req, IEspQueryUserViewColumnsResponse &resp);
+
     virtual bool onPermissionAddInput(IEspContext &context, IEspPermissionAddRequest &req, IEspPermissionAddResponse &resp);
     virtual bool onPermissionAction(IEspContext &context, IEspPermissionActionRequest &req, IEspPermissionActionResponse &resp);
     virtual bool onUserGroupEditInput(IEspContext &context, IEspUserGroupEditInputRequest &req, IEspUserGroupEditInputResponse &resp);