changeset 64:5f21f8d3334b

Only users who have the personas.can_publish permission or who own a persona can edit them now; added more workflow logic. I'm not entirely happy with the way the workflow logic is structured right now, but this seems to work okay for the time being.
author Atul Varma <varmaa@toolness.com>
date Tue, 11 Mar 2008 14:15:43 -0500
parents ec4f7cbb1ae2
children f54ea1612d1e
files PersonasBackend/personas/forms.py PersonasBackend/personas/models.py PersonasBackend/personas/templates/personas/list.html PersonasBackend/personas/views.py
diffstat 4 files changed, 85 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/PersonasBackend/personas/forms.py	Tue Mar 11 11:40:00 2008 -0500
+++ b/PersonasBackend/personas/forms.py	Tue Mar 11 14:15:43 2008 -0500
@@ -1,7 +1,22 @@
 from django.newforms import ModelForm
 from PersonasBackend.personas import models
 
-class PersonaForm( ModelForm ):
+class StandardPersonaForm( ModelForm ):
+    """
+    Form given to normal users who don't have the permission to
+    publish Personas.
+    """
+
     class Meta:
         model = models.Persona
         exclude = ["owner", "status", "updater"]
+
+class PublisherPersonaForm( ModelForm ):
+    """
+    Form given to admin/staff users who have the permission to publish
+    Personas.
+    """
+
+    class Meta:
+        model = models.Persona
+        exclude = ["updater"]
--- a/PersonasBackend/personas/models.py	Tue Mar 11 11:40:00 2008 -0500
+++ b/PersonasBackend/personas/models.py	Tue Mar 11 14:15:43 2008 -0500
@@ -122,6 +122,11 @@
     class Admin:
         pass
 
+    class Meta:
+        permissions = (
+            ("can_publish", "Can publish"),
+            )
+
     MAX_NAME_LENGTH = 50
 
     name = models.CharField(
@@ -218,6 +223,8 @@
         User,
         help_text="The user who made this revision.",
         related_name="changed_personas",
+        # TODO: Consider making this null=False.  Keeping it true
+        # makes it easier to write tests, though.
         null=True,
         )
 
@@ -237,7 +244,6 @@
                  ("unpublished", "Unpublished"),
                  ("deleted", "Deleted")),
         blank=False,
-        default="unpublished",
         help_text=("Status of the Persona; can be deleted, published, "
                    "or unpublished (i.e., pending for review).")
         )
@@ -344,20 +350,53 @@
         """
 
         if self.id == None:
+            # We're a brand-new Persona.
             self.revision = 0
+            if not self.owner:
+                self.owner = self.updater
+            assert self.owner == self.updater
+            if ( not self.status ) and self.updater:
+                if self.updater.has_perm( "personas.can_publish" ):
+                    # If the person creating the Persona can publish
+                    # Personas, mark this new Persona as published, by
+                    # default.
+                    self.status = "published"
+                else:
+                    # Otherwise, mark this new Persona as unpublished by
+                    # default.
+                    self.status = "unpublished"
         else:
-            # TODO: See who made the update; depending on how much we
-            # trust them, this may mean:
-            #
-            #   * rejecting the change, 
-            #   * accepting the changes but marking the persona's
-            #     status as "unpublished",
-            #   * accepting the changes.
+            # We're an existing Persona that's being modified.
+
+            if self.updater:
+                if not self.can_user_edit( self.updater ):
+                    # The user can't actually edit this Persona, reject
+                    # the change.  View logic should've prevented this
+                    # from ever being the case, so we're going to be
+                    # ungraceful here.
+                    raise AssertionError( "User can't edit this persona." )
+
+                if ( self.status == "published" and
+                     not self.updater.has_perm( "personas.can_publish" ) ):
+                    # The Persona is currently published, but a user
+                    # without publishing permissions has just changed it,
+                    # so mark it as unpublished so an editor can review it
+                    # before re-publishing it.
+
+                    self.status = "unpublished"
 
             self.__make_new_revision()
 
         super(Persona, self).save()
 
+    def can_user_edit( self, user ):
+        """
+        Returns whether the given User can edit this Persona.
+        """
+
+        return ( user.has_perm( "personas.can_publish" ) or
+                 self.owner == user )
+
 class Revision(models.Model):
     """
     Represents an old revision of a Persona.
--- a/PersonasBackend/personas/templates/personas/list.html	Tue Mar 11 11:40:00 2008 -0500
+++ b/PersonasBackend/personas/templates/personas/list.html	Tue Mar 11 14:15:43 2008 -0500
@@ -7,6 +7,13 @@
 <div class="addon-listitem clearfix-right corner-box">
   <h2 class="addonname">{{ persona.name }}</h2>
   <div class="addon-desc">{{ persona.description }}</div>
+  {% ifequal persona.owner user %}
+  <a href="{% url edit-persona persona.id %}">Edit</a>
+  {% else %}
+  {% if perms.personas.can_publish %}
+  <a href="{% url edit-persona persona.id %}">Edit</a>
+  {% endif %}
+  {% endifequal %}
 </div>
 {% endfor %}
 {% else %}
--- a/PersonasBackend/personas/views.py	Tue Mar 11 11:40:00 2008 -0500
+++ b/PersonasBackend/personas/views.py	Tue Mar 11 14:15:43 2008 -0500
@@ -1,4 +1,4 @@
-from django.http import HttpResponseRedirect
+from django.http import HttpResponseRedirect, HttpResponseForbidden
 from django.template import RequestContext
 from django.contrib.auth.decorators import login_required
 from django.core.urlresolvers import reverse
@@ -68,34 +68,41 @@
 
 @login_required
 def edit_view( request, persona_id=None ):
-    # TODO: Perform permissions check to see if user has
-    # the rights to edit the persona or create a new one.
     if persona_id is None:
         persona = None
         pageTitle = "Create a new Persona"
     else:
         persona = get_object_or_404( models.Persona, id=persona_id )
+        if not persona.can_user_edit( request.user ):
+            return HttpResponseForbidden(
+                "<h1>You do not have permission to edit "
+                "this Persona.</h1>"
+                )
         pageTitle = "Edit Persona"
 
+    if request.user.has_perm( "personas.can_publish" ):
+        PersonaForm = forms.PublisherPersonaForm
+    else:
+        PersonaForm = forms.StandardPersonaForm
+
     if request.method == "POST":
         for img_name in request.FILES:
             _rename_file( request.FILES[img_name], persona )
-        form = forms.PersonaForm( request.POST, request.FILES,
-                                  instance=persona )
+        form = PersonaForm( request.POST, request.FILES,
+                            instance=persona )
         if form.is_valid():
             newPersona = form.save( commit=False )
             newPersona.updater = request.user
+            newPersona.save()
             if persona is None:
                 msgText = "Persona created successfully."
-                newPersona.owner = request.user
             else:
                 msgText = "Persona edited successfully."
-            newPersona.save()
             request.user.message_set.create( message = msgText )
             url = reverse("edit-persona", args=[newPersona.id])
             return HttpResponseRedirect( url )
     else:
-        form = forms.PersonaForm( instance=persona )
+        form = PersonaForm( instance=persona )
 
     return render_to_response(
         "personas/edit.html",