1+ import logging
12import uuid
23from datetime import timedelta
34from uuid import uuid5
45
5- from aiocache import cached # type: ignore[import-untyped]
66from fastapi import FastAPI
77from models_library .products import ProductName
88from models_library .projects import ProjectID
99from models_library .projects_nodes_io import NodeID
10- from models_library .rpc .webserver .auth .api_keys import ApiKeyGet
10+ from models_library .rpc .webserver .auth .api_keys import generate_unique_api_key
1111from models_library .users import UserID
1212
1313from ._api_auth_rpc import create_api_key as rpc_create_api_key
1616_EXPIRATION_AUTO_KEYS = timedelta (weeks = 4 )
1717
1818
19+ _logger = logging .getLogger (__name__ )
20+
21+
1922def create_unique_api_name_for (
2023 product_name : ProductName ,
2124 user_id : UserID ,
@@ -27,50 +30,17 @@ def create_unique_api_name_for(
2730 return f"__auto_{ uuid5 (uuid .NAMESPACE_DNS , f'{ product_name } /{ user_id } /{ project_id } /{ node_id } ' )} "
2831
2932
30- # NOTE: Uses caching to prevent multiple calls to the external service
31- # when 'create_user_api_key' or 'create_user_api_secret' are invoked.
32- def _cache_key (fct , * _ , ** kwargs ):
33- return f"{ fct .__name__ } _{ kwargs ['product_name' ]} _{ kwargs ['user_id' ]} _{ kwargs ['project_id' ]} _{ kwargs ['node_id' ]} "
34-
35-
36- @cached (ttl = 3 , key_builder = _cache_key )
37- async def _create_for (
38- app : FastAPI ,
39- * ,
40- product_name : ProductName ,
41- user_id : UserID ,
42- project_id : ProjectID ,
43- node_id : NodeID ,
44- ) -> ApiKeyGet :
45- display_name = create_unique_api_name_for (
46- product_name , user_id , project_id , node_id
47- )
48- return await rpc_create_api_key (
49- app ,
50- user_id = user_id ,
51- product_name = product_name ,
52- display_name = display_name ,
53- expiration = _EXPIRATION_AUTO_KEYS ,
54- )
55-
56-
5733async def create_user_api_key (
58- app : FastAPI ,
34+ app : FastAPI , # pylint: disable=unused-argument
5935 product_name : ProductName ,
6036 user_id : UserID ,
6137 project_id : ProjectID ,
6238 node_id : NodeID ,
6339) -> str :
64- data = await _create_for (
65- app ,
66- product_name = product_name ,
67- user_id = user_id ,
68- project_id = project_id ,
69- node_id = node_id ,
40+ # NOTE: Given the display name, the API key is deterministically generated
41+ return generate_unique_api_key (
42+ create_unique_api_name_for (product_name , user_id , project_id , node_id )
7043 )
71- assert data .api_key # nosec
72- assert isinstance (data .api_key , str ) # nosec
73- return data .api_key
7444
7545
7646async def create_user_api_secret (
@@ -80,12 +50,16 @@ async def create_user_api_secret(
8050 project_id : ProjectID ,
8151 node_id : NodeID ,
8252) -> str :
83- data = await _create_for (
53+ display_name = create_unique_api_name_for (
54+ product_name , user_id , project_id , node_id
55+ )
56+ _logger .debug ("Creating API key for %s" , display_name )
57+ data = await rpc_create_api_key (
8458 app ,
85- product_name = product_name ,
8659 user_id = user_id ,
87- project_id = project_id ,
88- node_id = node_id ,
60+ product_name = product_name ,
61+ display_name = display_name ,
62+ expiration = _EXPIRATION_AUTO_KEYS ,
8963 )
9064 assert data .api_secret # nosec
9165 assert isinstance (data .api_secret , str ) # nosec
0 commit comments