Skip to content

Commit a7e028a

Browse files
use ID str
1 parent cb7c873 commit a7e028a

File tree

8 files changed

+112
-56
lines changed

8 files changed

+112
-56
lines changed

api/specs/web-server/_auth_api_keys.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
from typing import Annotated
22

33
from fastapi import APIRouter, Depends, status
4-
from models_library.api_schemas_webserver.auth import ApiKeyCreate, ApiKeyGet
4+
from models_library.api_schemas_webserver.auth import (
5+
ApiKeyCreateRequest,
6+
ApiKeyCreateResponse,
7+
ApiKeyGet,
8+
)
59
from models_library.generics import Envelope
610
from models_library.rest_error import EnvelopedError
711
from simcore_service_webserver._meta import API_VTAG
@@ -21,9 +25,9 @@
2125
"/auth/api-keys",
2226
operation_id="create_api_key",
2327
status_code=status.HTTP_201_CREATED,
24-
response_model=Envelope[ApiKeyGet],
28+
response_model=Envelope[ApiKeyCreateResponse],
2529
)
26-
async def create_api_key(_body: ApiKeyCreate):
30+
async def create_api_key(_body: ApiKeyCreateRequest):
2731
"""creates API keys to access public API"""
2832

2933

packages/models-library/src/models_library/api_schemas_webserver/auth.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from datetime import timedelta
22
from typing import Annotated, Any
33

4+
from models_library.basic_types import IDStr
45
from pydantic import BaseModel, ConfigDict, Field, HttpUrl, SecretStr
56

67
from ..emails import LowerCaseEmailStr
@@ -51,14 +52,15 @@ class UnregisterCheck(InputSchema):
5152
#
5253

5354

54-
class ApiKeyCreate(BaseModel):
55+
class ApiKeyCreateRequest(BaseModel):
5556
display_name: Annotated[str, Field(..., min_length=3)]
5657
expiration: timedelta | None = Field(
5758
None,
5859
description="Time delta from creation time to expiration. If None, then it does not expire.",
5960
)
6061

6162
model_config = ConfigDict(
63+
from_attributes=True,
6264
json_schema_extra={
6365
"examples": [
6466
{
@@ -73,27 +75,28 @@ class ApiKeyCreate(BaseModel):
7375
"expiration": "24:00:00",
7476
},
7577
]
76-
}
78+
},
7779
)
7880

7981

82+
class ApiKeyCreateResponse(ApiKeyCreateRequest):
83+
id: IDStr
84+
api_base_url: HttpUrl
85+
api_key: str
86+
api_secret: str
87+
88+
8089
class ApiKeyGet(BaseModel):
81-
id: int
90+
id: IDStr
8291
display_name: Annotated[str, Field(..., min_length=3)]
83-
api_base_url: HttpUrl | None = None
84-
api_key: str | None = None
85-
api_secret: str | None = None
8692

8793
model_config = ConfigDict(
88-
populate_by_name=True,
8994
from_attributes=True,
9095
json_schema_extra={
9196
"examples": [
9297
{
93-
"id": 42,
98+
"id": "42",
9499
"display_name": "myapi",
95-
"api_key": "key",
96-
"api_secret": "secret",
97100
},
98101
]
99102
},

services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -412,15 +412,15 @@ paths:
412412
content:
413413
application/json:
414414
schema:
415-
$ref: '#/components/schemas/ApiKeyCreate'
415+
$ref: '#/components/schemas/ApiKeyCreateRequest'
416416
required: true
417417
responses:
418418
'201':
419419
description: Successful Response
420420
content:
421421
application/json:
422422
schema:
423-
$ref: '#/components/schemas/Envelope_ApiKeyGet_'
423+
$ref: '#/components/schemas/Envelope_ApiKeyCreateResponse_'
424424
'404':
425425
description: Not Found
426426
content:
@@ -439,7 +439,9 @@ paths:
439439
in: path
440440
required: true
441441
schema:
442-
type: integer
442+
type: string
443+
minLength: 1
444+
maxLength: 100
443445
title: Api Key Id
444446
responses:
445447
'200':
@@ -465,7 +467,9 @@ paths:
465467
in: path
466468
required: true
467469
schema:
468-
type: integer
470+
type: string
471+
minLength: 1
472+
maxLength: 100
469473
title: Api Key Id
470474
responses:
471475
'204':
@@ -6629,7 +6633,7 @@ components:
66296633
- link
66306634
- widgets
66316635
title: Announcement
6632-
ApiKeyCreate:
6636+
ApiKeyCreateRequest:
66336637
properties:
66346638
display_name:
66356639
type: string
@@ -6646,36 +6650,59 @@ components:
66466650
type: object
66476651
required:
66486652
- display_name
6649-
title: ApiKeyCreate
6650-
ApiKeyGet:
6653+
title: ApiKeyCreateRequest
6654+
ApiKeyCreateResponse:
66516655
properties:
6652-
id:
6653-
type: integer
6654-
title: Id
66556656
display_name:
66566657
type: string
66576658
minLength: 3
66586659
title: Display Name
6659-
api_base_url:
6660+
expiration:
66606661
anyOf:
66616662
- type: string
6662-
maxLength: 2083
6663-
minLength: 1
6664-
format: uri
6663+
format: duration
66656664
- type: 'null'
6665+
title: Expiration
6666+
description: Time delta from creation time to expiration. If None, then
6667+
it does not expire.
6668+
id:
6669+
type: string
6670+
maxLength: 100
6671+
minLength: 1
6672+
title: Id
6673+
api_base_url:
6674+
type: string
6675+
maxLength: 2083
6676+
minLength: 1
6677+
format: uri
66666678
title: Api Base Url
66676679
api_key:
6668-
anyOf:
6669-
- type: string
6670-
- type: 'null'
6680+
type: string
66716681
title: Api Key
66726682
api_secret:
6673-
anyOf:
6674-
- type: string
6675-
- type: 'null'
6683+
type: string
66766684
title: Api Secret
66776685
type: object
66786686
required:
6687+
- display_name
6688+
- id
6689+
- api_base_url
6690+
- api_key
6691+
- api_secret
6692+
title: ApiKeyCreateResponse
6693+
ApiKeyGet:
6694+
properties:
6695+
id:
6696+
type: string
6697+
maxLength: 100
6698+
minLength: 1
6699+
title: Id
6700+
display_name:
6701+
type: string
6702+
minLength: 3
6703+
title: Display Name
6704+
type: object
6705+
required:
66796706
- id
66806707
- display_name
66816708
title: ApiKeyGet
@@ -7504,6 +7531,19 @@ components:
75047531
additionalProperties: false
75057532
type: object
75067533
title: EmptyModel
7534+
Envelope_ApiKeyCreateResponse_:
7535+
properties:
7536+
data:
7537+
anyOf:
7538+
- $ref: '#/components/schemas/ApiKeyCreateResponse'
7539+
- type: 'null'
7540+
error:
7541+
anyOf:
7542+
- {}
7543+
- type: 'null'
7544+
title: Error
7545+
type: object
7546+
title: Envelope[ApiKeyCreateResponse]
75077547
Envelope_ApiKeyGet_:
75087548
properties:
75097549
data:

services/web/server/src/simcore_service_webserver/api_keys/_api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ async def get_api_keys(
6464
async def get_api_key(
6565
app: web.Application,
6666
*,
67-
api_key_id: int,
67+
api_key_id: str,
6868
user_id: UserID,
6969
product_name: ProductName,
7070
) -> ApiKey:
@@ -104,7 +104,7 @@ async def get_or_create_api_key(
104104
async def delete_api_key(
105105
app: web.Application,
106106
*,
107-
api_key_id: int,
107+
api_key_id: str,
108108
user_id: UserID,
109109
product_name: ProductName,
110110
) -> None:

services/web/server/src/simcore_service_webserver/api_keys/_db.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ async def create(
4545
row = await result.first()
4646

4747
return ApiKey(
48-
id=row.id,
48+
id=f"{row.id}", # NOTE: remove after migration to str
4949
display_name=display_name,
5050
expiration=expiration,
5151
api_key=api_key,
@@ -91,7 +91,7 @@ async def get_or_create(
9191
assert row # nosec
9292

9393
return ApiKey(
94-
id=row.id,
94+
id=f"{row.id}", # NOTE: remove after migration to str
9595
display_name=row.display_name,
9696
expiration=row.expires_at,
9797
api_key=row.api_key,
@@ -116,7 +116,7 @@ async def get_all(
116116

117117
return [
118118
ApiKey(
119-
id=row.id,
119+
id=f"{row.id}", # NOTE: remove after migration to str
120120
display_name=row.display_name,
121121
)
122122
for row in rows
@@ -133,8 +133,8 @@ async def get(
133133
) -> ApiKey | None:
134134
async with transaction_context(get_asyncpg_engine(app), connection) as conn:
135135
stmt = sa.select(api_keys).where(
136-
(api_keys.c.user_id == user_id)
137-
& (api_keys.c.id == api_key_id)
136+
(api_keys.c.id == int(api_key_id)) # NOTE: remove after migration to str
137+
& (api_keys.c.user_id == user_id)
138138
& (api_keys.c.product_name == product_name)
139139
)
140140

@@ -143,7 +143,7 @@ async def get(
143143

144144
return (
145145
ApiKey(
146-
id=row.id,
146+
id=f"{row.id}", # NOTE: remove after migration to str
147147
display_name=row.display_name,
148148
expiration=row.expires_at,
149149
)
@@ -158,11 +158,11 @@ async def delete(
158158
*,
159159
user_id: UserID,
160160
product_name: ProductName,
161-
api_key_id: int,
161+
api_key_id: str,
162162
) -> None:
163163
async with transaction_context(get_asyncpg_engine(app), connection) as conn:
164164
stmt = api_keys.delete().where(
165-
(api_keys.c.id == api_key_id)
165+
(api_keys.c.id == int(api_key_id)) # NOTE: remove after migration to str
166166
& (api_keys.c.user_id == user_id)
167167
& (api_keys.c.product_name == product_name)
168168
)

services/web/server/src/simcore_service_webserver/api_keys/_rest.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
import logging
2+
from dataclasses import asdict
23

34
from aiohttp import web
45
from aiohttp.web import RouteTableDef
5-
from models_library.api_schemas_webserver.auth import ApiKeyCreate, ApiKeyGet
6+
from models_library.api_schemas_webserver.auth import (
7+
ApiKeyCreateRequest,
8+
ApiKeyCreateResponse,
9+
ApiKeyGet,
10+
)
11+
from models_library.basic_types import IDStr
612
from models_library.rest_base import StrictRequestParameters
713
from pydantic import TypeAdapter
814
from servicelib.aiohttp import status
@@ -29,7 +35,7 @@
2935

3036

3137
class ApiKeysPathParams(StrictRequestParameters):
32-
api_key_id: int
38+
api_key_id: IDStr
3339

3440

3541
@routes.post(f"/{API_VTAG}/auth/api-keys", name="create_api_key")
@@ -38,7 +44,7 @@ class ApiKeysPathParams(StrictRequestParameters):
3844
@handle_plugin_requests_exceptions
3945
async def create_api_key(request: web.Request):
4046
req_ctx = RequestContext.model_validate(request)
41-
new_api_key = await parse_request_body_as(ApiKeyCreate, request)
47+
new_api_key = await parse_request_body_as(ApiKeyCreateRequest, request)
4248

4349
created_api_key: ApiKey = await _api.create_api_key(
4450
request.app,
@@ -48,8 +54,12 @@ async def create_api_key(request: web.Request):
4854
product_name=req_ctx.product_name,
4955
)
5056

51-
api_key = ApiKeyGet.model_validate(created_api_key)
52-
# api_key.api_base_url = TODO: https://github.com/ITISFoundation/osparc-simcore/issues/6340 # @pcrespov
57+
api_key = ApiKeyCreateResponse.model_validate(
58+
{
59+
**asdict(created_api_key),
60+
"api_base_url": "http://localhost:8000",
61+
} # TODO: https://github.com/ITISFoundation/osparc-simcore/issues/6340 # @pcrespov
62+
)
5363

5464
return envelope_json_response(api_key)
5565

0 commit comments

Comments
 (0)