diff --git a/app/api/events.py b/app/api/events.py index 9b8a153a37..10c2cf254d 100644 --- a/app/api/events.py +++ b/app/api/events.py @@ -179,7 +179,7 @@ def query(self, view_kwargs): if not has_access('is_user_itself', user_id=int(view_kwargs['user_id'])): raise ForbiddenError({'source': ''}, 'Access Forbidden') user = safe_query_kwargs(User, view_kwargs, 'user_id') - query_ = query_.join(Event.roles).filter_by(user_id=user.id) + query_ = query_.join(Event.roles).filter_by(user_id=user.id, deleted_at=None) if view_kwargs.get('user_owner_id') and 'GET' in request.method: if not has_access( @@ -189,7 +189,7 @@ def query(self, view_kwargs): user = safe_query_kwargs(User, view_kwargs, 'user_owner_id') query_ = ( query_.join(Event.roles) - .filter_by(user_id=user.id) + .filter_by(user_id=user.id, deleted_at=None) .join(UsersEventsRoles.role) .filter(Role.name == Role.OWNER) ) @@ -203,7 +203,7 @@ def query(self, view_kwargs): query_ = ( query_.join(Event.roles) - .filter_by(user_id=user.id) + .filter_by(user_id=user.id, deleted_at=None) .join(UsersEventsRoles.role) .filter(Role.name == Role.ORGANIZER) ) @@ -216,7 +216,7 @@ def query(self, view_kwargs): user = safe_query_kwargs(User, view_kwargs, 'user_coorganizer_id') query_ = ( query_.join(Event.roles) - .filter_by(user_id=user.id) + .filter_by(user_id=user.id, deleted_at=None) .join(UsersEventsRoles.role) .filter(Role.name == Role.COORGANIZER) ) @@ -234,7 +234,7 @@ def query(self, view_kwargs): ) query_ = ( query_.join(Event.roles) - .filter_by(user_id=user.id) + .filter_by(user_id=user.id, deleted_at=None) .join(UsersEventsRoles.role) .filter(Role.name == TRACK_ORGANIZER) ) @@ -247,7 +247,7 @@ def query(self, view_kwargs): user = safe_query_kwargs(User, view_kwargs, 'user_registrar_id') query_ = ( query_.join(Event.roles) - .filter_by(user_id=user.id) + .filter_by(user_id=user.id, deleted_at=None) .join(UsersEventsRoles.role) .filter(Role.name == REGISTRAR) ) @@ -260,7 +260,7 @@ def query(self, view_kwargs): user = safe_query_kwargs(User, view_kwargs, 'user_moderator_id') query_ = ( query_.join(Event.roles) - .filter_by(user_id=user.id) + .filter_by(user_id=user.id, deleted_at=None) .join(UsersEventsRoles.role) .filter(Role.name == MODERATOR) ) @@ -273,7 +273,7 @@ def query(self, view_kwargs): user = safe_query_kwargs(User, view_kwargs, 'user_marketer_id') query_ = ( query_.join(Event.roles) - .filter_by(user_id=user.id) + .filter_by(user_id=user.id, deleted_at=None) .join(UsersEventsRoles.role) .filter(Role.name == MARKETER) ) @@ -286,7 +286,7 @@ def query(self, view_kwargs): user = safe_query_kwargs(User, view_kwargs, 'user_sales_admin_id') query_ = ( query_.join(Event.roles) - .filter_by(user_id=user.id) + .filter_by(user_id=user.id, deleted_at=None) .join(UsersEventsRoles.role) .filter(Role.name == SALES_ADMIN) ) diff --git a/app/api/role_invites.py b/app/api/role_invites.py index b88a9592c6..f6ee33653b 100644 --- a/app/api/role_invites.py +++ b/app/api/role_invites.py @@ -160,7 +160,7 @@ def accept_invite(): ) event = Event.query.filter_by(id=role_invite.event_id).first() uer = ( - UsersEventsRoles.query.filter_by(user=user) + UsersEventsRoles.query.filter_by(user=user, deleted_at=None) .filter_by(event=event) .filter_by(role=role) .first() @@ -185,6 +185,7 @@ def accept_invite(): { "email": user.email, "event": role_invite.event_id, + "event_identifier": role_invite.event.identifier, "name": user.fullname if user.fullname else None, "role": uer.role.name, } diff --git a/app/api/users_events_roles.py b/app/api/users_events_roles.py index 2af9988ec4..5cd58a44f7 100644 --- a/app/api/users_events_roles.py +++ b/app/api/users_events_roles.py @@ -5,6 +5,7 @@ from app.api.helpers.query import event_query from app.api.schema.users_events_roles import UsersEventsRolesSchema from app.models import db +from app.models.role_invite import RoleInvite from app.models.users_events_role import UsersEventsRoles @@ -52,6 +53,11 @@ def before_update_object(self, users_events_roles, data, view_kwargs): {'source': 'Role'}, 'You cannot remove the owner of the event.', ) + RoleInvite.query.filter_by( + event_id=users_events_roles.event_id, + email=users_events_roles.user.email, + role_id=role.id, + ).delete(synchronize_session=False) methods = ['GET', 'PATCH', 'DELETE'] decorators = ( diff --git a/app/models/event.py b/app/models/event.py index 34737ce86e..0c28135fc0 100644 --- a/app/models/event.py +++ b/app/models/event.py @@ -163,7 +163,7 @@ class Privacy: 'User', viewonly=True, secondary='join(UsersEventsRoles, Role,' - ' and_(Role.id == UsersEventsRoles.role_id, Role.name == "owner"))', + ' and_(UsersEventsRoles.deleted_at == None, Role.id == UsersEventsRoles.role_id, Role.name == "owner"))', primaryjoin='UsersEventsRoles.event_id == Event.id', secondaryjoin='User.id == UsersEventsRoles.user_id', backref='owner_events', @@ -174,7 +174,7 @@ class Privacy: 'User', viewonly=True, secondary='join(UsersEventsRoles, Role,' - ' and_(Role.id == UsersEventsRoles.role_id, Role.name == "organizer"))', + ' and_(UsersEventsRoles.deleted_at == None, Role.id == UsersEventsRoles.role_id, Role.name == "organizer"))', primaryjoin='UsersEventsRoles.event_id == Event.id', secondaryjoin='User.id == UsersEventsRoles.user_id', backref='organizer_events', @@ -184,7 +184,7 @@ class Privacy: 'User', viewonly=True, secondary='join(UsersEventsRoles, Role,' - ' and_(Role.id == UsersEventsRoles.role_id, Role.name == "coorganizer"))', + ' and_(UsersEventsRoles.deleted_at == None, Role.id == UsersEventsRoles.role_id, Role.name == "coorganizer"))', primaryjoin='UsersEventsRoles.event_id == Event.id', secondaryjoin='User.id == UsersEventsRoles.user_id', backref='coorganizer_events', @@ -194,7 +194,7 @@ class Privacy: 'User', viewonly=True, secondary='join(UsersEventsRoles, Role,' - ' and_(Role.id == UsersEventsRoles.role_id,' + ' and_(UsersEventsRoles.deleted_at == None, Role.id == UsersEventsRoles.role_id,' ' Role.name == "track_organizer"))', primaryjoin='UsersEventsRoles.event_id == Event.id', secondaryjoin='User.id == UsersEventsRoles.user_id', @@ -205,7 +205,7 @@ class Privacy: 'User', viewonly=True, secondary='join(UsersEventsRoles, Role,' - ' and_(Role.id == UsersEventsRoles.role_id, Role.name == "registrar"))', + ' and_(UsersEventsRoles.deleted_at == None, Role.id == UsersEventsRoles.role_id, Role.name == "registrar"))', primaryjoin='UsersEventsRoles.event_id == Event.id', secondaryjoin='User.id == UsersEventsRoles.user_id', backref='registrar_events', @@ -215,7 +215,7 @@ class Privacy: 'User', viewonly=True, secondary='join(UsersEventsRoles, Role,' - ' and_(Role.id == UsersEventsRoles.role_id, Role.name == "moderator"))', + ' and_(UsersEventsRoles.deleted_at == None, Role.id == UsersEventsRoles.role_id, Role.name == "moderator"))', primaryjoin='UsersEventsRoles.event_id == Event.id', secondaryjoin='User.id == UsersEventsRoles.user_id', backref='moderator_events', @@ -226,7 +226,7 @@ class Privacy: 'User', viewonly=True, secondary='join(UsersEventsRoles, Role,' - ' and_(Role.id == UsersEventsRoles.role_id))', + ' and_(UsersEventsRoles.deleted_at == None, Role.id == UsersEventsRoles.role_id))', primaryjoin='UsersEventsRoles.event_id == Event.id', secondaryjoin='User.id == UsersEventsRoles.user_id', backref='events', diff --git a/app/models/role_invite.py b/app/models/role_invite.py index c5e946366c..e52571f623 100644 --- a/app/models/role_invite.py +++ b/app/models/role_invite.py @@ -57,9 +57,7 @@ def send_invite(self): user = User.query.filter_by(email=self.email).first() event = Event.query.filter_by(id=self.event_id).first() frontend_url = get_settings()['frontend_url'] - link = "{}/e/{}/role-invites?token={}".format( - frontend_url, event.identifier, self.hash - ) + link = f"{frontend_url}/role-invites?token={self.hash}" if not has_access('is_coorganizer', event_id=event.id): raise ForbiddenError({'source': ''}, "Co-Organizer Access Required") if user: diff --git a/app/models/user.py b/app/models/user.py index b8384985fb..eb5528382e 100644 --- a/app/models/user.py +++ b/app/models/user.py @@ -188,13 +188,10 @@ def _is_role(self, role_name, event_id=None): Checks if a user has a particular Role at an Event. """ role = Role.query.filter_by(name=role_name).first() + uer = UER.query.filter_by(user=self, role=role, deleted_at=None) if event_id: - uer = UER.query.filter_by(user=self, event_id=event_id, role=role).first() - else: - uer = UER.query.filter_by(user=self, role=role).first() - if not uer: - return False - return True + uer = uer.filter_by(event_id=event_id) + return bool(uer.first()) def is_owner(self, event_id): return self._is_role(Role.OWNER, event_id) diff --git a/tests/all/integration/api/event/test_event_roles.py b/tests/all/integration/api/event/test_event_roles.py index c633edcffe..bd246d98f4 100644 --- a/tests/all/integration/api/event/test_event_roles.py +++ b/tests/all/integration/api/event/test_event_roles.py @@ -1,12 +1,28 @@ import json +from app.models.role_invite import RoleInvite +from tests.factories.role_invite import RoleInviteSubFactory from tests.factories.users_events_roles import UsersEventsRolesSubFactory def test_event_role_delete(db, client, user, jwt): uer = UsersEventsRolesSubFactory(user=user) + RoleInviteSubFactory( + status='accepted', event=uer.event, email=user.email, role=uer.role + ) db.session.commit() + assert ( + RoleInvite.query.filter_by( + email=user.email, event=uer.event, role=uer.role + ).count() + == 1 + ) + + resp = client.get(f'/v1/events/{uer.event_id}/users-events-roles', headers=jwt) + + assert resp.status_code == 200 + resp = client.delete(f'/v1/users-events-roles/{uer.id}', headers=jwt) assert resp.status_code == 200 @@ -14,3 +30,14 @@ def test_event_role_delete(db, client, user, jwt): 'jsonapi': {'version': '1.0'}, 'meta': {'message': 'Object successfully deleted'}, } + + assert ( + RoleInvite.query.filter_by( + email=user.email, event=uer.event, role=uer.role + ).count() + == 0 + ) + + resp = client.get(f'/v1/events/{uer.event_id}/users-events-roles', headers=jwt) + + assert resp.status_code == 403 diff --git a/tests/factories/role_invite.py b/tests/factories/role_invite.py index 8350916906..25d88472bc 100644 --- a/tests/factories/role_invite.py +++ b/tests/factories/role_invite.py @@ -7,15 +7,25 @@ from tests.factories.role import RoleFactory -class RoleInviteFactory(BaseFactory): +class RoleInviteFactoryBase(BaseFactory): class Meta: model = RoleInvite - event = factory.RelatedFactory(EventFactoryBasic) - role = factory.RelatedFactory(RoleFactory) email = common.email_ hash = common.string_ status = common.string_ role_name = common.string_ + + +class RoleInviteFactory(RoleInviteFactoryBase): + + event = factory.RelatedFactory(EventFactoryBasic) + role = factory.RelatedFactory(RoleFactory) event_id = 1 role_id = 1 + + +class RoleInviteSubFactory(RoleInviteFactoryBase): + + event = factory.SubFactory(EventFactoryBasic) + role = factory.SubFactory(RoleFactory)