Skip to content

Commit 9404272

Browse files
author
Andrei Neagu
committed
Merge remote-tracking branch 'upstream/master' into pr-osparc-redirect-service-restart-containers
2 parents 7a74839 + 92ddd6c commit 9404272

File tree

73 files changed

+2140
-343
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+2140
-343
lines changed

api/specs/web-server/_catalog_licensed_items.py renamed to api/specs/web-server/_licensed_items.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@
1414
from models_library.generics import Envelope
1515
from models_library.rest_error import EnvelopedError
1616
from simcore_service_webserver._meta import API_VTAG
17-
from simcore_service_webserver.catalog.licenses._exceptions_handlers import (
18-
_TO_HTTP_ERROR_MAP,
19-
)
20-
from simcore_service_webserver.catalog.licenses._models import (
17+
from simcore_service_webserver.licenses._exceptions_handlers import _TO_HTTP_ERROR_MAP
18+
from simcore_service_webserver.licenses._models import (
2119
LicensedItemsBodyParams,
2220
LicensedItemsListQueryParams,
2321
LicensedItemsPathParams,
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
""" Helper script to generate OAS automatically
2+
"""
3+
4+
# pylint: disable=redefined-outer-name
5+
# pylint: disable=unused-argument
6+
# pylint: disable=unused-variable
7+
# pylint: disable=too-many-arguments
8+
9+
from typing import Annotated
10+
11+
from _common import as_query
12+
from fastapi import APIRouter, Depends
13+
from models_library.api_schemas_webserver.licensed_items_purchases import (
14+
LicensedItemPurchaseGet,
15+
)
16+
from models_library.generics import Envelope
17+
from models_library.rest_error import EnvelopedError
18+
from models_library.rest_pagination import Page
19+
from simcore_service_webserver._meta import API_VTAG
20+
from simcore_service_webserver.licenses._exceptions_handlers import _TO_HTTP_ERROR_MAP
21+
from simcore_service_webserver.licenses._models import (
22+
LicensedItemsPurchasesListQueryParams,
23+
LicensedItemsPurchasesPathParams,
24+
)
25+
from simcore_service_webserver.wallets._handlers import WalletsPathParams
26+
27+
router = APIRouter(
28+
prefix=f"/{API_VTAG}",
29+
tags=[
30+
"licenses",
31+
],
32+
responses={
33+
i.status_code: {"model": EnvelopedError} for i in _TO_HTTP_ERROR_MAP.values()
34+
},
35+
)
36+
37+
38+
@router.get(
39+
"/wallets/{wallet_id}/licensed-items-purchases",
40+
response_model=Page[LicensedItemPurchaseGet],
41+
tags=["wallets"],
42+
)
43+
async def list_wallet_licensed_items_purchases(
44+
_path: Annotated[WalletsPathParams, Depends()],
45+
_query: Annotated[as_query(LicensedItemsPurchasesListQueryParams), Depends()],
46+
):
47+
...
48+
49+
50+
@router.get(
51+
"/licensed-items-purchases/{licensed_item_purchase_id}",
52+
response_model=Envelope[LicensedItemPurchaseGet],
53+
)
54+
async def get_licensed_item_purchase(
55+
_path: Annotated[LicensedItemsPurchasesPathParams, Depends()],
56+
):
57+
...

api/specs/web-server/openapi.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@
3232
"_announcements",
3333
"_catalog",
3434
"_catalog_tags", # MUST BE after _catalog
35-
"_catalog_licensed_items",
3635
"_computations",
3736
"_exporter",
3837
"_folders",
3938
"_long_running_tasks",
39+
"_licensed_items",
40+
"_licensed_items_purchases",
4041
"_metamodeling",
4142
"_nih_sparc",
4243
"_nih_sparc_redirections",
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from datetime import datetime
2+
from decimal import Decimal
3+
from typing import NamedTuple
4+
5+
from models_library.licensed_items import LicensedItemID
6+
from models_library.products import ProductName
7+
from models_library.resource_tracker import PricingUnitCostId
8+
from models_library.resource_tracker_licensed_items_purchases import (
9+
LicensedItemPurchaseID,
10+
)
11+
from models_library.users import UserID
12+
from models_library.wallets import WalletID
13+
from pydantic import BaseModel, ConfigDict, PositiveInt
14+
15+
16+
class LicensedItemPurchaseGet(BaseModel):
17+
licensed_item_purchase_id: LicensedItemPurchaseID
18+
product_name: ProductName
19+
licensed_item_id: LicensedItemID
20+
wallet_id: WalletID
21+
wallet_name: str
22+
pricing_unit_cost_id: PricingUnitCostId
23+
pricing_unit_cost: Decimal
24+
start_at: datetime
25+
expire_at: datetime
26+
num_of_seats: int
27+
purchased_by_user: UserID
28+
purchased_at: datetime
29+
modified: datetime
30+
31+
model_config = ConfigDict(
32+
json_schema_extra={
33+
"examples": [
34+
{
35+
"licensed_item_purchase_id": "beb16d18-d57d-44aa-a638-9727fa4a72ef",
36+
"product_name": "osparc",
37+
"licensed_item_id": "303942ef-6d31-4ba8-afbe-dbb1fce2a953",
38+
"wallet_id": 1,
39+
"wallet_name": "My Wallet",
40+
"pricing_unit_cost_id": 1,
41+
"pricing_unit_cost": 10,
42+
"start_at": "2023-01-11 13:11:47.293595",
43+
"expire_at": "2023-01-11 13:11:47.293595",
44+
"num_of_seats": 1,
45+
"purchased_by_user": 1,
46+
"purchased_at": "2023-01-11 13:11:47.293595",
47+
"modified": "2023-01-11 13:11:47.293595",
48+
}
49+
]
50+
}
51+
)
52+
53+
54+
class LicensedItemsPurchasesPage(NamedTuple):
55+
items: list[LicensedItemPurchaseGet]
56+
total: PositiveInt

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

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import Annotated, Any, Self, TypeVar
33

44
from common_library.basic_types import DEFAULT_FACTORY
5+
from models_library.groups import EVERYONE_GROUP_ID
56
from pydantic import (
67
AnyHttpUrl,
78
AnyUrl,
@@ -14,16 +15,16 @@
1415
model_validator,
1516
)
1617

17-
from ..basic_types import IDStr
1818
from ..emails import LowerCaseEmailStr
1919
from ..groups import (
2020
AccessRightsDict,
2121
Group,
22+
GroupID,
2223
GroupMember,
2324
StandardGroupCreate,
2425
StandardGroupUpdate,
2526
)
26-
from ..users import UserID
27+
from ..users import UserID, UserNameID
2728
from ..utils.common_validators import create__check_only_one_is_set__root_validator
2829
from ._base import InputSchema, OutputSchema
2930

@@ -55,7 +56,7 @@ class GroupAccessRights(BaseModel):
5556

5657

5758
class GroupGet(OutputSchema):
58-
gid: int = Field(..., description="the group ID")
59+
gid: GroupID = Field(..., description="the group ID")
5960
label: str = Field(..., description="the group name")
6061
description: str = Field(..., description="the group description")
6162
thumbnail: AnyUrl | None = Field(
@@ -114,7 +115,7 @@ def from_model(cls, group: Group, access_rights: AccessRightsDict) -> Self:
114115
"accessRights": {"read": True, "write": False, "delete": False},
115116
},
116117
{
117-
"gid": "0",
118+
"gid": "1",
118119
"label": "All",
119120
"description": "Open to all users",
120121
"accessRights": {"read": True, "write": True, "delete": True},
@@ -214,7 +215,7 @@ class MyGroupsGet(OutputSchema):
214215
},
215216
],
216217
"all": {
217-
"gid": "0",
218+
"gid": EVERYONE_GROUP_ID,
218219
"label": "All",
219220
"description": "Open to all users",
220221
"accessRights": {"read": True, "write": False, "delete": False},
@@ -228,13 +229,11 @@ class GroupUserGet(BaseModel):
228229
# OutputSchema
229230

230231
# Identifiers
231-
id: Annotated[
232-
str | None, Field(description="the user id", coerce_numbers_to_str=True)
233-
] = None
234-
user_name: Annotated[IDStr, Field(alias="userName")]
232+
id: Annotated[UserID | None, Field(description="the user's id")] = None
233+
user_name: Annotated[UserNameID, Field(alias="userName")]
235234
gid: Annotated[
236-
str | None,
237-
Field(description="the user primary gid", coerce_numbers_to_str=True),
235+
GroupID | None,
236+
Field(description="the user primary gid"),
238237
] = None
239238

240239
# Private Profile
@@ -296,7 +295,7 @@ class GroupUserAdd(InputSchema):
296295
"""
297296

298297
uid: UserID | None = None
299-
user_name: Annotated[IDStr | None, Field(alias="userName")] = None
298+
user_name: Annotated[UserNameID | None, Field(alias="userName")] = None
300299
email: Annotated[
301300
LowerCaseEmailStr | None,
302301
Field(
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from datetime import datetime
2+
from decimal import Decimal
3+
from typing import NamedTuple
4+
5+
from models_library.licensed_items import LicensedItemID
6+
from models_library.products import ProductName
7+
from models_library.resource_tracker import PricingUnitCostId
8+
from models_library.resource_tracker_licensed_items_purchases import (
9+
LicensedItemPurchaseID,
10+
)
11+
from models_library.users import UserID
12+
from models_library.wallets import WalletID
13+
from pydantic import PositiveInt
14+
15+
from ._base import OutputSchema
16+
17+
18+
class LicensedItemPurchaseGet(OutputSchema):
19+
licensed_item_purchase_id: LicensedItemPurchaseID
20+
product_name: ProductName
21+
licensed_item_id: LicensedItemID
22+
wallet_id: WalletID
23+
pricing_unit_cost_id: PricingUnitCostId
24+
pricing_unit_cost: Decimal
25+
start_at: datetime
26+
expire_at: datetime
27+
num_of_seats: int
28+
purchased_by_user: UserID
29+
purchased_at: datetime
30+
modified_at: datetime
31+
32+
33+
class LicensedItemPurchaseGetPage(NamedTuple):
34+
items: list[LicensedItemPurchaseGet]
35+
total: PositiveInt

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

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,59 @@ class WalletGet(OutputSchema):
2020
created: datetime
2121
modified: datetime
2222

23-
model_config = ConfigDict(from_attributes=True, frozen=False)
23+
model_config = ConfigDict(
24+
from_attributes=True,
25+
frozen=False,
26+
json_schema_extra={
27+
"examples": [
28+
{
29+
"wallet_id": 1,
30+
"name": "My wallet",
31+
"description": "My description",
32+
"owner": 1,
33+
"thumbnail": "https://example.com/payment-method/form",
34+
"status": "ACTIVE",
35+
"created": "2024-03-25T00:00:00",
36+
"modified": "2024-03-25T00:00:00",
37+
}
38+
]
39+
},
40+
)
2441

2542

2643
class WalletGetWithAvailableCredits(WalletGet):
2744
available_credits: Decimal
2845

46+
model_config = ConfigDict(
47+
json_schema_extra={
48+
"examples": [
49+
{
50+
**WalletGet.model_config["json_schema_extra"]["examples"][0], # type: ignore
51+
"available_credits": 10.5,
52+
}
53+
]
54+
}
55+
)
56+
2957

3058
class WalletGetPermissions(WalletGet):
3159
read: bool
3260
write: bool
3361
delete: bool
3462

63+
model_config = ConfigDict(
64+
json_schema_extra={
65+
"examples": [
66+
{
67+
**WalletGet.model_config["json_schema_extra"]["examples"][0], # type: ignore
68+
"read": True,
69+
"write": True,
70+
"delete": True,
71+
}
72+
]
73+
}
74+
)
75+
3576

3677
class CreateWalletBodyParams(OutputSchema):
3778
name: str

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
EVERYONE_GROUP_ID: Final[int] = 1
1414

1515

16+
__all__: tuple[str, ...] = ("GroupID",)
17+
18+
1619
class GroupTypeInModel(str, enum.Enum):
1720
"""
1821
standard: standard group, e.g. any group that is not a primary group or special group such as the everyone group

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class CreditTransactionStatus(StrAutoEnum):
4848
class CreditClassification(StrAutoEnum):
4949
ADD_WALLET_TOP_UP = auto() # user top up credits
5050
DEDUCT_SERVICE_RUN = auto() # computational/dynamic service run costs)
51+
DEDUCT_LICENSE_PURCHASE = auto()
5152

5253

5354
class PricingPlanClassification(StrAutoEnum):
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from datetime import datetime
2+
from decimal import Decimal
3+
from typing import TypeAlias
4+
from uuid import UUID
5+
6+
from pydantic import BaseModel, ConfigDict
7+
8+
from .licensed_items import LicensedItemID
9+
from .products import ProductName
10+
from .resource_tracker import PricingPlanId, PricingUnitCostId, PricingUnitId
11+
from .users import UserID
12+
from .wallets import WalletID
13+
14+
LicensedItemPurchaseID: TypeAlias = UUID
15+
16+
17+
class LicensedItemsPurchasesCreate(BaseModel):
18+
product_name: ProductName
19+
licensed_item_id: LicensedItemID
20+
wallet_id: WalletID
21+
wallet_name: str
22+
pricing_plan_id: PricingPlanId
23+
pricing_unit_id: PricingUnitId
24+
pricing_unit_cost_id: PricingUnitCostId
25+
pricing_unit_cost: Decimal
26+
start_at: datetime
27+
expire_at: datetime
28+
num_of_seats: int
29+
purchased_by_user: UserID
30+
user_email: str
31+
purchased_at: datetime
32+
33+
model_config = ConfigDict(from_attributes=True)

0 commit comments

Comments
 (0)