Fix bug 713
[osm/NBI.git] / osm_nbi / admin_topics.py
index 76e4065..bc2c7d9 100644 (file)
@@ -34,18 +34,17 @@ class UserTopic(BaseTopic):
     topic_msg = "users"
     schema_new = user_new_schema
     schema_edit = user_edit_schema
     topic_msg = "users"
     schema_new = user_new_schema
     schema_edit = user_edit_schema
+    multiproject = False
 
     def __init__(self, db, fs, msg):
         BaseTopic.__init__(self, db, fs, msg)
 
     @staticmethod
 
     def __init__(self, db, fs, msg):
         BaseTopic.__init__(self, db, fs, msg)
 
     @staticmethod
-    def _get_project_filter(session, write=False, show_all=True):
+    def _get_project_filter(session):
         """
         Generates a filter dictionary for querying database users.
         Current policy is admin can show all, non admin, only its own user.
         """
         Generates a filter dictionary for querying database users.
         Current policy is admin can show all, non admin, only its own user.
-        :param session: contains "username", if user is "admin" and the working "project_id"
-        :param write: if operation is for reading (False) or writing (True)
-        :param show_all:  if True it will show public or
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :return:
         """
         if session["admin"]:  # allows all
         :return:
         """
         if session["admin"]:  # allows all
@@ -53,21 +52,26 @@ class UserTopic(BaseTopic):
         else:
             return {"username": session["username"]}
 
         else:
             return {"username": session["username"]}
 
-    def check_conflict_on_new(self, session, indata, force=False):
+    def check_conflict_on_new(self, session, indata):
         # check username not exists
         if self.db.get_one(self.topic, {"username": indata.get("username")}, fail_on_empty=False, fail_on_more=False):
             raise EngineException("username '{}' exists".format(indata["username"]), HTTPStatus.CONFLICT)
         # check projects
         # check username not exists
         if self.db.get_one(self.topic, {"username": indata.get("username")}, fail_on_empty=False, fail_on_more=False):
             raise EngineException("username '{}' exists".format(indata["username"]), HTTPStatus.CONFLICT)
         # check projects
-        if not force:
-            for p in indata["projects"]:
-                if p == "admin":
-                    continue
+        if not session["force"]:
+            for p in indata.get("projects"):
                 # To allow project addressing by Name as well as ID
                 if not self.db.get_one("projects", {BaseTopic.id_field("projects", p): p}, fail_on_empty=False,
                                        fail_on_more=False):
                     raise EngineException("project '{}' does not exist".format(p), HTTPStatus.CONFLICT)
 
                 # To allow project addressing by Name as well as ID
                 if not self.db.get_one("projects", {BaseTopic.id_field("projects", p): p}, fail_on_empty=False,
                                        fail_on_more=False):
                     raise EngineException("project '{}' does not exist".format(p), HTTPStatus.CONFLICT)
 
-    def check_conflict_on_del(self, session, _id, force=False):
+    def check_conflict_on_del(self, session, _id, db_content):
+        """
+        Check if deletion can be done because of dependencies if it is not force. To override
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
+        :param _id: internal _id
+        :param db_content: The database content of this item _id
+        :return: None if ok or raises EngineException with the conflict
+        """
         if _id == session["username"]:
             raise EngineException("You cannot delete your own user", http_code=HTTPStatus.CONFLICT)
 
         if _id == session["username"]:
             raise EngineException("You cannot delete your own user", http_code=HTTPStatus.CONFLICT)
 
@@ -80,6 +84,13 @@ class UserTopic(BaseTopic):
         content["_admin"]["salt"] = salt
         if content.get("password"):
             content["password"] = sha256(content["password"].encode('utf-8') + salt.encode('utf-8')).hexdigest()
         content["_admin"]["salt"] = salt
         if content.get("password"):
             content["password"] = sha256(content["password"].encode('utf-8') + salt.encode('utf-8')).hexdigest()
+        if content.get("project_role_mappings"):
+            projects = [mapping[0] for mapping in content["project_role_mappings"]]
+
+            if content.get("projects"):
+                content["projects"] += projects
+            else:
+                content["projects"] = projects
 
     @staticmethod
     def format_on_edit(final_content, edit_content):
 
     @staticmethod
     def format_on_edit(final_content, edit_content):
@@ -90,7 +101,7 @@ class UserTopic(BaseTopic):
             final_content["password"] = sha256(edit_content["password"].encode('utf-8') +
                                                salt.encode('utf-8')).hexdigest()
 
             final_content["password"] = sha256(edit_content["password"].encode('utf-8') +
                                                salt.encode('utf-8')).hexdigest()
 
-    def edit(self, session, _id, indata=None, kwargs=None, force=False, content=None):
+    def edit(self, session, _id, indata=None, kwargs=None, content=None):
         if not session["admin"]:
             raise EngineException("needed admin privileges", http_code=HTTPStatus.UNAUTHORIZED)
         # Names that look like UUIDs are not allowed
         if not session["admin"]:
             raise EngineException("needed admin privileges", http_code=HTTPStatus.UNAUTHORIZED)
         # Names that look like UUIDs are not allowed
@@ -98,9 +109,9 @@ class UserTopic(BaseTopic):
         if is_valid_uuid(name):
             raise EngineException("Usernames that look like UUIDs are not allowed",
                                   http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
         if is_valid_uuid(name):
             raise EngineException("Usernames that look like UUIDs are not allowed",
                                   http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
-        return BaseTopic.edit(self, session, _id, indata=indata, kwargs=kwargs, force=force, content=content)
+        return BaseTopic.edit(self, session, _id, indata=indata, kwargs=kwargs, content=content)
 
 
-    def new(self, rollback, session, indata=None, kwargs=None, headers=None, force=False, make_public=False):
+    def new(self, rollback, session, indata=None, kwargs=None, headers=None):
         if not session["admin"]:
             raise EngineException("needed admin privileges", http_code=HTTPStatus.UNAUTHORIZED)
         # Names that look like UUIDs are not allowed
         if not session["admin"]:
             raise EngineException("needed admin privileges", http_code=HTTPStatus.UNAUTHORIZED)
         # Names that look like UUIDs are not allowed
@@ -108,8 +119,7 @@ class UserTopic(BaseTopic):
         if is_valid_uuid(name):
             raise EngineException("Usernames that look like UUIDs are not allowed",
                                   http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
         if is_valid_uuid(name):
             raise EngineException("Usernames that look like UUIDs are not allowed",
                                   http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
-        return BaseTopic.new(self, rollback, session, indata=indata, kwargs=kwargs, headers=headers, force=force,
-                             make_public=make_public)
+        return BaseTopic.new(self, rollback, session, indata=indata, kwargs=kwargs, headers=headers)
 
 
 class ProjectTopic(BaseTopic):
 
 
 class ProjectTopic(BaseTopic):
@@ -117,11 +127,25 @@ class ProjectTopic(BaseTopic):
     topic_msg = "projects"
     schema_new = project_new_schema
     schema_edit = project_edit_schema
     topic_msg = "projects"
     schema_new = project_new_schema
     schema_edit = project_edit_schema
+    multiproject = False
 
     def __init__(self, db, fs, msg):
         BaseTopic.__init__(self, db, fs, msg)
 
 
     def __init__(self, db, fs, msg):
         BaseTopic.__init__(self, db, fs, msg)
 
-    def check_conflict_on_new(self, session, indata, force=False):
+    @staticmethod
+    def _get_project_filter(session):
+        """
+        Generates a filter dictionary for querying database users.
+        Current policy is admin can show all, non admin, only its own user.
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
+        :return:
+        """
+        if session["admin"]:  # allows all
+            return {}
+        else:
+            return {"_id.cont": session["project_id"]}
+
+    def check_conflict_on_new(self, session, indata):
         if not indata.get("name"):
             raise EngineException("missing 'name'")
         # check name not exists
         if not indata.get("name"):
             raise EngineException("missing 'name'")
         # check name not exists
@@ -134,16 +158,23 @@ class ProjectTopic(BaseTopic):
         # Removed so that the UUID is kept, to allow Project Name modification
         # content["_id"] = content["name"]
 
         # Removed so that the UUID is kept, to allow Project Name modification
         # content["_id"] = content["name"]
 
-    def check_conflict_on_del(self, session, _id, force=False):
-        if _id == session["project_id"]:
+    def check_conflict_on_del(self, session, _id, db_content):
+        """
+        Check if deletion can be done because of dependencies if it is not force. To override
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
+        :param _id: internal _id
+        :param db_content: The database content of this item _id
+        :return: None if ok or raises EngineException with the conflict
+        """
+        if _id in session["project_id"]:
             raise EngineException("You cannot delete your own project", http_code=HTTPStatus.CONFLICT)
             raise EngineException("You cannot delete your own project", http_code=HTTPStatus.CONFLICT)
-        if force:
+        if session["force"]:
             return
         _filter = {"projects": _id}
         if self.db.get_list("users", _filter):
             raise EngineException("There is some USER that contains this project", http_code=HTTPStatus.CONFLICT)
 
             return
         _filter = {"projects": _id}
         if self.db.get_list("users", _filter):
             raise EngineException("There is some USER that contains this project", http_code=HTTPStatus.CONFLICT)
 
-    def edit(self, session, _id, indata=None, kwargs=None, force=False, content=None):
+    def edit(self, session, _id, indata=None, kwargs=None, content=None):
         if not session["admin"]:
             raise EngineException("needed admin privileges", http_code=HTTPStatus.UNAUTHORIZED)
         # Names that look like UUIDs are not allowed
         if not session["admin"]:
             raise EngineException("needed admin privileges", http_code=HTTPStatus.UNAUTHORIZED)
         # Names that look like UUIDs are not allowed
@@ -151,9 +182,9 @@ class ProjectTopic(BaseTopic):
         if is_valid_uuid(name):
             raise EngineException("Project names that look like UUIDs are not allowed",
                                   http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
         if is_valid_uuid(name):
             raise EngineException("Project names that look like UUIDs are not allowed",
                                   http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
-        return BaseTopic.edit(self, session, _id, indata=indata, kwargs=kwargs, force=force, content=content)
+        return BaseTopic.edit(self, session, _id, indata=indata, kwargs=kwargs, content=content)
 
 
-    def new(self, rollback, session, indata=None, kwargs=None, headers=None, force=False, make_public=False):
+    def new(self, rollback, session, indata=None, kwargs=None, headers=None):
         if not session["admin"]:
             raise EngineException("needed admin privileges", http_code=HTTPStatus.UNAUTHORIZED)
         # Names that look like UUIDs are not allowed
         if not session["admin"]:
             raise EngineException("needed admin privileges", http_code=HTTPStatus.UNAUTHORIZED)
         # Names that look like UUIDs are not allowed
@@ -161,8 +192,7 @@ class ProjectTopic(BaseTopic):
         if is_valid_uuid(name):
             raise EngineException("Project names that look like UUIDs are not allowed",
                                   http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
         if is_valid_uuid(name):
             raise EngineException("Project names that look like UUIDs are not allowed",
                                   http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
-        return BaseTopic.new(self, rollback, session, indata=indata, kwargs=kwargs, headers=headers, force=force,
-                             make_public=make_public)
+        return BaseTopic.new(self, rollback, session, indata=indata, kwargs=kwargs, headers=headers)
 
 
 class VimAccountTopic(BaseTopic):
 
 
 class VimAccountTopic(BaseTopic):
@@ -171,15 +201,16 @@ class VimAccountTopic(BaseTopic):
     schema_new = vim_account_new_schema
     schema_edit = vim_account_edit_schema
     vim_config_encrypted = ("admin_password", "nsx_password", "vcenter_password")
     schema_new = vim_account_new_schema
     schema_edit = vim_account_edit_schema
     vim_config_encrypted = ("admin_password", "nsx_password", "vcenter_password")
+    multiproject = True
 
     def __init__(self, db, fs, msg):
         BaseTopic.__init__(self, db, fs, msg)
 
 
     def __init__(self, db, fs, msg):
         BaseTopic.__init__(self, db, fs, msg)
 
-    def check_conflict_on_new(self, session, indata, force=False):
+    def check_conflict_on_new(self, session, indata):
         self.check_unique_name(session, indata["name"], _id=None)
 
         self.check_unique_name(session, indata["name"], _id=None)
 
-    def check_conflict_on_edit(self, session, final_content, edit_content, _id, force=False):
-        if not force and edit_content.get("name"):
+    def check_conflict_on_edit(self, session, final_content, edit_content, _id):
+        if not session["force"] and edit_content.get("name"):
             self.check_unique_name(session, edit_content["name"], _id=_id)
 
         # encrypt passwords
             self.check_unique_name(session, edit_content["name"], _id=_id)
 
         # encrypt passwords
@@ -210,20 +241,19 @@ class VimAccountTopic(BaseTopic):
 
         content["_admin"]["operationalState"] = "PROCESSING"
 
 
         content["_admin"]["operationalState"] = "PROCESSING"
 
-    def delete(self, session, _id, force=False, dry_run=False):
+    def delete(self, session, _id, dry_run=False):
         """
         Delete item by its internal _id
         """
         Delete item by its internal _id
-        :param session: contains the used login username, working project, and admin rights
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id: server internal id
         :param _id: server internal id
-        :param force: indicates if deletion must be forced in case of conflict
         :param dry_run: make checking but do not delete
         :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ...
         """
         # TODO add admin to filter, validate rights
         :param dry_run: make checking but do not delete
         :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ...
         """
         # TODO add admin to filter, validate rights
-        if dry_run or force:    # delete completely
-            return BaseTopic.delete(self, session, _id, force, dry_run)
+        if dry_run or session["force"]:    # delete completely
+            return BaseTopic.delete(self, session, _id, dry_run)
         else:  # if not, sent to kafka
         else:  # if not, sent to kafka
-            v = BaseTopic.delete(self, session, _id, force, dry_run=True)
+            v = BaseTopic.delete(self, session, _id, dry_run=True)
             self.db.set_one("vim_accounts", {"_id": _id}, {"_admin.to_delete": True})  # TODO change status
             self._send_msg("delete", {"_id": _id})
             return v  # TODO indicate an offline operation to return 202 ACCEPTED
             self.db.set_one("vim_accounts", {"_id": _id}, {"_admin.to_delete": True})  # TODO change status
             self._send_msg("delete", {"_id": _id})
             return v  # TODO indicate an offline operation to return 202 ACCEPTED
@@ -234,16 +264,17 @@ class WimAccountTopic(BaseTopic):
     topic_msg = "wim_account"
     schema_new = wim_account_new_schema
     schema_edit = wim_account_edit_schema
     topic_msg = "wim_account"
     schema_new = wim_account_new_schema
     schema_edit = wim_account_edit_schema
+    multiproject = True
     wim_config_encrypted = ()
 
     def __init__(self, db, fs, msg):
         BaseTopic.__init__(self, db, fs, msg)
 
     wim_config_encrypted = ()
 
     def __init__(self, db, fs, msg):
         BaseTopic.__init__(self, db, fs, msg)
 
-    def check_conflict_on_new(self, session, indata, force=False):
+    def check_conflict_on_new(self, session, indata):
         self.check_unique_name(session, indata["name"], _id=None)
 
         self.check_unique_name(session, indata["name"], _id=None)
 
-    def check_conflict_on_edit(self, session, final_content, edit_content, _id, force=False):
-        if not force and edit_content.get("name"):
+    def check_conflict_on_edit(self, session, final_content, edit_content, _id):
+        if not session["force"] and edit_content.get("name"):
             self.check_unique_name(session, edit_content["name"], _id=_id)
 
         # encrypt passwords
             self.check_unique_name(session, edit_content["name"], _id=_id)
 
         # encrypt passwords
@@ -274,20 +305,19 @@ class WimAccountTopic(BaseTopic):
 
         content["_admin"]["operationalState"] = "PROCESSING"
 
 
         content["_admin"]["operationalState"] = "PROCESSING"
 
-    def delete(self, session, _id, force=False, dry_run=False):
+    def delete(self, session, _id, dry_run=False):
         """
         Delete item by its internal _id
         """
         Delete item by its internal _id
-        :param session: contains the used login username, working project, and admin rights
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id: server internal id
         :param _id: server internal id
-        :param force: indicates if deletion must be forced in case of conflict
         :param dry_run: make checking but do not delete
         :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ...
         """
         # TODO add admin to filter, validate rights
         :param dry_run: make checking but do not delete
         :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ...
         """
         # TODO add admin to filter, validate rights
-        if dry_run or force:    # delete completely
-            return BaseTopic.delete(self, session, _id, force, dry_run)
+        if dry_run or session["force"]:    # delete completely
+            return BaseTopic.delete(self, session, _id, dry_run)
         else:  # if not, sent to kafka
         else:  # if not, sent to kafka
-            v = BaseTopic.delete(self, session, _id, force, dry_run=True)
+            v = BaseTopic.delete(self, session, _id, dry_run=True)
             self.db.set_one("wim_accounts", {"_id": _id}, {"_admin.to_delete": True})  # TODO change status
             self._send_msg("delete", {"_id": _id})
             return v  # TODO indicate an offline operation to return 202 ACCEPTED
             self.db.set_one("wim_accounts", {"_id": _id}, {"_admin.to_delete": True})  # TODO change status
             self._send_msg("delete", {"_id": _id})
             return v  # TODO indicate an offline operation to return 202 ACCEPTED
@@ -298,15 +328,16 @@ class SdnTopic(BaseTopic):
     topic_msg = "sdn"
     schema_new = sdn_new_schema
     schema_edit = sdn_edit_schema
     topic_msg = "sdn"
     schema_new = sdn_new_schema
     schema_edit = sdn_edit_schema
+    multiproject = True
 
     def __init__(self, db, fs, msg):
         BaseTopic.__init__(self, db, fs, msg)
 
 
     def __init__(self, db, fs, msg):
         BaseTopic.__init__(self, db, fs, msg)
 
-    def check_conflict_on_new(self, session, indata, force=False):
+    def check_conflict_on_new(self, session, indata):
         self.check_unique_name(session, indata["name"], _id=None)
 
         self.check_unique_name(session, indata["name"], _id=None)
 
-    def check_conflict_on_edit(self, session, final_content, edit_content, _id, force=False):
-        if not force and edit_content.get("name"):
+    def check_conflict_on_edit(self, session, final_content, edit_content, _id):
+        if not session["force"] and edit_content.get("name"):
             self.check_unique_name(session, edit_content["name"], _id=_id)
 
         # encrypt passwords
             self.check_unique_name(session, edit_content["name"], _id=_id)
 
         # encrypt passwords
@@ -325,27 +356,26 @@ class SdnTopic(BaseTopic):
 
         content["_admin"]["operationalState"] = "PROCESSING"
 
 
         content["_admin"]["operationalState"] = "PROCESSING"
 
-    def delete(self, session, _id, force=False, dry_run=False):
+    def delete(self, session, _id, dry_run=False):
         """
         Delete item by its internal _id
         """
         Delete item by its internal _id
-        :param session: contains the used login username, working project, and admin rights
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id: server internal id
         :param _id: server internal id
-        :param force: indicates if deletion must be forced in case of conflict
         :param dry_run: make checking but do not delete
         :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ...
         """
         :param dry_run: make checking but do not delete
         :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ...
         """
-        if dry_run or force:  # delete completely
-            return BaseTopic.delete(self, session, _id, force, dry_run)
+        if dry_run or session["force"]:  # delete completely
+            return BaseTopic.delete(self, session, _id, dry_run)
         else:  # if not sent to kafka
         else:  # if not sent to kafka
-            v = BaseTopic.delete(self, session, _id, force, dry_run=True)
+            v = BaseTopic.delete(self, session, _id, dry_run=True)
             self.db.set_one("sdns", {"_id": _id}, {"_admin.to_delete": True})  # TODO change status
             self._send_msg("delete", {"_id": _id})
             return v   # TODO indicate an offline operation to return 202 ACCEPTED
 
 
 class UserTopicAuth(UserTopic):
             self.db.set_one("sdns", {"_id": _id}, {"_admin.to_delete": True})  # TODO change status
             self._send_msg("delete", {"_id": _id})
             return v   # TODO indicate an offline operation to return 202 ACCEPTED
 
 
 class UserTopicAuth(UserTopic):
-    topic = "users"
-    topic_msg = "users"
+    topic = "users"
+    topic_msg = "users"
     schema_new = user_new_schema
     schema_edit = user_edit_schema
 
     schema_new = user_new_schema
     schema_edit = user_edit_schema
 
@@ -353,30 +383,32 @@ class UserTopicAuth(UserTopic):
         UserTopic.__init__(self, db, fs, msg)
         self.auth = auth
 
         UserTopic.__init__(self, db, fs, msg)
         self.auth = auth
 
-    def check_conflict_on_new(self, session, indata, force=False):
+    def check_conflict_on_new(self, session, indata):
         """
         Check that the data to be inserted is valid
 
         """
         Check that the data to be inserted is valid
 
-        :param session: contains "username", if user is "admin" and the working "project_id"
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param indata: data to be inserted
         :param indata: data to be inserted
-        :param force: boolean. With force it is more tolerant
         :return: None or raises EngineException
         """
         username = indata.get("username")
         user_list = list(map(lambda x: x["username"], self.auth.get_user_list()))
 
         :return: None or raises EngineException
         """
         username = indata.get("username")
         user_list = list(map(lambda x: x["username"], self.auth.get_user_list()))
 
+        if "projects" in indata.keys():
+            raise EngineException("Format invalid: the keyword \"projects\" is not allowed for Keystone", 
+                                  HTTPStatus.BAD_REQUEST)
+
         if username in user_list:
             raise EngineException("username '{}' exists".format(username), HTTPStatus.CONFLICT)
 
         if username in user_list:
             raise EngineException("username '{}' exists".format(username), HTTPStatus.CONFLICT)
 
-    def check_conflict_on_edit(self, session, final_content, edit_content, _id, force=False):
+    def check_conflict_on_edit(self, session, final_content, edit_content, _id):
         """
         Check that the data to be edited/uploaded is valid
 
         """
         Check that the data to be edited/uploaded is valid
 
-        :param session: contains "username", if user is "admin" and the working "project_id"
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param final_content: data once modified
         :param edit_content: incremental data that contains the modifications to apply
         :param _id: internal _id
         :param final_content: data once modified
         :param edit_content: incremental data that contains the modifications to apply
         :param _id: internal _id
-        :param force: boolean. With force it is more tolerant
         :return: None or raises EngineException
         """
         users = self.auth.get_user_list()
         :return: None or raises EngineException
         """
         users = self.auth.get_user_list()
@@ -391,13 +423,12 @@ class UserTopicAuth(UserTopic):
                 raise EngineException("You cannot remove system_admin role from admin user", 
                                       http_code=HTTPStatus.FORBIDDEN)
 
                 raise EngineException("You cannot remove system_admin role from admin user", 
                                       http_code=HTTPStatus.FORBIDDEN)
 
-    def check_conflict_on_del(self, session, _id, force=False):
+    def check_conflict_on_del(self, session, _id, db_content):
         """
         Check if deletion can be done because of dependencies if it is not force. To override
         """
         Check if deletion can be done because of dependencies if it is not force. To override
-
-        :param session: contains "username", if user is "admin" and the working "project_id"
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id: internal _id
         :param _id: internal _id
-        :param force: Avoid this checking
+        :param db_content: The database content of this item _id
         :return: None if ok or raises EngineException with the conflict
         """
         if _id == session["username"]:
         :return: None if ok or raises EngineException with the conflict
         """
         if _id == session["username"]:
@@ -437,19 +468,32 @@ class UserTopicAuth(UserTopic):
         else:
             final_content["project_role_mappings"] = edit_content["project_role_mappings"]
 
         else:
             final_content["project_role_mappings"] = edit_content["project_role_mappings"]
 
-    def new(self, rollback, session, indata=None, kwargs=None, headers=None, force=False, make_public=False):
+    @staticmethod
+    def format_on_show(content):
+        """
+        Modifies the content of the role information to separate the role 
+        metadata from the role definition.
+        """
+        project_role_mappings = []
+
+        for project in content["projects"]:
+            for role in project["roles"]:
+                project_role_mappings.append({"project": project, "role": role})
+        
+        del content["projects"]
+        content["project_role_mappings"] = project_role_mappings
+
+    def new(self, rollback, session, indata=None, kwargs=None, headers=None):
         """
         Creates a new entry into the authentication backend.
 
         NOTE: Overrides BaseTopic functionality because it doesn't require access to database.
 
         :param rollback: list to append created items at database in case a rollback may to be done
         """
         Creates a new entry into the authentication backend.
 
         NOTE: Overrides BaseTopic functionality because it doesn't require access to database.
 
         :param rollback: list to append created items at database in case a rollback may to be done
-        :param session: contains the used login username and working project
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param indata: data to be inserted
         :param kwargs: used to override the indata descriptor
         :param headers: http request headers
         :param indata: data to be inserted
         :param kwargs: used to override the indata descriptor
         :param headers: http request headers
-        :param force: If True avoid some dependence checks
-        :param make_public: Make the created item public to all projects
         :return: _id: identity of the inserted data.
         """
         try:
         :return: _id: identity of the inserted data.
         """
         try:
@@ -457,9 +501,9 @@ class UserTopicAuth(UserTopic):
 
             # Override descriptor with query string kwargs
             BaseTopic._update_input_with_kwargs(content, kwargs)
 
             # Override descriptor with query string kwargs
             BaseTopic._update_input_with_kwargs(content, kwargs)
-            content = self._validate_input_new(content, force)
-            self.check_conflict_on_new(session, content, force=force)
-            self.format_on_new(content, project_id=session["project_id"], make_public=make_public)
+            content = self._validate_input_new(content, session["force"])
+            self.check_conflict_on_new(session, content)
+            self.format_on_new(content, session["project_id"], make_public=session["public"])
             _id = self.auth.create_user(content["username"], content["password"])
             rollback.append({"topic": self.topic, "_id": _id})
             del content["password"]
             _id = self.auth.create_user(content["username"], content["password"])
             rollback.append({"topic": self.topic, "_id": _id})
             del content["password"]
@@ -472,28 +516,27 @@ class UserTopicAuth(UserTopic):
         """
         Get complete information on an topic
 
         """
         Get complete information on an topic
 
-        :param session: contains the used login username and working project
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id: server internal id
         :return: dictionary, raise exception if not found.
         """
         users = [user for user in self.auth.get_user_list() if user["_id"] == _id]
 
         if len(users) == 1:
         :param _id: server internal id
         :return: dictionary, raise exception if not found.
         """
         users = [user for user in self.auth.get_user_list() if user["_id"] == _id]
 
         if len(users) == 1:
-            return users[0]
+            return self.format_on_show(users[0])
         elif len(users) > 1:
             raise EngineException("Too many users found", HTTPStatus.CONFLICT)
         else:
             raise EngineException("User not found", HTTPStatus.NOT_FOUND)
 
         elif len(users) > 1:
             raise EngineException("Too many users found", HTTPStatus.CONFLICT)
         else:
             raise EngineException("User not found", HTTPStatus.NOT_FOUND)
 
-    def edit(self, session, _id, indata=None, kwargs=None, force=False, content=None):
+    def edit(self, session, _id, indata=None, kwargs=None, content=None):
         """
         Updates an user entry.
 
         """
         Updates an user entry.
 
-        :param session: contains the used login username and working project
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id:
         :param indata: data to be inserted
         :param kwargs: used to override the indata descriptor
         :param _id:
         :param indata: data to be inserted
         :param kwargs: used to override the indata descriptor
-        :param force: If True avoid some dependence checks
         :param content:
         :return: _id: identity of the inserted data.
         """
         :param content:
         :return: _id: identity of the inserted data.
         """
@@ -503,27 +546,19 @@ class UserTopicAuth(UserTopic):
         if kwargs:
             BaseTopic._update_input_with_kwargs(indata, kwargs)
         try:
         if kwargs:
             BaseTopic._update_input_with_kwargs(indata, kwargs)
         try:
-            indata = self._validate_input_edit(indata, force=force)
+            indata = self._validate_input_edit(indata, force=session["force"])
 
             if not content:
                 content = self.show(session, _id)
 
             if not content:
                 content = self.show(session, _id)
-            self.check_conflict_on_edit(session, content, indata, _id=_id, force=force)
+            self.check_conflict_on_edit(session, content, indata, _id=_id)
             self.format_on_edit(content, indata)
 
             if "password" in content:
                 self.auth.change_password(content["name"], content["password"])
             else:
             self.format_on_edit(content, indata)
 
             if "password" in content:
                 self.auth.change_password(content["name"], content["password"])
             else:
-                users = self.auth.get_user_list()
-                user = [user for user in users if user["_id"] == content["_id"]][0]
-                original_mapping = []
+                user = self.show(session, _id)
+                original_mapping = user["project_role_mappings"]
                 edit_mapping = content["project_role_mappings"]
                 edit_mapping = content["project_role_mappings"]
-
-                for project in user["projects"]:
-                    for role in project["roles"]:
-                        original_mapping += {
-                            "project": project["name"],
-                            "role": role["name"]
-                        }
                 
                 mappings_to_remove = [mapping for mapping in original_mapping 
                                       if mapping not in edit_mapping]
                 
                 mappings_to_remove = [mapping for mapping in original_mapping 
                                       if mapping not in edit_mapping]
@@ -552,23 +587,28 @@ class UserTopicAuth(UserTopic):
     def list(self, session, filter_q=None):
         """
         Get a list of the topic that matches a filter
     def list(self, session, filter_q=None):
         """
         Get a list of the topic that matches a filter
-        :param session: contains the used login username and working project
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param filter_q: filter of data to be applied
         :return: The list, it can be empty if no one match the filter.
         """
         :param filter_q: filter of data to be applied
         :return: The list, it can be empty if no one match the filter.
         """
-        return self.auth.get_user_list()
+        if not filter_q:
+            filter_q = {}
+
+        users = [self.format_on_show(user) for user in self.auth.get_user_list(filter_q)]
 
 
-    def delete(self, session, _id, force=False, dry_run=False):
+        return users
+
+    def delete(self, session, _id, dry_run=False):
         """
         Delete item by its internal _id
 
         """
         Delete item by its internal _id
 
-        :param session: contains the used login username, working project, and admin rights
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id: server internal id
         :param force: indicates if deletion must be forced in case of conflict
         :param dry_run: make checking but do not delete
         :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ...
         """
         :param _id: server internal id
         :param force: indicates if deletion must be forced in case of conflict
         :param dry_run: make checking but do not delete
         :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ...
         """
-        self.check_conflict_on_del(session, _id, force)
+        self.check_conflict_on_del(session, _id, None)
         if not dry_run:
             v = self.auth.delete_user(_id)
             return v
         if not dry_run:
             v = self.auth.delete_user(_id)
             return v
@@ -576,22 +616,21 @@ class UserTopicAuth(UserTopic):
 
 
 class ProjectTopicAuth(ProjectTopic):
 
 
 class ProjectTopicAuth(ProjectTopic):
-    topic = "projects"
-    topic_msg = "projects"
-    schema_new = project_new_schema
-    schema_edit = project_edit_schema
+    topic = "projects"
+    topic_msg = "projects"
+    schema_new = project_new_schema
+    schema_edit = project_edit_schema
 
     def __init__(self, db, fs, msg, auth):
         ProjectTopic.__init__(self, db, fs, msg)
         self.auth = auth
 
 
     def __init__(self, db, fs, msg, auth):
         ProjectTopic.__init__(self, db, fs, msg)
         self.auth = auth
 
-    def check_conflict_on_new(self, session, indata, force=False):
+    def check_conflict_on_new(self, session, indata):
         """
         Check that the data to be inserted is valid
 
         """
         Check that the data to be inserted is valid
 
-        :param session: contains "username", if user is "admin" and the working "project_id"
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param indata: data to be inserted
         :param indata: data to be inserted
-        :param force: boolean. With force it is more tolerant
         :return: None or raises EngineException
         """
         project = indata.get("name")
         :return: None or raises EngineException
         """
         project = indata.get("name")
@@ -600,13 +639,13 @@ class ProjectTopicAuth(ProjectTopic):
         if project in project_list:
             raise EngineException("project '{}' exists".format(project), HTTPStatus.CONFLICT)
 
         if project in project_list:
             raise EngineException("project '{}' exists".format(project), HTTPStatus.CONFLICT)
 
-    def check_conflict_on_del(self, session, _id, force=False):
+    def check_conflict_on_del(self, session, _id, db_content):
         """
         Check if deletion can be done because of dependencies if it is not force. To override
 
         """
         Check if deletion can be done because of dependencies if it is not force. To override
 
-        :param session: contains "username", if user is "admin" and the working "project_id"
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id: internal _id
         :param _id: internal _id
-        :param force: Avoid this checking
+        :param db_content: The database content of this item _id
         :return: None if ok or raises EngineException with the conflict
         """
         projects = self.auth.get_project_list()
         :return: None if ok or raises EngineException with the conflict
         """
         projects = self.auth.get_project_list()
@@ -616,19 +655,17 @@ class ProjectTopicAuth(ProjectTopic):
         if _id == current_project["_id"]:
             raise EngineException("You cannot delete your own project", http_code=HTTPStatus.CONFLICT)
 
         if _id == current_project["_id"]:
             raise EngineException("You cannot delete your own project", http_code=HTTPStatus.CONFLICT)
 
-    def new(self, rollback, session, indata=None, kwargs=None, headers=None, force=False, make_public=False):
+    def new(self, rollback, session, indata=None, kwargs=None, headers=None):
         """
         Creates a new entry into the authentication backend.
 
         NOTE: Overrides BaseTopic functionality because it doesn't require access to database.
 
         :param rollback: list to append created items at database in case a rollback may to be done
         """
         Creates a new entry into the authentication backend.
 
         NOTE: Overrides BaseTopic functionality because it doesn't require access to database.
 
         :param rollback: list to append created items at database in case a rollback may to be done
-        :param session: contains the used login username and working project
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param indata: data to be inserted
         :param kwargs: used to override the indata descriptor
         :param headers: http request headers
         :param indata: data to be inserted
         :param kwargs: used to override the indata descriptor
         :param headers: http request headers
-        :param force: If True avoid some dependence checks
-        :param make_public: Make the created item public to all projects
         :return: _id: identity of the inserted data.
         """
         try:
         :return: _id: identity of the inserted data.
         """
         try:
@@ -636,9 +673,9 @@ class ProjectTopicAuth(ProjectTopic):
 
             # Override descriptor with query string kwargs
             BaseTopic._update_input_with_kwargs(content, kwargs)
 
             # Override descriptor with query string kwargs
             BaseTopic._update_input_with_kwargs(content, kwargs)
-            content = self._validate_input_new(content, force)
-            self.check_conflict_on_new(session, content, force=force)
-            self.format_on_new(content, project_id=session["project_id"], make_public=make_public)
+            content = self._validate_input_new(content, session["force"])
+            self.check_conflict_on_new(session, content)
+            self.format_on_new(content, project_id=session["project_id"], make_public=session["public"])
             _id = self.auth.create_project(content["name"])
             rollback.append({"topic": self.topic, "_id": _id})
             # self._send_msg("create", content)
             _id = self.auth.create_project(content["name"])
             rollback.append({"topic": self.topic, "_id": _id})
             # self._send_msg("create", content)
@@ -650,7 +687,7 @@ class ProjectTopicAuth(ProjectTopic):
         """
         Get complete information on an topic
 
         """
         Get complete information on an topic
 
-        :param session: contains the used login username and working project
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id: server internal id
         :return: dictionary, raise exception if not found.
         """
         :param _id: server internal id
         :return: dictionary, raise exception if not found.
         """
@@ -667,23 +704,25 @@ class ProjectTopicAuth(ProjectTopic):
         """
         Get a list of the topic that matches a filter
 
         """
         Get a list of the topic that matches a filter
 
-        :param session: contains the used login username and working project
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param filter_q: filter of data to be applied
         :return: The list, it can be empty if no one match the filter.
         """
         :param filter_q: filter of data to be applied
         :return: The list, it can be empty if no one match the filter.
         """
-        return self.auth.get_project_list()
+        if not filter_q:
+            filter_q = {}
 
 
-    def delete(self, session, _id, force=False, dry_run=False):
+        return self.auth.get_project_list(filter_q)
+
+    def delete(self, session, _id, dry_run=False):
         """
         Delete item by its internal _id
 
         """
         Delete item by its internal _id
 
-        :param session: contains the used login username, working project, and admin rights
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id: server internal id
         :param _id: server internal id
-        :param force: indicates if deletion must be forced in case of conflict
         :param dry_run: make checking but do not delete
         :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ...
         """
         :param dry_run: make checking but do not delete
         :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ...
         """
-        self.check_conflict_on_del(session, _id, force)
+        self.check_conflict_on_del(session, _id, None)
         if not dry_run:
             v = self.auth.delete_project(_id)
             return v
         if not dry_run:
             v = self.auth.delete_project(_id)
             return v
@@ -695,6 +734,7 @@ class RoleTopicAuth(BaseTopic):
     topic_msg = "roles"
     schema_new = roles_new_schema
     schema_edit = roles_edit_schema
     topic_msg = "roles"
     schema_new = roles_new_schema
     schema_edit = roles_edit_schema
+    multiproject = False
 
     def __init__(self, db, fs, msg, auth, ops):
         BaseTopic.__init__(self, db, fs, msg)
 
     def __init__(self, db, fs, msg, auth, ops):
         BaseTopic.__init__(self, db, fs, msg)
@@ -711,9 +751,15 @@ class RoleTopicAuth(BaseTopic):
         :param role_definitions: role definition to test
         :return: None if ok, raises ValidationError exception on error
         """
         :param role_definitions: role definition to test
         :return: None if ok, raises ValidationError exception on error
         """
+        ignore_fields = ["_id", "_admin", "name"]
         for role_def in role_definitions.keys():
         for role_def in role_definitions.keys():
-            if role_def == ".":
+            if role_def in ignore_fields:
                 continue
                 continue
+            if role_def == ".":
+                if isinstance(role_definitions[role_def], bool):
+                    continue
+                else:
+                    raise ValidationError("Operation authorization \".\" should be True/False.")
             if role_def[-1] == ".":
                 raise ValidationError("Operation cannot end with \".\"")
             
             if role_def[-1] == ".":
                 raise ValidationError("Operation cannot end with \".\"")
             
@@ -722,6 +768,9 @@ class RoleTopicAuth(BaseTopic):
             if len(role_def_matches) == 0:
                 raise ValidationError("No matching operation found.")
 
             if len(role_def_matches) == 0:
                 raise ValidationError("No matching operation found.")
 
+            if not isinstance(role_definitions[role_def], bool):
+                raise ValidationError("Operation authorization {} should be True/False.".format(role_def))
+
     def _validate_input_new(self, input, force=False):
         """
         Validates input user content for a new entry.
     def _validate_input_new(self, input, force=False):
         """
         Validates input user content for a new entry.
@@ -732,8 +781,8 @@ class RoleTopicAuth(BaseTopic):
         """
         if self.schema_new:
             validate_input(input, self.schema_new)
         """
         if self.schema_new:
             validate_input(input, self.schema_new)
-        if "definition" in input and input["definition"]:
-            self.validate_role_definition(self.operations, input["definition"])
+            self.validate_role_definition(self.operations, input)
+        
         return input
 
     def _validate_input_edit(self, input, force=False):
         return input
 
     def _validate_input_edit(self, input, force=False):
@@ -746,17 +795,16 @@ class RoleTopicAuth(BaseTopic):
         """
         if self.schema_edit:
             validate_input(input, self.schema_edit)
         """
         if self.schema_edit:
             validate_input(input, self.schema_edit)
-        if "definition" in input and input["definition"]:
-            self.validate_role_definition(self.operations, input["definition"])
+            self.validate_role_definition(self.operations, input)
+        
         return input
 
         return input
 
-    def check_conflict_on_new(self, session, indata, force=False):
+    def check_conflict_on_new(self, session, indata):
         """
         Check that the data to be inserted is valid
 
         """
         Check that the data to be inserted is valid
 
-        :param session: contains "username", if user is "admin" and the working "project_id"
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param indata: data to be inserted
         :param indata: data to be inserted
-        :param force: boolean. With force it is more tolerant
         :return: None or raises EngineException
         """
         role = indata.get("name")
         :return: None or raises EngineException
         """
         role = indata.get("name")
@@ -765,15 +813,14 @@ class RoleTopicAuth(BaseTopic):
         if role in role_list:
             raise EngineException("role '{}' exists".format(role), HTTPStatus.CONFLICT)
 
         if role in role_list:
             raise EngineException("role '{}' exists".format(role), HTTPStatus.CONFLICT)
 
-    def check_conflict_on_edit(self, session, final_content, edit_content, _id, force=False):
+    def check_conflict_on_edit(self, session, final_content, edit_content, _id):
         """
         Check that the data to be edited/uploaded is valid
 
         """
         Check that the data to be edited/uploaded is valid
 
-        :param session: contains "username", if user is "admin" and the working "project_id"
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param final_content: data once modified
         :param edit_content: incremental data that contains the modifications to apply
         :param _id: internal _id
         :param final_content: data once modified
         :param edit_content: incremental data that contains the modifications to apply
         :param _id: internal _id
-        :param force: boolean. With force it is more tolerant
         :return: None or raises EngineException
         """
         roles = self.auth.get_role_list()
         :return: None or raises EngineException
         """
         roles = self.auth.get_role_list()
@@ -783,13 +830,13 @@ class RoleTopicAuth(BaseTopic):
         if _id == system_admin_role["_id"]:
             raise EngineException("You cannot edit system_admin role", http_code=HTTPStatus.FORBIDDEN)
 
         if _id == system_admin_role["_id"]:
             raise EngineException("You cannot edit system_admin role", http_code=HTTPStatus.FORBIDDEN)
 
-    def check_conflict_on_del(self, session, _id, force=False):
+    def check_conflict_on_del(self, session, _id, db_content):
         """
         Check if deletion can be done because of dependencies if it is not force. To override
 
         """
         Check if deletion can be done because of dependencies if it is not force. To override
 
-        :param session: contains "username", if user is "admin" and the working "project_id"
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id: internal _id
         :param _id: internal _id
-        :param force: Avoid this checking
+        :param db_content: The database content of this item _id
         :return: None if ok or raises EngineException with the conflict
         """
         roles = self.auth.get_role_list()
         :return: None if ok or raises EngineException with the conflict
         """
         roles = self.auth.get_role_list()
@@ -815,19 +862,21 @@ class RoleTopicAuth(BaseTopic):
         if not content["_admin"].get("created"):
             content["_admin"]["created"] = now
         content["_admin"]["modified"] = now
         if not content["_admin"].get("created"):
             content["_admin"]["created"] = now
         content["_admin"]["modified"] = now
-        content["root"] = False
-
-        # Saving the role definition
-        if "definition" in content and content["definition"]:
-            for role_def, value in content["definition"].items():
-                if role_def == ".":
-                    content["root"] = value
-                else:
-                    content[role_def.replace(".", ":")] = value
+        
+        if "." in content.keys():
+            content["root"] = content["."]
+            del content["."]
+        
+        if "root" not in content.keys():
+            content["root"] = False
 
 
-        # Cleaning undesired values
-        if "definition" in content:
-            del content["definition"]
+        ignore_fields = ["_id", "_admin", "name"]
+        content_keys = content.keys()
+        for role_def in content_keys:
+            if role_def in ignore_fields:
+                continue
+            content[role_def.replace(".", ":")] = content[role_def]
+            del content[role_def]
 
     @staticmethod
     def format_on_edit(final_content, edit_content):
 
     @staticmethod
     def format_on_edit(final_content, edit_content):
@@ -847,14 +896,14 @@ class RoleTopicAuth(BaseTopic):
             del final_content[key]
 
         # Saving the role definition
             del final_content[key]
 
         # Saving the role definition
-        if "definition" in edit_content and edit_content["definition"]:
-            for role_def, value in edit_content["definition"].items():
-                if role_def == ".":
-                    final_content["root"] = value
-                else:
-                    final_content[role_def.replace(".", ":")] = value
-
-        if "root" not in final_content:
+        for role_def, value in edit_content.items():
+            final_content[role_def.replace(".", ":")] = value
+        
+        if ":" in final_content.keys():
+            final_content["root"] = final_content[":"]
+            del final_content[":"]
+        
+        if "root" not in final_content.keys():
             final_content["root"] = False
 
     @staticmethod
             final_content["root"] = False
 
     @staticmethod
@@ -866,31 +915,24 @@ class RoleTopicAuth(BaseTopic):
 
         :param definition: role definition to be processed
         """
 
         :param definition: role definition to be processed
         """
-        ignore_fields = ["_admin", "_id", "name", "root"]
         content_keys = list(content.keys())
         content_keys = list(content.keys())
-        definition = dict(content)
-        
+
+        content["_id"] = str(content["_id"])
+
         for key in content_keys:
         for key in content_keys:
-            if key in ignore_fields:
-                del definition[key]
-            if ":" not in key:
+            if ":" in key:
+                content[key.replace(":", ".")] = content[key]
                 del content[key]
                 del content[key]
-                continue
-            definition[key.replace(":", ".")] = definition[key]
-            del definition[key]
-            del content[key]
-        
-        content["definition"] = definition
 
     def show(self, session, _id):
         """
         Get complete information on an topic
 
 
     def show(self, session, _id):
         """
         Get complete information on an topic
 
-        :param session: contains the used login username and working project
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id: server internal id
         :return: dictionary, raise exception if not found.
         """
         :param _id: server internal id
         :return: dictionary, raise exception if not found.
         """
-        filter_db = self._get_project_filter(session, write=False, show_all=True)
+        filter_db = self._get_project_filter(session)
         filter_db["_id"] = _id
 
         role = self.db.get_one(self.topic, filter_db)
         filter_db["_id"] = _id
 
         role = self.db.get_one(self.topic, filter_db)
@@ -903,13 +945,24 @@ class RoleTopicAuth(BaseTopic):
         """
         Get a list of the topic that matches a filter
 
         """
         Get a list of the topic that matches a filter
 
-        :param session: contains the used login username and working project
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param filter_q: filter of data to be applied
         :return: The list, it can be empty if no one match the filter.
         """
         if not filter_q:
             filter_q = {}
 
         :param filter_q: filter of data to be applied
         :return: The list, it can be empty if no one match the filter.
         """
         if not filter_q:
             filter_q = {}
 
+        if "root" in filter_q:
+            filter_q[":"] = filter_q["root"]
+            del filter_q["root"]
+        
+        if len(filter_q) > 0:
+            keys = [key for key in filter_q.keys() if "." in key]
+
+            for key in keys:
+                filter_q[key.replace(".", ":")] = filter_q[key]
+                del filter_q[key]
+
         roles = self.db.get_list(self.topic, filter_q)
         new_roles = []
 
         roles = self.db.get_list(self.topic, filter_q)
         new_roles = []
 
@@ -920,17 +973,15 @@ class RoleTopicAuth(BaseTopic):
 
         return new_roles
 
 
         return new_roles
 
-    def new(self, rollback, session, indata=None, kwargs=None, headers=None, force=False, make_public=False):
+    def new(self, rollback, session, indata=None, kwargs=None, headers=None):
         """
         Creates a new entry into database.
 
         :param rollback: list to append created items at database in case a rollback may to be done
         """
         Creates a new entry into database.
 
         :param rollback: list to append created items at database in case a rollback may to be done
-        :param session: contains the used login username and working project
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param indata: data to be inserted
         :param kwargs: used to override the indata descriptor
         :param headers: http request headers
         :param indata: data to be inserted
         :param kwargs: used to override the indata descriptor
         :param headers: http request headers
-        :param force: If True avoid some dependence checks
-        :param make_public: Make the created item public to all projects
         :return: _id: identity of the inserted data.
         """
         try:
         :return: _id: identity of the inserted data.
         """
         try:
@@ -938,9 +989,9 @@ class RoleTopicAuth(BaseTopic):
 
             # Override descriptor with query string kwargs
             BaseTopic._update_input_with_kwargs(content, kwargs)
 
             # Override descriptor with query string kwargs
             BaseTopic._update_input_with_kwargs(content, kwargs)
-            content = self._validate_input_new(content, force)
-            self.check_conflict_on_new(session, content, force=force)
-            self.format_on_new(content, project_id=session["project_id"], make_public=make_public)
+            content = self._validate_input_new(content, session["force"])
+            self.check_conflict_on_new(session, content)
+            self.format_on_new(content, project_id=session["project_id"], make_public=session["public"])
             role_name = content["name"]
             role = self.auth.create_role(role_name)
             content["_id"] = role["_id"]
             role_name = content["name"]
             role = self.auth.create_role(role_name)
             content["_id"] = role["_id"]
@@ -951,18 +1002,17 @@ class RoleTopicAuth(BaseTopic):
         except ValidationError as e:
             raise EngineException(e, HTTPStatus.UNPROCESSABLE_ENTITY)
 
         except ValidationError as e:
             raise EngineException(e, HTTPStatus.UNPROCESSABLE_ENTITY)
 
-    def delete(self, session, _id, force=False, dry_run=False):
+    def delete(self, session, _id, dry_run=False):
         """
         Delete item by its internal _id
 
         """
         Delete item by its internal _id
 
-        :param session: contains the used login username, working project, and admin rights
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id: server internal id
         :param _id: server internal id
-        :param force: indicates if deletion must be forced in case of conflict
         :param dry_run: make checking but do not delete
         :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ...
         """
         :param dry_run: make checking but do not delete
         :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ...
         """
-        self.check_conflict_on_del(session, _id, force)
-        filter_q = self._get_project_filter(session, write=True, show_all=True)
+        self.check_conflict_on_del(session, _id, None)
+        filter_q = self._get_project_filter(session)
         filter_q["_id"] = _id
         if not dry_run:
             self.auth.delete_role(_id)
         filter_q["_id"] = _id
         if not dry_run:
             self.auth.delete_role(_id)
@@ -970,15 +1020,14 @@ class RoleTopicAuth(BaseTopic):
             return v
         return None
 
             return v
         return None
 
-    def edit(self, session, _id, indata=None, kwargs=None, force=False, content=None):
+    def edit(self, session, _id, indata=None, kwargs=None, content=None):
         """
         Updates a role entry.
 
         """
         Updates a role entry.
 
-        :param session: contains the used login username and working project
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
         :param _id:
         :param indata: data to be inserted
         :param kwargs: used to override the indata descriptor
         :param _id:
         :param indata: data to be inserted
         :param kwargs: used to override the indata descriptor
-        :param force: If True avoid some dependence checks
         :param content:
         :return: _id: identity of the inserted data.
         """
         :param content:
         :return: _id: identity of the inserted data.
         """
@@ -986,13 +1035,13 @@ class RoleTopicAuth(BaseTopic):
 
         # Override descriptor with query string kwargs
         if kwargs:
 
         # Override descriptor with query string kwargs
         if kwargs:
-            BaseTopic._update_input_with_kwargs(indata, kwargs)
+            self._update_input_with_kwargs(indata, kwargs)
         try:
         try:
-            indata = self._validate_input_edit(indata, force=force)
+            indata = self._validate_input_edit(indata, force=session["force"])
 
             if not content:
                 content = self.show(session, _id)
 
             if not content:
                 content = self.show(session, _id)
-            self.check_conflict_on_edit(session, content, indata, _id=_id, force=force)
+            self.check_conflict_on_edit(session, content, indata, _id=_id)
             self.format_on_edit(content, indata)
             self.db.replace(self.topic, _id, content)
             return id
             self.format_on_edit(content, indata)
             self.db.replace(self.topic, _id, content)
             return id