From e6aa4663d4208089e5786c4608afc8d77372f24a Mon Sep 17 00:00:00 2001 From: richard-dds Date: Wed, 28 Nov 2018 15:54:22 -0500 Subject: [PATCH 1/4] Better error handling for Auditable class --- atst/models/invitation.py | 2 +- atst/models/mixins/auditable.py | 40 +++++++++++++++++------------ atst/models/request_status_event.py | 2 +- tests/domain/test_invitations.py | 10 ++++---- 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/atst/models/invitation.py b/atst/models/invitation.py index 0b7d6686..ded1d2b3 100644 --- a/atst/models/invitation.py +++ b/atst/models/invitation.py @@ -112,4 +112,4 @@ class Invitation(Base, TimestampsMixin, AuditableMixin): @property def workspace_id(self): - return self.workspace_role.workspace_id + return self.workspace_role.workspace_id if self.workspace_role else None diff --git a/atst/models/mixins/auditable.py b/atst/models/mixins/auditable.py index b39c8768..b2ff5635 100644 --- a/atst/models/mixins/auditable.py +++ b/atst/models/mixins/auditable.py @@ -13,14 +13,14 @@ class AuditableMixin(object): @staticmethod def create_audit_event(connection, resource, action): user_id = getattr_path(g, "current_user.id") - workspace_id = resource.auditable_workspace_id() - request_id = resource.auditable_request_id() - resource_type = resource.auditable_resource_type() - display_name = resource.auditable_displayname() - event_details = resource.auditable_event_details() + workspace_id = resource.workspace_id + request_id = resource.request_id + resource_type = resource.resource_type + display_name = resource.displayname + event_details = resource.event_details changed_state = ( - resource.auditable_changed_state() if action == ACTION_UPDATE else None + resource.history if action == ACTION_UPDATE else None ) audit_event = AuditEvent( @@ -77,20 +77,26 @@ class AuditableMixin(object): previous_state[attr.key] = [deleted, added] return previous_state - def auditable_changed_state(self): - return getattr_path(self, "history") + @property + def history(self): + return None - def auditable_event_details(self): - return getattr_path(self, "event_details") + @property + def event_details(self): + return None - def auditable_resource_type(self): + @property + def resource_type(self): return camel_to_snake(type(self).__name__) - def auditable_workspace_id(self): - return getattr_path(self, "workspace_id") + @property + def workspace_id(self): + return None - def auditable_request_id(self): - return getattr_path(self, "request_id") + @property + def request_id(self): + return None - def auditable_displayname(self): - return getattr_path(self, "displayname") + @property + def displayname(self): + return None diff --git a/atst/models/request_status_event.py b/atst/models/request_status_event.py index 90ec2532..e3367951 100644 --- a/atst/models/request_status_event.py +++ b/atst/models/request_status_event.py @@ -43,7 +43,7 @@ class RequestStatusEvent(Base, mixins.TimestampsMixin, mixins.AuditableMixin): @property def displayname(self): - return self.new_status.value + return self.new_status.value if self.new_status else None @property def log_name(self): diff --git a/tests/domain/test_invitations.py b/tests/domain/test_invitations.py index ee5021a3..d570f994 100644 --- a/tests/domain/test_invitations.py +++ b/tests/domain/test_invitations.py @@ -47,7 +47,7 @@ def test_accept_expired_invitation(): increment = Invitations.EXPIRATION_LIMIT_MINUTES + 1 expiration_time = datetime.datetime.now() - datetime.timedelta(minutes=increment) invite = InvitationFactory.create( - user_id=user.id, expiration_time=expiration_time, status=Status.PENDING + user=user, expiration_time=expiration_time, status=Status.PENDING ) with pytest.raises(ExpiredError): Invitations.accept(user, invite.token) @@ -57,14 +57,14 @@ def test_accept_expired_invitation(): def test_accept_rejected_invite(): user = UserFactory.create() - invite = InvitationFactory.create(user_id=user.id, status=Status.REJECTED_EXPIRED) + invite = InvitationFactory.create(user=user, status=Status.REJECTED_EXPIRED) with pytest.raises(InvitationError): Invitations.accept(user, invite.token) def test_accept_revoked_invite(): user = UserFactory.create() - invite = InvitationFactory.create(user_id=user.id, status=Status.REVOKED) + invite = InvitationFactory.create(user=user, status=Status.REVOKED) with pytest.raises(InvitationError): Invitations.accept(user, invite.token) @@ -72,7 +72,7 @@ def test_accept_revoked_invite(): def test_wrong_user_accepts_invitation(): user = UserFactory.create() wrong_user = UserFactory.create() - invite = InvitationFactory.create(user_id=user.id) + invite = InvitationFactory.create(user=user) with pytest.raises(WrongUserError): Invitations.accept(wrong_user, invite.token) @@ -80,7 +80,7 @@ def test_wrong_user_accepts_invitation(): def test_user_cannot_accept_invitation_accepted_by_wrong_user(): user = UserFactory.create() wrong_user = UserFactory.create() - invite = InvitationFactory.create(user_id=user.id) + invite = InvitationFactory.create(user=user) with pytest.raises(WrongUserError): Invitations.accept(wrong_user, invite.token) with pytest.raises(InvitationError): From ee18b704b221c230779e6d28e754ac8a035f52e6 Mon Sep 17 00:00:00 2001 From: Montana Date: Mon, 3 Dec 2018 15:37:57 -0500 Subject: [PATCH 2/4] Formatting --- atst/models/mixins/auditable.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/atst/models/mixins/auditable.py b/atst/models/mixins/auditable.py index b2ff5635..c765a36f 100644 --- a/atst/models/mixins/auditable.py +++ b/atst/models/mixins/auditable.py @@ -19,9 +19,7 @@ class AuditableMixin(object): display_name = resource.displayname event_details = resource.event_details - changed_state = ( - resource.history if action == ACTION_UPDATE else None - ) + changed_state = resource.history if action == ACTION_UPDATE else None audit_event = AuditEvent( user_id=user_id, From 9ddac1fa61cee35f66dc8b7a7b89878c28697975 Mon Sep 17 00:00:00 2001 From: Montana Date: Mon, 3 Dec 2018 16:49:59 -0500 Subject: [PATCH 3/4] Prevent invitations without a workspace role --- atst/models/invitation.py | 2 +- tests/domain/test_invitations.py | 27 ++++++++-- tests/models/test_invitation.py | 30 +++++++++-- tests/models/test_workspace_role.py | 60 +++++++++++++++------ tests/routes/workspaces/test_invitations.py | 17 ++++-- 5 files changed, 106 insertions(+), 30 deletions(-) diff --git a/atst/models/invitation.py b/atst/models/invitation.py index ded1d2b3..0b7d6686 100644 --- a/atst/models/invitation.py +++ b/atst/models/invitation.py @@ -112,4 +112,4 @@ class Invitation(Base, TimestampsMixin, AuditableMixin): @property def workspace_id(self): - return self.workspace_role.workspace_id if self.workspace_role else None + return self.workspace_role.workspace_id diff --git a/tests/domain/test_invitations.py b/tests/domain/test_invitations.py index d570f994..54a98d6d 100644 --- a/tests/domain/test_invitations.py +++ b/tests/domain/test_invitations.py @@ -44,10 +44,15 @@ def test_accept_invitation(): def test_accept_expired_invitation(): user = UserFactory.create() + workspace = WorkspaceFactory.create() + ws_role = WorkspaceRoleFactory.create(user=user, workspace=workspace) increment = Invitations.EXPIRATION_LIMIT_MINUTES + 1 expiration_time = datetime.datetime.now() - datetime.timedelta(minutes=increment) invite = InvitationFactory.create( - user=user, expiration_time=expiration_time, status=Status.PENDING + user=user, + expiration_time=expiration_time, + status=Status.PENDING, + workspace_role=ws_role, ) with pytest.raises(ExpiredError): Invitations.accept(user, invite.token) @@ -57,30 +62,42 @@ def test_accept_expired_invitation(): def test_accept_rejected_invite(): user = UserFactory.create() - invite = InvitationFactory.create(user=user, status=Status.REJECTED_EXPIRED) + workspace = WorkspaceFactory.create() + ws_role = WorkspaceRoleFactory.create(user=user, workspace=workspace) + invite = InvitationFactory.create( + user=user, status=Status.REJECTED_EXPIRED, workspace_role=ws_role + ) with pytest.raises(InvitationError): Invitations.accept(user, invite.token) def test_accept_revoked_invite(): user = UserFactory.create() - invite = InvitationFactory.create(user=user, status=Status.REVOKED) + workspace = WorkspaceFactory.create() + ws_role = WorkspaceRoleFactory.create(user=user, workspace=workspace) + invite = InvitationFactory.create( + user=user, status=Status.REVOKED, workspace_role=ws_role + ) with pytest.raises(InvitationError): Invitations.accept(user, invite.token) def test_wrong_user_accepts_invitation(): user = UserFactory.create() + workspace = WorkspaceFactory.create() + ws_role = WorkspaceRoleFactory.create(user=user, workspace=workspace) wrong_user = UserFactory.create() - invite = InvitationFactory.create(user=user) + invite = InvitationFactory.create(user=user, workspace_role=ws_role) with pytest.raises(WrongUserError): Invitations.accept(wrong_user, invite.token) def test_user_cannot_accept_invitation_accepted_by_wrong_user(): user = UserFactory.create() + workspace = WorkspaceFactory.create() + ws_role = WorkspaceRoleFactory.create(user=user, workspace=workspace) wrong_user = UserFactory.create() - invite = InvitationFactory.create(user=user) + invite = InvitationFactory.create(user=user, workspace_role=ws_role) with pytest.raises(WrongUserError): Invitations.accept(wrong_user, invite.token) with pytest.raises(InvitationError): diff --git a/tests/models/test_invitation.py b/tests/models/test_invitation.py index 44fb30fb..891d98a0 100644 --- a/tests/models/test_invitation.py +++ b/tests/models/test_invitation.py @@ -2,22 +2,44 @@ import pytest import datetime from atst.models.invitation import Invitation, Status +from atst.models.workspace_role import Status as WorkspaceRoleStatus -from tests.factories import InvitationFactory +from tests.factories import ( + InvitationFactory, + WorkspaceFactory, + UserFactory, + WorkspaceRoleFactory, +) def test_expired_invite_is_not_revokable(): + workspace = WorkspaceFactory.create() + user = UserFactory.create() + ws_role = WorkspaceRoleFactory.create( + workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING + ) invite = InvitationFactory.create( - expiration_time=datetime.datetime.now() - datetime.timedelta(minutes=60) + expiration_time=datetime.datetime.now() - datetime.timedelta(minutes=60), + workspace_role=ws_role, ) assert not invite.is_revokable def test_unexpired_invite_is_revokable(): - invite = InvitationFactory.create() + workspace = WorkspaceFactory.create() + user = UserFactory.create() + ws_role = WorkspaceRoleFactory.create( + workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING + ) + invite = InvitationFactory.create(workspace_role=ws_role) assert invite.is_revokable def test_invite_is_not_revokable_if_invite_is_not_pending(): - invite = InvitationFactory.create(status=Status.ACCEPTED) + workspace = WorkspaceFactory.create() + user = UserFactory.create() + ws_role = WorkspaceRoleFactory.create( + workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING + ) + invite = InvitationFactory.create(workspace_role=ws_role, status=Status.ACCEPTED) assert not invite.is_revokable diff --git a/tests/models/test_workspace_role.py b/tests/models/test_workspace_role.py index 4ccc0529..63f7fd02 100644 --- a/tests/models/test_workspace_role.py +++ b/tests/models/test_workspace_role.py @@ -7,6 +7,7 @@ from atst.models.workspace_role import Status from atst.models.role import Role from atst.models.invitation import Status as InvitationStatus from atst.models.audit_event import AuditEvent +from atst.models.workspace_role import Status as WorkspaceRoleStatus from tests.factories import ( RequestFactory, UserFactory, @@ -196,44 +197,69 @@ def test_status_when_member_is_active(): def test_status_when_invitation_has_been_rejected_for_expirations(): - workspace_role = WorkspaceRoleFactory.create( - invitations=[InvitationFactory.create(status=InvitationStatus.REJECTED_EXPIRED)] + workspace = WorkspaceFactory.create() + user = UserFactory.create() + ws_role = WorkspaceRoleFactory.create( + workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING ) + invitation = InvitationFactory.create( + workspace_role=ws_role, status=InvitationStatus.REJECTED_EXPIRED + ) + workspace_role = WorkspaceRoleFactory.create(invitations=[invitation]) assert workspace_role.display_status == "Invite expired" def test_status_when_invitation_has_been_rejected_for_wrong_user(): - workspace_role = WorkspaceRoleFactory.create( - invitations=[ - InvitationFactory.create(status=InvitationStatus.REJECTED_WRONG_USER) - ] + workspace = WorkspaceFactory.create() + user = UserFactory.create() + ws_role = WorkspaceRoleFactory.create( + workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING ) + invitation = InvitationFactory.create( + workspace_role=ws_role, status=InvitationStatus.REJECTED_WRONG_USER + ) + workspace_role = WorkspaceRoleFactory.create(invitations=[invitation]) assert workspace_role.display_status == "Error on invite" def test_status_when_invitation_is_expired(): - workspace_role = WorkspaceRoleFactory.create( - invitations=[ - InvitationFactory.create( - status=InvitationStatus.PENDING, - expiration_time=datetime.datetime.now() - datetime.timedelta(seconds=1), - ) - ] + workspace = WorkspaceFactory.create() + user = UserFactory.create() + ws_role = WorkspaceRoleFactory.create( + workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING ) + invitation = InvitationFactory.create( + workspace_role=ws_role, + status=InvitationStatus.PENDING, + expiration_time=datetime.datetime.now() - datetime.timedelta(seconds=1), + ) + workspace_role = WorkspaceRoleFactory.create(invitations=[invitation]) assert workspace_role.display_status == "Invite expired" def test_can_not_resend_invitation_if_active(): - workspace_role = WorkspaceRoleFactory.create( - invitations=[InvitationFactory.create(status=InvitationStatus.ACCEPTED)] + workspace = WorkspaceFactory.create() + user = UserFactory.create() + ws_role = WorkspaceRoleFactory.create( + workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING ) + invitation = InvitationFactory.create( + workspace_role=ws_role, status=InvitationStatus.ACCEPTED + ) + workspace_role = WorkspaceRoleFactory.create(invitations=[invitation]) assert not workspace_role.can_resend_invitation def test_can_resend_invitation_if_expired(): - workspace_role = WorkspaceRoleFactory.create( - invitations=[InvitationFactory.create(status=InvitationStatus.REJECTED_EXPIRED)] + workspace = WorkspaceFactory.create() + user = UserFactory.create() + ws_role = WorkspaceRoleFactory.create( + workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING ) + invitation = InvitationFactory.create( + workspace_role=ws_role, status=InvitationStatus.REJECTED_EXPIRED + ) + workspace_role = WorkspaceRoleFactory.create(invitations=[invitation]) assert workspace_role.can_resend_invitation diff --git a/tests/routes/workspaces/test_invitations.py b/tests/routes/workspaces/test_invitations.py index c981cb72..bc18a470 100644 --- a/tests/routes/workspaces/test_invitations.py +++ b/tests/routes/workspaces/test_invitations.py @@ -19,7 +19,9 @@ def test_existing_member_accepts_valid_invite(client, user_session): ws_role = WorkspaceRoleFactory.create( workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING ) - invite = InvitationFactory.create(user_id=user.id, workspace_role_id=ws_role.id) + invite = InvitationFactory.create( + user_id=user.id, workspace_role=ws_role, workspace_role_id=ws_role.id + ) # the user does not have access to the workspace before accepting the invite assert len(Workspaces.for_user(user)) == 0 @@ -76,6 +78,7 @@ def test_member_accepts_invalid_invite(client, user_session): ) invite = InvitationFactory.create( user_id=user.id, + workspace_role=ws_role, workspace_role_id=ws_role.id, status=InvitationStatus.REJECTED_WRONG_USER, ) @@ -109,7 +112,9 @@ def test_user_accepts_invite_with_wrong_dod_id(client, user_session): ws_role = WorkspaceRoleFactory.create( user=user, workspace=workspace, status=WorkspaceRoleStatus.PENDING ) - invite = InvitationFactory.create(user_id=user.id, workspace_role_id=ws_role.id) + invite = InvitationFactory.create( + user_id=user.id, workspace_role=ws_role, workspace_role_id=ws_role.id + ) user_session(different_user) response = client.get(url_for("workspaces.accept_invitation", token=invite.token)) @@ -124,6 +129,7 @@ def test_user_accepts_expired_invite(client, user_session): ) invite = InvitationFactory.create( user_id=user.id, + workspace_role=ws_role, workspace_role_id=ws_role.id, status=InvitationStatus.REJECTED_EXPIRED, expiration_time=datetime.datetime.now() - datetime.timedelta(seconds=1), @@ -142,6 +148,7 @@ def test_revoke_invitation(client, user_session): ) invite = InvitationFactory.create( user_id=user.id, + workspace_role=ws_role, workspace_role_id=ws_role.id, status=InvitationStatus.REJECTED_EXPIRED, expiration_time=datetime.datetime.now() - datetime.timedelta(seconds=1), @@ -166,7 +173,10 @@ def test_resend_invitation_sends_email(client, user_session, queue): user=user, workspace=workspace, status=WorkspaceRoleStatus.PENDING ) invite = InvitationFactory.create( - user_id=user.id, workspace_role_id=ws_role.id, status=InvitationStatus.PENDING + user_id=user.id, + workspace_role=ws_role, + workspace_role_id=ws_role.id, + status=InvitationStatus.PENDING, ) user_session(workspace.owner) client.post( @@ -190,6 +200,7 @@ def test_existing_member_invite_resent_to_email_submitted_in_form( ) invite = InvitationFactory.create( user_id=user.id, + workspace_role=ws_role, workspace_role_id=ws_role.id, status=InvitationStatus.PENDING, email="example@example.com", From a4caf98ef7e1c95612d0f93df14d1f2f9a5743fb Mon Sep 17 00:00:00 2001 From: Montana Date: Tue, 4 Dec 2018 16:20:40 -0500 Subject: [PATCH 4/4] Removed repetitive code in tests --- tests/models/test_workspace_role.py | 25 +++++++++------------ tests/routes/workspaces/test_invitations.py | 17 +++----------- 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/tests/models/test_workspace_role.py b/tests/models/test_workspace_role.py index 63f7fd02..284415bf 100644 --- a/tests/models/test_workspace_role.py +++ b/tests/models/test_workspace_role.py @@ -199,67 +199,62 @@ def test_status_when_member_is_active(): def test_status_when_invitation_has_been_rejected_for_expirations(): workspace = WorkspaceFactory.create() user = UserFactory.create() - ws_role = WorkspaceRoleFactory.create( + workspace_role = WorkspaceRoleFactory.create( workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING ) invitation = InvitationFactory.create( - workspace_role=ws_role, status=InvitationStatus.REJECTED_EXPIRED + workspace_role=workspace_role, status=InvitationStatus.REJECTED_EXPIRED ) - workspace_role = WorkspaceRoleFactory.create(invitations=[invitation]) assert workspace_role.display_status == "Invite expired" def test_status_when_invitation_has_been_rejected_for_wrong_user(): workspace = WorkspaceFactory.create() user = UserFactory.create() - ws_role = WorkspaceRoleFactory.create( + workspace_role = WorkspaceRoleFactory.create( workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING ) invitation = InvitationFactory.create( - workspace_role=ws_role, status=InvitationStatus.REJECTED_WRONG_USER + workspace_role=workspace_role, status=InvitationStatus.REJECTED_WRONG_USER ) - workspace_role = WorkspaceRoleFactory.create(invitations=[invitation]) assert workspace_role.display_status == "Error on invite" def test_status_when_invitation_is_expired(): workspace = WorkspaceFactory.create() user = UserFactory.create() - ws_role = WorkspaceRoleFactory.create( + workspace_role = WorkspaceRoleFactory.create( workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING ) invitation = InvitationFactory.create( - workspace_role=ws_role, + workspace_role=workspace_role, status=InvitationStatus.PENDING, expiration_time=datetime.datetime.now() - datetime.timedelta(seconds=1), ) - workspace_role = WorkspaceRoleFactory.create(invitations=[invitation]) assert workspace_role.display_status == "Invite expired" def test_can_not_resend_invitation_if_active(): workspace = WorkspaceFactory.create() user = UserFactory.create() - ws_role = WorkspaceRoleFactory.create( + workspace_role = WorkspaceRoleFactory.create( workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING ) invitation = InvitationFactory.create( - workspace_role=ws_role, status=InvitationStatus.ACCEPTED + workspace_role=workspace_role, status=InvitationStatus.ACCEPTED ) - workspace_role = WorkspaceRoleFactory.create(invitations=[invitation]) assert not workspace_role.can_resend_invitation def test_can_resend_invitation_if_expired(): workspace = WorkspaceFactory.create() user = UserFactory.create() - ws_role = WorkspaceRoleFactory.create( + workspace_role = WorkspaceRoleFactory.create( workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING ) invitation = InvitationFactory.create( - workspace_role=ws_role, status=InvitationStatus.REJECTED_EXPIRED + workspace_role=workspace_role, status=InvitationStatus.REJECTED_EXPIRED ) - workspace_role = WorkspaceRoleFactory.create(invitations=[invitation]) assert workspace_role.can_resend_invitation diff --git a/tests/routes/workspaces/test_invitations.py b/tests/routes/workspaces/test_invitations.py index bc18a470..d6e99ee0 100644 --- a/tests/routes/workspaces/test_invitations.py +++ b/tests/routes/workspaces/test_invitations.py @@ -19,9 +19,7 @@ def test_existing_member_accepts_valid_invite(client, user_session): ws_role = WorkspaceRoleFactory.create( workspace=workspace, user=user, status=WorkspaceRoleStatus.PENDING ) - invite = InvitationFactory.create( - user_id=user.id, workspace_role=ws_role, workspace_role_id=ws_role.id - ) + invite = InvitationFactory.create(user_id=user.id, workspace_role=ws_role) # the user does not have access to the workspace before accepting the invite assert len(Workspaces.for_user(user)) == 0 @@ -79,7 +77,6 @@ def test_member_accepts_invalid_invite(client, user_session): invite = InvitationFactory.create( user_id=user.id, workspace_role=ws_role, - workspace_role_id=ws_role.id, status=InvitationStatus.REJECTED_WRONG_USER, ) user_session(user) @@ -112,9 +109,7 @@ def test_user_accepts_invite_with_wrong_dod_id(client, user_session): ws_role = WorkspaceRoleFactory.create( user=user, workspace=workspace, status=WorkspaceRoleStatus.PENDING ) - invite = InvitationFactory.create( - user_id=user.id, workspace_role=ws_role, workspace_role_id=ws_role.id - ) + invite = InvitationFactory.create(user_id=user.id, workspace_role=ws_role) user_session(different_user) response = client.get(url_for("workspaces.accept_invitation", token=invite.token)) @@ -130,7 +125,6 @@ def test_user_accepts_expired_invite(client, user_session): invite = InvitationFactory.create( user_id=user.id, workspace_role=ws_role, - workspace_role_id=ws_role.id, status=InvitationStatus.REJECTED_EXPIRED, expiration_time=datetime.datetime.now() - datetime.timedelta(seconds=1), ) @@ -149,7 +143,6 @@ def test_revoke_invitation(client, user_session): invite = InvitationFactory.create( user_id=user.id, workspace_role=ws_role, - workspace_role_id=ws_role.id, status=InvitationStatus.REJECTED_EXPIRED, expiration_time=datetime.datetime.now() - datetime.timedelta(seconds=1), ) @@ -173,10 +166,7 @@ def test_resend_invitation_sends_email(client, user_session, queue): user=user, workspace=workspace, status=WorkspaceRoleStatus.PENDING ) invite = InvitationFactory.create( - user_id=user.id, - workspace_role=ws_role, - workspace_role_id=ws_role.id, - status=InvitationStatus.PENDING, + user_id=user.id, workspace_role=ws_role, status=InvitationStatus.PENDING ) user_session(workspace.owner) client.post( @@ -201,7 +191,6 @@ def test_existing_member_invite_resent_to_email_submitted_in_form( invite = InvitationFactory.create( user_id=user.id, workspace_role=ws_role, - workspace_role_id=ws_role.id, status=InvitationStatus.PENDING, email="example@example.com", )