Skip to content

Commit

Permalink
Send flag notification emails to moderators
Browse files Browse the repository at this point in the history
Send flag notification emails to all of a group's moderators rather than
just to the group's creator.

Also allow all moderators to moderate (hide) flagged annotations, not
just the creator.
  • Loading branch information
seanh committed Nov 23, 2024
1 parent 8765297 commit 77ae1a8
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 8 deletions.
27 changes: 25 additions & 2 deletions h/services/group_members.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import logging
from functools import partial

from sqlalchemy import select
from sqlalchemy import or_, select

from h import session
from h.models import GroupMembership
from h.models import Group, GroupMembership, GroupMembershipRoles

log = logging.getLogger(__name__)

Expand All @@ -24,6 +24,29 @@ def __init__(self, db, user_fetcher, publish):
self.user_fetcher = user_fetcher
self.publish = publish

def get(self, group: Group, roles: list[GroupMembershipRoles] | None = None):
"""
Return `group`'s memberships.
If `roles` is None return all of `group`'s memberships.
If `roles` is not None return only those memberships matching the given role(s).
If multiple roles are given return all memberships matching *any* of
the given roles.
"""
query = select(GroupMembership).where(GroupMembership.group == group)

if roles:
if len(roles) == 1:
query = query.where(GroupMembership.roles.contains(roles[0]))
else:
query = query.where(
or_(GroupMembership.roles.contains(role) for role in roles)
)

return self.db.scalars(query)

def add_members(self, group, userids):
"""
Add the users indicated by userids to this group's members.
Expand Down
24 changes: 19 additions & 5 deletions h/views/api/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from h.security import Permission
from h.tasks import mailer
from h.views.api.config import api_config
from h.models import GroupMembershipRoles


@api_config(
Expand All @@ -18,19 +19,32 @@
def create(context, request):
request.find_service(name="flag").create(request.user, context.annotation)

_email_group_admin(request, context.annotation)
_email_group_moderators(request, context.annotation)

return HTTPNoContent()


def _email_group_admin(request, annotation):
def _email_group_moderators(request, annotation):
incontext_link = links.incontext_link(request, annotation)
if incontext_link is None:
incontext_link = annotation.target_uri

group = annotation.group
if group.creator and group.creator.email:
group_members_service = request.find_service(name="group_members")

memberships = group_members_service.get(
annotation.group,
roles=[
GroupMembershipRoles.OWNER,
GroupMembershipRoles.ADMIN,
GroupMembershipRoles.MODERATOR,
]
)

for membership.user in memberships:
if not user.email:
continue

send_params = flag_notification.generate(
request, group.creator.email, incontext_link
request, user.email, incontext_link
)
mailer.send.delay(*send_params)
68 changes: 67 additions & 1 deletion tests/unit/h/services/group_members_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,76 @@
import pytest
from sqlalchemy import select

from h.models import GroupMembership, User
from h.models import GroupMembership, GroupMembershipRoles, User
from h.services.group_members import GroupMembersService, group_members_factory


class TestGet:
def test_it(self, group_members_service, db_session, factories):
group, other_group = factories.Group.build_batch(size=2)
users = factories.User.build_batch(size=2)
memberships = [GroupMembership(group=group, user=user) for user in users]
db_session.add_all(
[*memberships, GroupMembership(group=other_group, user=users[0])]
)

assert list(group_members_service.get(group)) == memberships

def test_roles(self, group_members_service, db_session, factories):
group = factories.Group.build()
admins = factories.User.build_batch(size=2)
moderator = factories.User.build()
memberships = [
GroupMembership(group=group, user=user, roles=[GroupMembershipRoles.ADMIN])
for user in admins
]
db_session.add_all(
[
*memberships,
GroupMembership(
group=group, user=moderator, roles=[GroupMembershipRoles.MODERATOR]
),
]
)

assert (
list(group_members_service.get(group, roles=[GroupMembershipRoles.ADMIN]))
== memberships
)

def test_multiple_roles(self, group_members_service, db_session, factories):
group = factories.Group.build()
admin = factories.User.build()
moderator = factories.User.build()
member = factories.User.build()
memberships = [
GroupMembership(
group=group, user=admin, roles=[GroupMembershipRoles.ADMIN]
),
GroupMembership(
group=group, user=moderator, roles=[GroupMembershipRoles.MODERATOR]
),
]
db_session.add_all(
[
*memberships,
GroupMembership(
group=group, user=member, roles=[GroupMembershipRoles.MEMBER]
),
]
)

assert (
list(
group_members_service.get(
group,
roles=[GroupMembershipRoles.ADMIN, GroupMembershipRoles.MODERATOR],
)
)
== memberships
)


class TestMemberJoin:
def test_it_adds_user_to_group(
self, group_members_service, factories, caplog, db_session
Expand Down

0 comments on commit 77ae1a8

Please sign in to comment.