Преглед изворни кода

HUE-8530 [organization] Add the notion of organization admin

Romain пре 5 година
родитељ
комит
92d7327f68

+ 19 - 13
apps/useradmin/src/useradmin/models2.py

@@ -20,6 +20,8 @@ import logging
 from django.contrib.auth.models import models, AbstractUser, BaseUserManager
 from django.utils.translation import ugettext_lazy as _t
 
+from desktop.models import uuid_default
+
 
 LOG = logging.getLogger(__name__)
 
@@ -36,6 +38,8 @@ class OrganizationManager(models.Manager):
 
 class Organization(models.Model):
   name = models.CharField(max_length=200, help_text=_t("The name of the organization"))
+  uuid = models.CharField(default=uuid_default, max_length=36, db_index=True)
+  domain = models.CharField(max_length=200, help_text=_t("The domain name of the organization, e.g. gethue.com"))
   is_active = models.BooleanField(default=True)
 
   objects = OrganizationManager()
@@ -89,17 +93,21 @@ class UserManager(BaseUserManager):
       """Create and save a regular User with the given email and password."""
       extra_fields.setdefault('is_staff', False)
       extra_fields.setdefault('is_superuser', False)
+      extra_fields.setdefault('is_admin', False)
       return self._create_user(email, password, **extra_fields)
 
   def create_superuser(self, email, password, **extra_fields):
       """Create and save a SuperUser with the given email and password."""
-      extra_fields.setdefault('is_staff', True)
-      extra_fields.setdefault('is_superuser', True)
+      extra_fields.setdefault('is_staff', False)
+      extra_fields.setdefault('is_superuser', False)
+      extra_fields.setdefault('is_admin', True)
 
-      if extra_fields.get('is_staff') is not True:
-          raise ValueError('Superuser must have is_staff=True.')
-      if extra_fields.get('is_superuser') is not True:
-          raise ValueError('Superuser must have is_superuser=True.')
+      if extra_fields.get('is_staff') is not False:
+          raise ValueError('Organization superuser must have is_staff=False.')
+      if extra_fields.get('is_superuser') is not False:
+          raise ValueError('Organization superuser must have is_superuser=False.')
+      if extra_fields.get('is_admin') is not True:
+          raise ValueError('Organization superuser must have is_admin=False.')
 
       return self._create_user(email, password, **extra_fields)
 
@@ -108,17 +116,15 @@ def default_organization():
   return default_organization
 
 class OrganizationUser(AbstractUser):
-    """User model."""
+    """User model in a multi tenant setup."""
 
     username = None
-    email = models.EmailField(_t('email address'), unique=True)
-    token = models.CharField(_t('token'), max_length=128, default=None, null=True)
+    email = models.EmailField(_t('Email address'), unique=True)
+    token = models.CharField(_t('Token'), max_length=128, default=None, null=True)
     customer_id = models.CharField(_t('Customer id'), max_length=128, default=None, null=True)
     organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
-    # settings = json
-    #   connector_whitelist
-    #   connector_blacklist
-    #   auths: login/password, Google SSO, SAML, LDAP, Github
+    is_admin = models.BooleanField(default=False)
+    # settings are in UserProfile
 
     groups = models.ManyToManyField(
         OrganizationGroup,

+ 5 - 1
desktop/core/src/desktop/auth/backend.py

@@ -106,7 +106,7 @@ def is_admin(user):
   is_admin = False
   if hasattr(user, 'is_superuser'):
     is_admin = user.is_superuser
-  if not is_admin and user.is_authenticated():
+  if not is_admin and user.is_authenticated() and not ENABLE_ORGANIZATIONS.get():  # Admin group only within an organization if later is enabled
     try:
       user = rewrite_user(user)
       is_admin = user.has_hue_permission(action="superuser", app="useradmin")
@@ -115,6 +115,10 @@ def is_admin(user):
   return is_admin
 
 
+def is_organization_admin(user):
+  return hasattr(user, 'is_admin') and user.is_admin
+
+
 class DefaultUserAugmentor(object):
   def __init__(self, parent):
     self._parent = parent

+ 1 - 1
desktop/core/src/desktop/js/ko/components/ko.sidebar.js

@@ -71,7 +71,7 @@ const TEMPLATE = `
               }
             ">${I18n('My Profile')}</a></li>
           <!-- /ko -->
-          <!-- ko if: window.USER_IS_ADMIN -->
+          <!-- ko if: window.USER_IS_ADMIN || window.USER_IS_ORG_ADMIN -->
           <li><a href="javascript: void(0);" data-bind="hueLink: '/useradmin/users/'">${I18n(
             'Manage Users'
           )}</a></li>

+ 10 - 6
desktop/core/src/desktop/templates/about_layout.mako

@@ -17,7 +17,7 @@
 <%!
 from django.utils.translation import ugettext as _
 
-from desktop.auth.backend import is_admin
+from desktop.auth.backend import is_admin, is_organization_admin
 from desktop.conf import METRICS, has_connectors, ANALYTICS
 
 def is_selected(section, matcher):
@@ -35,22 +35,26 @@ def is_selected(section, matcher):
             <ul class="nav">
               <li class="app-header">
                 <a href="${ url('about:admin_wizard') }">
-                  <img src="${ static('desktop/art/icon_hue_48.png') }" class="app-icon"  alt="${ _('Hue icon') }"/>
+                  <img src="${ static('desktop/art/icon_hue_48.png') }" class="app-icon" alt="${ _('Hue icon') }"/>
                   ${ _('About Hue') }
                 </a>
-               </li>
-              % if is_admin(user):
+              </li>
+              % if is_admin(user) or is_organization_admin(user):
                 <li class="${is_selected(section, 'quick_start')}">
                   <a href="${ url('about:admin_wizard') }">${_('Quick start')}</a>
                 </li>
+              % endif
+              % if is_admin(user):
                 <li class="${is_selected(section, 'dump_config')}">
                   <a href="${ url('desktop.views.dump_config') }">${_('Configuration')}</a>
                 </li>
-                % if has_connectors():
+              % endif
+              % if has_connectors() and (is_admin(user) or is_organization_admin(user)):
                 <li class="${is_selected(section, 'connectors')}">
                   <a href="${ url('desktop.lib.connectors.views.index') }">${_('Connectors')}</a>
                 </li>
-                % endif
+              % endif
+              % if is_admin(user):
                 % if ANALYTICS.IS_ENABLED.get():
                 <li class="${is_selected(section, 'analytics')}">
                   <a href="${ url('desktop.lib.analytics.views.index') }">${_('Analytics')}</a>

+ 5 - 5
desktop/core/src/desktop/templates/dump_config.mako

@@ -132,7 +132,7 @@ LOG = logging.getLogger(__name__)
             <td>
          % endif
           % if isinstance(config_obj, BoundContainer):
-            %if config_obj.config.help or len(config_obj.get().values()) == 0:
+            % if config_obj.config.help or not config_obj.get().values():
             <i>${ config_obj.config.help or _('No help available.') }</i>
             % endif
             ${ recurseList(config_obj.get().values(), depth + 1) }
@@ -150,13 +150,13 @@ LOG = logging.getLogger(__name__)
                 except:
                   LOG.exception("Potential misconfiguration. Error value of key '%s' in configuration." % config_obj.grab_key)
               %>
-              %if config_str == '':
+              % if config_str == '':
               &nbsp;
-              %endif
+              % endif
             </code><br/>
-              %if config_obj.config.help:
+              % if config_obj.config.help:
                 <i>${ config_obj.config.help or _('No help available.') }</i>
-              %endif
+              % endif
             <span class="muted">${ _('Default:') } <i>${ config_obj.config.default if sys.version_info[0] > 2 else str(config_obj.config.default).decode('utf-8', 'replace') }</i></span>
           % endif
           </td>

+ 2 - 1
desktop/core/src/desktop/templates/global_js_constants.mako

@@ -18,7 +18,7 @@
   from django.utils.translation import ugettext as _
 
   from desktop import conf
-  from desktop.auth.backend import is_admin
+  from desktop.auth.backend import is_admin, is_organization_admin
   from desktop.conf import APP_SWITCHER_ALTUS_BASE_URL, APP_SWITCHER_MOW_BASE_URL, DISPLAY_APP_SWITCHER, IS_K8S_ONLY, IS_MULTICLUSTER_ONLY, \
       USE_DEFAULT_CONFIGURATION, USE_NEW_SIDE_PANELS, VCS, ENABLE_GIST, ENABLE_LINK_SHARING
   from desktop.models import hue_version, _get_apps, get_cluster_config
@@ -640,6 +640,7 @@
 
   window.USER_VIEW_EDIT_USER_ENABLED = '${ user.has_hue_permission(action="access_view:useradmin:edit_user", app="useradmin") or is_admin(user) }' === 'True';
   window.USER_IS_ADMIN = '${ is_admin(user) }' === 'True';
+  window.USER_IS_ORG_ADMIN = '${ is_organization_admin(user) }' === 'True';
   window.DJANGO_DEBUG_MODE = '${ conf.DJANGO_DEBUG_MODE.get() }' === 'True';
   window.IS_LDAP_SETUP = '${ 'desktop.auth.backend.LdapBackend' in conf.AUTH.BACKEND.get() }' === 'True';
   window.LOGGED_USERNAME = '${ user.username }';