Beispiel #1
0
    def test_member_join_publishes_join_event(self, db_session, users):
        publish = mock.Mock(spec_set=[])
        svc = GroupsService(db_session, users.get, publish=publish)
        group = Group(name='Donkey Trust', creator=users['cazimir'])
        group.pubid = 'abc123'

        svc.member_join(group, 'theresa')

        publish.assert_called_once_with('group-join', 'abc123', 'theresa')
Beispiel #2
0
    def test_member_join_publishes_join_event(self, db_session, users):
        publish = mock.Mock(spec_set=[])
        svc = GroupsService(db_session, users.get, publish=publish)
        group = Group(name='Donkey Trust', creator=users['cazimir'])
        group.pubid = 'abc123'

        svc.member_join(group, 'theresa')

        publish.assert_called_once_with('group-join', 'abc123', 'theresa')
Beispiel #3
0
    def test_member_leave_publishes_leave_event(self, service, users, publish):
        group = Group(name='Donkey Trust',
                      authority='foobari.com',
                      creator=users['theresa'])
        group.members.append(users['cazimir'])
        group.pubid = 'abc123'

        service.member_leave(group, 'cazimir')

        publish.assert_called_once_with('group-leave', 'abc123', 'cazimir')
Beispiel #4
0
    def test_member_leave_publishes_leave_event(self, db_session, users):
        publish = mock.Mock(spec_set=[])
        svc = GroupService(db_session, users.get, publish=publish)
        group = Group(name='Donkey Trust',
                      authority='foobari.com',
                      creator=users['theresa'])
        group.members.append(users['cazimir'])
        group.pubid = 'abc123'

        svc.member_leave(group, 'cazimir')

        publish.assert_called_once_with('group-leave', 'abc123', 'cazimir')
Beispiel #5
0
    def test_member_leave_publishes_leave_event(self, db_session, users):
        publish = mock.Mock(spec_set=[])
        svc = GroupService(db_session, users.get, publish=publish)
        group = Group(name='Donkey Trust',
                      authority='foobari.com',
                      creator=users['theresa'])
        group.members.append(users['cazimir'])
        group.pubid = 'abc123'

        svc.member_leave(group, 'cazimir')

        publish.assert_called_once_with('group-leave', 'abc123', 'cazimir')
Beispiel #6
0
    def execute(self, batch, effective_user_id=None, **_):
        if effective_user_id is None:
            raise CommandSequenceError(
                "Effective user must be configured before upserting groups")

        # Check that we can actually process this batch
        self._check_upsert_queries(
            batch, expected_keys=["authority", "authority_provided_id"])

        # Prep the query
        values = [command.body.attributes for command in batch]
        for value in values:
            value["creator_id"] = effective_user_id

        stmt = insert(Group).values(values)
        stmt = stmt.on_conflict_do_update(
            index_elements=["authority", "authority_provided_id"],
            set_={
                "name": stmt.excluded.name
            },
        ).returning(Group.id, Group.authority, Group.authority_provided_id)

        # Upsert the data
        group_rows = self._execute_statement(stmt).fetchall()

        # Report back
        return [
            Report(
                id_,
                public_id=Group(
                    authority=authority,
                    authority_provided_id=authority_provided_id).groupid,
            ) for id_, authority, authority_provided_id in group_rows
        ]
Beispiel #7
0
    def create(self, name, authority, userid, description=None, type_='private'):
        """
        Create a new group.

        :param name: the human-readable name of the group
        :param userid: the userid of the group creator
        :param description: the description of the group
        :param type_: the type of group (private or publisher) which sets the
                      appropriate access flags

        :returns: the created group
        """
        creator = self.user_fetcher(userid)
        group = Group(name=name,
                      authority=authority,
                      creator=creator,
                      description=description)

        access_flags = GROUP_ACCESS_FLAGS.get(type_)
        if access_flags is None:
            raise ValueError('Invalid group type %s' % type_)
        for attr, value in access_flags.iteritems():
            setattr(group, attr, value)

        self.session.add(group)
        self.session.flush()

        if self.publish:
            self.publish('group-join', group.pubid, userid)

        return group
Beispiel #8
0
    def test_post_sets_group_properties(self, form_validating_to, pyramid_request):
        creator = User(username='******', authority='example.org')
        group = Group(name='Birdwatcher Community',
                      description='We watch birds all day long',
                      creator=creator)
        group.pubid = 'the-test-pubid'

        controller = views.GroupEditController(group, pyramid_request)
        controller.form = form_validating_to({
            'name': 'Alligatorwatcher Comm.',
            'description': 'We are all about the alligators now',
        })
        controller.post()

        assert group.name == 'Alligatorwatcher Comm.'
        assert group.description == 'We are all about the alligators now'
Beispiel #9
0
    def test_member_join_adds_user_to_group(self, db_session, users):
        svc = GroupsService(db_session, users.get)
        group = Group(name='Donkey Trust', creator=users['cazimir'])

        svc.member_join(group, 'theresa')

        assert users['theresa'] in group.members
Beispiel #10
0
    def test_member_leave_removes_user_from_group(self, db_session, users):
        svc = GroupsService(db_session, users.get)
        group = Group(name='Theresa and her buddies', creator=users['theresa'])
        group.members.append(users['cazimir'])

        svc.member_leave(group, 'cazimir')

        assert users['cazimir'] not in group.members
Beispiel #11
0
    def test_member_join_is_idempotent(self, db_session, users):
        svc = GroupsService(db_session, users.get)
        group = Group(name='Donkey Trust', creator=users['cazimir'])

        svc.member_join(group, 'theresa')
        svc.member_join(group, 'theresa')

        assert group.members.count(users['theresa']) == 1
Beispiel #12
0
    def test_get_reads_group_properties(self, pyramid_request):
        pyramid_request.create_form.return_value = FakeForm()

        creator = User(username='******', authority='example.org')
        group = Group(name='Birdwatcher Community',
                      description='We watch birds all day long',
                      creator=creator)
        group.pubid = 'the-test-pubid'

        result = views.GroupEditController(group, pyramid_request).get()

        assert result == {
            'form': {
                'name': 'Birdwatcher Community',
                'description': 'We watch birds all day long',
            },
            'group_path': '/g/the-test-pubid/birdwatcher-community'
        }
Beispiel #13
0
    def test_get_reads_group_properties(self, pyramid_request):
        pyramid_request.create_form.return_value = FakeForm()

        creator = User(username='******', authority='example.org')
        group = Group(name='Birdwatcher Community',
                      description='We watch birds all day long',
                      creator=creator)
        group.pubid = 'the-test-pubid'

        result = views.GroupEditController(group, pyramid_request).get()

        assert result == {
            'form': {
                'name': 'Birdwatcher Community',
                'description': 'We watch birds all day long',
            },
            'group_path': '/g/the-test-pubid/birdwatcher-community'
        }
Beispiel #14
0
    def test_member_leave_removes_user_from_group(self, service, users):
        group = Group(name='Theresa and her buddies',
                      authority='foobar.com',
                      creator=users['theresa'])
        group.members.append(users['cazimir'])

        service.member_leave(group, 'cazimir')

        assert users['cazimir'] not in group.members
Beispiel #15
0
    def test_member_leave_is_idempotent(self, db_session, users):
        svc = GroupService(db_session, users.get)
        group = Group(name='Theresa and her buddies',
                      authority='foobar.com',
                      creator=users['theresa'])
        group.members.append(users['cazimir'])

        svc.member_leave(group, 'cazimir')
        svc.member_leave(group, 'cazimir')

        assert users['cazimir'] not in group.members
Beispiel #16
0
    def execute(self, batch, effective_user_id=None, **_):  # pylint: disable=arguments-differ
        if effective_user_id is None:
            raise CommandSequenceError(
                "Effective user must be configured before upserting groups")

        # Check that we can actually process this batch
        self._check_upsert_queries(
            batch, expected_keys=["authority", "authority_provided_id"])

        static_values = {
            # Set the group to be owned by the effective user
            "creator_id": effective_user_id,
            # Set the group to match the specified type (private in this case)
            "joinable_by": self.type_flags.joinable_by,
            "readable_by": self.type_flags.readable_by,
            "writeable_by": self.type_flags.writeable_by,
        }

        # Prep the query
        values = [command.body.attributes for command in batch]
        for value in values:
            value.update(static_values)

        stmt = insert(Group).values(values)
        stmt = stmt.on_conflict_do_update(
            index_elements=["authority", "authority_provided_id"],
            set_={
                "name": stmt.excluded.name
            },
        ).returning(Group.id, Group.authority, Group.authority_provided_id)

        # Upsert the data
        try:
            group_rows = self._execute_statement(stmt).fetchall()

        except ProgrammingError as err:
            # https://www.postgresql.org/docs/9.4/errcodes-appendix.html
            # 21000 == cardinality violation
            if err.orig.pgcode == "21000":
                raise ConflictingDataError(
                    "Attempted to create two groups with the same authority and id"
                ) from err

            raise

        # Report back
        return [
            Report(
                id_,
                public_id=Group(
                    authority=authority,
                    authority_provided_id=authority_provided_id).groupid,
            ) for id_, authority, authority_provided_id in group_rows
        ]
Beispiel #17
0
    def test_post_sets_group_properties(self, form_validating_to, pyramid_request):
        creator = User(username="******", authority="example.org")
        group = Group(
            name="Birdwatcher Community",
            authority="foobar.com",
            description="We watch birds all day long",
            creator=creator,
        )
        group.pubid = "the-test-pubid"

        controller = views.GroupEditController(group, pyramid_request)
        controller.form = form_validating_to(
            {
                "name": "Alligatorwatcher Comm.",
                "description": "We are all about the alligators now",
            }
        )
        controller.post()

        assert group.name == "Alligatorwatcher Comm."
        assert group.description == "We are all about the alligators now"
Beispiel #18
0
    def test_get_reads_group_properties(self, pyramid_request):
        pyramid_request.create_form.return_value = FakeForm()

        creator = User(username="******", authority="example.org")
        group = Group(
            name="Birdwatcher Community",
            authority="foobar.com",
            description="We watch birds all day long",
            creator=creator,
        )
        group.pubid = "the-test-pubid"

        result = views.GroupEditController(group, pyramid_request).get()

        assert result == {
            "form": {
                "name": "Birdwatcher Community",
                "description": "We watch birds all day long",
            },
            "group_path": "/g/the-test-pubid/birdwatcher-community",
        }
Beispiel #19
0
    def test_get_reads_group_properties(self, pyramid_request):
        pyramid_request.create_form.return_value = FakeForm()

        creator = User(username="******", authority="example.org")
        group = Group(
            name="Birdwatcher Community",
            authority="foobar.com",
            description="We watch birds all day long",
            creator=creator,
        )
        group.pubid = "the-test-pubid"

        result = views.GroupEditController(group, pyramid_request).get()

        assert result == {
            "form": {
                "name": "Birdwatcher Community",
                "description": "We watch birds all day long",
            },
            "group_path": "/g/the-test-pubid/birdwatcher-community",
        }
Beispiel #20
0
    def groups(self, db_session):
        groups = [
            Group(
                name=f"group_{i}",
                authority="lms.hypothes.is",
                authority_provided_id=f"ap_id_{i}",
            ) for i in range(3)
        ]

        db_session.add_all(groups)
        db_session.flush()

        return groups
Beispiel #21
0
    def test_post_sets_group_properties(self, form_validating_to,
                                        pyramid_request):
        creator = User(username="******", authority="example.org")
        group = Group(
            name="Birdwatcher Community",
            authority="foobar.com",
            description="We watch birds all day long",
            creator=creator,
        )
        group.pubid = "the-test-pubid"

        controller = views.GroupEditController(group, pyramid_request)
        controller.form = form_validating_to({
            "name":
            "Alligatorwatcher Comm.",
            "description":
            "We are all about the alligators now",
        })
        controller.post()

        assert group.name == "Alligatorwatcher Comm."
        assert group.description == "We are all about the alligators now"
Beispiel #22
0
    def _create(self,
                name,
                userid,
                description,
                type_flags,
                origins=None,
                add_creator_as_member=False,
                organization=None):
        """
        Create a group and save it to the DB.

        :param name: the human-readable name of the group
        :param userid: the userid of the group creator
        :param description: the description of the group
        :param type_flags: the type of this group
        :param origins: the list of origins that the group will be scoped to
        :param add_creator_as_member: if the group creator should be added as a member
        :param organization: the organization that this group belongs to
        :type organization: h.models.Organization
        """
        if origins is None:
            origins = []

        creator = self.user_fetcher(userid)
        scopes = [GroupScope(origin=o) for o in origins]
        if organization is not None:
            self._validate_authorities_match(creator.authority,
                                             organization.authority)
        group = Group(
            name=name,
            authority=creator.authority,
            creator=creator,
            description=description,
            joinable_by=type_flags.joinable_by,
            readable_by=type_flags.readable_by,
            writeable_by=type_flags.writeable_by,
            scopes=scopes,
            organization=organization,
        )
        self.session.add(group)

        if add_creator_as_member:
            group.members.append(group.creator)

            # Flush the DB to generate group.pubid before publish()ing it.
            self.session.flush()

            self.publish('group-join', group.pubid, group.creator.userid)

        return group
Beispiel #23
0
    def groups(self, db_session, user):
        groups = [
            Group(
                name=f"group_{i}",
                authority=user.authority,
                authority_provided_id=f"ap_id_{i}",
            )
            for i in range(3)
        ]

        db_session.add_all(groups)
        db_session.flush()

        return groups
Beispiel #24
0
 def _create(self, name, userid, description, joinable_by, readable_by,
             writeable_by):
     """Create a group and save it to the DB."""
     creator = self.user_fetcher(userid)
     group = Group(
         name=name,
         authority=creator.authority,
         creator=creator,
         description=description,
         joinable_by=joinable_by,
         readable_by=readable_by,
         writeable_by=writeable_by,
     )
     self.session.add(group)
     return group
Beispiel #25
0
 def _create(self, name, userid, description, type_flags, scopes=[]):
     """Create a group and save it to the DB."""
     creator = self.user_fetcher(userid)
     group = Group(
         name=name,
         authority=creator.authority,
         creator=creator,
         description=description,
         joinable_by=type_flags.joinable_by,
         readable_by=type_flags.readable_by,
         writeable_by=type_flags.writeable_by,
         scopes=scopes,
     )
     self.session.add(group)
     return group
Beispiel #26
0
    def test_update_memberships_adds_and_remove_members(
            self, factories, publish, service, users):
        group = Group(name='Donkey Trust',
                      authority='example.com',
                      creator=users['theresa'])
        group.pubid = 'abc123'
        service.member_join = mock.Mock()
        service.member_leave = mock.Mock()

        group.members.append(users['cazimir'])
        group.members.append(users['theresa'])
        group.members.append(users['ali'])

        service.update_membership(group, [
            users['henry'].username, users['poppy'].username,
            users['theresa'].username
        ])

        assert len(service.member_leave.call_args_list) == 2
        service.member_leave.assert_any_call(group, users['cazimir'].userid)
        service.member_leave.assert_any_call(group, users['ali'].userid)
        assert len(service.member_join.call_args_list) == 2
        service.member_join.assert_any_call(group, users['henry'].userid)
        service.member_join.assert_any_call(group, users['poppy'].userid)
Beispiel #27
0
    def _create(  # pylint: disable=too-many-arguments
            self, name, userid, type_flags, scopes, add_creator_as_member,
            **kwargs):
        """
        Create a group and save it to the DB.

        :param name: the human-readable name of the group
        :param userid: the userid of the group creator
        :param type_flags: the type of this group
        :param scopes: the list of scopes (URIs) that the group will be scoped to
        :type scopes: list(str)
        :param add_creator_as_member: if the group creator should be added as a member
        :param kwargs: optional attributes to set on the group, as keyword
            arguments
        """
        if scopes is None:
            scopes = []

        creator = self.user_fetcher(userid)

        group_scopes = [GroupScope(scope=s) for s in scopes]

        if "organization" in kwargs:
            self._validate_authorities_match(creator.authority,
                                             kwargs["organization"].authority)

        group = Group(
            name=name,
            authority=creator.authority,
            creator=creator,
            joinable_by=type_flags.joinable_by,
            readable_by=type_flags.readable_by,
            writeable_by=type_flags.writeable_by,
            scopes=group_scopes,
            **kwargs,
        )
        self.db.add(group)

        if add_creator_as_member:
            group.members.append(group.creator)

            # Flush the DB to generate group.pubid before publish()ing it.
            self.db.flush()

            self.publish("group-join", group.pubid, group.creator.userid)

        return group
Beispiel #28
0
    def create(self, name, userid, description=None):
        """
        Create a new group.

        :param name: the human-readable name of the group
        :param userid: the userid of the group creator
        :param description: the description of the group

        :returns: the created group
        """
        creator = self.user_fetcher(userid)
        group = Group(name=name, creator=creator, description=description)
        self.session.add(group)
        self.session.flush()

        if self.publish:
            self.publish('group-join', group.pubid, userid)

        return group
Beispiel #29
0
    def execute(self, batch, effective_user_id=None, **_):
        if effective_user_id is None:
            raise CommandSequenceError(
                "Effective user must be configured before upserting groups")

        # Check that we can actually process this batch
        self._check_upsert_queries(
            batch, expected_keys=["authority", "authority_provided_id"])

        static_values = {
            # Set the group to be owned by the effective user
            "creator_id": effective_user_id,
            # Set the group to match the specified type (private in this case)
            "joinable_by": self.type_flags.joinable_by,
            "readable_by": self.type_flags.readable_by,
            "writeable_by": self.type_flags.writeable_by,
        }

        # Prep the query
        values = [command.body.attributes for command in batch]
        for value in values:
            value.update(static_values)

        stmt = insert(Group).values(values)
        stmt = stmt.on_conflict_do_update(
            index_elements=["authority", "authority_provided_id"],
            set_={
                "name": stmt.excluded.name
            },
        ).returning(Group.id, Group.authority, Group.authority_provided_id)

        # Upsert the data
        group_rows = self._execute_statement(stmt).fetchall()

        # Report back
        return [
            Report(
                id_,
                public_id=Group(
                    authority=authority,
                    authority_provided_id=authority_provided_id).groupid,
            ) for id_, authority, authority_provided_id in group_rows
        ]
Beispiel #30
0
    def _create(self, name, userid, type_flags, origins, add_creator_as_member,
                **kwargs):
        """
        Create a group and save it to the DB.

        :param name: the human-readable name of the group
        :param userid: the userid of the group creator
        :param type_flags: the type of this group
        :param origins: the list of origins that the group will be scoped to
        :param add_creator_as_member: if the group creator should be added as a member
        :param kwargs: optional attributes to set on the group, as keyword
            arguments
        """
        if origins is None:
            origins = []

        creator = self.user_fetcher(userid)

        scopes = [GroupScope(origin=o) for o in origins]

        if "organization" in kwargs:
            self._validate_authorities_match(creator.authority,
                                             kwargs["organization"].authority)

        group = Group(name=name,
                      authority=creator.authority,
                      creator=creator,
                      joinable_by=type_flags.joinable_by,
                      readable_by=type_flags.readable_by,
                      writeable_by=type_flags.writeable_by,
                      scopes=scopes,
                      **kwargs)
        self.session.add(group)

        if add_creator_as_member:
            group.members.append(group.creator)

            # Flush the DB to generate group.pubid before publish()ing it.
            self.session.flush()

            self.publish('group-join', group.pubid, group.creator.userid)

        return group
def group_with_two_users(db_session, factories):
    """
    Create a group with two members and an annotation created by each.
    """
    creator = factories.User()
    member = factories.User()

    group = Group(authority=creator.authority, creator=creator, members=[creator, member],
                  name='test', pubid='group_with_two_users')
    db_session.add(group)

    doc = Document(web_uri='https://example.org')
    creator_ann = Annotation(userid=creator.userid, groupid=group.pubid, document=doc)
    member_ann = Annotation(userid=member.userid, groupid=group.pubid, document=doc)

    db_session.add(creator_ann)
    db_session.add(member_ann)
    db_session.flush()

    return (group, creator, member, creator_ann, member_ann)
Beispiel #32
0
 def group(self, users):
     return Group(name='Donkey Trust',
                  authority='foobar.com',
                  creator=users['cazimir'])