Problems limiting editors to their own content in Wagtail admin - python

Users that have been assigned to a group with 'add' permissions are able to access, copy, move and add pages created by other users via the admin search or by directly entering the correct path in the browser.
The goal is to prevent users from seeing anything the other users are doing. I had thought it was pretty much implemented.
My page tree looks like this:
Home > Persons > Person Profile > Person Story
Users sign up for an account and are automatically assigned to a custom 'Authors' group. This group has 'add' and 'publish' permissions on the Persons page. The user is responsible for any number of people on their team. With this setup they are able to add a Profile page for each member of their team. Then multiple stories may be added for each person with a profile. Now each Person has subpages of Stories linked to their profile.
I have the page explorer set so users only see their pages:
#hooks.register('construct_explorer_page_queryset')
def show_authors_only_their_articles(parent_page, pages, request):
user_group = request.user.groups.filter(name='Authors').exists()
if user_group:
pages = pages.filter(owner=request.user)
return pages
The image chooser also only displays images uploaded by the user:
#hooks.register('construct_image_chooser_queryset')
def filter_images_by_user(images, request):
images = images.filter(uploaded_by_user=request.user)
return images
And page summary items show only what belongs to the user using similar code.
But during what I thought was going to be final testing, I discovered that a search done using the admin search leads to a list of all available Person Profile and Person Story pages with those search terms. For example if they search for 'John', all Profile and Story page are returned for John. Users may then click on John's Profile page. Once arriving on John's profile page in the explorer they are able to add Stories to John's profile, copy, move or unpublish it! They can do the same with John's stories, minus adding a subpage.
This is a game changer and won't work for us.
I've looked around and see what might be several solutions:
1) Create a similar setup using ModelAdmin but I think I'm going to have the same problem. When searching users will still be able to find and manipulate forbidden content.
2) Create a unique user group for each user as recommended in this post: Wagtail per page user permission
In the second method, after the user is created I would need to programmatically:
1) Create a new user group just for them, maybe using their username.
2) Assign them to the new user group
3) Create a new 'Person' page specific to them and grant them 'add' and 'publish' permissions to it.
The last step because it seems that if I assign them all to the same Person page, they will still be able to add pages to other users Profiles regardless of being in a different user group, since all those different user groups will still have add access to the same Person page.
Ultimately I need to block each user off from what the other users are doing. Your thoughts are much appreciated. It's been years since I've done any programming and I'm still catching up. In the meantime I'm going to start seeing I can come up with.
I think we are pretty close. The system works and flows so well!

I finally figure this one out by searching for instances of GroupPagePermission and GroupCollectionPermission in the Wagtail core package. Was able to piece it together looking at how they did it.
In the models.py of an app I have called 'users' I implemented the django-allauth user_sign_up #receiver. As soon as the user is successfully signed up it runs the below code:
from django.contrib.auth.models import Group, Permission
from django.dispatch import receiver
from allauth.account.signals import user_signed_up
from wagtail.core.models import Page, GroupPagePermission, GroupCollectionPermission, Collection
from article.models import PersonIndexPage
#receiver(user_signed_up)
def create_user_group_and_pages(sender, **kwargs):
"""
When a new user signs up create a unique group and page for them.
Assign it the appropriate permission for admin, page and collection access.
"""
# Grab the new user
user = kwargs['user']
# Create a group object that matches their username
new_group, created = Group.objects.get_or_create(name=user.username)
# Add the new group to the database
user.groups.add(new_group)
# Create new permission to access the wagtail admin
access_admin = Permission.objects.get(codename='access_admin')
# Add the permission to the group
new_group.permissions.add(access_admin)
# Now start creating page access
# First find the homepage
home = Page.objects.get(slug='home').specific
# Create unique PersonIndexPage for the user
person_index_page = PersonIndexPage(title=user.username)
# Add PersonIndexPage to homepage as a child
home.add_child(instance=person_index_page)
# Save new page as first revision
person_index_page.save_revision()
# Create new add GroupPagePermission
GroupPagePermission.objects.create(
group=new_group,
page=person_index_page,
permission_type='add'
)
# Create new GroupCollectionPermission for Profile Images collection
GroupCollectionPermission.objects.create(
group=new_group,
collection=Collection.objects.get(name='Images'),
permission=Permission.objects.get(codename='add_image')
)
Now when a creates a new account a new Index page is created for them that has a unique group created that gives them access to only that Index page and it's child pages. Effectively blocking them from access to any other content on the site. They can still see results to other pages in the admin search but don't have permission to do anything with those results.
Users can log in, create profiles for each person and then as many stories as they want for each person.

Related

Show only users that don't yet exist in the through table

Inside of the __init__ method of a form ProjectUserCreateForm(forms.ModelForm) to add Users to a Project (Project model has a users = models.ManyToManyField(...)) I have
self.fields['users'].queryset = User.objects.filter(company=self.request.user.company)
This way I'm able to show only the users to be added to the Project that belong to the company of the user requesting the page.
This form can be found in
path('<int:pk>/users/create/', views.ProjectUserCreateView.as_view(), name='project-user-create'),
where the <int:pk> is the PK of the Project, and ProjectUserCreateView is a CBV CreateView.
How can I show only the users that belong to the company of the logged in user (this part already works) AND that don't yet exist in the through table (the table based on the ManyToManyField)?
You can get all users that do not yet belong to the request.user's company with:
users_in_company = request.user.company.user_set.all().values(pk).distinct()
users_not_in_company = User.objects.all().exclude(pk__in=list(users_in_company))
Bonus:
If you want to get all users which don't belong to any company:
users_not_in_any_company = users_not_in_company.filter(company__isnull=True) # Equal to User.objects.filter(company__isnull=True), but it doesn't really matter.
Note:
request.user.company.user_set.all()
If you changed the related name of the user to the company, change user_set too ofcourse. I could give you the full example code, but alas, no models.
Edit:
To get all users in a company if the request.user has one:
users = request.user.company.user_set.all()
To filter those users which belong to a specific project:
users.filter(project=my_project)
To get users that don't belong to the project:
users = User.objects.all().exclude(project__pk=self.kwargs['pk'])
To get users that belong to the request.user's company, but not to a project:
request.user.company.user_set.all().exclude(project__pk=self.kwargs['pk'])
Final
User.objects.filter(company=self.request.user.company).exclude(project_users=project_pk)

Check whether user is in django_db or no

I have the django model called "create-chat" and there I write names of people I want to see in a group chat.
So. I created the model, but I don't know how to make a condition whether user is in django_db or no, if so then I want to show them the button "join chat"
And after clicking the button he will be transferred to the url sitename.com/lobby/1
Now I have the view that shows the page /lobby/any_number
First of all I'd to block these pages from users and only if the user is in django_db
He is able to visit the page Lobby/1
ONLY THE lobby/1 not lobby/2
I don't ask you to do it, I just want you to explain me how to do it, or maybe advice me some articles about my problem.
https://i.stack.imgur.com/FQw4Y.jpg
..1). How to block all users for visiting this url sitename.com/1234 <- here goes any number u d liked. ( 4 characters )
So now I blocked all the users for visiting this page, and how now make it visible for a certain users/user?
I am assuming you are storing the information in User object.
usr = User.objects.get(username = whateveristheusername)
if usr is not None:
#User Exist. Click to join chat
else:
#Create User or any other viable functionality

assign edit permission for specific page to specific user

I'm looking for a way in Wagtail 1.8 to give a specific user edit and preview permissions on a specific page once it's created, so I can create the first version of a document for them and then they can add content, tweak, and preview until they're happy with it. One way to do that would have been to assign ownership of the page to them, but that field is read-only. Error is
django.core.exceptions.FieldError: 'owner' cannot be specified
for ArticlePage model form as it is a non-editable field
I can give the user edit and preview permissions for all documents by assigning them to an appropriate Group (e.g., the predefined Editor role) with the right permissions, but I'd rather avoid that if I can.
This can be accomplished using the stock wagtail permissions (http://docs.wagtail.io/en/v1.8/topics/permissions.html):
Just assign the user to a group of his own (so you need to create a new group) and then give edit permissions to that group for the page you mention. The permissions will propagate down the tree but since there are no children on that page it won't matter. Or you can explicitly don't allow the page to be edited to have children by setting subpage_types = [] to your custom page model.

Custom user dashboard in django

I have a system that has two types of users with different privileges, the first user is the admin who can access all objects from the database, the second one is a dealer who can only view information pertaining to them alone.(There are many dealers)
This is how the system iworks: the admin creates a coupon code and issues it to a person (already done) then that person goes to a dealer who is supposed to check if that coupon code exists.
when a dealer logs in he is supposed to be redirected to a dashboard that has the number of items he has sold and to whom. To sell a new item he needs to check if that coupon code exists and if it does then access a form to fill in the item details(I have a model for issued_items)
How would I implement a custom admin page for the dealer without affecting the admin dashboard.
I created a dealer with super-admin and changed his permissions so that he is only able to change specific models, problem is, the models appear with all objects in that model even the ones by other dealers.
I have thought(not tried yet) of creating a view,and a template and redirect login but if i do this then i override the admin
(not so sure)Probably create a new app for the dealer???????
This sounds like a situation where you want the functionality to be loosely coupled to prevent headaches down the road, so I'd go with option 3. Leave the admin for the admins and create a new dealer app for the dealers to go to, with a regular view/model/template that they'll be required to login to see.
I wasn't able to elaborate my question coz am a django newbie, but after a week of trying a lot of different things I found a way out. For the dealers and other non staff users I created a dashboard and also overiding the registration to suit my project.
Its now working fine.

Create separate Django Admin sites and separate permissions

In Django, i have extend the AdminSite class into a UserAdminSite class. But there is a problem: Any Admin who has access to the UserAdminSite would also have a "is_staff = True" status and could therefore access the default admin site for the entire website. How do I separate the access permission for these two admin sites?
Under Site Administration: Add a new "Group"; then select which permissions you want to give any user assigned to that group.
After creating the new group, then assign the user to that group.

Categories

Resources