<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -5,6 +5,7 @@ This module defines wrapper functions around the permission framework.
 from cms.models import *
 from django.db import models
 from django.db.models import Q
+from django.conf import settings
 
 ###############################################################################
 # Helper functions
@@ -100,8 +101,10 @@ class PermissionCache(object):
         &quot;&quot;&quot;
         Return a set of global abilities the agent has.
         &quot;&quot;&quot;
+        if not settings.ENABLE_PERMISSION_CHECKING:
+            return all_possible_global_abilities()
         if self._global_ability_cache is None:
-            abilities_yes, abilities_no = self.calculate_abilities(None, None)
+            abilities_yes, abilities_no = self._calculate_abilities(None, None)
             self._global_ability_cache = (abilities_yes, abilities_no)
         else:
             abilities_yes, abilities_no = self._global_ability_cache
@@ -113,9 +116,11 @@ class PermissionCache(object):
         &quot;&quot;&quot;
         if item.destroyed:
             return frozenset()
+        item_type = item.actual_item_type()
+        if not settings.ENABLE_PERMISSION_CHECKING:
+            return all_possible_item_abilities(item_type)
         result = self._item_ability_cache.get(item.pk)
         if result is None:
-            item_type = item.actual_item_type()
             self.global_abilities() # cache the global abilities
             global_abilities_yes, global_abilities_no = self._global_ability_cache
             if 'do_anything' in global_abilities_yes:
@@ -125,7 +130,7 @@ class PermissionCache(object):
                 abilities_yes = frozenset()
                 abilities_no = all_possible_item_abilities(item_type)
             else:
-                abilities_yes, abilities_no = self.calculate_abilities(item, item_type)
+                abilities_yes, abilities_no = self._calculate_abilities(item, item_type)
             self._item_ability_cache[item.pk] = (abilities_yes, abilities_no)
         else:
             abilities_yes, abilities_no = result
@@ -136,7 +141,7 @@ class PermissionCache(object):
         Returns a QuerySet that filters the given QuerySet, into only the items
         that the specified agent has the specified ability to do.
         
-        Unlike filter_items_by_permission, this takes into account the fact that
+        Unlike _filter_items_by_permission, this takes into account the fact that
         agents with the global ability &quot;do_anything&quot; virtually have all item
         abilities.
         
@@ -145,6 +150,8 @@ class PermissionCache(object):
         the same agent and ability for all of the items in the queryset,
         without having to do a new database query each time.
         &quot;&quot;&quot;
+        if not settings.ENABLE_PERMISSION_CHECKING:
+            return queryset
         item_type = queryset.model
         self.global_abilities() # cache the global abilities
         global_abilities_yes, global_abilities_no = self._global_ability_cache
@@ -157,7 +164,7 @@ class PermissionCache(object):
             # Nothing to update, since no more database calls need to be made
             return queryset.none()
         else:
-            authorized_queryset = queryset.filter(self.filter_items_by_permission(ability), destroyed=False)
+            authorized_queryset = queryset.filter(self._filter_items_by_permission(ability), destroyed=False)
             yes_ids = set(authorized_queryset.values_list('pk', flat=True))
             no_ids = set(queryset.values_list('pk', flat=True)) - yes_ids
             self._ability_yes_cache.setdefault(ability, set()).update(yes_ids)
@@ -168,7 +175,7 @@ class PermissionCache(object):
     # Methods to calculate ability sets
     ###############################################################################
 
-    def calculate_abilities(self, item, item_type):
+    def _calculate_abilities(self, item, item_type):
         &quot;&quot;&quot;
         Return a pair (yes_abilities, no_abilities) where yes_abilities is the set
         of item abilities that the agent is granted and no_abilities is a set of
@@ -265,7 +272,7 @@ class PermissionCache(object):
     # Methods to calculate QuerySet filters
     ###############################################################################
 
-    def filter_items_by_permission(self, ability):
+    def _filter_items_by_permission(self, ability):
         &quot;&quot;&quot;
         Return a Q object that can be used as a QuerySet filter, specifying only
         those items that the agent has the ability for.
@@ -320,7 +327,7 @@ class PermissionCache(object):
                 else:
                     no_q_filters.append(q_filter)
 
-        # Combine all of the Q objects by the rules specified in calculate_abilities
+        # Combine all of the Q objects by the rules specified in _calculate_abilities
         # Nested conjuncts: ~n1 &amp; (y1 | (~n2 &amp; (y2 | (~n3 &amp; (y3 | (~n4 &amp; (y4 | (~n5 &amp; (y5 | ... )))))))))
         #TODO if we keep using the inelegant Q(pk__isnull=False) stuff, we could check for that and break early as an optimization
         result = Q()</diff>
      <filename>deme_django/cms/permissions.py</filename>
    </modified>
    <modified>
      <diff>@@ -37,10 +37,6 @@
 		.fg-menu-ipod .ui-widget-content { border:0; }
 	&lt;/style&gt;
 	&lt;![endif]--&gt;	
-
-    &lt;script type=&quot;text/javascript&quot; src=&quot;{% media_url &quot;javascripts/sexy-combo/lib/jquery.sexy-combo-2.1.2.pack.js&quot; %}&quot;&gt;&lt;/script&gt;
-    &lt;link href=&quot;{% media_url &quot;javascripts/sexy-combo/lib/sexy-combo.css&quot; %}&quot; media=&quot;all&quot; rel=&quot;Stylesheet&quot; type=&quot;text/css&quot; /&gt;
-    &lt;link href=&quot;{% media_url &quot;javascripts/sexy-combo/skins/sexy/sexy.css&quot; %}&quot; media=&quot;all&quot; rel=&quot;Stylesheet&quot; type=&quot;text/css&quot; /&gt;
     
     {% ifequal action 'show' %}
     {% if item %}</diff>
      <filename>deme_django/cms/templates/default_layout.html</filename>
    </modified>
    <modified>
      <diff>@@ -434,7 +434,7 @@ class ItemToolbar(template.Node):
                     &lt;input type=&quot;submit&quot; value=&quot;Submit&quot; /&gt;
                 &lt;/form&gt;
             &lt;/div&gt;
-            &quot;&quot;&quot; % (item_name, reverse('item_type_url', kwargs={'viewer':'subscription', 'action':'dialogcreate'}), context['full_path'], item.pk, AjaxModelChoiceField(EmailContactMethod.objects, permission_cache=context['_viewer'].permission_cache, required_abilities=[]).widget.render('email', None, {'id':'memberajaxfield'}), subscribe_url  ))
+            &quot;&quot;&quot; % (item_name, reverse('item_type_url', kwargs={'viewer':'subscription', 'action':'dialogcreate'}), context['full_path'], item.pk, AjaxModelChoiceField(EmailContactMethod.objects, permission_cache=context['_viewer'].permission_cache, required_abilities=['add_subscription']).widget.render('email', None, {'id':'memberajaxfield'}), subscribe_url))
 
         if isinstance(item, Agent):
             if agentcan_helper(context, 'add_authentication_method', item):</diff>
      <filename>deme_django/cms/templatetags/item_tags.py</filename>
    </modified>
    <modified>
      <diff>@@ -664,6 +664,8 @@ class SubscriptionViewer(ItemViewer):
         self.require_global_ability('create %s' % self.accepted_item_type.__name__)
         item = Item.objects.get(pk=self.request.POST.get('item'))
         email = EmailContactMethod.objects.get(pk=self.request.POST.get('email'))
+        self.require_ability('add_subscription', email)
+        self.require_ability('view Item.action_notices', item)
 
         new_subscription = Subscription(contact_method=email, item=item) 
         permissions = self._get_permissions_from_post_data(self.accepted_item_type, 'one')</diff>
      <filename>deme_django/cms/views.py</filename>
    </modified>
    <modified>
      <diff>@@ -83,6 +83,9 @@ DEFAULT_HOSTNAME = 'localhost'
 # The hostname from which notification emails are sent
 NOTIFICATION_EMAIL_HOSTNAME = 'localhost'
 
+# Enable if you want Deme to check permissions (highly recommended)
+ENABLE_PERMISSION_CHECKING = True
+
 INSTALLED_APPS = (
     'django.contrib.sessions',
     'deme_django.cms',</diff>
      <filename>deme_django/settings.py_EXAMPLE</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>2ec792e56c728406afa8b595ea868abb97fc2785</id>
    </parent>
    <parent>
      <id>6ad2661ebc6956e5fef8c4dff373b702c0e6cc35</id>
    </parent>
  </parents>
  <author>
    <name>Joseph</name>
    <email>joe@joe-laptop.(none)</email>
  </author>
  <url>http://github.com/mikemintz/deme/commit/6525a260d2d9073cc842aad4765fbdaac5a026ac</url>
  <id>6525a260d2d9073cc842aad4765fbdaac5a026ac</id>
  <committed-date>2009-10-09T14:58:48-07:00</committed-date>
  <authored-date>2009-10-09T14:58:48-07:00</authored-date>
  <message>Merge branch 'master' of git@github.com:mikemintz/deme</message>
  <tree>fe3a22503f86f255e87635c6bde7939ed68b59a2</tree>
  <committer>
    <name>Joseph</name>
    <email>joe@joe-laptop.(none)</email>
  </committer>
</commit>
