def post(self, request, data, group_id): """Creates a new group invitation and sends it the provided email.""" group = CoreHandler().get_group(group_id) group_invitation = CoreHandler().create_group_invitation( request.user, group, **data) return Response(GroupInvitationSerializer(group_invitation).data)
def delete(self, request, group_user_id): """Deletes an existing group_user if the user belongs to the group.""" group_user = CoreHandler().get_group_user( group_user_id, base_queryset=GroupUser.objects.select_for_update()) CoreHandler().delete_group_user(request.user, group_user) return Response(status=204)
def test_get_group_invitation_by_token(data_fixture): user = data_fixture.create_user() group_user = data_fixture.create_user_group(user=user) invitation = data_fixture.create_group_invitation(group=group_user.group, email=user.email) handler = CoreHandler() signer = handler.get_group_invitation_signer() with pytest.raises(BadSignature): handler.get_group_invitation_by_token(token='INVALID') with pytest.raises(GroupInvitationDoesNotExist): handler.get_group_invitation_by_token(token=signer.dumps(999999)) invitation2 = handler.get_group_invitation_by_token( token=signer.dumps(invitation.id)) assert invitation.id == invitation2.id assert invitation.invited_by_id == invitation2.invited_by_id assert invitation.group_id == invitation2.group_id assert invitation.email == invitation2.email assert invitation.permissions == invitation2.permissions assert isinstance(invitation2, GroupInvitation) with pytest.raises(AttributeError): handler.get_group_invitation_by_token( token=signer.dumps(invitation.id), base_queryset=GroupInvitation.objects.prefetch_related('UNKNOWN'))
def test_delete_group(send_mock, data_fixture): user = data_fixture.create_user() group_1 = data_fixture.create_group(user=user) database = data_fixture.create_database_application(group=group_1) table = data_fixture.create_database_table(database=database) data_fixture.create_group(user=user) user_2 = data_fixture.create_user() group_3 = data_fixture.create_group(user=user_2) handler = CoreHandler() handler.delete_group(user, group_1) send_mock.assert_called_once() assert send_mock.call_args[1]['group'].id == group_1.id assert send_mock.call_args[1]['user'].id == user.id assert len(send_mock.call_args[1]['group_users']) == 1 assert send_mock.call_args[1]['group_users'][0].id == user.id assert Database.objects.all().count() == 0 assert Table.objects.all().count() == 0 assert f'database_table_{table.id}' not in connection.introspection.table_names( ) assert Group.objects.all().count() == 2 assert GroupUser.objects.all().count() == 2 with pytest.raises(UserNotInGroupError): handler.delete_group(user, group_3) handler.delete_group(user_2, group_3) assert Group.objects.all().count() == 1 assert GroupUser.objects.all().count() == 1 with pytest.raises(ValueError): handler.delete_group(user=user_2, group=object())
def delete(self, request, group_id): """Deletes an existing group if it belongs to a user.""" group = CoreHandler().get_group( group_id, base_queryset=Group.objects.select_for_update()) CoreHandler().delete_group(request.user, group) return Response(status=204)
def create_user(self, name, email, password): """ Creates a new user with the provided information and creates a new group and application for him. :param name: The name of the new user. :param email: The e-mail address of the user, this is also the username. :param password: The password of the user. :raises: UserAlreadyExist: When a user with the provided username (email) already exists. :return: The user object. :rtype: User """ try: email = normalize_email_address(email) user = User(first_name=name, email=email, username=email) user.set_password(password) user.save() except IntegrityError: raise UserAlreadyExist( f'A user with username {email} already exists.') # Insert some initial data for the newly created user. core_handler = CoreHandler() group_user = core_handler.create_group(user=user, name=f"{name}'s group") # Call the user_created method for each plugin that is un the registry. for plugin in plugin_registry.registry.values(): plugin.user_created(user, group_user.group) return user
def test_delete_group(data_fixture): user = data_fixture.create_user() group_1 = data_fixture.create_group(user=user) database = data_fixture.create_database_application(group=group_1) table = data_fixture.create_database_table(database=database) data_fixture.create_group(user=user) user_2 = data_fixture.create_user() group_3 = data_fixture.create_group(user=user_2) handler = CoreHandler() handler.delete_group(user, group_1) assert Database.objects.all().count() == 0 assert Table.objects.all().count() == 0 assert f'database_table_{table.id}' not in connection.introspection.table_names() assert Group.objects.all().count() == 2 assert GroupUser.objects.all().count() == 2 with pytest.raises(UserNotInGroupError): handler.delete_group(user, group_3) handler.delete_group(user_2, group_3) assert Group.objects.all().count() == 1 assert GroupUser.objects.all().count() == 1 with pytest.raises(ValueError): handler.delete_group(user=user_2, group=object())
def create_user(self, name, email, password, group_invitation_token=None): """ Creates a new user with the provided information and creates a new group and application for him. If the optional group invitation is provided then the user joins that group without creating a new one. :param name: The name of the new user. :type name: str :param email: The e-mail address of the user, this is also the username. :type email: str :param password: The password of the user. :type password: str :param group_invitation_token: If provided and valid, the invitation will be accepted and and initial group will not be created. :type group_invitation_token: str :raises: UserAlreadyExist: When a user with the provided username (email) already exists. :raises GroupInvitationEmailMismatch: If the group invitation email does not match the one of the user. :return: The user object. :rtype: User """ email = normalize_email_address(email) if User.objects.filter(Q(email=email) | Q(username=email)).exists(): raise UserAlreadyExist( f'A user with username {email} already exists.') core_handler = CoreHandler() group_invitation = None group_user = None if group_invitation_token: group_invitation = core_handler.get_group_invitation_by_token( group_invitation_token) if email != group_invitation.email: raise GroupInvitationEmailMismatch( 'The email address of the invitation does not match the one of the ' 'user.') user = User(first_name=name, email=email, username=email) user.set_password(password) user.save() if group_invitation_token: group_user = core_handler.accept_group_invitation( user, group_invitation) if not group_user: group_user = core_handler.create_group(user=user, name=f"{name}'s group") # Call the user_created method for each plugin that is un the registry. for plugin in plugin_registry.registry.values(): plugin.user_created(user, group_user.group, group_invitation) return user
def get(self, request, group_id): """Responds with a list of serialized users that are part of the group.""" group = CoreHandler().get_group(group_id) group.has_user(request.user, 'ADMIN', True) group_users = GroupUser.objects.filter(group=group).select_related('group') serializer = GroupUserSerializer(group_users, many=True) return Response(serializer.data)
def patch(self, request, data, group_user_id): """Updates the group user if the user has admin permissions to the group.""" group_user = CoreHandler().get_group_user( group_user_id, base_queryset=GroupUser.objects.select_for_update()) group_user = CoreHandler().update_group_user(request.user, group_user, **data) return Response(GroupUserGroupSerializer(group_user).data)
def get(self, request, group_id): """Lists all the invitations of the provided group id.""" group = CoreHandler().get_group(group_id) group.has_user(request.user, 'ADMIN', raise_error=True) group_invitations = GroupInvitation.objects.filter(group=group) serializer = GroupInvitationSerializer(group_invitations, many=True) return Response(serializer.data)
def patch(self, request, data, group_id): """Updates the group if it belongs to a user.""" group = CoreHandler().get_group( group_id, base_queryset=Group.objects.select_for_update() ) group = CoreHandler().update_group(request.user, group, name=data["name"]) return Response(GroupSerializer(group).data)
def test_sync_all_templates(): handler = CoreHandler() handler.sync_templates() assert ( Template.objects.count() == len(list(Path(settings.APPLICATION_TEMPLATES_DIR).glob('*.json'))) )
def delete(self, request, group_invitation_id): """Deletes an existing group_invitation if the user belongs to the group.""" group_invitation = CoreHandler().get_group_invitation( group_invitation_id, base_queryset=GroupInvitation.objects.select_for_update(), ) CoreHandler().delete_group_invitation(request.user, group_invitation) return Response(status=204)
def patch(self, request, data, group_invitation_id): """Updates the group invitation if the user belongs to the group.""" group_invitation = CoreHandler().get_group_invitation( group_invitation_id, base_queryset=GroupInvitation.objects.select_for_update()) group_invitation = CoreHandler().update_group_invitation( request.user, group_invitation, **data) return Response(GroupInvitationSerializer(group_invitation).data)
def delete(self, request, application_id): """Deletes an existing application if the user belongs to the group.""" application = CoreHandler().get_application( application_id, base_queryset=Application.objects.select_for_update()) CoreHandler().delete_application(request.user, application) return Response(status=204)
def post(self, request, data, group_id): """Creates a new application for a user.""" group = CoreHandler().get_group(group_id) application = CoreHandler().create_application( request.user, group, data["type"], name=data["name"] ) return Response(get_application_serializer(application).data)
def patch(self, request, data, application_id): """Updates the application if the user belongs to the group.""" application = CoreHandler().get_application( application_id, base_queryset=Application.objects.select_for_update()) application = CoreHandler().update_application(request.user, application, name=data['name']) return Response(get_application_serializer(application).data)
def test_install_template(send_mock, data_fixture): old_templates = settings.APPLICATION_TEMPLATES_DIR settings.APPLICATION_TEMPLATES_DIR = os.path.join( settings.BASE_DIR, '../../../tests/templates' ) user = data_fixture.create_user() group = data_fixture.create_group(user=user) group_2 = data_fixture.create_group() handler = CoreHandler() handler.sync_templates() template_2 = data_fixture.create_template(slug='does-not-exist') with pytest.raises(TemplateFileDoesNotExist): handler.install_template(user, group, template_2) template = Template.objects.get(slug='example-template') with pytest.raises(UserNotInGroupError): handler.install_template(user, group_2, template) applications, id_mapping = handler.install_template(user, group, template) assert len(applications) == 1 assert applications[0].group_id == group.id assert applications[0].name == 'Event marketing' send_mock.assert_called_once() assert send_mock.call_args[1]['application'].id == applications[0].id assert send_mock.call_args[1]['user'].id == user.id assert send_mock.call_args[1]['type_name'] == 'database' settings.APPLICATION_TEMPLATES_DIR = old_templates
def test_update_settings(data_fixture): user_1 = data_fixture.create_user(is_staff=True) user_2 = data_fixture.create_user() with pytest.raises(IsNotAdminError): CoreHandler().update_settings(user_2, allow_new_signups=False) settings = CoreHandler().update_settings(user_1, allow_new_signups=False) assert settings.allow_new_signups is False settings = Settings.objects.all().first() assert settings.allow_new_signups is False
def test_create_database_application(send_mock, data_fixture): user = data_fixture.create_user() user_2 = data_fixture.create_user() group = data_fixture.create_group(user=user) handler = CoreHandler() handler.create_application(user=user, group=group, type_name="database", name="Test database") assert Application.objects.all().count() == 1 assert Database.objects.all().count() == 1 database = Database.objects.all().first() assert database.name == "Test database" assert database.order == 1 assert database.group == group send_mock.assert_called_once() assert send_mock.call_args[1]["application"].id == database.id assert send_mock.call_args[1]["user"].id == user.id assert send_mock.call_args[1]["type_name"] == "database" with pytest.raises(UserNotInGroup): handler.create_application(user=user_2, group=group, type_name="database", name="") with pytest.raises(ApplicationTypeDoesNotExist): handler.create_application(user=user, group=group, type_name="UNKNOWN", name="")
def test_delete_database_application(send_mock, data_fixture): user = data_fixture.create_user() user_2 = data_fixture.create_user() group = data_fixture.create_group(user=user) database = data_fixture.create_database_application(group=group) table = data_fixture.create_database_table(database=database) handler = CoreHandler() with pytest.raises(UserNotInGroupError): handler.delete_application(user=user_2, application=database) with pytest.raises(ValueError): handler.delete_application(user=user_2, application=object()) handler.delete_application(user=user, application=database) assert Database.objects.all().count() == 0 assert Table.objects.all().count() == 0 assert f'database_table_{table.id}' not in connection.introspection.table_names( ) send_mock.assert_called_once() assert send_mock.call_args[1]['application_id'] == database.id assert send_mock.call_args[1]['application'].id == database.id assert send_mock.call_args[1]['user'].id == user.id
def test_update_database_application(send_mock, data_fixture): user = data_fixture.create_user() user_2 = data_fixture.create_user() group = data_fixture.create_group(user=user) database = data_fixture.create_database_application(group=group) handler = CoreHandler() with pytest.raises(UserNotInGroupError): handler.update_application(user=user_2, application=database, name='Test 1') with pytest.raises(ValueError): handler.update_application(user=user_2, application=object(), name='Test 1') handler.update_application(user=user, application=database, name='Test 1') send_mock.assert_called_once() assert send_mock.call_args[1]['application'].id == database.id assert send_mock.call_args[1]['user'].id == user.id database.refresh_from_db() assert database.name == 'Test 1'
def test_create_database_application(send_mock, data_fixture): user = data_fixture.create_user() user_2 = data_fixture.create_user() group = data_fixture.create_group(user=user) handler = CoreHandler() handler.create_application(user=user, group=group, type_name='database', name='Test database') assert Application.objects.all().count() == 1 assert Database.objects.all().count() == 1 database = Database.objects.all().first() assert database.name == 'Test database' assert database.order == 1 assert database.group == group send_mock.assert_called_once() assert send_mock.call_args[1]['application'].id == database.id assert send_mock.call_args[1]['user'].id == user.id assert send_mock.call_args[1]['type_name'] == 'database' with pytest.raises(UserNotInGroupError): handler.create_application(user=user_2, group=group, type_name='database', name='') with pytest.raises(ApplicationTypeDoesNotExist): handler.create_application(user=user, group=group, type_name='UNKNOWN', name='')
def get(self, request, group_id, template_id): """Install a template into a group.""" handler = CoreHandler() group = handler.get_group(group_id) template = handler.get_template(template_id) applications, id_mapping = handler.install_template( request.user, group, template) data = [ get_application_serializer(application).data for application in applications ] return Response(data)
def test_delete_group_user(send_mock, data_fixture): user_1 = data_fixture.create_user() user_2 = data_fixture.create_user() user_3 = data_fixture.create_user() group_1 = data_fixture.create_group() data_fixture.create_user_group(user=user_1, group=group_1, permissions='ADMIN') group_user_2 = data_fixture.create_user_group(user=user_2, group=group_1, permissions='MEMBER') handler = CoreHandler() with pytest.raises(UserNotInGroupError): handler.delete_group_user(user=user_3, group_user=group_user_2) with pytest.raises(UserInvalidGroupPermissionsError): handler.delete_group_user(user=user_2, group_user=group_user_2) group_user_id = group_user_2.id handler.delete_group_user(user=user_1, group_user=group_user_2) assert GroupUser.objects.all().count() == 1 send_mock.assert_called_once() assert send_mock.call_args[1]['group_user_id'] == group_user_id assert send_mock.call_args[1][ 'group_user'].group_id == group_user_2.group_id assert send_mock.call_args[1]['user'].id == user_1.id
def test_get_group_invitation_by_token(api_client, data_fixture): data_fixture.create_user(email="*****@*****.**") invitation = data_fixture.create_group_invitation(email="*****@*****.**", permissions="ADMIN", message="TEst") invitation_2 = data_fixture.create_group_invitation( email="*****@*****.**", permissions="ADMIN", ) handler = CoreHandler() signer = handler.get_group_invitation_signer() response = api_client.get( reverse("api:groups:invitations:token", kwargs={"token": "INVALID"}), ) response_json = response.json() assert response.status_code == HTTP_400_BAD_REQUEST assert response_json["error"] == "BAD_TOKEN_SIGNATURE" response = api_client.get( reverse("api:groups:invitations:token", kwargs={"token": signer.dumps(99999)}), ) response_json = response.json() assert response.status_code == HTTP_404_NOT_FOUND assert response_json["error"] == "ERROR_GROUP_INVITATION_DOES_NOT_EXIST" response = api_client.get( reverse( "api:groups:invitations:token", kwargs={"token": signer.dumps(invitation.id)}, ), ) response_json = response.json() assert response.status_code == HTTP_200_OK assert response_json["id"] == invitation.id assert response_json["invited_by"] == invitation.invited_by.first_name assert response_json["group"] == invitation.group.name assert response_json["email"] == invitation.email assert response_json["message"] == invitation.message assert response_json["email_exists"] is False assert "created_on" in response_json response = api_client.get( reverse( "api:groups:invitations:token", kwargs={"token": signer.dumps(invitation_2.id)}, ), ) response_json = response.json() assert response.status_code == HTTP_200_OK assert response_json["id"] == invitation_2.id assert response_json["email_exists"] is True
def test_get_set_export_serialized_value_single_select_field(data_fixture): user = data_fixture.create_user() group = data_fixture.create_group(user=user) imported_group = data_fixture.create_group(user=user) database = data_fixture.create_database_application(group=group) table = data_fixture.create_database_table(database=database) field = data_fixture.create_single_select_field(table=table) option_a = data_fixture.create_select_option(field=field, value="A", color="green") option_b = data_fixture.create_select_option(field=field, value="B", color="red") core_handler = CoreHandler() model = table.get_model() model.objects.create() model.objects.create(**{f"field_{field.id}_id": option_a.id}) model.objects.create(**{f"field_{field.id}_id": option_b.id}) exported_applications = core_handler.export_group_applications( group, BytesIO()) imported_applications, id_mapping = core_handler.import_applications_to_group( imported_group, exported_applications, BytesIO(), None) imported_database = imported_applications[0] imported_table = imported_database.table_set.all()[0] imported_field = imported_table.field_set.all().first().specific assert imported_table.id != table.id assert imported_field.id != field.id imported_model = imported_table.get_model() all = imported_model.objects.all() assert len(all) == 3 imported_row_1 = all[0] imported_row_2 = all[1] imported_row_3 = all[2] assert getattr(imported_row_1, f"field_{imported_field.id}") is None assert getattr(imported_row_2, f"field_{imported_field.id}_id") != option_a.id assert getattr(imported_row_2, f"field_{imported_field.id}").value == "A" assert getattr(imported_row_2, f"field_{imported_field.id}").color == "green" assert getattr(imported_row_3, f"field_{imported_field.id}_id") != option_b.id assert getattr(imported_row_3, f"field_{imported_field.id}").value == "B" assert getattr(imported_row_3, f"field_{imported_field.id}").color == "red"
def post(self, request, data): """Creates a new token for the authorized user.""" data['group'] = CoreHandler().get_group(data.pop('group')) token = TokenHandler().create_token(request.user, **data) serializer = TokenSerializer(token) return Response(serializer.data)
def delete_group(self, user, group): """ Deletes an existing group and related applications if the user is staff. :param user: The user on whose behalf the group is deleted :type: user: User :param group: The group instance that must be deleted. :type: group: Group :raises IsNotAdminError: If the user is not admin or staff. """ if not user.is_staff: raise IsNotAdminError() # Load the group users before the group is deleted so that we can pass those # along with the signal. group_id = group.id group_users = list(group.users.all()) CoreHandler()._delete_group(group) group_deleted.send(self, group_id=group_id, group=group, group_users=group_users)