record expiration time on the invitation

This commit is contained in:
dandds 2018-10-26 13:43:40 -04:00
parent d5998ed370
commit 5c5f9c6c9c
5 changed files with 44 additions and 8 deletions

View File

@ -0,0 +1,28 @@
"""add expiration_time to invitation
Revision ID: e62bcc460c26
Revises: 03654d08f5ff
Create Date: 2018-10-26 13:37:39.015003
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'e62bcc460c26'
down_revision = '03654d08f5ff'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('invitations', sa.Column('expiration_time', sa.TIMESTAMP(timezone=True), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('invitations', 'expiration_time')
# ### end Alembic commands ###

View File

@ -36,6 +36,7 @@ class Invitations(object):
inviter=inviter,
user=user,
status=InvitationStatus.PENDING,
expiration_time=Invitations.current_expiration_time(),
)
db.session.add(invite)
db.session.commit()
@ -46,7 +47,7 @@ class Invitations(object):
def accept(cls, invite_id):
invite = Invitations._get(invite_id)
if Invitations._is_expired(invite):
if invite.is_expired:
invite.status = InvitationStatus.REJECTED
elif invite.is_pending:
invite.status = InvitationStatus.ACCEPTED
@ -60,9 +61,7 @@ class Invitations(object):
return invite
@classmethod
def _is_expired(cls, invite):
time_created = invite.time_created
expiration = datetime.datetime.now(time_created.tzinfo) - datetime.timedelta(
def current_expiration_time(cls):
return datetime.datetime.now() + datetime.timedelta(
minutes=Invitations.EXPIRATION_LIMIT_MINUTES
)
return invite.time_created < expiration

View File

@ -1,6 +1,7 @@
import datetime
from enum import Enum
from sqlalchemy import Column, ForeignKey, Enum as SQLAEnum
from sqlalchemy import Column, ForeignKey, Enum as SQLAEnum, TIMESTAMP
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
@ -31,6 +32,8 @@ class Invitation(Base, TimestampsMixin):
status = Column(SQLAEnum(Status, native_enum=False, default=Status.PENDING))
expiration_time = Column(TIMESTAMP(timezone=True))
def __repr__(self):
return "<Invitation(user='{}', workspace='{}', id='{}')>".format(
self.user.id, self.workspace.id, self.id
@ -51,3 +54,7 @@ class Invitation(Base, TimestampsMixin):
@property
def is_rejected(self):
return self.status == Status.REJECTED
@property
def is_expired(self):
return datetime.datetime.now(self.expiration_time.tzinfo) > self.expiration_time

View File

@ -30,11 +30,11 @@ def test_accept_expired_invitation():
workspace = WorkspaceFactory.create()
user = UserFactory.create()
increment = Invitations.EXPIRATION_LIMIT_MINUTES + 1
created_at = datetime.datetime.now() - datetime.timedelta(minutes=increment)
expiration_time = datetime.datetime.now() - datetime.timedelta(minutes=increment)
invite = InvitationFactory.create(
workspace_id=workspace.id,
user_id=user.id,
time_created=created_at,
expiration_time=expiration_time,
status=Status.PENDING,
)
with pytest.raises(InvitationError):

View File

@ -22,6 +22,7 @@ from atst.models.workspace_role import WorkspaceRole
from atst.models.environment_role import EnvironmentRole
from atst.models.invitation import Invitation, Status as InvitationStatus
from atst.domain.workspaces import Workspaces
from atst.domain.invitations import Invitations
class Base(factory.alchemy.SQLAlchemyModelFactory):
@ -341,3 +342,4 @@ class InvitationFactory(Base):
model = Invitation
status = InvitationStatus.PENDING
expiration_time = Invitations.current_expiration_time()