From 9cc35d52820e02dd77409b3808baa1c533d8d7fd Mon Sep 17 00:00:00 2001 From: Cristhian Garcia Date: Thu, 29 Jun 2023 08:57:30 -0500 Subject: [PATCH] feat: add support for extra rlsf --- README.rst | 15 ++++++++ tutoraspects/plugin.py | 1 + .../pythonpath/create_row_level_security.py | 37 ++++++++++++------- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/README.rst b/README.rst index 7e59139dc..112ec5bca 100644 --- a/README.rst +++ b/README.rst @@ -190,6 +190,21 @@ Available languages are stored in a mapping, and so best edited directly in Tuto Where the first key is the abbreviation of the language to use, "flag" is which flag icon is displayed in the user interface for choosing the language, and "name" is the displayed name for that language. The mapping above shows all of the current languages supported by Superset, but please note that different languages have different levels of completion and support at this time. +Adding custom Row Level Security Filters to Superset +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you want to apply custom row level security filters to Superset, you can do so by using the +setting SUPERSET_EXTRA_ROW_LEVEL_SECURITY_FILTERS in the config.yml file. This setting expects +a list of dictionaries with the following structure: + + SUPERSET_EXTRA_ROW_LEVEL_SECURITY_FILTERS: + - schema: "xapi" + table_name: "video_plays" + role_name: "Open edX" + group_key": "xapi_course_id" + clause": 'xapi_course_id = "{}"' + filter_type": RowLevelSecurityFilterType.REGULAR + License ------- diff --git a/tutoraspects/plugin.py b/tutoraspects/plugin.py index 1feda6a7c..4e63bc6a8 100644 --- a/tutoraspects/plugin.py +++ b/tutoraspects/plugin.py @@ -173,6 +173,7 @@ "es": {"flag": "es", "name": "Spanish"}, }, ), + ("SUPERSET_EXTRA_ROW_LEVEL_SECURITY_FILTERS", []), ###################### # dbt Settings # For the most part you shouldn't have to touch these diff --git a/tutoraspects/templates/aspects/apps/superset/pythonpath/create_row_level_security.py b/tutoraspects/templates/aspects/apps/superset/pythonpath/create_row_level_security.py index 406940d7b..81287e9d0 100644 --- a/tutoraspects/templates/aspects/apps/superset/pythonpath/create_row_level_security.py +++ b/tutoraspects/templates/aspects/apps/superset/pythonpath/create_row_level_security.py @@ -11,22 +11,27 @@ session = security_manager.get_session() -# Fetch the Open edX role -role_name = "{{SUPERSET_OPENEDX_ROLE_NAME}}" -openedx_role = session.query(Role).filter(Role.name == role_name).first() -assert openedx_role, "{{SUPERSET_OPENEDX_ROLE_NAME}} role doesn't exist yet?" - -for (schema, table_name, group_key, clause, filter_type) in ( +row_level_security_filters = [ ( "{{ASPECTS_XAPI_DATABASE}}", "{{ASPECTS_XAPI_TABLE}}", + "{{SUPERSET_OPENEDX_ROLE_NAME}}", "{{SUPERSET_ROW_LEVEL_SECURITY_XAPI_GROUP_KEY}}", - {% raw %} - '{{can_view_courses(current_username(), "splitByChar(\'/\', course_id)[-1]")}}', - {% endraw %} + {% raw %}'{{can_view_courses(current_username(), "splitByChar(\'/\', course_id)[-1]")}}',{% endraw %} RowLevelSecurityFilterType.REGULAR, ), -): + {% for row_level_security_filter in SUPERSET_EXTRA_ROW_LEVEL_SECURITY_FILTERS %}( + "{{row_level_security_filter.schema}}", + "{{row_level_security_filter.table_name}}", + "{{row_level_security_filter.role_name}}", + "{{row_level_security_filter.group_key}}", + '{{row_level_security_filter.clause}}', + {{row_level_security_filter.filter_type}}, + ),{% endfor %} +] + + +for (schema, table_name, role_name, group_key, clause, filter_type) in row_level_security_filters: # Fetch the table we want to restrict access to table = session.query(SqlaTable).filter( SqlaTable.schema == schema @@ -35,14 +40,19 @@ ).first() print(table) assert table, f"{schema}.{table_name} table doesn't exist yet?" + + role = session.query(Role).filter(Role.name == role_name).first() + assert role, f"{role_name} role doesn't exist yet?" # See if the Row Level Security Filter already exists rlsf = ( session.query( RowLevelSecurityFilter ).filter( - RLSFilterRoles.c.role_id.in_((openedx_role.id,)) + RLSFilterRoles.c.role_id.in_((role.id,)) ).filter( RowLevelSecurityFilter.group_key == group_key + ).filter( + RowLevelSecurityFilter.tables.any(id=table.id) ) ).first() # If it doesn't already exist, create one @@ -66,15 +76,16 @@ session.query( RLSFilterRoles ).filter( - RLSFilterRoles.c.role_id == openedx_role.id + RLSFilterRoles.c.role_id == role.id ).filter( RLSFilterRoles.c.rls_filter_id == rlsf.id ) ) + print(rls_filter_roles) if not rls_filter_roles.count(): session.execute(RLSFilterRoles.insert(), [ dict( - role_id=openedx_role.id, + role_id=role.id, rls_filter_id=rlsf.id ) ])