Skip to content

Commit

Permalink
✨ webserver API: generate invitation (ITISFoundation#4796)
Browse files Browse the repository at this point in the history
  • Loading branch information
pcrespov authored Sep 28, 2023
1 parent d1da92e commit d587eb3
Show file tree
Hide file tree
Showing 31 changed files with 641 additions and 356 deletions.
14 changes: 13 additions & 1 deletion api/specs/web-server/_products.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@


from fastapi import APIRouter
from models_library.api_schemas_webserver.product import CreditPriceGet
from models_library.api_schemas_webserver.product import (
CreditPriceGet,
GenerateInvitation,
InvitationGenerated,
)
from models_library.generics import Envelope
from simcore_service_webserver._meta import API_VTAG

Expand All @@ -24,3 +28,11 @@
)
async def get_current_product_price():
...


@router.get(
"/invitation:generate",
response_model=Envelope[InvitationGenerated],
)
async def generate_invitation(_body: GenerateInvitation):
...
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from typing import Any, ClassVar

from pydantic import BaseModel, Field, HttpUrl

from ..invitations import InvitationContent, InvitationInputs

_INPUTS_EXAMPLE: dict[str, Any] = {
"issuer": "issuerid",
"guest": "[email protected]",
"trial_account_days": 2,
}


class ApiInvitationInputs(InvitationInputs):
class Config:
schema_extra: ClassVar[dict[str, Any]] = {"example": _INPUTS_EXAMPLE}


class ApiInvitationContent(InvitationContent):
class Config:
schema_extra: ClassVar[dict[str, Any]] = {
"example": {
**_INPUTS_EXAMPLE,
"created": "2023-01-11 13:11:47.293595",
}
}


class ApiInvitationContentAndLink(ApiInvitationContent):
invitation_url: HttpUrl = Field(..., description="Invitation link")

class Config:
schema_extra: ClassVar[dict[str, Any]] = {
"example": {
**_INPUTS_EXAMPLE,
"created": "2023-01-11 12:11:47.293595",
"invitation_url": "https://foo.com/#/registration?invitation=1234",
}
}


class ApiEncryptedInvitation(BaseModel):
invitation_url: HttpUrl = Field(..., description="Invitation link")
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from datetime import datetime
from typing import Any, ClassVar

from pydantic import Field
from models_library.products import ProductName
from pydantic import Field, HttpUrl, PositiveInt

from ..basic_types import NonNegativeDecimal
from ._base import OutputSchema
from ..emails import LowerCaseEmailStr
from ._base import InputSchema, OutputSchema


class CreditPriceGet(OutputSchema):
Expand All @@ -14,10 +17,38 @@ class CreditPriceGet(OutputSchema):
"If None, then this product's price is UNDEFINED",
)

class Config:
class Config(OutputSchema.Config):
schema_extra: ClassVar[dict[str, Any]] = {
"examples": [
{"productName": "osparc", "usdPerCredit": None},
{"productName": "osparc", "usdPerCredit": "10"},
]
}


class GenerateInvitation(InputSchema):
guest: LowerCaseEmailStr
trial_account_days: PositiveInt | None = None


class InvitationGenerated(OutputSchema):
product_name: ProductName
issuer: LowerCaseEmailStr
guest: LowerCaseEmailStr
trial_account_days: PositiveInt | None = None
created: datetime
invitation_link: HttpUrl

class Config(OutputSchema.Config):
schema_extra: ClassVar[dict[str, Any]] = {
"examples": [
{
"productName": "osparc",
"issuer": "[email protected]",
"guest": "[email protected]",
"trialAccountDays": 7,
"created": "2023-09-27T15:30:00",
"invitationLink": "https://example.com/invitation#1234",
},
]
}
35 changes: 35 additions & 0 deletions packages/models-library/src/models_library/invitations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from datetime import datetime

from pydantic import BaseModel, Field, PositiveInt

from .emails import LowerCaseEmailStr


class InvitationInputs(BaseModel):
"""Input data necessary to create an invitation"""

issuer: str = Field(
...,
description="Identifies who issued the invitation. E.g. an email, a service name etc",
min_length=1,
max_length=30,
)
guest: LowerCaseEmailStr = Field(
...,
description="Invitee's email. Note that the registration can ONLY be used with this email",
)
trial_account_days: PositiveInt | None = Field(
None,
description="If set, this invitation will activate a trial account."
"Sets the number of days from creation until the account expires",
)


class InvitationContent(InvitationInputs):
"""Data in an invitation"""

# avoid using default to mark exactly the time
created: datetime = Field(..., description="Timestamp for creation")

def as_invitation_inputs(self) -> InvitationInputs:
return self.copy(exclude={"created"})
6 changes: 3 additions & 3 deletions services/invitations/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ include ../../scripts/common-service.Makefile



.env:
.env-ignore:
$(APP_CLI_NAME) generate-dotenv --auto-password > $@


.PHONY: openapi.json
openapi-specs: openapi.json
openapi.json: .env ## produces openapi.json
openapi.json: .env-ignore ## produces openapi.json
# generating openapi specs file (need to have the environment set for this)
@set -o allexport; \
source .env; \
source $<; \
set +o allexport; \
python3 -c "import json; from $(APP_PACKAGE_NAME).web_main import *; print( json.dumps(the_app.openapi(), indent=2) )" > $@

Expand Down
2 changes: 1 addition & 1 deletion services/invitations/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.1
1.0.2
Loading

0 comments on commit d587eb3

Please sign in to comment.