introduce Controller model
[plstackapi.git] / planetstack / core / models / user.py
index 9b54da9..42ea652 100644 (file)
@@ -4,7 +4,6 @@ from collections import defaultdict
 from django.db import models
 from django.db.models import F, Q
 from core.models import PlCoreBase,Site, DashboardView, DiffModelMixIn
-from core.models.site import Deployment
 from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
 from timezones.fields import TimeZoneField
 from operator import itemgetter, attrgetter
@@ -13,6 +12,20 @@ from core.middleware import get_request
 import model_policy
 from django.core.exceptions import PermissionDenied
 
+# ------ from plcorebase.py ------
+try:
+    # This is a no-op if observer_disabled is set to 1 in the config file
+    from observer import *
+except:
+    print >> sys.stderr, "import of observer failed! printing traceback and disabling observer:"
+    import traceback
+    traceback.print_exc()
+
+    # guard against something failing
+    def notify_observer(*args, **kwargs):
+        pass
+# ------ ------
+
 # Create your models here.
 class UserManager(BaseUserManager):
     def create_user(self, email, firstname, lastname, password=None):
@@ -48,6 +61,17 @@ class UserManager(BaseUserManager):
         user.save(using=self._db)
         return user
 
+    def get_queryset(self):
+        parent=super(UserManager, self)
+        if hasattr(parent, "get_queryset"):
+            return parent.get_queryset().filter(deleted=False)
+        else:
+            return parent.get_query_set().filter(deleted=False)
+
+    # deprecated in django 1.7 in favor of get_queryset().
+    def get_query_set(self):
+        return self.get_queryset()
+
 class DeletedUserManager(UserManager):
     def get_queryset(self):
         return super(UserManager, self).get_query_set().filter(deleted=True)
@@ -100,6 +124,9 @@ class User(AbstractBaseUser, DiffModelMixIn):
     USERNAME_FIELD = 'email'
     REQUIRED_FIELDS = ['firstname', 'lastname']
 
+    PI_FORBIDDEN_FIELDS = ["is_admin", "site", "is_staff"]
+    USER_FORBIDDEN_FIELDS = ["is_admin", "is_active", "site", "is_staff", "is_readonly"]
+
     def __init__(self, *args, **kwargs):
         super(User, self).__init__(*args, **kwargs)
         self._initial = self._dict # for DiffModelMixIn
@@ -118,6 +145,8 @@ class User(AbstractBaseUser, DiffModelMixIn):
     def delete(self, *args, **kwds):
         # so we have something to give the observer
         purge = kwds.get('purge',False)
+        if purge:
+            del kwds['purge']
         try:
             purge = purge or observer_disabled
         except NameError:
@@ -153,7 +182,7 @@ class User(AbstractBaseUser, DiffModelMixIn):
     def get_dashboards(self):
         DEFAULT_DASHBOARDS=["Tenant"]
 
-        dashboards = sorted(list(self.dashboardViews.all()), key=attrgetter('order'))
+        dashboards = sorted(list(self.userdashboardviews.all()), key=attrgetter('order'))
         dashboards = [x.dashboardView for x in dashboards]
 
         if not dashboards:
@@ -200,38 +229,28 @@ class User(AbstractBaseUser, DiffModelMixIn):
         msg.attach_alternative(html_content, "text/html")\r
         msg.send()
 
-    def can_update_field(self, user, fieldName):
-        from core.models import SitePrivilege
-        if (user.is_admin):
-            # admin can update anything
-            return True
-
-        # fields that a site PI can update
-        if fieldName in ["is_active", "is_readonly"]:
-            site_privs = SitePrivilege.objects.filter(user=user, site=self.site)
-            for site_priv in site_privs:
-                if site_priv.role.role == 'pi':
-                    return True
-
-        # fields that a user cannot update in his/her own record
-        if fieldName in ["is_admin", "is_active", "site", "is_staff", "is_readonly"]:
-            return False
-
-        return True
-
     def can_update(self, user):
         from core.models import SitePrivilege
+        _cant_update_fieldName = None
         if user.is_readonly:
             return False
         if user.is_admin:
             return True
-        if (user.id == self.id):
-            return True
         # site pis can update
         site_privs = SitePrivilege.objects.filter(user=user, site=self.site)
         for site_priv in site_privs:
             if site_priv.role.role == 'pi':
+                for fieldName in self.diff.keys():
+                    if fieldName in self.PI_FORBIDDEN_FIELDS:
+                        _cant_update_fieldName = fieldName
+                        return False
                 return True
+        if (user.id == self.id):
+            for fieldName in self.diff.keys():
+                if fieldName in self.USER_FORBIDDEN_FIELDS:
+                    _cant_update_fieldName = fieldName
+                    return False
+            return True
 
         return False
 
@@ -252,11 +271,10 @@ class User(AbstractBaseUser, DiffModelMixIn):
 
     def save_by_user(self, user, *args, **kwds):
         if not self.can_update(user):
-            raise PermissionDenied("You do not have permission to update %s objects" % self.__class__.__name__)
-
-        for fieldName in self.changed_fields:
-            if not self.can_update_field(user, fieldName):
-                raise PermissionDenied("You do not have permission to update field %s in object %s" % (fieldName, self.__class__.__name__))
+            if getattr(self, "_cant_update_fieldName", None) is not None:
+                raise PermissionDenied("You do not have permission to update field %s on object %s" % (self._cant_update_fieldName, self.__class__.__name__))
+            else:
+                raise PermissionDenied("You do not have permission to update %s objects" % self.__class__.__name__)
 
         self.save(*args, **kwds)
 
@@ -266,6 +284,6 @@ class User(AbstractBaseUser, DiffModelMixIn):
         self.delete(*args, **kwds)
 
 class UserDashboardView(PlCoreBase):
-     user = models.ForeignKey(User, related_name="dashboardViews")
-     dashboardView = models.ForeignKey(DashboardView, related_name="dashboardViews")
+     user = models.ForeignKey(User, related_name='userdashboardviews')
+     dashboardView = models.ForeignKey(DashboardView, related_name='userdashboardviews')
      order = models.IntegerField(default=0)