Skip to content

Commit 9dd6e27

Browse files
authored
feat: add a set_key method on AbstractAPIToken (#521)
Signed-off-by: tdruez <tdruez@aboutcode.org>
1 parent f5b1a72 commit 9dd6e27

2 files changed

Lines changed: 22 additions & 6 deletions

File tree

aboutcode/api_auth/models.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,18 @@ def generate_key(cls):
5757
"""Generate a plain (not encrypted) key."""
5858
return secrets.token_hex(32)
5959

60+
def set_key(self, plain_key):
61+
"""Set the prefix and hashed key from a plain key. Does not save."""
62+
self.prefix = plain_key[: self.PREFIX_LENGTH]
63+
self.key_hash = make_password(plain_key)
64+
6065
@classmethod
6166
def create_token(cls, user):
6267
"""Generate a new token for the given user and return the plain key once."""
6368
plain_key = cls.generate_key()
64-
prefix = plain_key[: cls.PREFIX_LENGTH]
65-
cls.objects.create(
66-
user=user,
67-
prefix=prefix,
68-
key_hash=make_password(plain_key),
69-
)
69+
token = cls(user=user)
70+
token.set_key(plain_key)
71+
token.save()
7072
return plain_key
7173

7274
@classmethod

dje/tests/test_api_auth.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
# See https://aboutcode.org for more information about AboutCode FOSS projects.
77
#
88

9+
from django.contrib.auth.hashers import check_password
910
from django.db.utils import IntegrityError
1011
from django.test import TestCase
1112

@@ -80,3 +81,16 @@ def test_api_auth_api_token_authentication_authenticate_credentials(self):
8081
self.base_user.save()
8182
with self.assertRaisesMessage(AuthenticationFailed, "User inactive or deleted."):
8283
api_token_auth.authenticate_credentials(plain_key=plain_key)
84+
85+
def test_api_auth_api_token_model_set_key(self):
86+
plain_key = APIToken.generate_key()
87+
token = APIToken(user=self.base_user)
88+
token.set_key(plain_key)
89+
90+
self.assertEqual(plain_key[: APIToken.PREFIX_LENGTH], token.prefix)
91+
self.assertEqual(59, len(token.key_hash))
92+
self.assertTrue(check_password(plain_key, token.key_hash))
93+
# set_key must not save the instance
94+
self.assertEqual(0, APIToken.objects.count())
95+
token.save()
96+
self.assertEqual(1, APIToken.objects.count())

0 commit comments

Comments
 (0)