Well, Django makes it fairly easy to use your own auth and/or
permissions-verification. You may be able to get away with a
decorator. You'll have to create a richer permission model and
associate it with various views & users. You don't detail the
granularity of site-permissions (are they just
read/add/edit/delete, or are there more nuanced permissions; does
a user only have a single type of permission, or can they have a
mask of permissions? and are permission-types site-specific?):
PERM_READ, PERM_WRITE, PERM_DELETE, PERM_ADMIN = range(4)
SITE_PERMISSIONS = (
(PERM_READ, "Read"),
(PERM_WRITE, "Write"),
(PERM_DELETE, "Delete"),
(PERM_ADMIN, "Admin"),
)
class UserCompanies(models.Model):
user = models.ForeignKey(auth.User)
company = models.ForeignKey(Company)
permission = models.IntegerField(choices=SITE_PERMISSIONS)
Then create a decorator for your functions that determines the
permissions for the given user+company combo and asserts that
they are permitted:
def MustHavePermission(*required_perms):
def decorate(f):
def new_f(request, *args, **kwargs):
perms = UserCompanies.objects.filter(
user=request.user,
company=determine_company(request),
)
for perm in required_perms:
perms = perms.filter(permission=perm)
if not perms:
raise Http403("Sorry, Dave, I can't let you do that.")
return f(request, *args, **kwargs)
return new_f
return decorate
You should then be able to wrap your views in decorators like
@MustHavePermission(PERM_READ, PERM_WRITE)
def some_editing_view(request, param, otherparam):
pass
@MustHavePermission(PERM_READ, PERM_WRITE, PERM_DELETE):
def some_delete_view(request, id):
pass
@MustHavePermission(PERM_ADMIN)
def company_admin_view(request, *args, **kwargs):
pass
The above code is untested, but should be fairly close to the
actual implementation.
Things get a lot hairier if each company has their own set of
unique permissions instead of generic global permissions. I.e.
company A has "Frobniculate" and "Gerrywheeze" permissions, while
company B has "Porterloin" and "Munchagrunch" permissions. The
above code assumes that every company has read/write/delete/etc
permissions, and that they're just doled out on a per
user+company basis.
Hope this gives you some ideas on how to go about it.
-tim
I noticed some serious bogosity in this logic (it only passed if
a single permission was required, never if multiple permissions
were required). That innermost function should be something like
def new_f(request, *args, **kwargs):
have = set(
UserCompanies.objects.filter(
user=request.user,
company=determine_company(request)
).values_list("permission", flat=True)
)
if have.issuperset(set(required_perms)):
return f(request, *args, **kwargs)
raise Http403("No way, Jose!")
-tim