@@ -58,13 +58,9 @@ def default_token_expiry():
58
58
59
59
def default_create_token (token_model , user , serializer ):
60
60
"""Generate a default value for the token."""
61
- token = token_model .objects .filter (user = user , name = '' , revoked = False )
62
-
63
- if token .exists ():
64
- return token .first ()
65
-
66
- else :
67
- return token_model .objects .create (user = user , name = '' )
61
+ # this implementation only works for inventree API tokens
62
+ assert token_model is ApiToken
63
+ return ApiToken .get_or_create (user = user , token_name = '' )
68
64
69
65
70
66
class ApiToken (AuthToken , InvenTree .models .MetadataMixin ):
@@ -94,6 +90,28 @@ def generate_key(cls, prefix='inv-'):
94
90
95
91
return prefix + str (AuthToken .generate_key ()) + suffix
96
92
93
+ @classmethod
94
+ def get_or_create (cls , user , token_name : str ):
95
+ """Gets or creates a valid API token for the given user. Only call from authenticated context."""
96
+ token_name = cls .sanitize_name (token_name )
97
+ today = datetime .date .today ()
98
+
99
+ # Find existing token, which has not expired
100
+ token = cls .objects .filter (
101
+ user = user , name = token_name , revoked = False , expiry__gte = today
102
+ ).first ()
103
+
104
+ # create new token if no matching one exists.
105
+ if not token :
106
+ token = cls .objects .create (user = user , name = token_name )
107
+ logger .info (
108
+ "Created new API token for user '%s' (name='%s')" ,
109
+ user .username ,
110
+ token_name ,
111
+ )
112
+
113
+ return token
114
+
97
115
# Override the 'key' field - force it to be unique
98
116
key = models .CharField (
99
117
default = default_token ,
0 commit comments