Add site permission to user in Django/Mezzanine - django

I have no clue how to add permission with this model in Mezzanine:
class SitePermission(models.Model):
"""
Permission relationship between a user and a site that's
used instead of ``User.is_staff``, for admin and inline-editing
access.
"""
user = models.OneToOneField(user_model_name, verbose_name=_("Author"),
related_name="%(class)ss")
sites = models.ManyToManyField("sites.Site", blank=True,
verbose_name=_("Sites"))
class Meta:
verbose_name = _("Site permission")
verbose_name_plural = _("Site permissions")
How can I add a specific user in a view to a specific site? I have not found any documentation regarding this.

Here's how to do it:
from mezzanine.core.models import SitePermission
siteperms = SitePermission.objects.create(user=user)
siteperms.sites.add(site)

Related

Django restrict user access to related objects

I am writing an application which allows a user to authenticate and view objects only within their organisation. For a generic.ListView, I can restrict access with the code below:
models.py
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
organisation = models.ForeignKey('Organisation', null=True, on_delete=models.CASCADE)
class Organisation(models.Model):
name = models.CharField(max_length=255, unique=True, null=False, verbose_name="Name")
views.py
class OrganisationList(LoginRequiredMixin, generic.ListView):
model = Organisation
def get_queryset(self):
return Organisation.objects.filter(id=self.request.user.organisation.id)
In addition to this view the user will access forms, an API and the django admin interface that require this restriction.
For example, user Brett belongs to Kids Incorporated. When he logs in to the admin panel he can currently also see ACME Corporation but should not be able to do so.
I have looked at ModelManager interface but I am not sure how to get the user request and override
Is there a way to run write one query for all views (DRY) that so that a user will only see their own organisation?
There is a way.
Install django-crequest package: https://github.com/Alir3z4/django-crequest#installing
Create a model.Manager within models.py and override the get_queryset method
models.py
...
from crequest.middleware import CrequestMiddleware
class UserOrganisationManager(models.Manager):
def get_queryset(self):
request = CrequestMiddleware.get_request()
return super().get_queryset().filter(id=request.user.organisation.id)
class Organisation(models.Model):
name = models.CharField(max_length=255,
unique=True, null=False, verbose_name="Name")
...
objects = UserOrganisationManager()
You should use groups and permissions for that, a group per organization. And only members of some group can read (the permission) objects within their organization group.
This will allow you to have more that one organization for a user or vice-versa. And of course no require any other dependency.

Django AUTHENTICATION AND AUTHORIZATION groups and permissions want to create verified users

Hi Djangonauts,
I am new to Django please forgive any silly mistake in logic or code.
Intro:
I am building a web app in which members can write posts on a topic and offer courses on that topic. Example A member can write a blog about doing a wheelie on a bicycle and offer courses on that.
What I want:
I want members who want to offer courses to be verified. Example: The member has to fill a form with their details like...
name, address, and photo ID. Plus pay a charge of $9.99 to get verified. After admin (I in this case) checks if everything is good I will approve them. and then they will be "Verified Members" and be able to offer courses
What I have so far: Right now members can offer courses as there is no verified clause
class Event(models.Model):
user = models.ForeignKey(User, related_name='seller')
post = models.ForeignKey(Post, related_name='course')
price = models.DecimalField(max_digits=6, decimal_places=2)
stock = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(35)])
date = models.DateField()
time_from = models.TimeField()
time_to = models.TimeField()
event_types = (
('1', 'Webinar'),
('2', 'Actual Meet'),
)
event_choice = models.CharField(max_length=1, choices=event_types)
def get_absolute_url(self):
return reverse('posts:single', kwargs={'username': self.user.username,
'slug': self.post.slug})
def __str__(self):
return 'Meet for ' + self.post.title
How I plan to do it: I was planning to add a group in Django's admin AUTHENTICATION AND AUTHORIZATION
Home › Authentication and Authorization › Groups › Add group
Name: Verified
Permissions: Chosen permissions
event| event| Can add event
event| event| Can change event
event| event| Can delete event
Now what do I do from here?: Have I done things right so far, How do I take it from here. Do I create a model called verified and add forms.py to have members verified. How do permissions come in the picture.
My monkey patch (not a part of the question, for #Ojas Kale )
class Contact(models.Model):
user_from = models.ForeignKey(User, related_name='supporter')
user_to = models.ForeignKey(User, related_name='leader')
def __str__(self):
return '{} follows {}'.format(self.user_from, self.user_to)
User.add_to_class('following',
models.ManyToManyField('self', through=Contact, related_name='followers', symmetrical=False))
One way to go about it is adding a is_verified column in the user. There are various ways for doing this. but extending from abstractUser is probably the most straightforward and suitable in your case, since the class django.contrib.auth.models.AbstractUser provides the full implementation of the default User as an abstract model.
in your app_name.models.py create user class like this.
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
is_verified = models.BooleanField(default=False)
in your settingps.py
AUTH_USER_MODEL = 'app_name.User'
notice how app_name is used.
Now you can add as many attributes as you want as well.
By defaul is_verified is set to False, As soon as admin approves (verifies) the user change it to True.
Hope this helps.

How to implement different permission in Django?

I have a model Payment with fields: date_created, comment, description, amount. Each payment belongs to User.
class Payment(models.Model):
author = models.ForeignKey('auth.User')
amount = models.FloatField(max_length=10)
description = models.CharField(max_length=128)
created_date = models.DateTimeField(
default=datetime.now())
comment = models.TextField(max_length=256)
def __str__(self):
return self.description
Now I need to implement different roles for User: regular (can CRUD his payments), manager (can CRUD users), admin (can CRUD everything). So, the main question is how to implement this roles for users during registration (further it can't be changed). I also need to be able to set this role during registration via api (django rest framework).
Finally decided to user Django built-in Permissions
#e.g.
content_type = ContentType.objects.get_for_model(User)
permission = Permission.objects.get(codename='admin_can_manage_users')
user.user_permissions.add(permission)

Restrict access to a Class Based View based on the request user and view to be rendered

Here's the scene:
profiles/models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, primary_key = True)
birthdate = models.DateTimeField(blank=True)
def __unicode__(self):
return unicode(self.user)
class SpecialProfile(models.Model):
user = models.OneToOneField(User, primary_key = True)
...
# additional fields here
def __unicode__(self):
return unicode(self.user)
class SpecialProfileURLs(models.Model):
profile = models.OneToOneField(SpecialProfile, primary_key = True)
... #some more URLs
homepage_url = models.URLField(blank = True)
def __unicode__(self):
return unicode(self.profile)
class SpecialProfileImages(models.Model):
profile = models.OneToOneField(SpecialProfile, primary_key = True)
img1 = models.ImageField(blank = True, upload_to='profiles/')
img2 = models.ImageField(blank = True, upload_to='profiles/')
img3 = models.ImageField(blank = True, upload_to='profiles/')
def __unicode__(self):
return unicode(self.profile)`
profiles/views.py
class PublicProfileView(DetailView):
template_name = "public_profile.html"
model = User
class PrivateProfileView(DetailView):
template_name = 'profile/profile2.html'
context_object_name = "profile"
model = User
pk_field = 'pk'
profiles/urls.py
urlpatterns = patterns("",
url(r'^$', 'mysite.views.home', name='home'), # give me nothing? just take me home!
url(r'^(?P<pk>\d+)/$', PrivateProfileView.as_view(), name="profile"),
url(r'^(?P<username>\w+)/$', ProfileRedirectView.as_view(), name="profile_redirect"),
url(r"^edit/(?P<profile_id>\w+)/$", EditProfileView.as_view(), name="profile_update_form"),
)
Here's the problem:
I want to be able to test whether the user giving the request is the same as the ID used to access a profile. I would intercept at a GET request and check, but django gets mad when I do that (probably because it's a DetailView). Is there a recommended/ non-hackish way to be sure only the user to whom this profile belongs can access it? If not, then the user sending the request should be redirected to the PublicProfileView.
It seems bad form to answer my first question but thankfully Alex helped me find exactly what I was looking for:
Per object permissions.
There is a package on GitHub, django-guardian which allows me to set specific permissions to any User or Group for a single model instance.
The documentation is quite thorough.
Your solution is a combination of some different things:
1) Use the PermissionsRequiredMixin from django-braces. This is an easy way to add Permission functionality to class-based views. Documentation on the PermissionsRequiredMixin can be found here.
2) Create your own permission. The Django documentation on that is here. Include this permission in your class based view.
Here's a related answer on SO that addresses the same problem in a function-based view. You can use it to help create your permission.

Django multiple User profiles/subprofiles

I am trying to create an intranet/extranet with internal/external user-specific profiles, with a common generic profile. I've looked at several answers on this site, but none specifically address what I'm looking to do. Below are the (stripped down) files I have so far.
What's the best way to create a profile model, with subprofiles for each user type? I'm trying not to require a custom authentication backend if at all possible.
https://gist.github.com/1196077
I have a solution I dont Know if its the best but see it:
models.py
from django.db import models
from django.contrib.auth.models import User
class Pollster(models.Model):
"""docstring for Polister"""
user = models.OneToOneField(User, related_name = 'polister', unique=True)
cedule = models.CharField( max_length = 100 )
class Respondent(models.Model):
""" """
born_date = models.DateField( verbose_name=u'fecha de nacimiento' )
cedule = models.CharField( max_length = 100, verbose_name=u'cedula' )
comunity = models.CharField( max_length = 100, verbose_name=u'comunidad')
phone = models.CharField( max_length = 50, verbose_name=u'telefono')
sanrelation = models.TextField( verbose_name =u'Relacion con SAN')
user = models.OneToOneField( User, related_name = 'respondent')
I create a MiddleWare: so
i create middleware.py
from django.contrib.auth.models import User
from encuestas.models import Pollster, Respondent
class RequestMiddleWare(object):
"""docstring for """
def process_request(self,request):
if isPollster(request.user):
request.user.userprofile = Pollster.objects.get( user = request.user.id)
elif isRespondent(request.user):
request.user.userprofile = Respondent.objects.get(user = request.user.id)
return None
def isPollster(user):
return Pollster.objects.filter(user=user.id).exists()
def isRespondent(user):
return Respondent.objects.filter(user=user.id).exists()
and you need to configure settings.py for the middleware:
add to MIDDLEWARE_CLASSES atribute:
'encuestas.middleware.RequestMiddleWare'
encuestas is my_app name
middleware is the Middleware file
RequestMiddleWare is the middleware class
You need a combination of storing additional information about users and model inheritance.
Basically, you'll need the generic User models we all know and either love or hate, and then you need a generic profile model that is your AUTH_PROFILE_MODULE setting.
That profile model will be a top-level model, with model subclasses for internal and extrernal users. You probably don't want an abstract model in this case since you'll need a common profile table to load user profiles from with User.get_profile().
So...I think the major thing you want to change is to make your Associate, External, etc. models inherit from your Profile model.
Please check this excellent article that describes how to inherit from the User class and add your own information. For me, at least, this clearly seems to be the way to go: http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
Using this method one should easily be able to add multiple user types to their Django application.