Skip to content

Commit b00e7e9

Browse files
committed
fixing oas
1 parent 1a0cb3c commit b00e7e9

File tree

3 files changed

+90
-49
lines changed

3 files changed

+90
-49
lines changed

api/specs/web-server/_users_admin.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
from enum import Enum
88
from typing import Annotated
99

10-
from _common import as_query
11-
from fastapi import APIRouter, Depends, status
10+
from fastapi import APIRouter, Depends, Query, status
1211
from models_library.api_schemas_webserver.users import (
12+
PageQueryParameters,
1313
UserAccountApprove,
1414
UserAccountGet,
1515
UserAccountReject,
1616
UserAccountSearchQueryParams,
17-
UsersAccountListQueryParams,
17+
UsersForAdminListFilter,
1818
)
1919
from models_library.generics import Envelope
2020
from models_library.rest_pagination import Page
@@ -26,13 +26,26 @@
2626
_extra_tags: list[str | Enum] = ["admin"]
2727

2828

29+
# NOTE: I still do not have a clean solution for this
30+
#
31+
class _Q(UsersForAdminListFilter, PageQueryParameters): ...
32+
33+
2934
@router.get(
3035
"/admin/user-accounts",
3136
response_model=Page[UserAccountGet],
3237
tags=_extra_tags,
3338
)
3439
async def list_users_accounts(
35-
_query: Annotated[as_query(UsersAccountListQueryParams), Depends()],
40+
_query: Annotated[_Q, Depends()],
41+
order_by: Annotated[
42+
str,
43+
Query(
44+
title="Order By",
45+
description="Comma-separated list of fields for ordering (prefix with '-' for descending).",
46+
example="-created_at,name",
47+
),
48+
] = "",
3649
): ...
3750

3851

packages/models-library/src/models_library/rest_ordering.py

Lines changed: 58 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class OrderBy(BaseModel):
3636

3737

3838
class _BaseOrderQueryParams(RequestParameters):
39+
# Use OrderingQueryParams instead for more flexible ordering
3940
order_by: OrderBy
4041

4142

@@ -128,53 +129,65 @@ class _OrderJsonQueryParams(_BaseOrderQueryParams):
128129
return _OrderJsonQueryParams
129130

130131

132+
def _parse_order_by(v):
133+
if not v:
134+
return []
135+
136+
if isinstance(v, list):
137+
v = ",".join(v)
138+
139+
if not isinstance(v, str):
140+
msg = "order_by must be a string"
141+
raise TypeError(msg)
142+
143+
# 1. from comma-separated string to list of OrderClause
144+
clauses = []
145+
for t in v.split(","):
146+
token = t.strip()
147+
if not token:
148+
continue
149+
if token.startswith("-"):
150+
clauses.append((token[1:], OrderDirection.DESC))
151+
elif token.startswith("+"):
152+
clauses.append((token[1:], OrderDirection.ASC))
153+
else:
154+
clauses.append((token, OrderDirection.ASC))
155+
156+
# 2. check for duplicates and conflicting directions
157+
return [
158+
{"field": field, "direction": direction}
159+
for field, direction in check_ordering_list(clauses)
160+
]
161+
162+
131163
class OrderingQueryParams(GenericModel, Generic[TField]):
132-
# NOTE: OrderingQueryParams is a more flexible variant for generic usage and that
133-
# does include multiple ordering clauses
134-
#
164+
"""
165+
This class is designed to parse query parameters for ordering results in an API request.
166+
167+
It supports multiple ordering clauses and allows for flexible sorting options.
168+
169+
NOTE: It only parses strings and validates into list[OrderClause[TField]]
170+
where TField is a type variable representing valid field names.
171+
172+
173+
For example:
174+
175+
/my/path?order_by=field1,-field2,+field3
176+
177+
would sort by field1 ascending, field2 descending, and field3 ascending.
178+
"""
179+
135180
order_by: Annotated[
136181
list[OrderClause[TField]],
137-
Field(
138-
default_factory=list,
139-
description="Order by clauses e.g. ?order_by=-created_at,name",
140-
),
182+
BeforeValidator(_parse_order_by),
183+
Field(default_factory=list),
141184
] = DEFAULT_FACTORY
142185

143-
@field_validator("order_by", mode="before")
144-
@classmethod
145-
def _parse_order_by_string(cls, v):
146-
"""Parses a comma-separated string into a list of OrderClause
147-
148-
Example, given the query parameter `order_by` in a request like `GET /items?order_by=-created_at,name`
149-
It parses to:
150-
[
151-
OrderClause(field="created_at", direction=OrderDirection.DESC),
152-
OrderClause(field="name", direction=OrderDirection.ASC),
153-
]
154-
"""
155-
if not v:
156-
return []
157-
158-
if isinstance(v, str):
159-
# 1. from comma-separated string to list of OrderClause
160-
v = v.split(",")
161-
clauses: list[tuple[str, OrderDirection]] = []
162-
for t in v:
163-
token = t.strip()
164-
if not token:
165-
continue
166-
if token.startswith("-"):
167-
clauses.append((token[1:].strip(), OrderDirection.DESC))
168-
elif token.startswith("+"):
169-
clauses.append((token[1:].strip(), OrderDirection.ASC))
170-
else:
171-
clauses.append((token, OrderDirection.ASC))
172-
# 2. check for duplicates and conflicting directions
173-
return [
174-
{"field": field, "direction": direction}
175-
for field, direction in check_ordering_list(clauses)
176-
]
177-
178-
# NOTE: Parses ONLY strings into list[OrderClause], otherwise raises TypeError
179-
msg = f"Invalid type for order_by: expected str, got {type(v)}"
180-
raise TypeError(msg)
186+
model_config = ConfigDict(
187+
json_schema_extra={
188+
"examples": [
189+
{"order_by": "-created_at,name,+gender"},
190+
{"order_by": ""},
191+
],
192+
}
193+
)

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,18 +1724,33 @@ paths:
17241724
summary: List Users Accounts
17251725
operationId: list_users_accounts
17261726
parameters:
1727+
- name: order_by
1728+
in: query
1729+
required: false
1730+
schema:
1731+
type: string
1732+
title: Order By
1733+
description: Comma-separated list of fields for ordering (prefix with '-'
1734+
for descending).
1735+
default: ''
1736+
description: Comma-separated list of fields for ordering (prefix with '-'
1737+
for descending).
1738+
example: -created_at,name
17271739
- name: limit
17281740
in: query
17291741
required: false
17301742
schema:
17311743
type: integer
1744+
maximum: 50
1745+
minimum: 1
17321746
default: 20
17331747
title: Limit
17341748
- name: offset
17351749
in: query
17361750
required: false
17371751
schema:
17381752
type: integer
1753+
minimum: 0
17391754
default: 0
17401755
title: Offset
17411756
- name: review_status

0 commit comments

Comments
 (0)