Implementation of Object Permissions

2012-04-13 Thread Moritz S.
Hi all,

I have been using django for a while and became happy by the time I 
discovered the auth module that supports permission handling. But this 
module turned out to only be able to handle model based permissions. I 
could not imagine django of not having such a basic functionality (in my 
opinion) despite of having so much other great abilities. So I started to 
search for it but eventually figured out that the auth model's code was 
prepared for implementing this but it haven't been done yet.
So I decided to write a patch for this on my own.
Currently I'm writing this patch but there are several design decisions to 
make so I wanted to share this with you and hear your opinions.

First of all: I think the main problem of this implementation is to link 
the objects with the corresponding permissions. With model based 
permissions that's easy because you only have to store a permission once 
with the models ContentType and relate with a ManyToManyField to them and 
that's it. The problem with object based permissions is that every object 
needs to have his own set of permissions and you can't just use ForeignKeys 
or ManyToManyFields from a permission model because in the process of 
creating the permission model (and table) you don't know about the models 
that will provide object permissions therefore you can't refer to them.
So I tried some different implementations.

At first I tried to used dynamic models (e.g. this project makes use of 
them: http://pypi.python.org/pypi/django-object-permissions): The idea is 
to create intermediate models like 'MyModel_ObjectPermissions' that stores 
the object permissions with foreign keys to the model itself, user and 
group.
But this has a huge disadvantage: the use of dynamic models.
In fact thinking as database specialist that is the easiest way of 
connecting the model instances to the permissions but dynamic models are 
very sensitive and kind of hacky in my opinion and I think that does not 
match well with django's ideas.

Then I found out about GenericRelations from the contenttypes framework. So 
you could possibly use a single model called 'ObjectPermissions' or 
something and link users, permissions and instances of all types of models 
and only had to use one GenericRelation. This solution eliminates the 
problem wit the dynamic models because it doesn't even make use of them. 
But the GenericRelations have another not negligible disadvantage: The 
databases behind django don't have native support for them. I thought of 
huge django projects handling thousands and thousands of object 
permissions. I think these GenericRelations wouldn't be such scalable to 
make use of them.

The only solution for me was to find a way to link the (unknown) model 
instances to the permissions in the reversed direction. So not use 
ForeignKeys, etc. in the permission model to refer to the unknown model but 
to refer from the model to the permission itself. That would fix the 
problem of not knowing the models while creating the permission model. So 
in the end I thought of following:
- there is a new model in the auth module called 'ObjectPermission' this 
model has ManyToManyFields to User and Group and a ForeignKey to Permission
- instead of ObjectPermission referring to the model using object 
permissions, a field called 'object_permissions' is added to the 
corresponding models (by use of the class_prepared signal) (dynamically 
adding fields is way better than use completely dynamic models in my 
opinion)
- the object_permissions field is a ManyToManyField, that refers to 
ObjectPermission. In fact, a 'ManyToOneField' would be sufficient but 
django only has one to many fields (the ForeignKeyField) and we can't just 
use this in the reversed direction, as I mentioned above
This picture illustrates the relations:




Furthermore I thought of slightly modifying the auth module (apart from the 
ObjectPermission model) in the following way:
- when the auth app is initialized a function is registered to listen to 
the class_prepared signal. This function adds the object_permissions field 
to each model, that has the Meta.object_permissions set to True (for this 
to work, this meta attribute has to be set in django.db.models.options)
- the User model gets the methods grant_perm and revoke_perm that takes the 
permission and as optional argument the object in order to simplify the 
process of handling permissions
- in the ModelBackend the methods has_perm, etc. have to be modified to be 
able to handle function calls with given objects (obviously)

So that was the technical part.

Now I want you to give feedback if this implementation is viable and maybe 
sometimes may get into django.


Thanks,
Moritz

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To view this discussion on the web visit 
h

Re: Implementation of Object Permissions

2012-04-13 Thread Moritz S.
I checked the four most used solutions.
The first three ones use GenericKeys (in my opinion not the ideal solution 
as I described above) and the fourth one as far as I can see does not use 
the auth permission backend but does permission handling on his own.

-Moritz

Am Samstag, 14. April 2012 02:14:35 UTC+2 schrieb Mike Axiak:
>
> How does it compare to the solutions that already exist listed here?
>
>  http://djangopackages.com/grids/g/perms/
>
> -Mike
>
> On Fri, Apr 13, 2012 at 7:56 PM, Moritz S. 
> wrote:
>
>> Hi all,
>>
>> I have been using django for a while and became happy by the time I 
>> discovered the auth module that supports permission handling. But this 
>> module turned out to only be able to handle model based permissions. I 
>> could not imagine django of not having such a basic functionality (in my 
>> opinion) despite of having so much other great abilities. So I started to 
>> search for it but eventually figured out that the auth model's code was 
>> prepared for implementing this but it haven't been done yet.
>> So I decided to write a patch for this on my own.
>> Currently I'm writing this patch but there are several design decisions 
>> to make so I wanted to share this with you and hear your opinions.
>>
>> First of all: I think the main problem of this implementation is to link 
>> the objects with the corresponding permissions. With model based 
>> permissions that's easy because you only have to store a permission once 
>> with the models ContentType and relate with a ManyToManyField to them and 
>> that's it. The problem with object based permissions is that every object 
>> needs to have his own set of permissions and you can't just use ForeignKeys 
>> or ManyToManyFields from a permission model because in the process of 
>> creating the permission model (and table) you don't know about the models 
>> that will provide object permissions therefore you can't refer to them.
>> So I tried some different implementations.
>>
>> At first I tried to used dynamic models (e.g. this project makes use of 
>> them: http://pypi.python.org/pypi/django-object-permissions): The idea 
>> is to create intermediate models like 'MyModel_ObjectPermissions' that 
>> stores the object permissions with foreign keys to the model itself, user 
>> and group.
>> But this has a huge disadvantage: the use of dynamic models.
>> In fact thinking as database specialist that is the easiest way of 
>> connecting the model instances to the permissions but dynamic models are 
>> very sensitive and kind of hacky in my opinion and I think that does not 
>> match well with django's ideas.
>>
>> Then I found out about GenericRelations from the contenttypes framework. 
>> So you could possibly use a single model called 'ObjectPermissions' or 
>> something and link users, permissions and instances of all types of models 
>> and only had to use one GenericRelation. This solution eliminates the 
>> problem wit the dynamic models because it doesn't even make use of them. 
>> But the GenericRelations have another not negligible disadvantage: The 
>> databases behind django don't have native support for them. I thought of 
>> huge django projects handling thousands and thousands of object 
>> permissions. I think these GenericRelations wouldn't be such scalable to 
>> make use of them.
>>
>> The only solution for me was to find a way to link the (unknown) model 
>> instances to the permissions in the reversed direction. So not use 
>> ForeignKeys, etc. in the permission model to refer to the unknown model but 
>> to refer from the model to the permission itself. That would fix the 
>> problem of not knowing the models while creating the permission model. So 
>> in the end I thought of following:
>> - there is a new model in the auth module called 'ObjectPermission' this 
>> model has ManyToManyFields to User and Group and a ForeignKey to Permission
>> - instead of ObjectPermission referring to the model using object 
>> permissions, a field called 'object_permissions' is added to the 
>> corresponding models (by use of the class_prepared signal) (dynamically 
>> adding fields is way better than use completely dynamic models in my 
>> opinion)
>> - the object_permissions field is a ManyToManyField, that refers to 
>> ObjectPermission. In fact, a 'ManyToOneField' would be sufficient but 
>> django only has one to many fields (the ForeignKeyField) and we can't just 
>> use this in the reversed dir

Re: Implementation of Object Permissions

2012-04-23 Thread Moritz S.

>
> With an appropriate index, SQL databases should be able to find rows 
> matching a condition on two columns about as quickly as if the condition 
> was only on one column, even in a table containing million of objects.
>
Databases can of course find the rows with appropriate indexes, but the 
problem is that GenericForeignKeys are precisely not such appropriate ones. 

> I'd like to see a benchmark before rejecting this idea on performance 
> grounds. Could you point us to some data supporting your assertion that 
> this isn't scalable?
>
To prove the increased performance I actually did some benchmark. I used 
the script in the attachment. It needs a model that has only one field 
called text. It randomly generates 10,000 users and 1,000,000 objects. Then 
it assigns to each user respectively 1,000 object permissions of randomly 
selected previously created objects. At least it checks for each user 
respectively 1,000 randomly selected objects again. That's what I got:

For the first version of my contrib.auth patch:
Summary:
granted permissions in 1 day, 10:41:07.523402
checked permissions in 22:48:44.662974

For a module using GenericForeignKeys (I used django-guardian because it 
seemed to be the most used one):
granted permissions in 11:31:12.216808
checked permissions 

I don't have the results for checking permissions with django-guardian yet 
because it took ages to check them. Each single check for a object 
permission took about 4 to 5 seconds! Now think about how long it would 
take to check for all users (10,000*1,000*4secs)! I think that is out of 
all proportion to my suggested solution.
This happens because of the lack of a appropriate index as you mentioned 
before. So the database has to do a full table scan and that's definitely 
not scalable at all.
By the way, the reason for the GenericForeignKeys being faster in creating 
them is that the database does not have to create the indexes (i.e. the 
foreign keys). 

> I'm -1 on a contrib app (django.contrib.auth) injecting a dynamic field 
> into every model.
>
> (Yes, Django does that for the primary key, to avoid declaring it in every 
> model. But it's core, not a contrib app.)
>
I totally agree with this but I don't see another way at the moment. 

> What's the definition of "when the auth app is initialized"? Wouldn't your 
> solution required that django.contrib.auth be loaded before all other apps?
>
Unfortunately it does but I have a open mind about better implementations.
>
> With the solution that I prefer, this doesn't seem absolutely necessary, 
> the following statements are simple enough:
>
> ObjectPermission.objects.create(user=user, object=instance)
> ObjectPermission.objects.get(user=user, object=instance).delete()
>
I think that's matter of taste ;-) 

Your need to add ‘object_permissions’ to a model is an incorrect approach 
> in my opinion as it would require any old apps to undergo a schema 
> migration. Your generic relations concerns might be valid however I would 
> like to mention Django guardian does use generic FK but so does built in 
> django auth – so I think this approach is just fine.

You don't have to add this field manually, auth app does that. And django 
auth does not use generic relationships, it only makes use of the 
ContentType field to comfortably store the type assigned to a permission. 

Best regards,
Moritz

>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/django-developers/-/fp-Bu8sgUq0J.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

#!/usr/bin/env python -u

import string
import random
from datetime import datetime

NUM_OBJECTS=100
NUM_USERS=1
NUM_PERMS_PER_USER=1000

def random_string(length=25, chars=string.ascii_letters+string.digits):
return ''.join(random.choice(chars) for i in range(length))

class Benchmark(object):

def __init__(self, User, TestModel, perm='testapp.add_testmodel', grant_perm=lambda user, perm, obj: ''):
self.time_grant=0
self.time_check=0
self._user=User
self._model=TestModel
self._perm=perm
self._grant_perm=grant_perm

def create_users(self, num=NUM_USERS):
print 'Creating users:',
self._user.objects.bulk_create(self._user(username=random_string()) for i in range(num))
print 'done'

def create_objects(self, num=NUM_OBJECTS):
print 'Creating objects:',
self._model.objects.bulk_create(self._model(text=random_string(50)) for i in xrange(num))
print 'done'

def grant_permissions(self, num_perms_per_user=NUM_PERMS_PER_USER, num_objects=NUM_OBJECTS):
print 'Grant permissions to users:',
k

Re: Why no http://media.djangoproject.com/releases/1.4/Django-1.4.tar.gz?

2012-04-24 Thread Moritz S.
Hi,

try http://www.djangoproject.com/download//tarball/

Best regards,
Moritz

Am Dienstag, 24. April 2012 05:56:20 UTC+2 schrieb Bob Cochran:
>
> These exist for 1.3, 1.3.1, 1.2..., but not 1.4.
>
> Are they located somewhere else moving forward?
>
> Thanks
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/django-developers/-/2-29TmgABl4J.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Implementation of Object Permissions

2012-04-27 Thread Moritz S.

>
> Are there any hopes of speeding up or caching GenericForgeinKey queries ? 
> I found -  
> http://zerokspot.com/weblog/2008/08/13/genericforeignkeys-with-less-queries/
>  
>
Adding 'db_index=True' to the GenericForeignKey's object_id field should be 
a significant performance enhancement. It won't get as good results as the 
other solution, though, but that should prevent the database from doing 
full table scans.
But I'm not sure whether GenericRelations allow this, because no django 
object permission app does this. 

> can your solution be backward compatible?
>
My solution should be backward compatible as-is. As default, the patch 
assumes every model not having the ability to grant/check for object 
permissions. So it won't get in conflict with those (outdated) models. 
Furthermore it does not modify the existing contrib.auth models in a way 
that would require a new database table schema but only adds a new model 
called ObjectPermission.

Best regards,
Moritz

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/django-developers/-/P1sCKnIJR38J.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Redesign of djangoproject.com?

2012-05-01 Thread Moritz S.
Those templates look very great but I think it's a really bad idea to use 
work without GPL compatible licenses...

Am Mittwoch, 2. Mai 2012 02:14:48 UTC+2 schrieb Daniel Sokolowski:
>
>   Being realistic here we must acknowledge that likely the majority of us 
> are great programmers but not great designers – none of the design proposed 
> did it for me – they were not bad but they weren’t great, and I want epic, 
> I want sexy and I want eye candy.  
>  
> So I say this: it is no shame to use a pre-existing, pre-made  template. 
>  
> I have used http://themeforest.net/?ref=danols successfully in the past - 
> yes it includes my referral link - an added benefit is we can get through 
> the mock up and conversion phases very quickly. Some designs that caught my 
> eye --- please note these are fluid designs hence table and smartphone 
> ready, resize your browser window to see what I mean.
>  
>
> http://themeforest.net/item/spectrum-responsive-business-site-template/full_screen_preview/2035034
>
> http://themeforest.net/item/doctype-claquette-responsive-video-html-template/full_screen_preview/2085780
>
> http://themeforest.net/item/valera-responsive-html-template/full_screen_preview/2194402
>  
>  
>  
> However 
>  *From:* Dana Woodman  
> *Sent:* Saturday, April 28, 2012 3:22 AM
> *To:* django-developers@googlegroups.com 
> *Subject:* Redesign of djangoproject.com?
>  
> So now that Django is being moved to Git/Github (which is awesome!), maybe 
> it would be a good time to think about a revamped home page for the project 
> ala djangoproject.com? 
>  
> Obviously this is no small undertaking and would be potentially 
> contentions as to what would be the proper path, but I feel (and I don't 
> think I'm alone) that djangoproject.com could use a bit of a facelift. 
>  
> I have some idea of my own as to how this could be accomplished and I'm 
> sure there are a ton of others out there with great ideas as well. Maybe we 
> could open up some discussion on this idea? 
>  
> Forgive me if this has been proposed before as I'm new to the group!
>  
> Cheers,
> Dana
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Django developers" group.
> To view this discussion on the web visit 
> https://groups.google.com/d/msg/django-developers/-/g8ngEnVG_EsJ.
> To post to this group, send email to django-developers@googlegroups.com.
> To unsubscribe from this group, send email to 
> django-developers+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/django-developers?hl=en.
> Daniel Sokolowski
> Web Engineer
> Danols Web Engineering
> http://webdesign.danols.com/
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/django-developers/-/NYKLLtL-AuQJ.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: About Class Based views

2015-03-17 Thread Moritz S.
Am Dienstag, 17. März 2015 20:41:53 UTC+1 schrieb poiati:
>
> The problem with CBV is the learning curve. 
>

Totally agree with that!
Personally I really like CBVs and I also write my own subclasses and mixins 
regularly, but I think you'll really have a hard time even writing a simple 
mixin if you have never heard of mro or metaclasses.

 

> On Tue, Mar 17, 2015 at 4:23 PM Gaurav Dadhania  > wrote:
>
>> IMHO, Class-based views — either ones provided by Django or a 3rd party 
>> library or your own —  are an inheritance pattern, like any other design 
>> pattern, use it if it suits your use case. Like a lot of things, there is 
>> no one, right answer. 
>>
>> I've enjoyed using CBVs for CMS-y projects (list products, product 
>> detail, product edit OR list posts, post detail, post edit, etc.) and 
>> functional views for endpoints which don't really have much in common eg: 
>> payment processing, authentication/authorization endpoints, etc. (use 
>> decorators for common simple guard checks, rate limiting, response 
>> serialization/template rendering if you need). YMMV. 
>>
>> Cheers,
>> G
>>
>> On Tue, Mar 17, 2015 at 8:53 PM, Asif Saifuddin > > wrote:
>>
>>> Hi,
>>>
>>> I found this blog post about class based views of django
>>>
>>> http://lukeplant.me.uk/blog/posts/my-approach-to-class-based-views/
>>>
>>>
>>> what do you guys think about?
>>>
>>> Regards
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "Django developers (Contributions to Django itself)" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to django-develop...@googlegroups.com .
>>> To post to this group, send email to django-d...@googlegroups.com 
>>> .
>>> Visit this group at http://groups.google.com/group/django-developers.
>>> To view this discussion on the web visit 
>>> https://groups.google.com/d/msgid/django-developers/e84fd370-044e-456e-b2f3-fd028f41232e%40googlegroups.com
>>>  
>>> 
>>> .
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>  -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Django developers (Contributions to Django itself)" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to django-develop...@googlegroups.com .
>> To post to this group, send email to django-d...@googlegroups.com 
>> .
>> Visit this group at http://groups.google.com/group/django-developers.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/django-developers/CAHgJS%3D_OCgApx6SBdqYCQysLU6MFR%3DganAwYv7LNBE4gzzucaA%40mail.gmail.com
>>  
>> 
>> .
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/19d912c9-3dc2-4a13-a4bd-e2f0354e95b1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.