Skip to content

Commit

Permalink
[feature:api] Allow creating users with a verified email via REST API
Browse files Browse the repository at this point in the history
  • Loading branch information
nemesifier authored Mar 14, 2024
1 parent e6b2d7a commit f0e785a
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 18 deletions.
6 changes: 6 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,12 @@ Create User
POST /api/v1/users/user/
**Note**: Passing ``true`` to the optional
``is_verified`` field allows creating users with
their email address flagged as verified. This will
also skip sending the verification link to their
email address.

Get User detail
^^^^^^^^^^^^^^^

Expand Down
14 changes: 11 additions & 3 deletions openwisp_users/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,15 @@ def to_representation(self, instance):


class SuperUserListSerializer(BaseSuperUserSerializer):
email_verified = serializers.BooleanField(default=False, write_only=True)

class Meta:
model = User
fields = (
'id',
'username',
'email',
'email_verified',
'password',
'first_name',
'last_name',
Expand All @@ -248,9 +251,10 @@ def validate_email(self, value):
def create(self, validated_data):
group_data = validated_data.pop('groups', None)
org_user_data = validated_data.pop('organization_users', None)
password = validated_data.pop('password')
email_verified = validated_data.pop('email_verified', False)

instance = self.instance or self.Meta.model(**validated_data)
password = validated_data.pop('password')
instance.set_password(password)
instance.full_clean()
instance.save()
Expand All @@ -267,13 +271,17 @@ def create(self, validated_data):

if instance.email:
try:
EmailAddress.objects.add_email(
email = EmailAddress.objects.add_email(
self.context['request'],
user=instance,
email=instance.email,
confirm=True,
confirm=not email_verified,
signup=True,
)
if email_verified:
email.primary = True
email.verified = True
email.save(update_fields=['primary', 'verified'])
except Exception as e:
logger.exception(
'Got exception {} while sending '
Expand Down
57 changes: 42 additions & 15 deletions openwisp_users/tests/test_api/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.contrib import auth
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.core import mail
from django.test import TestCase
from django.urls import reverse
from openwisp_utils.tests import AssertNumQueriesSubTestMixin
Expand Down Expand Up @@ -500,21 +501,47 @@ def test_get_user_list_api(self):
self.assertEqual(r.data['count'], 1)

def test_create_user_list_api(self):
self.assertEqual(User.objects.count(), 1)
path = reverse('users:user_list')
data = {
'username': 'tester',
'email': '[email protected]',
'password': 'password123',
}
r = self.client.post(path, data, content_type='application/json')
self.assertEqual(r.status_code, 201)
self.assertEqual(User.objects.count(), 2)
self.assertEqual(r.data['groups'], [])
self.assertEqual(r.data['organization_users'], [])
self.assertEqual(r.data['username'], 'tester')
self.assertEqual(r.data['email'], '[email protected]')
self.assertEqual(r.data['is_active'], True)
with self.subTest('create user, standard case'):
mail_sent = len(mail.outbox)
self.assertEqual(User.objects.count(), 1)
path = reverse('users:user_list')
data = {
'username': 'tester',
'email': '[email protected]',
'password': 'password123',
}
r = self.client.post(path, data, content_type='application/json')
self.assertEqual(r.status_code, 201)
self.assertEqual(User.objects.count(), 2)
self.assertEqual(r.data['groups'], [])
self.assertEqual(r.data['organization_users'], [])
self.assertEqual(r.data['username'], 'tester')
self.assertEqual(r.data['email'], '[email protected]')
self.assertEqual(r.data['is_active'], True)
# ensure email address object is created but not verified
user = User.objects.filter(email=data['email']).first()
self.assertIsNotNone(user)
self.assertEqual(user.emailaddress_set.count(), 1)
email = user.emailaddress_set.first()
self.assertFalse(email.verified)
self.assertFalse(email.primary)
# ensure the email verification link is sent
self.assertEqual(len(mail.outbox), mail_sent + 1)

with self.subTest('create user and flag email as verified'):
mail_sent = len(mail.outbox)
User.objects.filter(email=data['email']).delete()
data['email_verified'] = True
r = self.client.post(path, data, content_type='application/json')
self.assertEqual(r.status_code, 201)
user = User.objects.filter(email=data['email']).first()
self.assertIsNotNone(user)
self.assertEqual(user.emailaddress_set.count(), 1)
email = user.emailaddress_set.first()
self.assertTrue(email.verified)
self.assertTrue(email.primary)
# ensure the email verification link is not sent
self.assertEqual(len(mail.outbox), mail_sent)

def test_post_with_empty_form_api_400(self):
path = reverse('users:user_list')
Expand Down

0 comments on commit f0e785a

Please sign in to comment.