@@ -128,7 +128,7 @@ def renew_key(
128128 with self .engine .connect () as conn :
129129 t = self .t_apitoken
130130 resp = conn .execute (
131- select (t .c ["is_active" , "expiration_date " ]).where (
131+ select (t .c ["is_active" , "config " ]).where (
132132 (t .c .api_key == self .__hash (api_key )) & (t .c .user_id == user_id )
133133 )
134134 ).first ()
@@ -139,10 +139,12 @@ def renew_key(
139139 status_code = HTTP_404_NOT_FOUND , detail = "API key not found"
140140 )
141141
142+ old_active = resp [0 ]
143+ old_config = resp [1 ]
142144 response_lines = []
143145
144146 # Previously revoked key. Issue a text warning and reactivate it.
145- if not resp [ 0 ] :
147+ if not old_active :
146148 response_lines .append (
147149 "This API key was revoked and has been reactivated."
148150 )
@@ -167,6 +169,10 @@ def renew_key(
167169 LOGGER .debug ("Sync user info of `user_id` with KeyCLoak" )
168170 kc_info = self .kcutil .get_user_info (user_id )
169171
172+ # Merge the old config with the new valuesread from the oauth2 attributes.
173+ # NOTE: the new values have higher priority than the old config.
174+ new_config = old_config | kc_info .attributes
175+
170176 conn .execute (
171177 t .update ()
172178 .where (t .c .api_key == self .__hash (api_key ))
@@ -176,6 +182,7 @@ def renew_key(
176182 latest_sync_date = datetime .now (UTC ),
177183 is_active = True ,
178184 expiration_date = parsed_expiration_date ,
185+ config = new_config ,
179186 )
180187 )
181188
@@ -248,11 +255,18 @@ def check_key(self, api_key: str) -> dict | None:
248255 if latest_sync_date .utcoffset () is None :
249256 latest_sync_date = latest_sync_date .replace (tzinfo = timezone .utc )
250257
258+ # If the apikey info has not been updated from keycloak for a long time
251259 if settings .keycloak_sync_freq > 0 and datetime .now (UTC ) > (
252260 latest_sync_date + timedelta (seconds = settings .keycloak_sync_freq )
253261 ):
254262 LOGGER .debug (f"Sync user info of `{ response ['user_id' ]} ` with KeyCLoak" )
255263 kc_info = self .kcutil .get_user_info (response ["user_id" ])
264+
265+ # Merge the old config with the new valuesread from the oauth2
266+ # attributes.
267+ # NOTE: the new values have higher priority than the old config.
268+ new_config = response ["config" ] | kc_info .attributes
269+
256270 # Update the database
257271 conn .execute (
258272 t .update ()
@@ -261,12 +275,14 @@ def check_key(self, api_key: str) -> dict | None:
261275 user_active = kc_info .is_enabled ,
262276 iam_roles = kc_info .roles ,
263277 latest_sync_date = datetime .now (UTC ),
278+ config = new_config ,
264279 )
265280 )
266281 conn .commit ()
267282
268283 response ["user_active" ] = kc_info .is_enabled
269284 response ["iam_roles" ] = kc_info .roles
285+ response ["config" ] = new_config
270286
271287 if not response ["user_active" ]:
272288 # If user is not active anymore
0 commit comments