Skip to content

Commit 9dc5a02

Browse files
GitHKAndrei Neagu
and
Andrei Neagu
authored
🐛 Fix webserver storage OpenAPI schema (#4426)
Co-authored-by: Andrei Neagu <[email protected]>
1 parent 03dc50a commit 9dc5a02

File tree

6 files changed

+170
-81
lines changed

6 files changed

+170
-81
lines changed

api/specs/webserver/openapi-storage.yaml

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,7 @@ paths:
144144
- required: true
145145
schema:
146146
title: File Id
147-
anyOf:
148-
- pattern: ^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$
149-
type: string
150-
- pattern: ^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$
151-
type: string
147+
type: string
152148
name: file_id
153149
in: path
154150
responses:
@@ -178,11 +174,7 @@ paths:
178174
- required: true
179175
schema:
180176
title: File Id
181-
anyOf:
182-
- pattern: ^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$
183-
type: string
184-
- pattern: ^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$
185-
type: string
177+
type: string
186178
name: file_id
187179
in: path
188180
- required: false
@@ -216,11 +208,7 @@ paths:
216208
- required: true
217209
schema:
218210
title: File Id
219-
anyOf:
220-
- pattern: ^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$
221-
type: string
222-
- pattern: ^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$
223-
type: string
211+
type: string
224212
name: file_id
225213
in: path
226214
- required: true
@@ -269,11 +257,7 @@ paths:
269257
- required: true
270258
schema:
271259
title: File Id
272-
anyOf:
273-
- pattern: ^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$
274-
type: string
275-
- pattern: ^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$
276-
type: string
260+
type: string
277261
name: file_id
278262
in: path
279263
responses:
@@ -297,11 +281,7 @@ paths:
297281
- required: true
298282
schema:
299283
title: File Id
300-
anyOf:
301-
- pattern: ^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$
302-
type: string
303-
- pattern: ^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$
304-
type: string
284+
type: string
305285
name: file_id
306286
in: path
307287
responses:
@@ -324,11 +304,7 @@ paths:
324304
- required: true
325305
schema:
326306
title: File Id
327-
anyOf:
328-
- pattern: ^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$
329-
type: string
330-
- pattern: ^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$
331-
type: string
307+
type: string
332308
name: file_id
333309
in: path
334310
requestBody:
@@ -361,11 +337,7 @@ paths:
361337
- required: true
362338
schema:
363339
title: File Id
364-
anyOf:
365-
- pattern: ^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$
366-
type: string
367-
- pattern: ^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$
368-
type: string
340+
type: string
369341
name: file_id
370342
in: path
371343
- required: true

api/specs/webserver/scripts/openapi_storage.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99

1010
from enum import Enum
11+
from typing import TypeAlias
1112

1213
from fastapi import FastAPI, status
1314
from models_library.api_schemas_storage import (
@@ -21,7 +22,7 @@
2122
TableSynchronisation,
2223
)
2324
from models_library.generics import Envelope
24-
from models_library.projects_nodes_io import LocationID, StorageFileID
25+
from models_library.projects_nodes_io import LocationID
2526
from pydantic import AnyUrl, ByteSize
2627
from simcore_service_webserver.storage.schemas import DatasetMetaData, FileMetaData
2728

@@ -32,6 +33,13 @@
3233
]
3334

3435

36+
# NOTE: storage generates URLs that contain double encoded
37+
# slashes, and when applying validation via `StorageFileID`
38+
# it raises an error. Before `StorageFileID`, `str` was the
39+
# type used in the OpenAPI specs.
40+
StorageFileIDStr: TypeAlias = str
41+
42+
3543
@app.get(
3644
"/storage/locations",
3745
response_model=list[DatasetMetaData],
@@ -96,7 +104,7 @@ async def get_files_metadata_dataset(location_id: LocationID, dataset_id: str):
96104
summary="Get File Metadata",
97105
operation_id="get_file_metadata",
98106
)
99-
async def get_file_metadata(location_id: LocationID, file_id: StorageFileID):
107+
async def get_file_metadata(location_id: LocationID, file_id: StorageFileIDStr):
100108
...
101109

102110

@@ -109,7 +117,7 @@ async def get_file_metadata(location_id: LocationID, file_id: StorageFileID):
109117
)
110118
async def download_file(
111119
location_id: LocationID,
112-
file_id: StorageFileID,
120+
file_id: StorageFileIDStr,
113121
link_type: LinkType = LinkType.PRESIGNED,
114122
):
115123
"""Returns a presigned link"""
@@ -124,7 +132,7 @@ async def download_file(
124132
)
125133
async def upload_file(
126134
location_id: LocationID,
127-
file_id: StorageFileID,
135+
file_id: StorageFileIDStr,
128136
file_size: ByteSize | None,
129137
link_type: LinkType = LinkType.PRESIGNED,
130138
is_directory: bool = False,
@@ -139,7 +147,7 @@ async def upload_file(
139147
operation_id="delete_file",
140148
summary="Deletes File",
141149
)
142-
async def delete_file(location_id: LocationID, file_id: StorageFileID):
150+
async def delete_file(location_id: LocationID, file_id: StorageFileIDStr):
143151
...
144152

145153

@@ -149,7 +157,7 @@ async def delete_file(location_id: LocationID, file_id: StorageFileID):
149157
tags=TAGS,
150158
operation_id="abort_upload_file",
151159
)
152-
async def abort_upload_file(location_id: LocationID, file_id: StorageFileID):
160+
async def abort_upload_file(location_id: LocationID, file_id: StorageFileIDStr):
153161
"""Asks the server to abort the upload and revert to the last valid version if any"""
154162

155163

@@ -163,7 +171,7 @@ async def abort_upload_file(location_id: LocationID, file_id: StorageFileID):
163171
async def complete_upload_file(
164172
body_item: Envelope[FileUploadCompletionBody],
165173
location_id: LocationID,
166-
file_id: StorageFileID,
174+
file_id: StorageFileIDStr,
167175
):
168176
"""Asks the server to complete the upload"""
169177

@@ -176,7 +184,7 @@ async def complete_upload_file(
176184
operation_id="is_completed_upload_file",
177185
)
178186
async def is_completed_upload_file(
179-
location_id: LocationID, file_id: StorageFileID, future_id: str
187+
location_id: LocationID, file_id: StorageFileIDStr, future_id: str
180188
):
181189
"""Returns state of upload completion"""
182190

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

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,11 +2026,7 @@ paths:
20262026
- required: true
20272027
schema:
20282028
title: File Id
2029-
anyOf:
2030-
- pattern: '^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$'
2031-
type: string
2032-
- pattern: '^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$'
2033-
type: string
2029+
type: string
20342030
name: file_id
20352031
in: path
20362032
- required: false
@@ -2084,11 +2080,7 @@ paths:
20842080
- required: true
20852081
schema:
20862082
title: File Id
2087-
anyOf:
2088-
- pattern: '^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$'
2089-
type: string
2090-
- pattern: '^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$'
2091-
type: string
2083+
type: string
20922084
name: file_id
20932085
in: path
20942086
- required: true
@@ -2187,11 +2179,7 @@ paths:
21872179
- required: true
21882180
schema:
21892181
title: File Id
2190-
anyOf:
2191-
- pattern: '^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$'
2192-
type: string
2193-
- pattern: '^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$'
2194-
type: string
2182+
type: string
21952183
name: file_id
21962184
in: path
21972185
responses:
@@ -2214,11 +2202,7 @@ paths:
22142202
- required: true
22152203
schema:
22162204
title: File Id
2217-
anyOf:
2218-
- pattern: '^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$'
2219-
type: string
2220-
- pattern: '^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$'
2221-
type: string
2205+
type: string
22222206
name: file_id
22232207
in: path
22242208
requestBody:
@@ -2301,11 +2285,7 @@ paths:
23012285
- required: true
23022286
schema:
23032287
title: File Id
2304-
anyOf:
2305-
- pattern: '^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$'
2306-
type: string
2307-
- pattern: '^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$'
2308-
type: string
2288+
type: string
23092289
name: file_id
23102290
in: path
23112291
responses:
@@ -2328,11 +2308,7 @@ paths:
23282308
- required: true
23292309
schema:
23302310
title: File Id
2331-
anyOf:
2332-
- pattern: '^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$'
2333-
type: string
2334-
- pattern: '^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$'
2335-
type: string
2311+
type: string
23362312
name: file_id
23372313
in: path
23382314
- required: true
@@ -2383,11 +2359,7 @@ paths:
23832359
- required: true
23842360
schema:
23852361
title: File Id
2386-
anyOf:
2387-
- pattern: '^(api|([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}))\/([0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12})\/(.+)$'
2388-
type: string
2389-
- pattern: '^N:package:[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}$'
2390-
type: string
2362+
type: string
23912363
name: file_id
23922364
in: path
23932365
responses:

services/web/server/src/simcore_service_webserver/storage/_handlers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ async def complete_upload_file(request: web.Request) -> web.Response:
192192

193193

194194
@login_required
195-
@permission_required("storages.files.*")
195+
@permission_required("storage.files.*")
196196
async def abort_upload_file(request: web.Request) -> web.Response:
197197
payload, status = await _request_storage(request, "POST")
198198
return create_data_response(payload, status=status)

services/web/server/src/simcore_service_webserver/storage/_routes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,14 @@ def create(specs: openapi.Spec) -> list[web.RouteDef]:
5656
operation_id = specs.paths[path].operations["get"].operation_id
5757
routes.append(web.get(BASEPATH + path, handle, name=operation_id))
5858

59+
_FILE_PATH = "/storage/locations/{location_id}/files/{file_id}"
5960
path, handle = (
60-
"/storage/locations/{location_id}/files/{file_id}/metadata",
61+
f"{_FILE_PATH}/metadata",
6162
_handlers.get_file_metadata,
6263
)
6364
operation_id = specs.paths[path].operations["get"].operation_id
6465
routes.append(web.get(BASEPATH + path, handle, name=operation_id))
6566

66-
_FILE_PATH = "/storage/locations/{location_id}/files/{file_id}"
6767
path, handle = (
6868
_FILE_PATH,
6969
_handlers.download_file,

0 commit comments

Comments
 (0)