• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grafana / django-saml2-auth / 9202044683

23 May 2024 04:05AM UTC coverage: 90.335%. Remained the same
9202044683

Pull #304

github

web-flow
Merge 42a19fe60 into bb893cb8d
Pull Request #304: Bump ruff from 0.4.1 to 0.4.5

916 of 1014 relevant lines covered (90.34%)

6.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/django_saml2_auth/tests/test_user.py
1
"""
7✔
2
Tests for user.py
3
"""
4

5
from typing import Any, Dict, Union
7✔
6

7
import pytest
7✔
8
from django.contrib.auth import get_user_model
7✔
9
from django.contrib.auth.models import Group, User
7✔
10
from django_saml2_auth.exceptions import SAMLAuthError
7✔
11
from django_saml2_auth.user import (
7✔
12
    create_custom_or_default_jwt,
13
    create_new_user,
14
    decode_custom_or_default_jwt,
15
    get_or_create_user,
16
    get_user,
17
    get_user_id,
18
)
19
from jwt.exceptions import PyJWTError
7✔
20
from pytest_django.fixtures import SettingsWrapper
7✔
21

22

23
private_key = """-----BEGIN RSA PRIVATE KEY-----
7✔
24
Proc-Type: 4,ENCRYPTED
25
DEK-Info: DES-EDE3-CBC,098DF8240D954EE0
26

27
uW/IYor+xm5vOLHhDovanTaYWf+N/f+Yae80KJyuXaJ45jVtZBmbhQKy6MIc3pHG
28
QICO4x8esHkOgkzicnjGjaWscTIEy6yZzOzAGsA8t4uLTKix9TM31QQnaUVVWXtn
29
mSJN6rY3Qdudgzss47qcFjS+Rhr+X+u8PB3FhOd6Tgkphpl5Vdkb2K+bcbaXuUlN
30
DUUigoR0+7N5wCJHGKKQd6YRDKvSC4yo0VHbN3Hb55+84m1MGE+pPU8krkmL0u3M
31
7b37nOVXq+4bE/2t0UIVwZyz+pAqAC3tRpSKfe8EN/R2VcfRi4QNrtAkLxYaLWCr
32
SpQA7/qLuEXH1LeUFvDk/SjmCBvNz5vm8hSrj0O5eXN4uIBTg7tdof4KOxozaYKM
33
4SSnfEWjwDwGr/fE6Om5wKrwUjOm3ZTkOHEz5AarVFOsrccLFxSl7+RRKCeIlHSl
34
uAmqBW6pVxS65fwCwocHJ0jVKxEKGz3j++aqmQ0omEhtGWcDcfQMP6sAV1tY/FDd
35
NkVTD/cv23SeHZtjtCxz0W8/Vsqs6U6HMLTb0uJVVdMBiPnTYPKOeACx6GxnwH/e
36
VrjKEy9xqxzdo59lExl06ZBLd9x9u2CAhLqUIlqQu4EtGStpcDuEHj8LY7Y2Jt/G
37
w2IGG72YXrrewCFjgYcvsIjbwnFy/FeDyd5dLK4iT6bzInEm3Eo6MZYImBmD9gkB
38
4U8rXXQwXPwPM+rKwRlbP9v+k5Af29Br6L1T+MAczjThlIdikuCvFoRLQ921De83
39
iFL0LKtbK1sAtmnQBdTYRyWz0MDLJ+7emcXO/NEuK8EogQrLX0wyNXsH3bmXZXzk
40
sBI8gK80e/4hRYdHqgmU8XTI4PTa3tj29hpZa57nG6Ccd2uUULjBiUOBIe6Tm72D
41
DMGqY0wQWOn+wMPLBedOGyJdTWJvDlPpiuboCrr8ughkYIt/d6XynKdejCescJLM
42
t4pwG058EL489Y8O6UAtQYxuj2jrLx7aLxdWxBFjWmKdoDs/p7tOiOcOt6byXybE
43
xpoPG+h9X/GkoH8PaEqL40JlsNcb8dcaUcw2bBUjALnQ38eYETeoUFIsIhZ6nwtq
44
NzJlsWwHtaFue8Eh8/SxQ1ctU5U52E7pNm8vTNmjj1wVgSqht1RSfM/L5WyoqLrO
45
RZTUSqqrDGE31mwpPtEPPUyoGnBroMpJLGoYi03UIn/eSM87gCLBb1Wcsc+BarPf
46
KSSaCE+F3tpIssN1li5nYnfBtVd1hG6f8iCrZo+Ch+N1EVrYFuFSpUTUNSAZiwD2
47
hoRVxyVtDsvIZ+rasbcYSQZyPwhGB6vqjhwdJMIQ6nPyeWZYwPp18alcWRv/UIR7
48
SnEm4NBDCLAXnil2PxCw2c832yTI5/vv8Mi4UvunrUDk2C1ikcwPsPZFMhGYdUxJ
49
O0QirCOeIhRTTsSWxRx5Ac4BOdFjr+Hj8kQd9y/LGdeZ9XjB2AYirTj6zLZynJNa
50
cZU/c743apbLxvv6tvkzcM8hI1pYoYBZ+Eu5aSUqKZaUXxgARKnDX99GUVAXutAG
51
yjwNaiZe1gCKjP7aKZ85+uJZkRvlK/eB/EiNXyhKriKs/vraMeOgtA==
52
-----END RSA PRIVATE KEY-----"""
53

54
passphrase = "123456"
7✔
55

56
unencrypted_private_key = """-----BEGIN RSA PRIVATE KEY-----
7✔
57
MIIEowIBAAKCAQEA5EBnGco/VgirZAUk1qtPR1pkgEMdqBZImTPp6Xf4MDhB7zev
58
veqlXAdaFcvrG4rdO4jHr5snJzJpY52en27a/z2gtQhR9f/05ZjpX9eKCpNt8c/2
59
SDf/P+omEbvbvoUSjkyGeWBacRuHHj6C1voUrl1aKokRfV9GaSkN7+lOxCBCjXFn
60
xEsLlbJZFSsAQPf1282v5SuE2FxMjbs/Xrmjl1Q3h8YsV+vvrRK6/OczPVUb6M4H
61
KHqIpH5UTjP/44Mr5sbanjEEYCOsxiM7Q8JUEYczyjn/o2j8/w0Lms8LB8tnVpxd
62
pwp7QoPVRIr1slYlilP/fL6ZzL5k87XUsi4yGwIDAQABAoIBAASCnUbuLyg1DaXx
63
UBQJ2IwxZhD+woRCxHZ6hyG85COXyP3AHPHkxBW4c3hAykmGCe8WOdPnffORVHHK
64
eIrv9tXaUuWg33W79AvhZKMnMCwbU63WjShKKvoJV208SBBQstgq/PFDDSZ1A8t+
65
MrmqwWPcpl52zOisTEjhrcvS0WKgswFHqveaM4Ss1tR+VNj93r+lKXjsKrUfB1+b
66
T/+9aEjsGiKtfZ+EtUGyanoI/FnVs45ieUeb+WX8x9fJPXyLGeEWSlBQ8RdT1R00
67
VnYY37P+M8ITzwpQzosViClfSPk8ljTkhT+EdictTYVXMCKGUTQOTdw5SRH5l90L
68
YPFS7KECgYEA+QFhPNLWQEcIhEJT5q9Rh73u/jDW76f6UfrxIA59tOtlFPpYvYne
69
P2BPGbDPpdCIf6ypgGITuKjGhd6WbPIrRZz0g1iijlV5nfD+/fzj1ACTMBkBNHd+
70
1ysHjwlRPqJIFB/3Us0BtcYX+4hz1JHA/z7OBbEwKeIZ6uGcN0xw1vECgYEA6qnH
71
xErGnHsSTlVHg6k68RQzeiN/8tWAIGcp4QhlC6p5TeN+X8d25pUuWENNcZZNbC5M
72
hlz8dQ52aB8kVxZkRSOinraUtNoMnVriR3hr4iS9gMVGA+HQR3S5IdnBVnleRUfl
73
qDM/MxL3Ru0sYp4Fr2ndw4aJPUIVyAeTMVLJ0csCgYEA1KrWBqG3tRw17OfNSrev
74
tXSFevnxiKv5wizF5fAacvuc0GbkhbULaStzQ2jcYC0Td5/bALhDSbJ0I3+xEAlg
75
5cqgltGLvG7KORfMYNatKrL3AtxISCxK27B3ezWk+w6U6wNGM6S98ibm8sBe1U1K
76
/XUBdqEXlp3yLsZTqnMR6LECgYBRrl9WuCCB/2TT12NZNOLLX5i7fvfecupyXPZ6
77
2g0yDljC/9jRRgDhKjRDjMm8K/EvIr6IVn2Z0Trt60ke9zBX0JueWzdP7EZPz37M
78
GeKTiO5dkE1atJNnC/4VBlMB4qUpwGj0L0JkaMmh6pR0j0SzVkpW8NF8fTBPvDNE
79
C+ksGQKBgDvsvOc/8OfDVvu3OgUJnACQdKUD56ppYUZ8XLo34vUm2JAXeb5nRAdZ
80
Fo4X5nN+G7W2lV5W5384zfjN3IREeZtg4ZKw0w+vJrhz6bixBIOfMCu0O9TYT11B
81
G2RcH+T0kcs7QbXTY4QrMEYYQj4viihDDo3Ndt5eNJKPz2s+F2h3
82
-----END RSA PRIVATE KEY-----"""
83

84
public_key = """-----BEGIN PUBLIC KEY-----
7✔
85
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5EBnGco/VgirZAUk1qtP
86
R1pkgEMdqBZImTPp6Xf4MDhB7zevveqlXAdaFcvrG4rdO4jHr5snJzJpY52en27a
87
/z2gtQhR9f/05ZjpX9eKCpNt8c/2SDf/P+omEbvbvoUSjkyGeWBacRuHHj6C1voU
88
rl1aKokRfV9GaSkN7+lOxCBCjXFnxEsLlbJZFSsAQPf1282v5SuE2FxMjbs/Xrmj
89
l1Q3h8YsV+vvrRK6/OczPVUb6M4HKHqIpH5UTjP/44Mr5sbanjEEYCOsxiM7Q8JU
90
EYczyjn/o2j8/w0Lms8LB8tnVpxdpwp7QoPVRIr1slYlilP/fL6ZzL5k87XUsi4y
91
GwIDAQAB
92
-----END PUBLIC KEY-----"""
93

94

95
def trigger_change_first_name(user: Union[str, Dict[str, str]]) -> None:
7✔
96
    """Trigger function to change user's first name.
97

98
    Args:
99
        user (Union[str, Dict[str, str]]): User information
100
    """
101
    _user = get_user(user)
7✔
102
    _user.first_name = "CHANGED_FIRSTNAME"
7✔
103
    _user.save()
7✔
104

105

106
def trigger_get_user(user: Dict) -> User:
7✔
107
    """Trigger function to get a user.
108

109
    Args:
110
        user (Union[str, Dict[str, str]]): User information
111
    """
112
    user_model = get_user_model()
7✔
113
    return user_model.objects.get(email=user["username"])
7✔
114

115

116
@pytest.mark.django_db
7✔
117
def test_create_new_user_success(settings: SettingsWrapper):
7✔
118
    """Test create_new_user function to verify if it works and correctly joins the user to the
119
    respective group.
120

121
    Args:
122
        settings (SettingsWrapper): Fixture for django settings
123
    """
124
    settings.SAML2_AUTH = {
7✔
125
        "NEW_USER_PROFILE": {
126
            "USER_GROUPS": ["users"],
127
        }
128
    }
129

130
    # Create a group for the users to join
131
    Group.objects.create(name="users")
7✔
132
    user = create_new_user("test@example.com", "John", "Doe")
7✔
133
    # It can also be email depending on USERNAME_FIELD setting
134
    assert user.username == "test@example.com"
7✔
135
    assert user.is_active is True
7✔
136
    assert user.has_usable_password() is False
7✔
137
    assert user.groups.get(name="users") == Group.objects.get(name="users")
7✔
138

139

140
@pytest.mark.django_db
7✔
141
def test_create_new_user_with_dict_success(settings: SettingsWrapper):
7✔
142
    """Test create_new_user function to verify if it works and correctly joins the user to the
143
    respective group.
144

145
    Args:
146
        settings (SettingsWrapper): Fixture for django settings
147
    """
148
    settings.SAML2_AUTH = {
7✔
149
        "NEW_USER_PROFILE": {
150
            "USER_GROUPS": ["users"],
151
        }
152
    }
153

154
    # Create a group for the users to join
155
    Group.objects.create(name="users")
7✔
156
    params = {"first_name": "test_John", "last_name": "test_Doe"}
7✔
157
    user = create_new_user("user_test@example.com", **params)
7✔
158
    # It can also be email depending on USERNAME_FIELD setting
159
    assert user.username == "user_test@example.com"
7✔
160
    assert user.is_active is True
7✔
161
    assert user.has_usable_password() is False
7✔
162
    assert user.groups.get(name="users") == Group.objects.get(name="users")
7✔
163

164

165
@pytest.mark.django_db
7✔
166
def test_create_new_user_with_dict_success__no_first_and_last_name(settings: SettingsWrapper):
7✔
167
    """Test create_new_user function to verify if it works and correctly joins the user to the
168
    respective group.
169

170
    Args:
171
        settings (SettingsWrapper): Fixture for django settings
172
    """
173
    settings.SAML2_AUTH = {
7✔
174
        "NEW_USER_PROFILE": {
175
            "USER_GROUPS": ["users"],
176
        }
177
    }
178

179
    # Create a group for the users to join
180
    Group.objects.create(name="users")
7✔
181
    # Create a user without first and last name (valid use-case)
182
    user = create_new_user("user_test@example.com")
7✔
183
    # It can also be email depending on USERNAME_FIELD setting
184
    assert user.username == "user_test@example.com"
7✔
185
    assert user.is_active is True
7✔
186
    assert user.has_usable_password() is False
7✔
187
    assert user.groups.get(name="users") == Group.objects.get(name="users")
7✔
188

189

190
@pytest.mark.django_db
7✔
191
def test_create_new_user_no_group_error(settings: SettingsWrapper):
7✔
192
    """Test create_new_user function to verify if it creates the user, but fails to join the user
193
    to the respective group.
194

195
    Args:
196
        settings (SettingsWrapper): Fixture for django settings
197
    """
198
    settings.SAML2_AUTH = {
7✔
199
        "NEW_USER_PROFILE": {
200
            "USER_GROUPS": ["users"],
201
        }
202
    }
203

204
    with pytest.raises(SAMLAuthError) as exc_info:
7✔
205
        create_new_user("test@example.com", "John", "Doe")
7✔
206

207
    assert str(exc_info.value) == "There was an error joining the user to the group."
7✔
208
    assert exc_info.value.extra is not None
7✔
209
    assert exc_info.value.extra["exc_type"] == Group.DoesNotExist
7✔
210

211

212
def test_create_new_user_value_error():
7✔
213
    """Test create_new_user function to verify if it raises an exception upon passing invalid value
214
    as user_id."""
215
    with pytest.raises(SAMLAuthError) as exc_info:
7✔
216
        create_new_user("", "John", "Doe")
7✔
217

218
    assert str(exc_info.value) == "There was an error creating the new user."
7✔
219
    assert exc_info.value.extra["exc_type"] == ValueError
7✔
220

221

222
@pytest.mark.django_db
7✔
223
def test_get_or_create_user_success(settings: SettingsWrapper):
7✔
224
    """Test get_or_create_user function to verify if it creates a new user and joins it to the
225
    correct group based on the given SAML group and its mapping with internal groups.
226

227
    Args:
228
        settings (SettingsWrapper): Fixture for django settings
229
    """
230
    settings.SAML2_AUTH = {
7✔
231
        "ATTRIBUTES_MAP": {
232
            "groups": "groups",
233
        },
234
        "GROUPS_MAP": {"consumers": "users"},
235
    }
236

237
    Group.objects.create(name="users")
7✔
238
    created, user = get_or_create_user(
7✔
239
        {
240
            "username": "test@example.com",
241
            "first_name": "John",
242
            "last_name": "Doe",
243
            "user_identity": {
244
                "user.username": "test@example.com",
245
                "user.first_name": "John",
246
                "user.last_name": "Doe",
247
                "groups": ["consumers"],
248
            },
249
        }
250
    )
251
    assert created
7✔
252
    assert user.username == "test@example.com"
7✔
253
    assert user.is_active is True
7✔
254
    assert user.has_usable_password() is False
7✔
255
    assert user.groups.get(name="users") == Group.objects.get(name="users")
7✔
256

257

258
@pytest.mark.django_db
7✔
259
def test_get_or_create_user_trigger_error(settings: SettingsWrapper):
7✔
260
    """Test get_or_create_user function to verify if it raises an exception in case the CREATE_USER
261
    trigger function is nonexistent.
262

263
    Args:
264
        settings (SettingsWrapper): Fixture for django settings
265
    """
266
    settings.SAML2_AUTH = {
7✔
267
        "TRIGGER": {
268
            "CREATE_USER": "django_saml2_auth.tests.test_user.nonexistent_trigger",
269
        }
270
    }
271

272
    with pytest.raises(SAMLAuthError) as exc_info:
7✔
273
        get_or_create_user(
7✔
274
            {"username": "test@example.com", "first_name": "John", "last_name": "Doe"}
275
        )
276

277
    assert str(exc_info.value) == (
7✔
278
        "module 'django_saml2_auth.tests.test_user' has no attribute 'nonexistent_trigger'"
279
    )
280
    assert exc_info.value.extra is not None
7✔
281
    assert isinstance(exc_info.value.extra["exc"], AttributeError)
7✔
282

283

284
@pytest.mark.django_db
7✔
285
def test_get_user_trigger_error(settings: SettingsWrapper):
7✔
286
    """Test get_user function to verify if it raises an exception in case the GET_USER
287
    trigger function is nonexistent.
288

289
    Args:
290
        settings (SettingsWrapper): Fixture for django settings
291
    """
292
    settings.SAML2_AUTH = {
7✔
293
        "TRIGGER": {
294
            "GET_USER": "django_saml2_auth.tests.test_user.nonexistent_trigger",
295
        }
296
    }
297
    with pytest.raises(SAMLAuthError) as exc_info:
7✔
298
        get_user({"username": "test@example.com", "first_name": "John", "last_name": "Doe"})
7✔
299

300
    assert str(exc_info.value) == (
7✔
301
        "module 'django_saml2_auth.tests.test_user' has no attribute 'nonexistent_trigger'"
302
    )
303
    assert exc_info.value.extra is not None
7✔
304
    assert isinstance(exc_info.value.extra["exc"], AttributeError)
7✔
305

306

307
@pytest.mark.django_db
7✔
308
def test_get_user_trigger(settings: SettingsWrapper):
7✔
309
    settings.SAML2_AUTH = {
7✔
310
        "TRIGGER": {
311
            "GET_USER": "django_saml2_auth.tests.test_user.trigger_get_user",
312
        }
313
    }
314
    user_model = get_user_model()
7✔
315
    user_model.objects.create(username="test_example_com", email="test@example.com")
7✔
316
    created, user = get_or_create_user(
7✔
317
        {"username": "test@example.com", "first_name": "John", "last_name": "Doe"}
318
    )
319
    assert created is False
7✔
320
    assert user.username == "test_example_com"
7✔
321

322

323
@pytest.mark.django_db
7✔
324
def test_get_or_create_user_trigger_change_first_name(settings: SettingsWrapper):
7✔
325
    """Test get_or_create_user function to verify if it correctly triggers the CREATE_USER function
326
    and the trigger updates the user's first name.
327

328
    Args:
329
        settings (SettingsWrapper): Fixture for django settings
330
    """
331
    settings.SAML2_AUTH = {
7✔
332
        "TRIGGER": {
333
            "CREATE_USER": "django_saml2_auth.tests.test_user.trigger_change_first_name",
334
        }
335
    }
336

337
    created, user = get_or_create_user(
7✔
338
        {"username": "test@example.com", "first_name": "John", "last_name": "Doe"}
339
    )
340

341
    assert created
7✔
342
    assert user.username == "test@example.com"
7✔
343
    assert user.first_name == "CHANGED_FIRSTNAME"
7✔
344
    assert user.is_active is True
7✔
345
    assert user.has_usable_password() is False
7✔
346

347

348
@pytest.mark.django_db
7✔
349
def test_get_or_create_user_should_not_create_user(settings: SettingsWrapper):
7✔
350
    """Test get_or_create_user function to verify if it raise an exception while creating a new user
351
    is prohibited by settings.
352

353
    Args:
354
        settings (SettingsWrapper): Fixture for django settings
355
    """
356
    settings.SAML2_AUTH = {
7✔
357
        "CREATE_USER": False,
358
    }
359

360
    with pytest.raises(SAMLAuthError) as exc_info:
7✔
361
        get_or_create_user(
7✔
362
            {"username": "test@example.com", "first_name": "John", "last_name": "Doe"}
363
        )
364

365
    assert str(exc_info.value) == "Cannot create user."
7✔
366
    assert exc_info.value.extra is not None
7✔
367
    assert exc_info.value.extra["reason"] == (
7✔
368
        "Due to current config, a new user should not be created."
369
    )
370

371

372
@pytest.mark.django_db
7✔
373
def test_get_or_create_user_should_not_create_group(settings: SettingsWrapper):
7✔
374
    """Test get_or_create_user function to verify if it doesn't create a group while creating a new
375
    group is prohibited by settings.
376

377
    Args:
378
        settings (SettingsWrapper): Fixture for django settings
379
    """
380
    settings.SAML2_AUTH = {
7✔
381
        "ATTRIBUTES_MAP": {
382
            "groups": "groups",
383
        }
384
    }
385

386
    Group.objects.create(name="users")
7✔
387
    created, user = get_or_create_user(
7✔
388
        {
389
            "username": "test@example.com",
390
            "first_name": "John",
391
            "last_name": "Doe",
392
            "user_identity": {
393
                "user.username": "test@example.com",
394
                "user.first_name": "John",
395
                "user.last_name": "Doe",
396
                "groups": ["users", "consumers"],
397
            },
398
        }
399
    )
400
    assert created
7✔
401
    assert user.username == "test@example.com"
7✔
402
    assert user.is_active is True
7✔
403
    assert user.has_usable_password() is False
7✔
404
    assert Group.objects.get(name="users") in user.groups.all()
7✔
405
    assert Group.objects.filter(name="consumers").exists() is False
7✔
406
    assert user.groups.filter(name="consumers").exists() is False
7✔
407

408

409
@pytest.mark.django_db
7✔
410
def test_get_or_create_user_should_create_group(settings: SettingsWrapper):
7✔
411
    """Test get_or_create_user function to verify if it creates a group when creating a new
412
    group is enabled by settings.
413

414
    Args:
415
        settings (SettingsWrapper): Fixture for django settings
416
    """
417
    settings.SAML2_AUTH = {
7✔
418
        "CREATE_GROUPS": True,
419
        "ATTRIBUTES_MAP": {
420
            "groups": "groups",
421
        },
422
    }
423

424
    Group.objects.create(name="users")
7✔
425
    created, user = get_or_create_user(
7✔
426
        {
427
            "username": "test@example.com",
428
            "first_name": "John",
429
            "last_name": "Doe",
430
            "user_identity": {
431
                "user.username": "test@example.com",
432
                "user.first_name": "John",
433
                "user.last_name": "Doe",
434
                "groups": ["users", "consumers"],
435
            },
436
        }
437
    )
438
    assert created
7✔
439
    assert user.username == "test@example.com"
7✔
440
    assert user.is_active is True
7✔
441
    assert user.has_usable_password() is False
7✔
442
    assert user.groups.get(name="users") == Group.objects.get(name="users")
7✔
443
    assert user.groups.get(name="consumers") == Group.objects.get(name="consumers")
7✔
444

445

446
@pytest.mark.django_db
7✔
447
def test_get_or_create_user_should_create_and_map_group(settings: SettingsWrapper):
7✔
448
    """Test get_or_create_user function to verify if it creates a group when creating a new
449
    group is enabled by settings. It also verifies if the group is mapped correctly from
450
    "consumers" in SAML attributes to "customers" in Django.
451

452
    Args:
453
        settings (SettingsWrapper): Fixture for django settings
454
    """
455
    settings.SAML2_AUTH = {
7✔
456
        "CREATE_GROUPS": True,
457
        "ATTRIBUTES_MAP": {
458
            "groups": "groups",
459
        },
460
        "GROUPS_MAP": {
461
            "consumers": "customers",
462
        },
463
    }
464

465
    Group.objects.create(name="users")
7✔
466
    created, user = get_or_create_user(
7✔
467
        {
468
            "username": "test@example.com",
469
            "first_name": "John",
470
            "last_name": "Doe",
471
            "user_identity": {
472
                "user.username": "test@example.com",
473
                "user.first_name": "John",
474
                "user.last_name": "Doe",
475
                "groups": ["users", "consumers"],
476
            },
477
        }
478
    )
479
    assert created
7✔
480
    assert user.username == "test@example.com"
7✔
481
    assert user.is_active is True
7✔
482
    assert user.has_usable_password() is False
7✔
483
    assert user.groups.get(name="users") == Group.objects.get(name="users")
7✔
484
    assert user.groups.get(name="customers") == Group.objects.get(name="customers")
7✔
485

486

487
def test_get_user_id_success():
7✔
488
    """Test get_user_id function to verify if it correctly returns the user_id based on the
489
    User.USERNAME_FIELD."""
490
    assert get_user_id({"username": "test@example.com"}) == "test@example.com"
7✔
491
    assert get_user_id("test@example.com") == "test@example.com"
7✔
492

493

494
@pytest.mark.django_db
7✔
495
def test_get_user_success():
7✔
496
    """Test get_user function by first creating a new user and then trying to fetch it."""
497
    create_new_user("test@example.com", "John", "Doe")
7✔
498
    user_1 = get_user({"username": "test@example.com"})
7✔
499
    user_2 = get_user("test@example.com")
7✔
500

501
    assert user_1.username == "test@example.com"
7✔
502
    assert user_2.username == "test@example.com"
7✔
503
    assert user_1 == user_2
7✔
504

505

506
@pytest.mark.parametrize(
7✔
507
    "saml2_settings",
508
    [
509
        {"JWT_ALGORITHM": "HS256", "JWT_SECRET": "secret"},
510
        {
511
            "JWT_ALGORITHM": "RS256",
512
            "JWT_PRIVATE_KEY": private_key,
513
            "JWT_PRIVATE_KEY_PASSPHRASE": passphrase,
514
            "JWT_PUBLIC_KEY": public_key,
515
        },
516
        {
517
            "JWT_ALGORITHM": "RS256",
518
            "JWT_PRIVATE_KEY": unencrypted_private_key,
519
            "JWT_PUBLIC_KEY": public_key,
520
        },
521
    ],
522
)
523
def test_create_and_decode_jwt_token_success(
7✔
524
    settings: SettingsWrapper, saml2_settings: Dict[str, Any]
525
):
526
    """Test create_jwt_token and decode_jwt_token functions by verifying if the newly created
527
    JWT token using is valid.
528

529
    Args:
530
        settings (SettingsWrapper): Fixture for django settings
531
        saml2_settings (Dict[str, Any]): Fixture for SAML2 settings
532
    """
533
    settings.SAML2_AUTH = saml2_settings
7✔
534

535
    jwt_token = create_custom_or_default_jwt("test@example.com")
7✔
536
    user_id = decode_custom_or_default_jwt(jwt_token)
7✔
537
    assert user_id == "test@example.com"
7✔
538

539

540
@pytest.mark.parametrize(
7✔
541
    "saml2_settings,error_msg",
542
    [
543
        ({"JWT_ALGORITHM": None}, "Cannot encode/decode JWT token. Specify an algorithm."),
544
        (
545
            {"JWT_ALGORITHM": "HS256", "JWT_SECRET": None},
546
            "Cannot encode/decode JWT token. Specify a secret.",
547
        ),
548
        (
549
            {
550
                "JWT_ALGORITHM": "HS256",
551
                "JWT_SECRET": "",
552
            },
553
            "Cannot encode/decode JWT token. Specify a secret.",
554
        ),
555
        (
556
            {"JWT_ALGORITHM": "HS256", "JWT_PRIVATE_KEY": "-- PRIVATE KEY --"},
557
            "Cannot encode/decode JWT token. Specify a secret.",
558
        ),
559
        (
560
            {
561
                "JWT_ALGORITHM": "RS256",
562
            },
563
            "Cannot encode/decode JWT token. Specify a private key.",
564
        ),
565
        (
566
            {"JWT_ALGORITHM": "RS256", "JWT_SECRET": "A_SECRET_PHRASE"},
567
            "Cannot encode/decode JWT token. Specify a private key.",
568
        ),
569
    ],
570
)
571
def test_create_jwt_token_with_incorrect_jwt_settings(
7✔
572
    settings: SettingsWrapper, saml2_settings: Dict[str, str], error_msg: str
573
):
574
    """Test create_jwt_token function by trying to create a JWT token with incorrect settings.
575

576
    Args:
577
        settings (SettingsWrapper): Fixture for django settings
578
        saml2_settings (Dict[str, str]): Fixture for SAML2 settings
579
        error_msg (str): Expected error message
580
    """
581
    settings.SAML2_AUTH = saml2_settings
7✔
582

583
    with pytest.raises(SAMLAuthError) as exc_info:
7✔
584
        create_custom_or_default_jwt("test@example.com")
7✔
585

586
    assert str(exc_info.value) == error_msg
7✔
587

588

589
@pytest.mark.parametrize(
7✔
590
    "saml2_settings,error_msg",
591
    [
592
        ({"JWT_ALGORITHM": None}, "Cannot encode/decode JWT token. Specify an algorithm."),
593
        (
594
            {"JWT_ALGORITHM": "HS256", "JWT_SECRET": None},
595
            "Cannot encode/decode JWT token. Specify a secret.",
596
        ),
597
        (
598
            {
599
                "JWT_ALGORITHM": "HS256",
600
                "JWT_SECRET": "",
601
            },
602
            "Cannot encode/decode JWT token. Specify a secret.",
603
        ),
604
        (
605
            {"JWT_ALGORITHM": "HS256", "JWT_PRIVATE_KEY": "-- PRIVATE KEY --"},
606
            "Cannot encode/decode JWT token. Specify a secret.",
607
        ),
608
        (
609
            {"JWT_ALGORITHM": "HS256", "JWT_SECRET": "secret", "JWT_EXP": -60},
610
            "Cannot decode JWT token.",
611
        ),
612
        (
613
            {
614
                "JWT_ALGORITHM": "RS256",
615
            },
616
            "Cannot encode/decode JWT token. Specify a public key.",
617
        ),
618
        (
619
            {"JWT_ALGORITHM": "RS256", "JWT_SECRET": "A_SECRET_PHRASE"},
620
            "Cannot encode/decode JWT token. Specify a public key.",
621
        ),
622
    ],
623
)
624
def test_decode_jwt_token_with_incorrect_jwt_settings(
7✔
625
    settings: SettingsWrapper, saml2_settings: Dict[str, str], error_msg: str
626
):
627
    """Test decode_jwt_token function by trying to create a JWT token with incorrect settings.
628

629
    Args:
630
        settings (SettingsWrapper): Fixture for django settings
631
        saml2_settings (Dict[str, str]): Fixture for SAML2 settings
632
        error_msg (str): Expected error message
633
    """
634
    settings.SAML2_AUTH = saml2_settings
7✔
635

636
    with pytest.raises(SAMLAuthError) as exc_info:
7✔
637
        decode_custom_or_default_jwt("WHATEVER")
7✔
638

639
    assert str(exc_info.value) == error_msg
7✔
640

641

642
def test_decode_jwt_token_failure():
7✔
643
    """Test decode_jwt_token function by passing an invalid JWT token (None, in this case)."""
644
    with pytest.raises(SAMLAuthError) as exc_info:
7✔
645
        decode_custom_or_default_jwt(None)
7✔
646

647
    assert str(exc_info.value) == "Cannot decode JWT token."
7✔
648
    assert isinstance(exc_info.value.extra["exc"], PyJWTError)
7✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc