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')
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')
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')
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 ]
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
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'
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
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
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
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' }
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
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
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 ]
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"
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", }
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
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"
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
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
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
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
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)
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
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
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 ]
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)
def group(self, users): return Group(name='Donkey Trust', authority='foobar.com', creator=users['cazimir'])