I would like to be able to check if the user accessing a page is a specific user.
For instance, when a user accesses the "Edit Post" page on my blog app, I want to ensure that the user is the author of the post.
Currently, I check that the user accessing '/Blog/Edit//' has the blog.change_post permission.
However, if a second user (who also has that permission) were to enter the URL to change someone else's post, they would pass that permission check and be able to edit someone else's post.
What I want is a @user_passes_test function that check's the user object accessing the view against the author attribute of the post.
#/Blog/urls.py
urlpatterns = [
...
path('Edit/<int:pk>', views.BlogEdit, name='BlogEdit'),
...
]
#/Blog/views.py
@permission_required('blog.change_post', login_url='/Portal/login')
def BlogEdit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect('/Blog', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'Blog/Edit.html', {'form': form})
You can add an extra filter to your get_object_or_404
:
@permission_required('blog.change_post', login_url='/Portal/login')
def BlogEdit(request, pk):
post = get_object_or_404(Post, pk=pk, author=request.user)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
form.save()
return redirect('/Blog', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'Blog/Edit.html', {'form': form})
Here author
is the hypothetical ForeignKey
from Post
to the user model. It is possible that the name is different, but the idea is still the same.
This thus means that in case the pk
is the pk
of a Blog
for which request.user
is not the author
, then we will have a 404 response.
The advantage of filtering here, is that we use a single query for the filtering. We will not (lazily) load the author
to check if it is the same as the logged in user.
Note:
post = form.save(commit=False)
andpost.save()
are equivalent topost = form.save()
(so withcommit=True
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With