From 2c5f34d6f3d9ddac30b980724f4eb3dad285882c Mon Sep 17 00:00:00 2001
From: Anuj Borah <aborah@redhat.com>
Date: Mar 06 2019 01:01:24 +0000
Subject: Issue: 50253 -  Making an nsManagedRoleDefinition type in src/lib389/lib389/idm/nsrole.py


Making an nsManagedRoleDefinition type in src/lib389/lib389/idm/nsrole.py

https://pagure.io/389-ds-base/issue/50253

Reviewed by: William Brown, thierry bordaz

---

diff --git a/dirsrvtests/tests/suites/acl/acivattr_test.py b/dirsrvtests/tests/suites/acl/acivattr_test.py
index 96011df..c4f9b9c 100644
--- a/dirsrvtests/tests/suites/acl/acivattr_test.py
+++ b/dirsrvtests/tests/suites/acl/acivattr_test.py
@@ -15,7 +15,7 @@ from lib389.cos import CosTemplate, CosClassicDefinition
 from lib389.topologies import topology_st as topo
 from lib389.idm.nscontainer import nsContainer
 from lib389.idm.domain import Domain
-from lib389.idm.nsrole import nsFilterRoles
+from lib389.idm.role import FilterRoles
 
 
 
@@ -55,7 +55,7 @@ def _add_user(request, topo):
     ou = OrganizationalUnit(topo.standalone, "ou=sales,o=acivattr,{}".format(DEFAULT_SUFFIX))
     ou.create(properties={'ou': 'sales'})
 
-    roles = nsFilterRoles(topo.standalone, DNBASE)
+    roles = FilterRoles(topo.standalone, DNBASE)
     roles.create(properties={'cn':'FILTERROLEENGROLE', 'nsRoleFilter':'cn=eng*'})
     roles.create(properties={'cn': 'FILTERROLESALESROLE', 'nsRoleFilter': 'cn=sales*'})
 
diff --git a/dirsrvtests/tests/suites/cos/cos_test.py b/dirsrvtests/tests/suites/cos/cos_test.py
index 98bed4d..6a24537 100644
--- a/dirsrvtests/tests/suites/cos/cos_test.py
+++ b/dirsrvtests/tests/suites/cos/cos_test.py
@@ -10,7 +10,7 @@ import pytest, os, ldap
 from lib389.cos import  CosClassicDefinition, CosClassicDefinitions, CosTemplate
 from lib389._constants import DEFAULT_SUFFIX
 from lib389.topologies import topology_st as topo
-from lib389.idm.nsrole import nsFilterRoles
+from lib389.idm.role import FilterRoles
 from lib389.idm.nscontainer import nsContainer
 from lib389.idm.user import UserAccount
 
@@ -35,7 +35,7 @@ def test_positive(topo):
             6. Operation should success
     """
     # Adding ns filter role
-    roles = nsFilterRoles(topo.standalone, DEFAULT_SUFFIX)
+    roles = FilterRoles(topo.standalone, DEFAULT_SUFFIX)
     roles.create(properties={'cn': 'FILTERROLEENGROLE',
                              'nsRoleFilter': 'cn=eng*'})
     # adding ns container
diff --git a/dirsrvtests/tests/suites/roles/basic_test.py b/dirsrvtests/tests/suites/roles/basic_test.py
index 6289d74..1d3079a 100644
--- a/dirsrvtests/tests/suites/roles/basic_test.py
+++ b/dirsrvtests/tests/suites/roles/basic_test.py
@@ -8,11 +8,12 @@
 
 import pytest, os
 from lib389._constants import PW_DM, DEFAULT_SUFFIX
-from lib389.idm.user import UserAccount
+from lib389.idm.user import UserAccount, UserAccounts
 from lib389.idm.organization import Organization
 from lib389.idm.organizationalunit import OrganizationalUnit
 from lib389.topologies import topology_st as topo
-from lib389.idm.nsrole import nsFilterRoles
+from lib389.idm.role import FilterRoles, ManagedRole, ManagedRoles
+from lib389.idm.domain import Domain
 
 
 DNBASE = "o=acivattr,{}".format(DEFAULT_SUFFIX)
@@ -26,7 +27,7 @@ FILTERROLESALESROLE = "cn=FILTERROLESALESROLE,{}".format(DNBASE)
 FILTERROLEENGROLE = "cn=FILTERROLEENGROLE,{}".format(DNBASE)
 
 
-def test_nsrole(topo):
+def test_filterrole(topo):
     '''
         :id: 8ada4064-786b-11e8-8634-8c16451d917b
         :setup: server
@@ -50,7 +51,7 @@ def test_nsrole(topo):
     ou = OrganizationalUnit(topo.standalone, "ou=sales,o=acivattr,{}".format(DEFAULT_SUFFIX))
     ou.create(properties=properties)
 
-    roles = nsFilterRoles(topo.standalone, DNBASE)
+    roles = FilterRoles(topo.standalone, DNBASE)
     roles.create(properties={'cn': 'FILTERROLEENGROLE', 'nsRoleFilter': 'cn=eng*'})
     roles.create(properties={'cn': 'FILTERROLESALESROLE', 'nsRoleFilter': 'cn=sales*'})
 
@@ -119,6 +120,71 @@ def test_nsrole(topo):
         UserAccount(topo.standalone, DN).delete()
 
 
+def test_managedrole(topo):
+    '''
+        :id: d52a9c00-3bf6-11e9-9b7b-8c16451d917b
+        :setup: server
+        :steps:
+            1. Add test entry
+            2. Add ACI
+            3. Search managed role entries
+        :expectedresults:
+            1. Entry should be added
+            2. Operation should  succeed
+            3. Operation should  succeed
+    '''
+    # Create Managed role entry
+    roles = ManagedRoles(topo.standalone, DEFAULT_SUFFIX)
+    role = roles.create(properties={"cn": 'ROLE1'})
+
+    # Create user and Assign the role to the entry
+    uas = UserAccounts(topo.standalone, DEFAULT_SUFFIX, rdn=None)
+    uas.create(properties={
+            'uid': 'Fail',
+            'cn': 'Fail',
+            'sn': 'user',
+            'uidNumber': '1000',
+            'gidNumber': '2000',
+            'homeDirectory': '/home/' + 'Fail',
+            'nsRoleDN': role.dn,
+            'userPassword': PW_DM
+        })
+
+    # Create user and do not Assign any role to the entry
+    uas.create(
+        properties={
+            'uid': 'Success',
+            'cn': 'Success',
+            'sn': 'user',
+            'uidNumber': '1000',
+            'gidNumber': '2000',
+            'homeDirectory': '/home/' + 'Success',
+            'userPassword': PW_DM
+        })
+
+    # Assert that Manage role entry is created and its searchable
+    assert ManagedRoles(topo.standalone, DEFAULT_SUFFIX).list()[0].dn == 'cn=ROLE1,dc=example,dc=com'
+
+    # Set an aci that will deny  ROLE1 manage role
+    Domain(topo.standalone, DEFAULT_SUFFIX).add('aci', '(targetattr=*)(version 3.0; aci "role aci"; deny(all) roledn="ldap:///{}";)'.format(role.dn),)
+
+    # Crate a connection with cn=Fail which is member of ROLE1
+    conn = UserAccount(topo.standalone, "uid=Fail,{}".format(DEFAULT_SUFFIX)).bind(PW_DM)
+    # Access denied to ROLE1 members
+    assert 0 == len(ManagedRoles(conn, DEFAULT_SUFFIX).list())
+
+    # Now create a connection with cn=Success which is not a member of ROLE1
+    conn = UserAccount(topo.standalone, "uid=Success,{}".format(DEFAULT_SUFFIX)).bind(PW_DM)
+    # Access allowed here
+    assert 1 == len(ManagedRoles(conn, DEFAULT_SUFFIX).list())
+
+    for i in uas.list():
+        i.delete()
+
+    for i in roles.list():
+        i.delete()
+
+
 if __name__ == "__main__":
     CURRENT_FILE = os.path.realpath(__file__)
     pytest.main("-s -v %s" % CURRENT_FILE)
diff --git a/src/lib389/lib389/idm/nsrole.py b/src/lib389/lib389/idm/nsrole.py
deleted file mode 100644
index 482837d..0000000
--- a/src/lib389/lib389/idm/nsrole.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# --- BEGIN COPYRIGHT BLOCK ---
-# Copyright (C) 2019 Red Hat, Inc.
-# All rights reserved.
-#
-# License: GPL (version 3 or any later version).
-# See LICENSE for details.
-# --- END COPYRIGHT BLOCK ----
-
-
-from lib389._mapped_object import DSLdapObject, DSLdapObjects
-
-
-class nsFilterRole(DSLdapObject):
-    """A single instance of nsfilter entry to create nsFIltered role.
-
-        :param instance: An instance
-        :type instance: lib389.DirSrv
-        :param dn: Entry DN
-        :type dn: str
-        Usages:
-        user1 = 'cn=anuj,ou=people,dc=example,ed=com'
-        user2 = 'cn=unknownuser,ou=people,dc=example,ed=com'
-        role=nsFilterRole(topo.standalone,'cn=NameofRole,ou=People,dc=example,dc=com')
-        role_props={'cn':'Anuj', 'nsRoleFilter':'cn=anuj*'}
-        role.create(properties=role_props, basedn=SUFFIX)
-        The user1 entry matches the filter (possesses the cn=anuj* attribute with the value anuj)
-        therefore, it is a member of this filtered role automatically.
-    """
-    def __init__(self, instance, dn=None):
-        super(nsFilterRole, self).__init__(instance, dn)
-        self._rdn_attribute = 'cn'
-        self._create_objectclasses = [
-            'top',
-            'nsRoleDefinition',
-            'nsComplexRoleDefinition',
-            'nsFilteredRoleDefinition'
-        ]
-
-
-class nsFilterRoles(DSLdapObjects):
-    """DSLdapObjects that represents all nsfiltertrole entries in suffix.
-
-        This instance is used mainly for search operation  nsfiltred role
-
-        :param instance: An instance
-        :type instance: lib389.DirSrv
-        :param basedn: Suffix DN
-        :type basedn: str
-        :param rdn: The DN that will be combined wit basedn
-        :type rdn: str
-        Usages:
-        role_props={'cn':'Anuj', 'nsRoleFilter':'cn=*'}
-        nsFilterRoles(topo.standalone, DEFAULT_SUFFIX).create(properties=role_props)
-        nsFilterRoles(topo.standalone, DEFAULT_SUFFIX).list()
-        user1 = 'cn=anuj,ou=people,dc=example,ed=com'
-        user2 = 'uid=unknownuser,ou=people,dc=example,ed=com'
-        The user1 entry matches the filter (possesses the cn=* attribute with the value cn)
-        therefore, it is a member of this filtered role automatically.
-        """
-    def __init__(self, instance, basedn):
-        super(nsFilterRoles, self).__init__(instance)
-        self._objectclasses = [
-            'top',
-            'nsRoleDefinition',
-            'nsComplexRoleDefinition',
-            'nsFilteredRoleDefinition'
-        ]
-        self._filterattrs = ['cn']
-        self._basedn = basedn
-        self._childobject = nsFilterRole
diff --git a/src/lib389/lib389/idm/role.py b/src/lib389/lib389/idm/role.py
new file mode 100644
index 0000000..91699d4
--- /dev/null
+++ b/src/lib389/lib389/idm/role.py
@@ -0,0 +1,115 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2019 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ----
+
+
+from lib389._mapped_object import DSLdapObject, DSLdapObjects
+
+
+class FilterRole(DSLdapObject):
+    """A single instance of FilterRole entry to create FilterRole role.
+
+        :param instance: An instance
+        :type instance: lib389.DirSrv
+        :param dn: Entry DN
+        :type dn: str
+        Usages:
+        user1 = 'cn=anuj,ou=people,dc=example,ed=com'
+        user2 = 'cn=unknownuser,ou=people,dc=example,ed=com'
+        role=FilterRole(topo.standalone,'cn=NameofRole,ou=People,dc=example,dc=com')
+        role_props={'cn':'Anuj', 'nsRoleFilter':'cn=anuj*'}
+        role.create(properties=role_props, basedn=SUFFIX)
+        The user1 entry matches the filter (possesses the cn=anuj* attribute with the value anuj)
+        therefore, it is a member of this filtered role automatically.
+    """
+    def __init__(self, instance, dn=None):
+        super(FilterRole, self).__init__(instance, dn)
+        self._rdn_attribute = 'cn'
+        self._create_objectclasses = [
+            'top',
+            'nsRoleDefinition',
+            'nsComplexRoleDefinition',
+            'nsFilteredRoleDefinition'
+        ]
+
+
+class FilterRoles(DSLdapObjects):
+    """DSLdapObjects that represents all filtertrole entries in suffix.
+
+        This instance is used mainly for search operation  filtred role
+
+        :param instance: An instance
+        :type instance: lib389.DirSrv
+        :param basedn: Suffix DN
+        :type basedn: str
+        :param rdn: The DN that will be combined wit basedn
+        :type rdn: str
+        Usages:
+        role_props={'cn':'Anuj', 'nsRoleFilter':'cn=*'}
+        FilterRoles(topo.standalone, DEFAULT_SUFFIX).create(properties=role_props)
+        FilterRoles(topo.standalone, DEFAULT_SUFFIX).list()
+        user1 = 'cn=anuj,ou=people,dc=example,ed=com'
+        user2 = 'uid=unknownuser,ou=people,dc=example,ed=com'
+        The user1 entry matches the filter (possesses the cn=* attribute with the value cn)
+        therefore, it is a member of this filtered role automatically.
+        """
+    def __init__(self, instance, basedn):
+        super(FilterRoles, self).__init__(instance)
+        self._objectclasses = [
+            'top',
+            'nsRoleDefinition',
+            'nsComplexRoleDefinition',
+            'nsFilteredRoleDefinition'
+        ]
+        self._filterattrs = ['cn']
+        self._basedn = basedn
+        self._childobject = FilterRole
+
+
+class ManagedRole(DSLdapObject):
+    """A single instance of ManagedRole entry to create ManagedRole role.
+
+        :param instance: An instance
+        :type instance: lib389.DirSrv
+        :param dn: Entry DN
+        :type dn: str
+
+    """
+    def __init__(self, instance, dn=None):
+        super(ManagedRole, self).__init__(instance, dn)
+        self._rdn_attribute = 'cn'
+        self._create_objectclasses = [
+            'top',
+            'nsRoleDefinition',
+            'nsSimpleRoleDefinition',
+            'nsManagedRoleDefinition'
+        ]
+
+
+class ManagedRoles(DSLdapObjects):
+    """DSLdapObjects that represents all ManagedRoles entries in suffix.
+
+        This instance is used mainly for search operation  ManagedRoles role
+
+        :param instance: An instance
+        :type instance: lib389.DirSrv
+        :param basedn: Suffix DN
+        :type basedn: str
+        :param rdn: The DN that will be combined wit basedn
+        :type rdn: str
+        """
+    def __init__(self, instance, basedn):
+        super(ManagedRoles, self).__init__(instance)
+        self._objectclasses = [
+            'top',
+            'nsRoleDefinition',
+            'nsSimpleRoleDefinition',
+            'nsManagedRoleDefinition'
+        ]
+        self._filterattrs = ['cn']
+        self._basedn = basedn
+        self._childobject = ManagedRole
\ No newline at end of file

