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

✨ webserver API: generate invitation #4796

Merged
merged 20 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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):
...
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