Skip to content

Commit

Permalink
Add GroupMembership.roles column to model
Browse files Browse the repository at this point in the history
  • Loading branch information
seanh committed Oct 18, 2024
1 parent 8f2d01f commit f7e751f
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
13 changes: 13 additions & 0 deletions h/models/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import slugify
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import JSONB

from h import pubid
from h.db import Base, mixins
Expand Down Expand Up @@ -47,6 +48,18 @@ class GroupMembership(Base):
nullable=False,
index=True,
)
roles = sa.Column(
JSONB,
sa.CheckConstraint(
" OR ".join(
f"""(roles = '["{role}"]'::jsonb)"""
for role in ["member", "moderator", "admin", "owner"]
),
name="validate_role_strings",
),
server_default=sa.text("""'["member"]'::jsonb"""),
nullable=False,
)


class Group(Base, mixins.Timestamps):
Expand Down
59 changes: 59 additions & 0 deletions tests/unit/h/models/group_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest
from sqlalchemy.exc import IntegrityError

from h import models
from h.models.group import (
Expand Down Expand Up @@ -218,6 +219,64 @@ def test_non_public_group():
assert not group.is_public


class TestGroupMembership:
def test_defaults(self, db_session, user, group):
membership = models.GroupMembership(user_id=user.id, group_id=group.id)
db_session.add(membership)

db_session.flush()
assert membership.id
assert membership.user_id == user.id
assert membership.group_id == group.id
assert membership.roles == ["member"]

@pytest.mark.parametrize(
"roles",
(
["member"],
["moderator"],
["admin"],
["owner"],
),
)
def test_custom_roles(self, db_session, user, group, roles):
membership = models.GroupMembership(
user_id=user.id, group_id=group.id, roles=roles
)
db_session.add(membership)

db_session.flush()
assert membership.roles == roles

@pytest.mark.parametrize(
"roles",
(
["unknown_role"],
["moderator", "admin"], # Two valid roles, only one role is allowed.
[], # Every membership must have at least one role.
),
)
def test_invalid_roles(self, db_session, user, group, roles):
membership = models.GroupMembership(
user_id=user.id, group_id=group.id, roles=roles
)
db_session.add(membership)

with pytest.raises(
IntegrityError,
match='new row for relation "user_group" violates check constraint "ck__user_group__validate_role_strings"',
):
db_session.flush()

@pytest.fixture
def user(self, factories):
return factories.User()

@pytest.fixture
def group(self, factories):
return factories.Group()


@pytest.fixture()
def organization(factories):
return factories.Organization()

0 comments on commit f7e751f

Please sign in to comment.