Django: userena edit profile forbidden - python

I've installed django-userena to manage user profiles and everything works fine except new registered users unable to edit/update their profiles and face just blank screen.
If I make the user a superuser then it can change/update profile.
Found that profile_edit view in django-userena decorated with #permission_required_or_403('change_profile', (get_profile_model(), 'user__username', 'username'))
Obviously need to add post_save signal to add necessary permission and nevertheless I was wondering if there any settings like USERENA_ALLOW_UPDATE_PROFILE can anyone help me on this?

Finally digging around django-userena and django-guardian sources I present my output of this little research, so if you want the users to be able to edit their profile you can use the following code
User post save signal which adds 'change_profile' permission to new user objects
#receiver(post_save, sender=User, dispatch_uid='user.created')
def user_created(sender, instance, created, raw, using, **kwargs):
""" Adds 'change_profile' permission to created user objects """
if created:
from guardian.shortcuts import assign
assign('change_profile', instance, instance.get_profile())

For existing users, Just issue this command and the page will be working:
python manage.py check_permissions

Related

How to create Workspaces and manage them for all the users in Django?

I have a complete Login and Registration system in my Django app, that lets me register users, log in users, logout users, change passwords, reset passwords, invite users. I have all the basic functionality.
I want now to have Workspaces for users, as per following points:
There will be a workspace admin of each workspace.
Workspace admins can only add/remove (register/delete) users to his own workspaces.
Users can react to (log in to) only those workspaces to which they have been added.
A superuser (main admin) can manage all workspaces, all workspaces-admins and all users.
How do I accomplish this? You can say this is similar to a Slack thing. I just need a guidelines/roadmap and I will implement it myself.
I have already created a Workspace Model, which looks like below:
class Workspace(models.Model):
name = models.CharField(max_length=254)
created_at = models.DateTimeField(auto_now_add=True)
def make_admin(self, user):
user.is_workspace_admin = True
user.save()
def remove_admin(self, user):
user.is_workspace_admin = False
user.save()
and my User model has following two attributes beside other default Django fields:
class User(AbstractBaseUser, PermissionsMixin):
is_workspace_admin = models.BooleanField(default=True)
workspaces = models.ManyToManyField(Workspace)
Is this approach correct? If not please guide me to the proper way. BTW, using this approach, I can add/assign workspaces to any user, but how will I be able to manage the users logging in their own workspaces and reacting with only their workspaces to which they have been assigned. And also workspaces admins controlling their workspaces’ users etc?
I know about using Groups. So let's say I create all relevant permissions (Can you also tell me how to create permissions?) to add workspace user, remove workspace user, make workspace user a workspace admin, remove workspace admin from workspace adminship etc. and create different Groups and add relevant permissions in each group. Suppose my groups looks like manage_workspace_a to manage (add/remove) the workspace users groups, manage_workspace_admins to manage (add/remove) workspace admins, and default permissions that Django provides for each Model.
So, how will i be able to have the functionality that when a "User A" that has is_superuser=True, makes the is_workspace_admin=True of "User B", then "User B" should automatically gets all the Workspace Admin Permissions. Something like this:
workspace_user = User.objects.get(email="some-email-address")
if request.user.is_superuser:
wordspace_user.permissions.add([Workspace Admin Permissions])
Can somebody explain the whole process with a small code example?
This is a very long, multi-part question but hopefully I can point you in the right direction
I would suggest adding another Many-to-Many field on your User model that handles administrator status. At the moment, you have it set to Boolean flag - so an administrator can either manage all workspaces or none.
Personally, I would reverse the M2M status and put users and administrators on the workspace, rather than on the user model. It's not problematic to have on the user model but I feel it makes more sense to check that the user is in the workspace's permitted users/admins rather than the workspace is in the user's list of workspaces and admin workspaces.
You will need to change your code that adds an administrator to a workspace as you won't want to use a boolean flag:
def make_admin(self, user):
self.administrators.add(user)
As to how you manage the workspace itself, you can just put ORM filters at the very start of your relevant views:
def workspace_view(request, workspace_id):
workspace = get_object_or_404(Workspace, workspace_id)
if request.user not in workspace.users:
return redirect(...)
...the rest of your view
Bear in mind that this doesn't allow administrators in unless they are in the users group - you will either need to add them to users or add another condition to check if they are in administrators.
If you want an overview of all the workspaces in some sort of index/home page, you would just use the m2m reverse accessor which depends on your reverse name (or /relation/_set by default):
def workspaces(request):
workspaces = request.user.workspaces.all()
You can definitely leverage Django's in-built permissions system, I would point you to the documentation because that is a long subject:
https://docs.djangoproject.com/en/4.0/topics/auth/default/#permissions-and-authorization

Signal for the default user registration of django

I would like after creating a user to run a method and create content in other tables of this user that was created but I do not have a user model since I use the default model for the record.
Problems:
-I do not have user model (use the default model)
-I want to choose the newly created user to create the other records in other tables
-I'm not an expert in django (I'm just trying to solve a problem in another area and this would help)
I like the way to do it in this post:
https://simpleisbetterthancomplex.com/tutorial/2016/07/28/how-to-create-django-signals.html
Creating a signals.py to control the signals
You can attach a Django signal to the Django default User models with no problems, for example:
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
The instance argument is the new user recently created into the database, so you can use it as a reference to to add the new tables.
As well, you can put this function in your models.py as well, not necessarily need to create a signals.py

Django How to create a custom user from admin?

So I have this method:
def create_editor(self, email, dob, password):
user = self.create_user(
email,
dob,
accepted_tos=True,
password=password
)
try:
editors = Group.objects.get(name__iexact="Editors")
except Group.DoesNotExist:
editors = Group.objects.create(name="Editors")
editors.permissions.add(Permission.objects.get(codename="can_give_discount")) # add can_give_discount permission
user.groups.add(editors)
user.save()
return user
To create a normal user and then add the user to the editor group
I want to be able to create a manager from the normal django admin.
So in the image below I want another button called Add Manager
At first it looks like what you want to do is create a new Manager model that has a foreignkey to user. Then from the admin side you have the option to first click add user, then navigate to the Manager model and add a manager (where you also supply the user id so they are linked by foreignkey).
However if this is only done to accommodate permissions and groups you can also go to the groups model in django admin.
Spoiler alert, the django admin is not really made for customizations. But there are some think which django is prepared for, checkout the django admin docs here https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#custom-template-options.
It might be a solution for you to extend/override your existing create user template (see here: https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#overriding-vs-replacing-an-admin-template) to e.g. add ad flag that makes the new user an editor or not and you could override the User.objects.create() method to use the flag.
The solution with the least amount of work but 2 steps would be to add an admin action (if you want the button in the detail view: django object action https://github.com/crccheck/django-object-actions) to "upgrade" a normal user to an editor.
Or maybe you could add another choice field extending the User to say whether the added guy is 'Editor' or 'Manager' and on save check if the added user is 'Manager' or 'Editor', and override save to add the new user to the corresponding group.

removing buttons/links in django admin

I have an apps and I am making used of django admin, but my apps does not allow deleting of data and django admin have a delete button/link. I have already removed the delete action.
my question is, how can i remove the delete button/link in admin page in django?
class MyAdmin(ModelAdmin):
def get_actions(self, request):
actions = super(MyAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def has_delete_permission(self, request, obj=None):
return False
If the delete permission is not given the "Delete" button of a single object will disappear. The changelist "action" (select list to apply to objects with checkbox checked) will still be shown because you may have the permission to delete some of the objects. You can remove both with the above code.
CLARIFICATION (for the downvoters): admin checks if the current user has the permission to delete and then shows/hides the button/s accordingly. You wrote "my apps does not allow deleting" so I assumed you took away permissions. A superuser does not get looked up in permissions, superuser always returns "yes I have that permission". If you want the buttons to disappear for superusers, you have to use my above code. For other users just take away the permission as per Secator's answer.
Do not remove or change anything in the admin.
Instead remove user's/group's permission to delete given model. If user does not have the permission to delete, the delete button won't appear at any page related to that model.

Django: Using django.contrib.auth for SAAS ( Users, permissions, etc. )

I'm making a SAAS and I've been asking a slew of questions on here related to the Auth system built in. I'm having trouble understanding the "why" and "how". Primarily I don't understand how it fits in with my SAAS.
I (do) know the following:
You can do this: http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
There are many reasons to use the built in auth system (like security) instead of rolling your own
I (don't) know the following:
class MyUserProfile(models.Model):
"""
Administrator for an Account. Can edit tickets and other stuff.
"""
user = AutoOneToOneField(User, primary_key=True)
account = models.ForeignKey(Account)
dogs_name = models.CharField(max_length=255)
In the previous example, account is just what you'd expect; an entity that's paying to use my software. user is my main concern. Somebody goes to a page and creates a UserProfile with a username and password, etc. When they do this, where does the related User get created? Do I need to create it in my view manually based on the request.POST['username'], etc, and then do
myuserprof = MyUserProfile.create(user=foo_user_just_created, account=foo_account, dogs_name='Spot')
I don't know why but for some reason I feel like I'm missing something. This idea of asking somebody to sign up for an account, and then create a MyUserProfile with a form that asks for the password, username, email, et al, and then in my view creating 2 different objects (MyUserProfile and User) with different parts of the form data. I mean I shouldn't have a User form right? Like I said, I feel like I'm either skipping a step or I'm in the wrong paradigm. I'm not new to Django, but for some reason I have trouble with things that I didn't build (I think it might be a mental problem for real at this point).
Maybe there is a good example of this sort of thing being done on some open source project.
Update: Oops, forgot to mention that in the code above I tried to use AutoOneToOneField from django-annoying, but I have no idea where all the User's attributes get set or how to decide which User object to attach to it. This stuff is driving me crazy.
Also, do I need to use the sites app to do this stuff, and finally does a "super user" have all permissions to everything (I don't want people from Account "Acme" to access account "Microshaft" objects)? Or do they just have all permissions to all views?
Somebody goes to a page and creates a UserProfile with a username and password, etc.
UserProfile doesn't have an username or password field. So it should be somebody goes to a page and create an User. Then, it creates an UserProfile associated to that newly created User.
The question is, how and when do you want this UserProfile instance to be created?
Automatically, whenever a new User is created : use signals, as described in the docs
Automatically, whenever the profile is accessed from an user instance : use AutoOneToOneField, and access the profile using user.userprofile instead of user.get_profile()
Manually. But don't forget an user might have no UserProfile associated yet, so user.get_profile() might raise a DoesNotExist exception.
When they do this, where does the related User get created?
It doesn't. You have to create it explicitely.
This idea of asking somebody to sign up for an account, and then create a MyUserProfile with a form that asks for the password, username, email, et al, and then in my view creating 2 different objects (MyUserProfile and User) with different parts of the form data. I mean I shouldn't have a User form right?
Why not? You want here to create an User and his associated profile in one go, right? You could eventually use directly the POST data, or use a Form to access to the fields, or even better, use 2 ModelForm (one for User, one for UserProfile) that you will process in the same view (maybe this question can help?)
Maybe there is a good example of this sort of thing being done on some open source project.
I suggest you check out django-registration and django-profiles.
Note
You have another way of adding information to an User object, by extending the model itsel. It will allow you to put your extra fields directly in the user model and might be easier for you to understand and use.
I won't dive into details here, have a look at that tutorial for more informations.
Other questions
I tried to use AutoOneToOneField from django-annoying, but I have no idea where all the User's attributes get set or how to decide which User object to attach to it. This stuff is driving me crazy
See above on how to use it. If you feel uncomfortable with it, the best is to follow the documentation, which recommend using a ForeignKey with unique=True in user profiles.
Also, do I need to use the sites app to do this stuff
From the site framework docs : Use it if your single Django installation powers more than one site and you need to differentiate between those sites in some way.
and finally does a "super user" have all permissions to everything (I don't want people from Account "Acme" to access account "Microshaft" objects)?
Again, from the docs, Designates that this user has all permissions without explicitly assigning them. That means that everywhere Django is using the built-in permission system (e.g. default administration pages), a super-user will be authorized.
In views you're writing yourself, or if you tweak some ModelAdmin, it's up to you to decide how you are going to check permissions.

Categories

Resources