Authorization lack of understanding

I developed a prototype of my application in an other Python web framework and struggle to get my head around using Django’s authorization system.

In my prototype I have the tables auth_user, auth_group and auth_membership. auth_user is similar to auth_user in Django. auth_group has fields role and description and auth_membership is an intermediary join table containing user_id and group_id.

I can restrict access to a function using a decorator like this:
@auth.requires(lambda: auth.has_membership(group_id=28, cached=True)

In Django I created an app named accounts and I use a custom user model. This gives me the following tables in my database:

accounts_customuser
accounts_customuser_groups
accounts_customuser_user_permissions

auth_group
auth_group_permissions
auth_permission

All tables are empty.

What I think I understand is that when I have a class Event I can create an auth_group named ‘event’ and add the permissions: Can add event, Can change event, Can delete event and Can view event to that auth_group.

First question: when are the permissions added to the auth_permission table?

Second question: accounts_customuser_groups stores customuser_id and group_id, am I right that this table is the equivalent of the auth_membership table in my prototype?

In my prototype I added three fields to the auth_membership table: backend, expiration_date and frontend.
I added backend and expiration_date to be able to grant and withdraw memberships without the need to delete the membership record from the auth_membership table.
I added frontend to make it possible for the user to disable menu item in case they don’t want to use a function.

Third question: what is the best way to handle temporary memberships in Django?

Fourth question: considering Django’s architecture should I create a separate app to handle the menu.

I look forward to your sharing your thoughts about these issues with me.

Kind regards,

Johanna

This is duplicating what Django already provides. I wouldn’t recommend recreating the wheel.

Again, Django provides a couple of methods suitable for this.

In addition to the has_perm and has_perms methods, there’s also the user_passes_test decorators for creating more flexible solutions.

There’s enough flexibility in there for just about any desired permissions system to be created.

If you use migrations to manage your database, it adds the default permissions.

You’re free to add whatever additional permissions you deem necessary, but how/where that’s done is up to you. (You would likely want to do this as a migration, but you could create them as a fixture and load them directly.)

It looks like it would be - but since you created auth_membership, only you would be able to determine that.

There is no one best way. Everything’s a tradeoff. Some of the factors involve whether you want that membership to expire based on time vs being manually expired - or both.

Membership in a group is defined as an entry in the many-to-many join table between User and Group - adding or removing such an entry does not require either the User or Group table to be modified, so the overhead of adding or removing an entry in that table is quite low.

Generally, I do recommend that as the “default” design for managing membership. However, there are special cases where it may be desirable to add more granular controls - in which case you may wish to add additional columns to that join table.

For example, in one system, we added a “Role name” field. Each person may be a member of multiple groups - and have a different role in each group. Their access rights are determined by their role within a group.

I’m a strong proponent of “one app unless there’s a proven need to do something else.” With one exception, all our projects exist as single apps. I would never look to create something as a different app unless I had a current indication and knowledge of an imminent need to reuse an app in a different project.

So if you’re going to create a menu structure that you’re looking to share across multiple projects, then sure - work on making that an independant app suitable for reuse. But if that’s not the case, I would not enter into this thinking that’s what I’d want to do. It’s easier to add / create a new app than it is to delete one.

Hi Ken,

Thanks for your extensive reply, your answers are very helpful.

I recently switched frameworks and decided to make use of what Django provides out of the box to rebuilt my prototype. If I’m correct your reply encourages me to do just that.

Kind regards,

Johanna

Absolutely! And if you get stuck, we’ll still be here…

Hi,

In my project I don’t need social authentication, however, I wonder whether there are any other reasons to use django-allauth, instead of the built-in auth app.

Kind regards,

Johanna

There is other functionality that you can use in the package, such as associating multiple email addresses with an account. The docs at django-allauth may give you some other ideas.

Hi Ken,

Thanks for your reply and the link to the django-allauth home page.

From what I can judge, at the moment django’s built-in auth suites my needs. I figure that by the time I need django-allauth it’s no problem to add it to my project.

Kind regards,

Johanna

I wasn’t quite sure I knew where you were going with your question, so I didn’t want to confuse the issue unnecessarily - but I have never used django-allauth.
I use either the built-in authentication, or for one specific set of projects, a CAS server.

Thanks, that’s the answer I’d hoped for.

Until I’ve learned enough about Django, so I can really judge for myself, I want to add as few dependencies to my project as possible.