I am trying to use django-userena with django-oscar. So far, it is working well, except for when I try to link a non-staff user to a fulfillment partner (linking to a staff user works fine). Here is the error I am getting:
Traceback:
File "/Users/shafiquejamal/allfiles/htdocs/venvs/av4env/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
112. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/shafiquejamal/allfiles/htdocs/venvs/av4env/lib/python2.7/site-packages/django/db/transaction.py" in inner
371. return func(*args, **kwargs)
File "/Users/shafiquejamal/allfiles/htdocs/venvs/av4env/lib/python2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
22. return view_func(request, *args, **kwargs)
File "/Users/shafiquejamal/allfiles/htdocs/venvs/av4env/lib/python2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
22. return view_func(request, *args, **kwargs)
File "/Users/shafiquejamal/allfiles/htdocs/venvs/av4env/lib/python2.7/site-packages/django/views/generic/base.py" in view
69. return self.dispatch(request, *args, **kwargs)
File "/Users/shafiquejamal/allfiles/htdocs/venvs/av4env/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
87. return handler(request, *args, **kwargs)
File "/Users/shafiquejamal/allfiles/htdocs/venvs/av4env/lib/python2.7/site-packages/oscar/apps/dashboard/partners/views.py" in post
219. if self.link_user(user, partner):
File "/Users/shafiquejamal/allfiles/htdocs/venvs/av4env/lib/python2.7/site-packages/oscar/apps/dashboard/partners/views.py" in link_user
206. content_type__app_label='partner')
File "/Users/shafiquejamal/allfiles/htdocs/venvs/av4env/lib/python2.7/site-packages/django/db/models/manager.py" in get
151. return self.get_queryset().get(*args, **kwargs)
File "/Users/shafiquejamal/allfiles/htdocs/venvs/av4env/lib/python2.7/site-packages/django/db/models/query.py" in get
310. self.model._meta.object_name)
Exception Type: DoesNotExist at /en/store/dashboard/partners/1/users/380/link/
Exception Value: Permission matching query does not exist.
It seems that the problem is in oscar.apps.dashboards.partners.views
:
class PartnerUserLinkView(generic.View):
def link_user(self, user, partner):
"""
Links a user to a partner, and adds the dashboard permission if needed.
Returns False if the user was linked already; True otherwise.
"""
if partner.users.filter(pk=user.pk).exists():
return False
partner.users.add(user)
if not user.is_staff:
dashboard_access_perm = Permission.objects.get(
codename='dashboard_access',
content_type__app_label='partner')
user.user_permissions.add(dashboard_access_perm)
return True
Permission.objects.get
does not return an object. This is because the check_permissions
command in django-userena
checks the following permissions:
ASSIGNED_PERMISSIONS = {
'profile':
(('view_profile', 'Can view profile'),
('change_profile', 'Can change profile'),
('delete_profile', 'Can delete profile')),
'user':
(('change_user', 'Can change user'),
('delete_user', 'Can delete user'))
}
which, does not include dashboard_access
. I tried to add another profile permission ('dashboard_access', _('Can access dashboard')),),
to ASSIGNED_PERMISSIONS.profile
, but that didn't work - I still got the same error above. I think that the problem is that even if dashboard_access
is one of the permissions, the link_user
method specifies content_type__app_label='partner'
, but content_type__app_label
is never partner
(partner
is one of the oscar apps). So I guess I should override the check_permissions
management command to check permissions in away that accommodates django-oscar. My questions are:
How do I override or extend the check_permissions
management command without touching the code in my virtual environment? I consulted https://docs.djangoproject.com/en/1.6/howto/custom-management-commands/, and started by copying the managers.py code from userena
to a management/commands
folder in my project, but got a command not implemented error.
How do I modify check permissions to refer to an app label of 'partner'?
Am I even going about this correctly? Maybe I misunderstand how or whether oscar
and userena
can work together.
I think I was overthinking the problem. It seems that the unlink_user
method deletes the permission object that the link_user
method looks for, which is one reason that the latter method cannot find the permission object (the other reason being that the object might not have been created in the first place). I hacked together a (not really?) solution by overriding the link_user
method as follows:
# yourproject/dashboard/partners/views.py
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import Permission
from oscar.apps.dashboard.partners.views import PartnerUserLinkView as CorePartnerUserLinkView
class PartnerUserLinkView(CorePartnerUserLinkView):
def link_user(self, user, partner):
"""
Links a user to a partner, and adds the dashboard permission if needed.
Returns False if the user was linked already; True otherwise.
"""
if partner.users.filter(pk=user.pk).exists():
return False
partner.users.add(user)
if not user.is_staff:
try:
dashboard_access_perm = Permission.objects.get(
codename='dashboard_access',
content_type__app_label='partner')
except:
try:
my_content_type = ContentType.objects.get(name='partner',
app_label='partner',model='partner')
except:
my_content_type = ContentType.objects.create(name='partner',
app_label='partner',model='partner')
my_content_type.save()
my_permission = Permission.objects.create(name='partner',
content_type=my_content_type,codename='dashboard_access')
my_permission.save()
dashboard_access_perm = Permission.objects.get(
codename='dashboard_access',
content_type__app_label='partner')
user.user_permissions.add(dashboard_access_perm)
return True
This works for me - with this hack, I can now link non-staff users to fulfillment partners.