Skip to content

Commit

Permalink
✨ Optional extra_credits in invitations (#4850)
Browse files Browse the repository at this point in the history
  • Loading branch information
pcrespov authored Oct 11, 2023
1 parent a8d2126 commit a41530d
Show file tree
Hide file tree
Showing 20 changed files with 218 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ class Config(OutputSchema.Config):
class GenerateInvitation(InputSchema):
guest: LowerCaseEmailStr
trial_account_days: PositiveInt | None = None
extra_credits: PositiveInt | None = None


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

Expand All @@ -47,6 +49,15 @@ class Config(OutputSchema.Config):
"issuer": "[email protected]",
"guest": "[email protected]",
"trialAccountDays": 7,
"extraCredits": 30,
"created": "2023-09-27T15:30:00",
"invitationLink": "https://example.com/invitation#1234",
},
# w/o optional
{
"productName": "osparc",
"issuer": "[email protected]",
"guest": "[email protected]",
"created": "2023-09-27T15:30:00",
"invitationLink": "https://example.com/invitation#1234",
},
Expand Down
4 changes: 4 additions & 0 deletions packages/models-library/src/models_library/invitations.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class InvitationInputs(BaseModel):
description="If set, this invitation will activate a trial account."
"Sets the number of days from creation until the account expires",
)
extra_credits: PositiveInt | None = Field(
None,
description="If set, the account's primary wallet will add these extra credits",
)


class InvitationContent(InvitationInputs):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,15 @@ def __init__(
guest_email: str | None = None,
host: dict | None = None,
trial_days: int | None = None,
extra_credits: int | None = None,
):
assert client.app
super().__init__(params=host, app=client.app)
self.client = client
self.tag = f"Created by {guest_email or FAKE.email()}"
self.confirmation = None
self.trial_days = trial_days
self.extra_credits = extra_credits

async def __aenter__(self) -> "NewInvitation":
# creates host user
Expand All @@ -146,6 +148,7 @@ async def __aenter__(self) -> "NewInvitation":
user_email=self.user["email"],
tag=self.tag,
trial_days=self.trial_days,
extra_credits=self.extra_credits,
)
return self

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.2
1.1.0
23 changes: 22 additions & 1 deletion services/invitations/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"info": {
"title": "simcore-service-invitations web API",
"description": " Service that manages creation and validation of registration invitations",
"version": "1.0.2"
"version": "1.1.0"
},
"paths": {
"/": {
Expand Down Expand Up @@ -188,6 +188,13 @@
"description": "If set, this invitation will activate a trial account.Sets the number of days from creation until the account expires",
"minimum": 0
},
"extra_credits": {
"title": "Extra Credits",
"exclusiveMinimum": true,
"type": "integer",
"description": "If set, the account's primary wallet will add these extra credits",
"minimum": 0
},
"created": {
"title": "Created",
"type": "string",
Expand Down Expand Up @@ -233,6 +240,13 @@
"description": "If set, this invitation will activate a trial account.Sets the number of days from creation until the account expires",
"minimum": 0
},
"extra_credits": {
"title": "Extra Credits",
"exclusiveMinimum": true,
"type": "integer",
"description": "If set, the account's primary wallet will add these extra credits",
"minimum": 0
},
"created": {
"title": "Created",
"type": "string",
Expand Down Expand Up @@ -284,6 +298,13 @@
"type": "integer",
"description": "If set, this invitation will activate a trial account.Sets the number of days from creation until the account expires",
"minimum": 0
},
"extra_credits": {
"title": "Extra Credits",
"exclusiveMinimum": true,
"type": "integer",
"description": "If set, the account's primary wallet will add these extra credits",
"minimum": 0
}
},
"description": "Input data necessary to create an invitation",
Expand Down
2 changes: 1 addition & 1 deletion services/invitations/setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 1.0.2
current_version = 1.1.0
commit = True
message = services/invitations version: {current_version} → {new_version}
tag = False
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ class Config:
"trial_account_days": {
"alias": "t",
},
"extra_credits": {
"alias": "e",
},
"created": {
"alias": "c",
},
Expand Down
2 changes: 1 addition & 1 deletion services/web/server/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.32.0
0.33.0
2 changes: 1 addition & 1 deletion services/web/server/setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.32.0
current_version = 0.33.0
commit = True
message = services/webserver api version: {current_version} → {new_version}
tag = False
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ info:
title: simcore-service-webserver
description: ' Main service with an interface (http-API & websockets) to the web
front-end'
version: 0.32.0
version: 0.33.0
servers:
- url: ''
description: webserver
Expand Down Expand Up @@ -6272,6 +6272,11 @@ components:
exclusiveMinimum: true
type: integer
minimum: 0
extraCredits:
title: Extracredits
exclusiveMinimum: true
type: integer
minimum: 0
GetWalletAutoRecharge:
title: GetWalletAutoRecharge
required:
Expand Down Expand Up @@ -6468,6 +6473,11 @@ components:
exclusiveMinimum: true
type: integer
minimum: 0
extraCredits:
title: Extracredits
exclusiveMinimum: true
type: integer
minimum: 0
created:
title: Created
type: string
Expand Down Expand Up @@ -7472,7 +7482,7 @@ components:
required:
- pricingUnitId
- unitName
- unitAttributes
- unitExtraInfo
- currentCostPerUnit
- default
type: object
Expand All @@ -7485,8 +7495,8 @@ components:
unitName:
title: Unitname
type: string
unitAttributes:
title: Unitattributes
unitExtraInfo:
title: Unitextrainfo
type: object
currentCostPerUnit:
title: Currentcostperunit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ def create_application() -> web.Application:
setup_products(app)
setup_statics(app)

# users
setup_users(app)
setup_groups(app)

# resource tracking / billing
setup_resource_tracker(app)
setup_payments(app)
Expand All @@ -119,10 +123,6 @@ def create_application() -> web.Application:
setup_resource_manager(app)
setup_garbage_collector(app)

# users
setup_users(app)
setup_groups(app)

# projects
setup_projects(app)
# project add-ons
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from .storage import AsyncpgStorage, BaseConfirmationTokenDict, ConfirmationTokenDict
from .utils import CONFIRMATION_PENDING

log = logging.getLogger(__name__)
_logger = logging.getLogger(__name__)


class ConfirmationTokenInfoDict(ConfirmationTokenDict):
Expand All @@ -50,6 +50,7 @@ class InvitationData(BaseModel):
description="If set, this invitation will activate a trial account."
"Sets the number of days from creation until the account expires",
)
extra_credits: PositiveInt | None = None


class _InvitationValidator(BaseModel):
Expand Down Expand Up @@ -100,7 +101,7 @@ async def check_other_registrations(
user=user, confirmation=_confirmation
)

log.warning(
_logger.warning(
"Re-registration of %s with expired %s"
"Deleting user and proceeding to a new registration",
f"{user=}",
Expand All @@ -120,6 +121,7 @@ async def create_invitation_token(
user_email: LowerCaseEmailStr | None = None,
tag: str | None = None,
trial_days: PositiveInt | None = None,
extra_credits: PositiveInt | None = None,
) -> ConfirmationTokenDict:
"""Creates an invitation token for a guest to register in the platform and returns
Expand All @@ -130,12 +132,11 @@ async def create_invitation_token(
:type host: Dict-like
:param guest: some description of the guest, e.g. email, name or a json
"""
data_model = InvitationData.parse_obj(
{
"issuer": user_email,
"guest": tag,
"trial_account_days": trial_days,
}
data_model = InvitationData(
issuer=user_email,
guest=tag,
trial_account_days=trial_days,
extra_credits=extra_credits,
)
return await db.create_confirmation(
user_id=user_id,
Expand Down Expand Up @@ -191,7 +192,7 @@ async def check_and_consume_invitation(
guest_email: str,
db: AsyncpgStorage,
cfg: LoginOptions,
app=web.Application,
app: web.Application,
) -> InvitationData:
"""Consumes invitation: the code is validated, the invitation retrieives and then deleted
since it only has one use
Expand All @@ -210,15 +211,17 @@ async def check_and_consume_invitation(
invitation_url=f"{url}",
)

log.info("Consuming invitation from service:\n%s", content.json(indent=1))
_logger.info(
"Consuming invitation from service:\n%s", content.json(indent=1)
)
return InvitationData(
issuer=content.issuer,
guest=content.guest,
trial_account_days=content.trial_account_days,
extra_credits=content.extra_credits,
)

# database-type invitations

if confirmation_token := await validate_confirmation_code(invitation_code, db, cfg):
try:
invitation_data: InvitationData = _InvitationValidator.parse_obj(
Expand All @@ -227,7 +230,7 @@ async def check_and_consume_invitation(
return invitation_data

except ValidationError as err:
log.warning(
_logger.warning(
"%s is associated with an invalid %s.\nDetails: %s",
f"{invitation_code=}",
f"{confirmation_token=}",
Expand All @@ -236,7 +239,7 @@ async def check_and_consume_invitation(

finally:
await db.delete_confirmation(confirmation_token)
log.info("Invitation with %s was consumed", f"{confirmation_token=}")
_logger.info("Invitation with %s was consumed", f"{confirmation_token=}")

raise web.HTTPForbidden(
reason=(
Expand Down
Loading

0 comments on commit a41530d

Please sign in to comment.