Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ VIP models introduce licensed versioning (🗃️) #7215

Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
eada1fd
introduce licensed resources
matusdrobuliak66 Feb 9, 2025
8a1fcb8
Merge branch 'master' into vip-models-split-licensed-items-2-attempt
matusdrobuliak66 Feb 9, 2025
70d2ba5
Merge branch 'master' of github.com:ITISFoundation/osparc-simcore int…
matusdrobuliak66 Feb 10, 2025
6907294
fix revision id
matusdrobuliak66 Feb 10, 2025
34d6d64
remove redundant comment
matusdrobuliak66 Feb 10, 2025
bf795e5
Merge branch 'master' into vip-models-split-licensed-items-2-attempt
matusdrobuliak66 Feb 10, 2025
8230164
review @pcrespov
matusdrobuliak66 Feb 10, 2025
6e5d93b
fix revision id
matusdrobuliak66 Feb 10, 2025
fb5c095
merge master
matusdrobuliak66 Feb 11, 2025
778fc53
RUT refactoring (adding key & version)
matusdrobuliak66 Feb 11, 2025
81ec8eb
modification of itis vip service
matusdrobuliak66 Feb 11, 2025
85506e1
modification of rest part
matusdrobuliak66 Feb 12, 2025
6bb88c5
openapi specs
matusdrobuliak66 Feb 12, 2025
436ad91
openapi specs
matusdrobuliak66 Feb 12, 2025
01b08e6
Merge branch 'master' into p-models-split-licensed-items-2-attempt-co…
matusdrobuliak66 Feb 12, 2025
88cd8b4
fix RPC on webserver side
matusdrobuliak66 Feb 12, 2025
7b8ec5e
openapi specs
matusdrobuliak66 Feb 12, 2025
6487147
fix
matusdrobuliak66 Feb 12, 2025
1f8f22e
fix
matusdrobuliak66 Feb 12, 2025
c1cd346
Merge branch 'master' into p-models-split-licensed-items-2-attempt-co…
matusdrobuliak66 Feb 12, 2025
a4f45c6
Merge branch 'master' into p-models-split-licensed-items-2-attempt-co…
matusdrobuliak66 Feb 12, 2025
a9ac3a4
fix
matusdrobuliak66 Feb 12, 2025
3da7e4e
fix default sortering
matusdrobuliak66 Feb 12, 2025
4bace37
remove redundant comment
matusdrobuliak66 Feb 12, 2025
84fce1a
adding RUT tests for versionig
matusdrobuliak66 Feb 12, 2025
b881c85
add DB indexes
matusdrobuliak66 Feb 12, 2025
44d43b4
fix
matusdrobuliak66 Feb 12, 2025
9775aa8
review @pcrespov - adding back trashing
matusdrobuliak66 Feb 12, 2025
2e01957
fix openapi specs
matusdrobuliak66 Feb 12, 2025
24d8791
review @pcrespov @sanderegg
matusdrobuliak66 Feb 13, 2025
96362e2
review @pcrespov
matusdrobuliak66 Feb 13, 2025
0292917
fix trash after @pcrespov review
matusdrobuliak66 Feb 13, 2025
39da15d
fix & improvement
matusdrobuliak66 Feb 13, 2025
e79c716
fix & improvement
matusdrobuliak66 Feb 13, 2025
a9ce89b
fix & improvement
matusdrobuliak66 Feb 13, 2025
9de0dc8
Merge branch 'master' into p-models-split-licensed-items-2-attempt-co…
matusdrobuliak66 Feb 13, 2025
4c2aa6a
remove redundant comment
matusdrobuliak66 Feb 13, 2025
5be7db2
fix e2e tests - hack
matusdrobuliak66 Feb 13, 2025
156646e
openapi specs
matusdrobuliak66 Feb 13, 2025
85cdb00
Merge branch 'master' into p-models-split-licensed-items-2-attempt-co…
matusdrobuliak66 Feb 13, 2025
eee57c1
DB migration
matusdrobuliak66 Feb 13, 2025
bc8a9c0
fix
matusdrobuliak66 Feb 13, 2025
902e53b
fix
matusdrobuliak66 Feb 13, 2025
be8b5c6
Merge branch 'master' into p-models-split-licensed-items-2-attempt-co…
odeimaiz Feb 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 5 additions & 13 deletions api/specs/web-server/_licensed_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
from typing import Annotated

from _common import as_query
from fastapi import APIRouter, Depends, status
from fastapi import APIRouter, Depends
from models_library.api_schemas_webserver.licensed_items import LicensedItemRestGet
from models_library.generics import Envelope
from models_library.api_schemas_webserver.licensed_items_purchases import (
LicensedItemPurchaseGet,
)
from models_library.rest_error import EnvelopedError
from models_library.rest_pagination import Page
from simcore_service_webserver._meta import API_VTAG
Expand Down Expand Up @@ -46,19 +48,9 @@ async def list_licensed_items(
...


@router.get(
"/catalog/licensed-items/{licensed_item_id}",
response_model=Envelope[LicensedItemRestGet],
)
async def get_licensed_item(
_path: Annotated[LicensedItemsPathParams, Depends()],
):
...


@router.post(
"/catalog/licensed-items/{licensed_item_id}:purchase",
status_code=status.HTTP_204_NO_CONTENT,
response_model=LicensedItemPurchaseGet,
)
async def purchase_licensed_item(
_path: Annotated[LicensedItemsPathParams, Depends()],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
class LicensedItemCheckoutGet(BaseModel):
licensed_item_checkout_id: LicensedItemCheckoutID
licensed_item_id: LicensedItemID
key: str
version: str
wallet_id: WalletID
user_id: UserID
user_email: str
Expand All @@ -30,6 +32,8 @@ class LicensedItemCheckoutGet(BaseModel):
{
"licensed_item_checkout_id": "beb16d18-d57d-44aa-a638-9727fa4a72ef",
"licensed_item_id": "303942ef-6d31-4ba8-afbe-dbb1fce2a953",
"key": "Duke",
"version": "1.0.0",
"wallet_id": 1,
"user_id": 1,
"user_email": "[email protected]",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class LicensedItemPurchaseGet(BaseModel):
licensed_item_purchase_id: LicensedItemPurchaseID
product_name: ProductName
licensed_item_id: LicensedItemID
key: str
version: str
wallet_id: WalletID
wallet_name: str
pricing_unit_cost_id: PricingUnitCostId
Expand All @@ -36,6 +38,8 @@ class LicensedItemPurchaseGet(BaseModel):
"licensed_item_purchase_id": "beb16d18-d57d-44aa-a638-9727fa4a72ef",
"product_name": "osparc",
"licensed_item_id": "303942ef-6d31-4ba8-afbe-dbb1fce2a953",
"key": "Duke",
"version": "1.0.0",
"wallet_id": 1,
"wallet_name": "My Wallet",
"pricing_unit_cost_id": 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@

class LicensedItemRpcGet(BaseModel):
licensed_item_id: LicensedItemID
key: str
version: str
display_name: str
licensed_resource_type: LicensedResourceType
licensed_resource_data: dict[str, Any]
licensed_resources: list[dict[str, Any]]
pricing_plan_id: PricingPlanId
created_at: datetime
modified_at: datetime
Expand All @@ -32,9 +34,11 @@ class LicensedItemRpcGet(BaseModel):
"examples": [
{
"licensed_item_id": "0362b88b-91f8-4b41-867c-35544ad1f7a1",
"key": "Duke",
"version": "1.0.0",
"display_name": "best-model",
"licensed_resource_type": f"{LicensedResourceType.VIP_MODEL}",
"licensed_resource_data": cast(JsonDict, VIP_DETAILS_EXAMPLE),
"licensed_resources": [cast(JsonDict, VIP_DETAILS_EXAMPLE)],
"pricing_plan_id": "15",
"created_at": "2024-12-12 09:59:26.422140",
"modified_at": "2024-12-12 09:59:26.422140",
Expand All @@ -58,24 +62,28 @@ class _ItisVipRestData(OutputSchema):
thumbnail: str
features: FeaturesDict # NOTE: here there is a bit of coupling with domain model
doi: str | None
license_version: str


class _ItisVipResourceRestData(OutputSchema):
category_id: IDStr
category_display: str
category_icon: HttpUrl | None = None # NOTE: Placeholder until provide @odeimaiz
source: _ItisVipRestData
terms_of_use_url: HttpUrl | None = None # NOTE: Placeholder until provided @mguidon


class LicensedItemRestGet(OutputSchema):
licensed_item_id: LicensedItemID
key: str
version: str

display_name: str
# NOTE: to put here a discriminator we have to embed it one more layer
licensed_resource_type: LicensedResourceType
licensed_resource_data: _ItisVipResourceRestData
licensed_resources: list[_ItisVipResourceRestData]
pricing_plan_id: PricingPlanId

category_id: IDStr
category_display: str
category_icon: HttpUrl | None = None # NOTE: Placeholder until provide @odeimaiz
terms_of_use_url: HttpUrl | None = None # NOTE: Placeholder until provided @mguidon

created_at: datetime
modified_at: datetime

Expand All @@ -86,17 +94,21 @@ def _update_json_schema_extra(schema: JsonDict) -> None:
"examples": [
{
"licensedItemId": "0362b88b-91f8-4b41-867c-35544ad1f7a1",
"key": "Duke",
"version": "1.0.0",
"displayName": "my best model",
"licensedResourceType": f"{LicensedResourceType.VIP_MODEL}",
"licensedResourceData": cast(
JsonDict,
{
"categoryId": "HumanWholeBody",
"categoryDisplay": "Humans",
"source": {**VIP_DETAILS_EXAMPLE, "doi": doi},
},
),
"licensedResources": [
cast(
JsonDict,
{
"source": {**VIP_DETAILS_EXAMPLE, "doi": doi},
},
)
],
"pricingPlanId": "15",
"categoryId": "HumanWholeBody",
"categoryDisplay": "Humans",
"createdAt": "2024-12-12 09:59:26.422140",
"modifiedAt": "2024-12-12 09:59:26.422140",
}
Expand All @@ -114,6 +126,8 @@ def from_domain_model(cls, item: LicensedItem) -> Self:
**item.model_dump(
include={
"licensed_item_id",
"key",
"version",
"display_name",
"licensed_resource_type",
"pricing_plan_id",
Expand All @@ -122,9 +136,18 @@ def from_domain_model(cls, item: LicensedItem) -> Self:
},
exclude_unset=True,
),
"licensed_resource_data": {
**item.licensed_resource_data,
},
"licensed_resources": [
_ItisVipResourceRestData(**x)
for x in sorted(
item.licensed_resources,
key=lambda x: datetime.strptime(
x["source"]["features"]["date"], "%Y-%m-%d"
),
reverse=True,
)
],
"category_id": item.licensed_resources[0]["category_id"],
"category_display": item.licensed_resources[0]["category_display"],
}
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
class LicensedItemCheckoutRpcGet(BaseModel):
licensed_item_checkout_id: LicensedItemCheckoutID
licensed_item_id: LicensedItemID
key: str
version: str
wallet_id: WalletID
user_id: UserID
product_name: ProductName
Expand All @@ -29,6 +31,8 @@ class LicensedItemCheckoutRpcGet(BaseModel):
{
"licensed_item_checkout_id": "633ef980-6f3e-4b1a-989a-bd77bf9a5d6b",
"licensed_item_id": "0362b88b-91f8-4b41-867c-35544ad1f7a1",
"key": "Duke",
"version": "1.0.0",
"wallet_id": 6,
"user_id": 27845,
"product_name": "osparc",
Expand All @@ -52,6 +56,8 @@ class LicensedItemCheckoutRpcGetPage(NamedTuple):
class LicensedItemCheckoutRestGet(OutputSchema):
licensed_item_checkout_id: LicensedItemCheckoutID
licensed_item_id: LicensedItemID
key: str
version: str
wallet_id: WalletID
user_id: UserID
user_email: LowerCaseEmailStr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class LicensedItemPurchaseGet(OutputSchema):
licensed_item_purchase_id: LicensedItemPurchaseID
product_name: ProductName
licensed_item_id: LicensedItemID
key: str
version: str
wallet_id: WalletID
pricing_unit_cost_id: PricingUnitCostId
pricing_unit_cost: Decimal
Expand Down
41 changes: 23 additions & 18 deletions packages/models-library/src/models_library/licenses.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,25 +69,26 @@ class LicensedItemDB(BaseModel):
licensed_item_id: LicensedItemID
display_name: str

licensed_resource_name: str
key: str
version: str
licensed_resource_type: LicensedResourceType
licensed_resource_data: dict[str, Any] | None

pricing_plan_id: PricingPlanId | None
product_name: ProductName | None
pricing_plan_id: PricingPlanId
product_name: ProductName

# states
created: datetime
modified: datetime
trashed: datetime | None

model_config = ConfigDict(from_attributes=True)


class LicensedItemUpdateDB(BaseModel):
class LicensedItemPatchDB(BaseModel):
display_name: str | None = None
licensed_resource_name: str | None = None
pricing_plan_id: PricingPlanId | None = None


class LicensedResourcePatchDB(BaseModel):
trash: bool | None = None


Expand Down Expand Up @@ -115,10 +116,11 @@ class LicensedResourcePatchDB(BaseModel):

class LicensedItem(BaseModel):
licensed_item_id: LicensedItemID
key: str
version: str
display_name: str
licensed_resource_name: str
licensed_resource_type: LicensedResourceType
licensed_resource_data: dict[str, Any]
licensed_resources: list[dict[str, Any]]
pricing_plan_id: PricingPlanId
created_at: datetime
modified_at: datetime
Expand All @@ -130,17 +132,20 @@ def _update_json_schema_extra(schema: JsonDict) -> None:
"examples": [
{
"licensed_item_id": "0362b88b-91f8-4b41-867c-35544ad1f7a1",
"key": "Duke",
"version": "1.0.0",
"display_name": "my best model",
"licensed_resource_name": "best-model",
"licensed_resource_type": f"{LicensedResourceType.VIP_MODEL}",
"licensed_resource_data": cast(
JsonDict,
{
"category_id": "HumanWholeBody",
"category_display": "Humans",
"source": VIP_DETAILS_EXAMPLE,
},
),
"licensed_resources": [
cast(
JsonDict,
{
"category_id": "HumanWholeBody",
"category_display": "Humans",
"source": VIP_DETAILS_EXAMPLE,
},
)
],
"pricing_plan_id": "15",
"created_at": "2024-12-12 09:59:26.422140",
"modified_at": "2024-12-12 09:59:26.422140",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
class LicensedItemsPurchasesCreate(BaseModel):
product_name: ProductName
licensed_item_id: LicensedItemID
key: str
version: str
wallet_id: WalletID
wallet_name: str
pricing_plan_id: PricingPlanId
Expand Down
12 changes: 6 additions & 6 deletions packages/models-library/tests/test_licenses.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@ def test_licensed_item_from_domain_model():

# nullable doi
assert (
got.licensed_resource_data.source.doi
== item.licensed_resource_data["source"]["doi"]
got.licensed_resources[0].source.doi
== item.licensed_resources[0]["source"]["doi"]
)

# date is required
assert got.licensed_resource_data.source.features["date"]
assert got.licensed_resources[0].source.features["date"]

# id is required
assert (
got.licensed_resource_data.source.id
== item.licensed_resource_data["source"]["id"]
got.licensed_resources[0].source.id
== item.licensed_resources[0]["source"]["id"]
)

# checks unset fields
assert "category_icon" not in got.licensed_resource_data.model_fields_set
assert "category_icon" not in got.licensed_resources[0].model_fields_set


def test_strict_check_of_examples():
Expand Down
Loading
Loading