mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-11-20 13:36:05 -05:00
feat: approve users, edit users through manage users page (#1383)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import User
|
||||
@@ -5,20 +6,7 @@ from .models import User
|
||||
|
||||
class UserAdmin(admin.ModelAdmin):
|
||||
search_fields = ["email", "username", "name"]
|
||||
exclude = (
|
||||
"user_permissions",
|
||||
"title",
|
||||
"password",
|
||||
"groups",
|
||||
"last_login",
|
||||
"is_featured",
|
||||
"location",
|
||||
"first_name",
|
||||
"last_name",
|
||||
"media_count",
|
||||
"date_joined",
|
||||
"is_active",
|
||||
)
|
||||
exclude = ["user_permissions", "title", "password", "groups", "last_login", "is_featured", "location", "first_name", "last_name", "media_count", "date_joined", "is_active", "is_approved"]
|
||||
list_display = [
|
||||
"username",
|
||||
"name",
|
||||
@@ -33,5 +21,10 @@ class UserAdmin(admin.ModelAdmin):
|
||||
list_filter = ["is_superuser", "is_editor", "is_manager"]
|
||||
ordering = ("-date_added",)
|
||||
|
||||
if settings.USERS_NEEDS_TO_BE_APPROVED:
|
||||
list_display.append("is_approved")
|
||||
list_filter.append("is_approved")
|
||||
exclude.remove("is_approved")
|
||||
|
||||
|
||||
admin.site.register(User, UserAdmin)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
|
||||
from files.methods import is_mediacms_manager
|
||||
|
||||
@@ -25,6 +26,7 @@ class UserForm(forms.ModelForm):
|
||||
"advancedUser",
|
||||
"is_manager",
|
||||
"is_editor",
|
||||
"is_approved",
|
||||
# "allow_contact",
|
||||
)
|
||||
|
||||
@@ -44,6 +46,11 @@ class UserForm(forms.ModelForm):
|
||||
self.fields.pop("advancedUser")
|
||||
self.fields.pop("is_manager")
|
||||
self.fields.pop("is_editor")
|
||||
|
||||
if not settings.USERS_NEEDS_TO_BE_APPROVED or not is_mediacms_manager(user):
|
||||
if "is_approved" in self.fields:
|
||||
self.fields.pop("is_approved")
|
||||
|
||||
if user.socialaccount_set.exists():
|
||||
# for Social Accounts do not allow to edit the name
|
||||
self.fields["name"].widget.attrs['readonly'] = True
|
||||
|
||||
17
users/migrations/0002_user_is_approved.py
Normal file
17
users/migrations/0002_user_is_approved.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 5.1.6 on 2025-09-19 14:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('users', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='is_approved',
|
||||
field=models.BooleanField(blank=True, db_index=True, default=False, null=True, verbose_name='Is approved'),
|
||||
),
|
||||
]
|
||||
@@ -29,6 +29,7 @@ class User(AbstractUser):
|
||||
name = models.CharField("full name", max_length=250, db_index=True)
|
||||
date_added = models.DateTimeField("date added", default=timezone.now, db_index=True)
|
||||
is_featured = models.BooleanField("Is featured", default=False, db_index=True)
|
||||
is_approved = models.BooleanField("Is approved", default=False, null=True, blank=True, db_index=True)
|
||||
|
||||
title = models.CharField("Title", max_length=250, blank=True)
|
||||
advancedUser = models.BooleanField("advanced user", default=False, db_index=True)
|
||||
|
||||
@@ -22,7 +22,7 @@ class UserSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
read_only_fields = (
|
||||
read_only_fields = [
|
||||
"date_added",
|
||||
"is_featured",
|
||||
"uid",
|
||||
@@ -31,8 +31,8 @@ class UserSerializer(serializers.ModelSerializer):
|
||||
"is_editor",
|
||||
"is_manager",
|
||||
"email_is_verified",
|
||||
)
|
||||
fields = (
|
||||
]
|
||||
fields = [
|
||||
"description",
|
||||
"date_added",
|
||||
"name",
|
||||
@@ -45,7 +45,11 @@ class UserSerializer(serializers.ModelSerializer):
|
||||
"is_editor",
|
||||
"is_manager",
|
||||
"email_is_verified",
|
||||
)
|
||||
]
|
||||
|
||||
if settings.USERS_NEEDS_TO_BE_APPROVED:
|
||||
fields.append("is_approved")
|
||||
read_only_fields.append("is_approved")
|
||||
|
||||
|
||||
class UserDetailSerializer(serializers.ModelSerializer):
|
||||
|
||||
@@ -205,6 +205,12 @@ class UserList(APIView):
|
||||
operation_description='Paginated listing of users',
|
||||
)
|
||||
def get(self, request, format=None):
|
||||
if settings.CAN_SEE_MEMBERS_PAGE == "editors" and not is_mediacms_editor(request.user):
|
||||
raise PermissionDenied("You do not have permission to view this page.")
|
||||
|
||||
if settings.CAN_SEE_MEMBERS_PAGE == "admins" and not request.user.is_superuser:
|
||||
raise PermissionDenied("You do not have permission to view this page.")
|
||||
|
||||
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
|
||||
paginator = pagination_class()
|
||||
users = User.objects.filter()
|
||||
@@ -213,11 +219,57 @@ class UserList(APIView):
|
||||
if name:
|
||||
users = users.filter(Q(name__icontains=name) | Q(username__icontains=name))
|
||||
|
||||
if settings.USERS_NEEDS_TO_BE_APPROVED:
|
||||
is_approved = request.GET.get("is_approved")
|
||||
if is_approved == "true":
|
||||
users = users.filter(is_approved=True)
|
||||
elif is_approved == "false":
|
||||
users = users.filter(Q(is_approved=False) | Q(is_approved__isnull=True))
|
||||
|
||||
page = paginator.paginate_queryset(users, request)
|
||||
|
||||
serializer = UserSerializer(page, many=True, context={"request": request})
|
||||
return paginator.get_paginated_response(serializer.data)
|
||||
|
||||
@swagger_auto_schema(
|
||||
request_body=openapi.Schema(
|
||||
type=openapi.TYPE_OBJECT,
|
||||
required=["username", "password", "email", "name"],
|
||||
properties={
|
||||
"username": openapi.Schema(type=openapi.TYPE_STRING),
|
||||
"password": openapi.Schema(type=openapi.TYPE_STRING),
|
||||
"email": openapi.Schema(type=openapi.TYPE_STRING, format=openapi.FORMAT_EMAIL),
|
||||
"name": openapi.Schema(type=openapi.TYPE_STRING),
|
||||
},
|
||||
),
|
||||
tags=["Users"],
|
||||
operation_summary="Create user",
|
||||
operation_description="Create a new user. Only for managers.",
|
||||
responses={201: UserSerializer},
|
||||
)
|
||||
def post(self, request, format=None):
|
||||
if not is_mediacms_manager(request.user):
|
||||
raise PermissionDenied("You do not have permission to create users.")
|
||||
|
||||
username = request.data.get("username")
|
||||
password = request.data.get("password")
|
||||
email = request.data.get("email")
|
||||
name = request.data.get("name")
|
||||
|
||||
if not all([username, password, email, name]):
|
||||
return Response({"detail": "username, password, email, and name are required."}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
if User.objects.filter(username=username).exists():
|
||||
return Response({"detail": "A user with that username already exists."}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
if User.objects.filter(email=email).exists():
|
||||
return Response({"detail": "A user with that email already exists."}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
user = User.objects.create_user(username=username, password=password, email=email, name=name)
|
||||
|
||||
serializer = UserSerializer(user, context={"request": request})
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
class UserDetail(APIView):
|
||||
""""""
|
||||
@@ -284,27 +336,36 @@ class UserDetail(APIView):
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
@swagger_auto_schema(
|
||||
manual_parameters=[],
|
||||
manual_parameters=[
|
||||
openapi.Parameter(name='action', in_=openapi.IN_FORM, type=openapi.TYPE_STRING, required=True, description="action to perform ('change_password' or 'approve_user')"),
|
||||
openapi.Parameter(name='password', in_=openapi.IN_FORM, type=openapi.TYPE_STRING, required=False, description="new password (if action is 'change_password')"),
|
||||
],
|
||||
tags=['Users'],
|
||||
operation_summary='Xto_be_written',
|
||||
operation_description='to_be_written',
|
||||
operation_summary='Update user details',
|
||||
operation_description='Allows a user to change their password. Allows a manager to approve a user.',
|
||||
)
|
||||
def put(self, request, uid, format=None):
|
||||
# ADMIN
|
||||
user = self.get_user(uid)
|
||||
def put(self, request, username, format=None):
|
||||
user = self.get_user(username)
|
||||
if isinstance(user, Response):
|
||||
return user
|
||||
|
||||
if not request.user.is_superuser:
|
||||
return Response({"detail": "not allowed"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
action = request.data.get("action")
|
||||
if action == "feature":
|
||||
user.is_featured = True
|
||||
|
||||
if action == "change_password":
|
||||
# Permission to edit user is already checked by self.get_user -> self.check_object_permissions
|
||||
password = request.data.get("password")
|
||||
if not password:
|
||||
return Response({"detail": "Password is required"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
user.set_password(password)
|
||||
user.save()
|
||||
elif action == "unfeature":
|
||||
user.is_featured = False
|
||||
|
||||
elif action == "approve_user":
|
||||
if not is_mediacms_manager(request.user):
|
||||
raise PermissionDenied("You do not have permission to approve users.")
|
||||
user.is_approved = True
|
||||
user.save()
|
||||
else:
|
||||
return Response({"detail": "Invalid action"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
serializer = UserDetailSerializer(user, context={"request": request})
|
||||
return Response(serializer.data)
|
||||
|
||||
Reference in New Issue
Block a user