1
0
mirror of https://github.com/django/django.git synced 2025-07-05 02:09:13 +00:00

per-object-permissions: Made some code-formatting changes

git-svn-id: http://code.djangoproject.com/svn/django/branches/per-object-permissions@4100 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-11-25 05:18:33 +00:00
parent 1b54fc3aba
commit 6fab0ffcad
7 changed files with 141 additions and 205 deletions

View File

@ -1,31 +1,28 @@
var row_level_permission = { var row_level_permission = {
copyToNew: function (id) copyToNew: function (id) {
{
var newForm = document.getElementById("addRLPForm"); var newForm = document.getElementById("addRLPForm");
var form = document.getElementById("editRLPForm-"+id); var form = document.getElementById("editRLPForm-"+id);
newForm.owner.selectedIndex = form.owner.selectedIndex; newForm.owner.selectedIndex = form.owner.selectedIndex;
newForm.perm.selectedIndex = form.perm.selectedIndex; newForm.perm.selectedIndex = form.perm.selectedIndex;
newForm.negative.checked = form.negative.checked; newForm.negative.checked = form.negative.checked;
}, },
apply_selected: function () apply_selected: function () {
{
var eleList = document.getElementsByName("apply_checkbox"); var eleList = document.getElementsByName("apply_checkbox");
var formList = []; var formList = [];
for(var i=0; eleList.length; i++) for (var i=0; eleList.length; i++)
{ {
var ele = eleList[i]; var ele = eleList[i];
if(ele.tagName == "INPUT") { if (ele.tagName == "INPUT") {
if(ele.checked) { if (ele.checked) {
ele.form.submit(); ele.form.submit();
} }
} }
} }
return false; return false;
}, },
init: function() { init: function() {
} }
} }

View File

@ -10,39 +10,37 @@ class ChangeRLPManipulator(forms.Manipulator):
if ct: if ct:
self.ct = ct self.ct = ct
perm_list = [(o.id, o.name) for o in self.ct.permission_set.order_by("name")] perm_list = [(o.id, o.name) for o in self.ct.permission_set.order_by("name")]
obj_list = [(User, User.objects.order_by("username"))] obj_list = [(User, User.objects.order_by("username"))]
obj_list.extend([(Group, Group.objects.order_by("name"))]) obj_list.extend([(Group, Group.objects.order_by("name"))])
self.fields = ( self.fields = (
MultipleObjSelectField(field_name="owner", obj_list=obj_list), MultipleObjSelectField(field_name="owner", obj_list=obj_list),
forms.SelectField(field_name="perm", choices=perm_list), forms.SelectField(field_name="perm", choices=perm_list),
forms.CheckboxField(field_name="negative"), forms.CheckboxField(field_name="negative"),
) )
def save(self, new_data): def save(self, new_data):
rlp = RowLevelPermission.objects.get(pk=new_data['id']) rlp = RowLevelPermission.objects.get(pk=new_data['id'])
self.original_object = rlp self.original_object = rlp
self.manager = rlp._default_manager self.manager = rlp._default_manager
self.opts = rlp._meta self.opts = rlp._meta
owner = MultipleObjSelectField.returnObject(new_data['owner']) owner = MultipleObjSelectField.returnObject(new_data['owner'])
owner_ct = ContentType.objects.get_for_model(owner) owner_ct = ContentType.objects.get_for_model(owner)
model_ct = rlp.model_ct model_ct = rlp.model_ct
model = model_ct.get_object_for_this_type (pk=rlp.model_id) model = model_ct.get_object_for_this_type (pk=rlp.model_id)
model_id = rlp.model_id model_id = rlp.model_id
perm = Permission.objects.get(pk=new_data['perm']) perm = Permission.objects.get(pk=new_data['perm'])
field_name_list = ('owner_ct', 'owner_id', 'model_ct', 'model_id', 'permission') field_name_list = ('owner_ct', 'owner_id', 'model_ct', 'model_id', 'permission')
field_data = owner_ct.id field_data = owner_ct.id
all_data = {'owner_id':owner.id, 'model_ct_id':model_ct.id, 'model_id':model_id, 'permission_id':perm.id} all_data = {'owner_id': owner.id, 'model_ct_id': model_ct.id, 'model_id': model_id, 'permission_id': perm.id}
manipulators.manipulator_validator_unique_together(field_name_list, self.opts, self, field_data, all_data) manipulators.manipulator_validator_unique_together(field_name_list, self.opts, self, field_data, all_data)
rlp.owner = owner rlp.owner = owner
rlp.permission = perm rlp.permission = perm
rlp.negative = new_data['negative'] rlp.negative = new_data['negative']
@ -58,12 +56,11 @@ class AddRLPManipulator(ChangeRLPManipulator):
perm_list = [(o.id, o.name) for o in self.ct.permission_set.order_by("name")] perm_list = [(o.id, o.name) for o in self.ct.permission_set.order_by("name")]
self.fields = ( self.fields = (
MultipleObjSelectField(field_name="owner", obj_list=obj_list, default_text=_("Select an option")), MultipleObjSelectField(field_name="owner", obj_list=obj_list, default_text=_("Select an option")),
forms.SelectMultipleField(field_name="perm", choices=perm_list, size=3), forms.SelectMultipleField(field_name="perm", choices=perm_list, size=3),
forms.CheckboxField(field_name="negative"), forms.CheckboxField(field_name="negative"),
) )
def save(self, new_data): def save(self, new_data):
owner = MultipleObjSelectField.returnObject(new_data['owner']) owner = MultipleObjSelectField.returnObject(new_data['owner'])
self.manager = RowLevelPermission._default_manager self.manager = RowLevelPermission._default_manager
@ -71,68 +68,66 @@ class AddRLPManipulator(ChangeRLPManipulator):
ct = ContentType.objects.get_for_model(owner) ct = ContentType.objects.get_for_model(owner)
rlp_list = [] rlp_list = []
for i in new_data.getlist('perm'): for i in new_data.getlist('perm'):
perm = Permission.objects.get(pk=i) perm = Permission.objects.get(pk=i)
#Check that the new row level perms are unique # Check that the new row level perms are unique.
field_name_list = ('owner_ct', 'owner_id', 'model_ct', 'model_id', 'permission') field_name_list = ('owner_ct', 'owner_id', 'model_ct', 'model_id', 'permission')
field_data = ct.id field_data = ct.id
model_id = self.obj_instance._get_pk_val() model_id = self.obj_instance._get_pk_val()
all_data = {'owner_id':owner.id, 'model_ct_id':self.ct.id, 'model_id':model_id, 'permission_id':perm.id} all_data = {'owner_id': owner.id, 'model_ct_id': self.ct.id, 'model_id': model_id, 'permission_id': perm.id}
manipulators.manipulator_validator_unique_together(field_name_list, self.opts, self, field_data, all_data) manipulators.manipulator_validator_unique_together(field_name_list, self.opts, self, field_data, all_data)
rlp = RowLevelPermission.objects.create_row_level_permission(self.obj_instance, owner, perm, negative=new_data['negative']) rlp = RowLevelPermission.objects.create_row_level_permission(self.obj_instance, owner, perm, negative=new_data['negative'])
rlp_list.append(rlp) rlp_list.append(rlp)
return rlp_list return rlp_list
class MultipleObjSelectField(forms.SelectField): class MultipleObjSelectField(forms.SelectField):
""" """
Extends a select field to use more then one type of model in a select field. Extends a select field to use more then one type of model in a select field.
Uses optgroup in the select field to differentiate between object types. Uses optgroup in the select field to differentiate between object types.
obj_list should be a list of lists containing the model and a list of objects. obj_list should be a list of lists containing the model and a list of objects.
E.g. ((User, User.objects.all()), (Group, Group.objects.all)) E.g. ((User, User.objects.all()), (Group, Group.objects.all))
If you wish to define a default text to be shown as the default option, use the If you wish to define a default text to be shown as the default option, use the
default_text parameter. An example of default text would be "Select an option" default_text parameter. An example of default text would be "Select an option"
The remaining parameters are very similiar to the normal SelectField. The remaining parameters are very similiar to the normal SelectField.
To return the object selected pass the string result to MultipleObjSelectField.returnObject(string), To return the object selected pass the string result to MultipleObjSelectField.returnObject(string),
it returns the object instance. it returns the object instance.
To create a key for a specific object, use: MultipleObjSelectField.returnKey(object). It has an optional To create a key for a specific object, use: MultipleObjSelectField.returnKey(object). It has an optional
parameter for the content type (ct), if you have already determined the content type and want to save on parameter for the content type (ct), if you have already determined the content type and want to save on
db queries. db queries.
""" """
def __init__(self, field_name, obj_list=None, def __init__(self, field_name, obj_list=None, default_text=None, size=1,
default_text=None, size=1, is_required=False, validator_list=None, is_required=False, validator_list=None, member_name=None):
member_name=None):
choice_list = [] choice_list = []
self.default_text = default_text self.default_text = default_text
#Loop through the object list and create the list to be displayed # Loop through the object list and create the list to be displayed
for obj, obj_choices in obj_list: for obj, obj_choices in obj_list:
ct = ContentType.objects.get_for_model(obj) ct = ContentType.objects.get_for_model(obj)
object_choice = [(MultipleObjSelectField.returnKey(o, ct=ct), str(o)) for o in obj_choices] object_choice = [(MultipleObjSelectField.returnKey(o, ct=ct), str(o)) for o in obj_choices]
choice_list.extend([(ct.name.title(), object_choice)]) choice_list.extend([(ct.name.title(), object_choice)])
super(MultipleObjSelectField, self).__init__(field_name, choices=choice_list, super(MultipleObjSelectField, self).__init__(field_name, choices=choice_list,
size=size, is_required=is_required, size=size, is_required=is_required, validator_list=validator_list, member_name=member_name)
validator_list=validator_list,
member_name=member_name)
def render(self, data): def render(self, data):
from django.utils.html import escape from django.utils.html import escape
output = ['<select id="%s" class="v%s%s" name="%s" size="%s">' % \ output = ['<select id="%s" class="v%s%s" name="%s" size="%s">' % \
(self.get_id(), self.__class__.__name__, (self.get_id(), self.__class__.__name__,
self.is_required and ' required' or '', self.field_name, self.size)] self.is_required and ' required' or '', self.field_name, self.size)]
str_data = str(data) # normalize to string str_data = str(data) # normalize to string
if self.default_text: if self.default_text:
selected_html = '' selected_html = ''
if not str_data: if not str_data:
selected_html = ' selected="selected"' selected_html = ' selected="selected"'
output.append(' <option %s>%s</option>' % (selected_html, escape(self.default_text))) output.append(' <option %s>%s</option>' % (selected_html, escape(self.default_text)))
for obj, obj_choices in self.choices: for obj, obj_choices in self.choices:
output.append(' <optgroup label="%s">' % (obj,)) output.append(' <optgroup label="%s">' % (obj,))
for value, display_name in obj_choices: for value, display_name in obj_choices:
@ -142,8 +137,8 @@ class MultipleObjSelectField(forms.SelectField):
output.append(' <option value="%s"%s>%s</option>' % (escape(value), selected_html, escape(display_name))) output.append(' <option value="%s"%s>%s</option>' % (escape(value), selected_html, escape(display_name)))
output.append(' </optgroup>') output.append(' </optgroup>')
output.append(' </select>') output.append(' </select>')
return '\n'.join(output) return '\n'.join(output)
def returnObject(data): def returnObject(data):
data = data.split('/') data = data.split('/')
ct = ContentType.objects.get(app_label__exact=data[0], model__exact=data[1]) ct = ContentType.objects.get(app_label__exact=data[0], model__exact=data[1])
@ -153,10 +148,7 @@ class MultipleObjSelectField(forms.SelectField):
def returnKey(obj, ct=None): def returnKey(obj, ct=None):
if not ct: if not ct:
ct = ContentType.objects.get_for_model(obj.__class__) ct = ContentType.objects.get_for_model(obj.__class__)
return ct.app_label+"/"+ct.model+"/"+str(obj.id) return ct.app_label + "/" + ct.model + "/" + str(obj.id)
returnObject = staticmethod(returnObject) returnObject = staticmethod(returnObject)
returnKey = staticmethod(returnKey) returnKey = staticmethod(returnKey)

View File

@ -128,14 +128,14 @@ class FormFieldCollectionWrapper(object):
class TabularBoundRelatedObject(BoundRelatedObject): class TabularBoundRelatedObject(BoundRelatedObject):
def __init__(self, related_object, field_mapping, original): def __init__(self, related_object, field_mapping, original):
super(TabularBoundRelatedObject, self).__init__(related_object, field_mapping, original) super(TabularBoundRelatedObject, self).__init__(related_object, field_mapping, original)
self.field_wrapper_list = [FieldWrapper(field) for field in self.relation.editable_fields()] self.field_wrapper_list = [FieldWrapper(field) for field in self.relation.editable_fields()]
fields = self.relation.editable_fields() fields = self.relation.editable_fields()
self.form_field_collection_wrappers = [FormFieldCollectionWrapper(field_mapping, fields, i) self.form_field_collection_wrappers = [FormFieldCollectionWrapper(field_mapping, fields, i)
for (i,field_mapping) in self.field_mappings.items() ] for (i,field_mapping) in self.field_mappings.items() ]
self.original_row_needed = max([fw.use_raw_id_admin() for fw in self.field_wrapper_list]) self.original_row_needed = max([fw.use_raw_id_admin() for fw in self.field_wrapper_list])
if original: if original:
self.original = original self.original = original
@ -155,7 +155,7 @@ class StackedBoundRelatedObject(BoundRelatedObject):
if original: if original:
self.original = original self.original = original
self.show_url = original and hasattr(self.relation.opts, 'get_absolute_url') self.show_url = original and hasattr(self.relation.opts, 'get_absolute_url')
def template_name(self): def template_name(self):

View File

@ -100,22 +100,19 @@ if docutils_is_available:
for name, urlbase in ROLES.items(): for name, urlbase in ROLES.items():
create_reference_role(name, urlbase) create_reference_role(name, urlbase)
#Based off work by Ian Holsman # Based off work by Ian Holsman
#http://svn.zyons.python-hosting.com/trunk/zilbo/common/utils/misc.py # http://svn.zyons.python-hosting.com/trunk/zilbo/common/utils/misc.py
import sha import sha
from django.conf import settings from django.conf import settings
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
def verify_objref_hash( content_type_id, object_id, hash ): def verify_objref_hash(content_type_id, object_id, hash_):
hash_match = sha.new("%s/%s" % (content_type_id, object_id) + settings.SECRET_KEY).hexdigest() hash_match = sha.new("%s/%s" % (content_type_id, object_id) + settings.SECRET_KEY).hexdigest()
if hash == hash_match: return hash_ == hash_match
return True
else:
return False
def create_objref(object): def create_objref(object):
content_type_id = ContentType.objects.get_for_model( object ).id content_type_id = ContentType.objects.get_for_model(object).id
object_id = object.id object_id = object.id
return "%s/%d/%s" % ( content_type_id, object_id, sha.new("%s/%d" % (content_type_id, object_id) + settings.SECRET_KEY).hexdigest()) return "%s/%d/%s" % (content_type_id, object_id, sha.new("%s/%d" % (content_type_id, object_id) + settings.SECRET_KEY).hexdigest())

View File

@ -49,54 +49,48 @@ class Permission(models.Model):
class RowLevelPermissionManager(models.Manager): class RowLevelPermissionManager(models.Manager):
def create_row_level_permission(self, model_instance, owner, permission, negative=False): def create_row_level_permission(self, model_instance, owner, permission, negative=False):
model_ct=ContentType.objects.get_for_model(model_instance) model_ct = ContentType.objects.get_for_model(model_instance)
if isinstance(permission, str): if isinstance(permission, str):
permission = Permission.objects.get(codename__exact=permission, content_type=model_ct.id) permission = Permission.objects.get(codename=permission, content_type=model_ct.id)
if model_ct != permission.content_type: if model_ct != permission.content_type:
raise TypeError, "Invalid value: Permission content type(%s) and object content type(%s) do not match" % (permission.content_type, type_ct) raise TypeError, "Permission content type (%s) and object content type (%s) do not match" % (permission.content_type, type_ct)
model_id = model_instance._get_pk_val() model_id = model_instance._get_pk_val()
rowLvlPerm = self.model(model_id=model_id, model_ct=model_ct, row_lvl_perm = self.model(model_id=model_id, model_ct=model_ct, owner_id=owner.id,
owner_id=owner.id, owner_ct=ContentType.objects.get_for_model(owner), owner_ct=ContentType.objects.get_for_model(owner),
permission=permission, negative=negative) permission=permission, negative=negative)
rowLvlPerm.save() row_lvl_perm.save()
return rowLvlPerm return row_lvl_perm
def create_default_row_permissions(self, model_instance, owner, change=True, delete=True, negChange=False, negDel=False): def create_default_row_permissions(self, model_instance, owner, change=True, delete=True, negChange=False, negDel=False):
ret_dict = {} ret_dict = {}
model_ct = ContentType.objects.get_for_model(model_instance) model_ct = ContentType.objects.get_for_model(model_instance)
if change: if change:
change_str = "change_%s" % (model_ct.model) change_str = "change_%s" % (model_ct.model)
ret_dict[change_str]=self.create_row_level_permission(model_instance, owner, change_str, negative=negChange) ret_dict[change_str] = self.create_row_level_permission(model_instance, owner, change_str, negative=negChange)
if delete: if delete:
delete_str = "delete_%s" % (model_ct.model) delete_str = "delete_%s" % (model_ct.model)
ret_dict[delete_str]=self.create_row_level_permission(model_instance, owner, delete_str, negative=negDel) ret_dict[delete_str] = self.create_row_level_permission(model_instance, owner, delete_str, negative=negDel)
return ret_dict return ret_dict
def get_model_list(self,user, model, perm): def get_model_list(self, user, model, perm):
model_ct=ContentType.objects.get_for_model(model) model_ct = ContentType.objects.get_for_model(model)
if isinstance(perm, str): if isinstance(perm, str):
perm = Permission.objects.get(codename__exact=perm, content_type=model_ct.id) perm = Permission.objects.get(codename__exact=perm, content_type=model_ct.id)
user_model_ids = RowLevelPermission.objects.filter(owner_ct=ContentType.objects.get_for_model(User), user_model_ids = RowLevelPermission.objects.filter(owner_ct=ContentType.objects.get_for_model(User),
owner_id=user.id, permission=perm.id, owner_id=user.id, permission=perm.id, model_ct=model_ct).values('model_id')
model_ct=model_ct id_list = [o['model_id'] for o in user_model_ids]
).values('model_id') user_group_list = [g['id'] for g in user.groups.select_related().values('id')]
id_list = [o['model_id'] for o in user_model_ids]
user_group_list = [g['id'] for g in user.groups.select_related().values('id')]
if user_group_list: if user_group_list:
group_model_ids = RowLevelPermission.objects.filter(owner_ct=ContentType.objects.get_for_model(Group).id, group_model_ids = RowLevelPermission.objects.filter(owner_ct=ContentType.objects.get_for_model(Group).id,
owner_id__in=user_group_list, owner_id__in=user_group_list, model_ct = model_ct).values('model_id')
model_ct = model_ct id_list = id_list + [o['model_id'] for o in group_model_ids]
).values('model_id')
id_list=id_list + [o['model_id'] for o in group_model_ids]
return id_list return id_list
class RowLevelPermission(models.Model): class RowLevelPermission(models.Model):
""" """
Similiar to permissions but works on instances of objects instead of types. Similiar to permissions but works on instances of objects instead of types.
This uses generic relations to minimize the number of tables, and connects to the This uses generic relations to minimize the number of tables, and connects to the
permissions table using a many to one relation. permissions table using a many to one relation.
""" """
model_id = models.PositiveIntegerField("'Model' ID") model_id = models.PositiveIntegerField("'Model' ID")
model_ct = models.ForeignKey(ContentType, verbose_name="'Model' content type", related_name="model_ct") model_ct = models.ForeignKey(ContentType, verbose_name="'Model' content type", related_name="model_ct")
@ -104,27 +98,24 @@ class RowLevelPermission(models.Model):
owner_ct = models.ForeignKey(ContentType, verbose_name="'Owner' content type", related_name="owner_ct") owner_ct = models.ForeignKey(ContentType, verbose_name="'Owner' content type", related_name="owner_ct")
negative = models.BooleanField() negative = models.BooleanField()
permission = models.ForeignKey(Permission) permission = models.ForeignKey(Permission)
model = models.GenericForeignKey(fk_field='model_id', ct_field='model_ct') model = models.GenericForeignKey(fk_field='model_id', ct_field='model_ct')
owner = models.GenericForeignKey(fk_field='owner_id', ct_field='owner_ct') owner = models.GenericForeignKey(fk_field='owner_id', ct_field='owner_ct')
objects = RowLevelPermissionManager() objects = RowLevelPermissionManager()
class Meta: class Meta:
verbose_name = _('row level permission') verbose_name = _('row level permission')
verbose_name_plural = _('row level permissions') verbose_name_plural = _('row level permissions')
unique_together = (('model_ct', 'model_id', 'owner_id', 'owner_ct', 'permission'),) unique_together = (('model_ct', 'model_id', 'owner_id', 'owner_ct', 'permission'),)
class Admin: class Admin:
hidden = True hidden = True
def __str__(self): def __str__(self):
return "%s | %s:%s | %s:%s" % (self.permission, self.owner_ct, self.owner, self.model_ct, self.model) return "%s | %s:%s | %s:%s" % (self.permission, self.owner_ct, self.owner, self.model_ct, self.model)
def __repr__(self): def __repr__(self):
return "%s | %s:%s | %s:%s" % (self.permission, self.owner_ct, self.owner, self.model_ct, self.model) return "%s | %s:%s | %s:%s" % (self.permission, self.owner_ct, self.owner, self.model_ct, self.model)
class Group(models.Model): class Group(models.Model):
"""Groups are a generic way of categorizing users to apply permissions, or some other label, to those users. A user can belong to any number of groups. """Groups are a generic way of categorizing users to apply permissions, or some other label, to those users. A user can belong to any number of groups.
@ -179,7 +170,7 @@ class User(models.Model):
groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True, groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True,
help_text=_("In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in.")) help_text=_("In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."))
user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True, filter_interface=models.HORIZONTAL) user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True, filter_interface=models.HORIZONTAL)
row_level_permissions_owned = models.GenericRelation(RowLevelPermission, object_id_field="owner_id", content_type_field="owner_ct", related_name="owner") row_level_permissions_owned = models.GenericRelation(RowLevelPermission, object_id_field="owner_id", content_type_field="owner_ct", related_name="owner")
objects = UserManager() objects = UserManager()
@ -283,32 +274,23 @@ class User(models.Model):
return self._perm_cache return self._perm_cache
def check_row_level_permission(self, permission, object): def check_row_level_permission(self, permission, object):
object_ct=ContentType.objects.get_for_model(object) object_ct = ContentType.objects.get_for_model(object)
if isinstance(permission, str): if isinstance(permission, str):
try: try:
permission = Permission.objects.get(codename__exact=permission, content_type=object_ct.id) permission = Permission.objects.get(codename=permission, content_type=object_ct.id)
except Permission.DoesNotExist: except Permission.DoesNotExist:
return False return False
try: try:
model_id = object._get_pk_val() model_id = object._get_pk_val()
row_level_perm=self.row_level_permissions_owned.get(model_id=model_id, row_level_perm = self.row_level_permissions_owned.get(model_id=model_id,
model_ct=object_ct.id, model_ct=object_ct.id, permission=permission.id)
permission=permission.id)
except RowLevelPermission.DoesNotExist: except RowLevelPermission.DoesNotExist:
return self.check_group_row_level_permissions(permission, object) return self.check_group_row_level_permissions(permission, object)
return not row_level_perm.negative return not row_level_perm.negative
def check_group_row_level_permissions(self, permission, object): def check_group_row_level_permissions(self, permission, object):
#SELECT rlp."negative"
#FROM "auth_user_groups" ug, "auth_rowlevelpermission" rlp
#WHERE rlp."owner_id"=ug."group_id"
#AND ug."user_id"=%s
#AND rlp."owner_ct_id"=%s
#AND rlp."model_id"=%s
#AND rlp."model_ct_id"=%s
#AND rlp."permission_id"=%s;
model_id = object._get_pk_val() model_id = object._get_pk_val()
cursor = connection.cursor() cursor = connection.cursor()
sql = """ sql = """
SELECT rlp.%s SELECT rlp.%s
FROM %s ug, %s rlp FROM %s ug, %s rlp
@ -325,17 +307,15 @@ class User(models.Model):
backend.quote_name('owner_ct_id'), backend.quote_name('model_id'), backend.quote_name('owner_ct_id'), backend.quote_name('model_id'),
backend.quote_name('model_ct_id'), backend.quote_name('permission_id'), backend.quote_name('model_ct_id'), backend.quote_name('permission_id'),
backend.quote_name('negative')) backend.quote_name('negative'))
cursor.execute(sql, [self.id, cursor.execute(sql, [self.id,
ContentType.objects.get_for_model(Group).id, ContentType.objects.get_for_model(Group).id,
model_id, model_id,
ContentType.objects.get_for_model(object).id, ContentType.objects.get_for_model(object).id,
permission.id,]) permission.id,])
row = cursor.fetchone() row = cursor.fetchone()
if row is None: if row is None:
return None return None
return not row[0] return not row[0]
def has_perm(self, perm, object=None): def has_perm(self, perm, object=None):
"Returns True if the user has the specified permission." "Returns True if the user has the specified permission."
@ -344,7 +324,7 @@ class User(models.Model):
if self.is_superuser: if self.is_superuser:
return True return True
if object and object._meta.row_level_permissions: if object and object._meta.row_level_permissions:
#Since we use the content type for row level perms, we don't need the application name # Since we use the content type for row level perms, we don't need the application name.
permission_str = perm[perm.index('.')+1:] permission_str = perm[perm.index('.')+1:]
row_level_permission = self.check_row_level_permission(permission_str, object) row_level_permission = self.check_row_level_permission(permission_str, object)
if row_level_permission is not None: if row_level_permission is not None:
@ -360,7 +340,7 @@ class User(models.Model):
def contains_permission(self, perm, model=None): def contains_permission(self, perm, model=None):
""" """
This checks if the user has the given permission for any instance This checks if the user has the given permission for any instance
of the given model. of the given model.
""" """
if self.has_perm(perm): if self.has_perm(perm):
@ -369,29 +349,20 @@ class User(models.Model):
perm = perm[perm.index('.')+1:] perm = perm[perm.index('.')+1:]
return self.contains_row_level_perm(perm, model) return self.contains_row_level_perm(perm, model)
return False return False
def contains_row_level_perm(self, perm, model): def contains_row_level_perm(self, perm, model):
model_ct = ContentType.objects.get_for_model(model) model_ct = ContentType.objects.get_for_model(model)
if isinstance(perm, str): if isinstance(perm, str):
permission = Permission.objects.get(codename__exact=perm, content_type=model_ct.id) permission = Permission.objects.get(codename__exact=perm, content_type=model_ct.id)
else: else:
permission = perm permission = perm
count = self.row_level_permissions_owned.filter(model_ct=model_ct.id, permission=permission.id).count() count = self.row_level_permissions_owned.filter(model_ct=model_ct.id, permission=permission.id).count()
if count > 0:
if count>0:
return True return True
return self.contains_group_row_level_perms(permission, model_ct) return self.contains_group_row_level_perms(permission, model_ct)
def contains_group_row_level_perms(self, perm, ct): def contains_group_row_level_perms(self, perm, ct):
#SELECT COUNT(*) cursor = connection.cursor()
#FROM "auth_user_groups" ug, "auth_rowlevelpermission" rlp, "django_content_type" ct
#WHERE rlp."owner_id" = ug."group_id"
#AND ug."user_id"=%s
#AND rlp."negative" = False
#AND rlp."owner_ct_id" = %s
#AND rlp."model_ct_id" = %s
cursor = connection.cursor()
sql = """ sql = """
SELECT COUNT(*) SELECT COUNT(*)
FROM %s ug, %s rlp, %s ct FROM %s ug, %s rlp, %s ct
@ -401,14 +372,14 @@ class User(models.Model):
AND rlp.%s = %%s AND rlp.%s = %%s
AND rlp.%s = %%s AND rlp.%s = %%s
AND rlp.%s = %%s""" % ( AND rlp.%s = %%s""" % (
backend.quote_name('auth_user_groups'), backend.quote_name('auth_rowlevelpermission'), backend.quote_name('auth_user_groups'), backend.quote_name('auth_rowlevelpermission'),
backend.quote_name('django_content_type'), backend.quote_name('owner_id'), backend.quote_name('django_content_type'), backend.quote_name('owner_id'),
backend.quote_name('group_id'), backend.quote_name('user_id'), backend.quote_name('group_id'), backend.quote_name('user_id'),
backend.quote_name('negative'), backend.quote_name('owner_ct_id'), backend.quote_name('negative'), backend.quote_name('owner_ct_id'),
backend.quote_name('model_ct_id'), backend.quote_name('permission_id')) backend.quote_name('model_ct_id'), backend.quote_name('permission_id'))
cursor.execute(sql, [self.id, False, ContentType.objects.get_for_model(Group).id, ct.id, perm.id]) cursor.execute(sql, [self.id, False, ContentType.objects.get_for_model(Group).id, ct.id, perm.id])
count = int(cursor.fetchone()[0]) count = int(cursor.fetchone()[0])
return (count>0) return count > 0
def has_module_perms(self, app_label): def has_module_perms(self, app_label):
"Returns True if the user has any permissions in the given app label." "Returns True if the user has any permissions in the given app label."
@ -416,19 +387,12 @@ class User(models.Model):
return False return False
if self.is_superuser: if self.is_superuser:
return True return True
if bool(len([p for p in self.get_all_permissions() if p[:p.index('.')] == app_label])): if [p for p in self.get_all_permissions() if p[:p.index('.')] == app_label]:
return True return True
return self.has_module_row_level_perms(app_label) return self.has_module_row_level_perms(app_label)
def has_module_row_level_perms(self, app_label): def has_module_row_level_perms(self, app_label):
#SELECT COUNT(*) cursor = connection.cursor()
#FROM "django_content_type" ct, "auth_rowlevelpermission" rlp
#WHERE rlp."model_ct_id" = ct."id"
#AND ct."app_label"=%s
#AND rlp."negative" = False
#AND rlp."owner_ct_id" = %s
#AND rlp."owner_id" = %s
cursor = connection.cursor()
sql = """ sql = """
SELECT COUNT(*) SELECT COUNT(*)
FROM %s ct, %s rlp FROM %s ct, %s rlp
@ -437,30 +401,20 @@ class User(models.Model):
AND rlp.%s = %%s AND rlp.%s = %%s
AND rlp.%s = %%s AND rlp.%s = %%s
AND rlp.%s = %%s AND rlp.%s = %%s
""" % ( """ % (
backend.quote_name('django_content_type'), backend.quote_name('auth_rowlevelpermission'), backend.quote_name('django_content_type'), backend.quote_name('auth_rowlevelpermission'),
backend.quote_name('model_ct_id'), backend.quote_name('id'), backend.quote_name('model_ct_id'), backend.quote_name('id'),
backend.quote_name('app_label'), backend.quote_name('app_label'),
backend.quote_name('owner_ct_id'), backend.quote_name('owner_ct_id'),
backend.quote_name('owner_id'),backend.quote_name('negative'), ) backend.quote_name('owner_id'),backend.quote_name('negative'), )
#import pdb cursor.execute(sql, [app_label, ContentType.objects.get_for_model(User).id, self.id, False])
#pdb.set_trace()
cursor.execute(sql, [app_label, ContentType.objects.get_for_model(User).id, self.id, False])
count = int(cursor.fetchone()[0]) count = int(cursor.fetchone()[0])
if count>0: if count > 0:
return True return True
return self.has_module_group_row_level_perms(app_label) return self.has_module_group_row_level_perms(app_label)
def has_module_group_row_level_perms(self, app_label): def has_module_group_row_level_perms(self, app_label):
#SELECT COUNT(*) cursor = connection.cursor()
#FROM "auth_user_groups" ug, "auth_rowlevelpermission" rlp, "django_content_type" ct
#WHERE rlp."owner_id" = ug."group_id"
#AND ug."user_id"=%s
#AND rlp."model_ct_id" = ct."id"
#AND ct."app_label"=%s
#AND rlp."negative" = False
#AND rlp."owner_ct_id" = %s
cursor = connection.cursor()
sql = """ sql = """
SELECT COUNT(*) SELECT COUNT(*)
FROM %s ug, %s rlp, %s ct FROM %s ug, %s rlp, %s ct
@ -470,7 +424,7 @@ class User(models.Model):
AND ct.%s=%%s AND ct.%s=%%s
AND rlp.%s = %%s AND rlp.%s = %%s
AND rlp.%s = %%s""" % ( AND rlp.%s = %%s""" % (
backend.quote_name('auth_user_groups'), backend.quote_name('auth_rowlevelpermission'), backend.quote_name('auth_user_groups'), backend.quote_name('auth_rowlevelpermission'),
backend.quote_name('django_content_type'), backend.quote_name('owner_id'), backend.quote_name('django_content_type'), backend.quote_name('owner_id'),
backend.quote_name('group_id'), backend.quote_name('user_id'), backend.quote_name('group_id'), backend.quote_name('user_id'),
backend.quote_name('model_ct_id'), backend.quote_name('id'), backend.quote_name('model_ct_id'), backend.quote_name('id'),
@ -478,8 +432,7 @@ class User(models.Model):
backend.quote_name('owner_ct_id')) backend.quote_name('owner_ct_id'))
cursor.execute(sql, [self.id, app_label, False, ContentType.objects.get_for_model(Group).id]) cursor.execute(sql, [self.id, app_label, False, ContentType.objects.get_for_model(Group).id])
count = int(cursor.fetchone()[0]) count = int(cursor.fetchone()[0])
return (count>0) return (count>0)
def get_and_delete_messages(self): def get_and_delete_messages(self):
messages = [] messages = []

View File

@ -1,26 +1,24 @@
from django import template from django import template
from django.template import loader from django.template import loader
from django.conf import settings from django.conf import settings
register = template.Library() register = template.Library()
def if_has_perm(parser, token): def if_has_perm(parser, token):
""" """
TODO: Update document TODO: Update document
Checks permission on the given user. Will check Checks permission on the given user. Checks row-level permissions if an
row level permissions if an object is given. object is given.
Note: Perm name should be in the format of [app_label].[perm codename] Perm name should be in the format [app_label].[perm codename].
"""
"""
tokens = token.split_contents() tokens = token.split_contents()
if len(tokens)<2: if len(tokens) < 2:
raise template.TemplateSyntaxError, "%r tag requires at least 1 arguments" % tokens[0] raise template.TemplateSyntaxError, "%r tag requires at least 1 argument" % tokens[0]
if len(tokens)>4: if len(tokens) > 4:
raise template.TemplateSyntaxError, "%r tag should have no more then 3 arguments" % tokens[0] raise template.TemplateSyntaxError, "%r tag should have no more then 3 arguments" % tokens[0]
nodelist_true = parser.parse(('else', 'end_'+tokens[0],)) nodelist_true = parser.parse(('else', 'end_'+tokens[0],))
token = parser.next_token() token = parser.next_token()
if token.contents == 'else': if token.contents == 'else':
@ -28,24 +26,24 @@ def if_has_perm(parser, token):
parser.delete_first_token() parser.delete_first_token()
else: else:
nodelist_false = template.NodeList() nodelist_false = template.NodeList()
object_var = None object_var = None
not_flag = False not_flag = False
if tokens[1] is "not": if tokens[1] == "not":
not_flag = True not_flag = True
permission=tokens[2] permission = tokens[2]
if len(tokens)>3: if len(tokens) > 3:
object_var = parser.compile_filter(tokens[3]) object_var = parser.compile_filter(tokens[3])
else: else:
permission=tokens[1] permission = tokens[1]
if len(tokens)>2: if len(tokens) > 2:
object_var = parser.compile_filter(tokens[2]) object_var = parser.compile_filter(tokens[2])
if not (permission[0] == permission[-1] and permission[0] in ('"', "'")): if not (permission[0] == permission[-1] and permission[0] in ('"', "'")):
raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tokens[0] raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tokens[0]
return HasPermNode(permission[1:-1], not_flag, object_var, nodelist_true, nodelist_false) return HasPermNode(permission[1:-1], not_flag, object_var, nodelist_true, nodelist_false)
class HasPermNode(template.Node): class HasPermNode(template.Node):
def __init__(self, permission, not_flag, object_var, nodelist_true, nodelist_false): def __init__(self, permission, not_flag, object_var, nodelist_true, nodelist_false):
self.permission = permission self.permission = permission
@ -70,7 +68,7 @@ class HasPermNode(template.Node):
nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype)) nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype))
return nodes return nodes
def render(self, context): def render(self, context):
if self.object_var: if self.object_var:
try: try:
object = self.object_var.resolve(context) object = self.object_var.resolve(context)
@ -78,17 +76,17 @@ class HasPermNode(template.Node):
object = None object = None
else: else:
object=None object=None
try: try:
user = template.resolve_variable("user", context) user = template.resolve_variable("user", context)
except template.VariableDoesNotExist: except template.VariableDoesNotExist:
return settings.TEMPLATE_STRING_IF_INVALID return settings.TEMPLATE_STRING_IF_INVALID
bool_perm = user.has_perm(self.permission, object=object) bool_perm = user.has_perm(self.permission, object=object)
if (self.not_flag and not bool_perm) or (not self.not_flag and bool_perm): if (self.not_flag and not bool_perm) or (not self.not_flag and bool_perm):
return self.nodelist_true.render(context) return self.nodelist_true.render(context)
if (self.not_flag and bool_perm) or (not self.not_flag and not bool_perm): if (self.not_flag and bool_perm) or (not self.not_flag and not bool_perm):
return self.nodelist_false.render(context) return self.nodelist_false.render(context)
return '' return ''
register.tag('if_has_perm', if_has_perm) register.tag('if_has_perm', if_has_perm)

View File

@ -233,7 +233,6 @@ class AutomaticManipulator(forms.Manipulator):
new_rel_obj.delete() new_rel_obj.delete()
self.fields_deleted.append('%s "%s"' % (related.opts.verbose_name, old_rel_obj)) self.fields_deleted.append('%s "%s"' % (related.opts.verbose_name, old_rel_obj))
# Save the order, if applicable. # Save the order, if applicable.
if self.change and self.opts.get_ordered_objects(): if self.change and self.opts.get_ordered_objects():
order = new_data['order_'] and map(int, new_data['order_'].split(',')) or [] order = new_data['order_'] and map(int, new_data['order_'].split(',')) or []