Ver Fonte

HUE-8758 [useradmin] Sync permissions when updating connectors

Romain há 5 anos atrás
pai
commit
82af732bdf

+ 37 - 34
apps/useradmin/src/useradmin/models.py

@@ -18,15 +18,13 @@
 The core of this module adds permissions functionality to Hue applications.
 
 A "Hue Permission" (colloquially, appname.action, but stored in the HuePermission model) is a way to specify some action whose
-control may be restricted.  Every Hue application, by default, has an "access" action. To specify extra actions, applications
+control may be restricted. Every Hue application, by default, has an "access" action. To specify extra actions, applications
 can specify them in appname.settings.PERMISSION_ACTIONS, as pairs of (action_name, description).
 
-Several mechanisms enforce permission.  First of all, the "access" permission
-is controlled by LoginAndPermissionMiddleware.  For eligible views
-within an application, the access permission is checked.  Second,
-views may use @desktop.decorators.hue_permission_required("action", "app")
-to annotate their function, and this decorator will check a permission.
-Thirdly, you may wish to do so manually, by using something akin to:
+Several mechanisms enforce permission. First of all, the "access" permission
+is controlled by LoginAndPermissionMiddleware. For eligible views within an application, the access permission is checked. Second,
+views may use @desktop.decorators.hue_permission_required("action", "app") to annotate their function, and this decorator will
+check a permission. Thirdly, you may wish to do so manually, by using something akin to:
 
   app = desktop.lib.apputil.get_current_app() # a string
   dp = HuePermission.objects.get(app=pp, action=action)
@@ -36,11 +34,13 @@ Permissions may be granted to groups, but not, currently, to users. A user's abi
 has access to.
 
 Note that Django itself has a notion of users, groups, and permissions. We re-use Django's notion of users and groups, but ignore its notion of
-permissions.  The permissions notion in Django is strongly tied to what models you may or may not edit, and there are elaborations (especially
+permissions. The permissions notion in Django is strongly tied to what models you may or may not edit, and there are elaborations (especially
 in Django 1.2) to manipulate this row by row. This does not map nicely onto actions which may not relate to database models.
 """
+import collections
 import json
 import logging
+
 from datetime import datetime
 from enum import Enum
 
@@ -57,9 +57,8 @@ from desktop.lib.connectors.models import _get_installed_connectors
 from desktop.lib.exceptions_renderable import PopupException
 from desktop.lib.idbroker.conf import is_idbroker_enabled
 from desktop.monkey_patches import monkey_patch_username_validator
-from hadoop import cluster
 
-import useradmin.conf
+from useradmin.conf import DEFAULT_USER_GROUP
 
 
 if ENABLE_ORGANIZATIONS.get():
@@ -214,7 +213,7 @@ class HuePermission(models.Model):
 
 
 def get_default_user_group(**kwargs):
-  default_user_group = useradmin.conf.DEFAULT_USER_GROUP.get()
+  default_user_group = DEFAULT_USER_GROUP.get()
   if default_user_group is None:
     return None
 
@@ -231,25 +230,24 @@ def get_default_user_group(**kwargs):
 
 def update_app_permissions(**kwargs):
   """
-  Inserts missing permissions into the database table.
-  This is a 'syncdb' callback.
+  Keep in sync apps and connectors permissions into the database table.
+  Map app + action to a HuePermission.
+
+  v2
+  Based on the connectors.
+  Permissions are either based on connectors instances or Hue specific actions.
+  Permissions can be deleted or added dynamically.
+
+  v1
+  This is a 'migrate' callback.
 
   We never delete permissions automatically, because apps might come and go.
 
-  Note that signing up to the "syncdb" signal is not necessarily
-  the best thing we can do, since some apps might not
-  have models, but nonetheless, "syncdb" is typically
-  run when apps are installed.
+  Note that signing up to the "migrate" signal is not necessarily the best thing we can do, since some apps might not
+  have models, but nonetheless, "syncdb" is typically run when apps are installed.
   """
-  # Map app->action->HuePermission.
-
-  # The HuePermission model needs to be sync'd for the following code to work
-  # The point of 'if u'useradmin_huepermission' in connection.introspection.table_names():'
-  # is to check if Useradmin has been installed.
-  # It is okay to follow appmanager.DESKTOP_APPS before they've been sync'd
-  # because apps are referenced by app name in Hue permission and not by model ID.
   created_tables = connection.introspection.table_names()
-  if u'useradmin_huepermission' in created_tables:
+  if u'useradmin_huepermission' in created_tables:  # Check if Useradmin has been installed.
     current = {}
 
     try:
@@ -264,23 +262,25 @@ def update_app_permissions(**kwargs):
     added = []
 
     if ENABLE_CONNECTORS.get():
-      import collections
+      previous_apps = list(current.keys())
       ConnectorPerm = collections.namedtuple('ConnectorPerm', 'name settings')
       apps = [
         ConnectorPerm(name=connector['name'], settings=[]) for connector in _get_installed_connectors()
       ]
     else:
+      previous_apps = []
       apps = appmanager.DESKTOP_APPS
 
     for app_obj in apps:
-      print(app_obj)
       app = app_obj.name
       actions = set([("access", "Launch this application")])
       actions.update(getattr(app_obj.settings, "PERMISSION_ACTIONS", []))
 
-      if app not in current:
+      if app in current:
+        previous_apps.remove(app)
+      else:
         current[app] = {}
-      print(current)
+
       for action, description in actions:
         c = current[app].get(action)
         if c:
@@ -294,9 +294,10 @@ def update_app_permissions(**kwargs):
           new_dp = HuePermission(app=app, action=action, description=description)
           new_dp.save()
           added.append(new_dp)
-        print('%s %s %s' % (updated, uptodate, added))
 
-    # Add all permissions to default group.
+    deleted, _ = HuePermission.objects.filter(app__in=previous_apps).delete()
+
+    # Add all permissions to default group except some.
     default_group = get_default_user_group()
     if default_group:
       for new_dp in added:
@@ -315,9 +316,9 @@ def update_app_permissions(**kwargs):
     available = HuePermission.objects.count()
     stale = available - len(added) - updated - uptodate
 
-    if len(added) or updated or stale:
-      LOG.info("HuePermissions: %d added, %d updated, %d up to date, %d stale" % (
-          len(added), updated, uptodate, stale
+    if len(added) or updated or stale or deleted:
+      LOG.info("HuePermissions: %d added, %d updated, %d up to date, %d stale, %d deleted" % (
+          len(added), updated, uptodate, stale, deleted
         )
       )
 
@@ -332,6 +333,8 @@ def install_sample_user():
   """
   #Moved to avoid circular import with is_admin
   from desktop.models import SAMPLE_USER_ID, SAMPLE_USER_INSTALL
+  from hadoop import cluster
+
   user = None
 
   try:

+ 5 - 5
apps/useradmin/src/useradmin/templates/list_permissions.mako

@@ -52,19 +52,19 @@ from useradmin.models import group_permissions, Group
           <tr class="tableRow"
               data-search="${perm.app}${perm.description}${', '.join([group.name for group in Group.objects.filter(grouppermission__hue_permission=perm).order_by('name')])}">
           <td>
-            %if is_admin(user):
+            % if is_admin(user):
               <strong>
                 <a title="${_('Edit permission')}"
                     href="${ url('useradmin.views.edit_permission', app=perm.app, priv=perm.action) }"
-                    data-name="${perm.app}" data-row-selector="true">${ perm.app }
+                    data-name="${ perm.app }" data-row-selector="true">${ perm.app }
                 </a>
               </strong>
-            %else:
+            % else:
               <strong>${ perm.app }</strong>
-            %endif
+            % endif
           </td>
             <td>${ perm.description }</td>
-            <td>${', '.join([group.name for group in Group.objects.filter(grouppermission__hue_permission=perm).order_by('name')])}</td>
+            <td>${', '.join([group.name for group in Group.objects.filter(grouppermission__hue_permission=perm).order_by('name')]) }</td>
           </tr>
           % endfor
       </tbody>